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