• 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/byteorder.h"
14 #include "core/fxcrt/data_vector.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   return tag == CFX_FontMapper::MakeTag('v', 'r', 't', '2') ||
22          tag == CFX_FontMapper::MakeTag('v', 'e', 'r', 't');
23 }
24 
25 }  // namespace
26 
CFX_CTTGSUBTable(pdfium::span<const uint8_t> gsub)27 CFX_CTTGSUBTable::CFX_CTTGSUBTable(pdfium::span<const uint8_t> gsub) {
28   if (!LoadGSUBTable(gsub))
29     return;
30 
31   for (const auto& script : script_list_) {
32     for (const auto& record : script) {
33       for (uint16_t index : record) {
34         if (IsVerticalFeatureTag(feature_list_[index].feature_tag)) {
35           feature_set_.insert(index);
36         }
37       }
38     }
39   }
40   if (!feature_set_.empty()) {
41     return;
42   }
43 
44   int i = 0;
45   for (const FeatureRecord& feature : feature_list_) {
46     if (IsVerticalFeatureTag(feature.feature_tag)) {
47       feature_set_.insert(i);
48     }
49     ++i;
50   }
51 }
52 
53 CFX_CTTGSUBTable::~CFX_CTTGSUBTable() = default;
54 
LoadGSUBTable(pdfium::span<const uint8_t> gsub)55 bool CFX_CTTGSUBTable::LoadGSUBTable(pdfium::span<const uint8_t> gsub) {
56   if (fxcrt::GetUInt32MSBFirst(gsub) != 0x00010000) {
57     return false;
58   }
59 
60   auto scriptlist_span = gsub.subspan(4, 2);
61   auto featurelist_span = gsub.subspan(6, 2);
62   auto lookuplist_span = gsub.subspan(8, 2);
63   size_t scriptlist_index = fxcrt::GetUInt16MSBFirst(scriptlist_span);
64   size_t featurelist_index = fxcrt::GetUInt16MSBFirst(featurelist_span);
65   size_t lookuplist_index = fxcrt::GetUInt16MSBFirst(lookuplist_span);
66   Parse(gsub.subspan(scriptlist_index), gsub.subspan(featurelist_index),
67         gsub.subspan(lookuplist_index));
68   return true;
69 }
70 
GetVerticalGlyph(uint32_t glyphnum) const71 uint32_t CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum) const {
72   for (uint32_t item : feature_set_) {
73     std::optional<uint32_t> result =
74         GetVerticalGlyphSub(feature_list_[item], glyphnum);
75     if (result.has_value())
76       return result.value();
77   }
78   return 0;
79 }
80 
GetVerticalGlyphSub(const FeatureRecord & feature,uint32_t glyphnum) const81 std::optional<uint32_t> CFX_CTTGSUBTable::GetVerticalGlyphSub(
82     const FeatureRecord& feature,
83     uint32_t glyphnum) const {
84   for (int index : feature.lookup_list_indices) {
85     if (!fxcrt::IndexInBounds(lookup_list_, index)) {
86       continue;
87     }
88     if (lookup_list_[index].lookup_type != 1) {
89       continue;
90     }
91     std::optional<uint32_t> result =
92         GetVerticalGlyphSub2(lookup_list_[index], glyphnum);
93     if (result.has_value())
94       return result.value();
95   }
96   return std::nullopt;
97 }
98 
GetVerticalGlyphSub2(const Lookup & lookup,uint32_t glyphnum) const99 std::optional<uint32_t> CFX_CTTGSUBTable::GetVerticalGlyphSub2(
100     const Lookup& lookup,
101     uint32_t glyphnum) const {
102   for (const auto& sub_table : lookup.sub_tables) {
103     if (absl::holds_alternative<absl::monostate>(sub_table.table_data)) {
104       continue;
105     }
106     int index = GetCoverageIndex(sub_table.coverage, glyphnum);
107     if (absl::holds_alternative<int16_t>(sub_table.table_data)) {
108       if (index >= 0) {
109         return glyphnum + absl::get<int16_t>(sub_table.table_data);
110       }
111     } else {
112       const auto& substitutes =
113           absl::get<DataVector<uint16_t>>(sub_table.table_data);
114       if (fxcrt::IndexInBounds(substitutes, index)) {
115         return substitutes[index];
116       }
117     }
118   }
119   return std::nullopt;
120 }
121 
GetCoverageIndex(const CoverageFormat & coverage,uint32_t g) const122 int CFX_CTTGSUBTable::GetCoverageIndex(const CoverageFormat& coverage,
123                                        uint32_t g) const {
124   if (absl::holds_alternative<absl::monostate>(coverage)) {
125     return -1;
126   }
127 
128   if (absl::holds_alternative<DataVector<uint16_t>>(coverage)) {
129     int i = 0;
130     const auto& glyph_array = absl::get<DataVector<uint16_t>>(coverage);
131     for (const auto& glyph : glyph_array) {
132       if (static_cast<uint32_t>(glyph) == g) {
133         return i;
134       }
135       ++i;
136     }
137     return -1;
138   }
139 
140   const auto& range_records = absl::get<std::vector<RangeRecord>>(coverage);
141   for (const auto& range_rec : range_records) {
142     uint32_t s = range_rec.start;
143     uint32_t e = range_rec.end;
144     uint32_t si = range_rec.start_coverage_index;
145     if (s <= g && g <= e) {
146       return si + g - s;
147     }
148   }
149   return -1;
150 }
151 
GetUInt8(pdfium::span<const uint8_t> & p) const152 uint8_t CFX_CTTGSUBTable::GetUInt8(pdfium::span<const uint8_t>& p) const {
153   uint8_t ret = p.front();
154   p = p.subspan(1u);
155   return ret;
156 }
157 
GetInt16(pdfium::span<const uint8_t> & p) const158 int16_t CFX_CTTGSUBTable::GetInt16(pdfium::span<const uint8_t>& p) const {
159   uint16_t ret = fxcrt::GetUInt16MSBFirst(p.first(2u));
160   p = p.subspan(2u);
161   return static_cast<int16_t>(ret);
162 }
163 
GetUInt16(pdfium::span<const uint8_t> & p) const164 uint16_t CFX_CTTGSUBTable::GetUInt16(pdfium::span<const uint8_t>& p) const {
165   uint16_t ret = fxcrt::GetUInt16MSBFirst(p.first(2u));
166   p = p.subspan(2u);
167   return ret;
168 }
169 
GetInt32(pdfium::span<const uint8_t> & p) const170 int32_t CFX_CTTGSUBTable::GetInt32(pdfium::span<const uint8_t>& p) const {
171   uint32_t ret = fxcrt::GetUInt32MSBFirst(p.first(4u));
172   p = p.subspan(4u);
173   return static_cast<int32_t>(ret);
174 }
175 
GetUInt32(pdfium::span<const uint8_t> & p) const176 uint32_t CFX_CTTGSUBTable::GetUInt32(pdfium::span<const uint8_t>& p) const {
177   uint32_t ret = fxcrt::GetUInt32MSBFirst(p.first(4u));
178   p = p.subspan(4u);
179   return ret;
180 }
181 
Parse(pdfium::span<const uint8_t> scriptlist,pdfium::span<const uint8_t> featurelist,pdfium::span<const uint8_t> lookuplist)182 void CFX_CTTGSUBTable::Parse(pdfium::span<const uint8_t> scriptlist,
183                              pdfium::span<const uint8_t> featurelist,
184                              pdfium::span<const uint8_t> lookuplist) {
185   ParseScriptList(scriptlist);
186   ParseFeatureList(featurelist);
187   ParseLookupList(lookuplist);
188 }
189 
ParseScriptList(pdfium::span<const uint8_t> raw)190 void CFX_CTTGSUBTable::ParseScriptList(pdfium::span<const uint8_t> raw) {
191   pdfium::span<const uint8_t> sp = raw;
192   script_list_ = std::vector<ScriptRecord>(GetUInt16(sp));
193   for (auto& script : script_list_) {
194     // Skip over "ScriptTag" field.
195     sp = sp.subspan(4u);
196     script = ParseScript(raw.subspan(GetUInt16(sp)));
197   }
198 }
199 
ParseScript(pdfium::span<const uint8_t> raw)200 CFX_CTTGSUBTable::ScriptRecord CFX_CTTGSUBTable::ParseScript(
201     pdfium::span<const uint8_t> raw) {
202   // Skip over "DefaultLangSys" field.
203   pdfium::span<const uint8_t> sp = raw.subspan(2u);
204   ScriptRecord result(GetUInt16(sp));
205   for (auto& record : result) {
206     // Skip over "LangSysTag" field.
207     sp = sp.subspan(4u);
208     record = ParseLangSys(raw.subspan(GetUInt16(sp)));
209   }
210   return result;
211 }
212 
ParseLangSys(pdfium::span<const uint8_t> raw)213 CFX_CTTGSUBTable::FeatureIndices CFX_CTTGSUBTable::ParseLangSys(
214     pdfium::span<const uint8_t> raw) {
215   // Skip over "LookupOrder" and "ReqFeatureIndex" fields.
216   pdfium::span<const uint8_t> sp = raw.subspan(4u);
217   FeatureIndices result(GetUInt16(sp));
218   for (auto& element : result) {
219     element = GetUInt16(sp);
220   }
221   return result;
222 }
223 
ParseFeatureList(pdfium::span<const uint8_t> raw)224 void CFX_CTTGSUBTable::ParseFeatureList(pdfium::span<const uint8_t> raw) {
225   pdfium::span<const uint8_t> sp = raw;
226   feature_list_ = std::vector<FeatureRecord>(GetUInt16(sp));
227   for (auto& record : feature_list_) {
228     record.feature_tag = GetUInt32(sp);
229     record.lookup_list_indices =
230         ParseFeatureLookupListIndices(raw.subspan(GetUInt16(sp)));
231   }
232 }
233 
ParseFeatureLookupListIndices(pdfium::span<const uint8_t> raw)234 DataVector<uint16_t> CFX_CTTGSUBTable::ParseFeatureLookupListIndices(
235     pdfium::span<const uint8_t> raw) {
236   // Skip over "FeatureParams" field.
237   pdfium::span<const uint8_t> sp = raw.subspan(2u);
238   DataVector<uint16_t> result(GetUInt16(sp));
239   for (auto& index : result) {
240     index = GetUInt16(sp);
241   }
242   return result;
243 }
244 
ParseLookupList(pdfium::span<const uint8_t> raw)245 void CFX_CTTGSUBTable::ParseLookupList(pdfium::span<const uint8_t> raw) {
246   pdfium::span<const uint8_t> sp = raw;
247   lookup_list_ = std::vector<Lookup>(GetUInt16(sp));
248   for (auto& lookup : lookup_list_) {
249     lookup = ParseLookup(raw.subspan(GetUInt16(sp)));
250   }
251 }
252 
ParseLookup(pdfium::span<const uint8_t> raw)253 CFX_CTTGSUBTable::Lookup CFX_CTTGSUBTable::ParseLookup(
254     pdfium::span<const uint8_t> raw) {
255   pdfium::span<const uint8_t> sp = raw;
256   CFX_CTTGSUBTable::Lookup result;
257   result.lookup_type = GetUInt16(sp);
258   // Skip over "LookupFlag" field.
259   sp = sp.subspan(2u);
260   result.sub_tables = Lookup::SubTables(GetUInt16(sp));
261   if (result.lookup_type != 1) {
262     return result;
263   }
264   for (auto& sub_table : result.sub_tables) {
265     sub_table = ParseSingleSubst(raw.subspan(GetUInt16(sp)));
266   }
267   return result;
268 }
269 
ParseCoverage(pdfium::span<const uint8_t> raw)270 CFX_CTTGSUBTable::CoverageFormat CFX_CTTGSUBTable::ParseCoverage(
271     pdfium::span<const uint8_t> raw) {
272   pdfium::span<const uint8_t> sp = raw;
273   uint16_t format = GetUInt16(sp);
274   if (format != 1 && format != 2) {
275     return absl::monostate();
276   }
277   if (format == 1) {
278     DataVector<uint16_t> glyph_array(GetUInt16(sp));
279     for (auto& glyph : glyph_array) {
280       glyph = GetUInt16(sp);
281     }
282     return glyph_array;
283   }
284   std::vector<RangeRecord> range_records(GetUInt16(sp));
285   for (auto& range_rec : range_records) {
286     range_rec.start = GetUInt16(sp);
287     range_rec.end = GetUInt16(sp);
288     range_rec.start_coverage_index = GetUInt16(sp);
289   }
290   return range_records;
291 }
292 
ParseSingleSubst(pdfium::span<const uint8_t> raw)293 CFX_CTTGSUBTable::SubTable CFX_CTTGSUBTable::ParseSingleSubst(
294     pdfium::span<const uint8_t> raw) {
295   pdfium::span<const uint8_t> sp = raw;
296   uint16_t format = GetUInt16(sp);
297   SubTable rec;
298   if (format != 1 && format != 2) {
299     return rec;
300   }
301   rec.coverage = ParseCoverage(raw.subspan(GetUInt16(sp)));
302   if (format == 1) {
303     rec.table_data = GetInt16(sp);
304   } else {
305     DataVector<uint16_t> table_data(GetUInt16(sp));
306     for (auto& substitute : table_data) {
307       substitute = GetUInt16(sp);
308     }
309     rec.table_data = std::move(table_data);
310   }
311   return rec;
312 }
313 
314 CFX_CTTGSUBTable::FeatureRecord::FeatureRecord() = default;
315 
316 CFX_CTTGSUBTable::FeatureRecord::~FeatureRecord() = default;
317 
318 CFX_CTTGSUBTable::RangeRecord::RangeRecord() = default;
319 
320 CFX_CTTGSUBTable::SubTable::SubTable() = default;
321 
322 CFX_CTTGSUBTable::SubTable::SubTable(SubTable&& that) noexcept = default;
323 
324 CFX_CTTGSUBTable::SubTable& CFX_CTTGSUBTable::SubTable::operator=(
325     SubTable&& that) noexcept = default;
326 
327 CFX_CTTGSUBTable::SubTable::~SubTable() = default;
328 
329 CFX_CTTGSUBTable::Lookup::Lookup() = default;
330 
331 CFX_CTTGSUBTable::Lookup::Lookup(Lookup&& that) noexcept = default;
332 
333 CFX_CTTGSUBTable::Lookup& CFX_CTTGSUBTable::Lookup::operator=(
334     Lookup&& that) noexcept = default;
335 
336 CFX_CTTGSUBTable::Lookup::~Lookup() = default;
337