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 <memory>
8 
9 #include "core/fxge/cfx_gemodule.h"
10 #include "core/fxge/ge/cfx_folderfontinfo.h"
11 #include "core/fxge/ifx_systemfontinfo.h"
12 
13 #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
14 namespace {
15 
16 const size_t kLinuxGpNameSize = 6;
17 
18 const FX_CHAR* const g_LinuxGpFontList[][kLinuxGpNameSize] = {
19     {"TakaoPGothic", "VL PGothic", "IPAPGothic", "VL Gothic", "Kochi Gothic",
20      "VL Gothic regular"},
21     {"TakaoGothic", "VL Gothic", "IPAGothic", "Kochi Gothic", nullptr,
22      "VL Gothic regular"},
23     {"TakaoPMincho", "IPAPMincho", "VL Gothic", "Kochi Mincho", nullptr,
24      "VL Gothic regular"},
25     {"TakaoMincho", "IPAMincho", "VL Gothic", "Kochi Mincho", nullptr,
26      "VL Gothic regular"},
27 };
28 
29 const FX_CHAR* const g_LinuxGbFontList[] = {
30     "AR PL UMing CN Light", "WenQuanYi Micro Hei", "AR PL UKai CN",
31 };
32 
33 const FX_CHAR* const g_LinuxB5FontList[] = {
34     "AR PL UMing TW Light", "WenQuanYi Micro Hei", "AR PL UKai TW",
35 };
36 
37 const FX_CHAR* const g_LinuxHGFontList[] = {
38     "UnDotum",
39 };
40 
GetJapanesePreference(const FX_CHAR * facearr,int weight,int pitch_family)41 size_t GetJapanesePreference(const FX_CHAR* facearr,
42                              int weight,
43                              int pitch_family) {
44   CFX_ByteString face = facearr;
45   if (face.Find("Gothic") >= 0 ||
46       face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) {
47     if (face.Find("PGothic") >= 0 ||
48         face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) {
49       return 0;
50     }
51     return 1;
52   }
53   if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) {
54     if (face.Find("PMincho") >= 0 ||
55         face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) {
56       return 2;
57     }
58     return 3;
59   }
60   if (!(pitch_family & FXFONT_FF_ROMAN) && weight > 400)
61     return 0;
62 
63   return 2;
64 }
65 
66 class CFX_LinuxFontInfo : public CFX_FolderFontInfo {
67  public:
CFX_LinuxFontInfo()68   CFX_LinuxFontInfo() {}
~CFX_LinuxFontInfo()69   ~CFX_LinuxFontInfo() override {}
70 
71   void* MapFont(int weight,
72                 bool bItalic,
73                 int charset,
74                 int pitch_family,
75                 const FX_CHAR* family,
76                 int& iExact) override;
77   bool ParseFontCfg(const char** pUserPaths);
78 };
79 
MapFont(int weight,bool bItalic,int charset,int pitch_family,const FX_CHAR * cstr_face,int & iExact)80 void* CFX_LinuxFontInfo::MapFont(int weight,
81                                  bool bItalic,
82                                  int charset,
83                                  int pitch_family,
84                                  const FX_CHAR* cstr_face,
85                                  int& iExact) {
86   void* font = GetSubstFont(cstr_face);
87   if (font) {
88     iExact = 1;
89     return font;
90   }
91   bool bCJK = true;
92   switch (charset) {
93     case FXFONT_SHIFTJIS_CHARSET: {
94       size_t index = GetJapanesePreference(cstr_face, weight, pitch_family);
95       ASSERT(index < FX_ArraySize(g_LinuxGpFontList));
96       for (size_t i = 0; i < kLinuxGpNameSize; i++) {
97         auto it = m_FontList.find(g_LinuxGpFontList[index][i]);
98         if (it != m_FontList.end())
99           return it->second;
100       }
101       break;
102     }
103     case FXFONT_GB2312_CHARSET: {
104       for (size_t i = 0; i < FX_ArraySize(g_LinuxGbFontList); ++i) {
105         auto it = m_FontList.find(g_LinuxGbFontList[i]);
106         if (it != m_FontList.end())
107           return it->second;
108       }
109       break;
110     }
111     case FXFONT_CHINESEBIG5_CHARSET: {
112       for (size_t i = 0; i < FX_ArraySize(g_LinuxB5FontList); ++i) {
113         auto it = m_FontList.find(g_LinuxB5FontList[i]);
114         if (it != m_FontList.end())
115           return it->second;
116       }
117       break;
118     }
119     case FXFONT_HANGUL_CHARSET: {
120       for (size_t i = 0; i < FX_ArraySize(g_LinuxHGFontList); ++i) {
121         auto it = m_FontList.find(g_LinuxHGFontList[i]);
122         if (it != m_FontList.end())
123           return it->second;
124       }
125       break;
126     }
127     default:
128       bCJK = false;
129       break;
130   }
131   return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK);
132 }
133 
ParseFontCfg(const char ** pUserPaths)134 bool CFX_LinuxFontInfo::ParseFontCfg(const char** pUserPaths) {
135   if (!pUserPaths)
136     return false;
137 
138   for (const char** pPath = pUserPaths; *pPath; ++pPath)
139     AddPath(*pPath);
140   return true;
141 }
142 
143 }  // namespace
144 
CreateDefault(const char ** pUserPaths)145 std::unique_ptr<IFX_SystemFontInfo> IFX_SystemFontInfo::CreateDefault(
146     const char** pUserPaths) {
147   CFX_LinuxFontInfo* pInfo = new CFX_LinuxFontInfo;
148   if (!pInfo->ParseFontCfg(pUserPaths)) {
149     pInfo->AddPath("/usr/share/fonts");
150     pInfo->AddPath("/usr/share/X11/fonts/Type1");
151     pInfo->AddPath("/usr/share/X11/fonts/TTF");
152     pInfo->AddPath("/usr/local/share/fonts");
153   }
154   return std::unique_ptr<IFX_SystemFontInfo>(pInfo);
155 }
156 
InitPlatform()157 void CFX_GEModule::InitPlatform() {
158   m_pFontMgr->SetSystemFontInfo(
159       IFX_SystemFontInfo::CreateDefault(m_pUserFontPaths));
160 }
161 
DestroyPlatform()162 void CFX_GEModule::DestroyPlatform() {}
163 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
164