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