Home | History | Annotate | Download | only in 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 "core/fpdfapi/font/ttgsubtable.h"
      8 
      9 #include "core/fxge/fx_freetype.h"
     10 #include "third_party/base/ptr_util.h"
     11 #include "third_party/base/stl_util.h"
     12 
     13 CFX_GlyphMap::CFX_GlyphMap() {}
     14 
     15 CFX_GlyphMap::~CFX_GlyphMap() {}
     16 
     17 extern "C" {
     18 static int _CompareInt(const void* p1, const void* p2) {
     19   return (*(uint32_t*)p1) - (*(uint32_t*)p2);
     20 }
     21 };
     22 
     23 struct _IntPair {
     24   int32_t key;
     25   int32_t value;
     26 };
     27 
     28 void CFX_GlyphMap::SetAt(int key, int value) {
     29   uint32_t count = m_Buffer.GetSize() / sizeof(_IntPair);
     30   _IntPair* buf = (_IntPair*)m_Buffer.GetBuffer();
     31   _IntPair pair = {key, value};
     32   if (count == 0 || key > buf[count - 1].key) {
     33     m_Buffer.AppendBlock(&pair, sizeof(_IntPair));
     34     return;
     35   }
     36   int low = 0, high = count - 1;
     37   while (low <= high) {
     38     int mid = (low + high) / 2;
     39     if (buf[mid].key < key) {
     40       low = mid + 1;
     41     } else if (buf[mid].key > key) {
     42       high = mid - 1;
     43     } else {
     44       buf[mid].value = value;
     45       return;
     46     }
     47   }
     48   m_Buffer.InsertBlock(low * sizeof(_IntPair), &pair, sizeof(_IntPair));
     49 }
     50 
     51 bool CFX_GlyphMap::Lookup(int key, int& value) {
     52   void* pResult = FXSYS_bsearch(&key, m_Buffer.GetBuffer(),
     53                                 m_Buffer.GetSize() / sizeof(_IntPair),
     54                                 sizeof(_IntPair), _CompareInt);
     55   if (!pResult) {
     56     return false;
     57   }
     58   value = ((uint32_t*)pResult)[1];
     59   return true;
     60 }
     61 
     62 CFX_CTTGSUBTable::CFX_CTTGSUBTable()
     63     : m_bFeautureMapLoad(false), loaded(false) {}
     64 
     65 CFX_CTTGSUBTable::CFX_CTTGSUBTable(FT_Bytes gsub)
     66     : m_bFeautureMapLoad(false), loaded(false) {
     67   LoadGSUBTable(gsub);
     68 }
     69 
     70 CFX_CTTGSUBTable::~CFX_CTTGSUBTable() {}
     71 
     72 bool CFX_CTTGSUBTable::IsOk() const {
     73   return loaded;
     74 }
     75 
     76 bool CFX_CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub) {
     77   header.Version = gsub[0] << 24 | gsub[1] << 16 | gsub[2] << 8 | gsub[3];
     78   if (header.Version != 0x00010000) {
     79     return false;
     80   }
     81   header.ScriptList = gsub[4] << 8 | gsub[5];
     82   header.FeatureList = gsub[6] << 8 | gsub[7];
     83   header.LookupList = gsub[8] << 8 | gsub[9];
     84   return Parse(&gsub[header.ScriptList], &gsub[header.FeatureList],
     85                &gsub[header.LookupList]);
     86 }
     87 
     88 bool CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum,
     89                                         uint32_t* vglyphnum) {
     90   uint32_t tag[] = {
     91       (uint8_t)'v' << 24 | (uint8_t)'r' << 16 | (uint8_t)'t' << 8 |
     92           (uint8_t)'2',
     93       (uint8_t)'v' << 24 | (uint8_t)'e' << 16 | (uint8_t)'r' << 8 |
     94           (uint8_t)'t',
     95   };
     96   if (!m_bFeautureMapLoad) {
     97     for (const auto& script : ScriptList.ScriptRecords) {
     98       for (const auto& record : script.Script.LangSysRecords) {
     99         for (const auto& index : record.LangSys.FeatureIndices) {
    100           if (FeatureList.FeatureRecords[index].FeatureTag == tag[0] ||
    101               FeatureList.FeatureRecords[index].FeatureTag == tag[1]) {
    102             m_featureSet.insert(index);
    103           }
    104         }
    105       }
    106     }
    107     if (m_featureSet.empty()) {
    108       int i = 0;
    109       for (const auto& feature : FeatureList.FeatureRecords) {
    110         if (feature.FeatureTag == tag[0] || feature.FeatureTag == tag[1])
    111           m_featureSet.insert(i);
    112         ++i;
    113       }
    114     }
    115     m_bFeautureMapLoad = true;
    116   }
    117   for (const auto& item : m_featureSet) {
    118     if (GetVerticalGlyphSub(glyphnum, vglyphnum,
    119                             &FeatureList.FeatureRecords[item].Feature)) {
    120       return true;
    121     }
    122   }
    123   return false;
    124 }
    125 
    126 bool CFX_CTTGSUBTable::GetVerticalGlyphSub(uint32_t glyphnum,
    127                                            uint32_t* vglyphnum,
    128                                            TFeature* Feature) {
    129   for (int index : Feature->LookupListIndices) {
    130     if (index < 0 || index >= pdfium::CollectionSize<int>(LookupList.Lookups))
    131       continue;
    132 
    133     if (LookupList.Lookups[index].LookupType == 1 &&
    134         GetVerticalGlyphSub2(glyphnum, vglyphnum, &LookupList.Lookups[index])) {
    135       return true;
    136     }
    137   }
    138   return false;
    139 }
    140 
    141 bool CFX_CTTGSUBTable::GetVerticalGlyphSub2(uint32_t glyphnum,
    142                                             uint32_t* vglyphnum,
    143                                             TLookup* Lookup) {
    144   for (const auto& subTable : Lookup->SubTables) {
    145     switch (subTable->SubstFormat) {
    146       case 1: {
    147         auto tbl1 = static_cast<TSingleSubstFormat1*>(subTable.get());
    148         if (GetCoverageIndex(tbl1->Coverage.get(), glyphnum) >= 0) {
    149           *vglyphnum = glyphnum + tbl1->DeltaGlyphID;
    150           return true;
    151         }
    152         break;
    153       }
    154       case 2: {
    155         auto tbl2 = static_cast<TSingleSubstFormat2*>(subTable.get());
    156         int index = GetCoverageIndex(tbl2->Coverage.get(), glyphnum);
    157         if (index >= 0 &&
    158             index < pdfium::CollectionSize<int>(tbl2->Substitutes)) {
    159           *vglyphnum = tbl2->Substitutes[index];
    160           return true;
    161         }
    162         break;
    163       }
    164     }
    165   }
    166   return false;
    167 }
    168 
    169 int CFX_CTTGSUBTable::GetCoverageIndex(TCoverageFormatBase* Coverage,
    170                                        uint32_t g) const {
    171   if (!Coverage)
    172     return -1;
    173 
    174   switch (Coverage->CoverageFormat) {
    175     case 1: {
    176       int i = 0;
    177       TCoverageFormat1* c1 = (TCoverageFormat1*)Coverage;
    178       for (const auto& glyph : c1->GlyphArray) {
    179         if (static_cast<uint32_t>(glyph) == g)
    180           return i;
    181         ++i;
    182       }
    183       return -1;
    184     }
    185     case 2: {
    186       TCoverageFormat2* c2 = (TCoverageFormat2*)Coverage;
    187       for (const auto& rangeRec : c2->RangeRecords) {
    188         uint32_t s = rangeRec.Start;
    189         uint32_t e = rangeRec.End;
    190         uint32_t si = rangeRec.StartCoverageIndex;
    191         if (s <= g && g <= e)
    192           return si + g - s;
    193       }
    194       return -1;
    195     }
    196   }
    197   return -1;
    198 }
    199 
    200 uint8_t CFX_CTTGSUBTable::GetUInt8(FT_Bytes& p) const {
    201   uint8_t ret = p[0];
    202   p += 1;
    203   return ret;
    204 }
    205 
    206 int16_t CFX_CTTGSUBTable::GetInt16(FT_Bytes& p) const {
    207   uint16_t ret = p[0] << 8 | p[1];
    208   p += 2;
    209   return *(int16_t*)&ret;
    210 }
    211 
    212 uint16_t CFX_CTTGSUBTable::GetUInt16(FT_Bytes& p) const {
    213   uint16_t ret = p[0] << 8 | p[1];
    214   p += 2;
    215   return ret;
    216 }
    217 
    218 int32_t CFX_CTTGSUBTable::GetInt32(FT_Bytes& p) const {
    219   uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
    220   p += 4;
    221   return *(int32_t*)&ret;
    222 }
    223 
    224 uint32_t CFX_CTTGSUBTable::GetUInt32(FT_Bytes& p) const {
    225   uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
    226   p += 4;
    227   return ret;
    228 }
    229 
    230 bool CFX_CTTGSUBTable::Parse(FT_Bytes scriptlist,
    231                              FT_Bytes featurelist,
    232                              FT_Bytes lookuplist) {
    233   ParseScriptList(scriptlist, &ScriptList);
    234   ParseFeatureList(featurelist, &FeatureList);
    235   ParseLookupList(lookuplist, &LookupList);
    236   return true;
    237 }
    238 
    239 void CFX_CTTGSUBTable::ParseScriptList(FT_Bytes raw, TScriptList* rec) {
    240   FT_Bytes sp = raw;
    241   rec->ScriptRecords = std::vector<TScriptRecord>(GetUInt16(sp));
    242   for (auto& scriptRec : rec->ScriptRecords) {
    243     scriptRec.ScriptTag = GetUInt32(sp);
    244     ParseScript(&raw[GetUInt16(sp)], &scriptRec.Script);
    245   }
    246 }
    247 
    248 void CFX_CTTGSUBTable::ParseScript(FT_Bytes raw, TScript* rec) {
    249   FT_Bytes sp = raw;
    250   rec->DefaultLangSys = GetUInt16(sp);
    251   rec->LangSysRecords = std::vector<TLangSysRecord>(GetUInt16(sp));
    252   for (auto& sysRecord : rec->LangSysRecords) {
    253     sysRecord.LangSysTag = GetUInt32(sp);
    254     ParseLangSys(&raw[GetUInt16(sp)], &sysRecord.LangSys);
    255   }
    256 }
    257 
    258 void CFX_CTTGSUBTable::ParseLangSys(FT_Bytes raw, TLangSys* rec) {
    259   FT_Bytes sp = raw;
    260   rec->LookupOrder = GetUInt16(sp);
    261   rec->ReqFeatureIndex = GetUInt16(sp);
    262   rec->FeatureIndices = std::vector<uint16_t>(GetUInt16(sp));
    263   for (auto& element : rec->FeatureIndices)
    264     element = GetUInt16(sp);
    265 }
    266 
    267 void CFX_CTTGSUBTable::ParseFeatureList(FT_Bytes raw, TFeatureList* rec) {
    268   FT_Bytes sp = raw;
    269   rec->FeatureRecords = std::vector<TFeatureRecord>(GetUInt16(sp));
    270   for (auto& featureRec : rec->FeatureRecords) {
    271     featureRec.FeatureTag = GetUInt32(sp);
    272     ParseFeature(&raw[GetUInt16(sp)], &featureRec.Feature);
    273   }
    274 }
    275 
    276 void CFX_CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeature* rec) {
    277   FT_Bytes sp = raw;
    278   rec->FeatureParams = GetUInt16(sp);
    279   rec->LookupListIndices = std::vector<uint16_t>(GetUInt16(sp));
    280   for (auto& listIndex : rec->LookupListIndices)
    281     listIndex = GetUInt16(sp);
    282 }
    283 
    284 void CFX_CTTGSUBTable::ParseLookupList(FT_Bytes raw, TLookupList* rec) {
    285   FT_Bytes sp = raw;
    286   rec->Lookups = std::vector<TLookup>(GetUInt16(sp));
    287   for (auto& lookup : rec->Lookups)
    288     ParseLookup(&raw[GetUInt16(sp)], &lookup);
    289 }
    290 
    291 void CFX_CTTGSUBTable::ParseLookup(FT_Bytes raw, TLookup* rec) {
    292   FT_Bytes sp = raw;
    293   rec->LookupType = GetUInt16(sp);
    294   rec->LookupFlag = GetUInt16(sp);
    295   rec->SubTables = std::vector<std::unique_ptr<TSubTableBase>>(GetUInt16(sp));
    296   if (rec->LookupType != 1)
    297     return;
    298 
    299   for (auto& subTable : rec->SubTables)
    300     ParseSingleSubst(&raw[GetUInt16(sp)], &subTable);
    301 }
    302 
    303 CFX_CTTGSUBTable::TCoverageFormatBase* CFX_CTTGSUBTable::ParseCoverage(
    304     FT_Bytes raw) {
    305   FT_Bytes sp = raw;
    306   uint16_t format = GetUInt16(sp);
    307   TCoverageFormatBase* rec = nullptr;
    308   if (format == 1) {
    309     rec = new TCoverageFormat1();
    310     ParseCoverageFormat1(raw, static_cast<TCoverageFormat1*>(rec));
    311   } else if (format == 2) {
    312     rec = new TCoverageFormat2();
    313     ParseCoverageFormat2(raw, static_cast<TCoverageFormat2*>(rec));
    314   }
    315   return rec;
    316 }
    317 
    318 void CFX_CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw,
    319                                             TCoverageFormat1* rec) {
    320   FT_Bytes sp = raw;
    321   (void)GetUInt16(sp);
    322   rec->GlyphArray = std::vector<uint16_t>(GetUInt16(sp));
    323   for (auto& glyph : rec->GlyphArray)
    324     glyph = GetUInt16(sp);
    325 }
    326 
    327 void CFX_CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw,
    328                                             TCoverageFormat2* rec) {
    329   FT_Bytes sp = raw;
    330   (void)GetUInt16(sp);
    331   rec->RangeRecords = std::vector<TRangeRecord>(GetUInt16(sp));
    332   for (auto& rangeRec : rec->RangeRecords) {
    333     rangeRec.Start = GetUInt16(sp);
    334     rangeRec.End = GetUInt16(sp);
    335     rangeRec.StartCoverageIndex = GetUInt16(sp);
    336   }
    337 }
    338 
    339 void CFX_CTTGSUBTable::ParseSingleSubst(FT_Bytes raw,
    340                                         std::unique_ptr<TSubTableBase>* rec) {
    341   FT_Bytes sp = raw;
    342   uint16_t Format = GetUInt16(sp);
    343   switch (Format) {
    344     case 1:
    345       *rec = pdfium::MakeUnique<TSingleSubstFormat1>();
    346       ParseSingleSubstFormat1(raw,
    347                               static_cast<TSingleSubstFormat1*>(rec->get()));
    348       break;
    349     case 2:
    350       *rec = pdfium::MakeUnique<TSingleSubstFormat2>();
    351       ParseSingleSubstFormat2(raw,
    352                               static_cast<TSingleSubstFormat2*>(rec->get()));
    353       break;
    354   }
    355 }
    356 
    357 void CFX_CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw,
    358                                                TSingleSubstFormat1* rec) {
    359   FT_Bytes sp = raw;
    360   GetUInt16(sp);
    361   uint16_t offset = GetUInt16(sp);
    362   rec->Coverage.reset(ParseCoverage(&raw[offset]));
    363   rec->DeltaGlyphID = GetInt16(sp);
    364 }
    365 
    366 void CFX_CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw,
    367                                                TSingleSubstFormat2* rec) {
    368   FT_Bytes sp = raw;
    369   (void)GetUInt16(sp);
    370   uint16_t offset = GetUInt16(sp);
    371   rec->Coverage.reset(ParseCoverage(&raw[offset]));
    372   rec->Substitutes = std::vector<uint16_t>(GetUInt16(sp));
    373   for (auto& substitute : rec->Substitutes)
    374     substitute = GetUInt16(sp);
    375 }
    376 
    377 CFX_CTTGSUBTable::TCoverageFormat1::TCoverageFormat1()
    378     : TCoverageFormatBase(1) {}
    379 
    380 CFX_CTTGSUBTable::TCoverageFormat1::~TCoverageFormat1() {}
    381 
    382 CFX_CTTGSUBTable::TRangeRecord::TRangeRecord()
    383     : Start(0), End(0), StartCoverageIndex(0) {}
    384 
    385 CFX_CTTGSUBTable::TCoverageFormat2::TCoverageFormat2()
    386     : TCoverageFormatBase(2) {}
    387 
    388 CFX_CTTGSUBTable::TCoverageFormat2::~TCoverageFormat2() {}
    389 
    390 CFX_CTTGSUBTable::TSingleSubstFormat1::TSingleSubstFormat1()
    391     : TSubTableBase(1), DeltaGlyphID(0) {}
    392 
    393 CFX_CTTGSUBTable::TSingleSubstFormat1::~TSingleSubstFormat1() {}
    394 
    395 CFX_CTTGSUBTable::TSingleSubstFormat2::TSingleSubstFormat2()
    396     : TSubTableBase(2) {}
    397 
    398 CFX_CTTGSUBTable::TSingleSubstFormat2::~TSingleSubstFormat2() {}
    399 
    400 CFX_CTTGSUBTable::TLookup::TLookup() : LookupType(0), LookupFlag(0) {}
    401 
    402 CFX_CTTGSUBTable::TLookup::~TLookup() {}
    403 
    404 CFX_CTTGSUBTable::TScript::TScript() : DefaultLangSys(0) {}
    405 
    406 CFX_CTTGSUBTable::TScript::~TScript() {}
    407 
    408 CFX_CTTGSUBTable::TScriptList::TScriptList() {}
    409 
    410 CFX_CTTGSUBTable::TScriptList::~TScriptList() {}
    411 
    412 CFX_CTTGSUBTable::TFeature::TFeature() : FeatureParams(0) {}
    413 
    414 CFX_CTTGSUBTable::TFeature::~TFeature() {}
    415 
    416 CFX_CTTGSUBTable::TFeatureList::TFeatureList() {}
    417 
    418 CFX_CTTGSUBTable::TFeatureList::~TFeatureList() {}
    419 
    420 CFX_CTTGSUBTable::TLookupList::TLookupList() {}
    421 
    422 CFX_CTTGSUBTable::TLookupList::~TLookupList() {}
    423 
    424 CFX_CTTGSUBTable::TLangSys::TLangSys() : LookupOrder(0), ReqFeatureIndex(0) {}
    425 
    426 CFX_CTTGSUBTable::TLangSys::~TLangSys() {}
    427