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