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 "font_int.h"
8
9#include "core/include/fpdfapi/fpdf_module.h"
10#include "core/include/fpdfapi/fpdf_page.h"
11#include "core/include/fpdfapi/fpdf_resource.h"
12#include "core/include/fxcrt/fx_ext.h"
13#include "core/include/fxge/fx_freetype.h"
14#include "core/include/fxge/fx_ge.h"
15#include "core/src/fpdfapi/fpdf_cmaps/cmap_int.h"
16
17namespace {
18
19const FX_CHAR* const g_CharsetNames[CIDSET_NUM_SETS] =
20    {nullptr, "GB1", "CNS1", "Japan1", "Korea1", "UCS"};
21
22const int g_CharsetCPs[CIDSET_NUM_SETS] = {0, 936, 950, 932, 949, 1200};
23
24class CPDF_PredefinedCMap {
25 public:
26  const FX_CHAR* m_pName;
27  CIDSet m_Charset;
28  int m_Coding;
29  CPDF_CMap::CodingScheme m_CodingScheme;
30  FX_DWORD m_LeadingSegCount;
31  uint8_t m_LeadingSegs[4];
32};
33
34const CPDF_PredefinedCMap g_PredefinedCMaps[] = {
35    {"GB-EUC",
36     CIDSET_GB1,
37     CIDCODING_GB,
38     CPDF_CMap::MixedTwoBytes,
39     1,
40     {0xa1, 0xfe}},
41    {"GBpc-EUC",
42     CIDSET_GB1,
43     CIDCODING_GB,
44     CPDF_CMap::MixedTwoBytes,
45     1,
46     {0xa1, 0xfc}},
47    {"GBK-EUC",
48     CIDSET_GB1,
49     CIDCODING_GB,
50     CPDF_CMap::MixedTwoBytes,
51     1,
52     {0x81, 0xfe}},
53    {"GBKp-EUC",
54     CIDSET_GB1,
55     CIDCODING_GB,
56     CPDF_CMap::MixedTwoBytes,
57     1,
58     {0x81, 0xfe}},
59    {"GBK2K-EUC",
60     CIDSET_GB1,
61     CIDCODING_GB,
62     CPDF_CMap::MixedTwoBytes,
63     1,
64     {0x81, 0xfe}},
65    {"GBK2K",
66     CIDSET_GB1,
67     CIDCODING_GB,
68     CPDF_CMap::MixedTwoBytes,
69     1,
70     {0x81, 0xfe}},
71    {"UniGB-UCS2", CIDSET_GB1, CIDCODING_UCS2, CPDF_CMap::TwoBytes},
72    {"UniGB-UTF16", CIDSET_GB1, CIDCODING_UTF16, CPDF_CMap::TwoBytes},
73    {"B5pc",
74     CIDSET_CNS1,
75     CIDCODING_BIG5,
76     CPDF_CMap::MixedTwoBytes,
77     1,
78     {0xa1, 0xfc}},
79    {"HKscs-B5",
80     CIDSET_CNS1,
81     CIDCODING_BIG5,
82     CPDF_CMap::MixedTwoBytes,
83     1,
84     {0x88, 0xfe}},
85    {"ETen-B5",
86     CIDSET_CNS1,
87     CIDCODING_BIG5,
88     CPDF_CMap::MixedTwoBytes,
89     1,
90     {0xa1, 0xfe}},
91    {"ETenms-B5",
92     CIDSET_CNS1,
93     CIDCODING_BIG5,
94     CPDF_CMap::MixedTwoBytes,
95     1,
96     {0xa1, 0xfe}},
97    {"UniCNS-UCS2", CIDSET_CNS1, CIDCODING_UCS2, CPDF_CMap::TwoBytes},
98    {"UniCNS-UTF16", CIDSET_CNS1, CIDCODING_UTF16, CPDF_CMap::TwoBytes},
99    {"83pv-RKSJ",
100     CIDSET_JAPAN1,
101     CIDCODING_JIS,
102     CPDF_CMap::MixedTwoBytes,
103     2,
104     {0x81, 0x9f, 0xe0, 0xfc}},
105    {"90ms-RKSJ",
106     CIDSET_JAPAN1,
107     CIDCODING_JIS,
108     CPDF_CMap::MixedTwoBytes,
109     2,
110     {0x81, 0x9f, 0xe0, 0xfc}},
111    {"90msp-RKSJ",
112     CIDSET_JAPAN1,
113     CIDCODING_JIS,
114     CPDF_CMap::MixedTwoBytes,
115     2,
116     {0x81, 0x9f, 0xe0, 0xfc}},
117    {"90pv-RKSJ",
118     CIDSET_JAPAN1,
119     CIDCODING_JIS,
120     CPDF_CMap::MixedTwoBytes,
121     2,
122     {0x81, 0x9f, 0xe0, 0xfc}},
123    {"Add-RKSJ",
124     CIDSET_JAPAN1,
125     CIDCODING_JIS,
126     CPDF_CMap::MixedTwoBytes,
127     2,
128     {0x81, 0x9f, 0xe0, 0xfc}},
129    {"EUC",
130     CIDSET_JAPAN1,
131     CIDCODING_JIS,
132     CPDF_CMap::MixedTwoBytes,
133     2,
134     {0x8e, 0x8e, 0xa1, 0xfe}},
135    {"H", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {0x21, 0x7e}},
136    {"V", CIDSET_JAPAN1, CIDCODING_JIS, CPDF_CMap::TwoBytes, 1, {0x21, 0x7e}},
137    {"Ext-RKSJ",
138     CIDSET_JAPAN1,
139     CIDCODING_JIS,
140     CPDF_CMap::MixedTwoBytes,
141     2,
142     {0x81, 0x9f, 0xe0, 0xfc}},
143    {"UniJIS-UCS2", CIDSET_JAPAN1, CIDCODING_UCS2, CPDF_CMap::TwoBytes},
144    {"UniJIS-UCS2-HW", CIDSET_JAPAN1, CIDCODING_UCS2, CPDF_CMap::TwoBytes},
145    {"UniJIS-UTF16", CIDSET_JAPAN1, CIDCODING_UTF16, CPDF_CMap::TwoBytes},
146    {"KSC-EUC",
147     CIDSET_KOREA1,
148     CIDCODING_KOREA,
149     CPDF_CMap::MixedTwoBytes,
150     1,
151     {0xa1, 0xfe}},
152    {"KSCms-UHC",
153     CIDSET_KOREA1,
154     CIDCODING_KOREA,
155     CPDF_CMap::MixedTwoBytes,
156     1,
157     {0x81, 0xfe}},
158    {"KSCms-UHC-HW",
159     CIDSET_KOREA1,
160     CIDCODING_KOREA,
161     CPDF_CMap::MixedTwoBytes,
162     1,
163     {0x81, 0xfe}},
164    {"KSCpc-EUC",
165     CIDSET_KOREA1,
166     CIDCODING_KOREA,
167     CPDF_CMap::MixedTwoBytes,
168     1,
169     {0xa1, 0xfd}},
170    {"UniKS-UCS2", CIDSET_KOREA1, CIDCODING_UCS2, CPDF_CMap::TwoBytes},
171    {"UniKS-UTF16", CIDSET_KOREA1, CIDCODING_UTF16, CPDF_CMap::TwoBytes},
172};
173
174CIDSet CIDSetFromSizeT(size_t index) {
175  if (index >= CIDSET_NUM_SETS) {
176    NOTREACHED();
177    return CIDSET_UNKNOWN;
178  }
179  return static_cast<CIDSet>(index);
180}
181
182CIDSet CharsetFromOrdering(const CFX_ByteString& ordering) {
183  for (size_t charset = 1; charset < FX_ArraySize(g_CharsetNames); ++charset) {
184    if (ordering == CFX_ByteStringC(g_CharsetNames[charset]))
185      return CIDSetFromSizeT(charset);
186  }
187  return CIDSET_UNKNOWN;
188}
189
190CFX_ByteString CMap_GetString(const CFX_ByteStringC& word) {
191  return word.Mid(1, word.GetLength() - 2);
192}
193
194int CompareDWORD(const void* data1, const void* data2) {
195  return (*(FX_DWORD*)data1) - (*(FX_DWORD*)data2);
196}
197
198int CompareCID(const void* key, const void* element) {
199  if ((*(FX_DWORD*)key) < (*(FX_DWORD*)element)) {
200    return -1;
201  }
202  if ((*(FX_DWORD*)key) >
203      (*(FX_DWORD*)element) + ((FX_DWORD*)element)[1] / 65536) {
204    return 1;
205  }
206  return 0;
207}
208
209int CheckCodeRange(uint8_t* codes,
210                   int size,
211                   CMap_CodeRange* pRanges,
212                   int nRanges) {
213  int iSeg = nRanges - 1;
214  while (iSeg >= 0) {
215    if (pRanges[iSeg].m_CharSize < size) {
216      --iSeg;
217      continue;
218    }
219    int iChar = 0;
220    while (iChar < size) {
221      if (codes[iChar] < pRanges[iSeg].m_Lower[iChar] ||
222          codes[iChar] > pRanges[iSeg].m_Upper[iChar]) {
223        break;
224      }
225      ++iChar;
226    }
227    if (iChar == pRanges[iSeg].m_CharSize)
228      return 2;
229
230    if (iChar)
231      return (size == pRanges[iSeg].m_CharSize) ? 2 : 1;
232    iSeg--;
233  }
234  return 0;
235}
236
237int GetCharSizeImpl(FX_DWORD charcode,
238                    CMap_CodeRange* pRanges,
239                    int iRangesSize) {
240  if (!iRangesSize)
241    return 1;
242
243  uint8_t codes[4];
244  codes[0] = codes[1] = 0x00;
245  codes[2] = (uint8_t)(charcode >> 8 & 0xFF);
246  codes[3] = (uint8_t)charcode;
247  int offset = 0;
248  int size = 4;
249  for (int i = 0; i < 4; ++i) {
250    int iSeg = iRangesSize - 1;
251    while (iSeg >= 0) {
252      if (pRanges[iSeg].m_CharSize < size) {
253        --iSeg;
254        continue;
255      }
256      int iChar = 0;
257      while (iChar < size) {
258        if (codes[offset + iChar] < pRanges[iSeg].m_Lower[iChar] ||
259            codes[offset + iChar] > pRanges[iSeg].m_Upper[iChar]) {
260          break;
261        }
262        ++iChar;
263      }
264      if (iChar == pRanges[iSeg].m_CharSize)
265        return size;
266      --iSeg;
267    }
268    --size;
269    ++offset;
270  }
271  return 1;
272}
273
274bool IsValidEmbeddedCharcodeFromUnicodeCharset(CIDSet charset) {
275  switch (charset) {
276    case CIDSET_GB1:
277    case CIDSET_CNS1:
278    case CIDSET_JAPAN1:
279    case CIDSET_KOREA1:
280      return true;
281
282    default:
283      return false;
284  }
285}
286
287#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
288FX_DWORD EmbeddedCharcodeFromUnicode(const FXCMAP_CMap* pEmbedMap,
289                                     CIDSet charset,
290                                     FX_WCHAR unicode) {
291  if (!IsValidEmbeddedCharcodeFromUnicodeCharset(charset))
292    return 0;
293
294  CPDF_FontGlobals* pFontGlobals =
295      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
296  const FX_WORD* pCodes = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap;
297  if (!pCodes)
298    return 0;
299
300  int nCodes = pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count;
301  for (int i = 0; i < nCodes; ++i) {
302    if (pCodes[i] == unicode) {
303      FX_DWORD CharCode = FPDFAPI_CharCodeFromCID(pEmbedMap, i);
304      if (CharCode != 0) {
305        return CharCode;
306      }
307    }
308  }
309  return 0;
310}
311#endif  // _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
312
313FX_WCHAR EmbeddedUnicodeFromCharcode(const FXCMAP_CMap* pEmbedMap,
314                                     CIDSet charset,
315                                     FX_DWORD charcode) {
316  if (!IsValidEmbeddedCharcodeFromUnicodeCharset(charset))
317    return 0;
318
319  FX_WORD cid = FPDFAPI_CIDFromCharCode(pEmbedMap, charcode);
320  if (cid == 0)
321    return 0;
322
323  CPDF_FontGlobals* pFontGlobals =
324      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
325  const FX_WORD* pCodes = pFontGlobals->m_EmbeddedToUnicodes[charset].m_pMap;
326  if (!pCodes)
327    return 0;
328
329  if (cid < pFontGlobals->m_EmbeddedToUnicodes[charset].m_Count)
330    return pCodes[cid];
331  return 0;
332}
333
334void FT_UseCIDCharmap(FXFT_Face face, int coding) {
335  int encoding;
336  switch (coding) {
337    case CIDCODING_GB:
338      encoding = FXFT_ENCODING_GB2312;
339      break;
340    case CIDCODING_BIG5:
341      encoding = FXFT_ENCODING_BIG5;
342      break;
343    case CIDCODING_JIS:
344      encoding = FXFT_ENCODING_SJIS;
345      break;
346    case CIDCODING_KOREA:
347      encoding = FXFT_ENCODING_JOHAB;
348      break;
349    default:
350      encoding = FXFT_ENCODING_UNICODE;
351  }
352  int err = FXFT_Select_Charmap(face, encoding);
353  if (err) {
354    err = FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE);
355  }
356  if (err && FXFT_Get_Face_Charmaps(face)) {
357    FXFT_Set_Charmap(face, *FXFT_Get_Face_Charmaps(face));
358  }
359}
360
361const struct CIDTransform {
362  FX_WORD CID;
363  uint8_t a, b, c, d, e, f;
364} g_Japan1_VertCIDs[] = {
365    {97, 129, 0, 0, 127, 55, 0},
366    {7887, 127, 0, 0, 127, 76, 89},
367    {7888, 127, 0, 0, 127, 79, 94},
368    {7889, 0, 129, 127, 0, 17, 127},
369    {7890, 0, 129, 127, 0, 17, 127},
370    {7891, 0, 129, 127, 0, 17, 127},
371    {7892, 0, 129, 127, 0, 17, 127},
372    {7893, 0, 129, 127, 0, 17, 127},
373    {7894, 0, 129, 127, 0, 17, 127},
374    {7895, 0, 129, 127, 0, 17, 127},
375    {7896, 0, 129, 127, 0, 17, 127},
376    {7897, 0, 129, 127, 0, 17, 127},
377    {7898, 0, 129, 127, 0, 17, 127},
378    {7899, 0, 129, 127, 0, 17, 104},
379    {7900, 0, 129, 127, 0, 17, 127},
380    {7901, 0, 129, 127, 0, 17, 104},
381    {7902, 0, 129, 127, 0, 17, 127},
382    {7903, 0, 129, 127, 0, 17, 127},
383    {7904, 0, 129, 127, 0, 17, 127},
384    {7905, 0, 129, 127, 0, 17, 114},
385    {7906, 0, 129, 127, 0, 17, 127},
386    {7907, 0, 129, 127, 0, 17, 127},
387    {7908, 0, 129, 127, 0, 17, 127},
388    {7909, 0, 129, 127, 0, 17, 127},
389    {7910, 0, 129, 127, 0, 17, 127},
390    {7911, 0, 129, 127, 0, 17, 127},
391    {7912, 0, 129, 127, 0, 17, 127},
392    {7913, 0, 129, 127, 0, 17, 127},
393    {7914, 0, 129, 127, 0, 17, 127},
394    {7915, 0, 129, 127, 0, 17, 114},
395    {7916, 0, 129, 127, 0, 17, 127},
396    {7917, 0, 129, 127, 0, 17, 127},
397    {7918, 127, 0, 0, 127, 18, 25},
398    {7919, 127, 0, 0, 127, 18, 25},
399    {7920, 127, 0, 0, 127, 18, 25},
400    {7921, 127, 0, 0, 127, 18, 25},
401    {7922, 127, 0, 0, 127, 18, 25},
402    {7923, 127, 0, 0, 127, 18, 25},
403    {7924, 127, 0, 0, 127, 18, 25},
404    {7925, 127, 0, 0, 127, 18, 25},
405    {7926, 127, 0, 0, 127, 18, 25},
406    {7927, 127, 0, 0, 127, 18, 25},
407    {7928, 127, 0, 0, 127, 18, 25},
408    {7929, 127, 0, 0, 127, 18, 25},
409    {7930, 127, 0, 0, 127, 18, 25},
410    {7931, 127, 0, 0, 127, 18, 25},
411    {7932, 127, 0, 0, 127, 18, 25},
412    {7933, 127, 0, 0, 127, 18, 25},
413    {7934, 127, 0, 0, 127, 18, 25},
414    {7935, 127, 0, 0, 127, 18, 25},
415    {7936, 127, 0, 0, 127, 18, 25},
416    {7937, 127, 0, 0, 127, 18, 25},
417    {7938, 127, 0, 0, 127, 18, 25},
418    {7939, 127, 0, 0, 127, 18, 25},
419    {8720, 0, 129, 127, 0, 19, 102},
420    {8721, 0, 129, 127, 0, 13, 127},
421    {8722, 0, 129, 127, 0, 19, 108},
422    {8723, 0, 129, 127, 0, 19, 102},
423    {8724, 0, 129, 127, 0, 19, 102},
424    {8725, 0, 129, 127, 0, 19, 102},
425    {8726, 0, 129, 127, 0, 19, 102},
426    {8727, 0, 129, 127, 0, 19, 102},
427    {8728, 0, 129, 127, 0, 19, 114},
428    {8729, 0, 129, 127, 0, 19, 114},
429    {8730, 0, 129, 127, 0, 38, 108},
430    {8731, 0, 129, 127, 0, 13, 108},
431    {8732, 0, 129, 127, 0, 19, 108},
432    {8733, 0, 129, 127, 0, 19, 108},
433    {8734, 0, 129, 127, 0, 19, 108},
434    {8735, 0, 129, 127, 0, 19, 108},
435    {8736, 0, 129, 127, 0, 19, 102},
436    {8737, 0, 129, 127, 0, 19, 102},
437    {8738, 0, 129, 127, 0, 19, 102},
438    {8739, 0, 129, 127, 0, 19, 102},
439    {8740, 0, 129, 127, 0, 19, 102},
440    {8741, 0, 129, 127, 0, 19, 102},
441    {8742, 0, 129, 127, 0, 19, 102},
442    {8743, 0, 129, 127, 0, 19, 102},
443    {8744, 0, 129, 127, 0, 19, 102},
444    {8745, 0, 129, 127, 0, 19, 102},
445    {8746, 0, 129, 127, 0, 19, 114},
446    {8747, 0, 129, 127, 0, 19, 114},
447    {8748, 0, 129, 127, 0, 19, 102},
448    {8749, 0, 129, 127, 0, 19, 102},
449    {8750, 0, 129, 127, 0, 19, 102},
450    {8751, 0, 129, 127, 0, 19, 102},
451    {8752, 0, 129, 127, 0, 19, 102},
452    {8753, 0, 129, 127, 0, 19, 102},
453    {8754, 0, 129, 127, 0, 19, 102},
454    {8755, 0, 129, 127, 0, 19, 102},
455    {8756, 0, 129, 127, 0, 19, 102},
456    {8757, 0, 129, 127, 0, 19, 102},
457    {8758, 0, 129, 127, 0, 19, 102},
458    {8759, 0, 129, 127, 0, 19, 102},
459    {8760, 0, 129, 127, 0, 19, 102},
460    {8761, 0, 129, 127, 0, 19, 102},
461    {8762, 0, 129, 127, 0, 19, 102},
462    {8763, 0, 129, 127, 0, 19, 102},
463    {8764, 0, 129, 127, 0, 19, 102},
464    {8765, 0, 129, 127, 0, 19, 102},
465    {8766, 0, 129, 127, 0, 19, 102},
466    {8767, 0, 129, 127, 0, 19, 102},
467    {8768, 0, 129, 127, 0, 19, 102},
468    {8769, 0, 129, 127, 0, 19, 102},
469    {8770, 0, 129, 127, 0, 19, 102},
470    {8771, 0, 129, 127, 0, 19, 102},
471    {8772, 0, 129, 127, 0, 19, 102},
472    {8773, 0, 129, 127, 0, 19, 102},
473    {8774, 0, 129, 127, 0, 19, 102},
474    {8775, 0, 129, 127, 0, 19, 102},
475    {8776, 0, 129, 127, 0, 19, 102},
476    {8777, 0, 129, 127, 0, 19, 102},
477    {8778, 0, 129, 127, 0, 19, 102},
478    {8779, 0, 129, 127, 0, 19, 114},
479    {8780, 0, 129, 127, 0, 19, 108},
480    {8781, 0, 129, 127, 0, 19, 114},
481    {8782, 0, 129, 127, 0, 13, 114},
482    {8783, 0, 129, 127, 0, 19, 108},
483    {8784, 0, 129, 127, 0, 13, 114},
484    {8785, 0, 129, 127, 0, 19, 108},
485    {8786, 0, 129, 127, 0, 19, 108},
486    {8787, 0, 129, 127, 0, 19, 108},
487    {8788, 0, 129, 127, 0, 19, 108},
488    {8789, 0, 129, 127, 0, 19, 108},
489    {8790, 0, 129, 127, 0, 19, 108},
490    {8791, 0, 129, 127, 0, 19, 108},
491    {8792, 0, 129, 127, 0, 19, 108},
492    {8793, 0, 129, 127, 0, 19, 108},
493    {8794, 0, 129, 127, 0, 19, 108},
494    {8795, 0, 129, 127, 0, 19, 108},
495    {8796, 0, 129, 127, 0, 19, 108},
496    {8797, 0, 129, 127, 0, 19, 108},
497    {8798, 0, 129, 127, 0, 19, 108},
498    {8799, 0, 129, 127, 0, 19, 108},
499    {8800, 0, 129, 127, 0, 19, 108},
500    {8801, 0, 129, 127, 0, 19, 108},
501    {8802, 0, 129, 127, 0, 19, 108},
502    {8803, 0, 129, 127, 0, 19, 108},
503    {8804, 0, 129, 127, 0, 19, 108},
504    {8805, 0, 129, 127, 0, 19, 108},
505    {8806, 0, 129, 127, 0, 19, 108},
506    {8807, 0, 129, 127, 0, 19, 108},
507    {8808, 0, 129, 127, 0, 19, 108},
508    {8809, 0, 129, 127, 0, 19, 108},
509    {8810, 0, 129, 127, 0, 19, 108},
510    {8811, 0, 129, 127, 0, 19, 114},
511    {8812, 0, 129, 127, 0, 19, 102},
512    {8813, 0, 129, 127, 0, 19, 114},
513    {8814, 0, 129, 127, 0, 76, 102},
514    {8815, 0, 129, 127, 0, 13, 121},
515    {8816, 0, 129, 127, 0, 19, 114},
516    {8817, 0, 129, 127, 0, 19, 127},
517    {8818, 0, 129, 127, 0, 19, 114},
518    {8819, 0, 129, 127, 0, 218, 108},
519};
520
521int CompareCIDTransform(const void* key, const void* element) {
522  FX_WORD CID = *static_cast<const FX_WORD*>(key);
523  return CID - static_cast<const struct CIDTransform*>(element)->CID;
524}
525
526}  // namespace
527
528CPDF_CMapManager::CPDF_CMapManager() {
529  m_bPrompted = FALSE;
530  FXSYS_memset(m_CID2UnicodeMaps, 0, sizeof m_CID2UnicodeMaps);
531}
532CPDF_CMapManager::~CPDF_CMapManager() {
533  for (const auto& pair : m_CMaps) {
534    delete pair.second;
535  }
536  m_CMaps.clear();
537  for (size_t i = 0; i < FX_ArraySize(m_CID2UnicodeMaps); ++i) {
538    delete m_CID2UnicodeMaps[i];
539  }
540}
541CPDF_CMap* CPDF_CMapManager::GetPredefinedCMap(const CFX_ByteString& name,
542                                               FX_BOOL bPromptCJK) {
543  auto it = m_CMaps.find(name);
544  if (it != m_CMaps.end()) {
545    return it->second;
546  }
547  CPDF_CMap* pCMap = LoadPredefinedCMap(name, bPromptCJK);
548  if (!name.IsEmpty()) {
549    m_CMaps[name] = pCMap;
550  }
551  return pCMap;
552}
553CPDF_CMap* CPDF_CMapManager::LoadPredefinedCMap(const CFX_ByteString& name,
554                                                FX_BOOL bPromptCJK) {
555  CPDF_CMap* pCMap = new CPDF_CMap;
556  const FX_CHAR* pname = name;
557  if (*pname == '/') {
558    pname++;
559  }
560  pCMap->LoadPredefined(this, pname, bPromptCJK);
561  return pCMap;
562}
563
564void CPDF_CMapManager::ReloadAll() {
565  for (const auto& pair : m_CMaps) {
566    CPDF_CMap* pCMap = pair.second;
567    pCMap->LoadPredefined(this, pair.first, FALSE);
568  }
569  for (size_t i = 0; i < FX_ArraySize(m_CID2UnicodeMaps); ++i) {
570    if (CPDF_CID2UnicodeMap* pMap = m_CID2UnicodeMaps[i]) {
571      pMap->Load(this, CIDSetFromSizeT(i), FALSE);
572    }
573  }
574}
575CPDF_CID2UnicodeMap* CPDF_CMapManager::GetCID2UnicodeMap(CIDSet charset,
576                                                         FX_BOOL bPromptCJK) {
577  if (!m_CID2UnicodeMaps[charset])
578    m_CID2UnicodeMaps[charset] = LoadCID2UnicodeMap(charset, bPromptCJK);
579  return m_CID2UnicodeMaps[charset];
580}
581CPDF_CID2UnicodeMap* CPDF_CMapManager::LoadCID2UnicodeMap(CIDSet charset,
582                                                          FX_BOOL bPromptCJK) {
583  CPDF_CID2UnicodeMap* pMap = new CPDF_CID2UnicodeMap();
584  if (!pMap->Initialize()) {
585    delete pMap;
586    return NULL;
587  }
588  pMap->Load(this, charset, bPromptCJK);
589  return pMap;
590}
591CPDF_CMapParser::CPDF_CMapParser() {
592  m_pCMap = NULL;
593  m_Status = 0;
594  m_CodeSeq = 0;
595}
596FX_BOOL CPDF_CMapParser::Initialize(CPDF_CMap* pCMap) {
597  m_pCMap = pCMap;
598  m_Status = 0;
599  m_CodeSeq = 0;
600  m_AddMaps.EstimateSize(0, 10240);
601  return TRUE;
602}
603
604void CPDF_CMapParser::ParseWord(const CFX_ByteStringC& word) {
605  if (word.IsEmpty()) {
606    return;
607  }
608  if (word == "begincidchar") {
609    m_Status = 1;
610    m_CodeSeq = 0;
611  } else if (word == "begincidrange") {
612    m_Status = 2;
613    m_CodeSeq = 0;
614  } else if (word == "endcidrange" || word == "endcidchar") {
615    m_Status = 0;
616  } else if (word == "/WMode") {
617    m_Status = 6;
618  } else if (word == "/Registry") {
619    m_Status = 3;
620  } else if (word == "/Ordering") {
621    m_Status = 4;
622  } else if (word == "/Supplement") {
623    m_Status = 5;
624  } else if (word == "begincodespacerange") {
625    m_Status = 7;
626    m_CodeSeq = 0;
627  } else if (word == "usecmap") {
628  } else if (m_Status == 1 || m_Status == 2) {
629    m_CodePoints[m_CodeSeq] = CMap_GetCode(word);
630    m_CodeSeq++;
631    FX_DWORD StartCode, EndCode;
632    FX_WORD StartCID;
633    if (m_Status == 1) {
634      if (m_CodeSeq < 2) {
635        return;
636      }
637      EndCode = StartCode = m_CodePoints[0];
638      StartCID = (FX_WORD)m_CodePoints[1];
639    } else {
640      if (m_CodeSeq < 3) {
641        return;
642      }
643      StartCode = m_CodePoints[0];
644      EndCode = m_CodePoints[1];
645      StartCID = (FX_WORD)m_CodePoints[2];
646    }
647    if (EndCode < 0x10000) {
648      for (FX_DWORD code = StartCode; code <= EndCode; code++) {
649        m_pCMap->m_pMapping[code] = (FX_WORD)(StartCID + code - StartCode);
650      }
651    } else {
652      FX_DWORD buf[2];
653      buf[0] = StartCode;
654      buf[1] = ((EndCode - StartCode) << 16) + StartCID;
655      m_AddMaps.AppendBlock(buf, sizeof buf);
656    }
657    m_CodeSeq = 0;
658  } else if (m_Status == 3) {
659    CMap_GetString(word);
660    m_Status = 0;
661  } else if (m_Status == 4) {
662    m_pCMap->m_Charset = CharsetFromOrdering(CMap_GetString(word));
663    m_Status = 0;
664  } else if (m_Status == 5) {
665    CMap_GetCode(word);
666    m_Status = 0;
667  } else if (m_Status == 6) {
668    m_pCMap->m_bVertical = CMap_GetCode(word);
669    m_Status = 0;
670  } else if (m_Status == 7) {
671    if (word == "endcodespacerange") {
672      int nSegs = m_CodeRanges.GetSize();
673      if (nSegs > 1) {
674        m_pCMap->m_CodingScheme = CPDF_CMap::MixedFourBytes;
675        m_pCMap->m_nCodeRanges = nSegs;
676        m_pCMap->m_pLeadingBytes =
677            FX_Alloc2D(uint8_t, nSegs, sizeof(CMap_CodeRange));
678        FXSYS_memcpy(m_pCMap->m_pLeadingBytes, m_CodeRanges.GetData(),
679                     nSegs * sizeof(CMap_CodeRange));
680      } else if (nSegs == 1) {
681        m_pCMap->m_CodingScheme = (m_CodeRanges[0].m_CharSize == 2)
682                                      ? CPDF_CMap::TwoBytes
683                                      : CPDF_CMap::OneByte;
684      }
685      m_Status = 0;
686    } else {
687      if (word.GetLength() == 0 || word.GetAt(0) != '<') {
688        return;
689      }
690      if (m_CodeSeq % 2) {
691        CMap_CodeRange range;
692        if (CMap_GetCodeRange(range, m_LastWord, word)) {
693          m_CodeRanges.Add(range);
694        }
695      }
696      m_CodeSeq++;
697    }
698  }
699  m_LastWord = word;
700}
701
702// Static.
703FX_DWORD CPDF_CMapParser::CMap_GetCode(const CFX_ByteStringC& word) {
704  int num = 0;
705  if (word.GetAt(0) == '<') {
706    for (int i = 1; i < word.GetLength() && std::isxdigit(word.GetAt(i)); ++i)
707      num = num * 16 + FXSYS_toHexDigit(word.GetAt(i));
708    return num;
709  }
710
711  for (int i = 0; i < word.GetLength() && std::isdigit(word.GetAt(i)); ++i)
712    num = num * 10 + FXSYS_toDecimalDigit(word.GetAt(i));
713  return num;
714}
715
716// Static.
717bool CPDF_CMapParser::CMap_GetCodeRange(CMap_CodeRange& range,
718                                        const CFX_ByteStringC& first,
719                                        const CFX_ByteStringC& second) {
720  if (first.GetLength() == 0 || first.GetAt(0) != '<')
721    return false;
722
723  int i;
724  for (i = 1; i < first.GetLength(); ++i) {
725    if (first.GetAt(i) == '>') {
726      break;
727    }
728  }
729  range.m_CharSize = (i - 1) / 2;
730  if (range.m_CharSize > 4)
731    return false;
732
733  for (i = 0; i < range.m_CharSize; ++i) {
734    uint8_t digit1 = first.GetAt(i * 2 + 1);
735    uint8_t digit2 = first.GetAt(i * 2 + 2);
736    range.m_Lower[i] = FXSYS_toHexDigit(digit1) * 16 + FXSYS_toHexDigit(digit2);
737  }
738
739  FX_DWORD size = second.GetLength();
740  for (i = 0; i < range.m_CharSize; ++i) {
741    uint8_t digit1 = ((FX_DWORD)i * 2 + 1 < size)
742                         ? second.GetAt((FX_STRSIZE)i * 2 + 1)
743                         : '0';
744    uint8_t digit2 = ((FX_DWORD)i * 2 + 2 < size)
745                         ? second.GetAt((FX_STRSIZE)i * 2 + 2)
746                         : '0';
747    range.m_Upper[i] = FXSYS_toHexDigit(digit1) * 16 + FXSYS_toHexDigit(digit2);
748  }
749  return true;
750}
751
752CPDF_CMap::CPDF_CMap() {
753  m_Charset = CIDSET_UNKNOWN;
754  m_Coding = CIDCODING_UNKNOWN;
755  m_CodingScheme = TwoBytes;
756  m_bVertical = 0;
757  m_bLoaded = FALSE;
758  m_pMapping = NULL;
759  m_pLeadingBytes = NULL;
760  m_pAddMapping = NULL;
761  m_pEmbedMap = NULL;
762  m_pUseMap = NULL;
763  m_nCodeRanges = 0;
764}
765CPDF_CMap::~CPDF_CMap() {
766  FX_Free(m_pMapping);
767  FX_Free(m_pAddMapping);
768  FX_Free(m_pLeadingBytes);
769  delete m_pUseMap;
770}
771void CPDF_CMap::Release() {
772  if (m_PredefinedCMap.IsEmpty()) {
773    delete this;
774  }
775}
776
777FX_BOOL CPDF_CMap::LoadPredefined(CPDF_CMapManager* pMgr,
778                                  const FX_CHAR* pName,
779                                  FX_BOOL bPromptCJK) {
780  m_PredefinedCMap = pName;
781  if (m_PredefinedCMap == "Identity-H" || m_PredefinedCMap == "Identity-V") {
782    m_Coding = CIDCODING_CID;
783    m_bVertical = pName[9] == 'V';
784    m_bLoaded = TRUE;
785    return TRUE;
786  }
787  CFX_ByteString cmapid = m_PredefinedCMap;
788  m_bVertical = cmapid.Right(1) == "V";
789  if (cmapid.GetLength() > 2) {
790    cmapid = cmapid.Left(cmapid.GetLength() - 2);
791  }
792  const CPDF_PredefinedCMap* map = nullptr;
793  for (size_t i = 0; i < FX_ArraySize(g_PredefinedCMaps); ++i) {
794    if (cmapid == CFX_ByteStringC(g_PredefinedCMaps[i].m_pName)) {
795      map = &g_PredefinedCMaps[i];
796      break;
797    }
798  }
799  if (!map)
800    return FALSE;
801
802  m_Charset = map->m_Charset;
803  m_Coding = map->m_Coding;
804  m_CodingScheme = map->m_CodingScheme;
805  if (m_CodingScheme == MixedTwoBytes) {
806    m_pLeadingBytes = FX_Alloc(uint8_t, 256);
807    for (FX_DWORD i = 0; i < map->m_LeadingSegCount; ++i) {
808      const uint8_t* segs = map->m_LeadingSegs;
809      for (int b = segs[i * 2]; b <= segs[i * 2 + 1]; ++b) {
810        m_pLeadingBytes[b] = 1;
811      }
812    }
813  }
814  FPDFAPI_FindEmbeddedCMap(pName, m_Charset, m_Coding, m_pEmbedMap);
815  if (m_pEmbedMap) {
816    m_bLoaded = TRUE;
817    return TRUE;
818  }
819  return FALSE;
820}
821FX_BOOL CPDF_CMap::LoadEmbedded(const uint8_t* pData, FX_DWORD size) {
822  m_pMapping = FX_Alloc(FX_WORD, 65536);
823  CPDF_CMapParser parser;
824  parser.Initialize(this);
825  CPDF_SimpleParser syntax(pData, size);
826  while (1) {
827    CFX_ByteStringC word = syntax.GetWord();
828    if (word.IsEmpty()) {
829      break;
830    }
831    parser.ParseWord(word);
832  }
833  if (m_CodingScheme == MixedFourBytes && parser.m_AddMaps.GetSize()) {
834    m_pAddMapping = FX_Alloc(uint8_t, parser.m_AddMaps.GetSize() + 4);
835    *(FX_DWORD*)m_pAddMapping = parser.m_AddMaps.GetSize() / 8;
836    FXSYS_memcpy(m_pAddMapping + 4, parser.m_AddMaps.GetBuffer(),
837                 parser.m_AddMaps.GetSize());
838    FXSYS_qsort(m_pAddMapping + 4, parser.m_AddMaps.GetSize() / 8, 8,
839                CompareDWORD);
840  }
841  return TRUE;
842}
843
844FX_WORD CPDF_CMap::CIDFromCharCode(FX_DWORD charcode) const {
845  if (m_Coding == CIDCODING_CID) {
846    return (FX_WORD)charcode;
847  }
848  if (m_pEmbedMap) {
849    return FPDFAPI_CIDFromCharCode(m_pEmbedMap, charcode);
850  }
851  if (!m_pMapping) {
852    return (FX_WORD)charcode;
853  }
854  if (charcode >> 16) {
855    if (m_pAddMapping) {
856      void* found = FXSYS_bsearch(&charcode, m_pAddMapping + 4,
857                                  *(FX_DWORD*)m_pAddMapping, 8, CompareCID);
858      if (!found) {
859        if (m_pUseMap) {
860          return m_pUseMap->CIDFromCharCode(charcode);
861        }
862        return 0;
863      }
864      return (FX_WORD)(((FX_DWORD*)found)[1] % 65536 + charcode -
865                       *(FX_DWORD*)found);
866    }
867    if (m_pUseMap)
868      return m_pUseMap->CIDFromCharCode(charcode);
869    return 0;
870  }
871  FX_DWORD CID = m_pMapping[charcode];
872  if (!CID && m_pUseMap)
873    return m_pUseMap->CIDFromCharCode(charcode);
874  return (FX_WORD)CID;
875}
876
877FX_DWORD CPDF_CMap::GetNextChar(const FX_CHAR* pString,
878                                int nStrLen,
879                                int& offset) const {
880  switch (m_CodingScheme) {
881    case OneByte:
882      return ((uint8_t*)pString)[offset++];
883    case TwoBytes:
884      offset += 2;
885      return ((uint8_t*)pString)[offset - 2] * 256 +
886             ((uint8_t*)pString)[offset - 1];
887    case MixedTwoBytes: {
888      uint8_t byte1 = ((uint8_t*)pString)[offset++];
889      if (!m_pLeadingBytes[byte1]) {
890        return byte1;
891      }
892      uint8_t byte2 = ((uint8_t*)pString)[offset++];
893      return byte1 * 256 + byte2;
894    }
895    case MixedFourBytes: {
896      uint8_t codes[4];
897      int char_size = 1;
898      codes[0] = ((uint8_t*)pString)[offset++];
899      CMap_CodeRange* pRanges = (CMap_CodeRange*)m_pLeadingBytes;
900      while (1) {
901        int ret = CheckCodeRange(codes, char_size, pRanges, m_nCodeRanges);
902        if (ret == 0) {
903          return 0;
904        }
905        if (ret == 2) {
906          FX_DWORD charcode = 0;
907          for (int i = 0; i < char_size; i++) {
908            charcode = (charcode << 8) + codes[i];
909          }
910          return charcode;
911        }
912        if (char_size == 4 || offset == nStrLen) {
913          return 0;
914        }
915        codes[char_size++] = ((uint8_t*)pString)[offset++];
916      }
917      break;
918    }
919  }
920  return 0;
921}
922int CPDF_CMap::GetCharSize(FX_DWORD charcode) const {
923  switch (m_CodingScheme) {
924    case OneByte:
925      return 1;
926    case TwoBytes:
927      return 2;
928    case MixedTwoBytes:
929    case MixedFourBytes:
930      if (charcode < 0x100) {
931        return 1;
932      }
933      if (charcode < 0x10000) {
934        return 2;
935      }
936      if (charcode < 0x1000000) {
937        return 3;
938      }
939      return 4;
940  }
941  return 1;
942}
943int CPDF_CMap::CountChar(const FX_CHAR* pString, int size) const {
944  switch (m_CodingScheme) {
945    case OneByte:
946      return size;
947    case TwoBytes:
948      return (size + 1) / 2;
949    case MixedTwoBytes: {
950      int count = 0;
951      for (int i = 0; i < size; i++) {
952        count++;
953        if (m_pLeadingBytes[((uint8_t*)pString)[i]]) {
954          i++;
955        }
956      }
957      return count;
958    }
959    case MixedFourBytes: {
960      int count = 0, offset = 0;
961      while (offset < size) {
962        GetNextChar(pString, size, offset);
963        count++;
964      }
965      return count;
966    }
967  }
968  return size;
969}
970
971int CPDF_CMap::AppendChar(FX_CHAR* str, FX_DWORD charcode) const {
972  switch (m_CodingScheme) {
973    case OneByte:
974      str[0] = (uint8_t)charcode;
975      return 1;
976    case TwoBytes:
977      str[0] = (uint8_t)(charcode / 256);
978      str[1] = (uint8_t)(charcode % 256);
979      return 2;
980    case MixedTwoBytes:
981    case MixedFourBytes:
982      if (charcode < 0x100) {
983        CMap_CodeRange* pRanges = (CMap_CodeRange*)m_pLeadingBytes;
984        int iSize = GetCharSizeImpl(charcode, pRanges, m_nCodeRanges);
985        if (iSize == 0) {
986          iSize = 1;
987        }
988        if (iSize > 1) {
989          FXSYS_memset(str, 0, sizeof(uint8_t) * iSize);
990        }
991        str[iSize - 1] = (uint8_t)charcode;
992        return iSize;
993      }
994      if (charcode < 0x10000) {
995        str[0] = (uint8_t)(charcode >> 8);
996        str[1] = (uint8_t)charcode;
997        return 2;
998      }
999      if (charcode < 0x1000000) {
1000        str[0] = (uint8_t)(charcode >> 16);
1001        str[1] = (uint8_t)(charcode >> 8);
1002        str[2] = (uint8_t)charcode;
1003        return 3;
1004      }
1005      str[0] = (uint8_t)(charcode >> 24);
1006      str[1] = (uint8_t)(charcode >> 16);
1007      str[2] = (uint8_t)(charcode >> 8);
1008      str[3] = (uint8_t)charcode;
1009      return 4;
1010  }
1011  return 0;
1012}
1013CPDF_CID2UnicodeMap::CPDF_CID2UnicodeMap() {
1014  m_EmbeddedCount = 0;
1015}
1016CPDF_CID2UnicodeMap::~CPDF_CID2UnicodeMap() {}
1017FX_BOOL CPDF_CID2UnicodeMap::Initialize() {
1018  return TRUE;
1019}
1020FX_BOOL CPDF_CID2UnicodeMap::IsLoaded() {
1021  return m_EmbeddedCount != 0;
1022}
1023FX_WCHAR CPDF_CID2UnicodeMap::UnicodeFromCID(FX_WORD CID) {
1024  if (m_Charset == CIDSET_UNICODE) {
1025    return CID;
1026  }
1027  if (CID < m_EmbeddedCount) {
1028    return m_pEmbeddedMap[CID];
1029  }
1030  return 0;
1031}
1032
1033void CPDF_CID2UnicodeMap::Load(CPDF_CMapManager* pMgr,
1034                               CIDSet charset,
1035                               FX_BOOL bPromptCJK) {
1036  m_Charset = charset;
1037  FPDFAPI_LoadCID2UnicodeMap(charset, m_pEmbeddedMap, m_EmbeddedCount);
1038}
1039
1040#include "ttgsubtable.h"
1041CPDF_CIDFont::CPDF_CIDFont() : CPDF_Font(PDFFONT_CIDFONT) {
1042  m_pCMap = NULL;
1043  m_pAllocatedCMap = NULL;
1044  m_pCID2UnicodeMap = NULL;
1045  m_pAnsiWidths = NULL;
1046  m_pCIDToGIDMap = NULL;
1047  m_bCIDIsGID = FALSE;
1048  m_bAdobeCourierStd = FALSE;
1049  m_pTTGSUBTable = NULL;
1050  FXSYS_memset(m_CharBBox, 0xff, 256 * sizeof(FX_SMALL_RECT));
1051}
1052CPDF_CIDFont::~CPDF_CIDFont() {
1053  if (m_pAnsiWidths) {
1054    FX_Free(m_pAnsiWidths);
1055  }
1056  delete m_pAllocatedCMap;
1057  delete m_pCIDToGIDMap;
1058  delete m_pTTGSUBTable;
1059}
1060FX_WORD CPDF_CIDFont::CIDFromCharCode(FX_DWORD charcode) const {
1061  if (!m_pCMap) {
1062    return (FX_WORD)charcode;
1063  }
1064  return m_pCMap->CIDFromCharCode(charcode);
1065}
1066FX_BOOL CPDF_CIDFont::IsVertWriting() const {
1067  return m_pCMap ? m_pCMap->IsVertWriting() : FALSE;
1068}
1069
1070FX_WCHAR CPDF_CIDFont::_UnicodeFromCharCode(FX_DWORD charcode) const {
1071  switch (m_pCMap->m_Coding) {
1072    case CIDCODING_UCS2:
1073    case CIDCODING_UTF16:
1074      return (FX_WCHAR)charcode;
1075    case CIDCODING_CID:
1076      if (!m_pCID2UnicodeMap || !m_pCID2UnicodeMap->IsLoaded()) {
1077        return 0;
1078      }
1079      return m_pCID2UnicodeMap->UnicodeFromCID((FX_WORD)charcode);
1080  }
1081  if (!m_pCMap->IsLoaded() || !m_pCID2UnicodeMap ||
1082      !m_pCID2UnicodeMap->IsLoaded()) {
1083#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
1084    FX_WCHAR unicode;
1085    int charsize = 1;
1086    if (charcode > 255) {
1087      charcode = (charcode % 256) * 256 + (charcode / 256);
1088      charsize = 2;
1089    }
1090    int ret = FXSYS_MultiByteToWideChar(g_CharsetCPs[m_pCMap->m_Coding], 0,
1091                                        (const FX_CHAR*)&charcode, charsize,
1092                                        &unicode, 1);
1093    if (ret != 1) {
1094      return 0;
1095    }
1096    return unicode;
1097#endif
1098    if (m_pCMap->m_pEmbedMap) {
1099      return EmbeddedUnicodeFromCharcode(m_pCMap->m_pEmbedMap,
1100                                         m_pCMap->m_Charset, charcode);
1101    }
1102    return 0;
1103  }
1104  return m_pCID2UnicodeMap->UnicodeFromCID(CIDFromCharCode(charcode));
1105}
1106FX_DWORD CPDF_CIDFont::_CharCodeFromUnicode(FX_WCHAR unicode) const {
1107  switch (m_pCMap->m_Coding) {
1108    case CIDCODING_UNKNOWN:
1109      return 0;
1110    case CIDCODING_UCS2:
1111    case CIDCODING_UTF16:
1112      return unicode;
1113    case CIDCODING_CID: {
1114      if (!m_pCID2UnicodeMap || !m_pCID2UnicodeMap->IsLoaded()) {
1115        return 0;
1116      }
1117      FX_DWORD CID = 0;
1118      while (CID < 65536) {
1119        FX_WCHAR this_unicode = m_pCID2UnicodeMap->UnicodeFromCID((FX_WORD)CID);
1120        if (this_unicode == unicode) {
1121          return CID;
1122        }
1123        CID++;
1124      }
1125      break;
1126    }
1127  }
1128
1129  if (unicode < 0x80) {
1130    return static_cast<FX_DWORD>(unicode);
1131  }
1132  if (m_pCMap->m_Coding == CIDCODING_CID) {
1133    return 0;
1134  }
1135#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
1136  uint8_t buffer[32];
1137  int ret =
1138      FXSYS_WideCharToMultiByte(g_CharsetCPs[m_pCMap->m_Coding], 0, &unicode, 1,
1139                                (char*)buffer, 4, NULL, NULL);
1140  if (ret == 1) {
1141    return buffer[0];
1142  }
1143  if (ret == 2) {
1144    return buffer[0] * 256 + buffer[1];
1145  }
1146#else
1147  if (m_pCMap->m_pEmbedMap) {
1148    return EmbeddedCharcodeFromUnicode(m_pCMap->m_pEmbedMap, m_pCMap->m_Charset,
1149                                       unicode);
1150  }
1151#endif
1152  return 0;
1153}
1154
1155FX_BOOL CPDF_CIDFont::_Load() {
1156  if (m_pFontDict->GetString("Subtype") == "TrueType") {
1157    return LoadGB2312();
1158  }
1159  CPDF_Array* pFonts = m_pFontDict->GetArray("DescendantFonts");
1160  if (!pFonts) {
1161    return FALSE;
1162  }
1163  if (pFonts->GetCount() != 1) {
1164    return FALSE;
1165  }
1166  CPDF_Dictionary* pCIDFontDict = pFonts->GetDict(0);
1167  if (!pCIDFontDict) {
1168    return FALSE;
1169  }
1170  m_BaseFont = pCIDFontDict->GetString("BaseFont");
1171  if ((m_BaseFont.Compare("CourierStd") == 0 ||
1172       m_BaseFont.Compare("CourierStd-Bold") == 0 ||
1173       m_BaseFont.Compare("CourierStd-BoldOblique") == 0 ||
1174       m_BaseFont.Compare("CourierStd-Oblique") == 0) &&
1175      !IsEmbedded()) {
1176    m_bAdobeCourierStd = TRUE;
1177  }
1178  CPDF_Dictionary* pFontDesc = pCIDFontDict->GetDict("FontDescriptor");
1179  if (pFontDesc) {
1180    LoadFontDescriptor(pFontDesc);
1181  }
1182  CPDF_Object* pEncoding = m_pFontDict->GetElementValue("Encoding");
1183  if (!pEncoding) {
1184    return FALSE;
1185  }
1186  CFX_ByteString subtype = pCIDFontDict->GetString("Subtype");
1187  m_bType1 = (subtype == "CIDFontType0");
1188
1189  if (pEncoding->IsName()) {
1190    CFX_ByteString cmap = pEncoding->GetString();
1191    m_pCMap =
1192        CPDF_ModuleMgr::Get()
1193            ->GetPageModule()
1194            ->GetFontGlobals()
1195            ->m_CMapManager.GetPredefinedCMap(cmap, m_pFontFile && m_bType1);
1196  } else if (CPDF_Stream* pStream = pEncoding->AsStream()) {
1197    m_pAllocatedCMap = m_pCMap = new CPDF_CMap;
1198    CPDF_StreamAcc acc;
1199    acc.LoadAllData(pStream, FALSE);
1200    m_pCMap->LoadEmbedded(acc.GetData(), acc.GetSize());
1201  } else {
1202    return FALSE;
1203  }
1204  if (!m_pCMap) {
1205    return FALSE;
1206  }
1207  m_Charset = m_pCMap->m_Charset;
1208  if (m_Charset == CIDSET_UNKNOWN) {
1209    CPDF_Dictionary* pCIDInfo = pCIDFontDict->GetDict("CIDSystemInfo");
1210    if (pCIDInfo) {
1211      m_Charset = CharsetFromOrdering(pCIDInfo->GetString("Ordering"));
1212    }
1213  }
1214  if (m_Charset != CIDSET_UNKNOWN)
1215    m_pCID2UnicodeMap =
1216        CPDF_ModuleMgr::Get()
1217            ->GetPageModule()
1218            ->GetFontGlobals()
1219            ->m_CMapManager.GetCID2UnicodeMap(
1220                m_Charset,
1221                !m_pFontFile && (m_pCMap->m_Coding == CIDCODING_CID ||
1222                                 pCIDFontDict->KeyExist("W")));
1223  if (m_Font.GetFace()) {
1224    if (m_bType1) {
1225      FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE);
1226    } else {
1227      FT_UseCIDCharmap(m_Font.GetFace(), m_pCMap->m_Coding);
1228    }
1229  }
1230  m_DefaultWidth = pCIDFontDict->GetInteger("DW", 1000);
1231  CPDF_Array* pWidthArray = pCIDFontDict->GetArray("W");
1232  if (pWidthArray) {
1233    LoadMetricsArray(pWidthArray, m_WidthList, 1);
1234  }
1235  if (!IsEmbedded()) {
1236    LoadSubstFont();
1237  }
1238  if (1) {
1239    if (m_pFontFile || (GetSubstFont()->m_SubstFlags & FXFONT_SUBST_EXACT)) {
1240      CPDF_Object* pmap = pCIDFontDict->GetElementValue("CIDToGIDMap");
1241      if (pmap) {
1242        if (CPDF_Stream* pStream = pmap->AsStream()) {
1243          m_pCIDToGIDMap = new CPDF_StreamAcc;
1244          m_pCIDToGIDMap->LoadAllData(pStream, FALSE);
1245        } else if (pmap->GetString() == "Identity") {
1246#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
1247          if (m_pFontFile) {
1248            m_bCIDIsGID = TRUE;
1249          }
1250#else
1251          m_bCIDIsGID = TRUE;
1252#endif
1253        }
1254      }
1255    }
1256  }
1257  CheckFontMetrics();
1258  if (IsVertWriting()) {
1259    pWidthArray = pCIDFontDict->GetArray("W2");
1260    if (pWidthArray) {
1261      LoadMetricsArray(pWidthArray, m_VertMetrics, 3);
1262    }
1263    CPDF_Array* pDefaultArray = pCIDFontDict->GetArray("DW2");
1264    if (pDefaultArray) {
1265      m_DefaultVY = pDefaultArray->GetInteger(0);
1266      m_DefaultW1 = pDefaultArray->GetInteger(1);
1267    } else {
1268      m_DefaultVY = 880;
1269      m_DefaultW1 = -1000;
1270    }
1271  }
1272  return TRUE;
1273}
1274
1275void CPDF_CIDFont::GetCharBBox(FX_DWORD charcode, FX_RECT& rect, int level) {
1276  if (charcode < 256 && m_CharBBox[charcode].Right != -1) {
1277    rect.bottom = m_CharBBox[charcode].Bottom;
1278    rect.left = m_CharBBox[charcode].Left;
1279    rect.right = m_CharBBox[charcode].Right;
1280    rect.top = m_CharBBox[charcode].Top;
1281    return;
1282  }
1283  FX_BOOL bVert = FALSE;
1284  int glyph_index = GlyphFromCharCode(charcode, &bVert);
1285  FXFT_Face face = m_Font.GetFace();
1286  if (face) {
1287    rect.left = rect.bottom = rect.right = rect.top = 0;
1288    if (FXFT_Is_Face_Tricky(face)) {
1289      int err = FXFT_Load_Glyph(face, glyph_index,
1290                                FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
1291      if (!err) {
1292        FXFT_BBox cbox;
1293        FXFT_Glyph glyph;
1294        err = FXFT_Get_Glyph(((FXFT_Face)face)->glyph, &glyph);
1295        if (!err) {
1296          FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox);
1297          int pixel_size_x = ((FXFT_Face)face)->size->metrics.x_ppem;
1298          int pixel_size_y = ((FXFT_Face)face)->size->metrics.y_ppem;
1299          if (pixel_size_x == 0 || pixel_size_y == 0) {
1300            rect.left = cbox.xMin;
1301            rect.right = cbox.xMax;
1302            rect.top = cbox.yMax;
1303            rect.bottom = cbox.yMin;
1304          } else {
1305            rect.left = cbox.xMin * 1000 / pixel_size_x;
1306            rect.right = cbox.xMax * 1000 / pixel_size_x;
1307            rect.top = cbox.yMax * 1000 / pixel_size_y;
1308            rect.bottom = cbox.yMin * 1000 / pixel_size_y;
1309          }
1310          if (rect.top > FXFT_Get_Face_Ascender(face)) {
1311            rect.top = FXFT_Get_Face_Ascender(face);
1312          }
1313          if (rect.bottom < FXFT_Get_Face_Descender(face)) {
1314            rect.bottom = FXFT_Get_Face_Descender(face);
1315          }
1316          FXFT_Done_Glyph(glyph);
1317        }
1318      }
1319    } else {
1320      int err = FXFT_Load_Glyph(face, glyph_index, FXFT_LOAD_NO_SCALE);
1321      if (err == 0) {
1322        rect.left = TT2PDF(FXFT_Get_Glyph_HoriBearingX(face), face);
1323        rect.right = TT2PDF(
1324            FXFT_Get_Glyph_HoriBearingX(face) + FXFT_Get_Glyph_Width(face),
1325            face);
1326        rect.top = TT2PDF(FXFT_Get_Glyph_HoriBearingY(face), face);
1327        rect.top += rect.top / 64;
1328        rect.bottom = TT2PDF(
1329            FXFT_Get_Glyph_HoriBearingY(face) - FXFT_Get_Glyph_Height(face),
1330            face);
1331      }
1332    }
1333  } else {
1334    rect = FX_RECT(0, 0, 0, 0);
1335  }
1336  if (!m_pFontFile && m_Charset == CIDSET_JAPAN1) {
1337    FX_WORD CID = CIDFromCharCode(charcode);
1338    const uint8_t* pTransform = GetCIDTransform(CID);
1339    if (pTransform && !bVert) {
1340      CFX_Matrix matrix(CIDTransformToFloat(pTransform[0]),
1341                        CIDTransformToFloat(pTransform[1]),
1342                        CIDTransformToFloat(pTransform[2]),
1343                        CIDTransformToFloat(pTransform[3]),
1344                        CIDTransformToFloat(pTransform[4]) * 1000,
1345                        CIDTransformToFloat(pTransform[5]) * 1000);
1346      CFX_FloatRect rect_f(rect);
1347      rect_f.Transform(&matrix);
1348      rect = rect_f.GetOutterRect();
1349    }
1350  }
1351  if (charcode < 256) {
1352    m_CharBBox[charcode].Bottom = (short)rect.bottom;
1353    m_CharBBox[charcode].Left = (short)rect.left;
1354    m_CharBBox[charcode].Right = (short)rect.right;
1355    m_CharBBox[charcode].Top = (short)rect.top;
1356  }
1357}
1358int CPDF_CIDFont::GetCharWidthF(FX_DWORD charcode, int level) {
1359  if (m_pAnsiWidths && charcode < 0x80) {
1360    return m_pAnsiWidths[charcode];
1361  }
1362  FX_WORD cid = CIDFromCharCode(charcode);
1363  int size = m_WidthList.GetSize();
1364  FX_DWORD* list = m_WidthList.GetData();
1365  for (int i = 0; i < size; i += 3) {
1366    if (cid >= list[i] && cid <= list[i + 1]) {
1367      return (int)list[i + 2];
1368    }
1369  }
1370  return m_DefaultWidth;
1371}
1372short CPDF_CIDFont::GetVertWidth(FX_WORD CID) const {
1373  FX_DWORD vertsize = m_VertMetrics.GetSize() / 5;
1374  if (vertsize == 0) {
1375    return m_DefaultW1;
1376  }
1377  const FX_DWORD* pTable = m_VertMetrics.GetData();
1378  for (FX_DWORD i = 0; i < vertsize; i++)
1379    if (pTable[i * 5] <= CID && pTable[i * 5 + 1] >= CID) {
1380      return (short)(int)pTable[i * 5 + 2];
1381    }
1382  return m_DefaultW1;
1383}
1384void CPDF_CIDFont::GetVertOrigin(FX_WORD CID, short& vx, short& vy) const {
1385  FX_DWORD vertsize = m_VertMetrics.GetSize() / 5;
1386  if (vertsize) {
1387    const FX_DWORD* pTable = m_VertMetrics.GetData();
1388    for (FX_DWORD i = 0; i < vertsize; i++)
1389      if (pTable[i * 5] <= CID && pTable[i * 5 + 1] >= CID) {
1390        vx = (short)(int)pTable[i * 5 + 3];
1391        vy = (short)(int)pTable[i * 5 + 4];
1392        return;
1393      }
1394  }
1395  FX_DWORD dwWidth = m_DefaultWidth;
1396  int size = m_WidthList.GetSize();
1397  const FX_DWORD* list = m_WidthList.GetData();
1398  for (int i = 0; i < size; i += 3) {
1399    if (CID >= list[i] && CID <= list[i + 1]) {
1400      dwWidth = (FX_WORD)list[i + 2];
1401      break;
1402    }
1403  }
1404  vx = (short)dwWidth / 2;
1405  vy = (short)m_DefaultVY;
1406}
1407int CPDF_CIDFont::GetGlyphIndex(FX_DWORD unicode, FX_BOOL* pVertGlyph) {
1408  if (pVertGlyph) {
1409    *pVertGlyph = FALSE;
1410  }
1411  FXFT_Face face = m_Font.GetFace();
1412  int index = FXFT_Get_Char_Index(face, unicode);
1413  if (unicode == 0x2502) {
1414    return index;
1415  }
1416  if (index && IsVertWriting()) {
1417    if (m_pTTGSUBTable) {
1418      uint32_t vindex = 0;
1419      m_pTTGSUBTable->GetVerticalGlyph(index, &vindex);
1420      if (vindex) {
1421        index = vindex;
1422        if (pVertGlyph) {
1423          *pVertGlyph = TRUE;
1424        }
1425      }
1426      return index;
1427    }
1428    if (!m_Font.GetSubData()) {
1429      unsigned long length = 0;
1430      int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
1431                                       NULL, &length);
1432      if (!error) {
1433        m_Font.SetSubData(FX_Alloc(uint8_t, length));
1434      }
1435    }
1436    int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
1437                                     m_Font.GetSubData(), NULL);
1438    if (!error && m_Font.GetSubData()) {
1439      m_pTTGSUBTable = new CFX_CTTGSUBTable;
1440      m_pTTGSUBTable->LoadGSUBTable((FT_Bytes)m_Font.GetSubData());
1441      uint32_t vindex = 0;
1442      m_pTTGSUBTable->GetVerticalGlyph(index, &vindex);
1443      if (vindex) {
1444        index = vindex;
1445        if (pVertGlyph) {
1446          *pVertGlyph = TRUE;
1447        }
1448      }
1449    }
1450    return index;
1451  }
1452  if (pVertGlyph) {
1453    *pVertGlyph = FALSE;
1454  }
1455  return index;
1456}
1457int CPDF_CIDFont::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL* pVertGlyph) {
1458  if (pVertGlyph) {
1459    *pVertGlyph = FALSE;
1460  }
1461  if (!m_pFontFile && !m_pCIDToGIDMap) {
1462    FX_WORD cid = CIDFromCharCode(charcode);
1463    FX_WCHAR unicode = 0;
1464    if (m_bCIDIsGID) {
1465#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
1466      return cid;
1467#else
1468      if (m_Flags & PDFFONT_SYMBOLIC) {
1469        return cid;
1470      }
1471      CFX_WideString uni_str = UnicodeFromCharCode(charcode);
1472      if (uni_str.IsEmpty()) {
1473        return cid;
1474      }
1475      unicode = uni_str.GetAt(0);
1476#endif
1477    } else {
1478      if (cid && m_pCID2UnicodeMap && m_pCID2UnicodeMap->IsLoaded()) {
1479        unicode = m_pCID2UnicodeMap->UnicodeFromCID(cid);
1480      }
1481      if (unicode == 0) {
1482        unicode = _UnicodeFromCharCode(charcode);
1483      }
1484      if (unicode == 0 && !(m_Flags & PDFFONT_SYMBOLIC)) {
1485        unicode = UnicodeFromCharCode(charcode).GetAt(0);
1486      }
1487    }
1488    FXFT_Face face = m_Font.GetFace();
1489    if (unicode == 0) {
1490      if (!m_bAdobeCourierStd) {
1491        return charcode == 0 ? -1 : (int)charcode;
1492      }
1493      charcode += 31;
1494      int index = 0, iBaseEncoding;
1495      FX_BOOL bMSUnicode = FT_UseTTCharmap(face, 3, 1);
1496      FX_BOOL bMacRoman = FALSE;
1497      if (!bMSUnicode) {
1498        bMacRoman = FT_UseTTCharmap(face, 1, 0);
1499      }
1500      iBaseEncoding = PDFFONT_ENCODING_STANDARD;
1501      if (bMSUnicode) {
1502        iBaseEncoding = PDFFONT_ENCODING_WINANSI;
1503      } else if (bMacRoman) {
1504        iBaseEncoding = PDFFONT_ENCODING_MACROMAN;
1505      }
1506      const FX_CHAR* name = GetAdobeCharName(iBaseEncoding, NULL, charcode);
1507      if (!name) {
1508        return charcode == 0 ? -1 : (int)charcode;
1509      }
1510      FX_WORD unicode = PDF_UnicodeFromAdobeName(name);
1511      if (unicode) {
1512        if (bMSUnicode) {
1513          index = FXFT_Get_Char_Index(face, unicode);
1514        } else if (bMacRoman) {
1515          FX_DWORD maccode =
1516              FT_CharCodeFromUnicode(FXFT_ENCODING_APPLE_ROMAN, unicode);
1517          index = !maccode ? FXFT_Get_Name_Index(face, (char*)name)
1518                           : FXFT_Get_Char_Index(face, maccode);
1519        } else {
1520          return FXFT_Get_Char_Index(face, unicode);
1521        }
1522      } else {
1523        return charcode == 0 ? -1 : (int)charcode;
1524      }
1525      if (index == 0 || index == 0xffff) {
1526        return charcode == 0 ? -1 : (int)charcode;
1527      }
1528      return index;
1529    }
1530    if (m_Charset == CIDSET_JAPAN1) {
1531      if (unicode == '\\') {
1532        unicode = '/';
1533      }
1534#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
1535      else if (unicode == 0xa5) {
1536        unicode = 0x5c;
1537      }
1538#endif
1539    }
1540    if (!face)
1541      return unicode;
1542
1543    int err = FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE);
1544    if (err != 0) {
1545      int i;
1546      for (i = 0; i < FXFT_Get_Face_CharmapCount(face); i++) {
1547        FX_DWORD ret = FT_CharCodeFromUnicode(
1548            FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i]),
1549            (FX_WCHAR)charcode);
1550        if (ret == 0) {
1551          continue;
1552        }
1553        FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[i]);
1554        unicode = (FX_WCHAR)ret;
1555        break;
1556      }
1557      if (i == FXFT_Get_Face_CharmapCount(face) && i) {
1558        FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]);
1559        unicode = (FX_WCHAR)charcode;
1560      }
1561    }
1562    if (FXFT_Get_Face_Charmap(face)) {
1563      int index = GetGlyphIndex(unicode, pVertGlyph);
1564      if (index == 0)
1565        return -1;
1566      return index;
1567    }
1568    return unicode;
1569  }
1570  if (!m_Font.GetFace())
1571    return -1;
1572
1573  FX_WORD cid = CIDFromCharCode(charcode);
1574  if (m_bType1) {
1575    if (!m_pCIDToGIDMap) {
1576      return cid;
1577    }
1578  } else {
1579    if (!m_pCIDToGIDMap) {
1580      if (m_pFontFile && !m_pCMap->m_pMapping)
1581        return cid;
1582      if (m_pCMap->m_Coding == CIDCODING_UNKNOWN ||
1583          !FXFT_Get_Face_Charmap(m_Font.GetFace())) {
1584        return cid;
1585      }
1586      if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmap(m_Font.GetFace())) ==
1587          FXFT_ENCODING_UNICODE) {
1588        CFX_WideString unicode_str = UnicodeFromCharCode(charcode);
1589        if (unicode_str.IsEmpty()) {
1590          return -1;
1591        }
1592        charcode = unicode_str.GetAt(0);
1593      }
1594      return GetGlyphIndex(charcode, pVertGlyph);
1595    }
1596  }
1597  FX_DWORD byte_pos = cid * 2;
1598  if (byte_pos + 2 > m_pCIDToGIDMap->GetSize())
1599    return -1;
1600
1601  const uint8_t* pdata = m_pCIDToGIDMap->GetData() + byte_pos;
1602  return pdata[0] * 256 + pdata[1];
1603}
1604FX_DWORD CPDF_CIDFont::GetNextChar(const FX_CHAR* pString,
1605                                   int nStrLen,
1606                                   int& offset) const {
1607  return m_pCMap->GetNextChar(pString, nStrLen, offset);
1608}
1609int CPDF_CIDFont::GetCharSize(FX_DWORD charcode) const {
1610  return m_pCMap->GetCharSize(charcode);
1611}
1612int CPDF_CIDFont::CountChar(const FX_CHAR* pString, int size) const {
1613  return m_pCMap->CountChar(pString, size);
1614}
1615int CPDF_CIDFont::AppendChar(FX_CHAR* str, FX_DWORD charcode) const {
1616  return m_pCMap->AppendChar(str, charcode);
1617}
1618FX_BOOL CPDF_CIDFont::IsUnicodeCompatible() const {
1619  if (!m_pCMap->IsLoaded() || !m_pCID2UnicodeMap ||
1620      !m_pCID2UnicodeMap->IsLoaded()) {
1621    return m_pCMap->m_Coding != CIDCODING_UNKNOWN;
1622  }
1623  return TRUE;
1624}
1625FX_BOOL CPDF_CIDFont::IsFontStyleFromCharCode(FX_DWORD charcode) const {
1626  return TRUE;
1627}
1628void CPDF_CIDFont::LoadSubstFont() {
1629  m_Font.LoadSubst(m_BaseFont, !m_bType1, m_Flags, m_StemV * 5, m_ItalicAngle,
1630                   g_CharsetCPs[m_Charset], IsVertWriting());
1631}
1632void CPDF_CIDFont::LoadMetricsArray(CPDF_Array* pArray,
1633                                    CFX_DWordArray& result,
1634                                    int nElements) {
1635  int width_status = 0;
1636  int iCurElement = 0;
1637  int first_code = 0, last_code;
1638  FX_DWORD count = pArray->GetCount();
1639  for (FX_DWORD i = 0; i < count; i++) {
1640    CPDF_Object* pObj = pArray->GetElementValue(i);
1641    if (!pObj)
1642      continue;
1643
1644    if (CPDF_Array* pArray = pObj->AsArray()) {
1645      if (width_status != 1)
1646        return;
1647
1648      FX_DWORD count = pArray->GetCount();
1649      for (FX_DWORD j = 0; j < count; j += nElements) {
1650        result.Add(first_code);
1651        result.Add(first_code);
1652        for (int k = 0; k < nElements; k++) {
1653          result.Add(pArray->GetInteger(j + k));
1654        }
1655        first_code++;
1656      }
1657      width_status = 0;
1658    } else {
1659      if (width_status == 0) {
1660        first_code = pObj->GetInteger();
1661        width_status = 1;
1662      } else if (width_status == 1) {
1663        last_code = pObj->GetInteger();
1664        width_status = 2;
1665        iCurElement = 0;
1666      } else {
1667        if (!iCurElement) {
1668          result.Add(first_code);
1669          result.Add(last_code);
1670        }
1671        result.Add(pObj->GetInteger());
1672        iCurElement++;
1673        if (iCurElement == nElements) {
1674          width_status = 0;
1675        }
1676      }
1677    }
1678  }
1679}
1680
1681// static
1682FX_FLOAT CPDF_CIDFont::CIDTransformToFloat(uint8_t ch) {
1683  if (ch < 128) {
1684    return ch * 1.0f / 127;
1685  }
1686  return (-255 + ch) * 1.0f / 127;
1687}
1688
1689FX_BOOL CPDF_CIDFont::LoadGB2312() {
1690  m_BaseFont = m_pFontDict->GetString("BaseFont");
1691  CPDF_Dictionary* pFontDesc = m_pFontDict->GetDict("FontDescriptor");
1692  if (pFontDesc) {
1693    LoadFontDescriptor(pFontDesc);
1694  }
1695  m_Charset = CIDSET_GB1;
1696  m_bType1 = FALSE;
1697  m_pCMap = CPDF_ModuleMgr::Get()
1698                ->GetPageModule()
1699                ->GetFontGlobals()
1700                ->m_CMapManager.GetPredefinedCMap("GBK-EUC-H", FALSE);
1701  m_pCID2UnicodeMap = CPDF_ModuleMgr::Get()
1702                          ->GetPageModule()
1703                          ->GetFontGlobals()
1704                          ->m_CMapManager.GetCID2UnicodeMap(m_Charset, FALSE);
1705  if (!IsEmbedded()) {
1706    LoadSubstFont();
1707  }
1708  CheckFontMetrics();
1709  m_DefaultWidth = 1000;
1710  m_pAnsiWidths = FX_Alloc(FX_WORD, 128);
1711  for (int i = 32; i < 127; i++) {
1712    m_pAnsiWidths[i] = 500;
1713  }
1714  return TRUE;
1715}
1716
1717const uint8_t* CPDF_CIDFont::GetCIDTransform(FX_WORD CID) const {
1718  if (m_Charset != CIDSET_JAPAN1 || m_pFontFile)
1719    return nullptr;
1720
1721  const struct CIDTransform* found = (const struct CIDTransform*)FXSYS_bsearch(
1722      &CID, g_Japan1_VertCIDs, FX_ArraySize(g_Japan1_VertCIDs),
1723      sizeof(g_Japan1_VertCIDs[0]), CompareCIDTransform);
1724  return found ? &found->a : nullptr;
1725}
1726