diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-11-22 08:11:02 +0100 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-11-22 08:11:02 +0100 |
commit | 459f682af16a1982745f2c40a368c1a54059b23e (patch) | |
tree | e3c02a0a7d56d02b41bd2f05b3ca747347d51911 | |
parent | ce1bf1ef28a160c48c287d302ab7795330806cf0 (diff) | |
download | mupdf-459f682af16a1982745f2c40a368c1a54059b23e.tar.xz |
rewrite of render loop part 2
-rw-r--r-- | include/fitz/font.h | 2 | ||||
-rw-r--r-- | mupdf/font.c | 26 | ||||
-rw-r--r-- | mupdf/image2.c | 1 | ||||
-rw-r--r-- | mupdf/type3.c | 2 | ||||
-rw-r--r-- | render/glyphcache.c | 16 | ||||
-rw-r--r-- | render/rastnone.c | 9 | ||||
-rw-r--r-- | render/render.c | 274 |
7 files changed, 271 insertions, 59 deletions
diff --git a/include/fitz/font.h b/include/fitz/font.h index 7e925461..27217c6c 100644 --- a/include/fitz/font.h +++ b/include/fitz/font.h @@ -43,7 +43,7 @@ struct fz_font_s struct fz_glyph_s { int x, y, w, h; - unsigned char *bitmap; + unsigned char *samples; }; void fz_initfont(fz_font *font, char *name); diff --git a/mupdf/font.c b/mupdf/font.c index e2debc85..464d8c11 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -112,7 +112,7 @@ ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) glyph->h = 0; glyph->x = 0; glyph->y = 0; - glyph->bitmap = nil; + glyph->samples = nil; /* freetype mutilates complex glyphs if they are loaded * with FT_Set_Char_Size 1.0. it rounds the coordinates @@ -163,15 +163,15 @@ ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) glyph->h = face->glyph->bitmap.rows; glyph->x = face->glyph->bitmap_left; glyph->y = face->glyph->bitmap_top - glyph->h; - glyph->bitmap = face->glyph->bitmap.buffer; + glyph->samples = face->glyph->bitmap.buffer; int i; unsigned char tmp[glyph->w * glyph->h]; - memcpy(tmp, glyph->bitmap, glyph->w * glyph->h); + memcpy(tmp, glyph->samples, glyph->w * glyph->h); for (i = 0; i < glyph->h; i++) { - memcpy( glyph->bitmap + i * glyph->w, + memcpy( glyph->samples + i * glyph->w, tmp + (glyph->h - i - 1) * glyph->w, glyph->w ); } @@ -312,9 +312,12 @@ printf("loading simple font %s -> %s\n", basefont, fontname); symbolic = font->flags & 4; - fz_setfontbbox((fz_font*)font, - face->bbox.xMin, face->bbox.yMin, - face->bbox.xMax, face->bbox.yMax); + if (face->bbox.xMax == face->bbox.xMin) + fz_setfontbbox((fz_font*)font, -1000, -1000, 2000, 2000); + else + fz_setfontbbox((fz_font*)font, + face->bbox.xMin, face->bbox.yMin, + face->bbox.xMax, face->bbox.yMax); /* * Encoding @@ -615,9 +618,12 @@ printf(" collection %s\n", collection); face = font->ftface; kind = ftkind(face); - fz_setfontbbox((fz_font*)font, - face->bbox.xMin, face->bbox.yMin, - face->bbox.xMax, face->bbox.yMax); + if (face->bbox.xMax == face->bbox.xMin) + fz_setfontbbox((fz_font*)font, -1000, -1000, 2000, 2000); + else + fz_setfontbbox((fz_font*)font, + face->bbox.xMin, face->bbox.yMin, + face->bbox.xMax, face->bbox.yMax); /* * Encoding diff --git a/mupdf/image2.c b/mupdf/image2.c index d46bdd0e..ad07e6bc 100644 --- a/mupdf/image2.c +++ b/mupdf/image2.c @@ -202,7 +202,6 @@ pdf_loadtile(fz_image *img, fz_pixmap *tile) return fz_throw("rangecheck: unsupported bit depth: %d", src->bpc); } -printf(" unpack n=%d\n", tile->n); for (y = 0; y < tile->h; y++) { for (x = 0; x < tile->w; x++) diff --git a/mupdf/type3.c b/mupdf/type3.c index ee7708c0..64ef9a2c 100644 --- a/mupdf/type3.c +++ b/mupdf/type3.c @@ -56,7 +56,7 @@ t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) glyph->y = pixmap->y; glyph->w = pixmap->w; glyph->h = pixmap->h; - glyph->bitmap = pixmap->samples; + glyph->samples = pixmap->samples; return nil; } diff --git a/render/glyphcache.c b/render/glyphcache.c index a5f9f2b6..c47ed0ed 100644 --- a/render/glyphcache.c +++ b/render/glyphcache.c @@ -36,7 +36,7 @@ struct fz_hash_s struct fz_val_s { fz_hash *ent; - unsigned char *data; + unsigned char *samples; short w, h, x, y; int uses; }; @@ -276,7 +276,7 @@ evictlast(fz_glyphcache *arena) return; k = arena->load - 1; - s = lru[k].data; + s = lru[k].samples; e = s + lru[k].w * lru[k].h; /* pack buffer to fill hole */ @@ -286,8 +286,8 @@ evictlast(fz_glyphcache *arena) /* update lru pointers */ for (i = 0; i < k; i++) - if (lru[i].data >= e) - lru[i].data -= e - s; + if (lru[i].samples >= e) + lru[i].samples -= e - s; /* remove hash entry */ key = lru[k].ent->key; @@ -321,7 +321,7 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz glyph->h = val->h; glyph->x = val->x; glyph->y = val->y; - glyph->bitmap = val->data; + glyph->samples = val->samples; bubble(arena, val - arena->lru); @@ -356,12 +356,12 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz val->h = glyph->h; val->x = glyph->x; val->y = glyph->y; - val->data = arena->buffer + arena->used; + val->samples = arena->buffer + arena->used; arena->used += size; - memcpy(val->data, glyph->bitmap, glyph->w * glyph->h); - glyph->bitmap = val->data; + memcpy(val->samples, glyph->samples, glyph->w * glyph->h); + glyph->samples = val->samples; hashinsert(arena, &key, val); diff --git a/render/rastnone.c b/render/rastnone.c index 4e4066fa..2a575ccb 100644 --- a/render/rastnone.c +++ b/render/rastnone.c @@ -155,7 +155,7 @@ static inline void sampleargb(byte *s, int w, int h, int u, int v, byte *abcd) lerpargb(abcd, ab, cd, vd); } -#define PSRC byte *src, int w, int h, int nx, int ny +#define PSRC byte *src, int w, int h, int nx0, int ny #define PDST byte *dst0, int dstw #define PMSK byte *msk0, int mskw #define PCTM int u0, int v0, int fa, int fb, int fc, int fd @@ -169,6 +169,7 @@ static void example(PSRC, PDST, PMSK, PCTM) byte *msk = msk0; int u = u0; int v = v0; + int nx = nx0; while (nx--) { // dst[0] = ... msk[0] ... sample(s, w, h, u, v); @@ -191,7 +192,8 @@ static void example(PSRC, PDST, PMSK, PCTM) byte *dst = dst0; \ int u = u0; \ int v = v0; \ - while (nx--) \ + int nx = nx0; \ + while (nx--) #define ELOOP \ u0 += fc; \ @@ -206,7 +208,8 @@ static void example(PSRC, PDST, PMSK, PCTM) byte *msk = msk0; \ int u = u0; \ int v = v0; \ - while (nx--) \ + int nx = nx0; \ + while (nx--) #define ELOOPM \ u0 += fc; \ diff --git a/render/render.c b/render/render.c index 672f312f..13787ce4 100644 --- a/render/render.c +++ b/render/render.c @@ -213,6 +213,11 @@ renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm) gbox = fz_boundgel(gc->gel); clip = fz_intersectirects(gc->clip, gbox); + if (clip.max.x <= clip.min.x) + return nil; + if (clip.max.y <= clip.min.y) + return nil; + //printf("path clip[%d %d %d %d]\n", clip.min.x, clip.min.y, clip.max.x, clip.max.y); user.rast = &gc->rast; @@ -249,29 +254,71 @@ renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm) * Text */ -static void copyglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig, int yorig) +static void drawglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig, int yorig) { - int x, y; + unsigned char *dp, *sp; + int w, h; + + int dx1 = dst->x + dst->w; + int dy1 = dst->y + dst->h; + + int x0 = xorig + src->x; + int y0 = yorig + src->y; + int x1 = x0 + src->w; + int y1 = y0 + src->h; + + int sx0 = 0; + int sy0 = 0; + int sx1 = src->w; + int sy1 = src->h; - xorig += src->x; - yorig += src->y; + if (x1 < dst->x || x0 >= dx1) return; + if (y1 < dst->y || y0 >= dy1) return; - for (y = 0; y < src->h; y++) - for (x = 0; x < src->w; x++) + if (x0 < dst->x) { sx0 += dst->x - x0; x0 = dst->x; } + if (y0 < dst->y) { sy0 += dst->y - y0; y0 = dst->y; } + + if (x1 >= dx1) { sx1 -= dx1 - x1; x1 = dx1; } + if (y1 >= dy1) { sy1 -= dy1 - y1; y1 = dy1; } + + sp = src->samples + (sy0 * src->w + sx0); + dp = dst->samples + ((y0 - dst->y) * dst->w + (x0 - dst->x)) * dst->n; + + w = sx1 - sx0; + h = sy1 - sy0; + + switch (gc->flag) + { + case FNONE: + while (h--) + { + gc->rast.mask_g(w, sp, dp); + sp += src->w; + dp += dst->w * dst->n; + } + break; + + case FOVER: + while (h--) { - int dx = xorig + x - dst->x; - int dy = yorig + y - dst->y; - - if (dx < 0) {puts("dx<0");continue;} - if (dy < 0) {puts("dy<0");continue;} - if (dx >= dst->w) {puts("dx>w");continue;} - if (dy >= dst->h) {puts("dy>h");continue;} - - int a = src->bitmap[x + y * src->w]; - int b = dst->samples[dx + dy * dst->w]; - int c = a + fz_mul255(b, 255 - a); - dst->samples[dx + dy * dst->w] = a; + gc->rast.mask_o1(w, sp, dp); + sp += src->w; + dp += dst->w * dst->n; } + break; + + case FOVER | FRGB: + while (h--) + { + gc->rast.mask_o4w3(w, sp, dp, gc->rgb); + sp += src->w; + dp += dst->w * dst->n; + } + break; + + default: + assert(!"impossible flag in text span function"); + } } static fz_error * @@ -291,18 +338,24 @@ printf("text %s n=%d [%g %g %g %g] clip[%d %d %d %d]\n", text->font->name, text->len, text->trm.a, text->trm.b, text->trm.c, text->trm.d, clip.min.x, clip.min.y, clip.max.x, clip.max.y); -fflush(stdout); + + if (clip.max.x <= clip.min.x) + return nil; + if (clip.max.y <= clip.min.y) + return nil; clip.min.x ++; clip.min.y ++; clip.max.x ++; clip.max.y ++; - error = fz_newpixmapwithrect(&gc->dest, clip, 1); - if (error) - return error; - - fz_clearpixmap(gc->dest); + if (gc->flag == FNONE) + { + error = fz_newpixmapwithrect(&gc->dest, clip, 1); + if (error) + return error; + fz_clearpixmap(gc->dest); + } tm = text->trm; @@ -321,7 +374,10 @@ fflush(stdout); if (error) return error; - copyglyph(gc, gc->dest, &glyph, x, y); + if (gc->flag == FNONE) + drawglyph(gc, gc->dest, &glyph, x, y); + else + drawglyph(gc, gc->over, &glyph, x, y); } return nil; @@ -331,9 +387,156 @@ fflush(stdout); * Image */ +static inline void +calcimagescale(fz_matrix ctm, int w, int h, int *odx, int *ody) +{ + float sx, sy; + int dx, dy; + + sx = sqrt(ctm.a * ctm.a + ctm.b * ctm.b); + dx = 1; + while (((w+dx-1)/dx)/sx > 2.0 && (w+dx-1)/dx > 1) + dx++; + + sy = sqrt(ctm.c * ctm.c + ctm.d * ctm.d); + dy = 1; + while (((h+dy-1)/dy)/sy > 2.0 && (h+dy-1)/dy > 1) + dy++; + + *odx = dx; + *ody = dy; +} + static fz_error * -renderimage(fz_renderer *gc, fz_imagenode *image, fz_matrix ctm) +renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm) { + fz_error *error; + fz_image *image = node->image; + fz_irect bbox; + fz_irect clip; + int dx, dy; + fz_pixmap *tile; + fz_matrix imgmat; + fz_matrix invmat; + int fa, fb, fc, fd; + int u0, v0; + int x0, y0; + int w, h; + + /* TODO: check validity of xxx->n + 1 */ + +printf("renderimage %dx%d %d+%d %s\n", image->w, image->h, image->n, image->a, image->cs?image->cs->name:"(nil)"); + + bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm)); + clip = fz_intersectirects(gc->clip, bbox); + + if (clip.max.x <= clip.min.x) + return nil; + if (clip.max.y <= clip.min.y) + return nil; + + calcimagescale(ctm, image->w, image->h, &dx, &dy); + +printf(" load image\n"); + error = fz_newpixmap(&tile, 0, 0, image->w, image->h, image->n + 1); + error = image->loadtile(image, tile); + + if (dx != 1 || dy != 1) + { +printf(" scale image 1/%d 1/%d\n", dx, dy); + fz_pixmap *temp; + error = fz_scalepixmap(&temp, tile, dx, dy); + fz_droppixmap(tile); + tile = temp; + } + + if (image->cs && image->cs != gc->model) + { + fz_pixmap *temp; +printf(" convert from %s to %s\n", image->cs->name, gc->model->name); + error = fz_newpixmap(&temp, tile->x, tile->y, tile->w, tile->h, gc->model->n + 1); + fz_convertpixmap(image->cs, tile, gc->model, temp); + fz_droppixmap(tile); + tile = temp; + } + + imgmat.a = 1.0 / tile->w; + imgmat.b = 0.0; + imgmat.c = 0.0; + imgmat.d = -1.0 / tile->h; + imgmat.e = 0.0; + imgmat.f = 1.0; + invmat = fz_invertmatrix(fz_concat(imgmat, ctm)); + + w = clip.max.x - clip.min.x; + h = clip.max.y - clip.min.y; + x0 = clip.min.x; + y0 = clip.min.y; + u0 = (invmat.a * (x0+0.5) + invmat.c * (y0+0.5) + invmat.e) * 65536; + v0 = (invmat.b * (x0+0.5) + invmat.d * (y0+0.5) + invmat.f) * 65536; + fa = invmat.a * 65536; + fb = invmat.b * 65536; + fc = invmat.c * 65536; + fd = invmat.d * 65536; + + switch (gc->flag) + { + case FNONE: + { +printf(" fnone %d x %d\n", w, h); + if (image->cs) + error = fz_newpixmapwithrect(&gc->dest, clip, gc->model->n + 1); + else + error = fz_newpixmapwithrect(&gc->dest, clip, 1); + fz_clearpixmap(gc->dest); + + if (image->cs) + gc->rast.img4_g( + tile->samples, tile->w, tile->h, w, h, + gc->dest->samples, gc->dest->w * gc->dest->n, + u0, v0, fa, fb, fc, fd); + else + gc->rast.img1_g( + tile->samples, tile->w, tile->h, w, h, + gc->dest->samples, gc->dest->w * gc->dest->n, + u0, v0, fa, fb, fc, fd); + } + break; + + case FOVER: + { +printf(" fover %d x %d\n", w, h); + if (image->cs) + gc->rast.img4_o4( + tile->samples, tile->w, tile->h, w, h, + gc->over->samples + ((y0 - gc->over->y) * gc->over->w + (x0 - gc->over->x)) * 4, + gc->over->w * gc->over->n, + u0, v0, fa, fb, fc, fd); + else + gc->rast.img1_o1( + tile->samples, tile->w, tile->h, w, h, + gc->over->samples + ((y0 - gc->over->y) * gc->over->w + (x0 - gc->over->x)), + gc->over->w * gc->over->n, + u0, v0, fa, fb, fc, fd); + } + break; + + case FOVER | FRGB: + { +printf(" fover+rgb %d x %d\n", w, h); + gc->rast.img1_o4w3( + tile->samples, tile->w, tile->h, w, h, + gc->over->samples + ((y0 - gc->over->y) * gc->over->w + (x0 - gc->over->x)) * 4, + gc->over->w * gc->over->n, + u0, v0, fa, fb, fc, fd, gc->rgb); + } + break; + default: + assert(!"impossible flag in image span function"); + } + + fz_droppixmap(tile); + return nil; } @@ -449,18 +652,19 @@ printf("mask\n{\n"); shapepix = gc->dest; gc->dest = nil; - error = fz_newpixmapwithrect(&gc->dest, gc->clip, colorpix->n); - if (error) - return error; - - fz_clearpixmap(gc->dest); + if (colorpix && shapepix) + { + error = fz_newpixmapwithrect(&gc->dest, gc->clip, colorpix->n); + if (error) + return error; - fz_blendmask(gc->dest, colorpix, shapepix); + fz_clearpixmap(gc->dest); -//fz_debugpixmap(gc->dest);getchar(); + fz_blendmask(gc->dest, colorpix, shapepix); + } - fz_droppixmap(shapepix); - fz_droppixmap(colorpix); + if (shapepix) fz_droppixmap(shapepix); + if (colorpix) fz_droppixmap(colorpix); gc->over = oldover; gc->mask = oldmask; |