Add a newline at the end of fpdfeditpage.cpp.
[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(FX_INT32 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(FX_INT32 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(FX_INT32 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 FX_INT32 CPWL_FontMap::GetWordFontIndex(FX_WORD word, FX_INT32 nCharset, FX_INT32 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         FX_INT32 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 FX_INT32 CPWL_FontMap::CharCodeFromUnicode(FX_INT32 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(FX_INT32 nCharset)
157 {
158         //searching native font is slow, so we must save time
159         for (FX_INT32 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 (FX_INT32 i=0, sz=m_aData.GetSize(); i<sz; i++)
186                         delete m_aData.GetAt(i);
187
188                 m_aData.RemoveAll();
189         }
190         {
191                 for (FX_INT32 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 (FX_INT32 i=0; i<14; i++)
227         {
228                 if (sFontName == g_sDEStandardFontName[i])
229                         return TRUE;
230         }
231
232         return FALSE;
233 }
234
235 FX_INT32 CPWL_FontMap::FindFont(const CFX_ByteString& sFontName, FX_INT32 nCharset)
236 {
237         for (FX_INT32 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 FX_INT32 CPWL_FontMap::GetFontIndex(const CFX_ByteString& sFontName, FX_INT32 nCharset, FX_BOOL bFind)
253 {
254         FX_INT32 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 FX_INT32 CPWL_FontMap::GetPWLFontIndex(FX_WORD word, FX_INT32 nCharset)
289 {
290         FX_INT32 nFind = -1;
291
292         for (FX_INT32 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 #ifdef FOXIT_CHROME_BUILD
316   CFX_ByteString sAlias = EncodeFontAlias("Arial_Chrome", nCharset);
317 #else
318         CFX_ByteString sAlias = EncodeFontAlias("Arial_Foxit", nCharset);
319 #endif
320         AddedFont(pNewFont, sAlias);
321
322         return AddFontData(pNewFont, sAlias, nCharset);
323 }
324
325 CPDF_Font* CPWL_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, FX_INT32 nCharset)
326 {
327         return NULL;
328 }
329
330 FX_INT32 CPWL_FontMap::AddFontData(CPDF_Font* pFont, const CFX_ByteString& sFontAlias, FX_INT32 nCharset)
331 {
332         CPWL_FontMap_Data* pNewData = new CPWL_FontMap_Data;
333         pNewData->pFont = pFont;
334         pNewData->sFontName = sFontAlias;
335         pNewData->nCharset = nCharset;
336
337         m_aData.Add(pNewData);
338
339         return m_aData.GetSize() -1;
340 }
341
342 void CPWL_FontMap::AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias)
343 {
344 }
345
346 CFX_ByteString CPWL_FontMap::GetFontName(FX_INT32 nFontIndex)
347 {
348         if (nFontIndex >=0 && nFontIndex < m_aData.GetSize())
349         {
350                 if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex))
351                 {
352                         return pData->sFontName;
353                 }
354         }
355
356         return "";
357 }
358
359 CFX_ByteString CPWL_FontMap::GetNativeFont(FX_INT32 nCharset)
360 {
361         CFX_ByteString sFontName;
362
363         if (nCharset == DEFAULT_CHARSET)
364                 nCharset = GetNativeCharset();
365
366         sFontName = GetDefaultFontByCharset(nCharset);
367
368         if (m_pSystemHandler)
369         {
370                 if (m_pSystemHandler->FindNativeTrueTypeFont(nCharset, sFontName))
371                         return sFontName;
372
373                 sFontName = m_pSystemHandler->GetNativeTrueTypeFont(nCharset);
374         }
375
376         return sFontName;
377 }
378
379 CPDF_Font* CPWL_FontMap::AddFontToDocument(CPDF_Document* pDoc, CFX_ByteString& sFontName, FX_BYTE nCharset)
380 {
381         if (IsStandardFont(sFontName))
382                 return AddStandardFont(pDoc, sFontName);
383         else
384                 return AddSystemFont(pDoc, sFontName, nCharset);
385 }
386
387 CPDF_Font* CPWL_FontMap::AddStandardFont(CPDF_Document* pDoc, CFX_ByteString& sFontName)
388 {
389         if (!pDoc) return NULL;
390
391         CPDF_Font* pFont = NULL;
392
393         if (sFontName == "ZapfDingbats")
394                 pFont = pDoc->AddStandardFont(sFontName, NULL);
395         else
396         {
397                 CPDF_FontEncoding fe(PDFFONT_ENCODING_WINANSI);
398                 pFont = pDoc->AddStandardFont(sFontName, &fe);
399         }
400
401         return pFont;
402 }
403
404 CPDF_Font* CPWL_FontMap::AddSystemFont(CPDF_Document* pDoc, CFX_ByteString& sFontName, FX_BYTE nCharset)
405 {
406         if (!pDoc) return NULL;
407
408         if (sFontName.IsEmpty()) sFontName = GetNativeFont(nCharset);
409         if (nCharset == DEFAULT_CHARSET) nCharset = GetNativeCharset();
410
411         if (m_pSystemHandler)
412                 return m_pSystemHandler->AddNativeTrueTypeFontToPDF(pDoc, sFontName, nCharset);
413         
414         return NULL;
415 }
416
417 CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName, FX_INT32 nCharset)
418 {
419         CFX_ByteString sPostfix;
420         sPostfix.Format("_%02X", nCharset);
421         return EncodeFontAlias(sFontName) + sPostfix;
422 }
423
424 CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName)
425 {
426         CFX_ByteString sRet = sFontName;
427         sRet.Remove(' ');
428         return sRet;
429 }
430
431 FX_INT32 CPWL_FontMap::GetFontMapCount() const
432 {
433         return m_aData.GetSize();
434 }
435
436 const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(FX_INT32 nIndex) const
437 {
438         if (nIndex >=0 && nIndex < m_aData.GetSize())
439         {
440                 return m_aData.GetAt(nIndex);
441         }
442
443         return NULL;
444 }
445
446 FX_INT32 CPWL_FontMap::GetNativeCharset()
447 {
448         FX_BYTE nCharset = ANSI_CHARSET;
449         FX_INT32 iCodePage = FXSYS_GetACP();
450         switch (iCodePage)
451         {
452         case 932://Japan
453                 nCharset = SHIFTJIS_CHARSET;
454                 break;
455         case 936://Chinese (PRC, Singapore)
456                 nCharset = GB2312_CHARSET;
457                 break;
458         case 950://Chinese (Taiwan; Hong Kong SAR, PRC)
459                 nCharset = GB2312_CHARSET;
460                 break;
461         case 1252://Windows 3.1 Latin 1 (US, Western Europe)
462                 nCharset = ANSI_CHARSET;
463                 break;
464         case 874://Thai
465                 nCharset = THAI_CHARSET;
466                 break;
467         case 949://Korean
468                 nCharset = HANGUL_CHARSET;
469                 break;
470         case 1200://Unicode (BMP of ISO 10646)
471                 nCharset = ANSI_CHARSET;
472                 break;
473         case 1250://Windows 3.1 Eastern European
474                 nCharset = EASTEUROPE_CHARSET;
475                 break;
476         case 1251://Windows 3.1 Cyrillic
477                 nCharset = RUSSIAN_CHARSET;
478                 break;
479         case 1253://Windows 3.1 Greek
480                 nCharset = GREEK_CHARSET;
481                 break;
482         case 1254://Windows 3.1 Turkish
483                 nCharset = TURKISH_CHARSET;
484                 break;
485         case 1255://Hebrew
486                 nCharset = HEBREW_CHARSET;
487                 break;
488         case 1256://Arabic
489                 nCharset = ARABIC_CHARSET;
490                 break;
491         case 1257://Baltic
492                 nCharset = BALTIC_CHARSET;
493                 break;
494         case 1258://Vietnamese
495                 nCharset = VIETNAMESE_CHARSET;
496                 break;
497         case 1361://Korean(Johab)
498                 nCharset = JOHAB_CHARSET;
499                 break;
500         }
501         return nCharset;
502 }
503
504 const CPWL_FontMap::CharsetFontMap CPWL_FontMap::defaultTTFMap[] = {
505         { ANSI_CHARSET, "Helvetica" },
506         { GB2312_CHARSET, "SimSun" },
507         { CHINESEBIG5_CHARSET, "MingLiU" },
508         { SHIFTJIS_CHARSET, "MS Gothic" },
509         { HANGUL_CHARSET, "Batang" },
510         { RUSSIAN_CHARSET, "Arial" },
511 #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
512         { EASTEUROPE_CHARSET, "Arial" },
513 #else
514         { EASTEUROPE_CHARSET, "Tahoma" },
515 #endif
516         { ARABIC_CHARSET, "Arial" },
517         { -1, NULL }
518 };
519
520 CFX_ByteString CPWL_FontMap::GetDefaultFontByCharset(FX_INT32 nCharset)
521 {
522         int i = 0;
523         while (defaultTTFMap[i].charset != -1) {
524                 if (nCharset == defaultTTFMap[i].charset)
525                         return defaultTTFMap[i].fontname;
526         ++i;
527         }
528         return "";
529 }
530
531 FX_INT32 CPWL_FontMap::CharSetFromUnicode(FX_WORD word, FX_INT32 nOldCharset)
532 {
533         if(m_pSystemHandler && (-1 != m_pSystemHandler->GetCharSet()))
534                 return m_pSystemHandler->GetCharSet();
535         //to avoid CJK Font to show ASCII
536         if (word < 0x7F) return ANSI_CHARSET;
537         //follow the old charset
538         if (nOldCharset != DEFAULT_CHARSET) return nOldCharset;
539
540         //find new charset
541         if ((word >= 0x4E00 && word <= 0x9FA5) || 
542                 (word >= 0xE7C7 && word <= 0xE7F3) ||
543                 (word >= 0x3000 && word <= 0x303F) || //£©"¡¶" "¡·" "¡£" "¡¢" 
544                 (word >= 0x2000 && word <= 0x206F))
545         {
546                 return GB2312_CHARSET;
547         }
548
549         if (((word >= 0x3040) && (word <= 0x309F)) ||
550                 ((word >= 0x30A0) && (word <= 0x30FF)) ||
551                 ((word >= 0x31F0) && (word <= 0x31FF)) ||
552                 ((word >= 0xFF00) && (word <= 0xFFEF)) )
553         {
554                 return SHIFTJIS_CHARSET;
555         }
556
557         if (((word >= 0xAC00) && (word <= 0xD7AF)) ||
558                 ((word >= 0x1100) && (word <= 0x11FF)) ||
559                 ((word >= 0x3130) && (word <= 0x318F)))
560         {
561                 return HANGUL_CHARSET;
562         }
563
564         if (word >= 0x0E00 && word <= 0x0E7F)
565                 return THAI_CHARSET;
566
567         if ((word >= 0x0370 && word <= 0x03FF) ||
568                 (word >= 0x1F00 && word <= 0x1FFF))
569                 return GREEK_CHARSET;
570
571         if ((word >= 0x0600 && word <= 0x06FF) ||
572                 (word >= 0xFB50 && word <= 0xFEFC))
573                 return ARABIC_CHARSET;
574
575         if (word >= 0x0590 && word <= 0x05FF)
576                 return HEBREW_CHARSET;
577
578         if (word >= 0x0400 && word <= 0x04FF)
579                 return RUSSIAN_CHARSET;
580
581         if (word >= 0x0100 && word <= 0x024F)
582                 return EASTEUROPE_CHARSET;
583
584         if (word >= 0x1E00 && word <= 0x1EFF)
585                 return VIETNAMESE_CHARSET;
586
587         return ANSI_CHARSET;
588 }
589
590 /* ------------------------ CPWL_DocFontMap ------------------------ */
591
592 CPWL_DocFontMap::CPWL_DocFontMap(IFX_SystemHandler* pSystemHandler, CPDF_Document* pAttachedDoc) 
593         : CPWL_FontMap(pSystemHandler),
594         m_pAttachedDoc(pAttachedDoc)
595 {
596 }
597
598 CPWL_DocFontMap::~CPWL_DocFontMap()
599 {
600 }
601
602 CPDF_Document* CPWL_DocFontMap::GetDocument()
603 {
604         return m_pAttachedDoc;
605 }