// static IFX_GSUBTable* IFX_GSUBTable::Create(CFX_Font* pFont) { if (!pFont) { return NULL; } if (!pFont->GetSubData()) { unsigned long length = 0; int error = FXFT_Load_Sfnt_Table( pFont->GetFace(), FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, NULL, &length); if (!error) { pFont->SetSubData((uint8_t*)FX_Alloc(uint8_t, length)); } if (!pFont->GetSubData()) { return NULL; } } int error = FXFT_Load_Sfnt_Table(pFont->GetFace(), FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, pFont->GetSubData(), NULL); if (!error && pFont->GetSubData()) { nonstd::unique_ptr<CFX_GSUBTable> pGsubTable(new CFX_GSUBTable); if (pGsubTable->m_GsubImp.LoadGSUBTable((FT_Bytes)pFont->GetSubData())) { return pGsubTable.release(); } } return NULL; }
IFX_GSUBTable* FXGE_CreateGSUBTable(CFX_Font* pFont) { if (!pFont) { return NULL; } if (NULL == pFont->m_pGsubData) { unsigned long length = 0; int error = FXFT_Load_Sfnt_Table(pFont->m_Face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, NULL, &length); if (!error) { pFont->m_pGsubData = (unsigned char*)FX_Alloc(FX_BYTE, length); } if (!pFont->m_pGsubData) { return NULL; } } int error = FXFT_Load_Sfnt_Table(pFont->m_Face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, pFont->m_pGsubData, NULL); if (!error && pFont->m_pGsubData) { CFX_GSUBTable* pGsubTable = FX_NEW CFX_GSUBTable; if (!pGsubTable) { return NULL; } if (pGsubTable->m_GsubImp.LoadGSUBTable((FT_Bytes)pFont->m_pGsubData)) { return pGsubTable; } pGsubTable->Release(); } return NULL; }
int CPDF_CIDFont::GetGlyphIndex(uint32_t unicode, bool* pVertGlyph) { if (pVertGlyph) *pVertGlyph = false; FXFT_Face face = m_Font.GetFace(); int index = FXFT_Get_Char_Index(face, unicode); if (unicode == 0x2502) return index; if (!index || !IsVertWriting()) return index; if (m_pTTGSUBTable) return GetVerticalGlyph(index, pVertGlyph); if (!m_Font.GetSubData()) { unsigned long length = 0; int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, nullptr, &length); if (!error) m_Font.SetSubData(FX_Alloc(uint8_t, length)); } int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, m_Font.GetSubData(), nullptr); if (error || !m_Font.GetSubData()) return index; m_pTTGSUBTable = pdfium::MakeUnique<CFX_CTTGSUBTable>(); m_pTTGSUBTable->LoadGSUBTable((FT_Bytes)m_Font.GetSubData()); return GetVerticalGlyph(index, pVertGlyph); }
static PangoOTRuleset * get_gpos_ruleset (FT_Face face, const PangoIndicInfo *indic_info) { PangoOTInfo *info = pango_ot_info_get (face); GQuark ruleset_quark = g_quark_from_string (indic_info->gposQuarkName); PangoOTRuleset *ruleset; if (!info) return NULL; ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark); if (!ruleset) { guint script_index; ruleset = pango_ot_ruleset_new (info); if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GPOS, indic_info->scriptTag, &script_index)) { maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','m'), blwm); maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','m'), abvm); maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('d','i','s','t'), dist); } g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset, (GDestroyNotify)g_object_unref); } return ruleset; }
NSFonts::IFontFile* NSFonts::IFontManager::LoadFontFile(NSFonts::CLibrary& library, NSFonts::IFontStream* pStreamI, int lFaceIndex) { CFontStream* pStream = (CFontStream*)pStreamI; FT_Open_Args oOpenArgs; oOpenArgs.flags = FT_OPEN_MEMORY | FT_OPEN_PARAMS; oOpenArgs.memory_base = pStream->m_pData; oOpenArgs.memory_size = pStream->m_lSize; FT_Parameter *pParams = (FT_Parameter *)::malloc( sizeof(FT_Parameter) * 4 ); pParams[0].tag = FT_MAKE_TAG( 'i', 'g', 'p', 'f' ); pParams[0].data = NULL; pParams[1].tag = FT_MAKE_TAG( 'i', 'g', 'p', 's' ); pParams[1].data = NULL; pParams[2].tag = FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY; pParams[2].data = NULL; pParams[3].tag = FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY; pParams[3].data = NULL; oOpenArgs.params = pParams; oOpenArgs.num_params = 4; FT_Face pFace; if ( FT_Open_Face( library.m_internal->m_library, &oOpenArgs, lFaceIndex, &pFace ) ) return NULL; ::free(pParams); CFontFile* pFont = new CFontFile(); pFont->m_lFaceIndex = lFaceIndex; pFont->m_lUnits_Per_Em = pFace->units_per_EM; pFont->m_lAscender = pFace->ascender; pFont->m_lDescender = pFace->descender; pFont->m_lLineHeight = pFace->height; pFont->m_nNum_charmaps = pFace->num_charmaps; pFont->m_pFace = pFace; pFont->LoadDefaultCharAndSymbolicCmapIndex(); if (FT_Set_Char_Size(pFace, 0, (FT_F26Dot6)(pFont->m_dSize * 64), 0, 0)) { FT_Done_Face(pFace); delete pFont; return NULL; } pFont->ResetTextMatrix(); pFont->ResetFontMatrix(); return pFont; }
void ttfInitMAXP(TTFontPtr font) { ULONG tag = FT_MAKE_TAG ('m', 'a', 'x', 'p'); TableDirPtr ptd; if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) { font->maxp = XCALLOC1 (MAXP); ttfLoadMAXP(font->fp,font->maxp,ptd->offset); } }
void ttfInitLTSH(TTFontPtr font) { ULONG tag = FT_MAKE_TAG ('L', 'T', 'S', 'H'); TableDirPtr ptd; if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) { font->ltsh = XCALLOC1 (LTSH); ttfLoadLTSH(font->fp,font->ltsh,ptd->offset); } }
void ttfInitGASP(TTFontPtr font) { ULONG tag = FT_MAKE_TAG ('g', 'a', 's', 'p'); TableDirPtr ptd; if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) { font->gasp = XCALLOC1 (GASP); ttfLoadGASP(font->fp,font->gasp,ptd->offset); } }
void ttfInitCVT(TTFontPtr font) { ULONG tag = FT_MAKE_TAG ('c', 'v', 't', ' '); TableDirPtr ptd; if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) { font->cvtLength = ptd->length / sizeof(FWord); font->cvt = XCALLOC (font->cvtLength, FWord); ttfLoadCVT(font->fp,font->cvt,font->cvtLength,ptd->offset); } }
/* Caution: Because of interdependency between tables, * table vhea and maxp should be well initalized before * ttfInitVMTX has been called */ void ttfInitVMTX(TTFontPtr font) { ULONG tag = FT_MAKE_TAG ('v', 'm', 't', 'x'); TableDirPtr ptd; if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) { font->vmtx = XCALLOC1 (VMTX); font->vmtx->numOfLongVerMetrics = font->vhea->numOfLongVerMetrics; font->vmtx->numOfTSB = font->maxp->numGlyphs - font->vhea->numOfLongVerMetrics; ttfLoadVMTX(font->fp,font->vmtx,ptd->offset); } }
static char* getTable(char* t, FT_Face face) { FT_ULong tag = FT_MAKE_TAG(t[0], t[1], t[2], t[3]); FT_ULong length = 0; int error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &length); if (error) { qDebug("genft: cannot load table LILC"); exit(-3); } FT_Byte* buffer = (FT_Byte*)malloc(length + 1); error = FT_Load_Sfnt_Table(face, tag, 0, buffer, &length); buffer[length] = 0; if (error) { qDebug("genft: cannot load font table LILC"); exit(4); } return (char*)buffer; }
void KernFeature::makeCoverage() { if ( GPOSTableRaw.isEmpty() ) return; quint16 FeatureList_Offset= toUint16 ( 6 ); quint16 LookupList_Offset = toUint16 ( 8 ); // Find the offsets of the kern feature tables quint16 FeatureCount = toUint16 ( FeatureList_Offset );; QList<quint16> FeatureKern_Offset; for ( quint16 FeatureRecord ( 0 ); FeatureRecord < FeatureCount; ++ FeatureRecord ) { int rawIdx ( FeatureList_Offset + 2 + ( 6 * FeatureRecord ) ); quint32 tag ( FT_MAKE_TAG ( GPOSTableRaw.at ( rawIdx ), GPOSTableRaw.at ( rawIdx + 1 ), GPOSTableRaw.at ( rawIdx + 2 ), GPOSTableRaw.at ( rawIdx + 3 ) ) ); if ( tag == TTAG_kern ) { FeatureKern_Offset << ( toUint16 ( rawIdx + 4 ) + FeatureList_Offset ); } } // Extract indices of lookups for feture kern QList<quint16> LookupListIndex; foreach ( quint16 kern, FeatureKern_Offset ) { quint16 LookupCount ( toUint16 ( kern + 2 ) ); for ( int llio ( 0 ) ; llio < LookupCount; ++llio ) { quint16 Idx ( toUint16 ( kern + 4 + ( llio * 2 ) ) ); if ( !LookupListIndex.contains ( Idx ) ) { LookupListIndex <<Idx ; } } }
static void readGPOSTable(SFFontRef sfFont) { FT_ULong length = 0; FT_Tag tag; FT_Byte *buffer; FT_Error error; tag = FT_MAKE_TAG('G', 'P', 'O', 'S'); error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, NULL, &length); if (error) return; buffer = malloc(length); error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, buffer, &length); if (!error) { SFReadGPOS(buffer, &sfFont->_gpos); sfFont->_availableFontTables |= itGPOS; } free(buffer); }
static void readCMAPTable(SFFontRef sfFont) { FT_ULong length = 0; FT_Tag tag; FT_Byte *buffer; FT_Error error; tag = FT_MAKE_TAG('c', 'm', 'a', 'p'); error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, NULL, &length); if (error) return; buffer = malloc(length); error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, buffer, &length); if (!error) { SFReadCMAP(buffer, &sfFont->_cmap, length); sfFont->_availableFontTables |= itCMAP; } free(buffer); }
static void readGSUBTable(SFFontRef sfFont) { FT_ULong length = 0; FT_Tag tag; FT_Byte *buffer; FT_Error error; tag = FT_MAKE_TAG('G', 'S', 'U', 'B'); error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, NULL, &length); if (error) return; buffer = malloc(length); error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, buffer, &length); if (!error) { SFReadGSUB(buffer, &sfFont->_tables->_gsub); sfFont->_tables->_availableTables |= itGSUB; } free(buffer); }
static PangoOTRuleset * get_gsub_ruleset (FT_Face face, const PangoIndicInfo *indic_info) { PangoOTInfo *info = pango_ot_info_get (face); GQuark ruleset_quark = g_quark_from_string (indic_info->gsubQuarkName); PangoOTRuleset *ruleset; if (!info) return NULL; ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark); if (!ruleset) { guint script_index; ruleset = pango_ot_ruleset_new (info); if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GSUB, indic_info->scriptTag, &script_index)) { maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('i','n','i','t'), init); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('n','u','k','t'), nukt); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','k','h','n'), akhn); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('r','p','h','f'), rphf); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','f'), blwf); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('h','a','l','f'), half); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','s','t','f'), pstf); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('v','a','t','u'), vatu); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','r','e','s'), pres); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','s'), blws); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','s'), abvs); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','s','t','s'), psts); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('h','a','l','n'), haln); } g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset, (GDestroyNotify)g_object_unref); } return ruleset; }
static PangoOTRuleset * get_ruleset (FT_Face face) { PangoOTRuleset *ruleset; static GQuark ruleset_quark = 0; PangoOTInfo *info = pango_ot_info_get (face); if (!ruleset_quark) ruleset_quark = g_quark_from_string ("pango-khmer-ruleset"); if (!info) return NULL; ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark); if (!ruleset) { PangoOTTag khmer_tag = FT_MAKE_TAG ('k', 'h', 'm', 'r'); guint script_index; ruleset = pango_ot_ruleset_new (info); if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GSUB, khmer_tag, &script_index)) { maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','r','e','f'), pref); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','f'), blwf); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','f'), abvf); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','s','t','f'), pstf); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','r','e','s'), pres); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','s'), blws); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','s'), abvs); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','s','t','s'), psts); maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','l','i','g'), clig); } if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GPOS, khmer_tag, &script_index)) { maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('d','i','s','t'), dist); maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','m'), blwm); maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','m'), abvm); maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','k','m','k'), mkmk); } g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset, (GDestroyNotify)g_object_unref); } return ruleset; }
/* synthesized into a TTC with one offset table. */ static FT_Error sfnt_open_font( FT_Stream stream, TT_Face face ) { FT_Memory memory = stream->memory; FT_Error error; FT_ULong tag, offset; static const FT_Frame_Field ttc_header_fields[] = { #undef FT_STRUCTURE #define FT_STRUCTURE TTC_HeaderRec FT_FRAME_START( 8 ), FT_FRAME_LONG( version ), FT_FRAME_LONG( count ), FT_FRAME_END }; face->ttc_header.tag = 0; face->ttc_header.version = 0; face->ttc_header.count = 0; offset = FT_STREAM_POS(); if ( FT_READ_ULONG( tag ) ) return error; if ( tag != 0x00010000UL && tag != TTAG_ttcf && tag != FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) && tag != TTAG_true && tag != 0x00020000UL ) return SFNT_Err_Unknown_File_Format; face->ttc_header.tag = TTAG_ttcf; if ( tag == TTAG_ttcf ) { FT_Int n; FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) return error; /* now read the offsets of each font in the file */ if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) return error; if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) return error; for ( n = 0; n < face->ttc_header.count; n++ ) face->ttc_header.offsets[n] = FT_GET_ULONG(); FT_FRAME_EXIT(); } else { FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); face->ttc_header.version = 1 << 16; face->ttc_header.count = 1; if ( FT_NEW( face->ttc_header.offsets) ) return error; face->ttc_header.offsets[0] = offset; } return error; }
static FT_Error check_table_dir( SFNT_Header sfnt, FT_Stream stream ) { FT_Error error; FT_UInt nn; FT_UInt has_head = 0, has_sing = 0, has_meta = 0; FT_ULong offset = sfnt->offset + 12; const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' ); const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' ); static const FT_Frame_Field table_dir_entry_fields[] = { #undef FT_STRUCTURE #define FT_STRUCTURE TT_TableRec FT_FRAME_START( 16 ), FT_FRAME_ULONG( Tag ), FT_FRAME_ULONG( CheckSum ), FT_FRAME_ULONG( Offset ), FT_FRAME_ULONG( Length ), FT_FRAME_END }; if ( sfnt->num_tables == 0 || offset + sfnt->num_tables * 16 > stream->size ) return SFNT_Err_Unknown_File_Format; if ( FT_STREAM_SEEK( offset ) ) return error; for ( nn = 0; nn < sfnt->num_tables; nn++ ) { TT_TableRec table; if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) return error; if ( table.Offset + table.Length > stream->size && table.Tag != glyx_tag && table.Tag != locx_tag ) return SFNT_Err_Unknown_File_Format; if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed ) { FT_UInt32 magic; #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS if ( table.Tag == TTAG_head ) #endif has_head = 1; /* * The table length should be 0x36, but certain font tools make it * 0x38, so we will just check that it is greater. * * Note that according to the specification, the table must be * padded to 32-bit lengths, but this doesn't apply to the value of * its `Length' field! * */ if ( table.Length < 0x36 ) return SFNT_Err_Unknown_File_Format; if ( FT_STREAM_SEEK( table.Offset + 12 ) || FT_READ_ULONG( magic ) ) return error; if ( magic != 0x5F0F3CF5UL ) return SFNT_Err_Unknown_File_Format; if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) ) return error; } else if ( table.Tag == TTAG_SING ) has_sing = 1; else if ( table.Tag == TTAG_META ) has_meta = 1; } /* if `sing' and `meta' tables are present, there is no `head' table */ if ( has_head || ( has_sing && has_meta ) ) return SFNT_Err_Ok; else return SFNT_Err_Unknown_File_Format; }