diff options
-rw-r--r-- | Jamfile | 1 | ||||
-rw-r--r-- | include/fitz/font.h | 2 | ||||
-rw-r--r-- | include/fitz/math.h | 15 | ||||
-rw-r--r-- | include/mupdf/content.h | 2 | ||||
-rw-r--r-- | include/mupdf/rsrc.h | 17 | ||||
-rw-r--r-- | mupdf/font.c | 57 | ||||
-rw-r--r-- | mupdf/fontenc.h | 30 | ||||
-rw-r--r-- | mupdf/fontfile.c | 2 | ||||
-rw-r--r-- | mupdf/image.c | 44 | ||||
-rw-r--r-- | mupdf/interpret.c | 31 | ||||
-rw-r--r-- | mupdf/page.c | 2 | ||||
-rw-r--r-- | mupdf/type3.c | 346 | ||||
-rw-r--r-- | render/glyphcache.c | 8 | ||||
-rw-r--r-- | render/render.c | 16 | ||||
-rw-r--r-- | render/renderimage.c | 71 | ||||
-rw-r--r-- | render/rendertext.c | 16 |
16 files changed, 523 insertions, 137 deletions
@@ -109,6 +109,7 @@ Library libmupdf : mupdf/cmap.c mupdf/font.c mupdf/fontfile.c + mupdf/type3.c mupdf/colorspace.c mupdf/image.c mupdf/xobject.c diff --git a/include/fitz/font.h b/include/fitz/font.h index 4d9fb5e8..9fd9218b 100644 --- a/include/fitz/font.h +++ b/include/fitz/font.h @@ -8,7 +8,7 @@ struct fz_hmtx_s { unsigned short lo; unsigned short hi; - short w; + int w; /* type3 fonts can be big! */ }; struct fz_vmtx_s diff --git a/include/fitz/math.h b/include/fitz/math.h index bcbfee00..bfc1f8e6 100644 --- a/include/fitz/math.h +++ b/include/fitz/math.h @@ -4,6 +4,21 @@ static inline unsigned char fz_mul255(unsigned char a, unsigned char b) return ((a + 1) * b) >> 8; } +/* floor / ceil towards/from +/- inf */ +static inline float fz_floor(float x) +{ + if (x > 0) + return floor(x); + return ceil(x); +} + +static inline float fz_ceil(float x) +{ + if (x > 0) + return ceil(x); + return floor(x); +} + /* divide and floor towards -inf */ static inline int fz_idiv(int a, int b) { diff --git a/include/mupdf/content.h b/include/mupdf/content.h index 3f85fe06..96b31f8e 100644 --- a/include/mupdf/content.h +++ b/include/mupdf/content.h @@ -99,7 +99,7 @@ fz_error *pdf_flushtext(pdf_csi*); fz_error *pdf_showimage(pdf_csi*, pdf_image *img); /* interpret.c */ -fz_error *pdf_newcsi(pdf_csi **csip); +fz_error *pdf_newcsi(pdf_csi **csip, int maskonly); fz_error *pdf_runcsi(pdf_csi *, pdf_xref *xref, fz_obj *rdb, fz_file *); void pdf_dropcsi(pdf_csi *csi); diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index 9dc12acd..896e4335 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -17,7 +17,6 @@ void *pdf_findresource(pdf_rsrc *list, fz_obj *ref); * Functions */ - typedef struct pdf_function_s pdf_function; fz_error *pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *obj); @@ -91,9 +90,6 @@ struct pdf_font_s { fz_font super; - void *ftface; - int substitute; - /* FontDescriptor */ int flags; float italicangle; @@ -108,18 +104,16 @@ struct pdf_font_s int ncidtogid; unsigned short *cidtogid; - /* Raw data for freetype */ + /* Freetype */ + int substitute; + void *ftface; char *filename; fz_buffer *fontdata; -}; -struct pdf_type3_s -{ + /* Type3 data */ fz_rect bbox; fz_matrix matrix; - int widths[256]; fz_tree *charprocs[256]; - int tounicode[256]; }; /* cmap.c */ @@ -134,6 +128,9 @@ fz_error *pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref); fz_error *pdf_loadsystemfont(pdf_font *font, char *basefont, char *collection); fz_error *pdf_loadsubstitutefont(pdf_font *font, int fdflags, char *collection); +/* type3.c */ +fz_error *pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *font); + /* font.c */ fz_error *pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *collection); fz_error *pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *font); diff --git a/mupdf/font.c b/mupdf/font.c index 1ab2ea5f..8d3b70b1 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -13,24 +13,42 @@ #include "fontenc.h" #include "fontagl.h" +static char *basefontnames[14][7] = +{ + { "Courier", "CourierNew", "CourierNewPSMT", 0 }, + { "Courier-Bold", "CourierNew,Bold", "Courier,Bold", + "CourierNewPS-BoldMT", "CourierNew-Bold", 0 }, + { "Courier-Oblique", "CourierNew,Italic", "Courier,Italic", + "CourierNewPS-ItalicMT", "CourierNew-Italic", 0 }, + { "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic", + "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", 0 }, + { "Helvetica", "ArialMT", "Arial", 0 }, + { "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold", + "Helvetica,Bold", 0 }, + { "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic", + "Helvetica,Italic", "Helvetica-Italic", 0 }, + { "Helvetica-BoldOblique", "Arial-BoldItalicMT", + "Arial,BoldItalic", "Arial-BoldItalic", + "Helvetica,BoldItalic", "Helvetica-BoldItalic", 0 }, + { "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman", + "TimesNewRomanPS", 0 }, + { "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold", + "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", 0 }, + { "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic", + "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", 0 }, + { "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT", + "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic", + "TimesNewRoman-BoldItalic", 0 }, + { "Symbol", 0 }, + { "ZapfDingbats", 0 } +}; + /* * FreeType and Rendering glue */ enum { UNKNOWN, TYPE1, CFF, TRUETYPE, CID }; -enum -{ - FD_FIXED = 1 << 0, - FD_SERIF = 1 << 1, - FD_SYMBOLIC = 1 << 2, - FD_SCRIPT = 1 << 3, - FD_NONSYMBOLIC = 1 << 5, - FD_ITALIC = 1 << 6, - FD_ALLCAP = 1 << 16, - FD_SMALLCAP = 1 << 17, -}; - static int ftkind(FT_Face face) { const char *kind = face->driver->clazz->root.module_name; @@ -210,10 +228,11 @@ static void ftdropfont(fz_font *font) // XXX free freetype face } -static pdf_font * -newfont(char *name) +pdf_font * +pdf_newfont(char *name) { pdf_font *font; + int i; font = fz_malloc(sizeof (pdf_font)); if (!font) @@ -241,6 +260,9 @@ newfont(char *name) font->filename = nil; font->fontdata = nil; + for (i = 0; i < 256; i++) + font->charprocs[i] = nil; + return font; } @@ -275,7 +297,7 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict) printf("loading simple font %s\n", basefont); - font = *fontp = newfont(basefont); + font = *fontp = pdf_newfont(basefont); if (!font) return fz_outofmem; @@ -364,7 +386,6 @@ printf("loading simple font %s\n", basefont); if (fz_isname(base)) loadencoding(estrings, fz_toname(base)); - diff = fz_dictgets(encoding, "Differences"); if (fz_isarray(diff)) { @@ -578,7 +599,7 @@ printf(" collection %s\n", collection); * Load font file */ - font = *fontp = newfont(basefont); + font = *fontp = pdf_newfont(basefont); if (!font) return fz_outofmem; @@ -902,6 +923,8 @@ pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict) return loadsimplefont(fontp, xref, dict); else if (!strcmp(subtype, "TrueType")) return loadsimplefont(fontp, xref, dict); + else if (!strcmp(subtype, "Type3")) + return pdf_loadtype3font(fontp, xref, dict); else return fz_throw("unimplemented: %s fonts", subtype); } diff --git a/mupdf/fontenc.h b/mupdf/fontenc.h index 376a3f2d..d64e3e49 100644 --- a/mupdf/fontenc.h +++ b/mupdf/fontenc.h @@ -4,36 +4,6 @@ #define _notdef 0 -static char *basefontnames[14][7] = -{ - { "Courier", "CourierNew", "CourierNewPSMT", 0 }, - { "Courier-Bold", "CourierNew,Bold", "Courier,Bold", - "CourierNewPS-BoldMT", "CourierNew-Bold", 0 }, - { "Courier-Oblique", "CourierNew,Italic", "Courier,Italic", - "CourierNewPS-ItalicMT", "CourierNew-Italic", 0 }, - { "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic", - "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", 0 }, - { "Helvetica", "ArialMT", "Arial", 0 }, - { "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold", - "Helvetica,Bold", 0 }, - { "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic", - "Helvetica,Italic", "Helvetica-Italic", 0 }, - { "Helvetica-BoldOblique", "Arial-BoldItalicMT", - "Arial,BoldItalic", "Arial-BoldItalic", - "Helvetica,BoldItalic", "Helvetica-BoldItalic", 0 }, - { "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman", - "TimesNewRomanPS", 0 }, - { "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold", - "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", 0 }, - { "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic", - "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", 0 }, - { "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT", - "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic", - "TimesNewRoman-BoldItalic", 0 }, - { "Symbol", 0 }, - { "ZapfDingbats", 0 } -}; - static char *macroman[256] = { _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, diff --git a/mupdf/fontfile.c b/mupdf/fontfile.c index a7ea31d3..e1997f7e 100644 --- a/mupdf/fontfile.c +++ b/mupdf/fontfile.c @@ -237,6 +237,8 @@ printf(" find cid font %s (%d)\n", collection, isserif); } } +printf(" loading substitute font %s\n", name); + return pdf_loadbuiltinfont(font, name); } diff --git a/mupdf/image.c b/mupdf/image.c index 044307eb..bcffda71 100644 --- a/mupdf/image.c +++ b/mupdf/image.c @@ -205,6 +205,7 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_file *fil fz_error *error; pdf_image *img; fz_filter *filter; + fz_obj *f; fz_obj *cs; fz_obj *d; int ismask; @@ -221,6 +222,7 @@ printf("inline image ");fz_debugobj(dict);printf("\n"); img->super.n = 0; img->super.a = 0; img->indexed = nil; + img->mask = nil; img->super.w = fz_toint(fz_dictgetsa(dict, "Width", "W")); img->super.h = fz_toint(fz_dictgetsa(dict, "Height", "H")); @@ -277,19 +279,41 @@ printf(" decode array!\n"); img->stride = (img->super.w * (img->super.n + img->super.a) * img->bpc + 7) / 8; /* load image data */ - error = pdf_decodefilter(&filter, dict); - if (error) - return error; - error = fz_pushfilter(file, filter); - if (error) - return error; + f = fz_dictgetsa(dict, "Filter", "F"); + if (f) + { + error = pdf_decodefilter(&filter, dict); + if (error) + return error; - error = fz_readfile(&img->samples, file); - if (error) - return error; + error = fz_pushfilter(file, filter); + if (error) + return error; + + error = fz_readfile(&img->samples, file); + if (error) + return error; + + fz_popfilter(file); + } + else + { + error = fz_newbuffer(&img->samples, img->super.h * img->stride); + if (error) + return error; - fz_popfilter(file); +printf(" nullfilter %d\n", img->super.h * img->stride); + + i = fz_read(file, img->samples->bp, img->super.h * img->stride); + error = fz_ferror(file); + if (error) + return error; + +printf(" read %d\n", i); + + img->samples->wp += img->super.h * img->stride; + } /* 0 means opaque and 1 means transparent, so we invert to get alpha */ if (ismask) diff --git a/mupdf/interpret.c b/mupdf/interpret.c index dfe7d36d..4fb10443 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -2,7 +2,7 @@ #include <mupdf.h> fz_error * -pdf_newcsi(pdf_csi **csip) +pdf_newcsi(pdf_csi **csip, int maskonly) { fz_error *error; pdf_csi *csi; @@ -37,8 +37,16 @@ pdf_newcsi(pdf_csi **csip) csi->tree->root = node; csi->gstate[0].head = node; - error = fz_newcolornode(&node, pdf_devicegray, 1, &white); - fz_insertnode(csi->tree->root, node); + if (maskonly) + { + csi->gstate[0].fill.kind = PDF_MNONE; + csi->gstate[0].stroke.kind = PDF_MNONE; + } + else + { + error = fz_newcolornode(&node, pdf_devicegray, 1, &white); + fz_insertnode(csi->tree->root, node); + } csi->clip = nil; @@ -463,7 +471,7 @@ Lsetcolorspace: for (i = 0; i < csi->top; i++) v[i] = fz_toreal(csi->stack[i]); - error = pdf_setcolor(csi, PDF_MFILL, v); + error = pdf_setcolor(csi, PDF_MSTROKE, v); if (error) return error; } @@ -687,6 +695,16 @@ fz_debugobj(rdb); } } + else if (!strcmp(buf, "d0")) + { + fz_warn("unimplemented: d0 charprocs"); + } + + else if (!strcmp(buf, "d1")) + { +printf("%g %g d0\n", fz_toreal(csi->stack[0]), fz_toreal(csi->stack[1])); + } + else fprintf(stderr, "syntaxerror: unknown keyword '%s'\n", buf); //return fz_throw("syntaxerror: unknown keyword '%s'", buf); @@ -1036,9 +1054,14 @@ pdf_runcsi(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_file *file) if (!strcmp(buf, "BI")) { fz_obj *obj; + error = pdf_parsedict(&obj, file, buf, sizeof buf); if (error) return error; + + /* read whitespace after ID keyword */ + fz_readbyte(file); + error = runinlineimage(csi, xref, file, obj); fz_dropobj(obj); if (error) diff --git a/mupdf/page.c b/mupdf/page.c index 79fc6fd0..11ab6727 100644 --- a/mupdf/page.c +++ b/mupdf/page.c @@ -25,7 +25,7 @@ loadpagecontents(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *ref) pdf_csi *csi; int i; - error = pdf_newcsi(&csi); + error = pdf_newcsi(&csi, 0); if (error) return error; diff --git a/mupdf/type3.c b/mupdf/type3.c new file mode 100644 index 00000000..edc205cf --- /dev/null +++ b/mupdf/type3.c @@ -0,0 +1,346 @@ +#include <fitz.h> +#include <mupdf.h> + +extern pdf_font *pdf_newfont(char *name); + +/* TODO: factor out loadencoding which is common with simple fonts */ + +#include "fontenc.h" + +static void loadencoding(char **estrings, char *encoding) +{ + char **bstrings = nil; + int i; + + if (!strcmp(encoding, "MacRomanEncoding")) + bstrings = macroman; + if (!strcmp(encoding, "MacExpertEncoding")) + bstrings = macexpert; + if (!strcmp(encoding, "WinAnsiEncoding")) + bstrings = winansi; + + if (bstrings) + for (i = 0; i < 256; i++) + estrings[i] = bstrings[i]; +} + +static void +t3dropfont(fz_font *font) +{ + int i; + pdf_font *pfont = (pdf_font*)font; + if (pfont->encoding) + fz_dropcmap(pfont->encoding); + for (i = 0; i < 256; i++) + if (pfont->charprocs[i]) + fz_droptree(pfont->charprocs[i]); +} + +static fz_error * +t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) +{ + pdf_font *font = (pdf_font*)fzfont; + fz_error *error; + fz_renderer *gc; + fz_tree *tree; + fz_pixmap *pixmap; + fz_matrix ctm; + fz_rect bbox; + int i; + + if (cid < 0 || cid > 255) + return fz_throw("rangecheck: glyph out of range"); + + tree = font->charprocs[cid]; + if (!tree) + { + glyph->w = 0; + glyph->h = 0; + return nil; + } + + ctm = fz_concat(font->matrix, trm); + bbox = fz_boundtree(tree, ctm); + +printf("glyph bbox %g %g %g %g\n", + bbox.min.x, + bbox.min.y, + bbox.max.x, + bbox.max.y); + + bbox.min.x = fz_floor(bbox.min.x - 5.5); + bbox.min.y = fz_floor(bbox.min.y - 5.5); + bbox.max.x = fz_ceil(bbox.max.x + 5.5); + bbox.max.y = fz_ceil(bbox.max.y + 5.5); + +printf("glyph bbox %g %g %g %g\n", + bbox.min.x, + bbox.min.y, + bbox.max.x, + bbox.max.y); + + error = fz_newrenderer(&gc, nil); + if (error) + return error; + error = fz_rendertree(&pixmap, gc, tree, ctm, bbox); + fz_droprenderer(gc); + if (error) + return error; + + assert(pixmap->n == 1); + +printf("pixmap %d %d\n", pixmap->x, pixmap->y); + + glyph->lsb = pixmap->x; + glyph->top = pixmap->h + pixmap->y; + glyph->w = pixmap->w; + glyph->h = pixmap->h; + glyph->bitmap = pixmap->samples; + + unsigned char tmp[pixmap->w * pixmap->h]; + memcpy(tmp, pixmap->samples, pixmap->w * pixmap->h); + + for (i = 0; i < pixmap->h; i++) + { + memcpy( pixmap->samples + i * pixmap->w, + tmp + (pixmap->h - i - 1) * pixmap->w, + pixmap->w ); + } + + // XXX flip bitmap in ftrender instead; free pixmap + + return nil; +} + +static fz_error * +loadcharproc(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *stmref) +{ + fz_error *error; + pdf_csi *csi; + + printf(" loading charproc %d %d obj\n", + fz_tonum(stmref), fz_togen(stmref)); + + error = pdf_newcsi(&csi, 1); + + error = pdf_openstream(xref, fz_tonum(stmref), fz_togen(stmref)); + if (error) + return error; + + error = pdf_runcsi(csi, xref, rdb, xref->stream); + + pdf_closestream(xref); + + if (csi->tree) + fz_debugtree(csi->tree); + + *treep = csi->tree; + csi->tree = nil; + + pdf_dropcsi(csi); + + return error; +} + +fz_error * +pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict) +{ + fz_error *error; + char buf[256]; + char *estrings[256]; + pdf_font *font; + fz_obj *encoding; + fz_obj *widths; + fz_obj *resources; + fz_obj *charprocs; + fz_obj *obj; + int first, last; + int i, k, n; + + obj = fz_dictgets(dict, "Name"); + if (obj) + strlcpy(buf, fz_toname(obj), sizeof buf); + else + sprintf(buf, "Unnamed-T3"); + +printf("loading type3 font %s\n", buf); + + font = pdf_newfont(buf); + if (!font) + return fz_outofmem; + + font->super.render = t3render; + font->super.drop = (void(*)(fz_font*)) t3dropfont; + + obj = fz_dictgets(dict, "FontMatrix"); + font->matrix.a = fz_toreal(fz_arrayget(obj, 0)); + font->matrix.b = fz_toreal(fz_arrayget(obj, 1)); + font->matrix.c = fz_toreal(fz_arrayget(obj, 2)); + font->matrix.d = fz_toreal(fz_arrayget(obj, 3)); + font->matrix.e = fz_toreal(fz_arrayget(obj, 4)); + font->matrix.f = fz_toreal(fz_arrayget(obj, 5)); + +printf(" matrix [%g %g %g %g %g %g]\n", + font->matrix.a, font->matrix.b, + font->matrix.c, font->matrix.d, + font->matrix.e, font->matrix.f); + + /* TODO: scale bbox by fontmatrix * 1000 */ + obj = fz_dictgets(dict, "FontBBox"); + fz_setfontbbox((fz_font*)font, + fz_toreal(fz_arrayget(obj, 0)), + fz_toreal(fz_arrayget(obj, 1)), + fz_toreal(fz_arrayget(obj, 2)), + fz_toreal(fz_arrayget(obj, 3))); + + /* + * Encoding + */ + + for (i = 0; i < 256; i++) + estrings[i] = nil; + + encoding = fz_dictgets(dict, "Encoding"); + if (!encoding) { + error = fz_throw("syntaxerror: Type3 font missing Encoding"); + goto cleanup; + } + + error = pdf_resolve(&encoding, xref); + if (error) + goto cleanup; + + if (fz_isname(obj)) + loadencoding(estrings, fz_toname(encoding)); + + if (fz_isdict(encoding)) + { + fz_obj *base, *diff, *item; + + base = fz_dictgets(encoding, "BaseEncoding"); + if (fz_isname(base)) + loadencoding(estrings, fz_toname(base)); + + diff = fz_dictgets(encoding, "Differences"); + if (fz_isarray(diff)) + { + n = fz_arraylen(diff); + k = 0; + for (i = 0; i < n; i++) + { + item = fz_arrayget(diff, i); + if (fz_isint(item)) + k = fz_toint(item); + if (fz_isname(item)) + estrings[k++] = fz_toname(item); + if (k < 0) k = 0; + if (k > 255) k = 255; + } + } + } + + fz_dropobj(encoding); + + error = pdf_makeidentitycmap(&font->encoding, 0, 1); + if (error) + goto cleanup; + + /* + * Widths + */ + + fz_setdefaulthmtx((fz_font*)font, 0); + + first = fz_toint(fz_dictgets(dict, "FirstChar")); + last = fz_toint(fz_dictgets(dict, "LastChar")); + + widths = fz_dictgets(dict, "Widths"); + if (!widths) { + error = fz_throw("syntaxerror: Type3 font missing Widths"); + goto cleanup; + } + + error = pdf_resolve(&widths, xref); + if (error) + goto cleanup; + + for (i = first; i <= last; i++) + { + float w = fz_toreal(fz_arrayget(widths, i - first)); + w = font->matrix.a * w * 1000.0; + error = fz_addhmtx((fz_font*)font, i, i, w); + if (error) { + fz_dropobj(widths); + goto cleanup; + } + } + + fz_dropobj(widths); + + error = fz_endhmtx((fz_font*)font); + if (error) + goto cleanup; + + /* + * Resources + */ + + obj = fz_dictgets(dict, "Resources"); + if (!obj) { + error = fz_throw("syntaxerror: Type3 font missing Resources"); + goto cleanup; + } + + error = pdf_resolve(&obj, xref); + if (error) + goto cleanup; + + error = pdf_loadresources(&resources, xref, obj); + + fz_dropobj(obj); + + if (error) + goto cleanup; + + /* + * CharProcs + */ + + charprocs = fz_dictgets(dict, "CharProcs"); + if (!charprocs) + { + error = fz_throw("syntaxerror: Type3 font missing CharProcs"); + goto cleanup2; + } + + error = pdf_resolve(&charprocs, xref); + if (error) + goto cleanup2; + + for (i = 0; i < 256; i++) + { + if (estrings[i]) + { + obj = fz_dictgets(charprocs, estrings[i]); + if (obj) + { + error = loadcharproc(&font->charprocs[i], xref, resources, obj); + if (error) + goto cleanup2; + } + } + } + + fz_dropobj(charprocs); + fz_dropobj(resources); + + *fontp = font; + return nil; + +cleanup2: + fz_dropobj(resources); +cleanup: + fz_dropfont((fz_font*)font); + return error; +} + diff --git a/render/glyphcache.c b/render/glyphcache.c index e92b472e..ec77e857 100644 --- a/render/glyphcache.c +++ b/render/glyphcache.c @@ -310,8 +310,8 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz key.b = ctm.b * 65536; key.c = ctm.c * 65536; key.d = ctm.d * 65536; - key.e = (ctm.e - floor(ctm.e)) * HSUBPIX; - key.f = (ctm.f - floor(ctm.f)) * VSUBPIX; + key.e = (ctm.e - fz_floor(ctm.e)) * HSUBPIX; + key.f = (ctm.f - fz_floor(ctm.f)) * VSUBPIX; val = hashfind(arena, &key); if (val) @@ -328,8 +328,8 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz return nil; } - ctm.e = floor(ctm.e) + key.e / HSUBPIX; - ctm.f = floor(ctm.f) + key.f / HSUBPIX; + ctm.e = fz_floor(ctm.e) + key.e / HSUBPIX; + ctm.f = fz_floor(ctm.f) + key.f / HSUBPIX; error = font->render(glyph, font, cid, ctm); if (error) diff --git a/render/render.c b/render/render.c index fd3e0620..dd4b543d 100644 --- a/render/render.c +++ b/render/render.c @@ -77,6 +77,8 @@ fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm) printf("render color\n"); + assert(gc->model); + fz_convertcolor(color->cs, color->samples, gc->model, rgb); gc->r = rgb[0] * 255; gc->g = rgb[1] * 255; @@ -146,7 +148,7 @@ fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm) { printf("begin over accumulator\n"); oldacc = gc->acc; - error = fz_newpixmap(&gc->acc, gc->x, gc->y, gc->w, gc->h, 4); + error = fz_newpixmap(&gc->acc, gc->x, gc->y, gc->w, gc->h, gc->model ? 4 : 1); if (error) return error; fz_clearpixmap(gc->acc); @@ -285,14 +287,14 @@ fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, f { fz_error *error; - gc->x = floor(bbox.min.x); - gc->y = floor(bbox.min.y); - gc->w = ceil(bbox.max.x) - floor(bbox.min.x); - gc->h = ceil(bbox.max.y) - floor(bbox.min.y); + gc->x = fz_floor(bbox.min.x); + gc->y = fz_floor(bbox.min.y); + gc->w = fz_ceil(bbox.max.x) - fz_floor(bbox.min.x); + gc->h = fz_ceil(bbox.max.y) - fz_floor(bbox.min.y); /* compensate for rounding */ - ctm.e -= bbox.min.x - floor(bbox.min.x); - ctm.f -= bbox.min.y - floor(bbox.min.y); + ctm.e -= bbox.min.x - gc->x; + ctm.f -= bbox.min.y - gc->y; printf("render tree\n"); diff --git a/render/renderimage.c b/render/renderimage.c index 73b45e0c..e2c98eb1 100644 --- a/render/renderimage.c +++ b/render/renderimage.c @@ -9,10 +9,10 @@ void fz_gammapixmap(fz_pixmap *pix, float gamma); static inline int getcomp(fz_pixmap *pix, int u, int v, int k) { -// if (u < 0 || u >= pix->w) -// return 0; -// if (v < 0 || v >= pix->h) -// return 0; + if (u < 0 || u >= pix->w) + return 0; + if (v < 0 || v >= pix->h) + return 0; u = CLAMP(u, 0, pix->w - 1); v = CLAMP(v, 0, pix->h - 1); return pix->samples[ (v * pix->w + u) * pix->n + k ]; @@ -38,18 +38,21 @@ static inline int sampleimage(fz_pixmap *pix, int u, int v, int k) static inline void drawscan(fz_matrix *invmat, fz_pixmap *dst, fz_pixmap *src, int y, int x0, int x1) { - int x, k; + unsigned char *d; + int k, n; int u = (invmat->a * x0 + invmat->c * y + invmat->e) * 65536; int v = (invmat->b * x0 + invmat->d * y + invmat->f) * 65536; int du = invmat->a * 65536; int dv = invmat->b * 65536; - for (x = x0; x < x1; x++) + n = x1 - x0; + d = dst->samples + ((y - dst->y) * dst->w + (x0 - dst->x)) * dst->n; + + while (n--) { for (k = 0; k < src->n; k++) - dst->samples[ (y * dst->w + x) * dst->n + k ] - = sampleimage(src, u, v, k); + *d++ = sampleimage(src, u, v, k); u += du; v += dv; } @@ -98,13 +101,11 @@ static fz_error * drawtile(fz_renderer *gc, fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm, int over) { static const fz_point rect[4] = { {0, 0}, {0, 1}, {1, 1}, {1, 0} }; - fz_error *error; - fz_gel *gel = gc->gel; - fz_ael *ael = gc->ael; fz_matrix imgmat; fz_matrix invmat; fz_point v[4]; - int i, e, y, x0, x1; + int top, bot, x0, x1, y; + int i; imgmat.a = 1.0 / tile->w; imgmat.b = 0.0; @@ -116,41 +117,23 @@ drawtile(fz_renderer *gc, fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm, int ov for (i = 0; i < 4; i++) v[i] = fz_transformpoint(ctm, rect[i]); - fz_resetgel(gel, 1, 1); - fz_insertgel(gel, v[0].x, v[0].y, v[1].x, v[1].y); - fz_insertgel(gel, v[1].x, v[1].y, v[2].x, v[2].y); - fz_insertgel(gel, v[2].x, v[2].y, v[3].x, v[3].y); - fz_insertgel(gel, v[3].x, v[3].y, v[0].x, v[0].y); - fz_sortgel(gel); - e = 0; - y = gel->edges[0].y; + top = fz_floor(MIN4(v[0].y, v[1].y, v[2].y, v[3].y)) - 1; + bot = fz_ceil(MAX4(v[0].y, v[1].y, v[2].y, v[3].y)) + 1; + x0 = fz_floor(MIN4(v[0].x, v[1].x, v[2].x, v[3].x)) - 1; + x1 = fz_ceil(MAX4(v[0].x, v[1].x, v[2].x, v[3].x)) + 1; - while (ael->len > 0 || e < gel->len) - { - error = fz_insertael(ael, gel, y, &e); - if (error) - return error; - - x0 = ael->edges[0]->x; - x1 = ael->edges[ael->len - 1]->x; + top = CLAMP(top, out->y, out->y + out->h - 1); + bot = CLAMP(bot, out->y, out->y + out->h - 1); + x0 = CLAMP(x0, out->x, out->x + out->w - 1); + x1 = CLAMP(x1, out->x, out->x + out->w - 1); - if (y >= out->y && y < out->y + out->h) - { - x0 = CLAMP(x0, out->x, out->x + out->w - 1); - x1 = CLAMP(x1, out->x, out->x + out->w - 1); - if (over && tile->n == 4) - overscanrgb(&invmat, out, tile, y, x0, x1); - else - drawscan(&invmat, out, tile, y, x0, x1); - } - - fz_advanceael(ael); - - if (ael->len > 0) - y ++; - else if (e < gel->len) - y = gel->edges[e].y; + for (y = top; y <= bot; y++) + { + if (over && tile->n == 4) + overscanrgb(&invmat, out, tile, y, x0, x1); + else + drawscan(&invmat, out, tile, y, x0, x1); } return nil; diff --git a/render/rendertext.c b/render/rendertext.c index 1a3c49db..6819ccd8 100644 --- a/render/rendertext.c +++ b/render/rendertext.c @@ -78,11 +78,11 @@ fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm) tm.f = y; trm = fz_concat(tm, ctm); - ix = floor(trm.e); - iy = floor(trm.f); + ix = fz_floor(trm.e); + iy = fz_floor(trm.f); - trm.e = (trm.e - floor(trm.e)); - trm.f = (trm.f - floor(trm.f)); + trm.e = (trm.e - fz_floor(trm.e)); + trm.f = (trm.f - fz_floor(trm.f)); error = fz_renderglyph(gc->cache, &gl, text->font, g, trm); if (error) @@ -121,11 +121,11 @@ fz_rendercolortext(fz_renderer *gc, fz_textnode *text, fz_colornode *color, fz_m tm.f = y; trm = fz_concat(tm, ctm); - ix = floor(trm.e); - iy = floor(trm.f); + ix = fz_floor(trm.e); + iy = fz_floor(trm.f); - trm.e = (trm.e - floor(trm.e)); - trm.f = (trm.f - floor(trm.f)); + trm.e = (trm.e - fz_floor(trm.e)); + trm.f = (trm.f - fz_floor(trm.f)); error = fz_renderglyph(gc->cache, &gl, text->font, g, trm); if (error) |