• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CFX_GlyphMap()13 CFX_GlyphMap::CFX_GlyphMap() {}
14 
~CFX_GlyphMap()15 CFX_GlyphMap::~CFX_GlyphMap() {}
16 
17 extern "C" {
_CompareInt(const void * p1,const void * p2)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 
SetAt(int key,int value)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 
Lookup(int key,int & value)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 
CFX_CTTGSUBTable()62 CFX_CTTGSUBTable::CFX_CTTGSUBTable()
63     : m_bFeautureMapLoad(false), loaded(false) {}
64 
CFX_CTTGSUBTable(FT_Bytes gsub)65 CFX_CTTGSUBTable::CFX_CTTGSUBTable(FT_Bytes gsub)
66     : m_bFeautureMapLoad(false), loaded(false) {
67   LoadGSUBTable(gsub);
68 }
69 
~CFX_CTTGSUBTable()70 CFX_CTTGSUBTable::~CFX_CTTGSUBTable() {}
71 
IsOk() const72 bool CFX_CTTGSUBTable::IsOk() const {
73   return loaded;
74 }
75 
LoadGSUBTable(FT_Bytes gsub)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 
GetVerticalGlyph(uint32_t glyphnum,uint32_t * vglyphnum)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 
GetVerticalGlyphSub(uint32_t glyphnum,uint32_t * vglyphnum,TFeature * Feature)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 
GetVerticalGlyphSub2(uint32_t glyphnum,uint32_t * vglyphnum,TLookup * Lookup)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 
GetCoverageIndex(TCoverageFormatBase * Coverage,uint32_t g) const169 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 
GetUInt8(FT_Bytes & p) const200 uint8_t CFX_CTTGSUBTable::GetUInt8(FT_Bytes& p) const {
201   uint8_t ret = p[0];
202   p += 1;
203   return ret;
204 }
205 
GetInt16(FT_Bytes & p) const206 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 
GetUInt16(FT_Bytes & p) const212 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 
GetInt32(FT_Bytes & p) const218 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 
GetUInt32(FT_Bytes & p) const224 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 
Parse(FT_Bytes scriptlist,FT_Bytes featurelist,FT_Bytes lookuplist)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 
ParseScriptList(FT_Bytes raw,TScriptList * rec)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 
ParseScript(FT_Bytes raw,TScript * rec)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 
ParseLangSys(FT_Bytes raw,TLangSys * rec)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 
ParseFeatureList(FT_Bytes raw,TFeatureList * rec)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 
ParseFeature(FT_Bytes raw,TFeature * rec)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 
ParseLookupList(FT_Bytes raw,TLookupList * rec)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 
ParseLookup(FT_Bytes raw,TLookup * rec)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 
ParseCoverage(FT_Bytes raw)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 
ParseCoverageFormat1(FT_Bytes raw,TCoverageFormat1 * rec)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 
ParseCoverageFormat2(FT_Bytes raw,TCoverageFormat2 * rec)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 
ParseSingleSubst(FT_Bytes raw,std::unique_ptr<TSubTableBase> * rec)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 
ParseSingleSubstFormat1(FT_Bytes raw,TSingleSubstFormat1 * rec)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 
ParseSingleSubstFormat2(FT_Bytes raw,TSingleSubstFormat2 * rec)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 
TCoverageFormat1()377 CFX_CTTGSUBTable::TCoverageFormat1::TCoverageFormat1()
378     : TCoverageFormatBase(1) {}
379 
~TCoverageFormat1()380 CFX_CTTGSUBTable::TCoverageFormat1::~TCoverageFormat1() {}
381 
TRangeRecord()382 CFX_CTTGSUBTable::TRangeRecord::TRangeRecord()
383     : Start(0), End(0), StartCoverageIndex(0) {}
384 
TCoverageFormat2()385 CFX_CTTGSUBTable::TCoverageFormat2::TCoverageFormat2()
386     : TCoverageFormatBase(2) {}
387 
~TCoverageFormat2()388 CFX_CTTGSUBTable::TCoverageFormat2::~TCoverageFormat2() {}
389 
TSingleSubstFormat1()390 CFX_CTTGSUBTable::TSingleSubstFormat1::TSingleSubstFormat1()
391     : TSubTableBase(1), DeltaGlyphID(0) {}
392 
~TSingleSubstFormat1()393 CFX_CTTGSUBTable::TSingleSubstFormat1::~TSingleSubstFormat1() {}
394 
TSingleSubstFormat2()395 CFX_CTTGSUBTable::TSingleSubstFormat2::TSingleSubstFormat2()
396     : TSubTableBase(2) {}
397 
~TSingleSubstFormat2()398 CFX_CTTGSUBTable::TSingleSubstFormat2::~TSingleSubstFormat2() {}
399 
TLookup()400 CFX_CTTGSUBTable::TLookup::TLookup() : LookupType(0), LookupFlag(0) {}
401 
~TLookup()402 CFX_CTTGSUBTable::TLookup::~TLookup() {}
403 
TScript()404 CFX_CTTGSUBTable::TScript::TScript() : DefaultLangSys(0) {}
405 
~TScript()406 CFX_CTTGSUBTable::TScript::~TScript() {}
407 
TScriptList()408 CFX_CTTGSUBTable::TScriptList::TScriptList() {}
409 
~TScriptList()410 CFX_CTTGSUBTable::TScriptList::~TScriptList() {}
411 
TFeature()412 CFX_CTTGSUBTable::TFeature::TFeature() : FeatureParams(0) {}
413 
~TFeature()414 CFX_CTTGSUBTable::TFeature::~TFeature() {}
415 
TFeatureList()416 CFX_CTTGSUBTable::TFeatureList::TFeatureList() {}
417 
~TFeatureList()418 CFX_CTTGSUBTable::TFeatureList::~TFeatureList() {}
419 
TLookupList()420 CFX_CTTGSUBTable::TLookupList::TLookupList() {}
421 
~TLookupList()422 CFX_CTTGSUBTable::TLookupList::~TLookupList() {}
423 
TLangSys()424 CFX_CTTGSUBTable::TLangSys::TLangSys() : LookupOrder(0), ReqFeatureIndex(0) {}
425 
~TLangSys()426 CFX_CTTGSUBTable::TLangSys::~TLangSys() {}
427