void Print_Type( FT_Face face ) { FT_Module module; printf( "font type entries\n" ); module = &face->driver->root; printf( " FreeType driver: %s\n", module->clazz->module_name ); /* Is it better to dump all sfnt tag names? */ printf( " sfnt wrapped: %s\n", FT_IS_SFNT( face ) ? (char *)"yes" : (char *)"no" ); /* isScalable? */ comma_flag = 0; printf( " type: " ); if ( FT_IS_SCALABLE( face ) ) { Print_Comma( "scalable" ); if ( FT_HAS_MULTIPLE_MASTERS( face ) ) Print_Comma( "multiple masters" ); } if ( FT_HAS_FIXED_SIZES( face ) ) Print_Comma( "fixed size" ); printf( "\n" ); /* Direction */ comma_flag = 0; printf( " direction: " ); if ( FT_HAS_HORIZONTAL( face ) ) Print_Comma( "horizontal" ); if ( FT_HAS_VERTICAL( face ) ) Print_Comma( "vertical" ); printf( "\n" ); printf( " fixed width: %s\n", FT_IS_FIXED_WIDTH( face ) ? (char *)"yes" : (char *)"no" ); printf( " glyph names: %s\n", FT_HAS_GLYPH_NAMES( face ) ? (char *)"yes" : (char *)"no" ); if ( FT_IS_SCALABLE( face ) ) { printf( " EM size: %d\n", face->units_per_EM ); printf( " global BBox: (%ld,%ld):(%ld,%ld)\n", face->bbox.xMin, face->bbox.yMin, face->bbox.xMax, face->bbox.yMax ); printf( " ascent: %d\n", face->ascender ); printf( " descent: %d\n", face->descender ); printf( " text height: %d\n", face->height ); } }
Py::Object FT2Font::get_glyph_name(const Py::Tuple & args) { _VERBOSE("FT2Font::get_glyph_name"); args.verify_length(1); if (!FT_HAS_GLYPH_NAMES(face)) throw Py::RuntimeError("Face has no glyph names"); char buffer[128]; if (FT_Get_Glyph_Name(face, (FT_UInt) Py::Int(args[0]), buffer, 128)) Py::RuntimeError("Could not get glyph names."); return Py::String(buffer); }
const char* XeTeXFontInst::getGlyphName(GlyphID gid, int& nameLen) { if (FT_HAS_GLYPH_NAMES(m_ftFace)) { static char buffer[256]; FT_Get_Glyph_Name(m_ftFace, gid, buffer, 256); nameLen = strlen(buffer); return &buffer[0]; } else { nameLen = 0; return NULL; } }
const char* XeTeXFontInst_FT2::getGlyphName(LEGlyphID gid, int& nameLen) { if (!fFreeTypeOnly) return XeTeXFontInst::getGlyphName(gid, nameLen); else if (FT_HAS_GLYPH_NAMES(face)) { static char buffer[256]; FT_Get_Glyph_Name(face, gid, buffer, 256); nameLen = strlen(buffer); return &buffer[0]; } else { nameLen = 0; return NULL; } }
static pdf_font_desc * pdf_load_simple_font(pdf_document *xref, pdf_obj *dict) { pdf_obj *descriptor; pdf_obj *encoding; pdf_obj *widths; unsigned short *etable = NULL; pdf_font_desc *fontdesc = NULL; char *subtype; FT_Face face; FT_CharMap cmap; int symbolic; int kind; char *basefont; char *estrings[256]; char ebuffer[256][32]; int i, k, n; int fterr; fz_context *ctx = xref->ctx; fz_var(fontdesc); fz_var(etable); basefont = pdf_to_name(pdf_dict_gets(dict, "BaseFont")); /* Load font file */ fz_try(ctx) { fontdesc = pdf_new_font_desc(ctx); descriptor = pdf_dict_gets(dict, "FontDescriptor"); if (descriptor) pdf_load_font_descriptor(fontdesc, xref, descriptor, NULL, basefont); else pdf_load_builtin_font(ctx, fontdesc, basefont); /* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */ if (descriptor && pdf_is_string(pdf_dict_gets(descriptor, "FontName")) && !pdf_dict_gets(dict, "ToUnicode") && !strcmp(pdf_to_name(pdf_dict_gets(dict, "Encoding")), "WinAnsiEncoding") && pdf_to_int(pdf_dict_gets(descriptor, "Flags")) == 4) { char *cp936fonts[] = { "\xCB\xCE\xCC\xE5", "SimSun,Regular", "\xBA\xDA\xCC\xE5", "SimHei,Regular", "\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular", "\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular", "\xC1\xA5\xCA\xE9", "SimLi,Regular", NULL }; for (i = 0; cp936fonts[i]; i += 2) if (!strcmp(basefont, cp936fonts[i])) break; if (cp936fonts[i]) { fz_warn(ctx, "workaround for S22PDF lying about chinese font encodings"); pdf_drop_font(ctx, fontdesc); fontdesc = pdf_new_font_desc(ctx); pdf_load_font_descriptor(fontdesc, xref, descriptor, "Adobe-GB1", cp936fonts[i+1]); fontdesc->encoding = pdf_load_system_cmap(ctx, "GBK-EUC-H"); fontdesc->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); face = fontdesc->font->ft_face; kind = ft_kind(face); goto skip_encoding; } } face = fontdesc->font->ft_face; kind = ft_kind(face); /* Encoding */ symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; else cmap = NULL; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap test = face->charmaps[i]; if (kind == TYPE1) { if (test->platform_id == 7) cmap = test; } if (kind == TRUETYPE) { if (test->platform_id == 1 && test->encoding_id == 0) cmap = test; if (test->platform_id == 3 && test->encoding_id == 1) cmap = test; if (symbolic && test->platform_id == 3 && test->encoding_id == 0) cmap = test; } } if (cmap) { fterr = FT_Set_Charmap(face, cmap); if (fterr) fz_warn(ctx, "freetype could not set cmap: %s", ft_error_string(fterr)); } else fz_warn(ctx, "freetype could not find any cmaps"); etable = fz_malloc_array(ctx, 256, sizeof(unsigned short)); fontdesc->size += 256 * sizeof(unsigned short); for (i = 0; i < 256; i++) { estrings[i] = NULL; etable[i] = 0; } encoding = pdf_dict_gets(dict, "Encoding"); if (encoding) { if (pdf_is_name(encoding)) pdf_load_encoding(estrings, pdf_to_name(encoding)); if (pdf_is_dict(encoding)) { pdf_obj *base, *diff, *item; base = pdf_dict_gets(encoding, "BaseEncoding"); if (pdf_is_name(base)) pdf_load_encoding(estrings, pdf_to_name(base)); else if (!fontdesc->is_embedded && !symbolic) pdf_load_encoding(estrings, "StandardEncoding"); diff = pdf_dict_gets(encoding, "Differences"); if (pdf_is_array(diff)) { n = pdf_array_len(diff); k = 0; for (i = 0; i < n; i++) { item = pdf_array_get(diff, i); if (pdf_is_int(item)) k = pdf_to_int(item); if (pdf_is_name(item) && k >= 0 && k < nelem(estrings)) estrings[k++] = pdf_to_name(item); } } } } /* start with the builtin encoding */ for (i = 0; i < 256; i++) etable[i] = ft_char_index(face, i); fz_lock(ctx, FZ_LOCK_FREETYPE); /* built-in and substitute fonts may be a different type than what the document expects */ subtype = pdf_to_name(pdf_dict_gets(dict, "Subtype")); if (!strcmp(subtype, "Type1")) kind = TYPE1; else if (!strcmp(subtype, "MMType1")) kind = TYPE1; else if (!strcmp(subtype, "TrueType")) kind = TRUETYPE; else if (!strcmp(subtype, "CIDFontType0")) kind = TYPE1; else if (!strcmp(subtype, "CIDFontType2")) kind = TRUETYPE; /* encode by glyph name where we can */ if (kind == TYPE1) { for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) { int aglcode = pdf_lookup_agl(estrings[i]); const char **dupnames = pdf_lookup_agl_duplicates(aglcode); while (*dupnames) { etable[i] = FT_Get_Name_Index(face, (char*)*dupnames); if (etable[i]) break; dupnames++; } } } } } /* encode by glyph name where we can */ if (kind == TRUETYPE) { /* Unicode cmap */ if (!symbolic && face->charmap && face->charmap->platform_id == 3) { for (i = 0; i < 256; i++) { if (estrings[i]) { int aglcode = pdf_lookup_agl(estrings[i]); if (!aglcode) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ft_char_index(face, aglcode); } } } /* MacRoman cmap */ else if (!symbolic && face->charmap && face->charmap->platform_id == 1) { for (i = 0; i < 256; i++) { if (estrings[i]) { k = lookup_mre_code(estrings[i]); if (k <= 0) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ft_char_index(face, k); } } } /* Symbolic cmap */ else if (!face->charmap || face->charmap->encoding != FT_ENCODING_MS_SYMBOL) { for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) etable[i] = ft_char_index(face, i); } } } } /* try to reverse the glyph names from the builtin encoding */ for (i = 0; i < 256; i++) { if (etable[i] && !estrings[i]) { if (FT_HAS_GLYPH_NAMES(face)) { fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) fz_warn(ctx, "freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr)); if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } else { estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */ } } } /* symbolic Type 1 fonts with an implicit encoding and non-standard glyph names */ if (kind == TYPE1 && symbolic) { for (i = 0; i < 256; i++) if (etable[i] && estrings[i] && !pdf_lookup_agl(estrings[i])) estrings[i] = (char*) pdf_standard[i]; } fz_unlock(ctx, FZ_LOCK_FREETYPE); fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1); fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding); fontdesc->cid_to_gid_len = 256; fontdesc->cid_to_gid = etable; fz_try(ctx) { pdf_load_to_unicode(xref, fontdesc, estrings, NULL, pdf_dict_gets(dict, "ToUnicode")); } fz_catch(ctx) { fz_warn(ctx, "cannot load ToUnicode CMap"); } skip_encoding: /* Widths */ pdf_set_default_hmtx(ctx, fontdesc, fontdesc->missing_width); widths = pdf_dict_gets(dict, "Widths"); if (widths) { int first, last; first = pdf_to_int(pdf_dict_gets(dict, "FirstChar")); last = pdf_to_int(pdf_dict_gets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = pdf_to_int(pdf_array_get(widths, i)); pdf_add_hmtx(ctx, fontdesc, i + first, i + first, wid); } } else { fz_lock(ctx, FZ_LOCK_FREETYPE); fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) fz_warn(ctx, "freetype set character size: %s", ft_error_string(fterr)); for (i = 0; i < 256; i++) { pdf_add_hmtx(ctx, fontdesc, i, i, ft_width(ctx, fontdesc, i)); } fz_unlock(ctx, FZ_LOCK_FREETYPE); } pdf_end_hmtx(ctx, fontdesc); } fz_catch(ctx) { if (fontdesc && etable != fontdesc->cid_to_gid) fz_free(ctx, etable); pdf_drop_font(ctx, fontdesc); fz_throw(ctx, "cannot load simple font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict)); } return fontdesc; }
static fz_error loadsimplefont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict) { fz_error error; fz_obj *descriptor; fz_obj *encoding; fz_obj *widths; unsigned short *etable = nil; pdf_fontdesc *fontdesc; fz_bbox bbox; FT_Face face; FT_CharMap cmap; int kind; int symbolic; char *basefont; char *fontname; char *estrings[256]; char ebuffer[256][32]; int i, k, n; int fterr; basefont = fz_toname(fz_dictgets(dict, "BaseFont")); fontname = cleanfontname(basefont); /* Load font file */ fontdesc = pdf_newfontdesc(); pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), fontdesc); pdf_logfont("basefont %s -> %s\n", basefont, fontname); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor) error = pdf_loadfontdescriptor(fontdesc, xref, descriptor, nil, basefont); else error = pdf_loadbuiltinfont(fontdesc, fontname); if (error) goto cleanup; face = fontdesc->font->ftface; kind = ftkind(face); pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name); 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); /* Encoding */ symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; else cmap = nil; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap test = face->charmaps[i]; if (kind == TYPE1) { if (test->platform_id == 7) cmap = test; } if (kind == TRUETYPE) { if (test->platform_id == 1 && test->encoding_id == 0) cmap = test; if (test->platform_id == 3 && test->encoding_id == 1) cmap = test; } } if (cmap) { fterr = FT_Set_Charmap(face, cmap); if (fterr) fz_warn("freetype could not set cmap: %s", ft_errorstring(fterr)); } else fz_warn("freetype could not find any cmaps"); etable = fz_malloc(sizeof(unsigned short) * 256); for (i = 0; i < 256; i++) { estrings[i] = nil; etable[i] = 0; } encoding = fz_dictgets(dict, "Encoding"); if (encoding) { if (fz_isname(encoding)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); else if (!fontdesc->isembedded && !symbolic) pdf_loadencoding(estrings, "StandardEncoding"); /* cf. http://bugs.ghostscript.com/show_bug.cgi?id=690615 and http://code.google.com/p/sumatrapdf/issues/detail?id=687 */ /* try to extract an encoding from the font or synthesize a likely one */ /* note: FT_Get_Name_Index fails for symbolic CFF fonts, so let them be encoded by index */ else if (!fontdesc->encoding && !ftloadt1encoding(face, estrings) && !(symbolic && !strcmp(FT_Get_X11_Font_Format(face), "CFF"))) pdf_loadencoding(estrings, "StandardEncoding"); 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; } } } } /* start with the builtin encoding */ for (i = 0; i < 256; i++) etable[i] = ftcharindex(face, i); /* encode by glyph name where we can */ if (kind == TYPE1) { pdf_logfont("encode type1/cff by strings\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) { int aglcode = pdf_lookupagl(estrings[i]); char **aglnames = pdf_lookupaglnames(aglcode); while (*aglnames) { etable[i] = FT_Get_Name_Index(face, *aglnames); if (etable[i]) break; aglnames++; } } } } } /* encode by glyph name where we can */ if (kind == TRUETYPE) { /* Unicode cmap */ if (!symbolic && face->charmap && face->charmap->platform_id == 3) { pdf_logfont("encode truetype via unicode\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { int aglcode = pdf_lookupagl(estrings[i]); if (!aglcode) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, aglcode); } } } /* MacRoman cmap */ else if (!symbolic && face->charmap && face->charmap->platform_id == 1) { pdf_logfont("encode truetype via macroman\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { k = mrecode(estrings[i]); if (k <= 0) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, k); } } } /* Symbolic cmap */ else { pdf_logfont("encode truetype symbolic\n"); for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) etable[i] = ftcharindex(face, i); } } } } /* try to reverse the glyph names from the builtin encoding */ for (i = 0; i < 256; i++) { if (etable[i] && !estrings[i]) { if (FT_HAS_GLYPH_NAMES(face)) { fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) fz_warn("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr)); if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } else { estrings[i] = (char*) pdf_winansi[i]; /* discard const */ } } } /* Prevent encoding Differences from being overwritten by reloading them */ /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=115 */ if (fz_isdict(encoding)) { fz_obj *diff, *item; 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; } } } fontdesc->encoding = pdf_newidentitycmap(0, 1); fontdesc->ncidtogid = 256; fontdesc->cidtogid = etable; error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* Widths */ pdf_setdefaulthmtx(fontdesc, fontdesc->missingwidth); widths = fz_dictgets(dict, "Widths"); if (widths) { int first, last; first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = fz_toint(fz_arrayget(widths, i)); pdf_addhmtx(fontdesc, i + first, i + first, wid); } } else { fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) fz_warn("freetype set character size: %s", ft_errorstring(fterr)); for (i = 0; i < 256; i++) { pdf_addhmtx(fontdesc, i, i, ftwidth(fontdesc, i)); } } pdf_endhmtx(fontdesc); pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: if (etable != fontdesc->cidtogid) fz_free(etable); pdf_dropfont(fontdesc); return fz_rethrow(error, "cannot load simple font (%d %d R)", fz_tonum(dict), fz_togen(dict)); }
void FTopen (char *filename, Font *fnt, Boolean do_tfm, Boolean quiet) { FT_Error error; int i; unsigned short num_cmap, cmap_plat=0, cmap_enc=0; if ((error = FT_Init_FreeType(&engine))) oops("Cannot initialize FreeType engine (error code = 0x%x).", error); /* * Load face. */ if ((error = FT_New_Face(engine, filename, 0, &face))) oops("Cannot open `%s'.", filename); if (face->num_faces == 1) { if (fnt->fontindex != 0) { warning("This isn't a TrueType collection.\n" "Parameter `%s' is ignored.", do_tfm ? "-f" : "Fontindex"); fnt->fontindex = 0; } fnt->fontindexparam = NULL; } else { if (fnt->fontindex != 0) { /* * Now we try to open the proper font in a collection. */ FT_Done_Face(face); if ((error = FT_New_Face(engine, filename, (FT_Long)fnt->fontindex, &face))) oops("Cannot open font %lu in TrueType Collection `%s'.", fnt->fontindex, filename); } } if (do_tfm) { /* * Get the OS/2 table. */ if ((os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2)) == NULL) oops("Cannot find OS/2 table for `%s'.", filename); /* * Get the Postscript table. */ if ((postscript = FT_Get_Sfnt_Table(face, ft_sfnt_post)) == NULL) oops("Cannot find Postscript table for `%s'.", filename); } if ((error = FT_Set_Char_Size(face, ptsize * 64, ptsize * 64, dpi, dpi))) oops("Cannot set character size (error code = 0x%x).", error); matrix1.xx = (FT_Fixed)(floor(fnt->efactor * 1024) * (1<<16)/1024); matrix1.xy = (FT_Fixed)(floor(fnt->slant * 1024) * (1<<16)/1024); matrix1.yx = (FT_Fixed)0; matrix1.yy = (FT_Fixed)(1<<16); if (fnt->rotate) { matrix2.xx = 0; matrix2.yx = 1L << 16; matrix2.xy = -matrix2.yx; matrix2.yy = matrix2.xx; } if (do_tfm) { fnt->units_per_em = face->units_per_EM; fnt->fixedpitch = postscript->isFixedPitch; fnt->italicangle = postscript->italicAngle / 65536.0; fnt->xheight = os2->sxHeight * 1000 / fnt->units_per_em; } if (fnt->PSnames != Only) { num_cmap = face->num_charmaps; for (i = 0; i < num_cmap; i++) { cmap_plat=face->charmaps[i]->platform_id; cmap_enc=face->charmaps[i]->encoding_id; if (cmap_plat == fnt->pid && cmap_enc == fnt->eid) break; } if (i == num_cmap) { fprintf(stderr, "%s: ERROR: Invalid platform and/or encoding ID.\n", progname); if (num_cmap == 1) fprintf(stderr, " The only valid PID/EID pair is"); else fprintf(stderr, " Valid PID/EID pairs are:\n"); for (i = 0; i < num_cmap; i++) { cmap_plat=face->charmaps[i]->platform_id; cmap_enc=face->charmaps[i]->encoding_id; fprintf(stderr, " (%i,%i)\n", cmap_plat, cmap_enc); } fprintf(stderr, "\n"); exit(1); } if ((error = FT_Set_Charmap(face, face->charmaps[i]))) oops("Cannot load cmap (error code = 0x%x).", error); } if (fnt->PSnames) { if (!FT_HAS_GLYPH_NAMES(face)) oops("This font does not support PS names."); } else if (cmap_plat == Microsoft_platform && cmap_enc == Microsoft_Unicode_encoding) set_encoding_scheme(encUnicode, fnt); else if (cmap_plat == Macintosh_platform && cmap_enc == Macintosh_encoding) set_encoding_scheme(encMac, fnt); else set_encoding_scheme(encFontSpecific, fnt); if (fnt->rotate) fetch_GSUB(); }
static fz_error loadsimplefont(pdf_fontdesc **fontdescp, pdf_xref *xref, fz_obj *dict) { fz_error error; fz_obj *descriptor = nil; fz_obj *encoding = nil; fz_obj *widths = nil; unsigned short *etable = nil; pdf_fontdesc *fontdesc; fz_irect bbox; FT_Face face; FT_CharMap cmap; int kind; int symbolic; char *basefont; char *fontname; char *estrings[256]; char ebuffer[256][32]; int i, k, n; int fterr; basefont = fz_toname(fz_dictgets(dict, "BaseFont")); fontname = cleanfontname(basefont); /* * Load font file */ fontdesc = pdf_newfontdesc(); if (!fontdesc) return fz_rethrow(-1, "out of memory"); pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), 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(fontdesc, xref, descriptor, nil); else error = pdf_loadbuiltinfont(fontdesc, fontname); if (error) goto cleanup; face = fontdesc->font->ftface; kind = ftkind(face); pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name); 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); /* * Encoding */ symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; else cmap = nil; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap test = face->charmaps[i]; if (kind == TYPE1) { if (test->platform_id == 7) cmap = test; } if (kind == TRUETYPE) { if (test->platform_id == 1 && test->encoding_id == 0) cmap = test; if (test->platform_id == 3 && test->encoding_id == 1) cmap = test; } } if (cmap) { fterr = FT_Set_Charmap(face, cmap); if (fterr) fz_warn("freetype could not set cmap: %s", ft_errorstring(fterr)); } else fz_warn("freetype could not find any cmaps"); etable = fz_malloc(sizeof(unsigned short) * 256); if (!etable) goto cleanup; for (i = 0; i < 256; i++) { estrings[i] = nil; etable[i] = 0; } encoding = fz_dictgets(dict, "Encoding"); if (encoding && !(kind == TRUETYPE && symbolic)) { if (fz_isname(encoding)) pdf_loadencoding(estrings, fz_toname(encoding)); if (fz_isdict(encoding)) { fz_obj *base, *diff, *item; base = fz_dictgets(encoding, "BaseEncoding"); if (fz_isname(base)) pdf_loadencoding(estrings, fz_toname(base)); else if (!fontdesc->isembedded) pdf_loadencoding(estrings, "StandardEncoding"); 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; } } } if (kind == TYPE1) { pdf_logfont("encode type1/cff by strings\n"); for (i = 0; i < 256; i++) if (estrings[i]) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, i); } if (kind == TRUETYPE) { /* Unicode cmap */ if (face->charmap && face->charmap->platform_id == 3) { pdf_logfont("encode truetype via unicode\n"); for (i = 0; i < 256; i++) if (estrings[i]) { int aglbuf[256]; int aglnum; aglnum = pdf_lookupagl(estrings[i], aglbuf, nelem(aglbuf)); if (aglnum != 1) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, aglbuf[0]); } else etable[i] = ftcharindex(face, i); } /* MacRoman cmap */ else if (face->charmap && face->charmap->platform_id == 1) { pdf_logfont("encode truetype via macroman\n"); for (i = 0; i < 256; i++) if (estrings[i]) { k = mrecode(estrings[i]); if (k <= 0) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ftcharindex(face, k); } else etable[i] = ftcharindex(face, i); } /* Symbolic cmap */ else { pdf_logfont("encode truetype symbolic\n"); for (i = 0; i < 256; i++) { etable[i] = ftcharindex(face, i); fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) { error = fz_throw("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr)); goto cleanup; } if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } } } } else { pdf_logfont("encode builtin\n"); for (i = 0; i < 256; i++) { etable[i] = ftcharindex(face, i); if (etable[i] == 0) continue; if (FT_HAS_GLYPH_NAMES(face)) { fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) { error = fz_throw("freetype get glyph name (gid %d): %s", etable[i], ft_errorstring(fterr)); goto cleanup; } if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } } } error = pdf_newidentitycmap(&fontdesc->encoding, 0, 1); if (error) goto cleanup; fontdesc->ncidtogid = 256; fontdesc->cidtogid = etable; error = pdf_loadtounicode(fontdesc, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* * Widths */ pdf_setdefaulthmtx(fontdesc, fontdesc->missingwidth); widths = fz_dictgets(dict, "Widths"); if (widths) { int first, last; first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = fz_toint(fz_arrayget(widths, i)); error = pdf_addhmtx(fontdesc, i + first, i + first, wid); if (error) goto cleanup; } } else { fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) fz_warn("freetype set character size: %s", ft_errorstring(fterr)); for (i = 0; i < 256; i++) { error = pdf_addhmtx(fontdesc, i, i, ftwidth(fontdesc, i)); if (error) goto cleanup; } } error = pdf_endhmtx(fontdesc); if (error) goto cleanup; pdf_logfont("}\n"); *fontdescp = fontdesc; return fz_okay; cleanup: fz_free(etable); fz_dropfont(fontdesc->font); fz_free(fontdesc); return fz_rethrow(error, "cannot load simple font"); }
static int glnames( GLYPH *glyph_list ) { #define MAX_NAMELEN 1024 #ifdef XP_PSTEXT char buf[1024]; long i; FT_Error error; #ifdef XP_ONLY_BLOCKS extern unsigned long xp_font_block_offset; extern FTFontPtr xp_xtf; int bc; /* block counter */ /* FixMe: This code should use PsOut_Get_FreeType_Glyph_Name() instead of * duplicating the code */ for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) { /* Remap X11 font index to FreeType font index */ i = FTRemap(face, &xp_xtf->mapping, bc); if( i >= face->num_glyphs ) continue; #else for(i=0; i < face->num_glyphs; i++) { #endif /* XP_ONLY_BLOCKS */ if( FT_Has_PS_Glyph_Names(face) ) { error = FT_Get_Glyph_Name(face, i, buf, MAX_NAMELEN); } else { error = -1; } if( error ) { /* Check for unicode mapping * See Adobe document "Unicode and Glyph Names" * (http://partners.adobe.com/asn/tech/type/unicodegn.jsp) */ if( (xp_xtf->mapping.mapping->type == FONT_ENCODING_UNICODE) && (i < 0xFFFE) ) { sprintf(buf, "uni%04lx", i); } else { sprintf(buf, "ch%02lx", i); } } glyph_list[i].name = strdup(buf); if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, buf); if (glyph_list[i].name == NULL) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } } return 0; #else char bf[1024]; long i; if( ! FT_HAS_GLYPH_NAMES(face) ) { WARNING_1 fprintf(stderr, "Font has no glyph names\n"); return 1; } for(i=0; i < face->num_glyphs; i++) { if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) { sprintf(bf, "_g_%d", i); WARNING_2 fprintf(stderr, "Glyph No. %d has no postscript name, becomes %s\n", i, bf); } glyph_list[i].name = strdup(bf); if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf); if (glyph_list[i].name == NULL) { fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); exit(255); } } return 0; #endif /* XP_PSTEXT */ } /* * Get the metrics of the glyphs. */ static void glmetrics( GLYPH *glyph_list ) { GLYPH *g; int i; FT_Glyph_Metrics *met; FT_BBox bbox; FT_Glyph gly; #ifdef XP_ONLY_BLOCKS extern unsigned long xp_font_block_offset; extern FTFontPtr xp_xtf; int bc; /* block counter */ for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) { /* Remap X11 font index to FreeType font index */ i = FTRemap(face, &xp_xtf->mapping, bc); if( i >= face->num_glyphs ) continue; #else for(i=0; i < face->num_glyphs; i++) { #endif /* XP_ONLY_BLOCKS */ g = &(glyph_list[i]); if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) { fprintf(stderr, "Can't load glyph %s, skipped\n", g->name); continue; } met = &face->glyph->metrics; if(FT_HAS_HORIZONTAL(face)) { g->width = met->horiAdvance; g->lsb = met->horiBearingX; } else { WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name); g->width = met->width; g->lsb = 0; } if( FT_Get_Glyph(face->glyph, &gly) ) { fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name); continue; } FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox); g->xMin = bbox.xMin; g->yMin = bbox.yMin; g->xMax = bbox.xMax; g->yMax = bbox.yMax; g->ttf_pathlen = face->glyph->outline.n_points; } } /* * Get the original encoding of the font. * Returns 1 for if the original encoding is Unicode, 2 if the * original encoding is other 16-bit, 0 if 8-bit. */ static int glenc( GLYPH *glyph_list, int *encoding, int *unimap ) { #ifdef XP_PSTEXT int i, e; unsigned code; extern FTFontPtr xp_xtf; extern unsigned long xp_font_block_offset; enc_found = 1; enc_type = 0; for(i=0; i<ENCTABSZ; i++) { if(encoding[i] != -1) continue; /* Remap X11 font index to FreeType font index */ code = FTRemap(face, &xp_xtf->mapping, xp_font_block_offset+i); if(code == 0) continue; /* .notdef */ encoding[i] = code; } return enc_type; #else int i, e; unsigned code; if(ISDBG(FT)) for(e=0; e < face->num_charmaps; e++) { fprintf(stderr, "found encoding pid=%d eid=%d\n", face->charmaps[e]->platform_id, face->charmaps[e]->encoding_id); } if(enc_found) goto populate_map; enc_type = 0; /* first check for an explicit PID/EID */ if(force_pid != -1) { for(e=0; e < face->num_charmaps; e++) { if(face->charmaps[e]->platform_id == force_pid && face->charmaps[e]->encoding_id == force_eid) { WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", force_pid, force_eid); if( FT_Set_Charmap(face, face->charmaps[e]) ) { fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); exit(1); } enc_type = 1; goto populate_map; } } fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", force_pid, force_eid); exit(1); } /* next check for a direct Adobe mapping */ if(!forcemap) { for(e=0; e < face->num_charmaps; e++) { if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) { WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr); if( FT_Set_Charmap(face, face->charmaps[e]) ) { fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); exit(1); } goto populate_map; } } } for(e=0; e < face->num_charmaps; e++) { if(face->charmaps[e]->platform_id == 3) { switch(face->charmaps[e]->encoding_id) { case 0: WARNING_1 fputs("Found Symbol Encoding\n", stderr); break; case 1: WARNING_1 fputs("Found Unicode Encoding\n", stderr); enc_type = 1; break; default: WARNING_1 { fprintf(stderr, "****MS Encoding ID %d not supported****\n", face->charmaps[e]->encoding_id); fputs("Treating it like Symbol encoding\n", stderr); } break; } break; } } if(e >= face->num_charmaps) { WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr); e = 0; } if( FT_Set_Charmap(face, face->charmaps[e]) ) { fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); exit(1); } populate_map: enc_found = 1; for(i=0; i<ENCTABSZ; i++) { if(encoding[i] != -1) continue; if(enc_type == 1 || forcemap) { code = unimap[i]; if(code == (unsigned) -1) continue; } else code = i; code = FT_Get_Char_Index(face, code); if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code); if(code == 0) continue; /* .notdef */ encoding[i] = code; } return enc_type; #endif /* XP_PSTEXT */ }
gfxfont_t* gfxfont_load(const char*id, const char*filename, unsigned int flags, double quality) { FT_Face face; FT_Error error; const char* fontname = 0; FT_ULong charcode; FT_UInt gindex; gfxfont_t* font; int t; int*glyph2glyph = 0; int*glyph2unicode = 0; int max_unicode = 0; int charmap = -1; int isunicode = 1; int has_had_errors = 0; int num_names = 0; if(ftlibrary == 0) { if(FT_Init_FreeType(&ftlibrary)) { fprintf(stderr, "Couldn't init freetype library!\n"); exit(1); } } error = FT_New_Face(ftlibrary, filename, 0, &face); FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale); #ifdef DEBUG printf("gfxfont_load(%s, %s, %f)\n", id, filename, quality); #endif if(error) { fprintf(stderr, "Couldn't load file %s- not a TTF file? (error=%02x)\n", filename, error); return 0; } if(face->num_glyphs <= 0) { fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs); return 0; } font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t)); //font->style = ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0); //font->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin; //font->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax; //font->leading = font->layout->ascent + font->layout->descent; //font->encoding = FONT_ENCODING_UNICODE; font->max_unicode = 0; font->id = strdup(id); font->glyphs = (gfxglyph_t*)rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t)); glyph2unicode = (int*)rfx_calloc(face->num_glyphs*sizeof(int)); glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int)); if(FT_HAS_GLYPH_NAMES(face)) { //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*)); } fontname = FT_Get_Postscript_Name(face); #ifdef DEBUG for(t=0;t<face->num_charmaps;t++) { printf("possible encoding: %c%c%c%c (%d of %d)\n", (face->charmaps[t]->encoding >> 24)&255, (face->charmaps[t]->encoding >> 16)&255, (face->charmaps[t]->encoding >> 8)&255, (face->charmaps[t]->encoding >> 0)&255, t+1, face->num_charmaps ); } #endif while(1) { charcode = FT_Get_First_Char(face, &gindex); while(gindex != 0) { if(gindex >= 0 && gindex<face->num_glyphs) { if(!glyph2unicode[gindex]) { glyph2unicode[gindex] = charcode; if(charcode + 1 > font->max_unicode) { font->max_unicode = charcode + 1; } } } charcode = FT_Get_Next_Char(face, charcode, &gindex); } #ifdef DEBUG if(face->charmap) { printf("ENCODING: %c%c%c%c (%d of %d) max_unicode=%d\n", (face->charmap->encoding >> 24)&255, (face->charmap->encoding >> 16)&255, (face->charmap->encoding >> 8)&255, (face->charmap->encoding >> 0)&255, charmap, face->num_charmaps, font->max_unicode ); } else {
SWFFONT* swf_LoadTrueTypeFont(const char*filename, char flashtype) { FT_Face face; FT_Error error; const char* name = 0; FT_ULong charcode; FT_UInt gindex; SWFFONT* font; int t; int*glyph2glyph; int max_unicode = 0; int charmap = -1; if(ftlibrary == 0) { if(FT_Init_FreeType(&ftlibrary)) { fprintf(stderr, "Couldn't init freetype library!\n"); exit(1); } } error = FT_New_Face(ftlibrary, filename, 0, &face); if(error || !face) { fprintf(stderr, "Couldn't load file %s- not a TTF file?\n", filename); return 0; } int scale = flashtype?20:1; FT_Set_Pixel_Sizes (face, 16*loadfont_scale*scale, 16*loadfont_scale*scale); if(face->num_glyphs <= 0) { fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs); return 0; } font = (SWFFONT*)rfx_calloc(sizeof(SWFFONT)); font->id = -1; font->version = flashtype?3:2; font->layout = (SWFLAYOUT*)rfx_calloc(sizeof(SWFLAYOUT)); font->layout->bounds = (SRECT*)rfx_calloc(face->num_glyphs*sizeof(SRECT)); font->style = ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0); font->encoding = FONT_ENCODING_UNICODE; font->glyph2ascii = (U16*)rfx_calloc(face->num_glyphs*sizeof(U16)); font->maxascii = 0; font->glyph = (SWFGLYPH*)rfx_calloc(face->num_glyphs*sizeof(SWFGLYPH)); if(FT_HAS_GLYPH_NAMES(face)) { font->glyphnames = (char**)rfx_calloc(face->num_glyphs*sizeof(char*)); } font->layout->kerningcount = 0; name = face->family_name; if(!(name && *name)) name = FT_Get_Postscript_Name(face); if(name && *name) font->name = (U8*)strdup(name); while(1) { /* // Map Glyphs to Unicode, version 1 (quick and dirty): int t; for(t=0;t<65536;t++) { int index = FT_Get_Char_Index(face, t); if(index>=0 && index<face->num_glyphs) { if(font->glyph2ascii[index]<0) font->glyph2ascii[index] = t; } }*/ // Map Glyphs to Unicode, version 2 (much nicer): // (The third way would be the AGL algorithm, as proposed // by Werner Lemberg on [email protected]) charcode = FT_Get_First_Char(face, &gindex); while(gindex != 0) { if(gindex >= 0 && gindex<face->num_glyphs) { if(!font->glyph2ascii[gindex]) { font->glyph2ascii[gindex] = charcode; if(charcode + 1 > font->maxascii) { font->maxascii = charcode + 1; } } } charcode = FT_Get_Next_Char(face, charcode, &gindex); } /* if we didn't find a single encoding character, try the font's charmaps instead. That usually means that the encoding is no longer unicode. TODO: find a way to convert the encoding to unicode */ if(font->maxascii == 0 && charmap < face->num_charmaps - 1) { charmap++; FT_Set_Charmap(face, face->charmaps[charmap]); font->encoding = 0;//anything but unicode FIXME } else break; } if(full_unicode) font->maxascii = 65535; font->ascii2glyph = (int*)rfx_calloc(font->maxascii*sizeof(int)); for(t=0;t<font->maxascii;t++) { int g = FT_Get_Char_Index(face, t); if(!g || g>=face->num_glyphs) g = -1; font->ascii2glyph[t] = g; if(g>=0) { max_unicode = t+1; if(!font->glyph2ascii[g]) { font->glyph2ascii[g] = t; } } } font->maxascii = max_unicode; font->numchars = 0; glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int)); SRECT fontbbox = {0,0,0,0}; for(t=0; t < face->num_glyphs; t++) { FT_Glyph glyph; FT_BBox bbox; char name[128]; drawer_t draw; char hasname = 0; name[0]=0; if(FT_HAS_GLYPH_NAMES(face)) { error = FT_Get_Glyph_Name(face, t, name, 127); if(!error && name[0] && !strstr(name, "notdef")) { font->glyphnames[font->numchars] = strdup(name); hasname = 1; } } if(!font->glyph2ascii[t] && !hasname && skip_unused) { continue; } error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP); if(error) { //tends to happen with some pdfs fprintf(stderr, "Warning: Glyph %d has return code %d\n", t, error); glyph=0; if(skip_unused) continue; } else { error = FT_Get_Glyph(face->glyph, &glyph); if(error) { fprintf(stderr, "Couldn't get glyph %d, error:%d\n", t, error); glyph=0; if(skip_unused) continue; } } if(glyph) FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &bbox); else memset(&bbox, 0, sizeof(bbox)); bbox.yMin = -bbox.yMin; bbox.yMax = -bbox.yMax; if(bbox.xMax < bbox.xMin) { // swap bbox.xMax ^= bbox.xMin; bbox.xMin ^= bbox.xMax; bbox.xMax ^= bbox.xMin; } if(bbox.yMax < bbox.yMin) { // swap bbox.yMax ^= bbox.yMin; bbox.yMin ^= bbox.yMax; bbox.yMax ^= bbox.yMin; } swf_Shape01DrawerInit(&draw, 0); //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw); if(glyph) error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw); else error = 0; draw.finish(&draw); if(error) { fprintf(stderr, "Couldn't decompose glyph %d\n", t); draw.dealloc(&draw); continue; } #if 0 if(bbox.xMin > 0) { font->glyph[font->numchars].advance = (bbox.xMax*20*FT_SCALE)/FT_SUBPIXELS; } else { font->glyph[font->numchars].advance = ((bbox.xMax - bbox.xMin)*20*FT_SCALE)/FT_SUBPIXELS; } #else if(glyph) font->glyph[font->numchars].advance = glyph->advance.x*20/65536; else font->glyph[font->numchars].advance = 0; #endif SRECT b = swf_ShapeDrawerGetBBox(&draw); //font->layout->bounds[font->numchars].xmin = (bbox.xMin*FT_SCALE*20)/FT_SUBPIXELS; //font->layout->bounds[font->numchars].ymin = (bbox.yMin*FT_SCALE*20)/FT_SUBPIXELS; //font->layout->bounds[font->numchars].xmax = (bbox.xMax*FT_SCALE*20)/FT_SUBPIXELS; //font->layout->bounds[font->numchars].ymax = (bbox.yMax*FT_SCALE*20)/FT_SUBPIXELS; font->layout->bounds[font->numchars] = b; font->glyph[font->numchars].shape = swf_ShapeDrawerToShape(&draw); swf_ExpandRect2(&fontbbox, &font->layout->bounds[font->numchars]); draw.dealloc(&draw); if(glyph) FT_Done_Glyph(glyph); font->glyph2ascii[font->numchars] = font->glyph2ascii[t]; glyph2glyph[t] = font->numchars; font->numchars++; } //font->layout->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin; //font->layout->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax; //font->layout->leading = font->layout->ascent + font->layout->descent; if(-fontbbox.ymin < 0) font->layout->ascent = 0; else font->layout->ascent = -fontbbox.ymin; if(fontbbox.ymax < 0) font->layout->descent = 0; else font->layout->descent = fontbbox.ymax; int leading = fontbbox.ymax - fontbbox.ymin; font->layout->leading = leading>0x7fff?0x7fff:leading; /* notice: if skip_unused is true, font->glyph2ascii, font->glyphnames and font->layout->bounds will have more memory allocated than just font->numchars, but only the first font->numchars are used/valid */ for(t=0;t<font->maxascii;t++) { if(font->ascii2glyph[t]>=0) { font->ascii2glyph[t] = glyph2glyph[font->ascii2glyph[t]]; } } rfx_free(glyph2glyph); FT_Done_Face(face); FT_Done_FreeType(ftlibrary);ftlibrary=0; return font; }