Initial commit.
[pdfium.git] / core / src / fpdfapi / fpdf_font / fpdf_font.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../include/fpdfapi/fpdf_page.h"\r
8 #include "../../../include/fpdfapi/fpdf_module.h"\r
9 #include "../../../include/fpdfapi/fpdf_pageobj.h"\r
10 #include "font_int.h"\r
11 #include "../fpdf_page/pageint.h"\r
12 #include "../../../include/fxge/fx_freetype.h"\r
13 FX_BOOL FT_UseTTCharmap(FXFT_Face face, int platform_id, int encoding_id)\r
14 {\r
15     for (int i = 0; i < FXFT_Get_Face_CharmapCount(face); i ++) {\r
16         if (FXFT_Get_Charmap_PlatformID(FXFT_Get_Face_Charmaps(face)[i]) == platform_id &&\r
17                 FXFT_Get_Charmap_EncodingID(FXFT_Get_Face_Charmaps(face)[i]) == encoding_id) {\r
18             FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[i]);\r
19             return TRUE;\r
20         }\r
21     }\r
22     return FALSE;\r
23 }\r
24 extern const FX_WORD* PDF_UnicodesForPredefinedCharSet(int);\r
25 CPDF_FontGlobals::CPDF_FontGlobals()\r
26 {\r
27     FXSYS_memset32(m_EmbeddedCharsets, 0, sizeof m_EmbeddedCharsets);\r
28     FXSYS_memset32(m_EmbeddedToUnicodes, 0, sizeof m_EmbeddedToUnicodes);\r
29     m_pContrastRamps = NULL;\r
30 }\r
31 CPDF_FontGlobals::~CPDF_FontGlobals()\r
32 {\r
33     ClearAll();\r
34     if (m_pContrastRamps) {\r
35         FX_Free(m_pContrastRamps);\r
36     }\r
37 }\r
38 class CFX_StockFontArray : public CFX_Object\r
39 {\r
40 public:\r
41     CFX_StockFontArray()\r
42     {\r
43         FXSYS_memset32(m_pStockFonts, 0, sizeof(CPDF_Font*) * 14);\r
44     }\r
45     CPDF_Font*                  m_pStockFonts[14];\r
46 };\r
47 CPDF_Font* CPDF_FontGlobals::Find(void* key, int index)\r
48 {\r
49     void* value = NULL;\r
50     if (!m_pStockMap.Lookup(key, value)) {\r
51         return NULL;\r
52     }\r
53     if (!value) {\r
54         return NULL;\r
55     }\r
56     return ((CFX_StockFontArray*)value)->m_pStockFonts[index];\r
57 }\r
58 void CPDF_FontGlobals::Set(void* key, int index, CPDF_Font* pFont)\r
59 {\r
60     void* value = NULL;\r
61     if (m_pStockMap.Lookup(key, value)) {\r
62         ((CFX_StockFontArray*)value)->m_pStockFonts[index] = pFont;\r
63         return;\r
64     }\r
65     CFX_StockFontArray* pFonts = FX_NEW CFX_StockFontArray();\r
66     if (pFonts) {\r
67         pFonts->m_pStockFonts[index] = pFont;\r
68     }\r
69     m_pStockMap.SetAt(key, pFonts);\r
70 }\r
71 void CPDF_FontGlobals::Clear(void* key)\r
72 {\r
73     void* value = NULL;\r
74     if (!m_pStockMap.Lookup(key, value)) {\r
75         return;\r
76     }\r
77     if (value) {\r
78         CFX_StockFontArray* pStockFonts = (CFX_StockFontArray*)value;\r
79         for (int i = 0; i < 14; i ++) {\r
80             if (pStockFonts->m_pStockFonts[i]) {\r
81                 pStockFonts->m_pStockFonts[i]->GetFontDict()->Release();\r
82                 delete pStockFonts->m_pStockFonts[i];\r
83             }\r
84         }\r
85         delete pStockFonts;\r
86     }\r
87     m_pStockMap.RemoveKey(key);\r
88 }\r
89 void CPDF_FontGlobals::ClearAll()\r
90 {\r
91     FX_POSITION pos = m_pStockMap.GetStartPosition();\r
92     while (pos) {\r
93         void *key = NULL;\r
94         void* value = NULL;\r
95         m_pStockMap.GetNextAssoc(pos, key, value);\r
96         if (value) {\r
97             CFX_StockFontArray* pStockFonts = (CFX_StockFontArray*)value;\r
98             for (int i = 0; i < 14; i ++) {\r
99                 if (pStockFonts->m_pStockFonts[i]) {\r
100                     pStockFonts->m_pStockFonts[i]->GetFontDict()->Release();\r
101                     delete pStockFonts->m_pStockFonts[i];\r
102                 }\r
103             }\r
104             delete pStockFonts;\r
105         }\r
106         m_pStockMap.RemoveKey(key);\r
107     }\r
108 }\r
109 CPDF_Font::CPDF_Font()\r
110 {\r
111     m_FontType = 0;\r
112     m_FontBBox.left = m_FontBBox.right = m_FontBBox.top = m_FontBBox.bottom = 0;\r
113     m_StemV = m_Ascent = m_Descent = m_ItalicAngle = 0;\r
114     m_pFontFile = NULL;\r
115     m_Flags = 0;\r
116     m_pToUnicodeMap = NULL;\r
117     m_bToUnicodeLoaded = FALSE;\r
118     m_pCharMap = NULL;\r
119 }\r
120 FX_BOOL CPDF_Font::Initialize()\r
121 {\r
122     m_pCharMap = FX_NEW CPDF_FontCharMap(this);\r
123     return TRUE;\r
124 }\r
125 CPDF_Font::~CPDF_Font()\r
126 {\r
127     if (m_pCharMap) {\r
128         FX_Free(m_pCharMap);\r
129         m_pCharMap = NULL;\r
130     }\r
131     if (m_pToUnicodeMap) {\r
132         delete m_pToUnicodeMap;\r
133         m_pToUnicodeMap = NULL;\r
134     }\r
135     if (m_pFontFile) {\r
136         m_pDocument->GetPageData()->ReleaseFontFileStreamAcc((CPDF_Stream*)m_pFontFile->GetStream());\r
137     }\r
138 }\r
139 FX_BOOL CPDF_Font::IsVertWriting() const\r
140 {\r
141     FX_BOOL bVertWriting = FALSE;\r
142     CPDF_CIDFont* pCIDFont = GetCIDFont();\r
143     if (pCIDFont) {\r
144         bVertWriting = pCIDFont->IsVertWriting();\r
145     } else {\r
146         bVertWriting = m_Font.IsVertical();\r
147     }\r
148     return bVertWriting;\r
149 }\r
150 CFX_ByteString CPDF_Font::GetFontTypeName() const\r
151 {\r
152     switch (m_FontType) {\r
153         case PDFFONT_TYPE1:\r
154             return FX_BSTRC("Type1");\r
155         case PDFFONT_TRUETYPE:\r
156             return FX_BSTRC("TrueType");\r
157         case PDFFONT_TYPE3:\r
158             return FX_BSTRC("Type3");\r
159         case PDFFONT_CIDFONT:\r
160             return FX_BSTRC("Type0");\r
161     }\r
162     return CFX_ByteString();\r
163 }\r
164 void CPDF_Font::AppendChar(CFX_ByteString& str, FX_DWORD charcode) const\r
165 {\r
166     char buf[4];\r
167     int len = AppendChar(buf, charcode);\r
168     if (len == 1) {\r
169         str += buf[0];\r
170     } else {\r
171         str += CFX_ByteString(buf, len);\r
172     }\r
173 }\r
174 CFX_WideString CPDF_Font::UnicodeFromCharCode(FX_DWORD charcode) const\r
175 {\r
176     if (!m_bToUnicodeLoaded) {\r
177         ((CPDF_Font*)this)->LoadUnicodeMap();\r
178     }\r
179     if (m_pToUnicodeMap) {\r
180         CFX_WideString wsRet = m_pToUnicodeMap->Lookup(charcode);\r
181         if (!wsRet.IsEmpty()) {\r
182             return wsRet;\r
183         }\r
184     }\r
185     FX_WCHAR unicode = _UnicodeFromCharCode(charcode);\r
186     if (unicode == 0) {\r
187         return CFX_WideString();\r
188     }\r
189     return unicode;\r
190 }\r
191 FX_DWORD CPDF_Font::CharCodeFromUnicode(FX_WCHAR unicode) const\r
192 {\r
193     if (!m_bToUnicodeLoaded) {\r
194         ((CPDF_Font*)this)->LoadUnicodeMap();\r
195     }\r
196     if (m_pToUnicodeMap) {\r
197         FX_DWORD charcode = m_pToUnicodeMap->ReverseLookup(unicode);\r
198         if (charcode) {\r
199             return charcode;\r
200         }\r
201     }\r
202     return _CharCodeFromUnicode(unicode);\r
203 }\r
204 CFX_WideString CPDF_Font::DecodeString(const CFX_ByteString& str) const\r
205 {\r
206     CFX_WideString result;\r
207     int src_len = str.GetLength();\r
208     result.Reserve(src_len);\r
209     FX_LPCSTR src_buf = str;\r
210     int src_pos = 0;\r
211     while (src_pos < src_len) {\r
212         FX_DWORD charcode = GetNextChar(src_buf, src_pos);\r
213         CFX_WideString unicode = UnicodeFromCharCode(charcode);\r
214         if (!unicode.IsEmpty()) {\r
215             result += unicode;\r
216         } else {\r
217             result += (FX_WCHAR)charcode;\r
218         }\r
219     }\r
220     return result;\r
221 }\r
222 CFX_ByteString CPDF_Font::EncodeString(const CFX_WideString& str) const\r
223 {\r
224     CFX_ByteString result;\r
225     int src_len = str.GetLength();\r
226     FX_LPSTR dest_buf = result.GetBuffer(src_len * 2);\r
227     FX_LPCWSTR src_buf = str;\r
228     int dest_pos = 0;\r
229     for (int src_pos = 0; src_pos < src_len; src_pos ++) {\r
230         FX_DWORD charcode = CharCodeFromUnicode(src_buf[src_pos]);\r
231         dest_pos += AppendChar(dest_buf + dest_pos, charcode);\r
232     }\r
233     result.ReleaseBuffer(dest_pos);\r
234     return result;\r
235 }\r
236 void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc)\r
237 {\r
238     m_Flags = pFontDesc->GetInteger(FX_BSTRC("Flags"), PDFFONT_NONSYMBOLIC);\r
239     int ItalicAngle = 0;\r
240     FX_BOOL bExistItalicAngle = FALSE;\r
241     if (pFontDesc->KeyExist(FX_BSTRC("ItalicAngle"))) {\r
242         ItalicAngle = pFontDesc->GetInteger(FX_BSTRC("ItalicAngle"));\r
243         bExistItalicAngle = TRUE;\r
244     }\r
245     if (ItalicAngle < 0) {\r
246         m_Flags |= PDFFONT_ITALIC;\r
247         m_ItalicAngle = ItalicAngle;\r
248     }\r
249     FX_BOOL bExistStemV = FALSE;\r
250     if (pFontDesc->KeyExist(FX_BSTRC("StemV"))) {\r
251         m_StemV = pFontDesc->GetInteger(FX_BSTRC("StemV"));\r
252         bExistStemV = TRUE;\r
253     }\r
254     FX_BOOL bExistAscent = FALSE;\r
255     if (pFontDesc->KeyExist(FX_BSTRC("Ascent"))) {\r
256         m_Ascent = pFontDesc->GetInteger(FX_BSTRC("Ascent"));\r
257         bExistAscent = TRUE;\r
258     }\r
259     FX_BOOL bExistDescent = FALSE;\r
260     if (pFontDesc->KeyExist(FX_BSTRC("Descent"))) {\r
261         m_Descent = pFontDesc->GetInteger(FX_BSTRC("Descent"));\r
262         bExistDescent = TRUE;\r
263     }\r
264     FX_BOOL bExistCapHeight = FALSE;\r
265     if (pFontDesc->KeyExist(FX_BSTRC("CapHeight"))) {\r
266         bExistCapHeight = TRUE;\r
267     }\r
268     if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent && bExistStemV) {\r
269         m_Flags |= PDFFONT_USEEXTERNATTR;\r
270     }\r
271     if (m_Descent > 10) {\r
272         m_Descent = -m_Descent;\r
273     }\r
274     CPDF_Array* pBBox = pFontDesc->GetArray(FX_BSTRC("FontBBox"));\r
275     if (pBBox) {\r
276         m_FontBBox.left = pBBox->GetInteger(0);\r
277         m_FontBBox.bottom = pBBox->GetInteger(1);\r
278         m_FontBBox.right = pBBox->GetInteger(2);\r
279         m_FontBBox.top = pBBox->GetInteger(3);\r
280     }\r
281     CPDF_Stream* pFontFile = pFontDesc->GetStream(FX_BSTRC("FontFile"));\r
282     if (pFontFile == NULL) {\r
283         pFontFile = pFontDesc->GetStream(FX_BSTRC("FontFile2"));\r
284     }\r
285     if (pFontFile == NULL) {\r
286         pFontFile = pFontDesc->GetStream(FX_BSTRC("FontFile3"));\r
287     }\r
288     if (pFontFile) {\r
289         m_pFontFile = m_pDocument->LoadFontFile(pFontFile);\r
290         if (m_pFontFile == NULL) {\r
291             return;\r
292         }\r
293         FX_LPCBYTE pFontData = m_pFontFile->GetData();\r
294         FX_DWORD dwFontSize = m_pFontFile->GetSize();\r
295         m_Font.LoadEmbedded(pFontData, dwFontSize);\r
296         if (m_Font.m_Face == NULL) {\r
297             m_pFontFile = NULL;\r
298         }\r
299     }\r
300 }\r
301 short TT2PDF(int m, FXFT_Face face)\r
302 {\r
303     int upm = FXFT_Get_Face_UnitsPerEM(face);\r
304     if (upm == 0) {\r
305         return (short)m;\r
306     }\r
307     return (m * 1000 + upm / 2) / upm;\r
308 }\r
309 void CPDF_Font::CheckFontMetrics()\r
310 {\r
311     if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 && m_FontBBox.right == 0) {\r
312         if (m_Font.m_Face) {\r
313             m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(m_Font.m_Face), m_Font.m_Face);\r
314             m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(m_Font.m_Face), m_Font.m_Face);\r
315             m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(m_Font.m_Face), m_Font.m_Face);\r
316             m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(m_Font.m_Face), m_Font.m_Face);\r
317             m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(m_Font.m_Face), m_Font.m_Face);\r
318             m_Descent = TT2PDF(FXFT_Get_Face_Descender(m_Font.m_Face), m_Font.m_Face);\r
319         } else {\r
320             FX_BOOL bFirst = TRUE;\r
321             for (int i = 0; i < 256; i ++) {\r
322                 FX_RECT rect;\r
323                 GetCharBBox(i, rect);\r
324                 if (rect.left == rect.right) {\r
325                     continue;\r
326                 }\r
327                 if (bFirst) {\r
328                     m_FontBBox = rect;\r
329                     bFirst = FALSE;\r
330                 } else {\r
331                     if (m_FontBBox.top < rect.top) {\r
332                         m_FontBBox.top = rect.top;\r
333                     }\r
334                     if (m_FontBBox.right < rect.right) {\r
335                         m_FontBBox.right = rect.right;\r
336                     }\r
337                     if (m_FontBBox.left > rect.left) {\r
338                         m_FontBBox.left = rect.left;\r
339                     }\r
340                     if (m_FontBBox.bottom > rect.bottom) {\r
341                         m_FontBBox.bottom = rect.bottom;\r
342                     }\r
343                 }\r
344             }\r
345         }\r
346     }\r
347     if (m_Ascent == 0 && m_Descent == 0) {\r
348         FX_RECT rect;\r
349         GetCharBBox('A', rect);\r
350         if (rect.bottom == rect.top) {\r
351             m_Ascent = m_FontBBox.top;\r
352         } else {\r
353             m_Ascent = rect.top;\r
354         }\r
355         GetCharBBox('g', rect);\r
356         if (rect.bottom == rect.top) {\r
357             m_Descent = m_FontBBox.bottom;\r
358         } else {\r
359             m_Descent = rect.bottom;\r
360         }\r
361     }\r
362 }\r
363 void CPDF_Font::LoadUnicodeMap()\r
364 {\r
365     m_bToUnicodeLoaded = TRUE;\r
366     CPDF_Stream* pStream = m_pFontDict->GetStream(FX_BSTRC("ToUnicode"));\r
367     if (pStream == NULL) {\r
368         return;\r
369     }\r
370     m_pToUnicodeMap = FX_NEW CPDF_ToUnicodeMap;\r
371     m_pToUnicodeMap->Load(pStream);\r
372 }\r
373 int CPDF_Font::GetStringWidth(FX_LPCSTR pString, int size)\r
374 {\r
375     int offset = 0;\r
376     int width = 0;\r
377     while (offset < size) {\r
378         FX_DWORD charcode = GetNextChar(pString, offset);\r
379         width += GetCharWidthF(charcode);\r
380     }\r
381     return width;\r
382 }\r
383 int CPDF_Font::GetCharTypeWidth(FX_DWORD charcode)\r
384 {\r
385     if (m_Font.m_Face == NULL) {\r
386         return 0;\r
387     }\r
388     int glyph_index = GlyphFromCharCode(charcode);\r
389     if (glyph_index == 0xffff) {\r
390         return 0;\r
391     }\r
392     return m_Font.GetGlyphWidth(glyph_index);\r
393 }\r
394 int _PDF_GetStandardFontName(CFX_ByteString& name);\r
395 CPDF_Font* CPDF_Font::GetStockFont(CPDF_Document* pDoc, FX_BSTR name)\r
396 {\r
397     CFX_ByteString fontname(name);\r
398     int font_id = _PDF_GetStandardFontName(fontname);\r
399     if (font_id < 0) {\r
400         return NULL;\r
401     }\r
402     CPDF_FontGlobals* pFontGlobals = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();\r
403     CPDF_Font* pFont = pFontGlobals->Find(pDoc, font_id);\r
404     if (pFont) {\r
405         return pFont;\r
406     }\r
407     CPDF_Dictionary* pDict = CPDF_Dictionary::Create();\r
408     pDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("Font"));\r
409     pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Type1"));\r
410     pDict->SetAtName(FX_BSTRC("BaseFont"), fontname);\r
411     pDict->SetAtName(FX_BSTRC("Encoding"), FX_BSTRC("WinAnsiEncoding"));\r
412     pFont = CPDF_Font::CreateFontF(NULL, pDict);\r
413     pFontGlobals->Set(pDoc, font_id, pFont);\r
414     return pFont;\r
415 }\r
416 const FX_BYTE ChineseFontNames[][5] = {\r
417     {0xCB, 0xCE, 0xCC, 0xE5, 0x00},\r
418     {0xBF, 0xAC, 0xCC, 0xE5, 0x00},\r
419     {0xBA, 0xDA, 0xCC, 0xE5, 0x00},\r
420     {0xB7, 0xC2, 0xCB, 0xCE, 0x00},\r
421     {0xD0, 0xC2, 0xCB, 0xCE, 0x00}\r
422 };\r
423 CPDF_Font* CPDF_Font::CreateFontF(CPDF_Document* pDoc, CPDF_Dictionary* pFontDict)\r
424 {\r
425     CFX_ByteString type = pFontDict->GetString(FX_BSTRC("Subtype"));\r
426     CPDF_Font* pFont;\r
427     if (type == FX_BSTRC("TrueType")) {\r
428         {\r
429 #if _FXM_PLATFORM_  == _FXM_PLATFORM_WINDOWS_ || _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ || _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_\r
430             CFX_ByteString basefont = pFontDict->GetString(FX_BSTRC("BaseFont"));\r
431             CFX_ByteString tag = basefont.Left(4);\r
432             int i;\r
433             int count = sizeof(ChineseFontNames) / sizeof(ChineseFontNames[0]);\r
434             for (i = 0; i < count; ++i) {\r
435                 if (tag == CFX_ByteString((FX_LPCSTR)ChineseFontNames[i])) {\r
436                     break;\r
437                 }\r
438             }\r
439             if (i < count) {\r
440                 CPDF_Dictionary* pFontDesc = pFontDict->GetDict(FX_BSTRC("FontDescriptor"));\r
441                 if (pFontDesc == NULL || !pFontDesc->KeyExist(FX_BSTRC("FontFile2"))) {\r
442                     pFont = FX_NEW CPDF_CIDFont;\r
443                     pFont->Initialize();\r
444                     pFont->m_FontType = PDFFONT_CIDFONT;\r
445                     pFont->m_pFontDict = pFontDict;\r
446                     pFont->m_pDocument = pDoc;\r
447                     if (!pFont->Load()) {\r
448                         delete pFont;\r
449                         return NULL;\r
450                     }\r
451                     return pFont;\r
452                 }\r
453             }\r
454 #endif\r
455         }\r
456         pFont = FX_NEW CPDF_TrueTypeFont;\r
457         pFont->Initialize();\r
458         pFont->m_FontType = PDFFONT_TRUETYPE;\r
459     } else if (type == FX_BSTRC("Type3")) {\r
460         pFont = FX_NEW CPDF_Type3Font;\r
461         pFont->Initialize();\r
462         pFont->m_FontType = PDFFONT_TYPE3;\r
463     } else if (type == FX_BSTRC("Type0")) {\r
464         pFont = FX_NEW CPDF_CIDFont;\r
465         pFont->Initialize();\r
466         pFont->m_FontType = PDFFONT_CIDFONT;\r
467     } else {\r
468         pFont = FX_NEW CPDF_Type1Font;\r
469         pFont->Initialize();\r
470         pFont->m_FontType = PDFFONT_TYPE1;\r
471     }\r
472     pFont->m_pFontDict = pFontDict;\r
473     pFont->m_pDocument = pDoc;\r
474     if (!pFont->Load()) {\r
475         delete pFont;\r
476         return NULL;\r
477     }\r
478     return pFont;\r
479 }\r
480 FX_BOOL CPDF_Font::Load()\r
481 {\r
482     if (m_pFontDict == NULL) {\r
483         return FALSE;\r
484     }\r
485     CFX_ByteString type = m_pFontDict->GetString(FX_BSTRC("Subtype"));\r
486     m_BaseFont = m_pFontDict->GetString(FX_BSTRC("BaseFont"));\r
487     if (type == FX_BSTRC("MMType1")) {\r
488         type = FX_BSTRC("Type1");\r
489     }\r
490     return _Load();\r
491 }\r
492 static CFX_WideString _FontMap_GetWideString(CFX_CharMap* pMap, const CFX_ByteString& bytestr)\r
493 {\r
494     return ((CPDF_FontCharMap*)pMap)->m_pFont->DecodeString(bytestr);\r
495 }\r
496 static CFX_ByteString _FontMap_GetByteString(CFX_CharMap* pMap, const CFX_WideString& widestr)\r
497 {\r
498     return ((CPDF_FontCharMap*)pMap)->m_pFont->EncodeString(widestr);\r
499 }\r
500 CPDF_FontCharMap::CPDF_FontCharMap(CPDF_Font* pFont)\r
501 {\r
502     m_GetByteString = _FontMap_GetByteString;\r
503     m_GetWideString = _FontMap_GetWideString;\r
504     m_pFont = pFont;\r
505 }\r
506 CFX_WideString CPDF_ToUnicodeMap::Lookup(FX_DWORD charcode)\r
507 {\r
508     FX_DWORD value;\r
509     if (m_Map.Lookup(charcode, value)) {\r
510         FX_WCHAR unicode = (FX_WCHAR)(value & 0xffff);\r
511         if (unicode != 0xffff) {\r
512             return unicode;\r
513         }\r
514         FX_LPCWSTR buf = m_MultiCharBuf.GetBuffer();\r
515         FX_DWORD buf_len = m_MultiCharBuf.GetLength();\r
516         if (buf == NULL || buf_len == 0) {\r
517             return CFX_WideString();\r
518         }\r
519         FX_DWORD index = value >> 16;\r
520         if (index >= buf_len) {\r
521             return CFX_WideString();\r
522         }\r
523         FX_DWORD len = buf[index];\r
524         if (index + len < index || index + len >= buf_len) {\r
525             return CFX_WideString();\r
526         }\r
527         return CFX_WideString(buf + index + 1, len);\r
528     }\r
529     if (m_pBaseMap) {\r
530         return m_pBaseMap->UnicodeFromCID((FX_WORD)charcode);\r
531     }\r
532     return CFX_WideString();\r
533 }\r
534 FX_DWORD CPDF_ToUnicodeMap::ReverseLookup(FX_WCHAR unicode)\r
535 {\r
536     FX_POSITION pos = m_Map.GetStartPosition();\r
537     while (pos) {\r
538         FX_DWORD key, value;\r
539         m_Map.GetNextAssoc(pos, key, value);\r
540         if ((FX_WCHAR)value == unicode) {\r
541             return key;\r
542         }\r
543     }\r
544     return 0;\r
545 }\r
546 static FX_DWORD _StringToCode(FX_BSTR str)\r
547 {\r
548     FX_LPCSTR buf = str.GetCStr();\r
549     int len = str.GetLength();\r
550     if (len == 0) {\r
551         return 0;\r
552     }\r
553     int result = 0;\r
554     if (buf[0] == '<') {\r
555         for (int i = 1; i < len; i ++) {\r
556             int digit;\r
557             if (buf[i] >= '0' && buf[i] <= '9') {\r
558                 digit = buf[i] - '0';\r
559             } else if (buf[i] >= 'a' && buf[i] <= 'f') {\r
560                 digit = buf[i] - 'a' + 10;\r
561             } else if (buf[i] >= 'A' && buf[i] <= 'F') {\r
562                 digit = buf[i] - 'A' + 10;\r
563             } else {\r
564                 break;\r
565             }\r
566             result = result * 16 + digit;\r
567         }\r
568         return result;\r
569     } else {\r
570         for (int i = 0; i < len; i ++) {\r
571             if (buf[i] < '0' || buf[i] > '9') {\r
572                 break;\r
573             }\r
574             result = result * 10 + buf[i] - '0';\r
575         }\r
576     }\r
577     return result;\r
578 }\r
579 static CFX_WideString _StringDataAdd(CFX_WideString str)\r
580 {\r
581     CFX_WideString ret;\r
582     int len = str.GetLength();\r
583     FX_WCHAR value = 1;\r
584     for (int i = len - 1; i >= 0 ; --i) {\r
585         FX_WCHAR ch = str[i] + value;\r
586         if (ch < str[i]) {\r
587             ret.Insert(0, 0);\r
588         } else {\r
589             ret.Insert(0, ch);\r
590             value = 0;\r
591         }\r
592     }\r
593     if (value) {\r
594         ret.Insert(0, value);\r
595     }\r
596     return ret;\r
597 }\r
598 static CFX_WideString _StringToWideString(FX_BSTR str)\r
599 {\r
600     FX_LPCSTR buf = str.GetCStr();\r
601     int len = str.GetLength();\r
602     if (len == 0) {\r
603         return CFX_WideString();\r
604     }\r
605     CFX_WideString result;\r
606     if (buf[0] == '<') {\r
607         int byte_pos = 0;\r
608         FX_WCHAR ch = 0;\r
609         for (int i = 1; i < len; i ++) {\r
610             int digit;\r
611             if (buf[i] >= '0' && buf[i] <= '9') {\r
612                 digit = buf[i] - '0';\r
613             } else if (buf[i] >= 'a' && buf[i] <= 'f') {\r
614                 digit = buf[i] - 'a' + 10;\r
615             } else if (buf[i] >= 'A' && buf[i] <= 'F') {\r
616                 digit = buf[i] - 'A' + 10;\r
617             } else {\r
618                 break;\r
619             }\r
620             ch = ch * 16 + digit;\r
621             byte_pos ++;\r
622             if (byte_pos == 4) {\r
623                 result += ch;\r
624                 byte_pos = 0;\r
625                 ch = 0;\r
626             }\r
627         }\r
628         return result;\r
629     }\r
630     if (buf[0] == '(') {\r
631     }\r
632     return result;\r
633 }\r
634 void CPDF_ToUnicodeMap::Load(CPDF_Stream* pStream)\r
635 {\r
636     int CIDSet = 0;\r
637     CPDF_StreamAcc stream;\r
638     stream.LoadAllData(pStream, FALSE);\r
639     CPDF_SimpleParser parser(stream.GetData(), stream.GetSize());\r
640     m_Map.EstimateSize(stream.GetSize() / 8, 1024);\r
641     while (1) {\r
642         CFX_ByteStringC word = parser.GetWord();\r
643         if (word.IsEmpty()) {\r
644             break;\r
645         }\r
646         if (word == FX_BSTRC("beginbfchar")) {\r
647             while (1) {\r
648                 word = parser.GetWord();\r
649                 if (word.IsEmpty() || word == FX_BSTRC("endbfchar")) {\r
650                     break;\r
651                 }\r
652                 FX_DWORD srccode = _StringToCode(word);\r
653                 word = parser.GetWord();\r
654                 CFX_WideString destcode = _StringToWideString(word);\r
655                 int len = destcode.GetLength();\r
656                 if (len == 0) {\r
657                     continue;\r
658                 }\r
659                 if (len == 1) {\r
660                     m_Map.SetAt(srccode, destcode.GetAt(0));\r
661                 } else {\r
662                     m_Map.SetAt(srccode, m_MultiCharBuf.GetLength() * 0x10000 + 0xffff);\r
663                     m_MultiCharBuf.AppendChar(destcode.GetLength());\r
664                     m_MultiCharBuf << destcode;\r
665                 }\r
666             }\r
667         } else if (word == FX_BSTRC("beginbfrange")) {\r
668             while (1) {\r
669                 CFX_ByteString low, high;\r
670                 low = parser.GetWord();\r
671                 if (low.IsEmpty() || low == FX_BSTRC("endbfrange")) {\r
672                     break;\r
673                 }\r
674                 high = parser.GetWord();\r
675                 FX_DWORD lowcode = _StringToCode(low);\r
676                 FX_DWORD highcode = (lowcode & 0xffffff00) | (_StringToCode(high) & 0xff);\r
677                 if (highcode == (FX_DWORD) - 1) {\r
678                     break;\r
679                 }\r
680                 CFX_ByteString start = parser.GetWord();\r
681                 if (start == FX_BSTRC("[")) {\r
682                     for (FX_DWORD code = lowcode; code <= highcode; code ++) {\r
683                         CFX_ByteString dest = parser.GetWord();\r
684                         CFX_WideString destcode = _StringToWideString(dest);\r
685                         int len = destcode.GetLength();\r
686                         if (len == 0) {\r
687                             continue;\r
688                         }\r
689                         if (len == 1) {\r
690                             m_Map.SetAt(code, destcode.GetAt(0));\r
691                         } else {\r
692                             m_Map.SetAt(code, m_MultiCharBuf.GetLength() * 0x10000 + 0xffff);\r
693                             m_MultiCharBuf.AppendChar(destcode.GetLength());\r
694                             m_MultiCharBuf << destcode;\r
695                         }\r
696                     }\r
697                     parser.GetWord();\r
698                 } else {\r
699                     CFX_WideString destcode = _StringToWideString(start);\r
700                     int len = destcode.GetLength();\r
701                     FX_DWORD value = 0;\r
702                     if (len == 1) {\r
703                         value = _StringToCode(start);\r
704                         for (FX_DWORD code = lowcode; code <= highcode; code ++) {\r
705                             m_Map.SetAt(code, value++);\r
706                         }\r
707                     } else {\r
708                         for (FX_DWORD code = lowcode; code <= highcode; code ++) {\r
709                             CFX_WideString retcode;\r
710                             if (code == lowcode) {\r
711                                 retcode = destcode;\r
712                             } else {\r
713                                 retcode = _StringDataAdd(destcode);\r
714                             }\r
715                             m_Map.SetAt(code, m_MultiCharBuf.GetLength() * 0x10000 + 0xffff);\r
716                             m_MultiCharBuf.AppendChar(retcode.GetLength());\r
717                             m_MultiCharBuf << retcode;\r
718                             destcode = retcode;\r
719                         }\r
720                     }\r
721                 }\r
722             }\r
723         } else if (word == FX_BSTRC("/Adobe-Korea1-UCS2")) {\r
724             CIDSet = CIDSET_KOREA1;\r
725         } else if (word == FX_BSTRC("/Adobe-Japan1-UCS2")) {\r
726             CIDSet = CIDSET_JAPAN1;\r
727         } else if (word == FX_BSTRC("/Adobe-CNS1-UCS2")) {\r
728             CIDSet = CIDSET_CNS1;\r
729         } else if (word == FX_BSTRC("/Adobe-GB1-UCS2")) {\r
730             CIDSet = CIDSET_GB1;\r
731         }\r
732     }\r
733     if (CIDSet) {\r
734         m_pBaseMap = CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals()->m_CMapManager.GetCID2UnicodeMap(CIDSet, FALSE);\r
735     } else {\r
736         m_pBaseMap = NULL;\r
737     }\r
738 }\r
739 static FX_BOOL GetPredefinedEncoding(int& basemap, const CFX_ByteString& value)\r
740 {\r
741     if (value == FX_BSTRC("WinAnsiEncoding")) {\r
742         basemap = PDFFONT_ENCODING_WINANSI;\r
743     } else if (value == FX_BSTRC("MacRomanEncoding")) {\r
744         basemap = PDFFONT_ENCODING_MACROMAN;\r
745     } else if (value == FX_BSTRC("MacExpertEncoding")) {\r
746         basemap = PDFFONT_ENCODING_MACEXPERT;\r
747     } else if (value == FX_BSTRC("PDFDocEncoding")) {\r
748         basemap = PDFFONT_ENCODING_PDFDOC;\r
749     } else {\r
750         return FALSE;\r
751     }\r
752     return TRUE;\r
753 }\r
754 void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding, int& iBaseEncoding, CFX_ByteString*& pCharNames,\r
755                                 FX_BOOL bEmbedded, FX_BOOL bTrueType)\r
756 {\r
757     if (pEncoding == NULL) {\r
758         if (m_BaseFont == FX_BSTRC("Symbol")) {\r
759             iBaseEncoding = bTrueType ? PDFFONT_ENCODING_MS_SYMBOL : PDFFONT_ENCODING_ADOBE_SYMBOL;\r
760         } else if (!bEmbedded && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {\r
761             iBaseEncoding = PDFFONT_ENCODING_WINANSI;\r
762         }\r
763         return;\r
764     }\r
765     if (pEncoding->GetType() == PDFOBJ_NAME) {\r
766         if (iBaseEncoding == PDFFONT_ENCODING_ADOBE_SYMBOL || iBaseEncoding == PDFFONT_ENCODING_ZAPFDINGBATS) {\r
767             return;\r
768         }\r
769         if ((m_Flags & PDFFONT_SYMBOLIC) && m_BaseFont == FX_BSTRC("Symbol")) {\r
770             if (!bTrueType) {\r
771                 iBaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;\r
772             }\r
773             return;\r
774         }\r
775         CFX_ByteString bsEncoding = pEncoding->GetString();\r
776         if (bsEncoding.Compare(FX_BSTRC("MacExpertEncoding")) == 0) {\r
777             bsEncoding = FX_BSTRC("WinAnsiEncoding");\r
778         }\r
779         GetPredefinedEncoding(iBaseEncoding, bsEncoding);\r
780         return;\r
781     }\r
782     if (pEncoding->GetType() != PDFOBJ_DICTIONARY) {\r
783         return;\r
784     }\r
785     CPDF_Dictionary* pDict = (CPDF_Dictionary*)pEncoding;\r
786     if (iBaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL && iBaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS) {\r
787         CFX_ByteString bsEncoding = pDict->GetString(FX_BSTRC("BaseEncoding"));\r
788         if (bsEncoding.Compare(FX_BSTRC("MacExpertEncoding")) == 0 && bTrueType) {\r
789             bsEncoding = FX_BSTRC("WinAnsiEncoding");\r
790         }\r
791         GetPredefinedEncoding(iBaseEncoding, bsEncoding);\r
792     }\r
793     if ((!bEmbedded || bTrueType) && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {\r
794         iBaseEncoding = PDFFONT_ENCODING_STANDARD;\r
795     }\r
796     CPDF_Array* pDiffs = pDict->GetArray(FX_BSTRC("Differences"));\r
797     if (pDiffs == NULL) {\r
798         return;\r
799     }\r
800     FX_NEW_VECTOR(pCharNames, CFX_ByteString, 256);\r
801     FX_DWORD cur_code = 0;\r
802     for (FX_DWORD i = 0; i < pDiffs->GetCount(); i ++) {\r
803         CPDF_Object* pElement = pDiffs->GetElementValue(i);\r
804         if (pElement == NULL) {\r
805             continue;\r
806         }\r
807         if (pElement->GetType() == PDFOBJ_NAME) {\r
808             if (cur_code < 256) {\r
809                 pCharNames[cur_code] = ((CPDF_Name*)pElement)->GetString();\r
810             }\r
811             cur_code ++;\r
812         } else {\r
813             cur_code = pElement->GetInteger();\r
814         }\r
815     }\r
816 }\r
817 FX_BOOL CPDF_Font::IsStandardFont() const\r
818 {\r
819     if (m_FontType != PDFFONT_TYPE1) {\r
820         return FALSE;\r
821     }\r
822     if (m_pFontFile != NULL) {\r
823         return FALSE;\r
824     }\r
825     if (((CPDF_Type1Font*)this)->GetBase14Font() < 0) {\r
826         return FALSE;\r
827     }\r
828     return TRUE;\r
829 }\r
830 extern FX_LPCSTR PDF_CharNameFromPredefinedCharSet(int encoding, FX_BYTE charcode);\r
831 CPDF_SimpleFont::CPDF_SimpleFont()\r
832 {\r
833     FXSYS_memset8(m_CharBBox, 0xff, sizeof m_CharBBox);\r
834     FXSYS_memset8(m_CharWidth, 0xff, sizeof m_CharWidth);\r
835     FXSYS_memset8(m_GlyphIndex, 0xff, sizeof m_GlyphIndex);\r
836     FXSYS_memset8(m_ExtGID, 0xff, sizeof m_ExtGID);\r
837     m_pCharNames = NULL;\r
838     m_BaseEncoding = PDFFONT_ENCODING_BUILTIN;\r
839 }\r
840 CPDF_SimpleFont::~CPDF_SimpleFont()\r
841 {\r
842     if (m_pCharNames) {\r
843         FX_DELETE_VECTOR(m_pCharNames, CFX_ByteString, 256);\r
844     }\r
845 }\r
846 int CPDF_SimpleFont::GlyphFromCharCode(FX_DWORD charcode, FX_BOOL *pVertGlyph)\r
847 {\r
848     if (pVertGlyph) {\r
849         *pVertGlyph = FALSE;\r
850     }\r
851     if (charcode > 0xff) {\r
852         return -1;\r
853     }\r
854     int index = m_GlyphIndex[(FX_BYTE)charcode];\r
855     if (index == 0xffff) {\r
856         return -1;\r
857     }\r
858     return index;\r
859 }\r
860 void CPDF_SimpleFont::LoadCharMetrics(int charcode)\r
861 {\r
862     if (m_Font.m_Face == NULL) {\r
863         return;\r
864     }\r
865     if (charcode < 0 || charcode > 0xff) {\r
866         return;\r
867     }\r
868     int glyph_index = m_GlyphIndex[charcode];\r
869     if (glyph_index == 0xffff) {\r
870         if (m_pFontFile == NULL && charcode != 32) {\r
871             LoadCharMetrics(32);\r
872             m_CharBBox[charcode] = m_CharBBox[32];\r
873             if (m_bUseFontWidth) {\r
874                 m_CharWidth[charcode] = m_CharWidth[32];\r
875             }\r
876         }\r
877         return;\r
878     }\r
879     int err = FXFT_Load_Glyph(m_Font.m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);\r
880     if (err) {\r
881         return;\r
882     }\r
883     m_CharBBox[charcode].Left = TT2PDF(FXFT_Get_Glyph_HoriBearingX(m_Font.m_Face), m_Font.m_Face);\r
884     m_CharBBox[charcode].Right = TT2PDF(FXFT_Get_Glyph_HoriBearingX(m_Font.m_Face) + FXFT_Get_Glyph_Width(m_Font.m_Face), m_Font.m_Face);\r
885     m_CharBBox[charcode].Top = TT2PDF(FXFT_Get_Glyph_HoriBearingY(m_Font.m_Face), m_Font.m_Face);\r
886     m_CharBBox[charcode].Bottom = TT2PDF(FXFT_Get_Glyph_HoriBearingY(m_Font.m_Face) - FXFT_Get_Glyph_Height(m_Font.m_Face), m_Font.m_Face);\r
887     if (m_bUseFontWidth) {\r
888         int TT_Width = TT2PDF(FXFT_Get_Glyph_HoriAdvance(m_Font.m_Face), m_Font.m_Face);\r
889         if (m_CharWidth[charcode] == 0xffff) {\r
890             m_CharWidth[charcode] = TT_Width;\r
891         } else if (TT_Width && !IsEmbedded()) {\r
892             m_CharBBox[charcode].Right = m_CharBBox[charcode].Right * m_CharWidth[charcode] / TT_Width;\r
893             m_CharBBox[charcode].Left = m_CharBBox[charcode].Left * m_CharWidth[charcode] / TT_Width;\r
894         }\r
895     }\r
896 }\r
897 int CPDF_SimpleFont::GetCharWidthF(FX_DWORD charcode, int level)\r
898 {\r
899     if (charcode > 0xff) {\r
900         charcode = 0;\r
901     }\r
902     if (m_CharWidth[charcode] == 0xffff) {\r
903         LoadCharMetrics(charcode);\r
904         if (m_CharWidth[charcode] == 0xffff) {\r
905             m_CharWidth[charcode] = 0;\r
906         }\r
907     }\r
908     return (FX_INT16)m_CharWidth[charcode];\r
909 }\r
910 void CPDF_SimpleFont::GetCharBBox(FX_DWORD charcode, FX_RECT& rect, int level)\r
911 {\r
912     if (charcode > 0xff) {\r
913         charcode = 0;\r
914     }\r
915     if (m_CharBBox[charcode].Left == (FX_SHORT)0xffff) {\r
916         LoadCharMetrics(charcode);\r
917     }\r
918     rect.left = m_CharBBox[charcode].Left;\r
919     rect.right = m_CharBBox[charcode].Right;\r
920     rect.bottom = m_CharBBox[charcode].Bottom;\r
921     rect.top = m_CharBBox[charcode].Top;\r
922 }\r
923 FX_LPCSTR GetAdobeCharName(int iBaseEncoding, const CFX_ByteString* pCharNames, int charcode)\r
924 {\r
925     ASSERT(charcode >= 0 && charcode < 256);\r
926     if (charcode < 0 || charcode >= 256) {\r
927         return NULL;\r
928     }\r
929     FX_LPCSTR name = NULL;\r
930     if (pCharNames) {\r
931         name = pCharNames[charcode];\r
932     }\r
933     if ((name == NULL || name[0] == 0) && iBaseEncoding) {\r
934         name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode);\r
935     }\r
936     if (name == NULL || name[0] == 0) {\r
937         return NULL;\r
938     }\r
939     return name;\r
940 }\r
941 FX_BOOL CPDF_SimpleFont::LoadCommon()\r
942 {\r
943     CPDF_Dictionary* pFontDesc = m_pFontDict->GetDict(FX_BSTRC("FontDescriptor"));\r
944     if (pFontDesc) {\r
945         LoadFontDescriptor(pFontDesc);\r
946     }\r
947     CPDF_Array* pWidthArray = m_pFontDict->GetArray(FX_BSTRC("Widths"));\r
948     int width_start = 0, width_end = -1;\r
949     m_bUseFontWidth = TRUE;\r
950     if (pWidthArray) {\r
951         m_bUseFontWidth = FALSE;\r
952         if (pFontDesc && pFontDesc->KeyExist(FX_BSTRC("MissingWidth"))) {\r
953             int MissingWidth = pFontDesc->GetInteger(FX_BSTRC("MissingWidth"));\r
954             for (int i = 0; i < 256; i ++) {\r
955                 m_CharWidth[i] = MissingWidth;\r
956             }\r
957         }\r
958         width_start = m_pFontDict->GetInteger(FX_BSTRC("FirstChar"), 0);\r
959         width_end = m_pFontDict->GetInteger(FX_BSTRC("LastChar"), 0);\r
960         if (width_start >= 0 && width_start <= 255) {\r
961             if (width_end <= 0 || width_end >= width_start + (int)pWidthArray->GetCount()) {\r
962                 width_end = width_start + pWidthArray->GetCount() - 1;\r
963             }\r
964             if (width_end > 255) {\r
965                 width_end = 255;\r
966             }\r
967             for (int i = width_start; i <= width_end; i ++) {\r
968                 m_CharWidth[i] = pWidthArray->GetInteger(i - width_start);\r
969             }\r
970         }\r
971     }\r
972     if (m_pFontFile == NULL) {\r
973         LoadSubstFont();\r
974     } else {\r
975         if (m_BaseFont.GetLength() > 8 && m_BaseFont[7] == '+') {\r
976             m_BaseFont = m_BaseFont.Mid(8);\r
977         }\r
978     }\r
979     if (!(m_Flags & PDFFONT_SYMBOLIC)) {\r
980         m_BaseEncoding = PDFFONT_ENCODING_STANDARD;\r
981     }\r
982     CPDF_Object* pEncoding = m_pFontDict->GetElementValue(FX_BSTRC("Encoding"));\r
983     LoadPDFEncoding(pEncoding, m_BaseEncoding, m_pCharNames, m_pFontFile != NULL, m_Font.IsTTFont());\r
984     LoadGlyphMap();\r
985     if (m_pCharNames) {\r
986         FX_DELETE_VECTOR(m_pCharNames, CFX_ByteString, 256);\r
987         m_pCharNames = NULL;\r
988     }\r
989     if (m_Font.m_Face == NULL) {\r
990         return TRUE;\r
991     }\r
992     if (m_Flags & PDFFONT_ALLCAP) {\r
993         unsigned char lowercases[] = {'a', 'z', 0xe0, 0xf6, 0xf8, 0xfd};\r
994         for (int range = 0; range < sizeof lowercases / 2; range ++) {\r
995             for (int i = lowercases[range * 2]; i <= lowercases[range * 2 + 1]; i ++) {\r
996                 if (m_GlyphIndex[i] != 0xffff && m_pFontFile != NULL) {\r
997                     continue;\r
998                 }\r
999                 m_GlyphIndex[i] = m_GlyphIndex[i - 32];\r
1000                 if (m_CharWidth[i - 32]) {\r
1001                     m_CharWidth[i] = m_CharWidth[i - 32];\r
1002                     m_CharBBox[i] = m_CharBBox[i - 32];\r
1003                 }\r
1004             }\r
1005         }\r
1006     }\r
1007     CheckFontMetrics();\r
1008     return TRUE;\r
1009 }\r
1010 void CPDF_SimpleFont::LoadSubstFont()\r
1011 {\r
1012     if (!m_bUseFontWidth && !(m_Flags & PDFFONT_FIXEDPITCH)) {\r
1013         int width = 0, i;\r
1014         for (i = 0; i < 256; i ++) {\r
1015             if (m_CharWidth[i] == 0 || m_CharWidth[i] == 0xffff) {\r
1016                 continue;\r
1017             }\r
1018             if (width == 0) {\r
1019                 width = m_CharWidth[i];\r
1020             } else if (width != m_CharWidth[i]) {\r
1021                 break;\r
1022             }\r
1023         }\r
1024         if (i == 256 && width) {\r
1025             m_Flags |= PDFFONT_FIXEDPITCH;\r
1026         }\r
1027     }\r
1028     int weight = m_StemV < 140 ? m_StemV * 5 : (m_StemV * 4 + 140);\r
1029     m_Font.LoadSubst(m_BaseFont, m_FontType == PDFFONT_TRUETYPE, m_Flags, weight, m_ItalicAngle, 0);\r
1030     if (m_Font.m_pSubstFont->m_SubstFlags & FXFONT_SUBST_NONSYMBOL) {\r
1031     }\r
1032 }\r
1033 FX_BOOL CPDF_SimpleFont::IsUnicodeCompatible() const\r
1034 {\r
1035     return m_BaseEncoding != PDFFONT_ENCODING_BUILTIN && m_BaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL &&\r
1036            m_BaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS;\r
1037 }\r
1038 CPDF_Type1Font::CPDF_Type1Font()\r
1039 {\r
1040     m_Base14Font = -1;\r
1041 }\r
1042 FX_BOOL CPDF_Type1Font::_Load()\r
1043 {\r
1044     m_Base14Font = _PDF_GetStandardFontName(m_BaseFont);\r
1045     if (m_Base14Font >= 0) {\r
1046         CPDF_Dictionary* pFontDesc = m_pFontDict->GetDict(FX_BSTRC("FontDescriptor"));\r
1047         if (pFontDesc && pFontDesc->KeyExist(FX_BSTRC("Flags"))) {\r
1048             m_Flags = pFontDesc->GetInteger(FX_BSTRC("Flags"));\r
1049         } else {\r
1050             m_Flags = m_Base14Font >= 12 ? PDFFONT_SYMBOLIC : PDFFONT_NONSYMBOLIC;\r
1051         }\r
1052         if (m_Base14Font < 4)\r
1053             for (int i = 0; i < 256; i ++) {\r
1054                 m_CharWidth[i] = 600;\r
1055             }\r
1056         if (m_Base14Font == 12) {\r
1057             m_BaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;\r
1058         } else if (m_Base14Font == 13) {\r
1059             m_BaseEncoding = PDFFONT_ENCODING_ZAPFDINGBATS;\r
1060         } else if (m_Flags & PDFFONT_NONSYMBOLIC) {\r
1061             m_BaseEncoding = PDFFONT_ENCODING_STANDARD;\r
1062         }\r
1063     }\r
1064     return LoadCommon();\r
1065 }\r
1066 static FX_BOOL FT_UseType1Charmap(FXFT_Face face)\r
1067 {\r
1068     if (FXFT_Get_Face_CharmapCount(face) == 0) {\r
1069         return FALSE;\r
1070     }\r
1071     if (FXFT_Get_Face_CharmapCount(face) == 1 &&\r
1072             FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) == FXFT_ENCODING_UNICODE) {\r
1073         return FALSE;\r
1074     }\r
1075     if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) == FXFT_ENCODING_UNICODE) {\r
1076         FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[1]);\r
1077     } else {\r
1078         FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]);\r
1079     }\r
1080     return TRUE;\r
1081 }\r
1082 extern FX_WCHAR FT_UnicodeFromCharCode(int encoding, FX_DWORD charcode);\r
1083 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1084 #include "../../fxge/apple/apple_int.h"\r
1085 #endif\r
1086 int CPDF_Type1Font::GlyphFromCharCodeExt(FX_DWORD charcode)\r
1087 {\r
1088     if (charcode > 0xff) {\r
1089         return -1;\r
1090     }\r
1091     int index = m_ExtGID[(FX_BYTE)charcode];\r
1092     if (index == 0xffff) {\r
1093         return -1;\r
1094     }\r
1095     return index;\r
1096 }\r
1097 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1098 struct _GlyphNameMap {\r
1099     FX_LPCSTR m_pStrAdobe;\r
1100     FX_LPCSTR m_pStrUnicode;\r
1101 };\r
1102 static const _GlyphNameMap g_GlyphNameSubsts[] = {\r
1103     {"ff", "uniFB00"},\r
1104     {"fi", "uniFB01"},\r
1105     {"fl", "uniFB02"},\r
1106     {"ffi", "uniFB03"},\r
1107     {"ffl", "uniFB04"}\r
1108 };\r
1109 extern "C" {\r
1110     static int compareString(const void* key, const void* element)\r
1111     {\r
1112         return FXSYS_stricmp((FX_LPCSTR)key, ((_GlyphNameMap*)element)->m_pStrAdobe);\r
1113     }\r
1114 }\r
1115 static FX_LPCSTR _GlyphNameRemap(FX_LPCSTR pStrAdobe)\r
1116 {\r
1117     _GlyphNameMap* found = (_GlyphNameMap*)FXSYS_bsearch(pStrAdobe, g_GlyphNameSubsts,\r
1118                            sizeof g_GlyphNameSubsts / sizeof(_GlyphNameMap), sizeof(_GlyphNameMap),\r
1119                            compareString);\r
1120     if (found) {\r
1121         return found->m_pStrUnicode;\r
1122     }\r
1123     return NULL;\r
1124 }\r
1125 #endif\r
1126 void CPDF_Type1Font::LoadGlyphMap()\r
1127 {\r
1128     if (m_Font.m_Face == NULL) {\r
1129         return;\r
1130     }\r
1131 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1132     FX_BOOL bCoreText = TRUE;\r
1133     CQuartz2D & quartz2d = ((CApplePlatform *) CFX_GEModule::Get()->GetPlatformData())->_quartz2d;\r
1134     if (!m_Font.m_pPlatformFont) {\r
1135         if (m_Font.GetPsName() == CFX_WideString::FromLocal("DFHeiStd-W5")) {\r
1136             bCoreText = FALSE;\r
1137         }\r
1138         m_Font.m_pPlatformFont = quartz2d.CreateFont(m_Font.m_pFontData, m_Font.m_dwSize);\r
1139         if (NULL == m_Font.m_pPlatformFont) {\r
1140             bCoreText = FALSE;\r
1141         }\r
1142     }\r
1143 #endif\r
1144     if (!IsEmbedded() && (m_Base14Font < 12) && m_Font.IsTTFont()) {\r
1145         if (FT_UseTTCharmap(m_Font.m_Face, 3, 0)) {\r
1146             FX_BOOL bGotOne = FALSE;\r
1147             for (int charcode = 0; charcode < 256; charcode ++) {\r
1148                 const FX_BYTE prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};\r
1149                 for (int j = 0; j < 4; j ++) {\r
1150                     FX_WORD unicode = prefix[j] * 256 + charcode;\r
1151                     m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, unicode);\r
1152 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1153                     FX_CHAR name_glyph[256];\r
1154                     FXFT_Get_Glyph_Name(m_Font.m_Face, m_GlyphIndex[charcode], name_glyph, 256);\r
1155                     name_glyph[255] = 0;\r
1156                     CFStringRef name_ct = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, kCFAllocatorNull);\r
1157                     m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.m_pPlatformFont, name_ct);\r
1158                     if (name_ct) {\r
1159                         CFRelease(name_ct);\r
1160                     }\r
1161 #endif\r
1162                     if (m_GlyphIndex[charcode]) {\r
1163                         bGotOne = TRUE;\r
1164                         break;\r
1165                     }\r
1166                 }\r
1167             }\r
1168             if (bGotOne) {\r
1169 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1170                 if (!bCoreText) {\r
1171                     FXSYS_memcpy32(m_ExtGID, m_GlyphIndex, 256);\r
1172                 }\r
1173 #endif\r
1174                 return;\r
1175             }\r
1176         }\r
1177         FXFT_Select_Charmap(m_Font.m_Face, FXFT_ENCODING_UNICODE);\r
1178         if (m_BaseEncoding == 0) {\r
1179             m_BaseEncoding = PDFFONT_ENCODING_STANDARD;\r
1180         }\r
1181         for (int charcode = 0; charcode < 256; charcode ++) {\r
1182             FX_LPCSTR name = GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);\r
1183             if (name == NULL) {\r
1184                 continue;\r
1185             }\r
1186             m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);\r
1187             m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, m_Encoding.m_Unicodes[charcode]);\r
1188 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1189             FX_CHAR name_glyph[256];\r
1190             FXFT_Get_Glyph_Name(m_Font.m_Face, m_GlyphIndex[charcode], name_glyph, 256);\r
1191             name_glyph[255] = 0;\r
1192             CFStringRef name_ct = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, kCFAllocatorNull);\r
1193             m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.m_pPlatformFont, name_ct);\r
1194             if (name_ct) {\r
1195                 CFRelease(name_ct);\r
1196             }\r
1197 #endif\r
1198             if (m_GlyphIndex[charcode] == 0 && FXSYS_strcmp(name, ".notdef") == 0) {\r
1199                 m_Encoding.m_Unicodes[charcode] = 0x20;\r
1200                 m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, 0x20);\r
1201 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1202                 FX_CHAR name_glyph[256];\r
1203                 FXFT_Get_Glyph_Name(m_Font.m_Face, m_GlyphIndex[charcode], name_glyph, 256);\r
1204                 name_glyph[255] = 0;\r
1205                 CFStringRef name_ct = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, kCFAllocatorNull);\r
1206                 m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.m_pPlatformFont, name_ct);\r
1207                 if (name_ct) {\r
1208                     CFRelease(name_ct);\r
1209                 }\r
1210 #endif\r
1211             }\r
1212         }\r
1213 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1214         if (!bCoreText) {\r
1215             FXSYS_memcpy32(m_ExtGID, m_GlyphIndex, 256);\r
1216         }\r
1217 #endif\r
1218         return;\r
1219     }\r
1220     FT_UseType1Charmap(m_Font.m_Face);\r
1221 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1222     if (bCoreText) {\r
1223         if (m_Flags & PDFFONT_SYMBOLIC) {\r
1224             for (int charcode = 0; charcode < 256; charcode ++) {\r
1225                 FX_LPCSTR name = GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);\r
1226                 if (name) {\r
1227                     m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);\r
1228                     m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.m_Face, (char*)name);\r
1229                     CFStringRef name_ct = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, name, kCFStringEncodingASCII, kCFAllocatorNull);\r
1230                     m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.m_pPlatformFont, name_ct);\r
1231                     if (name_ct) {\r
1232                         CFRelease(name_ct);\r
1233                     }\r
1234                 } else {\r
1235                     m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, charcode);\r
1236                     FX_WCHAR unicode = 0;\r
1237                     if (m_GlyphIndex[charcode]) {\r
1238                         unicode = FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);\r
1239                     }\r
1240                     FX_CHAR name_glyph[256];\r
1241                     FXSYS_memset32(name_glyph, 0, sizeof(name_glyph));\r
1242                     FXFT_Get_Glyph_Name(m_Font.m_Face, m_GlyphIndex[charcode], name_glyph, 256);\r
1243                     name_glyph[255] = 0;\r
1244                     if (unicode == 0 && name_glyph[0] != 0) {\r
1245                         unicode = PDF_UnicodeFromAdobeName(name_glyph);\r
1246                     }\r
1247                     m_Encoding.m_Unicodes[charcode] = unicode;\r
1248                     CFStringRef name_ct = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, kCFAllocatorNull);\r
1249                     m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.m_pPlatformFont, name_ct);\r
1250                     if (name_ct) {\r
1251                         CFRelease(name_ct);\r
1252                     }\r
1253                 }\r
1254             }\r
1255             return;\r
1256         }\r
1257         FX_BOOL bUnicode = FALSE;\r
1258         if (0 == FXFT_Select_Charmap(m_Font.m_Face, FXFT_ENCODING_UNICODE)) {\r
1259             bUnicode = TRUE;\r
1260         }\r
1261         for (int charcode = 0; charcode < 256; charcode ++) {\r
1262             FX_LPCSTR name = GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);\r
1263             if (name == NULL) {\r
1264                 continue;\r
1265             }\r
1266             m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);\r
1267             FX_LPCSTR pStrUnicode = _GlyphNameRemap(name);\r
1268             if (pStrUnicode && 0 == FXFT_Get_Name_Index(m_Font.m_Face, (char*)name)) {\r
1269                 name = pStrUnicode;\r
1270             }\r
1271             m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.m_Face, (char*)name);\r
1272             CFStringRef name_ct = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, name, kCFStringEncodingASCII, kCFAllocatorNull);\r
1273             m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.m_pPlatformFont, name_ct);\r
1274             if (name_ct) {\r
1275                 CFRelease(name_ct);\r
1276             }\r
1277             if (m_GlyphIndex[charcode] == 0) {\r
1278                 if (FXSYS_strcmp(name, ".notdef") != 0 && FXSYS_strcmp(name, "space") != 0) {\r
1279                     m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);\r
1280                     FX_CHAR name_glyph[256];\r
1281                     FXFT_Get_Glyph_Name(m_Font.m_Face, m_GlyphIndex[charcode], name_glyph, 256);\r
1282                     name_glyph[255] = 0;\r
1283                     CFStringRef name_ct = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, kCFAllocatorNull);\r
1284                     m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.m_pPlatformFont, name_ct);\r
1285                     if (name_ct) {\r
1286                         CFRelease(name_ct);\r
1287                     }\r
1288                 } else {\r
1289                     m_Encoding.m_Unicodes[charcode] = 0x20;\r
1290                     m_GlyphIndex[charcode] = bUnicode ? FXFT_Get_Char_Index(m_Font.m_Face, 0x20) : 0xffff;\r
1291                     FX_CHAR name_glyph[256];\r
1292                     FXFT_Get_Glyph_Name(m_Font.m_Face, m_GlyphIndex[charcode], name_glyph, 256);\r
1293                     name_glyph[255] = 0;\r
1294                     CFStringRef name_ct = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, name_glyph, kCFStringEncodingASCII, kCFAllocatorNull);\r
1295                     m_ExtGID[charcode] = CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.m_pPlatformFont, name_ct);\r
1296                     if (name_ct) {\r
1297                         CFRelease(name_ct);\r
1298                     }\r
1299                 }\r
1300             }\r
1301         }\r
1302         return;\r
1303     }\r
1304 #endif\r
1305     if (m_Flags & PDFFONT_SYMBOLIC) {\r
1306         for (int charcode = 0; charcode < 256; charcode ++) {\r
1307             FX_LPCSTR name = GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);\r
1308             if (name) {\r
1309                 m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);\r
1310                 m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.m_Face, (char*)name);\r
1311             } else {\r
1312                 m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, charcode);\r
1313                 if (m_GlyphIndex[charcode]) {\r
1314                     FX_WCHAR unicode = FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);\r
1315                     if (unicode == 0) {\r
1316                         FX_CHAR name_glyph[256];\r
1317                         FXSYS_memset32(name_glyph, 0, sizeof(name_glyph));\r
1318                         FXFT_Get_Glyph_Name(m_Font.m_Face, m_GlyphIndex[charcode], name_glyph, 256);\r
1319                         name_glyph[255] = 0;\r
1320                         if (name_glyph[0] != 0) {\r
1321                             unicode = PDF_UnicodeFromAdobeName(name_glyph);\r
1322                         }\r
1323                     }\r
1324                     m_Encoding.m_Unicodes[charcode] = unicode;\r
1325                 }\r
1326             }\r
1327         }\r
1328 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1329         if (!bCoreText) {\r
1330             FXSYS_memcpy32(m_ExtGID, m_GlyphIndex, 256);\r
1331         }\r
1332 #endif\r
1333         return;\r
1334     }\r
1335     FX_BOOL bUnicode = FALSE;\r
1336     if (0 == FXFT_Select_Charmap(m_Font.m_Face, FXFT_ENCODING_UNICODE)) {\r
1337         bUnicode = TRUE;\r
1338     }\r
1339     for (int charcode = 0; charcode < 256; charcode ++) {\r
1340         FX_LPCSTR name = GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);\r
1341         if (name == NULL) {\r
1342             continue;\r
1343         }\r
1344         m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);\r
1345         m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.m_Face, (char*)name);\r
1346         if (m_GlyphIndex[charcode] == 0) {\r
1347             if (FXSYS_strcmp(name, ".notdef") != 0 && FXSYS_strcmp(name, "space") != 0) {\r
1348                 m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);\r
1349             } else {\r
1350                 m_Encoding.m_Unicodes[charcode] = 0x20;\r
1351                 m_GlyphIndex[charcode] = 0xffff;\r
1352             }\r
1353         }\r
1354     }\r
1355 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
1356     if (!bCoreText) {\r
1357         FXSYS_memcpy32(m_ExtGID, m_GlyphIndex, 256);\r
1358     }\r
1359 #endif\r
1360 }\r
1361 CPDF_FontEncoding::CPDF_FontEncoding()\r
1362 {\r
1363     FXSYS_memset32(m_Unicodes, 0, sizeof(m_Unicodes));\r
1364 }\r
1365 int CPDF_FontEncoding::CharCodeFromUnicode(FX_WCHAR unicode) const\r
1366 {\r
1367     for (int i = 0; i < 256; i ++)\r
1368         if (m_Unicodes[i] == unicode) {\r
1369             return i;\r
1370         }\r
1371     return -1;\r
1372 }\r
1373 CPDF_FontEncoding::CPDF_FontEncoding(int PredefinedEncoding)\r
1374 {\r
1375     const FX_WORD* pSrc = PDF_UnicodesForPredefinedCharSet(PredefinedEncoding);\r
1376     if (!pSrc) {\r
1377         FXSYS_memset32(m_Unicodes, 0, sizeof(m_Unicodes));\r
1378     } else\r
1379         for (int i = 0; i < 256; i++) {\r
1380             m_Unicodes[i] = pSrc[i];\r
1381         }\r
1382 }\r
1383 FX_BOOL CPDF_FontEncoding::IsIdentical(CPDF_FontEncoding* pAnother) const\r
1384 {\r
1385     return FXSYS_memcmp32(m_Unicodes, pAnother->m_Unicodes, sizeof(m_Unicodes)) == 0;\r
1386 }\r
1387 CPDF_Object* CPDF_FontEncoding::Realize()\r
1388 {\r
1389     int predefined = 0;\r
1390     for (int cs = PDFFONT_ENCODING_WINANSI; cs < PDFFONT_ENCODING_ZAPFDINGBATS; cs ++) {\r
1391         const FX_WORD* pSrc = PDF_UnicodesForPredefinedCharSet(cs);\r
1392         FX_BOOL match = TRUE;\r
1393         for (int i = 0; i < 256; ++i) {\r
1394             if (m_Unicodes[i] != pSrc[i]) {\r
1395                 match = FALSE;\r
1396                 break;\r
1397             }\r
1398         }\r
1399         if (match) {\r
1400             predefined = cs;\r
1401             break;\r
1402         }\r
1403     }\r
1404     if (predefined) {\r
1405         if (predefined == PDFFONT_ENCODING_WINANSI) {\r
1406             return CPDF_Name::Create("WinAnsiEncoding");\r
1407         }\r
1408         if (predefined == PDFFONT_ENCODING_MACROMAN) {\r
1409             return CPDF_Name::Create("MacRomanEncoding");\r
1410         }\r
1411         if (predefined == PDFFONT_ENCODING_MACEXPERT) {\r
1412             return CPDF_Name::Create("MacExpertEncoding");\r
1413         }\r
1414         return NULL;\r
1415     }\r
1416     CPDF_Dictionary* pDict = CPDF_Dictionary::Create();\r
1417     pDict->SetAtName(FX_BSTRC("BaseEncoding"), FX_BSTRC("WinAnsiEncoding"));\r
1418     const FX_WORD* pStandard = PDF_UnicodesForPredefinedCharSet(PDFFONT_ENCODING_WINANSI);\r
1419     CPDF_Array* pDiff = CPDF_Array::Create();\r
1420     for (int i = 0; i < 256; i ++) {\r
1421         if (pStandard[i] == m_Unicodes[i]) {\r
1422             continue;\r
1423         }\r
1424         pDiff->Add(CPDF_Number::Create(i));\r
1425         pDiff->Add(CPDF_Name::Create(PDF_AdobeNameFromUnicode(m_Unicodes[i])));\r
1426     }\r
1427     pDict->SetAt(FX_BSTRC("Differences"), pDiff);\r
1428     return pDict;\r
1429 }\r
1430 CPDF_TrueTypeFont::CPDF_TrueTypeFont()\r
1431 {\r
1432 }\r
1433 FX_BOOL CPDF_TrueTypeFont::_Load()\r
1434 {\r
1435     return LoadCommon();\r
1436 }\r
1437 extern FX_DWORD FT_CharCodeFromUnicode(int encoding, FX_WCHAR unicode);\r
1438 void CPDF_TrueTypeFont::LoadGlyphMap()\r
1439 {\r
1440     if (m_Font.m_Face == NULL) {\r
1441         return;\r
1442     }\r
1443     int baseEncoding = m_BaseEncoding;\r
1444     if (m_pFontFile && m_Font.m_Face->num_charmaps > 0\r
1445             && (baseEncoding == PDFFONT_ENCODING_MACROMAN || baseEncoding == PDFFONT_ENCODING_WINANSI)\r
1446             && (m_Flags & PDFFONT_SYMBOLIC)) {\r
1447         FX_BOOL bSupportWin = FALSE;\r
1448         FX_BOOL bSupportMac = FALSE;\r
1449         for (int i = 0; i < FXFT_Get_Face_CharmapCount(m_Font.m_Face); i++) {\r
1450             int platform_id = FXFT_Get_Charmap_PlatformID(FXFT_Get_Face_Charmaps(m_Font.m_Face)[i]);\r
1451             if (platform_id == 0 || platform_id == 3) {\r
1452                 bSupportWin = TRUE;\r
1453             } else if (platform_id == 0 || platform_id == 1) {\r
1454                 bSupportMac = TRUE;\r
1455             }\r
1456         }\r
1457         if (baseEncoding == PDFFONT_ENCODING_WINANSI && !bSupportWin) {\r
1458             baseEncoding = bSupportMac ? PDFFONT_ENCODING_MACROMAN : PDFFONT_ENCODING_BUILTIN;\r
1459         } else if (baseEncoding == PDFFONT_ENCODING_MACROMAN && !bSupportMac) {\r
1460             baseEncoding = bSupportWin ? PDFFONT_ENCODING_WINANSI : PDFFONT_ENCODING_BUILTIN;\r
1461         }\r
1462     }\r
1463     if (((baseEncoding == PDFFONT_ENCODING_MACROMAN || baseEncoding == PDFFONT_ENCODING_WINANSI)\r
1464             && m_pCharNames == NULL) || (m_Flags & PDFFONT_NONSYMBOLIC)) {\r
1465         if (!FXFT_Has_Glyph_Names(m_Font.m_Face) && (!m_Font.m_Face->num_charmaps || !m_Font.m_Face->charmaps)) {\r
1466             int nStartChar = m_pFontDict->GetInteger(FX_BSTRC("FirstChar"));\r
1467             int charcode = 0;\r
1468             for (; charcode < nStartChar; charcode ++) {\r
1469                 m_GlyphIndex[charcode] = 0;\r
1470             }\r
1471             FX_WORD nGlyph = charcode - nStartChar + 3;\r
1472             for (; charcode < 256; charcode ++, nGlyph ++) {\r
1473                 m_GlyphIndex[charcode] = nGlyph;\r
1474             }\r
1475             return;\r
1476         }\r
1477         FX_BOOL bMSUnicode = FT_UseTTCharmap(m_Font.m_Face, 3, 1);\r
1478         FX_BOOL bMacRoman = FALSE, bMSSymbol = FALSE;\r
1479         if (!bMSUnicode) {\r
1480             if (m_Flags & PDFFONT_NONSYMBOLIC) {\r
1481                 bMacRoman = FT_UseTTCharmap(m_Font.m_Face, 1, 0);\r
1482                 bMSSymbol = !bMacRoman && FT_UseTTCharmap(m_Font.m_Face, 3, 0);\r
1483             } else {\r
1484                 bMSSymbol = FT_UseTTCharmap(m_Font.m_Face, 3, 0);\r
1485                 bMacRoman = !bMSSymbol && FT_UseTTCharmap(m_Font.m_Face, 1, 0);\r
1486             }\r
1487         }\r
1488         FX_BOOL bToUnicode = m_pFontDict->KeyExist(FX_BSTRC("ToUnicode"));\r
1489         for (int charcode = 0; charcode < 256; charcode ++) {\r
1490             FX_LPCSTR name = GetAdobeCharName(baseEncoding, m_pCharNames, charcode);\r
1491             if (name == NULL) {\r
1492                 m_GlyphIndex[charcode] = m_pFontFile ? FXFT_Get_Char_Index(m_Font.m_Face, charcode) : -1;\r
1493                 continue;\r
1494             }\r
1495             m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);\r
1496             if (bMSSymbol) {\r
1497                 const FX_BYTE prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};\r
1498                 for (int j = 0; j < 4; j ++) {\r
1499                     FX_WORD unicode = prefix[j] * 256 + charcode;\r
1500                     m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, unicode);\r
1501                     if (m_GlyphIndex[charcode]) {\r
1502                         break;\r
1503                     }\r
1504                 }\r
1505             } else if (m_Encoding.m_Unicodes[charcode]) {\r
1506                 if (bMSUnicode) {\r
1507                     m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, m_Encoding.m_Unicodes[charcode]);\r
1508                 } else if (bMacRoman) {\r
1509                     FX_DWORD maccode = FT_CharCodeFromUnicode(FXFT_ENCODING_APPLE_ROMAN, m_Encoding.m_Unicodes[charcode]);\r
1510                     if (!maccode) {\r
1511                         m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.m_Face, (char *)name);\r
1512                     } else {\r
1513                         m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, maccode);\r
1514                     }\r
1515                 }\r
1516             }\r
1517             if ((m_GlyphIndex[charcode] == 0 || m_GlyphIndex[charcode] == 0xffff) && name != NULL) {\r
1518                 if (name[0] == '.' && FXSYS_strcmp(name, ".notdef") == 0) {\r
1519                     m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, 32);\r
1520                 } else {\r
1521                     m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.m_Face, (char*)name);\r
1522                     if (m_GlyphIndex[charcode] == 0) {\r
1523                         if (bToUnicode) {\r
1524                             CFX_WideString wsUnicode = UnicodeFromCharCode(charcode);\r
1525                             if (!wsUnicode.IsEmpty()) {\r
1526                                 m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, wsUnicode[0]);\r
1527                                 m_Encoding.m_Unicodes[charcode] = wsUnicode[0];\r
1528                             }\r
1529                         }\r
1530                         if (m_GlyphIndex[charcode] == 0) {\r
1531                             m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, charcode);\r
1532                         }\r
1533                     }\r
1534                 }\r
1535             }\r
1536         }\r
1537         return;\r
1538     }\r
1539     if (FT_UseTTCharmap(m_Font.m_Face, 3, 0)) {\r
1540         const FX_BYTE prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};\r
1541         FX_BOOL bGotOne = FALSE;\r
1542         for (int charcode = 0; charcode < 256; charcode ++) {\r
1543             for (int j = 0; j < 4; j ++) {\r
1544                 FX_WORD unicode = prefix[j] * 256 + charcode;\r
1545                 m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, unicode);\r
1546                 if (m_GlyphIndex[charcode]) {\r
1547                     bGotOne = TRUE;\r
1548                     break;\r
1549                 }\r
1550             }\r
1551         }\r
1552         if (bGotOne) {\r
1553             if (baseEncoding != PDFFONT_ENCODING_BUILTIN) {\r
1554                 for (int charcode = 0; charcode < 256; charcode ++) {\r
1555                     FX_LPCSTR name = GetAdobeCharName(baseEncoding, m_pCharNames, charcode);\r
1556                     if (name == NULL) {\r
1557                         continue;\r
1558                     }\r
1559                     m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);\r
1560                 }\r
1561             } else if (FT_UseTTCharmap(m_Font.m_Face, 1, 0)) {\r
1562                 for (int charcode = 0; charcode < 256; charcode ++) {\r
1563                     m_Encoding.m_Unicodes[charcode] = FT_UnicodeFromCharCode(FXFT_ENCODING_APPLE_ROMAN, charcode);\r
1564                 }\r
1565             }\r
1566             return;\r
1567         }\r
1568     }\r
1569     if (FT_UseTTCharmap(m_Font.m_Face, 1, 0)) {\r
1570         FX_BOOL bGotOne = FALSE;\r
1571         for (int charcode = 0; charcode < 256; charcode ++) {\r
1572             m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, charcode);\r
1573             m_Encoding.m_Unicodes[charcode] = FT_UnicodeFromCharCode(FXFT_ENCODING_APPLE_ROMAN, charcode);\r
1574             if (m_GlyphIndex[charcode]) {\r
1575                 bGotOne = TRUE;\r
1576             }\r
1577         }\r
1578         if (m_pFontFile || bGotOne) {\r
1579             return;\r
1580         }\r
1581     }\r
1582     if (FXFT_Select_Charmap(m_Font.m_Face, FXFT_ENCODING_UNICODE) == 0) {\r
1583         FX_BOOL bGotOne = FALSE;\r
1584         const FX_WORD* pUnicodes = PDF_UnicodesForPredefinedCharSet(baseEncoding);\r
1585         for (int charcode = 0; charcode < 256; charcode ++) {\r
1586             if (m_pFontFile == NULL) {\r
1587                 FX_LPCSTR name = GetAdobeCharName(0, m_pCharNames, charcode);\r
1588                 if (name != NULL) {\r
1589                     m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);\r
1590                 } else if (pUnicodes) {\r
1591                     m_Encoding.m_Unicodes[charcode] = pUnicodes[charcode];\r
1592                 }\r
1593             } else {\r
1594                 m_Encoding.m_Unicodes[charcode] = charcode;\r
1595             }\r
1596             m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.m_Face, m_Encoding.m_Unicodes[charcode]);\r
1597             if (m_GlyphIndex[charcode]) {\r
1598                 bGotOne = TRUE;\r
1599             }\r
1600         }\r
1601         if (bGotOne) {\r
1602             return;\r
1603         }\r
1604     }\r
1605     for (int charcode = 0; charcode < 256; charcode ++) {\r
1606         m_GlyphIndex[charcode] = charcode;\r
1607     }\r
1608 }\r
1609 CPDF_Type3Font::CPDF_Type3Font()\r
1610 {\r
1611     m_pPageResources = NULL;\r
1612     FXSYS_memset32(m_CharWidthL, 0, sizeof m_CharWidthL);\r
1613 }\r
1614 CPDF_Type3Font::~CPDF_Type3Font()\r
1615 {\r
1616     FX_POSITION pos = m_CacheMap.GetStartPosition();\r
1617     while (pos) {\r
1618         FX_LPVOID key, value;\r
1619         m_CacheMap.GetNextAssoc(pos, key, value);\r
1620         delete (CPDF_Type3Char*)value;\r
1621     }\r
1622     m_CacheMap.RemoveAll();\r
1623     pos = m_DeletedMap.GetStartPosition();\r
1624     while (pos) {\r
1625         FX_LPVOID key, value;\r
1626         m_DeletedMap.GetNextAssoc(pos, key, value);\r
1627         delete (CPDF_Type3Char*)key;\r
1628     }\r
1629 }\r
1630 FX_BOOL CPDF_Type3Font::_Load()\r
1631 {\r
1632     m_pFontResources = m_pFontDict->GetDict(FX_BSTRC("Resources"));\r
1633     CPDF_Array* pMatrix = m_pFontDict->GetArray(FX_BSTRC("FontMatrix"));\r
1634     FX_FLOAT xscale = 1.0f, yscale = 1.0f;\r
1635     if (pMatrix) {\r
1636         m_FontMatrix = pMatrix->GetMatrix();\r
1637         xscale = m_FontMatrix.a;\r
1638         yscale = m_FontMatrix.d;\r
1639     }\r
1640     CPDF_Array* pBBox = m_pFontDict->GetArray(FX_BSTRC("FontBBox"));\r
1641     if (pBBox) {\r
1642         m_FontBBox.left = (FX_INT32)(FXSYS_Mul(pBBox->GetNumber(0), xscale) * 1000);\r
1643         m_FontBBox.bottom = (FX_INT32)(FXSYS_Mul(pBBox->GetNumber(1), yscale) * 1000);\r
1644         m_FontBBox.right = (FX_INT32)(FXSYS_Mul(pBBox->GetNumber(2), xscale) * 1000);\r
1645         m_FontBBox.top = (FX_INT32)(FXSYS_Mul(pBBox->GetNumber(3), yscale) * 1000);\r
1646     }\r
1647     int StartChar = m_pFontDict->GetInteger(FX_BSTRC("FirstChar"));\r
1648     CPDF_Array* pWidthArray = m_pFontDict->GetArray(FX_BSTRC("Widths"));\r
1649     if (pWidthArray && (StartChar >= 0 && StartChar < 256)) {\r
1650         FX_DWORD count = pWidthArray->GetCount();\r
1651         if (count > 256) {\r
1652             count = 256;\r
1653         }\r
1654         if (StartChar + count > 256) {\r
1655             count = 256 - StartChar;\r
1656         }\r
1657         for (FX_DWORD i = 0; i < count; i ++) {\r
1658             m_CharWidthL[StartChar + i] = FXSYS_round(FXSYS_Mul(pWidthArray->GetNumber(i), xscale) * 1000);\r
1659         }\r
1660     }\r
1661     m_pCharProcs = m_pFontDict->GetDict(FX_BSTRC("CharProcs"));\r
1662     CPDF_Object* pEncoding = m_pFontDict->GetElementValue(FX_BSTRC("Encoding"));\r
1663     if (pEncoding) {\r
1664         LoadPDFEncoding(pEncoding, m_BaseEncoding, m_pCharNames, FALSE, FALSE);\r
1665         if (m_pCharNames) {\r
1666             for (int i = 0; i < 256; i ++) {\r
1667                 m_Encoding.m_Unicodes[i] = PDF_UnicodeFromAdobeName(m_pCharNames[i]);\r
1668                 if (m_Encoding.m_Unicodes[i] == 0) {\r
1669                     m_Encoding.m_Unicodes[i] = i;\r
1670                 }\r
1671             }\r
1672         }\r
1673     }\r
1674     return TRUE;\r
1675 }\r
1676 void CPDF_Type3Font::CheckType3FontMetrics()\r
1677 {\r
1678     CheckFontMetrics();\r
1679 }\r
1680 CPDF_Type3Char* CPDF_Type3Font::LoadChar(FX_DWORD charcode, int level)\r
1681 {\r
1682     if (level >= _FPDF_MAX_TYPE3_FORM_LEVEL_) {\r
1683         return NULL;\r
1684     }\r
1685     CPDF_Type3Char* pChar = NULL;\r
1686     if (m_CacheMap.Lookup((FX_LPVOID)(FX_UINTPTR)charcode, (FX_LPVOID&)pChar)) {\r
1687         if (pChar->m_bPageRequired && m_pPageResources) {\r
1688             delete pChar;\r
1689             m_CacheMap.RemoveKey((FX_LPVOID)(FX_UINTPTR)charcode);\r
1690             return LoadChar(charcode, level + 1);\r
1691         }\r
1692         return pChar;\r
1693     }\r
1694     FX_LPCSTR name = GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode);\r
1695     if (name == NULL) {\r
1696         return NULL;\r
1697     }\r
1698     CPDF_Stream* pStream = (CPDF_Stream*)m_pCharProcs->GetElementValue(name);\r
1699     if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) {\r
1700         return NULL;\r
1701     }\r
1702     pChar = FX_NEW CPDF_Type3Char;\r
1703     pChar->m_pForm = FX_NEW CPDF_Form(m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources, pStream, NULL);\r
1704     pChar->m_pForm->ParseContent(NULL, NULL, pChar, NULL, level + 1);\r
1705     FX_FLOAT scale = m_FontMatrix.GetXUnit();\r
1706     pChar->m_Width = (FX_INT32)(pChar->m_Width * scale + 0.5f);\r
1707     FX_RECT &rcBBox = pChar->m_BBox;\r
1708     CFX_FloatRect char_rect((FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f,\r
1709                             (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f);\r
1710     if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top) {\r
1711         char_rect = pChar->m_pForm->CalcBoundingBox();\r
1712     }\r
1713     char_rect.Transform(&m_FontMatrix);\r
1714     rcBBox.left = FXSYS_round(char_rect.left * 1000);\r
1715     rcBBox.right = FXSYS_round(char_rect.right * 1000);\r
1716     rcBBox.top = FXSYS_round(char_rect.top * 1000);\r
1717     rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000);\r
1718     m_CacheMap.SetAt((FX_LPVOID)(FX_UINTPTR)charcode, pChar);\r
1719     if (pChar->m_pForm->CountObjects() == 0) {\r
1720         delete pChar->m_pForm;\r
1721         pChar->m_pForm = NULL;\r
1722     }\r
1723     return pChar;\r
1724 }\r
1725 int CPDF_Type3Font::GetCharWidthF(FX_DWORD charcode, int level)\r
1726 {\r
1727     if (charcode > 0xff) {\r
1728         charcode = 0;\r
1729     }\r
1730     if (m_CharWidthL[charcode]) {\r
1731         return m_CharWidthL[charcode];\r
1732     }\r
1733     CPDF_Type3Char* pChar = LoadChar(charcode, level);\r
1734     if (pChar == NULL) {\r
1735         return 0;\r
1736     }\r
1737     return pChar->m_Width;\r
1738 }\r
1739 void CPDF_Type3Font::GetCharBBox(FX_DWORD charcode, FX_RECT& rect, int level)\r
1740 {\r
1741     CPDF_Type3Char* pChar = LoadChar(charcode, level);\r
1742     if (pChar == NULL) {\r
1743         rect.left = rect.right = rect.top = rect.bottom = 0;\r
1744         return;\r
1745     }\r
1746     rect = pChar->m_BBox;\r
1747 }\r
1748 CPDF_Type3Char::CPDF_Type3Char()\r
1749 {\r
1750     m_pForm = NULL;\r
1751     m_pBitmap = NULL;\r
1752     m_bPageRequired = FALSE;\r
1753     m_bColored = FALSE;\r
1754 }\r
1755 CPDF_Type3Char::~CPDF_Type3Char()\r
1756 {\r
1757     if (m_pForm) {\r
1758         delete m_pForm;\r
1759     }\r
1760     if (m_pBitmap) {\r
1761         delete m_pBitmap;\r
1762     }\r
1763 }\r