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