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