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