static FT_Error tt_glyph_load( FT_GlyphSlot ttslot, /* TT_GlyphSlot */ FT_Size ttsize, /* TT_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { TT_GlyphSlot slot = (TT_GlyphSlot)ttslot; TT_Size size = (TT_Size)ttsize; FT_Face face = ttslot->face; FT_Error error; if ( !slot ) return FT_THROW( Invalid_Slot_Handle ); if ( !size ) return FT_THROW( Invalid_Size_Handle ); if ( !face ) return FT_THROW( Invalid_Argument ); #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( glyph_index >= (FT_UInt)face->num_glyphs && !face->internal->incremental_interface ) #else if ( glyph_index >= (FT_UInt)face->num_glyphs ) #endif return FT_THROW( Invalid_Argument ); if ( load_flags & FT_LOAD_NO_HINTING ) { /* both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT */ /* are necessary to disable hinting for tricky fonts */ if ( FT_IS_TRICKY( face ) ) load_flags &= ~FT_LOAD_NO_HINTING; if ( load_flags & FT_LOAD_NO_AUTOHINT ) load_flags |= FT_LOAD_NO_HINTING; } if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) ) { load_flags |= FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE; if ( !FT_IS_TRICKY( face ) ) load_flags |= FT_LOAD_NO_HINTING; } /* now load the glyph outline if necessary */ error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); /* force drop-out mode to 2 - irrelevant now */ /* slot->outline.dropout_mode = 2; */ return error; }
static fz_error loadcidfont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *encoding, fz_obj *tounicode) { fz_error error; fz_obj *widths; fz_obj *descriptor; pdf_fontdesc *fontdesc; FT_Face face; fz_bbox bbox; int kind; char collection[256]; char *basefont; int i, k, fterr; fz_obj *obj; int dw; /* Get font name and CID collection */ basefont = fz_toname(fz_dictgets(dict, "BaseFont")); { fz_obj *cidinfo; char tmpstr[64]; int tmplen; cidinfo = fz_dictgets(dict, "CIDSystemInfo"); if (!cidinfo) return fz_throw("cid font is missing info"); obj = fz_dictgets(cidinfo, "Registry"); tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; fz_strlcpy(collection, tmpstr, sizeof collection); fz_strlcat(collection, "-", sizeof collection); obj = fz_dictgets(cidinfo, "Ordering"); tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; fz_strlcat(collection, tmpstr, sizeof collection); } /* Load font file */ fontdesc = pdf_newfontdesc(); pdf_logfont("load cid font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("basefont %s\n", basefont); pdf_logfont("collection %s\n", collection); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor) error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, collection, basefont); else error = fz_throw("syntaxerror: missing font descriptor"); if (error) goto cleanup; face = fontdesc->font->ftface; kind = ftkind(face); bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM; bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM; bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM; bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM; pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) fz_setfontbbox(fontdesc->font, -1000, -1000, 2000, 2000); else fz_setfontbbox(fontdesc->font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* Check for DynaLab fonts that must use hinting */ if (kind == TRUETYPE) { if (FT_IS_TRICKY(face) || isdynalab(fontdesc->font->name)) { fontdesc->font->fthint = 1; pdf_logfont("forced hinting for dynalab font\n"); } } /* Encoding */ error = fz_okay; if (fz_isname(encoding)) { pdf_logfont("encoding /%s\n", fz_toname(encoding)); if (!strcmp(fz_toname(encoding), "Identity-H")) fontdesc->encoding = pdf_newidentitycmap(0, 2); else if (!strcmp(fz_toname(encoding), "Identity-V")) fontdesc->encoding = pdf_newidentitycmap(1, 2); else 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(&fontdesc->encoding, xref, encoding); } else { error = fz_throw("syntaxerror: font missing encoding"); } if (error) goto cleanup; pdf_setfontwmode(fontdesc, pdf_getwmode(fontdesc->encoding)); pdf_logfont("wmode %d\n", pdf_getwmode(fontdesc->encoding)); if (kind == TRUETYPE) { fz_obj *cidtogidmap; cidtogidmap = fz_dictgets(dict, "CIDToGIDMap"); if (fz_isindirect(cidtogidmap)) { fz_buffer *buf; pdf_logfont("cidtogidmap stream\n"); error = pdf_loadstream(&buf, xref, fz_tonum(cidtogidmap), fz_togen(cidtogidmap)); if (error) goto cleanup; fontdesc->ncidtogid = (buf->len) / 2; fontdesc->cidtogid = fz_calloc(fontdesc->ncidtogid, sizeof(unsigned short)); for (i = 0; i < fontdesc->ncidtogid; i++) fontdesc->cidtogid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1]; fz_dropbuffer(buf); } /* 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 (fontdesc->font->ftsubstitute) { pdf_logfont("emulate ttf cidfont\n"); fterr = FT_Select_Charmap(face, ft_encoding_unicode); if (fterr) { error = fz_throw("fonterror: no unicode cmap when emulating CID font: %s", ft_errorstring(fterr)); goto cleanup; } if (!strcmp(collection, "Adobe-CNS1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Japan2-UCS2"); else if (!strcmp(collection, "Adobe-Korea1")) error = pdf_loadsystemcmap(&fontdesc->tottfcmap, "Adobe-Korea1-UCS2"); else error = fz_okay; if (error) { error = fz_rethrow(error, "cannot load system cmap %s", collection); goto cleanup; } } } error = pdf_loadtounicode(fontdesc, xref, nil, collection, tounicode); if (error) fz_catch(error, "cannot load tounicode"); /* Horizontal */ dw = 1000; obj = fz_dictgets(dict, "DW"); if (obj) dw = fz_toint(obj); pdf_setdefaulthmtx(fontdesc, dw); widths = fz_dictgets(dict, "W"); if (widths) { int c0, c1, w; for (i = 0; i < fz_arraylen(widths); ) { c0 = fz_toint(fz_arrayget(widths, i)); obj = fz_arrayget(widths, i + 1); if (fz_isarray(obj)) { for (k = 0; k < fz_arraylen(obj); k++) { w = fz_toint(fz_arrayget(obj, k)); pdf_addhmtx(fontdesc, c0 + k, c0 + k, w); } i += 2; } else { c1 = fz_toint(obj); w = fz_toint(fz_arrayget(widths, i + 2)); pdf_addhmtx(fontdesc, c0, c1, w); i += 3; } } } pdf_endhmtx(fontdesc); /* Vertical */ if (pdf_getwmode(fontdesc->encoding) == 1) { int dw2y = 880; int dw2w = -1000; obj = fz_dictgets(dict, "DW2"); if (obj) { dw2y = fz_toint(fz_arrayget(obj, 0)); dw2w = fz_toint(fz_arrayget(obj, 1)); } pdf_setdefaultvmtx(fontdesc, dw2y, dw2w); widths = fz_dictgets(dict, "W2"); if (widths) { int c0, c1, w, x, y; for (i = 0; i < fz_arraylen(widths); ) { c0 = fz_toint(fz_arrayget(widths, i)); obj = fz_arrayget(widths, i + 1); if (fz_isarray(obj)) { for (k = 0; k * 3 < fz_arraylen(obj); k ++) { w = fz_toint(fz_arrayget(obj, k * 3 + 0)); x = fz_toint(fz_arrayget(obj, k * 3 + 1)); y = fz_toint(fz_arrayget(obj, k * 3 + 2)); pdf_addvmtx(fontdesc, c0 + k, c0 + k, x, y, w); } i += 2; } else { c1 = fz_toint(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)); pdf_addvmtx(fontdesc, c0, c1, x, y, w); i += 5; } } } pdf_endvmtx(fontdesc); } pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: pdf_dropfont(fontdesc); return fz_rethrow(error, "cannot load cid font (%d %d R)", fz_tonum(dict), fz_togen(dict)); }