Home | History | Annotate | Download | only in fpdf_font
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../../include/fxge/fx_ge.h"
      8 #include "../../../include/fxge/fx_freetype.h"
      9 #include "ttgsubtable.h"
     10 CFX_GlyphMap::CFX_GlyphMap()
     11 {
     12 }
     13 CFX_GlyphMap::~CFX_GlyphMap()
     14 {
     15 }
     16 extern "C" {
     17     static int _CompareInt(const void* p1, const void* p2)
     18     {
     19         return (*(FX_DWORD*)p1) - (*(FX_DWORD*)p2);
     20     }
     21 };
     22 struct _IntPair {
     23     FX_INT32 key;
     24     FX_INT32 value;
     25 };
     26 void CFX_GlyphMap::SetAt(int key, int value)
     27 {
     28     FX_DWORD count = m_Buffer.GetSize() / sizeof(_IntPair);
     29     _IntPair* buf = (_IntPair*)m_Buffer.GetBuffer();
     30     _IntPair pair = {key, value};
     31     if (count == 0 || key > buf[count - 1].key) {
     32         m_Buffer.AppendBlock(&pair, sizeof(_IntPair));
     33         return;
     34     }
     35     int low = 0, high = count - 1;
     36     while (low <= high) {
     37         int mid = (low + high) / 2;
     38         if (buf[mid].key < key) {
     39             low = mid + 1;
     40         } else if (buf[mid].key > key) {
     41             high = mid - 1;
     42         } else {
     43             buf[mid].value = value;
     44             return;
     45         }
     46     }
     47     m_Buffer.InsertBlock(low * sizeof(_IntPair), &pair, sizeof(_IntPair));
     48 }
     49 FX_BOOL CFX_GlyphMap::Lookup(int key, int &value)
     50 {
     51     FX_LPVOID pResult = FXSYS_bsearch(&key, m_Buffer.GetBuffer(), m_Buffer.GetSize() / sizeof(_IntPair),
     52                                       sizeof(_IntPair), _CompareInt);
     53     if (pResult == NULL) {
     54         return FALSE;
     55     }
     56     value = ((FX_DWORD*)pResult)[1];
     57     return TRUE;
     58 }
     59 bool CFX_CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub)
     60 {
     61     header.Version = gsub[0] << 24 | gsub[1] << 16 | gsub[2] << 8 | gsub[3];
     62     if(header.Version != 0x00010000) {
     63         return false;
     64     }
     65     header.ScriptList  = gsub[4] << 8 | gsub[5];
     66     header.FeatureList = gsub[6] << 8 | gsub[7];
     67     header.LookupList  = gsub[8] << 8 | gsub[9];
     68     return Parse(
     69                &gsub[header.ScriptList],
     70                &gsub[header.FeatureList],
     71                &gsub[header.LookupList]);
     72 }
     73 bool CFX_CTTGSUBTable::GetVerticalGlyph(TT_uint32_t glyphnum, TT_uint32_t *vglyphnum)
     74 {
     75     TT_uint32_t tag[] = {
     76         (TT_uint8_t)'v' << 24 |
     77         (TT_uint8_t)'r' << 16 |
     78         (TT_uint8_t)'t' <<  8 |
     79         (TT_uint8_t)'2',
     80         (TT_uint8_t)'v' << 24 |
     81         (TT_uint8_t)'e' << 16 |
     82         (TT_uint8_t)'r' <<  8 |
     83         (TT_uint8_t)'t',
     84     };
     85     if (!m_bFeautureMapLoad) {
     86         for (int i = 0; i < ScriptList.ScriptCount; i++) {
     87             for (int j = 0; j <	(ScriptList.ScriptRecord + i)->Script.LangSysCount; ++j) {
     88                 for (int k = 0; k < ((ScriptList.ScriptRecord + i)->Script.LangSysRecord + j)->LangSys.FeatureCount; ++k) {
     89                     FX_DWORD index = *(((ScriptList.ScriptRecord + i)->Script.LangSysRecord + j)->LangSys.FeatureIndex + k);
     90                     if (FeatureList.FeatureRecord[index].FeatureTag == tag[0] || FeatureList.FeatureRecord[index].FeatureTag == tag[1]) {
     91                         FX_DWORD value;
     92                         if (!m_featureMap.Lookup(index, value)) {
     93                             m_featureMap.SetAt(index, index);
     94                         }
     95                     }
     96                 }
     97             }
     98         }
     99         if (!m_featureMap.GetStartPosition()) {
    100             for (int i = 0; i < FeatureList.FeatureCount; i ++) {
    101                 if (FeatureList.FeatureRecord[i].FeatureTag == tag[0] || FeatureList.FeatureRecord[i].FeatureTag == tag[1]) {
    102                     FX_DWORD value;
    103                     if (!m_featureMap.Lookup(i, value)) {
    104                         m_featureMap.SetAt(i, i);
    105                     }
    106                 }
    107             }
    108         }
    109         m_bFeautureMapLoad = TRUE;
    110     }
    111     FX_POSITION pos = m_featureMap.GetStartPosition();
    112     while (pos) {
    113         FX_DWORD index, value;
    114         m_featureMap.GetNextAssoc(pos, index, value);
    115         if(GetVerticalGlyphSub(glyphnum, vglyphnum,	&FeatureList.FeatureRecord[value].Feature)) {
    116             return true;
    117         }
    118     }
    119     return false;
    120 }
    121 bool CFX_CTTGSUBTable::GetVerticalGlyphSub(
    122     TT_uint32_t glyphnum,
    123     TT_uint32_t *vglyphnum,
    124     struct TFeature *Feature)
    125 {
    126     for(int i = 0; i < Feature->LookupCount; i++) {
    127         int index = Feature->LookupListIndex[i];
    128         if(index < 0 || LookupList.LookupCount < index) {
    129             continue;
    130         }
    131         if(LookupList.Lookup[index].LookupType == 1) {
    132             if(GetVerticalGlyphSub2(
    133                         glyphnum,
    134                         vglyphnum,
    135                         &LookupList.Lookup[index])) {
    136                 return true;
    137             }
    138         }
    139     }
    140     return false;
    141 }
    142 bool CFX_CTTGSUBTable::GetVerticalGlyphSub2(
    143     TT_uint32_t glyphnum,
    144     TT_uint32_t *vglyphnum,
    145     struct TLookup *Lookup)
    146 {
    147     for(int i = 0; i < Lookup->SubTableCount; i++) {
    148         switch(Lookup->SubTable[i]->SubstFormat) {
    149             case 1: {
    150                     TSingleSubstFormat1 *tbl1 = (TSingleSubstFormat1*)Lookup->SubTable[i];
    151                     if(GetCoverageIndex(tbl1->Coverage, glyphnum) >= 0) {
    152                         *vglyphnum = glyphnum + tbl1->DeltaGlyphID;
    153                         return true;
    154                     }
    155                     break;
    156                 }
    157             case 2: {
    158                     TSingleSubstFormat2 *tbl2 = (TSingleSubstFormat2*)Lookup->SubTable[i];
    159                     int index = -1;
    160                     index = GetCoverageIndex(tbl2->Coverage, glyphnum);
    161                     if(0 <= index && index < tbl2->GlyphCount) {
    162                         *vglyphnum = tbl2->Substitute[index];
    163                         return true;
    164                     }
    165                     break;
    166                 }
    167         }
    168     }
    169     return false;
    170 }
    171 int CFX_CTTGSUBTable::GetCoverageIndex(struct TCoverageFormatBase *Coverage, TT_uint32_t g)
    172 {
    173     int i = 0;
    174     if(Coverage == NULL) {
    175         return -1;
    176     }
    177     switch(Coverage->CoverageFormat) {
    178         case 1: {
    179                 TCoverageFormat1 *c1 = (TCoverageFormat1*)Coverage;
    180                 for(i = 0; i < c1->GlyphCount; i++) {
    181                     if((TT_uint32_t)c1->GlyphArray[i] == g) {
    182                         return i;
    183                     }
    184                 }
    185                 return -1;
    186             }
    187         case 2: {
    188                 TCoverageFormat2 *c2 = (TCoverageFormat2*)Coverage;
    189                 for(i = 0; i < c2->RangeCount; i++) {
    190                     TT_uint32_t s = c2->RangeRecord[i].Start;
    191                     TT_uint32_t e = c2->RangeRecord[i].End;
    192                     TT_uint32_t si = c2->RangeRecord[i].StartCoverageIndex;
    193                     if (s <= g && g <= e) {
    194                         return si + g - s;
    195                     }
    196                 }
    197                 return -1;
    198             }
    199     }
    200     return -1;
    201 }
    202 bool CFX_CTTGSUBTable::Parse(
    203     FT_Bytes scriptlist,
    204     FT_Bytes featurelist,
    205     FT_Bytes lookuplist)
    206 {
    207     ParseScriptList(scriptlist, &ScriptList);
    208     ParseFeatureList(featurelist, &FeatureList);
    209     ParseLookupList(lookuplist, &LookupList);
    210     return true;
    211 }
    212 void CFX_CTTGSUBTable::ParseScriptList(FT_Bytes raw, struct TScriptList *rec)
    213 {
    214     int i;
    215     FT_Bytes sp = raw;
    216     rec->ScriptCount = GetUInt16(sp);
    217     if(rec->ScriptCount <= 0) {
    218         return;
    219     }
    220     rec->ScriptRecord = new struct TScriptRecord[rec->ScriptCount];
    221     for(i = 0; i < rec->ScriptCount; i++) {
    222         rec->ScriptRecord[i].ScriptTag = GetUInt32(sp);
    223         TT_uint16_t offset = GetUInt16(sp);
    224         ParseScript(
    225             &raw[offset],
    226             &rec->ScriptRecord[i].Script);
    227     }
    228 }
    229 void CFX_CTTGSUBTable::ParseScript(FT_Bytes raw, struct TScript *rec)
    230 {
    231     int i;
    232     FT_Bytes sp = raw;
    233     rec->DefaultLangSys = GetUInt16(sp);
    234     rec->LangSysCount = GetUInt16(sp);
    235     if(rec->LangSysCount <= 0) {
    236         return;
    237     }
    238     rec->LangSysRecord = new struct TLangSysRecord[rec->LangSysCount];
    239     for(i = 0; i < rec->LangSysCount; i++) {
    240         rec->LangSysRecord[i].LangSysTag = GetUInt32(sp);
    241         TT_uint16_t offset = GetUInt16(sp);
    242         ParseLangSys(
    243             &raw[offset],
    244             &rec->LangSysRecord[i].LangSys);
    245     }
    246 }
    247 void CFX_CTTGSUBTable::ParseLangSys(FT_Bytes raw, struct TLangSys *rec)
    248 {
    249     FT_Bytes sp = raw;
    250     rec->LookupOrder = GetUInt16(sp);
    251     rec->ReqFeatureIndex = GetUInt16(sp);
    252     rec->FeatureCount = GetUInt16(sp);
    253     if(rec->FeatureCount <= 0) {
    254         return;
    255     }
    256     rec->FeatureIndex = new TT_uint16_t[rec->FeatureCount];
    257     FXSYS_memset32(rec->FeatureIndex, 0, sizeof(TT_uint16_t) * rec->FeatureCount);
    258     for (int i = 0; i < rec->FeatureCount; ++i) {
    259         rec->FeatureIndex[i] = GetUInt16(sp);
    260     }
    261 }
    262 void CFX_CTTGSUBTable::ParseFeatureList(FT_Bytes raw, TFeatureList *rec)
    263 {
    264     int i;
    265     FT_Bytes sp = raw;
    266     rec->FeatureCount = GetUInt16(sp);
    267     if(rec->FeatureCount <= 0) {
    268         return;
    269     }
    270     rec->FeatureRecord = new struct TFeatureRecord[rec->FeatureCount];
    271     for(i = 0; i < rec->FeatureCount; i++) {
    272         rec->FeatureRecord[i].FeatureTag = GetUInt32(sp);
    273         TT_uint16_t offset = GetUInt16(sp);
    274         ParseFeature(
    275             &raw[offset],
    276             &rec->FeatureRecord[i].Feature);
    277     }
    278 }
    279 void CFX_CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeature *rec)
    280 {
    281     int i;
    282     FT_Bytes sp = raw;
    283     rec->FeatureParams = GetUInt16(sp);
    284     rec->LookupCount = GetUInt16(sp);
    285     if(rec->LookupCount <= 0) {
    286         return;
    287     }
    288     rec->LookupListIndex = new TT_uint16_t[rec->LookupCount];
    289     for(i = 0; i < rec->LookupCount; i++) {
    290         rec->LookupListIndex[i] = GetUInt16(sp);
    291     }
    292 }
    293 void CFX_CTTGSUBTable::ParseLookupList(FT_Bytes raw, TLookupList *rec)
    294 {
    295     int i;
    296     FT_Bytes sp = raw;
    297     rec->LookupCount = GetUInt16(sp);
    298     if(rec->LookupCount <= 0) {
    299         return;
    300     }
    301     rec->Lookup = new struct TLookup[rec->LookupCount];
    302     for(i = 0; i < rec->LookupCount; i++) {
    303         TT_uint16_t offset = GetUInt16(sp);
    304         ParseLookup(
    305             &raw[offset],
    306             &rec->Lookup[i]);
    307     }
    308 }
    309 void CFX_CTTGSUBTable::ParseLookup(FT_Bytes raw, TLookup *rec)
    310 {
    311     int i;
    312     FT_Bytes sp = raw;
    313     rec->LookupType = GetUInt16(sp);
    314     rec->LookupFlag = GetUInt16(sp);
    315     rec->SubTableCount = GetUInt16(sp);
    316     if(rec->SubTableCount <= 0) {
    317         return;
    318     }
    319     rec->SubTable = new struct TSubTableBase*[rec->SubTableCount];
    320     for(i = 0; i < rec->SubTableCount; i++) {
    321         rec->SubTable[i] = NULL;
    322     }
    323     if(rec->LookupType != 1) {
    324         return;
    325     }
    326     for(i = 0; i < rec->SubTableCount; i++) {
    327         TT_uint16_t offset = GetUInt16(sp);
    328         ParseSingleSubst(
    329             &raw[offset],
    330             &rec->SubTable[i]);
    331     }
    332 }
    333 void CFX_CTTGSUBTable::ParseCoverage(FT_Bytes raw, TCoverageFormatBase **rec)
    334 {
    335     FT_Bytes sp = raw;
    336     TT_uint16_t Format = GetUInt16(sp);
    337     switch(Format) {
    338         case 1:
    339             *rec = new TCoverageFormat1();
    340             ParseCoverageFormat1(raw, (TCoverageFormat1*)*rec);
    341             break;
    342         case 2:
    343             *rec = new TCoverageFormat2();
    344             ParseCoverageFormat2(raw, (TCoverageFormat2*)*rec);
    345             break;
    346     }
    347 }
    348 void CFX_CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw, TCoverageFormat1 *rec)
    349 {
    350     int i;
    351     FT_Bytes sp = raw;
    352     GetUInt16(sp);
    353     rec->GlyphCount = GetUInt16(sp);
    354     if(rec->GlyphCount <= 0) {
    355         return;
    356     }
    357     rec->GlyphArray = new TT_uint16_t[rec->GlyphCount];
    358     for(i = 0; i < rec->GlyphCount; i++) {
    359         rec->GlyphArray[i] = GetUInt16(sp);
    360     }
    361 }
    362 void CFX_CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw, TCoverageFormat2 *rec)
    363 {
    364     int i;
    365     FT_Bytes sp = raw;
    366     GetUInt16(sp);
    367     rec->RangeCount = GetUInt16(sp);
    368     if(rec->RangeCount <= 0) {
    369         return;
    370     }
    371     rec->RangeRecord = new TRangeRecord[rec->RangeCount];
    372     for(i = 0; i < rec->RangeCount; i++) {
    373         rec->RangeRecord[i].Start = GetUInt16(sp);
    374         rec->RangeRecord[i].End = GetUInt16(sp);
    375         rec->RangeRecord[i].StartCoverageIndex = GetUInt16(sp);
    376     }
    377 }
    378 void CFX_CTTGSUBTable::ParseSingleSubst(FT_Bytes raw, TSubTableBase **rec)
    379 {
    380     FT_Bytes sp = raw;
    381     TT_uint16_t Format = GetUInt16(sp);
    382     switch(Format) {
    383         case 1:
    384             *rec = new TSingleSubstFormat1();
    385             ParseSingleSubstFormat1(raw, (TSingleSubstFormat1*)*rec);
    386             break;
    387         case 2:
    388             *rec = new TSingleSubstFormat2();
    389             ParseSingleSubstFormat2(raw, (TSingleSubstFormat2*)*rec);
    390             break;
    391     }
    392 }
    393 void CFX_CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw, TSingleSubstFormat1 *rec)
    394 {
    395     FT_Bytes sp = raw;
    396     GetUInt16(sp);
    397     TT_uint16_t offset = GetUInt16(sp);
    398     ParseCoverage(
    399         &raw[offset],
    400         &rec->Coverage);
    401     rec->DeltaGlyphID = GetInt16(sp);
    402 }
    403 void CFX_CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw, TSingleSubstFormat2 *rec)
    404 {
    405     int i;
    406     FT_Bytes sp = raw;
    407     GetUInt16(sp);
    408     TT_uint16_t offset = GetUInt16(sp);
    409     ParseCoverage(
    410         &raw[offset],
    411         &rec->Coverage);
    412     rec->GlyphCount = GetUInt16(sp);
    413     if(rec->GlyphCount <= 0) {
    414         return;
    415     }
    416     rec->Substitute = new TT_uint16_t[rec->GlyphCount];
    417     for(i = 0; i < rec->GlyphCount; i++) {
    418         rec->Substitute[i] = GetUInt16(sp);
    419     }
    420 }
    421 FX_BOOL CFX_GSUBTable::GetVerticalGlyph(FX_DWORD glyphnum, FX_DWORD* vglyphnum)
    422 {
    423     return m_GsubImp.GetVerticalGlyph(glyphnum, vglyphnum);
    424 }
    425 IFX_GSUBTable* FXGE_CreateGSUBTable(CFX_Font* pFont)
    426 {
    427     if (!pFont) {
    428         return NULL;
    429     }
    430     if (NULL == pFont->m_pGsubData) {
    431         unsigned long length = 0;
    432         int error = FXFT_Load_Sfnt_Table(pFont->m_Face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, NULL, &length);
    433         if (!error) {
    434             pFont->m_pGsubData = (unsigned char*)FX_Alloc(FX_BYTE, length);
    435         }
    436         if (!pFont->m_pGsubData) {
    437             return NULL;
    438         }
    439     }
    440     int error = FXFT_Load_Sfnt_Table(pFont->m_Face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, pFont->m_pGsubData, NULL);
    441     if (!error && pFont->m_pGsubData) {
    442         CFX_GSUBTable* pGsubTable = FX_NEW CFX_GSUBTable;
    443         if (!pGsubTable) {
    444             return NULL;
    445         }
    446         if (pGsubTable->m_GsubImp.LoadGSUBTable((FT_Bytes)pFont->m_pGsubData)) {
    447             return pGsubTable;
    448         }
    449         delete pGsubTable;
    450     }
    451     return NULL;
    452 }
    453