Use override in more classes in core/
[pdfium.git] / fpdfsdk / src / pdfwindow / PWL_FontMap.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../include/pdfwindow/PDFWindow.h"
8 #include "../../include/pdfwindow/PWL_Wnd.h"
9 #include "../../include/pdfwindow/PWL_FontMap.h"
10
11 #define DEFAULT_FONT_NAME "Helvetica"
12
13 /* ------------------------------ CPWL_FontMap ------------------------------ */
14
15 CPWL_FontMap::CPWL_FontMap(IFX_SystemHandler* pSystemHandler)
16     : m_pPDFDoc(NULL), m_pSystemHandler(pSystemHandler) {
17   ASSERT(m_pSystemHandler != NULL);
18 }
19
20 CPWL_FontMap::~CPWL_FontMap() {
21   delete m_pPDFDoc;
22   m_pPDFDoc = NULL;
23
24   Empty();
25 }
26
27 void CPWL_FontMap::SetSystemHandler(IFX_SystemHandler* pSystemHandler) {
28   m_pSystemHandler = pSystemHandler;
29 }
30
31 CPDF_Document* CPWL_FontMap::GetDocument() {
32   if (!m_pPDFDoc) {
33     if (CPDF_ModuleMgr::Get()) {
34       m_pPDFDoc = new CPDF_Document;
35       m_pPDFDoc->CreateNewDoc();
36     }
37   }
38
39   return m_pPDFDoc;
40 }
41
42 CPDF_Font* CPWL_FontMap::GetPDFFont(int32_t nFontIndex) {
43   if (nFontIndex >= 0 && nFontIndex < m_aData.GetSize()) {
44     if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex)) {
45       return pData->pFont;
46     }
47   }
48
49   return NULL;
50 }
51
52 CFX_ByteString CPWL_FontMap::GetPDFFontAlias(int32_t nFontIndex) {
53   if (nFontIndex >= 0 && nFontIndex < m_aData.GetSize()) {
54     if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex)) {
55       return pData->sFontName;
56     }
57   }
58
59   return "";
60 }
61
62 FX_BOOL CPWL_FontMap::KnowWord(int32_t nFontIndex, FX_WORD word) {
63   if (nFontIndex >= 0 && nFontIndex < m_aData.GetSize()) {
64     if (m_aData.GetAt(nFontIndex)) {
65       return CharCodeFromUnicode(nFontIndex, word) >= 0;
66     }
67   }
68
69   return FALSE;
70 }
71
72 int32_t CPWL_FontMap::GetWordFontIndex(FX_WORD word,
73                                        int32_t nCharset,
74                                        int32_t nFontIndex) {
75   if (nFontIndex > 0) {
76     if (KnowWord(nFontIndex, word))
77       return nFontIndex;
78   } else {
79     if (const CPWL_FontMap_Data* pData = GetFontMapData(0)) {
80       if (nCharset == DEFAULT_CHARSET || pData->nCharset == SYMBOL_CHARSET ||
81           nCharset == pData->nCharset) {
82         if (KnowWord(0, word))
83           return 0;
84       }
85     }
86   }
87
88   int32_t nNewFontIndex =
89       GetFontIndex(GetNativeFontName(nCharset), nCharset, TRUE);
90   if (nNewFontIndex >= 0) {
91     if (KnowWord(nNewFontIndex, word))
92       return nNewFontIndex;
93   }
94   nNewFontIndex = GetFontIndex("Arial Unicode MS", DEFAULT_CHARSET, FALSE);
95   if (nNewFontIndex >= 0) {
96     if (KnowWord(nNewFontIndex, word))
97       return nNewFontIndex;
98   }
99   return -1;
100 }
101
102 int32_t CPWL_FontMap::CharCodeFromUnicode(int32_t nFontIndex, FX_WORD word) {
103   if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex)) {
104     if (pData->pFont) {
105       if (pData->pFont->IsUnicodeCompatible()) {
106         int nCharCode = pData->pFont->CharCodeFromUnicode(word);
107         pData->pFont->GlyphFromCharCode(nCharCode);
108         return nCharCode;
109       }
110       if (word < 0xFF)
111         return word;
112     }
113   }
114   return -1;
115 }
116
117 CFX_ByteString CPWL_FontMap::GetNativeFontName(int32_t nCharset) {
118   // searching native font is slow, so we must save time
119   for (int32_t i = 0, sz = m_aNativeFont.GetSize(); i < sz; i++) {
120     if (CPWL_FontMap_Native* pData = m_aNativeFont.GetAt(i)) {
121       if (pData->nCharset == nCharset)
122         return pData->sFontName;
123     }
124   }
125
126   CFX_ByteString sNew = GetNativeFont(nCharset);
127
128   if (!sNew.IsEmpty()) {
129     CPWL_FontMap_Native* pNewData = new CPWL_FontMap_Native;
130     pNewData->nCharset = nCharset;
131     pNewData->sFontName = sNew;
132
133     m_aNativeFont.Add(pNewData);
134   }
135
136   return sNew;
137 }
138
139 void CPWL_FontMap::Empty() {
140   {
141     for (int32_t i = 0, sz = m_aData.GetSize(); i < sz; i++)
142       delete m_aData.GetAt(i);
143
144     m_aData.RemoveAll();
145   }
146   {
147     for (int32_t i = 0, sz = m_aNativeFont.GetSize(); i < sz; i++)
148       delete m_aNativeFont.GetAt(i);
149
150     m_aNativeFont.RemoveAll();
151   }
152 }
153
154 void CPWL_FontMap::Initial(const FX_CHAR* fontname) {
155   CFX_ByteString sFontName = fontname;
156
157   if (sFontName.IsEmpty())
158     sFontName = DEFAULT_FONT_NAME;
159
160   GetFontIndex(sFontName, ANSI_CHARSET, FALSE);
161 }
162
163 /*
164 List of currently supported standard fonts:
165 Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique
166 Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique
167 Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic
168 Symbol, ZapfDingbats
169 */
170
171 const char* g_sDEStandardFontName[] = {"Courier",
172                                        "Courier-Bold",
173                                        "Courier-BoldOblique",
174                                        "Courier-Oblique",
175                                        "Helvetica",
176                                        "Helvetica-Bold",
177                                        "Helvetica-BoldOblique",
178                                        "Helvetica-Oblique",
179                                        "Times-Roman",
180                                        "Times-Bold",
181                                        "Times-Italic",
182                                        "Times-BoldItalic",
183                                        "Symbol",
184                                        "ZapfDingbats"};
185
186 FX_BOOL CPWL_FontMap::IsStandardFont(const CFX_ByteString& sFontName) {
187   for (int32_t i = 0; i < 14; i++) {
188     if (sFontName == g_sDEStandardFontName[i])
189       return TRUE;
190   }
191
192   return FALSE;
193 }
194
195 int32_t CPWL_FontMap::FindFont(const CFX_ByteString& sFontName,
196                                int32_t nCharset) {
197   for (int32_t i = 0, sz = m_aData.GetSize(); i < sz; i++) {
198     if (CPWL_FontMap_Data* pData = m_aData.GetAt(i)) {
199       if (nCharset == DEFAULT_CHARSET || nCharset == pData->nCharset) {
200         if (sFontName.IsEmpty() || pData->sFontName == sFontName)
201           return i;
202       }
203     }
204   }
205
206   return -1;
207 }
208
209 int32_t CPWL_FontMap::GetFontIndex(const CFX_ByteString& sFontName,
210                                    int32_t nCharset,
211                                    FX_BOOL bFind) {
212   int32_t nFontIndex = FindFont(EncodeFontAlias(sFontName, nCharset), nCharset);
213   if (nFontIndex >= 0)
214     return nFontIndex;
215
216   CFX_ByteString sAlias;
217   CPDF_Font* pFont = NULL;
218   if (bFind)
219     pFont = FindFontSameCharset(sAlias, nCharset);
220
221   if (!pFont) {
222     CFX_ByteString sTemp = sFontName;
223     pFont = AddFontToDocument(GetDocument(), sTemp, nCharset);
224     sAlias = EncodeFontAlias(sTemp, nCharset);
225   }
226   AddedFont(pFont, sAlias);
227   return AddFontData(pFont, sAlias, nCharset);
228 }
229
230 int32_t CPWL_FontMap::GetPWLFontIndex(FX_WORD word, int32_t nCharset) {
231   int32_t nFind = -1;
232
233   for (int32_t i = 0, sz = m_aData.GetSize(); i < sz; i++) {
234     if (CPWL_FontMap_Data* pData = m_aData.GetAt(i)) {
235       if (pData->nCharset == nCharset) {
236         nFind = i;
237         break;
238       }
239     }
240   }
241
242   CPDF_Font* pNewFont = GetPDFFont(nFind);
243
244   if (!pNewFont)
245     return -1;
246
247   /*
248   if (CPDF_Font* pFont = GetPDFFont(nFind))
249   {
250       PWLFont.AddWordToFontDict(pFontDict, word);
251   }
252   */
253
254   CFX_ByteString sAlias = EncodeFontAlias("Arial_Chrome", nCharset);
255   AddedFont(pNewFont, sAlias);
256
257   return AddFontData(pNewFont, sAlias, nCharset);
258 }
259
260 CPDF_Font* CPWL_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias,
261                                              int32_t nCharset) {
262   return NULL;
263 }
264
265 int32_t CPWL_FontMap::AddFontData(CPDF_Font* pFont,
266                                   const CFX_ByteString& sFontAlias,
267                                   int32_t nCharset) {
268   CPWL_FontMap_Data* pNewData = new CPWL_FontMap_Data;
269   pNewData->pFont = pFont;
270   pNewData->sFontName = sFontAlias;
271   pNewData->nCharset = nCharset;
272
273   m_aData.Add(pNewData);
274
275   return m_aData.GetSize() - 1;
276 }
277
278 void CPWL_FontMap::AddedFont(CPDF_Font* pFont,
279                              const CFX_ByteString& sFontAlias) {}
280
281 CFX_ByteString CPWL_FontMap::GetFontName(int32_t nFontIndex) {
282   if (nFontIndex >= 0 && nFontIndex < m_aData.GetSize()) {
283     if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex)) {
284       return pData->sFontName;
285     }
286   }
287
288   return "";
289 }
290
291 CFX_ByteString CPWL_FontMap::GetNativeFont(int32_t nCharset) {
292   if (nCharset == DEFAULT_CHARSET)
293     nCharset = GetNativeCharset();
294
295   CFX_ByteString sFontName = GetDefaultFontByCharset(nCharset);
296   if (m_pSystemHandler) {
297     if (m_pSystemHandler->FindNativeTrueTypeFont(nCharset, sFontName))
298       return sFontName;
299
300     sFontName = m_pSystemHandler->GetNativeTrueTypeFont(nCharset);
301   }
302   return sFontName;
303 }
304
305 CPDF_Font* CPWL_FontMap::AddFontToDocument(CPDF_Document* pDoc,
306                                            CFX_ByteString& sFontName,
307                                            uint8_t nCharset) {
308   if (IsStandardFont(sFontName))
309     return AddStandardFont(pDoc, sFontName);
310
311   return AddSystemFont(pDoc, sFontName, nCharset);
312 }
313
314 CPDF_Font* CPWL_FontMap::AddStandardFont(CPDF_Document* pDoc,
315                                          CFX_ByteString& sFontName) {
316   if (!pDoc)
317     return NULL;
318
319   CPDF_Font* pFont = NULL;
320
321   if (sFontName == "ZapfDingbats")
322     pFont = pDoc->AddStandardFont(sFontName, NULL);
323   else {
324     CPDF_FontEncoding fe(PDFFONT_ENCODING_WINANSI);
325     pFont = pDoc->AddStandardFont(sFontName, &fe);
326   }
327
328   return pFont;
329 }
330
331 CPDF_Font* CPWL_FontMap::AddSystemFont(CPDF_Document* pDoc,
332                                        CFX_ByteString& sFontName,
333                                        uint8_t nCharset) {
334   if (!pDoc)
335     return NULL;
336
337   if (sFontName.IsEmpty())
338     sFontName = GetNativeFont(nCharset);
339   if (nCharset == DEFAULT_CHARSET)
340     nCharset = GetNativeCharset();
341
342   if (m_pSystemHandler)
343     return m_pSystemHandler->AddNativeTrueTypeFontToPDF(pDoc, sFontName,
344                                                         nCharset);
345
346   return NULL;
347 }
348
349 CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName,
350                                              int32_t nCharset) {
351   CFX_ByteString sPostfix;
352   sPostfix.Format("_%02X", nCharset);
353   return EncodeFontAlias(sFontName) + sPostfix;
354 }
355
356 CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName) {
357   CFX_ByteString sRet = sFontName;
358   sRet.Remove(' ');
359   return sRet;
360 }
361
362 int32_t CPWL_FontMap::GetFontMapCount() const {
363   return m_aData.GetSize();
364 }
365
366 const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(int32_t nIndex) const {
367   if (nIndex >= 0 && nIndex < m_aData.GetSize()) {
368     return m_aData.GetAt(nIndex);
369   }
370
371   return NULL;
372 }
373
374 int32_t CPWL_FontMap::GetNativeCharset() {
375   uint8_t nCharset = ANSI_CHARSET;
376   int32_t iCodePage = FXSYS_GetACP();
377   switch (iCodePage) {
378     case 932:  // Japan
379       nCharset = SHIFTJIS_CHARSET;
380       break;
381     case 936:  // Chinese (PRC, Singapore)
382       nCharset = GB2312_CHARSET;
383       break;
384     case 950:  // Chinese (Taiwan; Hong Kong SAR, PRC)
385       nCharset = GB2312_CHARSET;
386       break;
387     case 1252:  // Windows 3.1 Latin 1 (US, Western Europe)
388       nCharset = ANSI_CHARSET;
389       break;
390     case 874:  // Thai
391       nCharset = THAI_CHARSET;
392       break;
393     case 949:  // Korean
394       nCharset = HANGUL_CHARSET;
395       break;
396     case 1200:  // Unicode (BMP of ISO 10646)
397       nCharset = ANSI_CHARSET;
398       break;
399     case 1250:  // Windows 3.1 Eastern European
400       nCharset = EASTEUROPE_CHARSET;
401       break;
402     case 1251:  // Windows 3.1 Cyrillic
403       nCharset = RUSSIAN_CHARSET;
404       break;
405     case 1253:  // Windows 3.1 Greek
406       nCharset = GREEK_CHARSET;
407       break;
408     case 1254:  // Windows 3.1 Turkish
409       nCharset = TURKISH_CHARSET;
410       break;
411     case 1255:  // Hebrew
412       nCharset = HEBREW_CHARSET;
413       break;
414     case 1256:  // Arabic
415       nCharset = ARABIC_CHARSET;
416       break;
417     case 1257:  // Baltic
418       nCharset = BALTIC_CHARSET;
419       break;
420     case 1258:  // Vietnamese
421       nCharset = VIETNAMESE_CHARSET;
422       break;
423     case 1361:  // Korean(Johab)
424       nCharset = JOHAB_CHARSET;
425       break;
426   }
427   return nCharset;
428 }
429
430 const CPWL_FontMap::CharsetFontMap CPWL_FontMap::defaultTTFMap[] = {
431     {ANSI_CHARSET, "Helvetica"},      {GB2312_CHARSET, "SimSun"},
432     {CHINESEBIG5_CHARSET, "MingLiU"}, {SHIFTJIS_CHARSET, "MS Gothic"},
433     {HANGUL_CHARSET, "Batang"},       {RUSSIAN_CHARSET, "Arial"},
434 #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || \
435     _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
436     {EASTEUROPE_CHARSET, "Arial"},
437 #else
438     {EASTEUROPE_CHARSET, "Tahoma"},
439 #endif
440     {ARABIC_CHARSET, "Arial"},        {-1, NULL}};
441
442 CFX_ByteString CPWL_FontMap::GetDefaultFontByCharset(int32_t nCharset) {
443   int i = 0;
444   while (defaultTTFMap[i].charset != -1) {
445     if (nCharset == defaultTTFMap[i].charset)
446       return defaultTTFMap[i].fontname;
447     ++i;
448   }
449   return "";
450 }
451
452 int32_t CPWL_FontMap::CharSetFromUnicode(FX_WORD word, int32_t nOldCharset) {
453   if (m_pSystemHandler && (-1 != m_pSystemHandler->GetCharSet()))
454     return m_pSystemHandler->GetCharSet();
455   // to avoid CJK Font to show ASCII
456   if (word < 0x7F)
457     return ANSI_CHARSET;
458   // follow the old charset
459   if (nOldCharset != DEFAULT_CHARSET)
460     return nOldCharset;
461
462   // find new charset
463   if ((word >= 0x4E00 && word <= 0x9FA5) ||
464       (word >= 0xE7C7 && word <= 0xE7F3) ||
465       (word >= 0x3000 && word <= 0x303F) ||
466       (word >= 0x2000 && word <= 0x206F)) {
467     return GB2312_CHARSET;
468   }
469
470   if (((word >= 0x3040) && (word <= 0x309F)) ||
471       ((word >= 0x30A0) && (word <= 0x30FF)) ||
472       ((word >= 0x31F0) && (word <= 0x31FF)) ||
473       ((word >= 0xFF00) && (word <= 0xFFEF))) {
474     return SHIFTJIS_CHARSET;
475   }
476
477   if (((word >= 0xAC00) && (word <= 0xD7AF)) ||
478       ((word >= 0x1100) && (word <= 0x11FF)) ||
479       ((word >= 0x3130) && (word <= 0x318F))) {
480     return HANGUL_CHARSET;
481   }
482
483   if (word >= 0x0E00 && word <= 0x0E7F)
484     return THAI_CHARSET;
485
486   if ((word >= 0x0370 && word <= 0x03FF) || (word >= 0x1F00 && word <= 0x1FFF))
487     return GREEK_CHARSET;
488
489   if ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
490     return ARABIC_CHARSET;
491
492   if (word >= 0x0590 && word <= 0x05FF)
493     return HEBREW_CHARSET;
494
495   if (word >= 0x0400 && word <= 0x04FF)
496     return RUSSIAN_CHARSET;
497
498   if (word >= 0x0100 && word <= 0x024F)
499     return EASTEUROPE_CHARSET;
500
501   if (word >= 0x1E00 && word <= 0x1EFF)
502     return VIETNAMESE_CHARSET;
503
504   return ANSI_CHARSET;
505 }
506
507 /* ------------------------ CPWL_DocFontMap ------------------------ */
508
509 CPWL_DocFontMap::CPWL_DocFontMap(IFX_SystemHandler* pSystemHandler,
510                                  CPDF_Document* pAttachedDoc)
511     : CPWL_FontMap(pSystemHandler), m_pAttachedDoc(pAttachedDoc) {}
512
513 CPWL_DocFontMap::~CPWL_DocFontMap() {}
514
515 CPDF_Document* CPWL_DocFontMap::GetDocument() {
516   return m_pAttachedDoc;
517 }