diff options
-rw-r--r-- | apps/common/pdfapp.c | 3 | ||||
-rw-r--r-- | apps/pdftool.c | 2 | ||||
-rw-r--r-- | include/fitz-world.h | 1 | ||||
-rw-r--r-- | include/fitz/wld_font.h | 60 | ||||
-rw-r--r-- | include/fitz/wld_text.h | 5 | ||||
-rw-r--r-- | include/mupdf/content.h | 2 | ||||
-rw-r--r-- | include/mupdf/rsrc.h | 77 | ||||
-rw-r--r-- | mupdf/Jamfile | 1 | ||||
-rw-r--r-- | mupdf/pdf_build.c | 41 | ||||
-rw-r--r-- | mupdf/pdf_font.c | 480 | ||||
-rw-r--r-- | mupdf/pdf_fontfile.c | 89 | ||||
-rw-r--r-- | mupdf/pdf_fontfilefc.c | 8 | ||||
-rw-r--r-- | mupdf/pdf_fontfilems.c | 8 | ||||
-rw-r--r-- | mupdf/pdf_fontmtx.c | 179 | ||||
-rw-r--r-- | mupdf/pdf_resources.c | 4 | ||||
-rw-r--r-- | mupdf/pdf_store.c | 4 | ||||
-rw-r--r-- | mupdf/pdf_type3.c | 108 | ||||
-rw-r--r-- | mupdf/pdf_unicode.c | 16 | ||||
-rw-r--r-- | raster/glyphcache.c | 17 | ||||
-rw-r--r-- | raster/render.c | 6 | ||||
-rw-r--r-- | world/node_text.c | 5 | ||||
-rw-r--r-- | world/node_toxml.c | 10 | ||||
-rw-r--r-- | world/res_font.c | 442 |
23 files changed, 874 insertions, 694 deletions
diff --git a/apps/common/pdfapp.c b/apps/common/pdfapp.c index 6d82ef39..b01bd485 100644 --- a/apps/common/pdfapp.c +++ b/apps/common/pdfapp.c @@ -635,6 +635,8 @@ void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int sta void pdfapp_oncopy(pdfapp_t *app, unsigned short *ucsbuf, int ucslen) { + ucsbuf[0] = 0; +#if 0 /* pdf_loadtextfromtree needs rewriting, so removing this temporarily */ fz_error *error; pdf_textline *line, *ln; int y, c; @@ -687,5 +689,6 @@ void pdfapp_oncopy(pdfapp_t *app, unsigned short *ucsbuf, int ucslen) ucsbuf[p] = 0; pdf_droptextline(line); +#endif } diff --git a/apps/pdftool.c b/apps/pdftool.c index 36bc35bc..91ecc22b 100644 --- a/apps/pdftool.c +++ b/apps/pdftool.c @@ -719,6 +719,7 @@ drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark *drawtimes) void drawtxt(int pagenum) { +#if 0 /* removed temporarily pending rewrite of pdf_loadtextfromtree */ fz_error *error; pdf_textline *line; fz_matrix ctm; @@ -737,6 +738,7 @@ drawtxt(int pagenum) pdf_droptextline(line); drawfreepage(); +#endif } void diff --git a/include/fitz-world.h b/include/fitz-world.h index f810e07b..ddf9a445 100644 --- a/include/fitz-world.h +++ b/include/fitz-world.h @@ -15,6 +15,7 @@ #include "fitz/wld_color.h" #include "fitz/wld_image.h" #include "fitz/wld_shade.h" + #include "fitz/wld_tree.h" #include "fitz/wld_path.h" #include "fitz/wld_text.h" diff --git a/include/fitz/wld_font.h b/include/fitz/wld_font.h index 27217c6c..8bcffb60 100644 --- a/include/fitz/wld_font.h +++ b/include/fitz/wld_font.h @@ -1,43 +1,22 @@ typedef struct fz_font_s fz_font; -typedef struct fz_hmtx_s fz_hmtx; -typedef struct fz_vmtx_s fz_vmtx; typedef struct fz_glyph_s fz_glyph; typedef struct fz_glyphcache_s fz_glyphcache; -struct fz_hmtx_s -{ - unsigned short lo; - unsigned short hi; - int w; /* type3 fonts can be big! */ -}; - -struct fz_vmtx_s -{ - unsigned short lo; - unsigned short hi; - short x; - short y; - short w; -}; +char *ft_errorstring(int err); struct fz_font_s { int refs; char name[32]; - fz_error* (*render)(fz_glyph*, fz_font*, int, fz_matrix); - void (*drop)(fz_font *); + void *ftface; /* has an FT_Face if used */ + int ftsubstitute; /* ... substitute metrics */ - int wmode; - fz_irect bbox; + struct fz_tree_s **t3procs; /* has 256 entries if used */ + fz_matrix t3matrix; - int nhmtx, hmtxcap; - fz_hmtx dhmtx; - fz_hmtx *hmtx; + fz_irect bbox; - int nvmtx, vmtxcap; - fz_vmtx dvmtx; - fz_vmtx *vmtx; }; struct fz_glyph_s @@ -46,23 +25,24 @@ struct fz_glyph_s unsigned char *samples; }; -void fz_initfont(fz_font *font, char *name); -fz_font *fz_keepfont(fz_font *font); +fz_error * fz_newfreetypefont(fz_font **fontp, char *name, int substitute); +fz_error * fz_loadfreetypefontfile(fz_font *font, char *path, int index); +fz_error * fz_loadfreetypefontbuffer(fz_font *font, unsigned char *data, int len, int index); +fz_error * fz_newtype3font(fz_font **fontp, char *name, fz_matrix matrix, void **procs); + +fz_error * fz_newfontfrombuffer(fz_font **fontp, unsigned char *data, int len, int index); +fz_error * fz_newfontfromfile(fz_font **fontp, char *path, int index); + +fz_font * fz_keepfont(fz_font *font); void fz_dropfont(fz_font *font); + void fz_debugfont(fz_font *font); -void fz_setfontwmode(fz_font *font, int wmode); void fz_setfontbbox(fz_font *font, int xmin, int ymin, int xmax, int ymax); -void fz_setdefaulthmtx(fz_font *font, int w); -void fz_setdefaultvmtx(fz_font *font, int y, int w); -fz_error *fz_addhmtx(fz_font *font, int lo, int hi, int w); -fz_error *fz_addvmtx(fz_font *font, int lo, int hi, int x, int y, int w); -fz_error *fz_endhmtx(fz_font *font); -fz_error *fz_endvmtx(fz_font *font); -fz_hmtx fz_gethmtx(fz_font *font, int cid); -fz_vmtx fz_getvmtx(fz_font *font, int cid); -fz_error *fz_newglyphcache(fz_glyphcache **arenap, int slots, int size); -fz_error *fz_renderglyph(fz_glyphcache*, fz_glyph*, fz_font*, int, fz_matrix); +fz_error * fz_renderftglyph(fz_glyph *glyph, fz_font *font, int cid, fz_matrix trm); +fz_error * fz_rendert3glyph(fz_glyph *glyph, fz_font *font, int cid, fz_matrix trm); +fz_error * fz_newglyphcache(fz_glyphcache **arenap, int slots, int size); +fz_error * fz_renderglyph(fz_glyphcache*, fz_glyph*, fz_font*, int, fz_matrix); void fz_debugglyphcache(fz_glyphcache *); void fz_dropglyphcache(fz_glyphcache *); diff --git a/include/fitz/wld_text.h b/include/fitz/wld_text.h index 619aae83..d9e5c980 100644 --- a/include/fitz/wld_text.h +++ b/include/fitz/wld_text.h @@ -25,7 +25,8 @@ typedef struct fz_textel_s fz_textel; struct fz_textel_s { float x, y; - int cid; + int gid; + int ucs; }; struct fz_textnode_s @@ -39,6 +40,6 @@ struct fz_textnode_s fz_error *fz_newtextnode(fz_textnode **textp, fz_font *face); fz_error *fz_clonetextnode(fz_textnode **textp, fz_textnode *oldtext); -fz_error *fz_addtext(fz_textnode *text, int g, float x, float y); +fz_error *fz_addtext(fz_textnode *text, int gid, int ucs, float x, float y); fz_error *fz_endtext(fz_textnode *text); diff --git a/include/mupdf/content.h b/include/mupdf/content.h index c28a33f3..a77a7296 100644 --- a/include/mupdf/content.h +++ b/include/mupdf/content.h @@ -54,7 +54,7 @@ struct pdf_gstate_s float wordspace; float scale; float leading; - pdf_font *font; + pdf_fontdesc *font; float size; int render; float rise; diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index aa1935b5..65f9e536 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -189,11 +189,31 @@ extern const char * const pdf_expert[256]; extern const char * const pdf_symbol[256]; extern const char * const pdf_zapfdingbats[256]; -typedef struct pdf_font_s pdf_font; +typedef struct pdf_hmtx_s pdf_hmtx; +typedef struct pdf_vmtx_s pdf_vmtx; +typedef struct pdf_fontdesc_s pdf_fontdesc; -struct pdf_font_s +struct pdf_hmtx_s { - fz_font super; + unsigned short lo; + unsigned short hi; + int w; /* type3 fonts can be big! */ +}; + +struct pdf_vmtx_s +{ + unsigned short lo; + unsigned short hi; + short x; + short y; + short w; +}; + +struct pdf_fontdesc_s +{ + int refs; + + fz_font *font; /* FontDescriptor */ int flags; @@ -215,32 +235,47 @@ struct pdf_font_s int ncidtoucs; unsigned short *cidtoucs; - /* Freetype */ - int substitute; - void *ftface; - char *filename; - fz_buffer *fontdata; + /* Metrics (given in the PDF file) */ + int wmode; - /* Type3 data */ - fz_matrix matrix; - fz_tree *charprocs[256]; + int nhmtx, hmtxcap; + pdf_hmtx dhmtx; + pdf_hmtx *hmtx; + + int nvmtx, vmtxcap; + pdf_vmtx dvmtx; + pdf_vmtx *vmtx; }; +/* fontmtx.c */ +void pdf_setfontwmode(pdf_fontdesc *font, int wmode); +void pdf_setdefaulthmtx(pdf_fontdesc *font, int w); +void pdf_setdefaultvmtx(pdf_fontdesc *font, int y, int w); +fz_error *pdf_addhmtx(pdf_fontdesc *font, int lo, int hi, int w); +fz_error *pdf_addvmtx(pdf_fontdesc *font, int lo, int hi, int x, int y, int w); +fz_error *pdf_endhmtx(pdf_fontdesc *font); +fz_error *pdf_endvmtx(pdf_fontdesc *font); +pdf_hmtx pdf_gethmtx(pdf_fontdesc *font, int cid); +pdf_vmtx pdf_getvmtx(pdf_fontdesc *font, int cid); + /* unicode.c */ -fz_error *pdf_loadtounicode(pdf_font *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm); +fz_error *pdf_loadtounicode(pdf_fontdesc *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm); /* fontfile.c */ -fz_error *pdf_loadbuiltinfont(pdf_font *font, char *basefont); -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); +fz_error *pdf_loadbuiltinfont(pdf_fontdesc *font, char *basefont); +fz_error *pdf_loadembeddedfont(pdf_fontdesc *font, pdf_xref *xref, fz_obj *stmref); +fz_error *pdf_loadsystemfont(pdf_fontdesc *font, char *basefont, char *collection); +fz_error *pdf_loadsubstitutefont(pdf_fontdesc *font, int fdflags, char *collection); /* type3.c */ -fz_error *pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *obj, fz_obj *ref); +fz_error *pdf_loadtype3font(pdf_fontdesc **fontp, pdf_xref *xref, fz_obj *obj, fz_obj *ref); /* font.c */ -char *ft_errstr(int err); -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 *obj, fz_obj *ref); -void pdf_dropfont(pdf_font *font); +int pdf_fontcidtogid(pdf_fontdesc *fontdesc, int cid); +fz_error *pdf_loadfontdescriptor(pdf_fontdesc *font, pdf_xref *xref, fz_obj *desc, char *collection); +fz_error *pdf_loadfont(pdf_fontdesc **fontp, pdf_xref *xref, fz_obj *obj, fz_obj *ref); +pdf_fontdesc * pdf_newfontdesc(void); +pdf_fontdesc * pdf_keepfont(pdf_fontdesc *fontdesc); +void pdf_dropfont(pdf_fontdesc *font); +void pdf_debugfont(pdf_fontdesc *fontdesc); diff --git a/mupdf/Jamfile b/mupdf/Jamfile index dba33a63..a96f4d30 100644 --- a/mupdf/Jamfile +++ b/mupdf/Jamfile @@ -26,6 +26,7 @@ Library libmupdf : pdf_unicode.c pdf_font.c pdf_type3.c + pdf_fontmtx.c pdf_fontfile.c # use builtin fonts # pdf_fontfilefc.c # use fontconfig # pdf_fontfilems.c # scan $WINDIR/Fonts diff --git a/mupdf/pdf_build.c b/mupdf/pdf_build.c index 741d5b72..f303a2c9 100644 --- a/mupdf/pdf_build.c +++ b/mupdf/pdf_build.c @@ -851,12 +851,14 @@ fz_error * showglyph(pdf_csi *csi, int cid) { pdf_gstate *gstate = csi->gstate + csi->gtop; - pdf_font *font = gstate->font; + pdf_fontdesc *fontdesc = gstate->font; fz_error *error; fz_matrix tsm, trm; float w0, w1, tx, ty; - fz_hmtx h; - fz_vmtx v; + pdf_hmtx h; + pdf_vmtx v; + int gid; + int ucs; tsm.a = gstate->size * gstate->scale; tsm.b = 0; @@ -865,9 +867,18 @@ showglyph(pdf_csi *csi, int cid) tsm.e = 0; tsm.f = gstate->rise; - if (font->super.wmode == 1) + if (fontdesc->tounicode) + ucs = pdf_lookupcmap(fontdesc->tounicode, cid); + else if (cid < fontdesc->ncidtoucs) + ucs = fontdesc->cidtoucs[cid]; + else + ucs = '?'; + + gid = pdf_fontcidtogid(fontdesc, cid); + + if (fontdesc->wmode == 1) { - v = fz_getvmtx((fz_font*)font, cid); + v = pdf_getvmtx(fontdesc, cid); tsm.e -= v.x * gstate->size / 1000.0; tsm.f -= v.y * gstate->size / 1000.0; } @@ -876,7 +887,7 @@ showglyph(pdf_csi *csi, int cid) /* flush buffered text if face or matrix or rendermode has changed */ if (!csi->text || - ((fz_font*)font) != csi->text->font || + (fontdesc->font) != csi->text->font || fabs(trm.a - csi->text->trm.a) > FLT_EPSILON || fabs(trm.b - csi->text->trm.b) > FLT_EPSILON || fabs(trm.c - csi->text->trm.c) > FLT_EPSILON || @@ -887,7 +898,7 @@ showglyph(pdf_csi *csi, int cid) if (error) return fz_rethrow(error, "cannot finish text node (face/matrix change)"); - error = fz_newtextnode(&csi->text, (fz_font*)font); + error = fz_newtextnode(&csi->text, fontdesc->font); if (error) return fz_rethrow(error, "cannot create text node"); @@ -898,13 +909,13 @@ showglyph(pdf_csi *csi, int cid) } /* add glyph to textobject */ - error = fz_addtext(csi->text, cid, trm.e, trm.f); + error = fz_addtext(csi->text, gid, ucs, trm.e, trm.f); if (error) return fz_rethrow(error, "cannot add glyph to text node"); - if (font->super.wmode == 0) + if (fontdesc->wmode == 0) { - h = fz_gethmtx((fz_font*)font, cid); + h = pdf_gethmtx(fontdesc, cid); w0 = h.w / 1000.0; tx = (w0 * gstate->size + gstate->charspace) * gstate->scale; csi->tm = fz_concat(fz_translate(tx, 0), csi->tm); @@ -923,8 +934,8 @@ void showspace(pdf_csi *csi, float tadj) { pdf_gstate *gstate = csi->gstate + csi->gtop; - pdf_font *font = gstate->font; - if (font->super.wmode == 0) + pdf_fontdesc *fontdesc = gstate->font; + if (fontdesc->wmode == 0) csi->tm = fz_concat(fz_translate(tadj * gstate->scale, 0), csi->tm); else csi->tm = fz_concat(fz_translate(0, tadj), csi->tm); @@ -934,7 +945,7 @@ fz_error * pdf_showtext(pdf_csi *csi, fz_obj *text) { pdf_gstate *gstate = csi->gstate + csi->gtop; - pdf_font *font = gstate->font; + pdf_fontdesc *fontdesc = gstate->font; fz_error *error; unsigned char *buf; unsigned char *end; @@ -966,8 +977,8 @@ pdf_showtext(pdf_csi *csi, fz_obj *text) while (buf < end) { - buf = pdf_decodecmap(font->encoding, buf, &cpt); - cid = pdf_lookupcmap(font->encoding, cpt); + buf = pdf_decodecmap(fontdesc->encoding, buf, &cpt); + cid = pdf_lookupcmap(fontdesc->encoding, cpt); if (cid == -1) cid = 0; diff --git a/mupdf/pdf_font.c b/mupdf/pdf_font.c index 7ed7ef1c..4a1a29db 100644 --- a/mupdf/pdf_font.c +++ b/mupdf/pdf_font.c @@ -43,33 +43,6 @@ static char *basefontnames[14][7] = enum { UNKNOWN, TYPE1, TRUETYPE, CID }; -#undef __FTERRORS_H__ -#define FT_ERRORDEF(e, v, s) { (e), (s) }, -#define FT_ERROR_START_LIST -#define FT_ERROR_END_LIST { 0, NULL } - -struct ft_error -{ - int err; - char *str; -}; - -const struct ft_error ft_errors[] = -{ -#include FT_ERRORS_H -}; - -char *ft_errstr(int err) -{ - const struct ft_error *e; - - for (e = ft_errors; e->str != NULL; e++) - if (e->err == err) - return e->str; - - return "Unknown error"; -} - static int ftkind(FT_Face face) { const char *kind = FT_Get_X11_Font_Format(face); @@ -93,138 +66,38 @@ static int ftcharindex(FT_Face face, int cid) return gid; } -static inline int ftcidtogid(pdf_font *font, int cid) +static inline int ftcidtogid(pdf_fontdesc *fontdesc, int cid) { - if (font->tottfcmap) + if (fontdesc->tottfcmap) { - cid = pdf_lookupcmap(font->tottfcmap, cid); - return ftcharindex(font->ftface, cid); + cid = pdf_lookupcmap(fontdesc->tottfcmap, cid); + return ftcharindex(fontdesc->font->ftface, cid); } - if (font->cidtogid) - return font->cidtogid[cid]; + if (fontdesc->cidtogid) + return fontdesc->cidtogid[cid]; return cid; } -static int ftwidth(pdf_font *font, int cid) +int pdf_fontcidtogid(pdf_fontdesc *fontdesc, int cid) { - int e; - - cid = ftcidtogid(font, cid); - - e = FT_Load_Glyph(font->ftface, cid, - FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); - if (e) - return 0; - return ((FT_Face)font->ftface)->glyph->advance.x; + if (fontdesc->font->ftface) + return ftcidtogid(fontdesc, cid); + return cid; } -static fz_error * -ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) +static int ftwidth(pdf_fontdesc *fontdesc, int cid) { - pdf_font *font = (pdf_font*)fzfont; - FT_Face face = font->ftface; - FT_Matrix m; - FT_Vector v; - FT_Error fterr; - float scale; - int gid; - int x, y; - - gid = ftcidtogid(font, cid); - - if (font->substitute && fzfont->wmode == 0) - { - fz_hmtx subw; - int realw; - - FT_Set_Char_Size(face, 1000, 1000, 72, 72); - - fterr = FT_Load_Glyph(font->ftface, gid, - FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); - if (fterr) - return fz_throw("freetype failed to load glyph: %s", ft_errstr(fterr)); - - realw = ((FT_Face)font->ftface)->glyph->advance.x; - subw = fz_gethmtx(fzfont, cid); - if (realw) - scale = (float) subw.w / realw; - else - scale = 1.0; - - trm = fz_concat(fz_scale(scale, 1.0), trm); - } - - glyph->w = 0; - glyph->h = 0; - glyph->x = 0; - glyph->y = 0; - glyph->samples = nil; - - /* freetype mutilates complex glyphs if they are loaded - * with FT_Set_Char_Size 1.0. it rounds the coordinates - * before applying transformation. to get more precision in - * freetype, we shift part of the scale in the matrix - * into FT_Set_Char_Size instead - */ + int gid, e; -#ifdef HINT - scale = fz_matrixexpansion(trm); - m.xx = trm.a * 65536 / scale; - m.yx = trm.b * 65536 / scale; - m.xy = trm.c * 65536 / scale; - m.yy = trm.d * 65536 / scale; - v.x = 0; - v.y = 0; + gid = ftcidtogid(fontdesc, cid); - FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72); - FT_Set_Transform(face, &m, &v); - - fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP); - if (fterr) - fz_warn("freetype load glyph: %s", ft_errstr(fterr)); - -#else - - m.xx = trm.a * 64; /* should be 65536 */ - m.yx = trm.b * 64; - m.xy = trm.c * 64; - m.yy = trm.d * 64; - v.x = trm.e * 64; - v.y = trm.f * 64; - - FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ - FT_Set_Transform(face, &m, &v); - - fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); - if (fterr) - fz_warn("freetype load glyph: %s", ft_errstr(fterr)); - -#endif - - fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal); - if (fterr) - fz_warn("freetype render glyph: %s", ft_errstr(fterr)); - - glyph->w = face->glyph->bitmap.width; - glyph->h = face->glyph->bitmap.rows; - glyph->x = face->glyph->bitmap_left; - glyph->y = face->glyph->bitmap_top - glyph->h; - glyph->samples = face->glyph->bitmap.buffer; - - for (y = 0; y < glyph->h / 2; y++) - { - for (x = 0; x < glyph->w; x++) - { - unsigned char a = glyph->samples[y * glyph->w + x ]; - unsigned char b = glyph->samples[(glyph->h - y - 1) * glyph->w + x]; - glyph->samples[y * glyph->w + x ] = b; - glyph->samples[(glyph->h - y - 1) * glyph->w + x] = a; - } - } - - return fz_okay; + e = FT_Load_Glyph(fontdesc->font->ftface, gid, + FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); + if (e) + return 0; + return ((FT_Face)fontdesc->font->ftface)->glyph->advance.x; } /* @@ -254,64 +127,84 @@ static int mrecode(char *name) * Create and destroy */ -static void ftdropfont(fz_font *font) +pdf_fontdesc * +pdf_keepfont(pdf_fontdesc *fontdesc) { - pdf_font *pfont = (pdf_font*)font; - if (pfont->encoding) - pdf_dropcmap(pfont->encoding); - if (pfont->tottfcmap) - pdf_dropcmap(pfont->tottfcmap); - if (pfont->tounicode) - pdf_dropcmap(pfont->tounicode); - fz_free(pfont->cidtogid); - fz_free(pfont->cidtoucs); - if (pfont->ftface) - FT_Done_Face((FT_Face)pfont->ftface); - if (pfont->fontdata) - fz_dropbuffer(pfont->fontdata); + fontdesc->refs ++; + return fontdesc; } -pdf_font * -pdf_newfont(char *name) +void +pdf_dropfont(pdf_fontdesc *fontdesc) { - pdf_font *font; - int i; + if (fontdesc && --fontdesc->refs == 0) + { + if (fontdesc->font) + fz_dropfont(fontdesc->font); + if (fontdesc->encoding) + pdf_dropcmap(fontdesc->encoding); + if (fontdesc->tottfcmap) + pdf_dropcmap(fontdesc->tottfcmap); + if (fontdesc->tounicode) + pdf_dropcmap(fontdesc->tounicode); + fz_free(fontdesc->cidtogid); + fz_free(fontdesc->cidtoucs); + fz_free(fontdesc->hmtx); + fz_free(fontdesc->vmtx); + fz_free(fontdesc); + } +} + +pdf_fontdesc * +pdf_newfontdesc(void) +{ + pdf_fontdesc *fontdesc; - font = fz_malloc(sizeof (pdf_font)); - if (!font) + fontdesc = fz_malloc(sizeof (pdf_fontdesc)); + if (!fontdesc) return nil; - fz_initfont((fz_font*)font, name); - font->super.render = ftrender; - font->super.drop = (void(*)(fz_font*)) ftdropfont; + fontdesc->refs = 1; - font->ftface = nil; - font->substitute = 0; + fontdesc->font = nil; - font->flags = 0; - font->italicangle = 0; - font->ascent = 0; - font->descent = 0; - font->capheight = 0; - font->xheight = 0; - font->missingwidth = 0; + fontdesc->flags = 0; + fontdesc->italicangle = 0; + fontdesc->ascent = 0; + fontdesc->descent = 0; + fontdesc->capheight = 0; + fontdesc->xheight = 0; + fontdesc->missingwidth = 0; - font->encoding = nil; - font->tottfcmap = 0; - font->ncidtogid = 0; - font->cidtogid = nil; + fontdesc->encoding = nil; + fontdesc->tottfcmap = 0; + fontdesc->ncidtogid = 0; + fontdesc->cidtogid = nil; - font->tounicode = nil; - font->ncidtoucs = 0; - font->cidtoucs = nil; + fontdesc->tounicode = nil; + fontdesc->ncidtoucs = 0; + fontdesc->cidtoucs = nil; - font->filename = nil; - font->fontdata = nil; + fontdesc->wmode = 0; - for (i = 0; i < 256; i++) - font->charprocs[i] = nil; + fontdesc->hmtxcap = 0; + fontdesc->vmtxcap = 0; + fontdesc->nhmtx = 0; + fontdesc->nvmtx = 0; + fontdesc->hmtx = nil; + fontdesc->vmtx = nil; + + fontdesc->dhmtx.lo = 0x0000; + fontdesc->dhmtx.hi = 0xFFFF; + fontdesc->dhmtx.w = 0; + + fontdesc->dvmtx.lo = 0x0000; + fontdesc->dvmtx.hi = 0xFFFF; + fontdesc->dvmtx.x = 0; + fontdesc->dvmtx.y = 880; + fontdesc->dvmtx.w = -1000; - return font; + return fontdesc; } /* @@ -319,14 +212,14 @@ pdf_newfont(char *name) */ static fz_error * -loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) +loadsimplefont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; fz_obj *descriptor = nil; fz_obj *encoding = nil; fz_obj *widths = nil; unsigned short *etable = nil; - pdf_font *font; + pdf_fontdesc *fontdesc; fz_irect bbox; FT_Face face; FT_CharMap cmap; @@ -347,23 +240,23 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) * Load font file */ - font = pdf_newfont(fontname); - if (!font) + fontdesc = pdf_newfontdesc(); + if (!fontdesc) return fz_outofmem; - pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(ref), fz_togen(ref), font); + pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(ref), fz_togen(ref), fontdesc); pdf_logfont("basefont0 %s\n", basefont); pdf_logfont("basefont1 %s\n", fontname); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor && basefont == fontname) - error = pdf_loadfontdescriptor(font, xref, descriptor, nil); + error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, nil); else - error = pdf_loadbuiltinfont(font, fontname); + error = pdf_loadbuiltinfont(fontdesc, fontname); if (error) goto cleanup; - face = font->ftface; + face = fontdesc->font->ftface; kind = ftkind(face); pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name); @@ -376,15 +269,15 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) - fz_setfontbbox((fz_font*)font, -1000, -1000, 2000, 2000); + fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000); else - fz_setfontbbox((fz_font*)font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); + fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding */ - symbolic = font->flags & 4; + symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; @@ -415,7 +308,7 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) fterr = FT_Set_Charmap(face, cmap); if (fterr) { - error = fz_throw("freetype could not set cmap: %s", ft_errstr(fterr)); + error = fz_throw("freetype could not set cmap: %s", ft_errorstring(fterr)); goto cleanup; } } @@ -545,15 +438,14 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) } } - error = pdf_newidentitycmap(&font->encoding, 0, 1); + error = pdf_newidentitycmap(&fontdesc->encoding, 0, 1); if (error) goto cleanup; - font->ncidtogid = 256; - font->cidtogid = etable; + fontdesc->ncidtogid = 256; + fontdesc->cidtogid = etable; - error = pdf_loadtounicode(font, xref, - estrings, nil, fz_dictgets(dict, "ToUnicode")); + error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; @@ -561,7 +453,7 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) * Widths */ - fz_setdefaulthmtx((fz_font*)font, font->missingwidth); + pdf_setdefaulthmtx(fontdesc, fontdesc->missingwidth); widths = fz_dictgets(dict, "Widths"); if (widths) @@ -581,7 +473,7 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) for (i = 0; i < last - first + 1; i++) { int wid = fz_toint(fz_arrayget(widths, i)); - error = fz_addhmtx((fz_font*)font, i + first, i + first, wid); + error = pdf_addhmtx(fontdesc, i + first, i + first, wid); if (error) goto cleanup; } @@ -593,26 +485,27 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) FT_Set_Char_Size(face, 1000, 1000, 72, 72); for (i = 0; i < 256; i++) { - error = fz_addhmtx((fz_font*)font, i, i, ftwidth(font, i)); + error = pdf_addhmtx(fontdesc, i, i, ftwidth(fontdesc, i)); if (error) goto cleanup; } } - error = fz_endhmtx((fz_font*)font); + error = pdf_endhmtx(fontdesc); if (error) goto cleanup; pdf_logfont("}\n"); - *fontp = font; + *fontdescp = fontdesc; return fz_okay; cleanup: fz_free(etable); if (widths) fz_dropobj(widths); - fz_dropfont((fz_font*)font); + fz_dropfont(fontdesc->font); + fz_free(fontdesc); return fz_rethrow(error, "cannot load simple font"); } @@ -621,12 +514,12 @@ cleanup: */ static fz_error * -loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj *encoding, fz_obj *tounicode) +loadcidfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj *encoding, fz_obj *tounicode) { fz_error *error; fz_obj *widths = nil; fz_obj *descriptor; - pdf_font *font; + pdf_fontdesc *fontdesc; FT_Face face; fz_irect bbox; int kind; @@ -673,23 +566,23 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj * Load font file */ - font = pdf_newfont(basefont); - if (!font) + fontdesc = pdf_newfontdesc(); + if (!fontdesc) return fz_outofmem; - pdf_logfont("load cid font (%d %d R) ptr=%p {\n", fz_tonum(ref), fz_togen(ref), font); + pdf_logfont("load cid font (%d %d R) ptr=%p {\n", fz_tonum(ref), fz_togen(ref), fontdesc); pdf_logfont("basefont %s\n", basefont); pdf_logfont("collection %s\n", collection); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor) - error = pdf_loadfontdescriptor(font, xref, descriptor, collection); + error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, collection); else error = fz_throw("syntaxerror: missing font descriptor"); if (error) goto cleanup; - face = font->ftface; + face = fontdesc->font->ftface; kind = ftkind(face); bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM; @@ -700,9 +593,9 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) - fz_setfontbbox((fz_font*)font, -1000, -1000, 2000, 2000); + fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000); else - fz_setfontbbox((fz_font*)font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); + fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding @@ -712,16 +605,16 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj { pdf_logfont("encoding /%s\n", fz_toname(encoding)); if (!strcmp(fz_toname(encoding), "Identity-H")) - error = pdf_newidentitycmap(&font->encoding, 0, 2); + error = pdf_newidentitycmap(&fontdesc->encoding, 0, 2); else if (!strcmp(fz_toname(encoding), "Identity-V")) - error = pdf_newidentitycmap(&font->encoding, 1, 2); + error = pdf_newidentitycmap(&fontdesc->encoding, 1, 2); else - error = pdf_loadsystemcmap(&font->encoding, fz_toname(encoding)); + error = pdf_loadsystemcmap(&fontdesc->encoding, fz_toname(encoding)); } else if (fz_isindirect(encoding)) { pdf_logfont("encoding %d %d R\n", fz_tonum(encoding), fz_togen(encoding)); - error = pdf_loadembeddedcmap(&font->encoding, xref, encoding); + error = pdf_loadembeddedcmap(&fontdesc->encoding, xref, encoding); } else { @@ -730,8 +623,8 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj if (error) goto cleanup; - fz_setfontwmode((fz_font*)font, pdf_getwmode(font->encoding)); - pdf_logfont("wmode %d\n", pdf_getwmode(font->encoding)); + pdf_setfontwmode(fontdesc, pdf_getwmode(fontdesc->encoding)); + pdf_logfont("wmode %d\n", pdf_getwmode(fontdesc->encoding)); if (kind == TRUETYPE) { @@ -762,8 +655,8 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj for (i = 0; i < len; i++) map[i] = (buf->rp[i * 2] << 8) + buf->rp[i * 2 + 1]; - font->ncidtogid = len; - font->cidtogid = map; + fontdesc->ncidtogid = len; + fontdesc->cidtogid = map; fz_dropbuffer(buf); } @@ -771,7 +664,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj /* if truetype font is external, cidtogidmap should not be identity */ /* so we map from cid to unicode and then map that through the (3 1) */ /* unicode cmap to get a glyph id */ - else if (font->substitute) + else if (fontdesc->font->ftsubstitute) { int e; @@ -782,15 +675,15 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj return fz_throw("fonterror: no unicode cmap when emulating CID font"); if (!strcmp(collection, "Adobe-CNS1")) - error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-CNS1-UCS2"); + error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) - error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-GB1-UCS2"); + error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) - error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-Japan1-UCS2"); + error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) - error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-Japan2-UCS2"); + error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan2-UCS2"); else if (!strcmp(collection, "Adobe-Korea1")) - error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-Korea1-UCS2"); + error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Korea1-UCS2"); else error = fz_okay; @@ -799,7 +692,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj } } - error = pdf_loadtounicode(font, xref, nil, collection, tounicode); + error = pdf_loadtounicode(fontdesc, xref, nil, collection, tounicode); if (error) goto cleanup; @@ -807,7 +700,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj * Horizontal */ - fz_setdefaulthmtx((fz_font*)font, fz_toint(fz_dictgets(dict, "DW"))); + pdf_setdefaulthmtx(fontdesc, fz_toint(fz_dictgets(dict, "DW"))); widths = fz_dictgets(dict, "W"); if (widths) @@ -828,7 +721,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj for (k = 0; k < fz_arraylen(obj); k++) { w = fz_toint(fz_arrayget(obj, k)); - error = fz_addhmtx((fz_font*)font, c0 + k, c0 + k, w); + error = pdf_addhmtx(fontdesc, c0 + k, c0 + k, w); if (error) goto cleanup; } @@ -838,7 +731,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj { c1 = fz_toint(obj); w = fz_toint(fz_arrayget(widths, i + 2)); - error = fz_addhmtx((fz_font*)font, c0, c1, w); + error = pdf_addhmtx(fontdesc, c0, c1, w); if (error) goto cleanup; i += 3; @@ -848,7 +741,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj fz_dropobj(widths); } - error = fz_endhmtx((fz_font*)font); + error = pdf_endhmtx(fontdesc); if (error) goto cleanup; @@ -856,7 +749,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj * Vertical */ - if (pdf_getwmode(font->encoding) == 1) + if (pdf_getwmode(fontdesc->encoding) == 1) { fz_obj *obj; int dw2y = 880; @@ -869,7 +762,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj dw2w = fz_toint(fz_arrayget(obj, 1)); } - fz_setdefaultvmtx((fz_font*)font, dw2y, dw2w); + pdf_setdefaultvmtx(fontdesc, dw2y, dw2w); widths = fz_dictgets(dict, "W2"); if (widths) @@ -891,7 +784,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj w = fz_toint(fz_arrayget(obj, k + 0)); x = fz_toint(fz_arrayget(obj, k + 1)); y = fz_toint(fz_arrayget(obj, k + 2)); - error = fz_addvmtx((fz_font*)font, c0 + k, c0 + k, x, y, w); + error = pdf_addvmtx(fontdesc, c0 + k, c0 + k, x, y, w); if (error) goto cleanup; } @@ -903,7 +796,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj w = fz_toint(fz_arrayget(widths, i + 2)); x = fz_toint(fz_arrayget(widths, i + 3)); y = fz_toint(fz_arrayget(widths, i + 4)); - error = fz_addvmtx((fz_font*)font, c0, c1, x, y, w); + error = pdf_addvmtx(fontdesc, c0, c1, x, y, w); if (error) goto cleanup; i += 5; @@ -913,25 +806,26 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj fz_dropobj(widths); } - error = fz_endvmtx((fz_font*)font); + error = pdf_endvmtx(fontdesc); if (error) goto cleanup; } pdf_logfont("}\n"); - *fontp = font; + *fontdescp = fontdesc; return fz_okay; cleanup: if (widths) fz_dropobj(widths); - fz_dropfont((fz_font*)font); + fz_dropfont(fontdesc->font); + fz_free(fontdesc); return fz_rethrow(error, "cannot load cid font"); } static fz_error * -loadtype0(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) +loadtype0(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; fz_obj *dfonts; @@ -958,9 +852,9 @@ loadtype0(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) tounicode = fz_dictgets(dict, "ToUnicode"); if (!strcmp(fz_toname(subtype), "CIDFontType0")) - error = loadcidfont(fontp, xref, dfont, ref, encoding, tounicode); + error = loadcidfont(fontdescp, xref, dfont, ref, encoding, tounicode); else if (!strcmp(fz_toname(subtype), "CIDFontType2")) - error = loadcidfont(fontp, xref, dfont, ref, encoding, tounicode); + error = loadcidfont(fontdescp, xref, dfont, ref, encoding, tounicode); else error = fz_throw("syntaxerror: unknown cid font type"); @@ -978,41 +872,41 @@ loadtype0(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) */ fz_error * -pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *collection) +pdf_loadfontdescriptor(pdf_fontdesc *fontdesc, pdf_xref *xref, fz_obj *dict, char *collection) { fz_error *error; fz_obj *obj1, *obj2, *obj3, *obj; fz_rect bbox; char *fontname; - error = pdf_resolve(&desc, xref); + error = pdf_resolve(&dict, xref); if (error) return fz_rethrow(error, "cannot find font descriptor"); pdf_logfont("load fontdescriptor {\n"); - fontname = fz_toname(fz_dictgets(desc, "FontName")); + fontname = fz_toname(fz_dictgets(dict, "FontName")); pdf_logfont("fontname %s\n", fontname); - font->flags = fz_toint(fz_dictgets(desc, "Flags")); - font->italicangle = fz_toreal(fz_dictgets(desc, "ItalicAngle")); - font->ascent = fz_toreal(fz_dictgets(desc, "Ascent")); - font->descent = fz_toreal(fz_dictgets(desc, "Descent")); - font->capheight = fz_toreal(fz_dictgets(desc, "CapHeight")); - font->xheight = fz_toreal(fz_dictgets(desc, "XHeight")); - font->missingwidth = fz_toreal(fz_dictgets(desc, "MissingWidth")); + fontdesc->flags = fz_toint(fz_dictgets(dict, "Flags")); + fontdesc->italicangle = fz_toreal(fz_dictgets(dict, "ItalicAngle")); + fontdesc->ascent = fz_toreal(fz_dictgets(dict, "Ascent")); + fontdesc->descent = fz_toreal(fz_dictgets(dict, "Descent")); + fontdesc->capheight = fz_toreal(fz_dictgets(dict, "CapHeight")); + fontdesc->xheight = fz_toreal(fz_dictgets(dict, "XHeight")); + fontdesc->missingwidth = fz_toreal(fz_dictgets(dict, "MissingWidth")); - bbox = pdf_torect(fz_dictgets(desc, "FontBBox")); + bbox = pdf_torect(fz_dictgets(dict, "FontBBox")); pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); - pdf_logfont("flags %d\n", font->flags); + pdf_logfont("flags %d\n", fontdesc->flags); - obj1 = fz_dictgets(desc, "FontFile"); - obj2 = fz_dictgets(desc, "FontFile2"); - obj3 = fz_dictgets(desc, "FontFile3"); + obj1 = fz_dictgets(dict, "FontFile"); + obj2 = fz_dictgets(dict, "FontFile2"); + obj3 = fz_dictgets(dict, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (getenv("NOFONT")) @@ -1020,59 +914,91 @@ pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *colle if (fz_isindirect(obj)) { - error = pdf_loadembeddedfont(font, xref, obj); + error = pdf_loadembeddedfont(fontdesc, xref, obj); if (error) goto cleanup; } else { - error = pdf_loadsystemfont(font, fontname, collection); + error = pdf_loadsystemfont(fontdesc, fontname, collection); if (error) goto cleanup; } - fz_dropobj(desc); + fz_dropobj(dict); pdf_logfont("}\n"); return fz_okay; cleanup: - fz_dropobj(desc); + fz_dropobj(dict); return fz_rethrow(error, "cannot load font descriptor"); } fz_error * -pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) +pdf_loadfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; char *subtype; - if ((*fontp = pdf_finditem(xref->store, PDF_KFONT, ref))) + if ((*fontdescp = pdf_finditem(xref->store, PDF_KFONT, ref))) { - fz_keepfont((fz_font*)*fontp); + // XXX pdf_keepfontdesc(*fontdescp); return fz_okay; } subtype = fz_toname(fz_dictgets(dict, "Subtype")); if (!strcmp(subtype, "Type0")) - error = loadtype0(fontp, xref, dict, ref); + error = loadtype0(fontdescp, xref, dict, ref); else if (!strcmp(subtype, "Type1") || !strcmp(subtype, "MMType1")) - error = loadsimplefont(fontp, xref, dict, ref); + error = loadsimplefont(fontdescp, xref, dict, ref); else if (!strcmp(subtype, "TrueType")) - error = loadsimplefont(fontp, xref, dict, ref); + error = loadsimplefont(fontdescp, xref, dict, ref); else if (!strcmp(subtype, "Type3")) - error = pdf_loadtype3font(fontp, xref, dict, ref); + error = pdf_loadtype3font(fontdescp, xref, dict, ref); else return fz_throw("cannot recognize font format %s", subtype); if (error) return fz_rethrow(error, "cannot load font"); - error = pdf_storeitem(xref->store, PDF_KFONT, ref, *fontp); + error = pdf_storeitem(xref->store, PDF_KFONT, ref, *fontdescp); if (error) return fz_rethrow(error, "cannot store font resource"); return fz_okay; } +void +pdf_debugfont(pdf_fontdesc *fontdesc) +{ + int i; + + printf("fontdesc {\n"); + + if (fontdesc->font->ftface) + printf(" freetype font\n"); + if (fontdesc->font->t3procs) + printf(" type3 font\n"); + + printf(" wmode %d\n", fontdesc->wmode); + printf(" DW %d\n", fontdesc->dhmtx.w); + + printf(" W {\n"); + for (i = 0; i < fontdesc->nhmtx; i++) + printf(" <%04x> <%04x> %d\n", + fontdesc->hmtx[i].lo, fontdesc->hmtx[i].hi, fontdesc->hmtx[i].w); + printf(" }\n"); + + if (fontdesc->wmode) + { + printf(" DW2 [%d %d]\n", fontdesc->dvmtx.y, fontdesc->dvmtx.w); + printf(" W2 {\n"); + for (i = 0; i < fontdesc->nvmtx; i++) + printf(" <%04x> <%04x> %d %d %d\n", fontdesc->vmtx[i].lo, fontdesc->vmtx[i].hi, + fontdesc->vmtx[i].x, fontdesc->vmtx[i].y, fontdesc->vmtx[i].w); + printf(" }\n"); + } +} + diff --git a/mupdf/pdf_fontfile.c b/mupdf/pdf_fontfile.c index d9808328..4ba4dfba 100644 --- a/mupdf/pdf_fontfile.c +++ b/mupdf/pdf_fontfile.c @@ -3,11 +3,6 @@ #include "mupdf/base14.h" -#include <ft2build.h> -#include FT_FREETYPE_H - -static FT_Library ftlib = nil; - enum { FD_FIXED = 1 << 0, @@ -26,7 +21,7 @@ static const struct const char *name; const unsigned char *cff; const unsigned int *len; -} basefonts[15] = { +} basefonts[] = { { "Courier", fonts_NimbusMonL_Regu_cff, &fonts_NimbusMonL_Regu_cff_len }, @@ -71,7 +66,8 @@ static const struct &fonts_Dingbats_cff_len }, { "Chancery", fonts_URWChanceryL_MediItal_cff, - &fonts_URWChanceryL_MediItal_cff_len } + &fonts_URWChanceryL_MediItal_cff_len }, + { 0, 0, 0 } }; enum { CNS, GB, Japan, Korea }; @@ -110,39 +106,15 @@ static const struct subent fontsubs[] = { Korea, GOTHIC, "dotum.ttc" }, }; -static fz_error *initfontlibs(void) -{ - int fterr; - int maj, min, pat; - - if (ftlib) - return fz_okay; - - fterr = FT_Init_FreeType(&ftlib); - if (fterr) - return fz_throw("freetype failed initialisation: %s", ft_errstr(fterr)); - - FT_Library_Version(ftlib, &maj, &min, &pat); - if (maj == 2 && min == 1 && pat < 7) - return fz_throw("freetype version too old: %d.%d.%d", maj, min, pat); - - return fz_okay; -} - fz_error * -pdf_loadbuiltinfont(pdf_font *font, char *fontname) +pdf_loadbuiltinfont(pdf_fontdesc *font, char *fontname) { fz_error *error; unsigned char *data; unsigned int len; - int fterr; int i; - error = initfontlibs(); - if (error) - return fz_rethrow(error, "cannot init font libraries"); - - for (i = 0; i < 15; i++) + for (i = 0; basefonts[i].name; i++) if (!strcmp(fontname, basefonts[i].name)) goto found; @@ -154,9 +126,9 @@ found: data = (unsigned char *) basefonts[i].cff; len = *basefonts[i].len; - fterr = FT_New_Memory_Face(ftlib, data, len, 0, (FT_Face*)&font->ftface); - if (fterr) - return fz_throw("freetype: cannot load font: %s", ft_errstr(fterr)); + error = fz_newfontfrombuffer(&font->font, data, len, 0); + if (error) + return fz_rethrow(error, "cannot load freetype font from buffer"); return fz_okay; } @@ -229,10 +201,10 @@ findcidfont(char *filename, char *path, int pathlen) } static fz_error * -loadcidfont(pdf_font *font, int csi, int kind) +loadcidfont(pdf_fontdesc *font, int csi, int kind) { char path[1024]; - int fterr; + fz_error *error; int i; for (i = 0; i < nelem(fontsubs); i++) @@ -242,9 +214,11 @@ loadcidfont(pdf_font *font, int csi, int kind) if (findcidfont(fontsubs[i].name, path, sizeof path)) { pdf_logfont("load system font '%s'\n", fontsubs[i].name); - fterr = FT_New_Face(ftlib, path, 0, (FT_Face*)&font->ftface); - if (fterr) - return fz_throw("freetype: cannot load font: %s", ft_errstr(fterr)); + + error = fz_newfontfromfile(&font->font, path, 0); + if (error) + return fz_rethrow(error, "cannot load freetype font from file: %s", path); + return fz_okay; } } @@ -254,7 +228,7 @@ loadcidfont(pdf_font *font, int csi, int kind) } fz_error * -pdf_loadsystemfont(pdf_font *font, char *fontname, char *collection) +pdf_loadsystemfont(pdf_fontdesc *font, char *fontname, char *collection) { fz_error *error; char *name; @@ -265,11 +239,9 @@ pdf_loadsystemfont(pdf_font *font, char *fontname, char *collection) int isscript = 0; int isfixed = 0; - error = initfontlibs(); - if (error) - return fz_rethrow(error, "cannot init font libraries"); - - font->substitute = 1; +//XXX error = initfontlibs(); +// if (error) +// return fz_rethrow(error, "cannot init font libraries"); if (strstr(fontname, "Bold")) isbold = 1; @@ -358,20 +330,21 @@ pdf_loadsystemfont(pdf_font *font, char *fontname, char *collection) if (error) return fz_throw("cannot load builtin substitute font: %s", name); + /* it's a substitute font: override the metrics */ + font->font->ftsubstitute = 1; + return fz_okay; } fz_error * -pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref) +pdf_loadembeddedfont(pdf_fontdesc *font, pdf_xref *xref, fz_obj *stmref) { fz_error *error; - int fterr; - FT_Face face; fz_buffer *buf; - error = initfontlibs(); - if (error) - return fz_rethrow(error, "cannot init font libraries"); +//XXX error = initfontlibs(); +// if (error) +// return fz_rethrow(error, "cannot init font libraries"); pdf_logfont("load embedded font\n"); @@ -379,15 +352,15 @@ pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref) if (error) return fz_rethrow(error, "cannot load font stream"); - fterr = FT_New_Memory_Face(ftlib, buf->rp, buf->wp - buf->rp, 0, &face); - if (fterr) + error = fz_newfontfrombuffer(&font->font, buf->rp, buf->wp - buf->rp, 0); + if (error) { fz_dropbuffer(buf); - return fz_throw("freetype: cannot load embedded font: %s", ft_errstr(fterr)); + return fz_rethrow(error, "cannot load embedded font (%d %d R)", fz_tonum(stmref), fz_togen(stmref)); } - font->ftface = face; - font->fontdata = buf; +//XXX font->ftbuffer = buf->rp; /* save the buffer so we can free it later */ +// fz_free(buf); /* only free the fz_buffer struct, not the contained data */ return fz_okay; } diff --git a/mupdf/pdf_fontfilefc.c b/mupdf/pdf_fontfilefc.c index 904fbb9a..5573f128 100644 --- a/mupdf/pdf_fontfilefc.c +++ b/mupdf/pdf_fontfilefc.c @@ -71,7 +71,7 @@ static fz_error *initfontlibs(void) fterr = FT_Init_FreeType(&ftlib); if (fterr) - return fz_throw("freetype failed initialisation: %s", ft_errstr(fterr)); + return fz_throw("freetype failed initialisation: %s", ft_errorstring(fterr)); FT_Library_Version(ftlib, &maj, &min, &pat); if (maj == 2 && min == 1 && pat < 7) @@ -130,7 +130,7 @@ pdf_loadbuiltinfont(pdf_font *font, char *basefont) fterr = FT_New_Face(ftlib, file, index, &face); if (fterr) - return fz_throw("freetype could not load font file '%s': %s", file, ft_errstr(fterr)); + return fz_throw("freetype could not load font file '%s': %s", file, ft_errorstring(fterr)); FcPatternDestroy(matchpat); FcPatternDestroy(searchpat); @@ -247,7 +247,7 @@ pdf_loadsystemfont(pdf_font *font, char *basefont, char *collection) if (fterr) { FcPatternDestroy(matchpat); FcPatternDestroy(searchpat); - return fz_throw("freetype could not load font file '%s': %s", file, ft_errstr(fterr)); + return fz_throw("freetype could not load font file '%s': %s", file, ft_errorstring(fterr)); } FcPatternDestroy(matchpat); @@ -284,7 +284,7 @@ pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref) if (fterr) { fz_free(buf); - return fz_throw("freetype could not load embedded font: %s", ft_errstr(fterr)); + return fz_throw("freetype could not load embedded font: %s", ft_errorstring(fterr)); } font->ftface = face; diff --git a/mupdf/pdf_fontfilems.c b/mupdf/pdf_fontfilems.c index 24fa846d..e5d9d551 100644 --- a/mupdf/pdf_fontfilems.c +++ b/mupdf/pdf_fontfilems.c @@ -679,7 +679,7 @@ static fz_error *initfontlibs(void) fterr = FT_Init_FreeType(&ftlib); if (fterr) - return fz_throw("freetype failed initialisation: %s", ft_errstr(fterr)); + return fz_throw("freetype failed initialisation: %s", ft_errorstring(fterr)); FT_Library_Version(ftlib, &maj, &min, &pat); if (maj == 2 && min == 1 && pat < 7) @@ -712,7 +712,7 @@ pdf_loadbuiltinfont(pdf_font *font, char *basefont) fterr = FT_New_Face(ftlib, file, index, &face); if (fterr) - return fz_throw("freetype could not load font file '%s': %s", file, ft_errstr(fterr)); + return fz_throw("freetype could not load font file '%s': %s", file, ft_errorstring(fterr)); font->ftface = face; @@ -738,7 +738,7 @@ pdf_loadsystemfont(pdf_font *font, char *basefont, char *collection) fterr = FT_New_Face(ftlib, file, index, &face); if (fterr) { - return fz_throw("freetype could not load font file '%s': %s", file, ft_errstr(fterr)); + return fz_throw("freetype could not load font file '%s': %s", file, ft_errorstring(fterr)); } font->ftface = face; @@ -769,7 +769,7 @@ pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref) if (fterr) { fz_free(buf); - return fz_throw("freetype could not load embedded font: %s", ft_errstr(fterr)); + return fz_throw("freetype could not load embedded font: %s", ft_errorstring(fterr)); } font->ftface = face; diff --git a/mupdf/pdf_fontmtx.c b/mupdf/pdf_fontmtx.c new file mode 100644 index 00000000..cf1560f8 --- /dev/null +++ b/mupdf/pdf_fontmtx.c @@ -0,0 +1,179 @@ +#include "fitz.h" +#include "mupdf.h" + +void +pdf_setfontwmode(pdf_fontdesc *font, int wmode) +{ + font->wmode = wmode; +} + +void +pdf_setdefaulthmtx(pdf_fontdesc *font, int w) +{ + font->dhmtx.w = w; +} + +void +pdf_setdefaultvmtx(pdf_fontdesc *font, int y, int w) +{ + font->dvmtx.y = y; + font->dvmtx.w = w; +} + +fz_error * +pdf_addhmtx(pdf_fontdesc *font, int lo, int hi, int w) +{ + int newcap; + pdf_hmtx *newmtx; + + if (font->nhmtx + 1 >= font->hmtxcap) + { + newcap = font->hmtxcap + 16; + newmtx = fz_realloc(font->hmtx, sizeof(pdf_hmtx) * newcap); + if (!newmtx) + return fz_outofmem; + font->hmtxcap = newcap; + font->hmtx = newmtx; + } + + font->hmtx[font->nhmtx].lo = lo; + font->hmtx[font->nhmtx].hi = hi; + font->hmtx[font->nhmtx].w = w; + font->nhmtx++; + + return fz_okay; +} + +fz_error * +pdf_addvmtx(pdf_fontdesc *font, int lo, int hi, int x, int y, int w) +{ + int newcap; + pdf_vmtx *newmtx; + + if (font->nvmtx + 1 >= font->vmtxcap) + { + newcap = font->vmtxcap + 16; + newmtx = fz_realloc(font->vmtx, sizeof(pdf_vmtx) * newcap); + if (!newmtx) + return fz_outofmem; + font->vmtxcap = newcap; + font->vmtx = newmtx; + } + + font->vmtx[font->nvmtx].lo = lo; + font->vmtx[font->nvmtx].hi = hi; + font->vmtx[font->nvmtx].x = x; + font->vmtx[font->nvmtx].y = y; + font->vmtx[font->nvmtx].w = w; + font->nvmtx++; + + return fz_okay; +} + +static int cmph(const void *a0, const void *b0) +{ + pdf_hmtx *a = (pdf_hmtx*)a0; + pdf_hmtx *b = (pdf_hmtx*)b0; + return a->lo - b->lo; +} + +static int cmpv(const void *a0, const void *b0) +{ + pdf_vmtx *a = (pdf_vmtx*)a0; + pdf_vmtx *b = (pdf_vmtx*)b0; + return a->lo - b->lo; +} + +fz_error * +pdf_endhmtx(pdf_fontdesc *font) +{ + pdf_hmtx *newmtx; + + if (!font->hmtx) + return fz_okay; + + qsort(font->hmtx, font->nhmtx, sizeof(pdf_hmtx), cmph); + + newmtx = fz_realloc(font->hmtx, sizeof(pdf_hmtx) * font->nhmtx); + if (!newmtx) + return fz_outofmem; + font->hmtxcap = font->nhmtx; + font->hmtx = newmtx; + + return fz_okay; +} + +fz_error * +pdf_endvmtx(pdf_fontdesc *font) +{ + pdf_vmtx *newmtx; + + if (!font->vmtx) + return fz_okay; + + qsort(font->vmtx, font->nvmtx, sizeof(pdf_vmtx), cmpv); + + newmtx = fz_realloc(font->vmtx, sizeof(pdf_vmtx) * font->nvmtx); + if (!newmtx) + return fz_outofmem; + font->vmtxcap = font->nvmtx; + font->vmtx = newmtx; + + return fz_okay; +} + +pdf_hmtx +pdf_gethmtx(pdf_fontdesc *font, int cid) +{ + int l = 0; + int r = font->nhmtx - 1; + int m; + + if (!font->hmtx) + goto notfound; + + while (l <= r) + { + m = (l + r) >> 1; + if (cid < font->hmtx[m].lo) + r = m - 1; + else if (cid > font->hmtx[m].hi) + l = m + 1; + else + return font->hmtx[m]; + } + +notfound: + return font->dhmtx; +} + +pdf_vmtx +pdf_getvmtx(pdf_fontdesc *font, int cid) +{ + pdf_hmtx h; + pdf_vmtx v; + int l = 0; + int r = font->nvmtx - 1; + int m; + + if (!font->vmtx) + goto notfound; + + while (l <= r) + { + m = (l + r) >> 1; + if (cid < font->vmtx[m].lo) + r = m - 1; + else if (cid > font->vmtx[m].hi) + l = m + 1; + else + return font->vmtx[m]; + } + +notfound: + h = pdf_gethmtx(font, cid); + v = font->dvmtx; + v.x = h.w / 2; + return v; +} + diff --git a/mupdf/pdf_resources.c b/mupdf/pdf_resources.c index 7a2c750c..52bd624e 100644 --- a/mupdf/pdf_resources.c +++ b/mupdf/pdf_resources.c @@ -180,13 +180,13 @@ static fz_error * preloadfont(pdf_xref *xref, fz_obj *ref) { fz_error *error; - pdf_font *font; + pdf_fontdesc *font; fz_obj *obj = ref; error = pdf_resolve(&obj, xref); if (error) return fz_rethrow(error, "cannot resolve font resource (%d %d R)", fz_tonum(ref), fz_togen(ref)); error = pdf_loadfont(&font, xref, obj, ref); - fz_dropfont((fz_font*)font); /* we did this just to fill the store, no need to hold on to it */ + pdf_dropfont(font); /* we did this just to fill the store, no need to hold on to it */ if (error) return fz_rethrow(error, "cannot load font resource (%d %d R)", fz_tonum(ref), fz_togen(ref)); return fz_okay; diff --git a/mupdf/pdf_store.c b/mupdf/pdf_store.c index 917a1ebc..ab8004a0 100644 --- a/mupdf/pdf_store.c +++ b/mupdf/pdf_store.c @@ -58,7 +58,7 @@ static void dropitem(pdf_itemkind kind, void *val) case PDF_KPATTERN: pdf_droppattern(val); break; case PDF_KSHADE: fz_dropshade(val); break; case PDF_KCMAP: pdf_dropcmap(val); break; - case PDF_KFONT: fz_dropfont(val); break; + case PDF_KFONT: pdf_dropfont(val); break; } } @@ -234,7 +234,7 @@ pdf_removeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key) case PDF_KPATTERN: pdf_droppattern(val); break; case PDF_KSHADE: fz_dropshade(val); break; case PDF_KCMAP: pdf_dropcmap(val); break; - case PDF_KFONT: fz_dropfont(val); break; + case PDF_KFONT: pdf_dropfont(val); break; } } diff --git a/mupdf/pdf_type3.c b/mupdf/pdf_type3.c index 7948a9a5..35f0591b 100644 --- a/mupdf/pdf_type3.c +++ b/mupdf/pdf_type3.c @@ -1,68 +1,6 @@ #include "fitz.h" #include "mupdf.h" -/* TODO: we leak the pixmap buffer. not good. we should render into the glyph cache directly or keep it in the font struct.. */ - -#define GCMEM (4 * 1024) - -extern pdf_font *pdf_newfont(char *name); - -static void -t3dropfont(fz_font *font) -{ - int i; - pdf_font *pfont = (pdf_font*)font; - if (pfont->encoding) - pdf_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_irect bbox; - - if (cid < 0 || cid > 255) - return fz_throw("assert: glyph out of range"); - - tree = font->charprocs[cid]; - if (!tree) - { - glyph->w = 0; - glyph->h = 0; - return fz_okay; - } - - ctm = fz_concat(font->matrix, trm); - bbox = fz_roundrect(fz_boundtree(tree, ctm)); - - error = fz_newrenderer(&gc, pdf_devicegray, 1, GCMEM); - if (error) - return fz_rethrow(error, "cannot create renderer"); - error = fz_rendertree(&pixmap, gc, tree, ctm, bbox, 0); - fz_droprenderer(gc); - if (error) - return fz_rethrow(error, "cannot render glyph"); - - assert(pixmap->n == 1); - - glyph->x = pixmap->x; - glyph->y = pixmap->y; - glyph->w = pixmap->w; - glyph->h = pixmap->h; - glyph->samples = pixmap->samples; - - return fz_okay; -} - static fz_error * loadcharproc(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *stmref) { @@ -98,12 +36,12 @@ loadcharproc(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *stmref) } fz_error * -pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) +pdf_loadtype3font(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; char buf[256]; char *estrings[256]; - pdf_font *font; + pdf_fontdesc *fontdesc; fz_obj *encoding; fz_obj *widths; fz_obj *resources; @@ -119,23 +57,20 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) else sprintf(buf, "Unnamed-T3"); - font = pdf_newfont(buf); - if (!font) + fontdesc = pdf_newfontdesc(); + if (!fontdesc) return fz_throw("outofmem: font struct"); - pdf_logfont("load type3 font (%d %d R) ptr=%p {\n", fz_tonum(ref), fz_togen(ref), font); + pdf_logfont("load type3 font (%d %d R) ptr=%p {\n", fz_tonum(ref), fz_togen(ref), fontdesc); pdf_logfont("name %s\n", buf); - font->super.render = t3render; - font->super.drop = (void(*)(fz_font*)) t3dropfont; - obj = fz_dictgets(dict, "FontMatrix"); - font->matrix = pdf_tomatrix(obj); + fontdesc->font->t3matrix = pdf_tomatrix(obj); pdf_logfont("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); + fontdesc->font->t3matrix.a, fontdesc->font->t3matrix.b, + fontdesc->font->t3matrix.c, fontdesc->font->t3matrix.d, + fontdesc->font->t3matrix.e, fontdesc->font->t3matrix.f); obj = fz_dictgets(dict, "FontBBox"); bbox = pdf_torect(obj); @@ -144,12 +79,12 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) bbox.x0, bbox.y0, bbox.x1, bbox.y1); - bbox = fz_transformaabb(font->matrix, bbox); + bbox = fz_transformaabb(fontdesc->font->t3matrix, bbox); bbox.x0 = fz_floor(bbox.x0 * 1000); bbox.y0 = fz_floor(bbox.y0 * 1000); bbox.x1 = fz_ceil(bbox.x1 * 1000); bbox.y1 = fz_ceil(bbox.y1 * 1000); - fz_setfontbbox((fz_font*)font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); + fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding @@ -199,11 +134,11 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) fz_dropobj(encoding); - error = pdf_newidentitycmap(&font->encoding, 0, 1); + error = pdf_newidentitycmap(&fontdesc->encoding, 0, 1); if (error) goto cleanup; - error = pdf_loadtounicode(font, xref, + error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; @@ -212,7 +147,7 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) * Widths */ - fz_setdefaulthmtx((fz_font*)font, 0); + pdf_setdefaulthmtx(fontdesc, 0); first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); @@ -230,8 +165,8 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) 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); + w = fontdesc->font->t3matrix.a * w * 1000.0; + error = pdf_addhmtx(fontdesc, i, i, w); if (error) { fz_dropobj(widths); goto cleanup; @@ -240,7 +175,7 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) fz_dropobj(widths); - error = fz_endhmtx((fz_font*)font); + error = pdf_endhmtx(fontdesc); if (error) goto cleanup; @@ -290,11 +225,11 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) if (obj) { pdf_logfont("load charproc %s {\n", estrings[i]); - error = loadcharproc(&font->charprocs[i], xref, resources, obj); + error = loadcharproc(&fontdesc->font->t3procs[i], xref, resources, obj); if (error) goto cleanup2; - error = fz_optimizetree(font->charprocs[i]); + error = fz_optimizetree(fontdesc->font->t3procs[i]); if (error) goto cleanup2; @@ -309,14 +244,15 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) pdf_logfont("}\n"); - *fontp = font; + *fontdescp = fontdesc; return fz_okay; cleanup2: if (resources) fz_dropobj(resources); cleanup: - fz_dropfont((fz_font*)font); + fz_dropfont(fontdesc->font); + fz_free(fontdesc); return fz_rethrow(error, "cannot load type3 font"); } diff --git a/mupdf/pdf_unicode.c b/mupdf/pdf_unicode.c index 8c3a90a2..4001b5b0 100644 --- a/mupdf/pdf_unicode.c +++ b/mupdf/pdf_unicode.c @@ -6,7 +6,7 @@ */ fz_error * -pdf_loadtounicode(pdf_font *font, pdf_xref *xref, +pdf_loadtounicode(pdf_fontdesc *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm) { fz_error *error = fz_okay; @@ -115,9 +115,15 @@ pdf_loadtounicode(pdf_font *font, pdf_xref *xref, } /* - * Extract lines of text from display tree + * Extract lines of text from display tree. + * + * This extraction needs to be rewritten for the new tree + * architecture where glyph index and unicode characters are both stored + * in the text objects. */ +#if 0 + fz_error * pdf_newtextline(pdf_textline **linep) { @@ -175,7 +181,7 @@ extracttext(pdf_textline **line, fz_node *node, fz_matrix ctm) if (fz_istextnode(node)) { fz_textnode *text = (fz_textnode*)node; - pdf_font *font = (pdf_font*)text->font; + pdf_fontdesc *font = (pdf_fontdesc*)text->font; fz_matrix inv = fz_invertmatrix(text->trm); fz_matrix tm = text->trm; fz_matrix trm; @@ -183,7 +189,7 @@ extracttext(pdf_textline **line, fz_node *node, fz_matrix ctm) fz_point p; fz_point vx; fz_point vy; - fz_vmtx v; + _vmtx v; fz_hmtx h; int i, g; int x, y; @@ -329,3 +335,5 @@ pdf_debugtextline(pdf_textline *line) pdf_debugtextline(line->next); } +#endif + diff --git a/raster/glyphcache.c b/raster/glyphcache.c index e2d93bc9..fe03524e 100644 --- a/raster/glyphcache.c +++ b/raster/glyphcache.c @@ -352,9 +352,22 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz ctm.e = fz_floor(ctm.e) + key.e / 256.0; ctm.f = fz_floor(ctm.f) + key.f / 256.0; - error = font->render(glyph, font, cid, ctm); - if (error) + if (font->ftface) + { + error = fz_renderftglyph(glyph, font, cid, ctm); + if (error) + return error; + } + else if (font->t3procs) + { + error = fz_rendert3glyph(glyph, font, cid, ctm); + if (error) return error; + } + else + { + return fz_throw("uninitialized font structure"); + } size = glyph->w * glyph->h; diff --git a/raster/render.c b/raster/render.c index bbdf019f..90ead6a7 100644 --- a/raster/render.c +++ b/raster/render.c @@ -315,7 +315,7 @@ rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm) fz_irect clip; fz_matrix tm, trm; fz_glyph glyph; - int i, x, y, cid; + int i, x, y, gid; tbox = fz_roundrect(fz_boundnode((fz_node*)text, ctm)); clip = fz_intersectirects(gc->clip, tbox); @@ -339,7 +339,7 @@ text->trm.a, text->trm.b, text->trm.c, text->trm.d); for (i = 0; i < text->len; i++) { - cid = text->els[i].cid; + gid = text->els[i].gid; tm.e = text->els[i].x; tm.f = text->els[i].y; trm = fz_concat(tm, ctm); @@ -348,7 +348,7 @@ text->trm.a, text->trm.b, text->trm.c, text->trm.d); trm.e = QUANT(trm.e - fz_floor(trm.e), HSUBPIX); trm.f = QUANT(trm.f - fz_floor(trm.f), VSUBPIX); - error = fz_renderglyph(gc->cache, &glyph, text->font, cid, trm); + error = fz_renderglyph(gc->cache, &glyph, text->font, gid, trm); if (error) return error; diff --git a/world/node_text.c b/world/node_text.c index b816196e..86a523df 100644 --- a/world/node_text.c +++ b/world/node_text.c @@ -129,11 +129,12 @@ growtext(fz_textnode *text, int n) } fz_error * -fz_addtext(fz_textnode *text, int cid, float x, float y) +fz_addtext(fz_textnode *text, int gid, int ucs, float x, float y) { if (growtext(text, 1) != nil) return fz_outofmem; - text->els[text->len].cid = cid; + text->els[text->len].ucs = ucs; + text->els[text->len].gid = gid; text->els[text->len].x = x; text->els[text->len].y = y; text->len++; diff --git a/world/node_toxml.c b/world/node_toxml.c index 4dff8dbf..cc87c997 100644 --- a/world/node_toxml.c +++ b/world/node_toxml.c @@ -119,12 +119,12 @@ static void xmltext(fz_textnode *node, int level) for (i = 0; i < node->len; i++) { indent(level + 1); - if (node->els[i].cid >= 32 && node->els[i].cid < 128) - printf("<g c=\"%c\" x=\"%g\" y=\"%g\" />\n", - node->els[i].cid, node->els[i].x, node->els[i].y); + if (node->els[i].ucs >= 32 && node->els[i].ucs < 128) + printf("<g ucs=\"%c\" gid=%d x=\"%g\" y=\"%g\" />\n", + node->els[i].ucs, node->els[i].gid, node->els[i].x, node->els[i].y); else - printf("<g c=\"<%04x>\" x=\"%g\" y=\"%g\" />\n", - node->els[i].cid, node->els[i].x, node->els[i].y); + printf("<g ucs=\"U+%04X\" gid=%d x=\"%g\" y=\"%g\" />\n", + node->els[i].ucs, node->els[i].gid, node->els[i].x, node->els[i].y); } indent(level); diff --git a/world/res_font.c b/world/res_font.c index 9d5f29bf..299f0d50 100644 --- a/world/res_font.c +++ b/world/res_font.c @@ -1,35 +1,34 @@ #include "fitz-base.h" #include "fitz-world.h" +#include "fitz-draw.h" /* for type3 font rendering */ -void -fz_initfont(fz_font *font, char *name) +#include <ft2build.h> +#include FT_FREETYPE_H + +static fz_font * +fz_newfont(void) { + fz_font *font; + + font = fz_malloc(sizeof(fz_font)); + if (!font) + return nil; + font->refs = 1; - strlcpy(font->name, name, sizeof font->name); + strcpy(font->name, "<unknown>"); + + font->ftsubstitute = 0; + font->ftface = nil; - font->wmode = 0; + font->t3matrix = fz_identity(); + font->t3procs = nil; font->bbox.x0 = 0; font->bbox.y0 = 0; font->bbox.x1 = 1000; font->bbox.y1 = 1000; - font->hmtxcap = 0; - font->vmtxcap = 0; - font->nhmtx = 0; - font->nvmtx = 0; - font->hmtx = nil; - font->vmtx = nil; - - font->dhmtx.lo = 0x0000; - font->dhmtx.hi = 0xFFFF; - font->dhmtx.w = 0; - - font->dvmtx.lo = 0x0000; - font->dvmtx.hi = 0xFFFF; - font->dvmtx.x = 0; - font->dvmtx.y = 880; - font->dvmtx.w = -1000; + return font; } fz_font * @@ -42,23 +41,28 @@ fz_keepfont(fz_font *font) void fz_dropfont(fz_font *font) { + int i; + if (font && --font->refs == 0) { - if (font->drop) - font->drop(font); - fz_free(font->hmtx); - fz_free(font->vmtx); + if (font->t3procs) + { + for (i = 0; i < 256; i++) + if (font->t3procs[i]) + fz_droptree(font->t3procs[i]); + fz_free(font->t3procs); + } + + if (font->ftface) + { + FT_Done_Face((FT_Face)font->ftface); + } + fz_free(font); } } void -fz_setfontwmode(fz_font *font, int wmode) -{ - font->wmode = wmode; -} - -void fz_setfontbbox(fz_font *font, int xmin, int ymin, int xmax, int ymax) { font->bbox.x0 = xmin; @@ -67,204 +71,310 @@ fz_setfontbbox(fz_font *font, int xmin, int ymin, int xmax, int ymax) font->bbox.y1 = ymax; } -void -fz_setdefaulthmtx(fz_font *font, int w) +/* + * Freetype hooks + */ + +static FT_Library fz_ftlib = nil; + +#undef __FTERRORS_H__ +#define FT_ERRORDEF(e, v, s) { (e), (s) }, +#define FT_ERROR_START_LIST +#define FT_ERROR_END_LIST { 0, NULL } + +struct ft_error { - font->dhmtx.w = w; -} + int err; + char *str; +}; -void -fz_setdefaultvmtx(fz_font *font, int y, int w) +const struct ft_error ft_errors[] = { - font->dvmtx.y = y; - font->dvmtx.w = w; +#include FT_ERRORS_H +}; + +char *ft_errorstring(int err) +{ + const struct ft_error *e; + + for (e = ft_errors; e->str != NULL; e++) + if (e->err == err) + return e->str; + + return "Unknown error"; } -fz_error * -fz_addhmtx(fz_font *font, int lo, int hi, int w) +static fz_error * +fz_initfreetype(void) { - int newcap; - fz_hmtx *newmtx; + int code; + int maj, min, pat; - if (font->nhmtx + 1 >= font->hmtxcap) - { - newcap = font->hmtxcap + 16; - newmtx = fz_realloc(font->hmtx, sizeof(fz_hmtx) * newcap); - if (!newmtx) - return fz_outofmem; - font->hmtxcap = newcap; - font->hmtx = newmtx; - } + if (fz_ftlib) + return fz_okay; + + code = FT_Init_FreeType(&fz_ftlib); + if (code) + return fz_throw("cannot init freetype: %s", ft_errorstring(code)); - font->hmtx[font->nhmtx].lo = lo; - font->hmtx[font->nhmtx].hi = hi; - font->hmtx[font->nhmtx].w = w; - font->nhmtx++; + FT_Library_Version(fz_ftlib, &maj, &min, &pat); + if (maj == 2 && min == 1 && pat < 7) + return fz_throw("freetype version too old: %d.%d.%d", maj, min, pat); return fz_okay; } fz_error * -fz_addvmtx(fz_font *font, int lo, int hi, int x, int y, int w) +fz_newfontfromfile(fz_font **fontp, char *path, int index) { - int newcap; - fz_vmtx *newmtx; + fz_error *error; + fz_font *font; + int code; - if (font->nvmtx + 1 >= font->vmtxcap) + error = fz_initfreetype(); + if (error) + return fz_rethrow(error, "cannot init freetype library"); + + font = fz_newfont(); + if (!font) + return fz_throw("outofmem: font struct"); + + code = FT_New_Face(fz_ftlib, path, index, (FT_Face*)&font->ftface); + if (code) { - newcap = font->vmtxcap + 16; - newmtx = fz_realloc(font->vmtx, sizeof(fz_vmtx) * newcap); - if (!newmtx) - return fz_outofmem; - font->vmtxcap = newcap; - font->vmtx = newmtx; + fz_free(font); + return fz_throw("freetype: cannot load font: %s", ft_errorstring(code)); } - font->vmtx[font->nvmtx].lo = lo; - font->vmtx[font->nvmtx].hi = hi; - font->vmtx[font->nvmtx].x = x; - font->vmtx[font->nvmtx].y = y; - font->vmtx[font->nvmtx].w = w; - font->nvmtx++; - + *fontp = font; return fz_okay; } -static int cmph(const void *a0, const void *b0) -{ - fz_hmtx *a = (fz_hmtx*)a0; - fz_hmtx *b = (fz_hmtx*)b0; - return a->lo - b->lo; -} - -static int cmpv(const void *a0, const void *b0) -{ - fz_vmtx *a = (fz_vmtx*)a0; - fz_vmtx *b = (fz_vmtx*)b0; - return a->lo - b->lo; -} - fz_error * -fz_endhmtx(fz_font *font) +fz_newfontfrombuffer(fz_font **fontp, unsigned char *data, int len, int index) { - fz_hmtx *newmtx; + fz_error *error; + fz_font *font; + int code; - if (!font->hmtx) - return fz_okay; + error = fz_initfreetype(); + if (error) + return fz_rethrow(error, "cannot init freetype library"); - qsort(font->hmtx, font->nhmtx, sizeof(fz_hmtx), cmph); + font = fz_newfont(); + if (!font) + return fz_throw("outofmem: font struct"); - newmtx = fz_realloc(font->hmtx, sizeof(fz_hmtx) * font->nhmtx); - if (!newmtx) - return fz_outofmem; - font->hmtxcap = font->nhmtx; - font->hmtx = newmtx; + code = FT_New_Memory_Face(fz_ftlib, data, len, index, (FT_Face*)&font->ftface); + if (code) + { + fz_free(font); + return fz_throw("freetype: cannot load font: %s", ft_errorstring(code)); + } + *fontp = font; return fz_okay; } fz_error * -fz_endvmtx(fz_font *font) +fz_renderftglyph(fz_glyph *glyph, fz_font *font, int gid, fz_matrix trm) { - fz_vmtx *newmtx; + FT_Face face = font->ftface; + FT_Matrix m; + FT_Vector v; + FT_Error fterr; + int x, y; + +#if 0 + /* We lost this feature in refactoring. + * We can't access pdf_fontdesc metrics from fz_font. + * The pdf_fontdesc metrics are character based (cid), + * where the glyph being rendered is given by glyph (gid). + */ + if (font->ftsubstitute && font->wmode == 0) + { + fz_hmtx subw; + int realw; + float scale; - if (!font->vmtx) - return fz_okay; + FT_Set_Char_Size(face, 1000, 1000, 72, 72); - qsort(font->vmtx, font->nvmtx, sizeof(fz_vmtx), cmpv); + fterr = FT_Load_Glyph(font->ftface, gid, + FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); + if (fterr) + return fz_throw("freetype failed to load glyph: %s", ft_errorstring(fterr)); + + realw = ((FT_Face)font->ftface)->glyph->advance.x; + subw = fz_gethmtx(font, cid); // <-- this is the offender + if (realw) + scale = (float) subw.w / realw; + else + scale = 1.0; - newmtx = fz_realloc(font->vmtx, sizeof(fz_vmtx) * font->nvmtx); - if (!newmtx) - return fz_outofmem; - font->vmtxcap = font->nvmtx; - font->vmtx = newmtx; + trm = fz_concat(fz_scale(scale, 1.0), trm); + } +#endif + + glyph->w = 0; + glyph->h = 0; + glyph->x = 0; + glyph->y = 0; + glyph->samples = nil; + + /* freetype mutilates complex glyphs if they are loaded + * with FT_Set_Char_Size 1.0. it rounds the coordinates + * before applying transformation. to get more precision in + * freetype, we shift part of the scale in the matrix + * into FT_Set_Char_Size instead + */ + + m.xx = trm.a * 64; /* should be 65536 */ + m.yx = trm.b * 64; + m.xy = trm.c * 64; + m.yy = trm.d * 64; + v.x = trm.e * 64; + v.y = trm.f * 64; + + FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ + FT_Set_Transform(face, &m, &v); + + fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); + if (fterr) + fz_warn("freetype load glyph: %s", ft_errorstring(fterr)); + fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal); + + if (fterr) + fz_warn("freetype render glyph: %s", ft_errorstring(fterr)); + + glyph->w = face->glyph->bitmap.width; + glyph->h = face->glyph->bitmap.rows; + glyph->x = face->glyph->bitmap_left; + glyph->y = face->glyph->bitmap_top - glyph->h; + glyph->samples = face->glyph->bitmap.buffer; + + for (y = 0; y < glyph->h / 2; y++) + { + for (x = 0; x < glyph->w; x++) + { + unsigned char a = glyph->samples[y * glyph->w + x ]; + unsigned char b = glyph->samples[(glyph->h - y - 1) * glyph->w + x]; + glyph->samples[y * glyph->w + x ] = b; + glyph->samples[(glyph->h - y - 1) * glyph->w + x] = a; + } + } return fz_okay; } -fz_hmtx -fz_gethmtx(fz_font *font, int cid) + +/* + * Type 3 fonts... + */ + +fz_error * +fz_newtype3font(fz_font **fontp, char *name, fz_matrix matrix, void **procs0) { - int l = 0; - int r = font->nhmtx - 1; - int m; + fz_font *font; + fz_tree **procs = (fz_tree**)procs0; + int i; - if (!font->hmtx) - goto notfound; + font = fz_newfont(); + if (!font) + return fz_throw("outofmem: font struct"); - while (l <= r) + font->t3procs = fz_malloc(sizeof(fz_tree*) * 256); + if (!font->t3procs) { - m = (l + r) >> 1; - if (cid < font->hmtx[m].lo) - r = m - 1; - else if (cid > font->hmtx[m].hi) - l = m + 1; - else - return font->hmtx[m]; + fz_free(font); + return fz_throw("outofmem: type3 font charproc array"); } -notfound: - return font->dhmtx; + font->t3matrix = matrix; + for (i = 0; i < 256; i++) + font->t3procs[i] = procs[i]; + + strlcpy(font->name, name, sizeof(font->name)); + + *fontp = font; + return fz_okay; } -fz_vmtx -fz_getvmtx(fz_font *font, int cid) +fz_error * +fz_rendert3glyph(fz_glyph *glyph, fz_font *font, int gid, fz_matrix trm) { - fz_hmtx h; - fz_vmtx v; - int l = 0; - int r = font->nvmtx - 1; - int m; + fz_error *error; + fz_renderer *gc; + fz_tree *tree; + fz_matrix ctm; + fz_irect bbox; + + /* TODO: make it reentrant */ + static fz_pixmap *pixmap = nil; + if (pixmap) + { + fz_droppixmap(pixmap); + pixmap = nil; + } + + if (gid < 0 || gid > 255) + return fz_throw("assert: glyph out of range"); + + tree = font->t3procs[gid]; + if (!tree) + { + glyph->w = 0; + glyph->h = 0; + return fz_okay; + } - if (!font->vmtx) - goto notfound; + /* XXX UGLY HACK XXX */ + extern fz_colorspace *pdf_devicegray; - while (l <= r) - { - m = (l + r) >> 1; - if (cid < font->vmtx[m].lo) - r = m - 1; - else if (cid > font->vmtx[m].hi) - l = m + 1; - else - return font->vmtx[m]; - } + ctm = fz_concat(font->t3matrix, trm); + bbox = fz_roundrect(fz_boundtree(tree, ctm)); + + error = fz_newrenderer(&gc, pdf_devicegray, 1, 4096); + if (error) + return fz_rethrow(error, "cannot create renderer"); + error = fz_rendertree(&pixmap, gc, tree, ctm, bbox, 0); + fz_droprenderer(gc); + if (error) + return fz_rethrow(error, "cannot render glyph"); -notfound: - h = fz_gethmtx(font, cid); - v = font->dvmtx; - v.x = h.w / 2; - return v; + assert(pixmap->n == 1); + + glyph->x = pixmap->x; + glyph->y = pixmap->y; + glyph->w = pixmap->w; + glyph->h = pixmap->h; + glyph->samples = pixmap->samples; + + return fz_okay; } void fz_debugfont(fz_font *font) { - int i; - printf("font '%s' {\n", font->name); - printf(" wmode %d\n", font->wmode); - printf(" bbox [%d %d %d %d]\n", - font->bbox.x0, font->bbox.y0, - font->bbox.x1, font->bbox.y1); - printf(" DW %d\n", font->dhmtx.w); - printf(" W {\n"); - for (i = 0; i < font->nhmtx; i++) - printf(" <%04x> <%04x> %d\n", - font->hmtx[i].lo, font->hmtx[i].hi, font->hmtx[i].w); - printf(" }\n"); + if (font->ftface) + { + printf(" freetype face %p\n", font->ftface); + if (font->ftsubstitute) + printf(" substitute metrics\n"); + } - if (font->wmode) + if (font->t3procs) { - printf(" DW2 [%d %d]\n", font->dvmtx.y, font->dvmtx.w); - printf(" W2 {\n"); - for (i = 0; i < font->nvmtx; i++) - printf(" <%04x> <%04x> %d %d %d\n", font->vmtx[i].lo, font->vmtx[i].hi, - font->vmtx[i].x, font->vmtx[i].y, font->vmtx[i].w); - printf(" }\n"); + printf(" type3 matrix [%g %g %g %g]\n", + font->t3matrix.a, font->t3matrix.b, + font->t3matrix.c, font->t3matrix.d); } + printf(" bbox [%d %d %d %d]\n", + font->bbox.x0, font->bbox.y0, + font->bbox.x1, font->bbox.y1); + printf("}\n"); } |