Merge to XFA: Use stdint.h types throughout PDFium.
[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 = FX_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 = this->GetFontIndex(GetNativeFontName(nCharset), nCharset, TRUE);
117         if (nNewFontIndex >= 0)
118         {
119                 if (KnowWord(nNewFontIndex, word))
120                         return nNewFontIndex;
121         }
122
123         nNewFontIndex = this->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(FX_LPCSTR 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         //GetFontIndex(this->GetNativeFontName(nCharset), nCharset);
208 }
209         
210
211 /*
212 List of currently supported standard fonts:
213 Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique
214 Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique
215 Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic
216 Symbol, ZapfDingbats
217 */
218
219 const char* g_sDEStandardFontName[] = {"Courier", "Courier-Bold", "Courier-BoldOblique", "Courier-Oblique",
220         "Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique", "Helvetica-Oblique",
221         "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
222         "Symbol", "ZapfDingbats"};
223
224 FX_BOOL CPWL_FontMap::IsStandardFont(const CFX_ByteString& sFontName)
225 {
226         for (int32_t i=0; i<14; i++)
227         {
228                 if (sFontName == g_sDEStandardFontName[i])
229                         return TRUE;
230         }
231
232         return FALSE;
233 }
234
235 int32_t CPWL_FontMap::FindFont(const CFX_ByteString& sFontName, int32_t nCharset)
236 {
237         for (int32_t i=0,sz=m_aData.GetSize(); i<sz; i++)
238         {
239                 if (CPWL_FontMap_Data* pData = m_aData.GetAt(i))
240                 {
241                         if (nCharset == DEFAULT_CHARSET || nCharset == pData->nCharset)
242                         {
243                                 if (sFontName.IsEmpty() || pData->sFontName == sFontName)
244                                         return i;
245                         }
246                 }
247         }
248
249         return -1;
250 }
251
252 int32_t CPWL_FontMap::GetFontIndex(const CFX_ByteString& sFontName, int32_t nCharset, FX_BOOL bFind)
253 {
254         int32_t nFontIndex = FindFont(EncodeFontAlias(sFontName, nCharset), nCharset);
255         if (nFontIndex >= 0) return nFontIndex;
256
257 //      nFontIndex = FindFont("", nCharset);
258 //      if (nFontIndex >= 0) return nFontIndex;
259
260         CFX_ByteString sAlias;
261         CPDF_Font* pFont = NULL;
262
263         if (bFind)
264                 pFont = FindFontSameCharset(sAlias, nCharset);
265
266         if (!pFont)
267         {
268                 CFX_ByteString sTemp = sFontName;
269                 pFont = AddFontToDocument(GetDocument(), sTemp, nCharset);
270
271                 /*
272                 if (FindFont(sAlias))
273                 {
274                         sAlias = EncodeFontAlias(sTemp, nCharset);
275                 }
276                 else
277                 */
278                 {
279                         sAlias = EncodeFontAlias(sTemp, nCharset);
280                 }               
281         }
282
283         AddedFont(pFont, sAlias);
284
285         return AddFontData(pFont, sAlias, nCharset);
286 }
287
288 int32_t CPWL_FontMap::GetPWLFontIndex(FX_WORD word, int32_t nCharset)
289 {
290         int32_t nFind = -1;
291
292         for (int32_t i=0,sz=m_aData.GetSize(); i<sz; i++)
293         {
294                 if (CPWL_FontMap_Data* pData = m_aData.GetAt(i))
295                 {
296                         if (pData->nCharset == nCharset)
297                         {
298                                 nFind = i;
299                                 break;
300                         }
301                 }
302         }
303
304         CPDF_Font* pNewFont = GetPDFFont(nFind);
305
306         if (!pNewFont) return -1;
307
308         /*
309         if (CPDF_Font* pFont = GetPDFFont(nFind))
310         {
311                 PWLFont.AddWordToFontDict(pFontDict, word);
312         }
313         */
314
315         CFX_ByteString sAlias = EncodeFontAlias("Arial_Chrome", nCharset);
316         AddedFont(pNewFont, sAlias);
317
318         return AddFontData(pNewFont, sAlias, nCharset);
319 }
320
321 CPDF_Font* CPWL_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, int32_t nCharset)
322 {
323         return NULL;
324 }
325
326 int32_t CPWL_FontMap::AddFontData(CPDF_Font* pFont, const CFX_ByteString& sFontAlias, int32_t nCharset)
327 {
328         CPWL_FontMap_Data* pNewData = new CPWL_FontMap_Data;
329         pNewData->pFont = pFont;
330         pNewData->sFontName = sFontAlias;
331         pNewData->nCharset = nCharset;
332
333         m_aData.Add(pNewData);
334
335         return m_aData.GetSize() -1;
336 }
337
338 void CPWL_FontMap::AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias)
339 {
340 }
341
342 CFX_ByteString CPWL_FontMap::GetFontName(int32_t nFontIndex)
343 {
344         if (nFontIndex >=0 && nFontIndex < m_aData.GetSize())
345         {
346                 if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex))
347                 {
348                         return pData->sFontName;
349                 }
350         }
351
352         return "";
353 }
354
355 CFX_ByteString CPWL_FontMap::GetNativeFont(int32_t nCharset)
356 {
357         CFX_ByteString sFontName;
358
359         if (nCharset == DEFAULT_CHARSET)
360                 nCharset = GetNativeCharset();
361
362         sFontName = GetDefaultFontByCharset(nCharset);
363
364         if (m_pSystemHandler)
365         {
366                 if (m_pSystemHandler->FindNativeTrueTypeFont(nCharset, sFontName))
367                         return sFontName;
368
369                 sFontName = m_pSystemHandler->GetNativeTrueTypeFont(nCharset);
370         }
371
372         return sFontName;
373 }
374
375 CPDF_Font* CPWL_FontMap::AddFontToDocument(CPDF_Document* pDoc, CFX_ByteString& sFontName, uint8_t nCharset)
376 {
377         if (IsStandardFont(sFontName))
378                 return AddStandardFont(pDoc, sFontName);
379         else
380                 return AddSystemFont(pDoc, sFontName, nCharset);
381 }
382
383 CPDF_Font* CPWL_FontMap::AddStandardFont(CPDF_Document* pDoc, CFX_ByteString& sFontName)
384 {
385         if (!pDoc) return NULL;
386
387         CPDF_Font* pFont = NULL;
388
389         if (sFontName == "ZapfDingbats")
390                 pFont = pDoc->AddStandardFont(sFontName, NULL);
391         else
392         {
393                 CPDF_FontEncoding fe(PDFFONT_ENCODING_WINANSI);
394                 pFont = pDoc->AddStandardFont(sFontName, &fe);
395         }
396
397         return pFont;
398 }
399
400 CPDF_Font* CPWL_FontMap::AddSystemFont(CPDF_Document* pDoc, CFX_ByteString& sFontName, uint8_t nCharset)
401 {
402         if (!pDoc) return NULL;
403
404         if (sFontName.IsEmpty()) sFontName = GetNativeFont(nCharset);
405         if (nCharset == DEFAULT_CHARSET) nCharset = GetNativeCharset();
406
407         if (m_pSystemHandler)
408                 return m_pSystemHandler->AddNativeTrueTypeFontToPDF(pDoc, sFontName, nCharset);
409         
410         return NULL;
411 }
412
413 CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName, int32_t nCharset)
414 {
415         CFX_ByteString sPostfix;
416         sPostfix.Format("_%02X", nCharset);
417         return EncodeFontAlias(sFontName) + sPostfix;
418 }
419
420 CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName)
421 {
422         CFX_ByteString sRet = sFontName;
423         sRet.Remove(' ');
424         return sRet;
425 }
426
427 int32_t CPWL_FontMap::GetFontMapCount() const
428 {
429         return m_aData.GetSize();
430 }
431
432 const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(int32_t nIndex) const
433 {
434         if (nIndex >=0 && nIndex < m_aData.GetSize())
435         {
436                 return m_aData.GetAt(nIndex);
437         }
438
439         return NULL;
440 }
441
442 int32_t CPWL_FontMap::GetNativeCharset()
443 {
444         uint8_t nCharset = ANSI_CHARSET;
445         int32_t iCodePage = FXSYS_GetACP();
446         switch (iCodePage)
447         {
448         case 932://Japan
449                 nCharset = SHIFTJIS_CHARSET;
450                 break;
451         case 936://Chinese (PRC, Singapore)
452                 nCharset = GB2312_CHARSET;
453                 break;
454         case 950://Chinese (Taiwan; Hong Kong SAR, PRC)
455                 nCharset = GB2312_CHARSET;
456                 break;
457         case 1252://Windows 3.1 Latin 1 (US, Western Europe)
458                 nCharset = ANSI_CHARSET;
459                 break;
460         case 874://Thai
461                 nCharset = THAI_CHARSET;
462                 break;
463         case 949://Korean
464                 nCharset = HANGUL_CHARSET;
465                 break;
466         case 1200://Unicode (BMP of ISO 10646)
467                 nCharset = ANSI_CHARSET;
468                 break;
469         case 1250://Windows 3.1 Eastern European
470                 nCharset = EASTEUROPE_CHARSET;
471                 break;
472         case 1251://Windows 3.1 Cyrillic
473                 nCharset = RUSSIAN_CHARSET;
474                 break;
475         case 1253://Windows 3.1 Greek
476                 nCharset = GREEK_CHARSET;
477                 break;
478         case 1254://Windows 3.1 Turkish
479                 nCharset = TURKISH_CHARSET;
480                 break;
481         case 1255://Hebrew
482                 nCharset = HEBREW_CHARSET;
483                 break;
484         case 1256://Arabic
485                 nCharset = ARABIC_CHARSET;
486                 break;
487         case 1257://Baltic
488                 nCharset = BALTIC_CHARSET;
489                 break;
490         case 1258://Vietnamese
491                 nCharset = VIETNAMESE_CHARSET;
492                 break;
493         case 1361://Korean(Johab)
494                 nCharset = JOHAB_CHARSET;
495                 break;
496         }
497         return nCharset;
498 }
499
500 const CPWL_FontMap::CharsetFontMap CPWL_FontMap::defaultTTFMap[] = {
501         { ANSI_CHARSET, "Helvetica" },
502         { GB2312_CHARSET, "SimSun" },
503         { CHINESEBIG5_CHARSET, "MingLiU" },
504         { SHIFTJIS_CHARSET, "MS Gothic" },
505         { HANGUL_CHARSET, "Batang" },
506         { RUSSIAN_CHARSET, "Arial" },
507 #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
508         { EASTEUROPE_CHARSET, "Arial" },
509 #else
510         { EASTEUROPE_CHARSET, "Tahoma" },
511 #endif
512         { ARABIC_CHARSET, "Arial" },
513         { -1, NULL }
514 };
515
516 CFX_ByteString CPWL_FontMap::GetDefaultFontByCharset(int32_t nCharset)
517 {
518         int i = 0;
519         while (defaultTTFMap[i].charset != -1) {
520                 if (nCharset == defaultTTFMap[i].charset)
521                         return defaultTTFMap[i].fontname;
522         ++i;
523         }
524         return "";
525 }
526
527 int32_t CPWL_FontMap::CharSetFromUnicode(FX_WORD word, int32_t nOldCharset)
528 {
529         if(m_pSystemHandler && (-1 != m_pSystemHandler->GetCharSet()))
530                 return m_pSystemHandler->GetCharSet();
531         //to avoid CJK Font to show ASCII
532         if (word < 0x7F) return ANSI_CHARSET;
533         //follow the old charset
534         if (nOldCharset != DEFAULT_CHARSET) return nOldCharset;
535
536         //find new charset
537         if ((word >= 0x4E00 && word <= 0x9FA5) || 
538                 (word >= 0xE7C7 && word <= 0xE7F3) ||
539                 (word >= 0x3000 && word <= 0x303F) || //£©"¡¶" "¡·" "¡£" "¡¢" 
540                 (word >= 0x2000 && word <= 0x206F))
541         {
542                 return GB2312_CHARSET;
543         }
544
545         if (((word >= 0x3040) && (word <= 0x309F)) ||
546                 ((word >= 0x30A0) && (word <= 0x30FF)) ||
547                 ((word >= 0x31F0) && (word <= 0x31FF)) ||
548                 ((word >= 0xFF00) && (word <= 0xFFEF)) )
549         {
550                 return SHIFTJIS_CHARSET;
551         }
552
553         if (((word >= 0xAC00) && (word <= 0xD7AF)) ||
554                 ((word >= 0x1100) && (word <= 0x11FF)) ||
555                 ((word >= 0x3130) && (word <= 0x318F)))
556         {
557                 return HANGUL_CHARSET;
558         }
559
560         if (word >= 0x0E00 && word <= 0x0E7F)
561                 return THAI_CHARSET;
562
563         if ((word >= 0x0370 && word <= 0x03FF) ||
564                 (word >= 0x1F00 && word <= 0x1FFF))
565                 return GREEK_CHARSET;
566
567         if ((word >= 0x0600 && word <= 0x06FF) ||
568                 (word >= 0xFB50 && word <= 0xFEFC))
569                 return ARABIC_CHARSET;
570
571         if (word >= 0x0590 && word <= 0x05FF)
572                 return HEBREW_CHARSET;
573
574         if (word >= 0x0400 && word <= 0x04FF)
575                 return RUSSIAN_CHARSET;
576
577         if (word >= 0x0100 && word <= 0x024F)
578                 return EASTEUROPE_CHARSET;
579
580         if (word >= 0x1E00 && word <= 0x1EFF)
581                 return VIETNAMESE_CHARSET;
582
583         return ANSI_CHARSET;
584 }
585
586 /* ------------------------ CPWL_DocFontMap ------------------------ */
587
588 CPWL_DocFontMap::CPWL_DocFontMap(IFX_SystemHandler* pSystemHandler, CPDF_Document* pAttachedDoc) 
589         : CPWL_FontMap(pSystemHandler),
590         m_pAttachedDoc(pAttachedDoc)
591 {
592 }
593
594 CPWL_DocFontMap::~CPWL_DocFontMap()
595 {
596 }
597
598 CPDF_Document* CPWL_DocFontMap::GetDocument()
599 {
600         return m_pAttachedDoc;
601 }