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