CFX_MapByteStringToPtr considered harmful.
[pdfium.git] / core / src / fxge / ge / fx_ge_linux.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/fxge/fx_ge.h"
8 #include "../agg/include/fx_agg_driver.h"
9 #include "text_int.h"
10
11 #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
12 static const struct {
13   const FX_CHAR* m_pName;
14   const FX_CHAR* m_pSubstName;
15 } Base14Substs[] = {
16     {"Courier", "Courier New"},
17     {"Courier-Bold", "Courier New Bold"},
18     {"Courier-BoldOblique", "Courier New Bold Italic"},
19     {"Courier-Oblique", "Courier New Italic"},
20     {"Helvetica", "Arial"},
21     {"Helvetica-Bold", "Arial Bold"},
22     {"Helvetica-BoldOblique", "Arial Bold Italic"},
23     {"Helvetica-Oblique", "Arial Italic"},
24     {"Times-Roman", "Times New Roman"},
25     {"Times-Bold", "Times New Roman Bold"},
26     {"Times-BoldItalic", "Times New Roman Bold Italic"},
27     {"Times-Italic", "Times New Roman Italic"},
28 };
29 class CFX_LinuxFontInfo : public CFX_FolderFontInfo {
30  public:
31   void* MapFont(int weight,
32                 FX_BOOL bItalic,
33                 int charset,
34                 int pitch_family,
35                 const FX_CHAR* family,
36                 int& iExact) override;
37   FX_BOOL ParseFontCfg(const char** pUserPaths);
38   void* FindFont(int weight,
39                  FX_BOOL bItalic,
40                  int charset,
41                  int pitch_family,
42                  const FX_CHAR* family,
43                  FX_BOOL bMatchName);
44 };
45 #define LINUX_GPNAMESIZE 6
46 static const struct {
47   const FX_CHAR* NameArr[LINUX_GPNAMESIZE];
48 } LinuxGpFontList[] = {
49     {{"TakaoPGothic", "VL PGothic", "IPAPGothic", "VL Gothic", "Kochi Gothic",
50       "VL Gothic regular"}},
51     {{"TakaoGothic", "VL Gothic", "IPAGothic", "Kochi Gothic", NULL,
52       "VL Gothic regular"}},
53     {{"TakaoPMincho", "IPAPMincho", "VL Gothic", "Kochi Mincho", NULL,
54       "VL Gothic regular"}},
55     {{"TakaoMincho", "IPAMincho", "VL Gothic", "Kochi Mincho", NULL,
56       "VL Gothic regular"}},
57 };
58 static const FX_CHAR* const g_LinuxGbFontList[] = {
59     "AR PL UMing CN Light", "WenQuanYi Micro Hei", "AR PL UKai CN",
60 };
61 static const FX_CHAR* const g_LinuxB5FontList[] = {
62     "AR PL UMing TW Light", "WenQuanYi Micro Hei", "AR PL UKai TW",
63 };
64 static const FX_CHAR* const g_LinuxHGFontList[] = {
65     "UnDotum",
66 };
67 static int32_t GetJapanesePreference(const FX_CHAR* facearr,
68                                      int weight,
69                                      int picth_family) {
70   CFX_ByteString face = facearr;
71   if (face.Find("Gothic") >= 0 ||
72       face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) {
73     if (face.Find("PGothic") >= 0 ||
74         face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) {
75       return 0;
76     }
77     return 1;
78   }
79   if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) {
80     if (face.Find("PMincho") >= 0 ||
81         face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) {
82       return 2;
83     }
84     return 3;
85   }
86   if (!(picth_family & FXFONT_FF_ROMAN) && weight > 400) {
87     return 0;
88   }
89   return 2;
90 }
91 void* CFX_LinuxFontInfo::MapFont(int weight,
92                                  FX_BOOL bItalic,
93                                  int charset,
94                                  int pitch_family,
95                                  const FX_CHAR* cstr_face,
96                                  int& iExact) {
97   CFX_ByteString face = cstr_face;
98   int iBaseFont;
99   for (iBaseFont = 0; iBaseFont < 12; iBaseFont++)
100     if (face == CFX_ByteStringC(Base14Substs[iBaseFont].m_pName)) {
101       face = Base14Substs[iBaseFont].m_pSubstName;
102       iExact = 1;
103       break;
104     }
105   if (iBaseFont < 12) {
106     return GetFont(face);
107   }
108   FX_BOOL bCJK = TRUE;
109   switch (charset) {
110     case FXFONT_SHIFTJIS_CHARSET: {
111       int32_t index = GetJapanesePreference(cstr_face, weight, pitch_family);
112       if (index < 0) {
113         break;
114       }
115       for (int32_t i = 0; i < LINUX_GPNAMESIZE; i++) {
116         auto it = m_FontList.find(LinuxGpFontList[index].NameArr[i]);
117         if (it != m_FontList.end()) {
118           return it->second;
119         }
120       }
121     } break;
122     case FXFONT_GB2312_CHARSET: {
123       for (int32_t i = 0; i < FX_ArraySize(g_LinuxGbFontList); ++i) {
124         auto it = m_FontList.find(g_LinuxGbFontList[i]);
125         if (it != m_FontList.end()) {
126           return it->second;
127         }
128       }
129     } break;
130     case FXFONT_CHINESEBIG5_CHARSET: {
131       for (int32_t i = 0; i < FX_ArraySize(g_LinuxB5FontList); ++i) {
132         auto it = m_FontList.find(g_LinuxB5FontList[i]);
133         if (it != m_FontList.end()) {
134           return it->second;
135         }
136       }
137     } break;
138     case FXFONT_HANGEUL_CHARSET: {
139       for (int32_t i = 0; i < FX_ArraySize(g_LinuxHGFontList); ++i) {
140         auto it = m_FontList.find(g_LinuxHGFontList[i]);
141         if (it != m_FontList.end()) {
142           return it->second;
143         }
144       }
145     } break;
146     default:
147       bCJK = FALSE;
148       break;
149   }
150   if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) {
151     return GetFont("Courier New");
152   }
153   return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK);
154 }
155 static FX_DWORD _LinuxGetCharset(int charset) {
156   switch (charset) {
157     case FXFONT_SHIFTJIS_CHARSET:
158       return CHARSET_FLAG_SHIFTJIS;
159     case FXFONT_GB2312_CHARSET:
160       return CHARSET_FLAG_GB;
161     case FXFONT_CHINESEBIG5_CHARSET:
162       return CHARSET_FLAG_BIG5;
163     case FXFONT_HANGEUL_CHARSET:
164       return CHARSET_FLAG_KOREAN;
165     case FXFONT_SYMBOL_CHARSET:
166       return CHARSET_FLAG_SYMBOL;
167     case FXFONT_ANSI_CHARSET:
168       return CHARSET_FLAG_ANSI;
169     default:
170       break;
171   }
172   return 0;
173 }
174 static int32_t _LinuxGetSimilarValue(int weight,
175                                      FX_BOOL bItalic,
176                                      int pitch_family,
177                                      FX_DWORD style) {
178   int32_t iSimilarValue = 0;
179   if ((style & FXFONT_BOLD) == (weight > 400)) {
180     iSimilarValue += 16;
181   }
182   if ((style & FXFONT_ITALIC) == bItalic) {
183     iSimilarValue += 16;
184   }
185   if ((style & FXFONT_SERIF) == (pitch_family & FXFONT_FF_ROMAN)) {
186     iSimilarValue += 16;
187   }
188   if ((style & FXFONT_SCRIPT) == (pitch_family & FXFONT_FF_SCRIPT)) {
189     iSimilarValue += 8;
190   }
191   if ((style & FXFONT_FIXED_PITCH) == (pitch_family & FXFONT_FF_FIXEDPITCH)) {
192     iSimilarValue += 8;
193   }
194   return iSimilarValue;
195 }
196 void* CFX_LinuxFontInfo::FindFont(int weight,
197                                   FX_BOOL bItalic,
198                                   int charset,
199                                   int pitch_family,
200                                   const FX_CHAR* family,
201                                   FX_BOOL bMatchName) {
202   CFX_FontFaceInfo* pFind = NULL;
203   FX_DWORD charset_flag = _LinuxGetCharset(charset);
204   int32_t iBestSimilar = 0;
205   for (const auto& it : m_FontList) {
206     const CFX_ByteString& bsName = it.first;
207     CFX_FontFaceInfo* pFont = it.second;
208     if (!(pFont->m_Charsets & charset_flag) &&
209         charset != FXFONT_DEFAULT_CHARSET) {
210       continue;
211     }
212     int32_t iSimilarValue = 0;
213     int32_t index = bsName.Find(family);
214     if (bMatchName && index < 0) {
215       continue;
216     }
217     if (!bMatchName && index > 0) {
218       iSimilarValue += 64;
219     }
220     iSimilarValue =
221         _LinuxGetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles);
222     if (iSimilarValue > iBestSimilar) {
223       iBestSimilar = iSimilarValue;
224       pFind = pFont;
225     }
226   }
227   return pFind;
228 }
229 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUserPaths) {
230   CFX_LinuxFontInfo* pInfo = new CFX_LinuxFontInfo;
231   if (!pInfo->ParseFontCfg(pUserPaths)) {
232     pInfo->AddPath("/usr/share/fonts");
233     pInfo->AddPath("/usr/share/X11/fonts/Type1");
234     pInfo->AddPath("/usr/share/X11/fonts/TTF");
235     pInfo->AddPath("/usr/local/share/fonts");
236   }
237   return pInfo;
238 }
239 FX_BOOL CFX_LinuxFontInfo::ParseFontCfg(const char** pUserPaths) {
240   if (!pUserPaths) {
241     return FALSE;
242   }
243   for (const char** pPath = pUserPaths; *pPath; ++pPath) {
244     AddPath(*pPath);
245   }
246   return TRUE;
247 }
248 void CFX_GEModule::InitPlatform() {
249   m_pFontMgr->SetSystemFontInfo(
250       IFX_SystemFontInfo::CreateDefault(m_pUserFontPaths));
251 }
252 void CFX_GEModule::DestroyPlatform() {}
253 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_