• 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 "ttgsubtable.h"
8 
9 #include <memory>
10 
11 #include "core/include/fxge/fx_freetype.h"
12 #include "core/include/fxge/fx_ge.h"
13 #include "third_party/base/stl_util.h"
14 
CFX_GlyphMap()15 CFX_GlyphMap::CFX_GlyphMap() {}
~CFX_GlyphMap()16 CFX_GlyphMap::~CFX_GlyphMap() {}
17 extern "C" {
_CompareInt(const void * p1,const void * p2)18 static int _CompareInt(const void* p1, const void* p2) {
19   return (*(FX_DWORD*)p1) - (*(FX_DWORD*)p2);
20 }
21 };
22 struct _IntPair {
23   int32_t key;
24   int32_t value;
25 };
SetAt(int key,int value)26 void CFX_GlyphMap::SetAt(int key, int value) {
27   FX_DWORD count = m_Buffer.GetSize() / sizeof(_IntPair);
28   _IntPair* buf = (_IntPair*)m_Buffer.GetBuffer();
29   _IntPair pair = {key, value};
30   if (count == 0 || key > buf[count - 1].key) {
31     m_Buffer.AppendBlock(&pair, sizeof(_IntPair));
32     return;
33   }
34   int low = 0, high = count - 1;
35   while (low <= high) {
36     int mid = (low + high) / 2;
37     if (buf[mid].key < key) {
38       low = mid + 1;
39     } else if (buf[mid].key > key) {
40       high = mid - 1;
41     } else {
42       buf[mid].value = value;
43       return;
44     }
45   }
46   m_Buffer.InsertBlock(low * sizeof(_IntPair), &pair, sizeof(_IntPair));
47 }
Lookup(int key,int & value)48 FX_BOOL CFX_GlyphMap::Lookup(int key, int& value) {
49   void* pResult = FXSYS_bsearch(&key, m_Buffer.GetBuffer(),
50                                 m_Buffer.GetSize() / sizeof(_IntPair),
51                                 sizeof(_IntPair), _CompareInt);
52   if (!pResult) {
53     return FALSE;
54   }
55   value = ((FX_DWORD*)pResult)[1];
56   return TRUE;
57 }
LoadGSUBTable(FT_Bytes gsub)58 bool CFX_CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub) {
59   header.Version = gsub[0] << 24 | gsub[1] << 16 | gsub[2] << 8 | gsub[3];
60   if (header.Version != 0x00010000) {
61     return false;
62   }
63   header.ScriptList = gsub[4] << 8 | gsub[5];
64   header.FeatureList = gsub[6] << 8 | gsub[7];
65   header.LookupList = gsub[8] << 8 | gsub[9];
66   return Parse(&gsub[header.ScriptList], &gsub[header.FeatureList],
67                &gsub[header.LookupList]);
68 }
GetVerticalGlyph(uint32_t glyphnum,uint32_t * vglyphnum)69 bool CFX_CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum,
70                                         uint32_t* vglyphnum) {
71   uint32_t tag[] = {
72       (uint8_t)'v' << 24 | (uint8_t)'r' << 16 | (uint8_t)'t' << 8 |
73           (uint8_t)'2',
74       (uint8_t)'v' << 24 | (uint8_t)'e' << 16 | (uint8_t)'r' << 8 |
75           (uint8_t)'t',
76   };
77   if (!m_bFeautureMapLoad) {
78     for (int i = 0; i < ScriptList.ScriptCount; i++) {
79       for (int j = 0; j < (ScriptList.ScriptRecord + i)->Script.LangSysCount;
80            ++j) {
81         for (int k = 0;
82              k < ((ScriptList.ScriptRecord + i)->Script.LangSysRecord + j)
83                      ->LangSys.FeatureCount;
84              ++k) {
85           FX_DWORD index =
86               *(((ScriptList.ScriptRecord + i)->Script.LangSysRecord + j)
87                     ->LangSys.FeatureIndex +
88                 k);
89           if (FeatureList.FeatureRecord[index].FeatureTag == tag[0] ||
90               FeatureList.FeatureRecord[index].FeatureTag == tag[1]) {
91             if (!pdfium::ContainsKey(m_featureMap, index)) {
92               m_featureMap[index] = index;
93             }
94           }
95         }
96       }
97     }
98     if (m_featureMap.empty()) {
99       for (int i = 0; i < FeatureList.FeatureCount; i++) {
100         if (FeatureList.FeatureRecord[i].FeatureTag == tag[0] ||
101             FeatureList.FeatureRecord[i].FeatureTag == tag[1]) {
102           m_featureMap[i] = i;
103         }
104       }
105     }
106     m_bFeautureMapLoad = TRUE;
107   }
108   for (const auto& pair : m_featureMap) {
109     if (GetVerticalGlyphSub(glyphnum, vglyphnum,
110                             &FeatureList.FeatureRecord[pair.second].Feature)) {
111       return true;
112     }
113   }
114   return false;
115 }
GetVerticalGlyphSub(uint32_t glyphnum,uint32_t * vglyphnum,struct TFeature * Feature)116 bool CFX_CTTGSUBTable::GetVerticalGlyphSub(uint32_t glyphnum,
117                                            uint32_t* vglyphnum,
118                                            struct TFeature* Feature) {
119   for (int i = 0; i < Feature->LookupCount; i++) {
120     int index = Feature->LookupListIndex[i];
121     if (index < 0 || LookupList.LookupCount < index) {
122       continue;
123     }
124     if (LookupList.Lookup[index].LookupType == 1) {
125       if (GetVerticalGlyphSub2(glyphnum, vglyphnum,
126                                &LookupList.Lookup[index])) {
127         return true;
128       }
129     }
130   }
131   return false;
132 }
GetVerticalGlyphSub2(uint32_t glyphnum,uint32_t * vglyphnum,struct TLookup * Lookup)133 bool CFX_CTTGSUBTable::GetVerticalGlyphSub2(uint32_t glyphnum,
134                                             uint32_t* vglyphnum,
135                                             struct TLookup* Lookup) {
136   for (int i = 0; i < Lookup->SubTableCount; i++) {
137     switch (Lookup->SubTable[i]->SubstFormat) {
138       case 1: {
139         TSingleSubstFormat1* tbl1 = (TSingleSubstFormat1*)Lookup->SubTable[i];
140         if (GetCoverageIndex(tbl1->Coverage, glyphnum) >= 0) {
141           *vglyphnum = glyphnum + tbl1->DeltaGlyphID;
142           return true;
143         }
144         break;
145       }
146       case 2: {
147         TSingleSubstFormat2* tbl2 = (TSingleSubstFormat2*)Lookup->SubTable[i];
148         int index = -1;
149         index = GetCoverageIndex(tbl2->Coverage, glyphnum);
150         if (0 <= index && index < tbl2->GlyphCount) {
151           *vglyphnum = tbl2->Substitute[index];
152           return true;
153         }
154         break;
155       }
156     }
157   }
158   return false;
159 }
GetCoverageIndex(struct TCoverageFormatBase * Coverage,uint32_t g)160 int CFX_CTTGSUBTable::GetCoverageIndex(struct TCoverageFormatBase* Coverage,
161                                        uint32_t g) {
162   int i = 0;
163   if (!Coverage) {
164     return -1;
165   }
166   switch (Coverage->CoverageFormat) {
167     case 1: {
168       TCoverageFormat1* c1 = (TCoverageFormat1*)Coverage;
169       for (i = 0; i < c1->GlyphCount; i++) {
170         if ((uint32_t)c1->GlyphArray[i] == g) {
171           return i;
172         }
173       }
174       return -1;
175     }
176     case 2: {
177       TCoverageFormat2* c2 = (TCoverageFormat2*)Coverage;
178       for (i = 0; i < c2->RangeCount; i++) {
179         uint32_t s = c2->RangeRecord[i].Start;
180         uint32_t e = c2->RangeRecord[i].End;
181         uint32_t si = c2->RangeRecord[i].StartCoverageIndex;
182         if (s <= g && g <= e) {
183           return si + g - s;
184         }
185       }
186       return -1;
187     }
188   }
189   return -1;
190 }
Parse(FT_Bytes scriptlist,FT_Bytes featurelist,FT_Bytes lookuplist)191 bool CFX_CTTGSUBTable::Parse(FT_Bytes scriptlist,
192                              FT_Bytes featurelist,
193                              FT_Bytes lookuplist) {
194   ParseScriptList(scriptlist, &ScriptList);
195   ParseFeatureList(featurelist, &FeatureList);
196   ParseLookupList(lookuplist, &LookupList);
197   return true;
198 }
ParseScriptList(FT_Bytes raw,struct TScriptList * rec)199 void CFX_CTTGSUBTable::ParseScriptList(FT_Bytes raw, struct TScriptList* rec) {
200   int i;
201   FT_Bytes sp = raw;
202   rec->ScriptCount = GetUInt16(sp);
203   if (rec->ScriptCount <= 0) {
204     return;
205   }
206   rec->ScriptRecord = new struct TScriptRecord[rec->ScriptCount];
207   for (i = 0; i < rec->ScriptCount; i++) {
208     rec->ScriptRecord[i].ScriptTag = GetUInt32(sp);
209     uint16_t offset = GetUInt16(sp);
210     ParseScript(&raw[offset], &rec->ScriptRecord[i].Script);
211   }
212 }
ParseScript(FT_Bytes raw,struct TScript * rec)213 void CFX_CTTGSUBTable::ParseScript(FT_Bytes raw, struct TScript* rec) {
214   int i;
215   FT_Bytes sp = raw;
216   rec->DefaultLangSys = GetUInt16(sp);
217   rec->LangSysCount = GetUInt16(sp);
218   if (rec->LangSysCount <= 0) {
219     return;
220   }
221   rec->LangSysRecord = new struct TLangSysRecord[rec->LangSysCount];
222   for (i = 0; i < rec->LangSysCount; i++) {
223     rec->LangSysRecord[i].LangSysTag = GetUInt32(sp);
224     uint16_t offset = GetUInt16(sp);
225     ParseLangSys(&raw[offset], &rec->LangSysRecord[i].LangSys);
226   }
227 }
ParseLangSys(FT_Bytes raw,struct TLangSys * rec)228 void CFX_CTTGSUBTable::ParseLangSys(FT_Bytes raw, struct TLangSys* rec) {
229   FT_Bytes sp = raw;
230   rec->LookupOrder = GetUInt16(sp);
231   rec->ReqFeatureIndex = GetUInt16(sp);
232   rec->FeatureCount = GetUInt16(sp);
233   if (rec->FeatureCount <= 0) {
234     return;
235   }
236   rec->FeatureIndex = new uint16_t[rec->FeatureCount];
237   FXSYS_memset(rec->FeatureIndex, 0, sizeof(uint16_t) * rec->FeatureCount);
238   for (int i = 0; i < rec->FeatureCount; ++i) {
239     rec->FeatureIndex[i] = GetUInt16(sp);
240   }
241 }
ParseFeatureList(FT_Bytes raw,TFeatureList * rec)242 void CFX_CTTGSUBTable::ParseFeatureList(FT_Bytes raw, TFeatureList* rec) {
243   int i;
244   FT_Bytes sp = raw;
245   rec->FeatureCount = GetUInt16(sp);
246   if (rec->FeatureCount <= 0) {
247     return;
248   }
249   rec->FeatureRecord = new struct TFeatureRecord[rec->FeatureCount];
250   for (i = 0; i < rec->FeatureCount; i++) {
251     rec->FeatureRecord[i].FeatureTag = GetUInt32(sp);
252     uint16_t offset = GetUInt16(sp);
253     ParseFeature(&raw[offset], &rec->FeatureRecord[i].Feature);
254   }
255 }
ParseFeature(FT_Bytes raw,TFeature * rec)256 void CFX_CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeature* rec) {
257   int i;
258   FT_Bytes sp = raw;
259   rec->FeatureParams = GetUInt16(sp);
260   rec->LookupCount = GetUInt16(sp);
261   if (rec->LookupCount <= 0) {
262     return;
263   }
264   rec->LookupListIndex = new uint16_t[rec->LookupCount];
265   for (i = 0; i < rec->LookupCount; i++) {
266     rec->LookupListIndex[i] = GetUInt16(sp);
267   }
268 }
ParseLookupList(FT_Bytes raw,TLookupList * rec)269 void CFX_CTTGSUBTable::ParseLookupList(FT_Bytes raw, TLookupList* rec) {
270   int i;
271   FT_Bytes sp = raw;
272   rec->LookupCount = GetUInt16(sp);
273   if (rec->LookupCount <= 0) {
274     return;
275   }
276   rec->Lookup = new struct TLookup[rec->LookupCount];
277   for (i = 0; i < rec->LookupCount; i++) {
278     uint16_t offset = GetUInt16(sp);
279     ParseLookup(&raw[offset], &rec->Lookup[i]);
280   }
281 }
ParseLookup(FT_Bytes raw,TLookup * rec)282 void CFX_CTTGSUBTable::ParseLookup(FT_Bytes raw, TLookup* rec) {
283   int i;
284   FT_Bytes sp = raw;
285   rec->LookupType = GetUInt16(sp);
286   rec->LookupFlag = GetUInt16(sp);
287   rec->SubTableCount = GetUInt16(sp);
288   if (rec->SubTableCount <= 0) {
289     return;
290   }
291   rec->SubTable = new struct TSubTableBase*[rec->SubTableCount];
292   for (i = 0; i < rec->SubTableCount; i++) {
293     rec->SubTable[i] = NULL;
294   }
295   if (rec->LookupType != 1) {
296     return;
297   }
298   for (i = 0; i < rec->SubTableCount; i++) {
299     uint16_t offset = GetUInt16(sp);
300     ParseSingleSubst(&raw[offset], &rec->SubTable[i]);
301   }
302 }
ParseCoverage(FT_Bytes raw,TCoverageFormatBase ** rec)303 void CFX_CTTGSUBTable::ParseCoverage(FT_Bytes raw, TCoverageFormatBase** rec) {
304   FT_Bytes sp = raw;
305   uint16_t Format = GetUInt16(sp);
306   switch (Format) {
307     case 1:
308       *rec = new TCoverageFormat1();
309       ParseCoverageFormat1(raw, (TCoverageFormat1*)*rec);
310       break;
311     case 2:
312       *rec = new TCoverageFormat2();
313       ParseCoverageFormat2(raw, (TCoverageFormat2*)*rec);
314       break;
315   }
316 }
ParseCoverageFormat1(FT_Bytes raw,TCoverageFormat1 * rec)317 void CFX_CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw,
318                                             TCoverageFormat1* rec) {
319   int i;
320   FT_Bytes sp = raw;
321   GetUInt16(sp);
322   rec->GlyphCount = GetUInt16(sp);
323   if (rec->GlyphCount <= 0) {
324     return;
325   }
326   rec->GlyphArray = new uint16_t[rec->GlyphCount];
327   for (i = 0; i < rec->GlyphCount; i++) {
328     rec->GlyphArray[i] = GetUInt16(sp);
329   }
330 }
ParseCoverageFormat2(FT_Bytes raw,TCoverageFormat2 * rec)331 void CFX_CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw,
332                                             TCoverageFormat2* rec) {
333   int i;
334   FT_Bytes sp = raw;
335   GetUInt16(sp);
336   rec->RangeCount = GetUInt16(sp);
337   if (rec->RangeCount <= 0) {
338     return;
339   }
340   rec->RangeRecord = new TRangeRecord[rec->RangeCount];
341   for (i = 0; i < rec->RangeCount; i++) {
342     rec->RangeRecord[i].Start = GetUInt16(sp);
343     rec->RangeRecord[i].End = GetUInt16(sp);
344     rec->RangeRecord[i].StartCoverageIndex = GetUInt16(sp);
345   }
346 }
ParseSingleSubst(FT_Bytes raw,TSubTableBase ** rec)347 void CFX_CTTGSUBTable::ParseSingleSubst(FT_Bytes raw, TSubTableBase** rec) {
348   FT_Bytes sp = raw;
349   uint16_t Format = GetUInt16(sp);
350   switch (Format) {
351     case 1:
352       *rec = new TSingleSubstFormat1();
353       ParseSingleSubstFormat1(raw, (TSingleSubstFormat1*)*rec);
354       break;
355     case 2:
356       *rec = new TSingleSubstFormat2();
357       ParseSingleSubstFormat2(raw, (TSingleSubstFormat2*)*rec);
358       break;
359   }
360 }
ParseSingleSubstFormat1(FT_Bytes raw,TSingleSubstFormat1 * rec)361 void CFX_CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw,
362                                                TSingleSubstFormat1* rec) {
363   FT_Bytes sp = raw;
364   GetUInt16(sp);
365   uint16_t offset = GetUInt16(sp);
366   ParseCoverage(&raw[offset], &rec->Coverage);
367   rec->DeltaGlyphID = GetInt16(sp);
368 }
ParseSingleSubstFormat2(FT_Bytes raw,TSingleSubstFormat2 * rec)369 void CFX_CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw,
370                                                TSingleSubstFormat2* rec) {
371   int i;
372   FT_Bytes sp = raw;
373   GetUInt16(sp);
374   uint16_t offset = GetUInt16(sp);
375   ParseCoverage(&raw[offset], &rec->Coverage);
376   rec->GlyphCount = GetUInt16(sp);
377   if (rec->GlyphCount <= 0) {
378     return;
379   }
380   rec->Substitute = new uint16_t[rec->GlyphCount];
381   for (i = 0; i < rec->GlyphCount; i++) {
382     rec->Substitute[i] = GetUInt16(sp);
383   }
384 }
GetVerticalGlyph(FX_DWORD glyphnum,FX_DWORD * vglyphnum)385 FX_BOOL CFX_GSUBTable::GetVerticalGlyph(FX_DWORD glyphnum,
386                                         FX_DWORD* vglyphnum) {
387   return m_GsubImp.GetVerticalGlyph(glyphnum, vglyphnum);
388 }
389 // static
Create(CFX_Font * pFont)390 IFX_GSUBTable* IFX_GSUBTable::Create(CFX_Font* pFont) {
391   if (!pFont) {
392     return NULL;
393   }
394   if (!pFont->GetSubData()) {
395     unsigned long length = 0;
396     int error = FXFT_Load_Sfnt_Table(
397         pFont->GetFace(), FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, NULL, &length);
398     if (!error) {
399       pFont->SetSubData(FX_Alloc(uint8_t, length));
400     }
401     if (!pFont->GetSubData()) {
402       return NULL;
403     }
404   }
405   int error =
406       FXFT_Load_Sfnt_Table(pFont->GetFace(), FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
407                            pFont->GetSubData(), NULL);
408   if (!error && pFont->GetSubData()) {
409     std::unique_ptr<CFX_GSUBTable> pGsubTable(new CFX_GSUBTable);
410     if (pGsubTable->m_GsubImp.LoadGSUBTable((FT_Bytes)pFont->GetSubData())) {
411       return pGsubTable.release();
412     }
413   }
414   return NULL;
415 }
416