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