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