PdfFont* PdfFontCache::GetFont( FT_Face face, bool bEmbedd, const PdfEncoding * const pEncoding ) { PdfFont* pFont; PdfFontMetrics* pMetrics; std::pair<TISortedFontList,TCISortedFontList> it; std::string sName = FT_Get_Postscript_Name( face ); if( sName.empty() ) { PdfError::LogMessage( eLogSeverity_Critical, "Could not retrieve fontname for font!\n" ); return NULL; } bool bBold = ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0); bool bItalic = ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0); it = std::equal_range( m_vecFonts.begin(), m_vecFonts.end(), TFontCacheElement( sName.c_str(), bBold, bItalic, pEncoding ) ); if( it.first == it.second ) { pMetrics = new PdfFontMetrics( &m_ftLibrary, face ); pFont = this->CreateFontObject( it.first, m_vecFonts, pMetrics, bEmbedd, bBold, bItalic, sName.c_str(), pEncoding ); } else pFont = (*it.first).m_pFont; return pFont; }
CAMLprim value Wrapper_FT_Get_Postscript_Name(value face) { CAMLparam1(face); FT_Face f; f = *(FT_Face *)Data_custom_val(face); CAMLreturn(copy_string(FT_Get_Postscript_Name(f))); };
void Print_Name( FT_Face face ) { const char* ps_name; printf( "font name entries\n" ); /* XXX: Foundry? Copyright? Version? ... */ printf( " family: %s\n", face->family_name ); printf( " style: %s\n", face->style_name ); ps_name = FT_Get_Postscript_Name( face ); if ( ps_name == NULL ) ps_name = "UNAVAILABLE"; printf( " postscript: %s\n", ps_name ); }
FT_Error get_file_info(FontManagerFontInfo *fileinfo, const gchar * filepath, gint index) { FT_Face face; FT_Library library; FT_Error error; PS_FontInfoRec ps_info; BDF_PropertyRec prop; gsize filesize = 0; gchar * font = NULL; if (G_UNLIKELY(!g_file_get_contents(filepath, &font, &filesize, NULL))) { g_warning("Failed to load file : %s", filepath); return FT_Err_Cannot_Open_Resource; } error = FT_Init_FreeType(&library); if (G_UNLIKELY(error)) return error; error = FT_New_Memory_Face(library, (const FT_Byte *) font, (FT_Long) filesize, index, &face); if (G_UNLIKELY(error)) { g_warning("Failed to create FT_Face for file : %s", filepath); return error; } font_manager_font_info_set_owner(fileinfo, get_file_owner(filepath)); font_manager_font_info_set_filetype(fileinfo, FT_Get_X11_Font_Format(face)); gchar * _size = g_format_size(filesize); font_manager_font_info_set_filesize(fileinfo, _size); g_free0(_size); gchar * _md5 = g_compute_checksum_for_data(G_CHECKSUM_MD5, (const guchar *) font, filesize); font_manager_font_info_set_checksum(fileinfo, _md5); g_free0(_md5); font_manager_font_info_set_psname(fileinfo, FT_Get_Postscript_Name(face)); TT_OS2 * os2 = (TT_OS2 *) FT_Get_Sfnt_Table(face, ft_sfnt_os2); if (G_LIKELY(os2 && os2->version >= 0x0001 && os2->version != 0xffff)) { gchar * _vendor = get_vendor_from_vendor_id((gchar *) os2->achVendID); font_manager_font_info_set_vendor(fileinfo, _vendor); g_free0(_vendor); gchar * panose = g_strdup_printf("%i:%i:%i:%i:%i:%i:%i:%i:%i:%i", os2->panose[0], os2->panose[1], os2->panose[2], os2->panose[3], os2->panose[4], os2->panose[5], os2->panose[6], os2->panose[7], os2->panose[8], os2->panose[9]); font_manager_font_info_set_panose(fileinfo, panose); g_free0(panose); } if (G_LIKELY(FT_IS_SFNT(face))) get_sfnt_info(fileinfo, face); if (FT_Get_PS_Font_Info(face, &ps_info) == 0) get_ps_info(fileinfo, ps_info, face); gint lic_type = get_license_type(font_manager_font_info_get_license_data(fileinfo), font_manager_font_info_get_copyright(fileinfo), font_manager_font_info_get_license_url(fileinfo)); gchar * _name = get_license_name(lic_type); font_manager_font_info_set_license_type(fileinfo, _name); g_free0(_name); if (!font_manager_font_info_get_license_url(fileinfo)) { gchar * _url = get_license_url(lic_type); if (_url) font_manager_font_info_set_license_url(fileinfo, _url); g_free0(_url); } if (!font_manager_font_info_get_version(fileinfo)) { TT_Header * head = (TT_Header *) FT_Get_Sfnt_Table (face, ft_sfnt_head); if (head) if (head->Font_Revision) { gchar * rev = g_strdup_printf("%f", (float) head->Font_Revision); font_manager_font_info_set_version(fileinfo, rev); g_free0(rev); } } if (!font_manager_font_info_get_vendor(fileinfo)) { int result = FT_Get_BDF_Property(face, "FOUNDRY", &prop); if(result == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) font_manager_font_info_set_vendor(fileinfo, prop.u.atom); else font_manager_font_info_set_vendor(fileinfo, "Unknown Vendor"); } FT_Done_Face(face); error = FT_Done_FreeType(library); g_free0(font); return error; }
bool CFontEngine::openFontFt(const QString &file) { enum ETtfWeight { TTF_WEIGHT_UNKNOWN = 0, TTF_WEIGHT_THIN = 100 + 50, TTF_WEIGHT_EXTRALIGHT = 200 + 50, TTF_WEIGHT_LIGHT = 300 + 50, TTF_WEIGHT_NORMAL = 400 + 50, TTF_WEIGHT_MEDIUM = 500 + 50, TTF_WEIGHT_SEMIBOLD = 600 + 50, TTF_WEIGHT_BOLD = 700 + 50, TTF_WEIGHT_EXTRABOLD = 800 + 50, TTF_WEIGHT_BLACK = 900 + 50 }; bool status = FT_New_Face(itsFt.library, QFile::encodeName(file), 0, &itsFt.face) ? false : true; if(status) itsFt.open = true; PS_FontInfoRec t1info; if(0 == FT_Get_PS_Font_Info(itsFt.face, &t1info)) { itsFamily = t1info.family_name; itsType = TYPE_1; } else { itsFamily = getName(itsFt.face, TT_NAME_ID_FONT_FAMILY); itsType = TRUE_TYPE; } if(itsFamily.isEmpty()) itsFamily = FT_Get_Postscript_Name(itsFt.face); if(itsFamily.isEmpty()) status = false; // Hmm... couldn't find any of the names! if(status) { removeSymbols(itsFamily); itsPsName = (FT_Get_Postscript_Name(itsFt.face)); if(TYPE_1 == itsType) { itsWeight = strToWeight(t1info.weight); itsItalic = t1info.italic_angle <= -4 || t1info.italic_angle >= 4 ? ITALIC_ITALIC : ITALIC_NONE; } else // TrueType... { TT_Postscript *post = NULL; TT_OS2 *os2 = NULL; TT_Header *head = NULL; bool gotItalic = false; if(NULL == (os2 = (TT_OS2 *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_os2)) || 0xFFFF == os2->version) itsWeight = WEIGHT_UNKNOWN; else { FT_UShort weight = (os2->usWeightClass > 0 && os2->usWeightClass < 100) ? os2->usWeightClass * 100 : os2->usWeightClass; if(weight < TTF_WEIGHT_THIN) itsWeight = WEIGHT_THIN; else if(weight < TTF_WEIGHT_EXTRALIGHT) itsWeight = WEIGHT_EXTRA_LIGHT; else if(weight < TTF_WEIGHT_LIGHT) itsWeight = WEIGHT_LIGHT; else if(/*weight<TTF_WEIGHT_NORMAL || */ weight < TTF_WEIGHT_MEDIUM) itsWeight = WEIGHT_MEDIUM; else if(weight < TTF_WEIGHT_SEMIBOLD) itsWeight = WEIGHT_SEMI_BOLD; else if(weight < TTF_WEIGHT_BOLD) itsWeight = WEIGHT_BOLD; else if(weight < TTF_WEIGHT_EXTRABOLD) itsWeight = WEIGHT_EXTRA_BOLD; else if(weight < TTF_WEIGHT_BLACK) itsWeight = WEIGHT_BLACK; else if(os2->fsSelection & (1 << 5)) itsWeight = WEIGHT_BOLD; else itsWeight = WEIGHT_UNKNOWN; itsItalic = os2->fsSelection & (1 << 0) ? ITALIC_ITALIC : ITALIC_NONE; gotItalic = true; } if(WEIGHT_UNKNOWN == itsWeight) itsWeight = NULL != (head = (TT_Header *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_head)) && head->Mac_Style & 1 ? WEIGHT_BOLD : WEIGHT_MEDIUM; if(!gotItalic && (head != NULL || NULL != (head = (TT_Header *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_head)))) { gotItalic = true; itsItalic = head->Mac_Style & 2 ? ITALIC_ITALIC : ITALIC_NONE; } if(!gotItalic && NULL != (post = (TT_Postscript *)FT_Get_Sfnt_Table(itsFt.face, ft_sfnt_post))) { struct TFixed { TFixed(unsigned long v) : upper(v >> 16), lower(v & 0xFFFF) { } short upper, lower; float value() { return upper + (lower / 65536.0); } }; gotItalic = true; itsItalic = 0.0f == ((TFixed)post->italicAngle).value() ? ITALIC_NONE : ITALIC_ITALIC; } } }
/** * \brief Select a face with the given charcode and add it to ASS_Font * \return index of the new face in font->faces, -1 if failed */ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch) { char *path; char *postscript_name = NULL; int i, index, uid, error; ASS_FontStream stream = { NULL, NULL }; FT_Face face; if (font->n_faces == ASS_FONT_MAX_FACES) return -1; path = ass_font_select(fontsel, font->library, font , &index, &postscript_name, &uid, &stream, ch); if (!path) return -1; for (i = 0; i < font->n_faces; i++) { if (font->faces_uid[i] == uid) { ass_msg(font->library, MSGL_INFO, "Got a font face that already is available! Skipping."); return i; } } if (stream.func) { FT_Open_Args args; FT_Stream ftstream = calloc(1, sizeof(FT_StreamRec)); ASS_FontStream *fs = calloc(1, sizeof(ASS_FontStream)); *fs = stream; ftstream->size = stream.func(stream.priv, NULL, 0, 0); ftstream->read = read_stream_font; ftstream->close = close_stream_font; ftstream->descriptor.pointer = (void *)fs; memset(&args, 0, sizeof(FT_Open_Args)); args.flags = FT_OPEN_STREAM; args.stream = ftstream; error = FT_Open_Face(font->ftlibrary, &args, index, &face); if (error) { ass_msg(font->library, MSGL_WARN, "Error opening memory font: '%s'", path); return -1; } } else { error = FT_New_Face(font->ftlibrary, path, index, &face); if (error) { ass_msg(font->library, MSGL_WARN, "Error opening font: '%s', %d", path, index); return -1; } if (postscript_name && index < 0 && face->num_faces > 0) { // The font provider gave us a post_script name and is not sure // about the face index.. so use the postscript name to find the // correct face_index in the collection! for (int i = 0; i < face->num_faces; i++) { FT_Done_Face(face); error = FT_New_Face(font->ftlibrary, path, i, &face); if (error) { ass_msg(font->library, MSGL_WARN, "Error opening font: '%s', %d", path, i); return -1; } const char *face_psname = FT_Get_Postscript_Name(face); if (face_psname != NULL && strcmp(face_psname, postscript_name) == 0) break; } } } charmap_magic(font->library, face); buggy_font_workaround(face); font->faces[font->n_faces] = face; font->faces_uid[font->n_faces++] = uid; ass_face_set_size(face, font->size); return font->n_faces - 1; }
FT2Font::FT2Font(std::string facefile) { _VERBOSE("FT2Font::FT2Font"); clear(Py::Tuple(0)); int error = FT_New_Face( _ft2Library, facefile.c_str(), 0, &face ); if (error == FT_Err_Unknown_File_Format ) { std::ostringstream s; s << "Could not load facefile " << facefile << "; Unknown_File_Format" << std::endl; throw Py::RuntimeError(s.str()); } else if (error == FT_Err_Cannot_Open_Resource) { std::ostringstream s; s << "Could not open facefile " << facefile << "; Cannot_Open_Resource" << std::endl; throw Py::RuntimeError(s.str()); } else if (error == FT_Err_Invalid_File_Format) { std::ostringstream s; s << "Could not open facefile " << facefile << "; Invalid_File_Format" << std::endl; throw Py::RuntimeError(s.str()); } else if (error) { std::ostringstream s; s << "Could not open facefile " << facefile << "; freetype error code " << error<< std::endl; throw Py::RuntimeError(s.str()); } // set a default fontsize 12 pt at 72dpi error = FT_Set_Char_Size( face, 12 * 64, 0, 72, 72 ); //error = FT_Set_Char_Size( face, 20 * 64, 0, 80, 80 ); if (error) { std::ostringstream s; s << "Could not set the fontsize for facefile " << facefile << std::endl; throw Py::RuntimeError(s.str()); } // set some face props as attributes //small memory leak fixed after 2.1.8 const char* ps_name = FT_Get_Postscript_Name( face ); //const char* ps_name = "jdh"; if ( ps_name == NULL ) ps_name = "UNAVAILABLE"; setattr("postscript_name", Py::String(ps_name)); setattr("num_faces", Py::Int(face->num_faces)); setattr("family_name", Py::String(face->family_name)); setattr("style_name", Py::String(face->style_name)); setattr("face_flags", Py::Int(face->face_flags)); setattr("style_flags", Py::Int(face->style_flags)); setattr("num_glyphs", Py::Int(face->num_glyphs)); setattr("num_fixed_sizes", Py::Int(face->num_fixed_sizes)); setattr("num_charmaps", Py::Int(face->num_charmaps)); int scalable = FT_IS_SCALABLE( face ); setattr("scalable", Py::Int(scalable)); if (scalable) { setattr("units_per_EM", Py::Int(face->units_per_EM)); Py::Tuple bbox(4); bbox[0] = Py::Int(face->bbox.xMin); bbox[1] = Py::Int(face->bbox.yMin); bbox[2] = Py::Int(face->bbox.xMax); bbox[3] = Py::Int(face->bbox.yMax); setattr("bbox", bbox); setattr("ascender", Py::Int(face->ascender)); setattr("descender", Py::Int(face->descender)); setattr("height", Py::Int(face->height)); setattr("max_advance_width", Py::Int(face->max_advance_width)); setattr("max_advance_height", Py::Int(face->max_advance_height)); setattr("underline_position", Py::Int(face->underline_position)); setattr("underline_thickness", Py::Int(face->underline_thickness)); } }
/** * \brief Read basic metadata (names, weight, slant) from a FreeType face, * as required for the FontSelector for matching and sorting. * \param lib FreeType library * \param face FreeType face * \param info metadata, returned here * \return success */ static bool get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) { int i; int num_fullname = 0; int num_family = 0; int num_names = FT_Get_Sfnt_Name_Count(face); int slant, weight; char *fullnames[MAX_FULLNAME]; char *families[MAX_FULLNAME]; // we're only interested in outlines if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) return false; for (i = 0; i < num_names; i++) { FT_SfntName name; if (FT_Get_Sfnt_Name(face, i, &name)) continue; if (name.platform_id == TT_PLATFORM_MICROSOFT && (name.name_id == TT_NAME_ID_FULL_NAME || name.name_id == TT_NAME_ID_FONT_FAMILY)) { char buf[1024]; ass_utf16be_to_utf8(buf, sizeof(buf), (uint8_t *)name.string, name.string_len); if (name.name_id == TT_NAME_ID_FULL_NAME) { fullnames[num_fullname] = strdup(buf); if (fullnames[num_fullname] == NULL) goto error; num_fullname++; } if (name.name_id == TT_NAME_ID_FONT_FAMILY) { families[num_family] = strdup(buf); if (families[num_family] == NULL) goto error; num_family++; } } } // check if we got a valid family - if not use whatever FreeType gives us if (num_family == 0 && face->family_name) { families[0] = strdup(face->family_name); if (families[0] == NULL) goto error; num_family++; } // we absolutely need a name if (num_family == 0) goto error; // calculate sensible slant and weight from style attributes slant = 110 * !!(face->style_flags & FT_STYLE_FLAG_ITALIC); weight = 300 * !!(face->style_flags & FT_STYLE_FLAG_BOLD) + 400; // fill our struct info->slant = slant; info->weight = weight; info->width = 100; // FIXME, should probably query the OS/2 table info->postscript_name = (char *)FT_Get_Postscript_Name(face); info->families = calloc(sizeof(char *), num_family); if (info->families == NULL) goto error; memcpy(info->families, &families, sizeof(char *) * num_family); info->n_family = num_family; if (num_fullname) { info->fullnames = calloc(sizeof(char *), num_fullname); if (info->fullnames == NULL) goto error; memcpy(info->fullnames, &fullnames, sizeof(char *) * num_fullname); info->n_fullname = num_fullname; } return false; error: for (i = 0; i < num_family; i++) free(families[i]); for (i = 0; i < num_fullname; i++) free(fullnames[i]); free(info->families); free(info->fullnames); return true; }
static VFontData *objfnt_to_ftvfontdata(PackedFile *pf) { /* Variables */ FT_Face face; const FT_ULong charcode_reserve = 256; FT_ULong charcode = 0, lcode; FT_UInt glyph_index; const char *fontname; VFontData *vfd; #if 0 FT_CharMap found = 0; FT_CharMap charmap; FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT; FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS; int n; #endif /* load the freetype font */ err = FT_New_Memory_Face(library, pf->data, pf->size, 0, &face); if (err) return NULL; #if 0 for (n = 0; n < face->num_charmaps; n++) { charmap = face->charmaps[n]; if (charmap->platform_id == my_platform_id && charmap->encoding_id == my_encoding_id) { found = charmap; break; } } if (!found) { return NULL; } /* now, select the charmap for the face object */ err = FT_Set_Charmap(face, found); if (err) { return NULL; } #endif /* allocate blender font */ vfd = MEM_callocN(sizeof(*vfd), "FTVFontData"); /* get the name */ fontname = FT_Get_Postscript_Name(face); BLI_strncpy(vfd->name, (fontname == NULL) ? "" : fontname, sizeof(vfd->name)); /* Extract the first 256 character from TTF */ lcode = charcode = FT_Get_First_Char(face, &glyph_index); /* No charmap found from the ttf so we need to figure it out */ if (glyph_index == 0) { FT_CharMap found = NULL; FT_CharMap charmap; int n; for (n = 0; n < face->num_charmaps; n++) { charmap = face->charmaps[n]; if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) { found = charmap; break; } } err = FT_Set_Charmap(face, found); if (err) return NULL; lcode = charcode = FT_Get_First_Char(face, &glyph_index); } /* Adjust font size */ if (face->bbox.yMax != face->bbox.yMin) { vfd->scale = (float)(1.0 / (double)(face->bbox.yMax - face->bbox.yMin)); } else { vfd->scale = 1.0f / 1000.0f; } /* Load characters */ vfd->characters = BLI_ghash_int_new_ex(__func__, charcode_reserve); while (charcode < charcode_reserve) { /* Generate the font data */ freetypechar_to_vchar(face, charcode, vfd); /* Next glyph */ charcode = FT_Get_Next_Char(face, charcode, &glyph_index); /* Check that we won't start infinite loop */ if (charcode <= lcode) break; lcode = charcode; } return vfd; }
XeTeXFontMgr::NameCollection* XeTeXFontMgr_FC::readNames(FcPattern* pat) { NameCollection* names = new NameCollection; char* pathname; if (FcPatternGetString(pat, FC_FILE, 0, (FcChar8**)&pathname) != FcResultMatch) return names; int index; if (FcPatternGetInteger(pat, FC_INDEX, 0, &index) != FcResultMatch) return names; FT_Face face; if (FT_New_Face(gFreeTypeLibrary, pathname, index, &face) != 0) return names; const char* name = FT_Get_Postscript_Name(face); if (name == NULL) return names; names->psName = name; // for sfnt containers, we'll read the name table ourselves, not rely on Fontconfig if (FT_IS_SFNT(face)) { std::list<std::string> familyNames; std::list<std::string> subFamilyNames; FT_SfntName nameRec; for (index = 0; index < FT_Get_Sfnt_Name_Count(face); ++index) { char* utf8name = NULL; if (FT_Get_Sfnt_Name(face, index, &nameRec) != 0) continue; switch (nameRec.name_id) { case kFontFullName: case kFontFamilyName: case kFontStyleName: case kPreferredFamilyName: case kPreferredSubfamilyName: { bool preferredName = false; if (nameRec.platform_id == TT_PLATFORM_MACINTOSH && nameRec.encoding_id == TT_MAC_ID_ROMAN && nameRec.language_id == 0) { utf8name = convertToUtf8(macRomanConv, nameRec.string, nameRec.string_len); preferredName = true; } else if ((nameRec.platform_id == TT_PLATFORM_APPLE_UNICODE) || (nameRec.platform_id == TT_PLATFORM_MICROSOFT)) utf8name = convertToUtf8(utf16beConv, nameRec.string, nameRec.string_len); if (utf8name != NULL) { std::list<std::string>* nameList = NULL; switch (nameRec.name_id) { case kFontFullName: nameList = &names->fullNames; break; case kFontFamilyName: nameList = &names->familyNames; break; case kFontStyleName: nameList = &names->styleNames; break; case kPreferredFamilyName: nameList = &familyNames; break; case kPreferredSubfamilyName: nameList = &subFamilyNames; break; } if (preferredName) prependToList(nameList, utf8name); else appendToList(nameList, utf8name); } } break; } } if (familyNames.size() > 0) names->familyNames = familyNames; if (subFamilyNames.size() > 0) names->styleNames = subFamilyNames; } else { index = 0; while (FcPatternGetString(pat, FC_FULLNAME, index++, (FcChar8**)&name) == FcResultMatch) appendToList(&names->fullNames, name); index = 0; while (FcPatternGetString(pat, FC_FAMILY, index++, (FcChar8**)&name) == FcResultMatch) appendToList(&names->familyNames, name); index = 0; while (FcPatternGetString(pat, FC_STYLE, index++, (FcChar8**)&name) == FcResultMatch) appendToList(&names->styleNames, name); if (names->fullNames.size() == 0) { std::string fullName(names->familyNames.front()); if (names->styleNames.size() > 0) { fullName += " "; fullName += names->styleNames.front(); } names->fullNames.push_back(fullName); } } FT_Done_Face(face); return names; }
static VFontData *objfnt_to_ftvfontdata(PackedFile * pf) { // Variables FT_Face face; FT_ULong charcode = 0, lcode; FT_UInt glyph_index; const char *fontname; VFontData *vfd; /* FT_CharMap found = 0; FT_CharMap charmap; FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT; FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS; int n; */ // load the freetype font err = FT_New_Memory_Face( library, pf->data, pf->size, 0, &face ); if(err) return NULL; /* for ( n = 0; n < face->num_charmaps; n++ ) { charmap = face->charmaps[n]; if ( charmap->platform_id == my_platform_id && charmap->encoding_id == my_encoding_id ) { found = charmap; break; } } if ( !found ) { return NULL; } // now, select the charmap for the face object err = FT_Set_Charmap( face, found ); if ( err ) { return NULL; } */ // allocate blender font vfd= MEM_callocN(sizeof(*vfd), "FTVFontData"); // get the name fontname = FT_Get_Postscript_Name(face); strcpy(vfd->name, (fontname == NULL) ? "" : fontname); // Extract the first 256 character from TTF lcode= charcode= FT_Get_First_Char(face, &glyph_index); // No charmap found from the ttf so we need to figure it out if(glyph_index == 0) { FT_CharMap found = NULL; FT_CharMap charmap; int n; for ( n = 0; n < face->num_charmaps; n++ ) { charmap = face->charmaps[n]; if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) { found = charmap; break; } } err = FT_Set_Charmap( face, found ); if( err ) return NULL; lcode= charcode= FT_Get_First_Char(face, &glyph_index); } // Load characters while(charcode < 256) { // Generate the font data freetypechar_to_vchar(face, charcode, vfd); // Next glyph charcode = FT_Get_Next_Char(face, charcode, &glyph_index); // Check that we won't start infinite loop if(charcode <= lcode) break; lcode = charcode; } return vfd; }
int main(int argc, char **argv) { char *fn; int begin=0; int end=255; int size=10; int cpl=0; int cell=0; char autohinter=0; char seq=0; char alpha=0; char pack=0; FT_Library freetype; FT_Face face; int err; int i; char *out_fn="font.png"; char *def_fn=NULL; Font font; if(argc<2) { usage(); return 1; } while((i=getopt(argc, argv, "r:s:l:c:o:atvh?ed:p"))!=-1) { char *ptr; int temp; switch(i) { case 'r': if(!strcmp(optarg, "all")) { begin=0; end=0x110000; } else { if(!isdigit(optarg[0])) temp=-1; else { temp=strtol(optarg, &ptr, 0); if(ptr[0]!=',' || !isdigit(ptr[1])) temp=-1; } if(temp<0) { printf("Not a valid range: %s\n", optarg); exit(1); } else { begin=temp; end=strtol(ptr+1, NULL, 0); } } break; case 's': size=strtol(optarg, NULL, 0); break; case 'l': cpl=strtol(optarg, NULL, 0); break; case 'c': cell=strtol(optarg, NULL, 0); break; case 'o': out_fn=optarg; break; case 'a': autohinter=1; break; case 't': alpha=1; break; case 'v': ++verbose; break; case 'h': case '?': usage(); return 0; case 'e': seq=1; break; case 'd': def_fn=optarg; break; case 'p': pack=1; break; } } if(!strcmp(out_fn, "-")) verbose=0; if(optind!=argc-1) { usage(); return 1; } fn=argv[optind]; err=FT_Init_FreeType(&freetype); if(err) { fprintf(stderr, "Couldn't initialize FreeType library\n"); return 1; } err=FT_New_Face(freetype, fn, 0, &face); if(err) { fprintf(stderr, "Couldn't load font file\n"); if(err==FT_Err_Unknown_File_Format) fprintf(stderr, "Unknown file format\n"); return 1; } if(verbose) { const char *name=FT_Get_Postscript_Name(face); printf("Font name: %s\n", name); printf("Glyphs: %ld\n", face->num_glyphs); } err=FT_Set_Pixel_Sizes(face, 0, size); if(err) { fprintf(stderr, "Couldn't set size\n"); return 1; } font.size=size; init_font(&font, face, begin, end, autohinter); if(pack) render_packed(&font); else render_grid(&font, cell, cpl, seq); save_png(out_fn, &font.image, alpha); if(def_fn) save_defs(def_fn, &font); for(i=0; i<font.n_glyphs; ++i) free(font.glyphs[i].image.data); free(font.glyphs); free(font.image.data); FT_Done_Face(face); FT_Done_FreeType(freetype); return 0; }
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 {
const char* PdfFontMetricsFreetype::GetFontname() const { const char* s = FT_Get_Postscript_Name( m_pFace ); return s ? s : ""; }
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; }
unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int size) { if ( descr == NULL ) { if ( size > 0 ) { str[0]=0; } return 0; } char* res=NULL; bool free_res=false; if ( strcmp(key,"name") == 0 ) { PangoFontDescription* td=pango_font_description_copy(descr); pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE); res=pango_font_description_to_string (td); pango_font_description_free(td); free_res=true; } else if ( strcmp(key,"psname") == 0 ) { #ifndef USE_PANGO_WIN32 res = (char *) FT_Get_Postscript_Name (theFace); // that's the main method, seems to always work #endif free_res=false; if (res == NULL) { // a very limited workaround, only bold, italic, and oblique will work PangoStyle style=pango_font_description_get_style(descr); bool i = (style == PANGO_STYLE_ITALIC); bool o = (style == PANGO_STYLE_OBLIQUE); PangoWeight weight=pango_font_description_get_weight(descr); bool b = (weight >= PANGO_WEIGHT_BOLD); res = g_strdup_printf ("%s%s%s%s", pango_font_description_get_family(descr), (b || i || o) ? "-" : "", (b) ? "Bold" : "", (i) ? "Italic" : ((o) ? "Oblique" : "") ); free_res = true; } } else if ( strcmp(key,"family") == 0 ) { res=(char*)pango_font_description_get_family(descr); free_res=false; } else if ( strcmp(key,"style") == 0 ) { PangoStyle v=pango_font_description_get_style(descr); if ( v == PANGO_STYLE_ITALIC ) { res=(char*)"italic"; } else if ( v == PANGO_STYLE_OBLIQUE ) { res=(char*)"oblique"; } else { res=(char*)"normal"; } free_res=false; } else if ( strcmp(key,"weight") == 0 ) { PangoWeight v=pango_font_description_get_weight(descr); if ( v <= PANGO_WEIGHT_THIN ) { res=(char*)"100"; } else if ( v <= PANGO_WEIGHT_ULTRALIGHT ) { res=(char*)"200"; } else if ( v <= PANGO_WEIGHT_LIGHT ) { res=(char*)"300"; } else if ( v <= PANGO_WEIGHT_BOOK ) { res=(char*)"380"; } else if ( v <= PANGO_WEIGHT_NORMAL ) { res=(char*)"normal"; } else if ( v <= PANGO_WEIGHT_MEDIUM ) { res=(char*)"500"; } else if ( v <= PANGO_WEIGHT_SEMIBOLD ) { res=(char*)"600"; } else if ( v <= PANGO_WEIGHT_BOLD ) { res=(char*)"bold"; } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) { res=(char*)"800"; } else { // HEAVY NB: Pango defines ULTRAHEAVY = 1000 but not CSS2 res=(char*)"900"; } free_res=false; } else if ( strcmp(key,"stretch") == 0 ) { PangoStretch v=pango_font_description_get_stretch(descr); if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) { res=(char*)"extra-condensed"; } else if ( v <= PANGO_STRETCH_CONDENSED ) { res=(char*)"condensed"; } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) { res=(char*)"semi-condensed"; } else if ( v <= PANGO_STRETCH_NORMAL ) { res=(char*)"normal"; } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) { res=(char*)"semi-expanded"; } else if ( v <= PANGO_STRETCH_EXPANDED ) { res=(char*)"expanded"; } else { res=(char*)"extra-expanded"; } free_res=false; } else if ( strcmp(key,"variant") == 0 ) { PangoVariant v=pango_font_description_get_variant(descr); if ( v == PANGO_VARIANT_SMALL_CAPS ) { res=(char*)"small-caps"; } else { res=(char*)"normal"; } free_res=false; } else { res = NULL; free_res=false; } if ( res == NULL ) { if ( size > 0 ) { str[0] = 0; } return 0; } if (res) { unsigned int len=strlen(res); unsigned int rlen=(size-1<len)?size-1:len; if ( str ) { if ( rlen > 0 ) { memcpy(str, res, rlen); } if ( size > 0 ) { str[rlen] = 0; } } if (free_res) { g_free(res); res = 0; } return len; } return 0; }