unsigned FTRemap(FT_Face face, FTMappingPtr tm, unsigned code) { unsigned index; char *name; unsigned glyph_index; if(tm->mapping) { if(tm->named) { name = FontEncName(code, tm->mapping); if(!name) return 0; glyph_index = FT_Get_Name_Index(face, name); return glyph_index; } else { index = FontEncRecode(code, tm->mapping) + tm->base; FT_Set_Charmap(face, tm->cmap); glyph_index = FT_Get_Char_Index(face, index); return glyph_index; } } else { if(code < 0x100) { index = code; FT_Set_Charmap(face, tm->cmap); glyph_index = FT_Get_Char_Index(face, index); return glyph_index; } else return 0; } }
static int find_cmap(int type, int pid, int eid, FT_Face face) { int i, n, rc; FT_CharMap cmap = NULL; n = face->num_charmaps; switch(type) { case FONT_ENCODING_TRUETYPE: /* specific cmap */ for(i=0; i<n; i++) { cmap = face->charmaps[i]; if(cmap->platform_id == pid && cmap->encoding_id == eid) { rc = FT_Set_Charmap(face, cmap); if(rc == 0) return 1; } } break; case FONT_ENCODING_UNICODE: /* any Unicode cmap */ /* prefer Microsoft Unicode */ for(i=0; i<n; i++) { cmap = face->charmaps[i]; if(cmap->platform_id == TT_PLATFORM_MICROSOFT && cmap->encoding_id == TT_MS_ID_UNICODE_CS) { rc = FT_Set_Charmap(face, cmap); if(rc == 0) return 1; } } /* Try Apple Unicode */ for(i=0; i<n; i++) { cmap = face->charmaps[i]; if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) { rc = FT_Set_Charmap(face, cmap); if(rc == 0) return 1; } } /* ISO Unicode? */ for(i=0; i<n; i++) { cmap = face->charmaps[i]; if(cmap->platform_id == TT_PLATFORM_ISO) { rc = FT_Set_Charmap(face, cmap); if(rc == 0) return 1; } } break; default: return 0; } return 0; }
static FT_Error af_indic_metrics_init( AF_CJKMetrics metrics, FT_Face face ) { /* skip blue zone init in CJK routines */ FT_CharMap oldmap = face->charmap; metrics->units_per_em = face->units_per_EM; if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) ) face->charmap = NULL; else { af_cjk_metrics_init_widths( metrics, face ); #if 0 /* either need indic specific blue_chars[] or just skip blue zones */ af_cjk_metrics_init_blues( metrics, face, af_cjk_blue_chars ); #endif af_cjk_metrics_check_digits( metrics, face ); } FT_Set_Charmap( face, oldmap ); return FT_Err_Ok; }
static gboolean check_font_contain_text (FT_Face face, const gchar *text) { gunichar *string; glong len, idx, map; FT_CharMap charmap; gboolean retval; string = g_utf8_to_ucs4_fast (text, -1, &len); for (map = 0; map < face->num_charmaps; map++) { charmap = face->charmaps[map]; FT_Set_Charmap (face, charmap); retval = TRUE; for (idx = 0; idx < len; idx++) { gunichar c = string[idx]; if (!FT_Get_Char_Index (face, c)) { retval = FALSE; break; } } if (retval) break; } g_free (string); return retval; }
TTF_Font* TTF_New_Memory_Face(const FT_Byte* file_base, FT_Long file_size, int ptsize) { TTF_Font *font = (TTF_Font*)malloc(sizeof *font); if (font == NULL) E_Exit("TTF: Out of memory"); memset(font, 0, sizeof(*font)); if (FT_New_Memory_Face(library, file_base, file_size, 0, &font->face)) E_Exit("TTF: Couldn't init font"); FT_Face face = font->face; if (!FT_IS_SCALABLE(face)) // Make sure that our font face is scalable (global metrics) E_Exit("TTF: Font is not scalable"); for (int i = 0; i < face->num_charmaps; i++) // Set charmap for loaded font { FT_CharMap charmap = face->charmaps[i]; if (charmap->platform_id == 3 && charmap->encoding_id == 1) // Windows Unicode { FT_Set_Charmap(face, charmap); break; } } TTF_SetCharSize(font, ptsize); bool fontOK = false; if (!FT_Load_Glyph(face, 0, FT_LOAD_DEFAULT)) // Test pixel mode if (!FT_Render_Glyph(font->face->glyph, FT_RENDER_MODE_NORMAL)) // Render the glyph if (font->face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) fontOK = true; if (!fontOK) E_Exit("TTF: Font is not 8 bits gray scale"); return font; }
static int check_freetypefont(PackedFile *pf) { FT_Face face; FT_GlyphSlot glyph; FT_UInt glyph_index; #if 0 FT_CharMap charmap; FT_CharMap found; FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT; FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS; int n; #endif int success = 0; err = FT_New_Memory_Face(library, pf->data, pf->size, 0, &face); if (err) { success = 0; //XXX error("This is not a valid font"); } else { #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 0; } /* now, select the charmap for the face object */ err = FT_Set_Charmap(face, found); if (err) { return 0; } #endif glyph_index = FT_Get_Char_Index(face, 'A'); err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP); if (err) { success = 0; } else { glyph = face->glyph; if (glyph->format == ft_glyph_format_outline) { success = 1; } else { //XXX error("Selected Font has no outline data"); success = 0; } } } return success; }
//============================================================================== static FTFaceWrapper::Ptr selectUnicodeCharmap (FTFaceWrapper* face) { if (face != nullptr) if (FT_Select_Charmap (face->face, ft_encoding_unicode) != 0) FT_Set_Charmap (face->face, face->face->charmaps[0]); return face; }
Charmap::Charmap(Face * face) : m_ftFace(*face->freetype()), m_error(0) { if(!m_ftFace->charmap) m_error = FT_Set_Charmap(m_ftFace, m_ftFace->charmaps[0]); m_ftEncoding = m_ftFace->charmap->encoding; }
/* See http://www.microsoft.com/typography/otspec/name.htm for a list of some possible platform-encoding pairs. We're interested in 0-3 aka 3-1 - UCS-2. Otherwise, fail. If a font has some unicode map, but lacks UCS-2 - it is a broken or irrelevant font. What exactly Freetype will select on face load (it promises most wide unicode, and if that will be slower that UCS-2 - left as an excercise to check. */ int force_ucs2_charmap(FT_Face ftf) { for(int i = 0; i < ftf->num_charmaps; i++) if (( (ftf->charmaps[i]->platform_id == 0) && (ftf->charmaps[i]->encoding_id == 3)) || ((ftf->charmaps[i]->platform_id == 3) && (ftf->charmaps[i]->encoding_id == 1))) return FT_Set_Charmap(ftf, ftf->charmaps[i]); return -1; }
/* See http://www.microsoft.com/typography/otspec/name.htm for a list of some possible platform-encoding pairs. We're interested in 0-3 aka 3-1 - UCS-2. Otherwise, fail. If a font has some unicode map, but lacks UCS-2 - it is a broken or irrelevant font. What exactly Freetype will select on face load (it promises most wide unicode, and if that will be slower that UCS-2 - left as an excercise to check. */ int force_ucs2_charmap( FT_Face face ) { int i; for(i = 0; i < face->num_charmaps; i++) if( ((face->charmaps[i]->platform_id == 0) && (face->charmaps[i]->encoding_id == 3)) || ((face->charmaps[i]->platform_id == 3) && (face->charmaps[i]->encoding_id == 1)) ) return FT_Set_Charmap( face, face->charmaps[i] ); return -1; }
// load and store charsmaps static void LoadCharsMaps(GFont2D& Font, const FT_Face Face) { GUInt32 i, numMaps; FT_ULong charCode; FT_UInt glyphIndex; FT_Error err; FT_CharMap *maps; FT_CharMap map; GEncodedChar encodedChar; GCharMap tmpMap; numMaps = Face->num_charmaps; maps = Face->charmaps; for (i = 0; i < numMaps; i++) { map = maps[i]; err = FT_Set_Charmap(Face, map); if (err == 0) { // get first (valid) char code charCode = FT_Get_First_Char(Face, &glyphIndex); // if glyphIndex is 0, it means that charmap is empty if (glyphIndex != 0) { tmpMap.CharMap.clear(); // store encoding informations tmpMap.PlatformID = map->platform_id; tmpMap.EncodingID = map->encoding_id; switch (map->encoding) { case FT_ENCODING_MS_SYMBOL: tmpMap.Encoding = G_ENCODING_MS_SYMBOL; case FT_ENCODING_UNICODE: tmpMap.Encoding = G_ENCODING_UNICODE; case FT_ENCODING_SJIS: tmpMap.Encoding = G_ENCODING_SJIS; case FT_ENCODING_GB2312: tmpMap.Encoding = G_ENCODING_GB2312; case FT_ENCODING_BIG5: tmpMap.Encoding = G_ENCODING_BIG5; case FT_ENCODING_WANSUNG: tmpMap.Encoding = G_ENCODING_WANSUNG; case FT_ENCODING_JOHAB: tmpMap.Encoding = G_ENCODING_JOHAB; case FT_ENCODING_ADOBE_STANDARD: tmpMap.Encoding = G_ENCODING_ADOBE_STANDARD; case FT_ENCODING_ADOBE_EXPERT: tmpMap.Encoding = G_ENCODING_ADOBE_EXPERT; case FT_ENCODING_ADOBE_CUSTOM: tmpMap.Encoding = G_ENCODING_ADOBE_CUSTOM; case FT_ENCODING_ADOBE_LATIN_1: tmpMap.Encoding = G_ENCODING_ADOBE_LATIN_1; case FT_ENCODING_OLD_LATIN_2: tmpMap.Encoding = G_ENCODING_OLD_LATIN_2; case FT_ENCODING_APPLE_ROMAN: tmpMap.Encoding = G_ENCODING_APPLE_ROMAN; default: tmpMap.Encoding = G_ENCODING_NONE; } while (glyphIndex != 0) { encodedChar.CharCode = (GUInt32)charCode; encodedChar.GlyphIndex = (GUInt32)(glyphIndex - 0); tmpMap.CharMap.push_back(encodedChar); charCode = FT_Get_Next_Char(Face, charCode, &glyphIndex); } // add the loaded charmap to the font Font.AddCharMap(tmpMap); } } } }
void initialize_face(FT_Face* face, FT_Library* library, int height, const char* filename) { int error; fprintf(stderr,"Loading %s... ", filename); error = FT_New_Face( *library, filename, 0, face ); if ( error == FT_Err_Unknown_File_Format ) { fprintf(stderr,"Error opening font file\n"); exit(1); } else if ( error ) { fprintf(stderr,"another error code means that the font file could not \nbe opened or read, or simply that it is broken..."); } FT_CharMap found = 0; int n; for (n = 0; n < (*face)->num_charmaps; n++ ) { FT_CharMap charmap = (*face)->charmaps[n]; #ifndef TTF2C printf("platform_id:%d encoding_id:%d\n", charmap->platform_id, charmap->encoding_id); #endif found = charmap; if ( charmap->platform_id == 3/*my_platform_id*/ && charmap->encoding_id == 1/*my_encoding_id*/ ) { // #ifndef TTF2C // fprintf(stderr,"found charmap\n"); // #endif break; } } if ( !found ) { fprintf(stderr,"Encoding not found\n"); exit(1); } /* now, select the charmap for the face object */ error = FT_Set_Charmap( *face, found ); if ( error ) { fprintf(stderr,"Error setting encoding\n"); exit(1); } int width = 0; error = FT_Set_Char_Size((*face), 0, height*64, 72, 72); error = FT_Set_Pixel_Sizes((*face), 0, height); if (error) { fprintf(stderr,"(fixed size) "); // exit(1); } fprintf(stderr,"ok\n"); }
FTCharmap::FTCharmap( FTFace* face) : ftFace( *(face->Face())), err(0) { if( !ftFace->charmap) { err = FT_Set_Charmap( ftFace, ftFace->charmaps[0]); } ftEncoding = ftFace->charmap->encoding; }
/* * Function : libaroma_font_set_ucs2 * Return Value: int * Descriptions: set ucs2 charmap for fontface */ int libaroma_font_set_ucs2( FT_Face ftf) { int i; for (i = 0; i < ftf->num_charmaps; i++) { if (( (ftf->charmaps[i]->platform_id == 0) && (ftf->charmaps[i]->encoding_id == 3)) || ((ftf->charmaps[i]->platform_id == 3) && (ftf->charmaps[i]->encoding_id == 1))) { return FT_Set_Charmap(ftf, ftf->charmaps[i]); } } return -1; } /* End of libaroma_font_set_ucs2 */
/** * Select Microfost Unicode CharMap, if the font has one. * Otherwise, let FreeType decide. */ static void charmap_magic(FT_Face face) { int i; for (i = 0; i < face->num_charmaps; ++i) { FT_CharMap cmap = face->charmaps[i]; unsigned pid = cmap->platform_id; unsigned eid = cmap->encoding_id; if (pid == 3 /*microsoft*/ && (eid == 1 /*unicode bmp*/ || eid == 10 /*full unicode*/)) { FT_Set_Charmap(face, cmap); return; } } if (!face->charmap) { if (face->num_charmaps == 0) { mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoCharmaps); return; } mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoCharmapAutodetected); FT_Set_Charmap(face, face->charmaps[0]); return; } }
/** * Select a good charmap, prefer Microsoft Unicode charmaps. * Otherwise, let FreeType decide. */ void charmap_magic(ASS_Library *library, FT_Face face) { int i; int ms_cmap = -1; // Search for a Microsoft Unicode cmap for (i = 0; i < face->num_charmaps; ++i) { FT_CharMap cmap = face->charmaps[i]; unsigned pid = cmap->platform_id; unsigned eid = cmap->encoding_id; if (pid == 3 /*microsoft */ && (eid == 1 /*unicode bmp */ || eid == 10 /*full unicode */ )) { FT_Set_Charmap(face, cmap); return; } else if (pid == 3 && ms_cmap < 0) ms_cmap = i; } // Try the first Microsoft cmap if no Microsoft Unicode cmap was found if (ms_cmap >= 0) { FT_CharMap cmap = face->charmaps[ms_cmap]; FT_Set_Charmap(face, cmap); return; } if (!face->charmap) { if (face->num_charmaps == 0) { ass_msg(library, MSGL_WARN, "Font face with no charmaps"); return; } ass_msg(library, MSGL_WARN, "No charmap autodetected, trying the first one"); FT_Set_Charmap(face, face->charmaps[0]); return; } }
cairo_font_face_t *Rcairo_set_font_face(int i, const char *file){ cairo_font_face_t *c_face; cairo_status_t status; FT_Face face; FT_Error er; FT_CharMap found = 0; FT_CharMap charmap; int n; /* Ensure that freetype library is ready */ if (!Rcairo_ft_library){ if (FT_Init_FreeType(&Rcairo_ft_library)){ error("Failed to initialize freetype library in Rcairo_set_font_face!\n"); return FALSE; } } er = FT_New_Face(Rcairo_ft_library, file, 0, &face); if ( er == FT_Err_Unknown_File_Format ) { error("Unsupported font file format\n"); return NULL; } else if ( er ) { error("Unknown font problem\n"); return NULL; } for ( n = 0; n < face->num_charmaps; n++ ) { charmap = face->charmaps[n]; if ( charmap->platform_id == TT_PLATFORM_MACINTOSH) { found = charmap; break; } } /* Only do this for symbol font */ if (found && i == 4){ er = FT_Set_Charmap( face, found ); } c_face = cairo_ft_font_face_create_for_ft_face(face,FT_LOAD_DEFAULT); status = cairo_font_face_set_user_data (c_face, &key, face, (cairo_destroy_func_t) FT_Done_Face); if (status) { cairo_font_face_destroy (c_face); FT_Done_Face (face); return NULL; } return c_face; }
/** * Loads the freetype font. * First type to load the fontname as if it were a path. If that fails, * try to resolve the filename of the font using fontconfig, where the * format is 'font family name' or 'font family name, font style'. */ static void LoadFreeTypeFont(const char *font_name, FT_Face *face, const char *type) { FT_Error error; if (StrEmpty(font_name)) return; error = FT_New_Face(_library, font_name, 0, face); if (error != FT_Err_Ok) error = GetFontByFaceName(font_name, face); if (error == FT_Err_Ok) { DEBUG(freetype, 2, "Requested '%s', using '%s %s'", font_name, (*face)->family_name, (*face)->style_name); /* Attempt to select the unicode character map */ error = FT_Select_Charmap(*face, ft_encoding_unicode); if (error == FT_Err_Ok) return; // Success if (error == FT_Err_Invalid_CharMap_Handle) { /* Try to pick a different character map instead. We default to * the first map, but platform_id 0 encoding_id 0 should also * be unicode (strange system...) */ FT_CharMap found = (*face)->charmaps[0]; int i; for (i = 0; i < (*face)->num_charmaps; i++) { FT_CharMap charmap = (*face)->charmaps[i]; if (charmap->platform_id == 0 && charmap->encoding_id == 0) { found = charmap; } } if (found != NULL) { error = FT_Set_Charmap(*face, found); if (error == FT_Err_Ok) return; } } } FT_Done_Face(*face); *face = NULL; ShowInfoF("Unable to use '%s' for %s font, FreeType reported error 0x%X, using sprite font instead", font_name, type, error); }
void FreeTypeLibrary::verifyCharacterMap(FT_Face face) { // // GT: Verify the correct character mapping for MS windows // as symbol fonts were being returned incorrectly // FT_CharMap charmap; if (face->charmap == NULL) { for (int n = 0; n < face->num_charmaps; n++) { charmap = face->charmaps[n]; if (charmap->platform_id == TT_PLATFORM_MICROSOFT) { FT_Set_Charmap(face, charmap); break; } } } }
af_cjk_metrics_init( AF_LatinMetrics metrics, FT_Face face ) { FT_CharMap oldmap = face->charmap; metrics->units_per_em = face->units_per_EM; /* TODO are there blues? */ if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) ) face->charmap = NULL; /* latin's version would suffice */ af_latin_metrics_init_widths( metrics, face, 0x7530 ); FT_Set_Charmap( face, oldmap ); return AF_Err_Ok; }
//============================================================================== FTFaceWrapper::Ptr createFace (const String& fontName, const String& fontStyle) { const KnownTypeface* ftFace = matchTypeface (fontName, fontStyle); if (ftFace == nullptr) ftFace = matchTypeface (fontName, "Regular"); if (ftFace == nullptr) ftFace = matchTypeface (fontName, String::empty); if (ftFace != nullptr) { if (FTFaceWrapper::Ptr face = new FTFaceWrapper (library, ftFace->file, ftFace->faceIndex)) { // If there isn't a unicode charmap then select the first one. if (FT_Select_Charmap (face->face, ft_encoding_unicode) != 0) FT_Set_Charmap (face->face, face->face->charmaps[0]); return face; } } return nullptr; }
void Print_Charmaps( FT_Face face ) { int i, active = -1; if ( face->charmap ) active = FT_Get_Charmap_Index( face->charmap ); /* CharMaps */ printf( "charmaps\n" ); for( i = 0; i < face->num_charmaps; i++ ) { printf( " %d: platform %d, encoding %d", i, face->charmaps[i]->platform_id, face->charmaps[i]->encoding_id ); if ( i == active ) printf( " (active)" ); printf ( "\n" ); if ( verbose ) { FT_ULong charcode; FT_UInt gindex; FT_Set_Charmap( face, face->charmaps[i] ); charcode = FT_Get_First_Char( face, &gindex ); while ( gindex ) { printf( " 0x%04lx => %d\n", charcode, gindex ); charcode = FT_Get_Next_Char( face, charcode, &gindex ); } printf( "\n" ); } } }
FTCharmap::FTCharmap(FTFace* face) : ftFace(*(face->Face())), err(0) { if(!ftFace->charmap) { if(!ftFace->num_charmaps) { // This face doesn't even have one charmap! err = 0x96; // Invalid_CharMap_Format return; } err = FT_Set_Charmap(ftFace, ftFace->charmaps[0]); } ftEncoding = ftFace->charmap->encoding; for(unsigned int i = 0; i < FTCharmap::MAX_PRECOMPUTED; i++) { charIndexCache[i] = FT_Get_Char_Index(ftFace, i); } }
FTCharmap::FTCharmap(FTFace* face) : ftFace(*(face->Face())), charMap(), err(0) { if(!ftFace->charmap){ err = FT_Set_Charmap(ftFace, ftFace->charmaps[0]); } ftEncoding = ftFace->charmap->encoding; if(ftEncoding != ft_encoding_unicode){ err = FT_Select_Charmap(ftFace, ft_encoding_unicode); if(!err){ ftEncoding = ft_encoding_unicode; }else{ ftEncoding = ft_encoding_none; PP_WARNING("Unable to set encoding to unicode: Error code -> " << err); } charMap.clear(); } }
af_latin_metrics_init( AF_LatinMetrics metrics, FT_Face face ) { FT_Error error = AF_Err_Ok; FT_CharMap oldmap = face->charmap; FT_UInt ee; static const FT_Encoding latin_encodings[] = { FT_ENCODING_UNICODE, FT_ENCODING_APPLE_ROMAN, FT_ENCODING_ADOBE_STANDARD, FT_ENCODING_ADOBE_LATIN_1, FT_ENCODING_NONE /* end of list */ }; metrics->units_per_em = face->units_per_EM; /* do we have a latin charmap in there? */ for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ ) { error = FT_Select_Charmap( face, latin_encodings[ee] ); if ( !error ) break; } if ( !error ) { /* For now, compute the standard width and height from the `o'. */ af_latin_metrics_init_widths( metrics, face, 'o' ); af_latin_metrics_init_blues( metrics, face ); } FT_Set_Charmap( face, oldmap ); return AF_Err_Ok; }
/* parse a PFM file -- for now, only read the kerning pairs */ static FT_Error T1_Read_PFM( FT_Face t1_face, FT_Stream stream, AFM_FontInfo fi ) { FT_Error error = FT_Err_Ok; FT_Memory memory = stream->memory; FT_Byte* start; FT_Byte* limit; FT_Byte* p; AFM_KernPair kp; FT_Int width_table_length; FT_CharMap oldcharmap; FT_CharMap charmap; FT_Int n; start = (FT_Byte*)stream->cursor; limit = (FT_Byte*)stream->limit; p = start; /* Figure out how long the width table is. */ /* This info is a little-endian short at offset 99. */ p = start + 99; if ( p + 2 > limit ) { error = FT_THROW( Unknown_File_Format ); goto Exit; } width_table_length = FT_PEEK_USHORT_LE( p ); p += 18 + width_table_length; if ( p + 0x12 > limit || FT_PEEK_USHORT_LE( p ) < 0x12 ) /* extension table is probably optional */ goto Exit; /* Kerning offset is 14 bytes from start of extensions table. */ p += 14; p = start + FT_PEEK_ULONG_LE( p ); if ( p == start ) /* zero offset means no table */ goto Exit; if ( p + 2 > limit ) { error = FT_THROW( Unknown_File_Format ); goto Exit; } fi->NumKernPair = FT_PEEK_USHORT_LE( p ); p += 2; if ( p + 4 * fi->NumKernPair > limit ) { error = FT_THROW( Unknown_File_Format ); goto Exit; } /* Actually, kerning pairs are simply optional! */ if ( fi->NumKernPair == 0 ) goto Exit; /* allocate the pairs */ if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) ) goto Exit; /* now, read each kern pair */ kp = fi->KernPairs; limit = p + 4 * fi->NumKernPair; /* PFM kerning data are stored by encoding rather than glyph index, */ /* so find the PostScript charmap of this font and install it */ /* temporarily. If we find no PostScript charmap, then just use */ /* the default and hope it is the right one. */ oldcharmap = t1_face->charmap; charmap = NULL; for ( n = 0; n < t1_face->num_charmaps; n++ ) { charmap = t1_face->charmaps[n]; /* check against PostScript pseudo platform */ if ( charmap->platform_id == 7 ) { error = FT_Set_Charmap( t1_face, charmap ); if ( error ) goto Exit; break; } } /* Kerning info is stored as: */ /* */ /* encoding of first glyph (1 byte) */ /* encoding of second glyph (1 byte) */ /* offset (little-endian short) */ for ( ; p < limit ; p += 4 ) { kp->index1 = FT_Get_Char_Index( t1_face, p[0] ); kp->index2 = FT_Get_Char_Index( t1_face, p[1] ); kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2); kp->y = 0; kp++; } if ( oldcharmap != NULL ) error = FT_Set_Charmap( t1_face, oldcharmap ); if ( error ) goto Exit; /* now, sort the kern pairs according to their glyph indices */ ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ), compare_kern_pairs ); Exit: if ( error ) { FT_FREE( fi->KernPairs ); fi->NumKernPair = 0; } return error; }
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; }
void xps_select_font_encoding(fz_font *font, int idx) { FT_Face face = font->ft_face; FT_Set_Charmap(face, face->charmaps[idx]); }
static FT_Error af_face_globals_compute_style_coverage( AF_FaceGlobals globals ) { FT_Error error; FT_Face face = globals->face; FT_CharMap old_charmap = face->charmap; FT_Byte* gstyles = globals->glyph_styles; FT_UInt ss; FT_UInt i; FT_UInt dflt = -1; /* the value AF_STYLE_UNASSIGNED means `uncovered glyph' */ FT_MEM_SET( globals->glyph_styles, AF_STYLE_UNASSIGNED, globals->glyph_count ); error = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); if ( error ) { /* * Ignore this error; we simply use the fallback style. * XXX: Shouldn't we rather disable hinting? */ error = FT_Err_Ok; goto Exit; } /* scan each style in a Unicode charmap */ for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ ) { AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss]; AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET[style_class->script]; AF_Script_UniRange range; if ( script_class->script_uni_ranges == NULL ) continue; /* * Scan all Unicode points in the range and set the corresponding * glyph style index. */ if ( style_class->coverage == AF_COVERAGE_DEFAULT ) { if ( style_class->script == globals->module->default_script ) dflt = ss; for ( range = script_class->script_uni_ranges; range->first != 0; range++ ) { FT_ULong charcode = range->first; FT_UInt gindex; gindex = FT_Get_Char_Index( face, charcode ); if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count && gstyles[gindex] == AF_STYLE_UNASSIGNED ) gstyles[gindex] = (FT_Byte)ss; for (;;) { charcode = FT_Get_Next_Char( face, charcode, &gindex ); if ( gindex == 0 || charcode > range->last ) break; if ( gindex < (FT_ULong)globals->glyph_count && gstyles[gindex] == AF_STYLE_UNASSIGNED ) gstyles[gindex] = (FT_Byte)ss; } } } else { /* get glyphs not directly addressable by cmap */ af_get_coverage( globals, style_class, gstyles ); } } /* handle the default OpenType features of the default script ... */ af_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles ); /* ... and the remaining default OpenType features */ for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ ) { AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss]; if ( ss != dflt && style_class->coverage == AF_COVERAGE_DEFAULT ) af_get_coverage( globals, style_class, gstyles ); } /* mark ASCII digits */ for ( i = 0x30; i <= 0x39; i++ ) { FT_UInt gindex = FT_Get_Char_Index( face, i ); if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count ) gstyles[gindex] |= AF_DIGIT; } Exit: /* * By default, all uncovered glyphs are set to the fallback style. * XXX: Shouldn't we disable hinting or do something similar? */ if ( globals->module->fallback_style != AF_STYLE_UNASSIGNED ) { FT_Long nn; for ( nn = 0; nn < globals->glyph_count; nn++ ) { if ( ( gstyles[nn] & ~AF_DIGIT ) == AF_STYLE_UNASSIGNED ) { gstyles[nn] &= ~AF_STYLE_UNASSIGNED; gstyles[nn] |= globals->module->fallback_style; } } } #ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE4(( "\n" "style coverage\n" "==============\n" "\n" )); for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ ) { AF_StyleClass style_class = AF_STYLE_CLASSES_GET[ss]; FT_UInt count = 0; FT_Long idx; FT_TRACE4(( "%s:\n", af_style_names[style_class->style] )); for ( idx = 0; idx < globals->glyph_count; idx++ ) { if ( ( gstyles[idx] & ~AF_DIGIT ) == style_class->style ) { if ( !( count % 10 ) ) FT_TRACE4(( " " )); FT_TRACE4(( " %d", idx )); count++; if ( !( count % 10 ) ) FT_TRACE4(( "\n" )); } } if ( !count ) FT_TRACE4(( " (none)\n" )); if ( count % 10 ) FT_TRACE4(( "\n" )); } #endif /* FT_DEBUG_LEVEL_TRACE */ FT_Set_Charmap( face, old_charmap ); return error; }
FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache, FTC_FaceID face_id, FT_Int cmap_index, FT_UInt32 char_code ) { FTC_Cache cache = FTC_CACHE( cmap_cache ); FTC_CMapQueryRec query; FTC_Node node; FT_Error error; FT_UInt gindex = 0; FT_Offset hash; FT_Int no_cmap_change = 0; if ( cmap_index < 0 ) { /* Treat a negative cmap index as a special value, meaning that you */ /* don't want to change the FT_Face's character map through this */ /* call. This can be useful if the face requester callback already */ /* sets the face's charmap to the appropriate value. */ no_cmap_change = 1; cmap_index = 0; } if ( !cache ) { FT_TRACE0(( "FTC_CMapCache_Lookup: bad arguments, returning 0\n" )); return 0; } query.face_id = face_id; query.cmap_index = (FT_UInt)cmap_index; query.char_code = char_code; hash = FTC_CMAP_HASH( face_id, (FT_UInt)cmap_index, char_code ); #if 1 FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query, node, error ); #else error = FTC_Cache_Lookup( cache, hash, &query, &node ); #endif if ( error ) goto Exit; FT_ASSERT( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first ) < FTC_CMAP_INDICES_MAX ); /* something rotten can happen with rogue clients */ if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >= FTC_CMAP_INDICES_MAX ) ) return 0; /* XXX: should return appropriate error */ gindex = FTC_CMAP_NODE( node )->indices[char_code - FTC_CMAP_NODE( node )->first]; if ( gindex == FTC_CMAP_UNKNOWN ) { FT_Face face; gindex = 0; error = FTC_Manager_LookupFace( cache->manager, FTC_CMAP_NODE( node )->face_id, &face ); if ( error ) goto Exit; if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps ) { FT_CharMap old, cmap = NULL; old = face->charmap; cmap = face->charmaps[cmap_index]; if ( old != cmap && !no_cmap_change ) FT_Set_Charmap( face, cmap ); gindex = FT_Get_Char_Index( face, char_code ); if ( old != cmap && !no_cmap_change ) FT_Set_Charmap( face, old ); } FTC_CMAP_NODE( node )->indices[char_code - FTC_CMAP_NODE( node )->first] = (FT_UShort)gindex; } Exit: return gindex; }