Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cfpf_skiafontmgr.cpp
Go to the documentation of this file.
1// Copyright 2016 The PDFium Authors
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 "core/fxge/android/cfpf_skiafontmgr.h"
8
9#include <algorithm>
10#include <iterator>
11#include <utility>
12
13#include "core/fxcrt/fx_codepage.h"
14#include "core/fxcrt/fx_extension.h"
15#include "core/fxcrt/fx_folder.h"
16#include "core/fxcrt/fx_system.h"
17#include "core/fxge/android/cfpf_skiafont.h"
18#include "core/fxge/android/cfpf_skiapathfont.h"
19#include "core/fxge/freetype/fx_freetype.h"
20#include "core/fxge/fx_font.h"
21#include "third_party/base/containers/adapters.h"
22
23namespace {
24
25constexpr int FPF_SKIAMATCHWEIGHT_NAME1 = 62;
26constexpr int FPF_SKIAMATCHWEIGHT_NAME2 = 60;
27constexpr int FPF_SKIAMATCHWEIGHT_1 = 16;
28constexpr int FPF_SKIAMATCHWEIGHT_2 = 8;
29
30struct FPF_SKIAFONTMAP {
31 uint32_t dwFamily;
32 uint32_t dwSubSt;
33};
34
35const FPF_SKIAFONTMAP kSkiaFontmap[] = {
36 {0x58c5083, 0xc8d2e345}, {0x5dfade2, 0xe1633081},
37 {0x684317d, 0xe1633081}, {0x14ee2d13, 0xc8d2e345},
38 {0x3918fe2d, 0xbbeeec72}, {0x3b98b31c, 0xe1633081},
39 {0x3d49f40e, 0xe1633081}, {0x432c41c5, 0xe1633081},
40 {0x491b6ad0, 0xe1633081}, {0x5612cab1, 0x59b9f8f1},
41 {0x779ce19d, 0xc8d2e345}, {0x7cc9510b, 0x59b9f8f1},
42 {0x83746053, 0xbbeeec72}, {0xaaa60c03, 0xbbeeec72},
43 {0xbf85ff26, 0xe1633081}, {0xc04fe601, 0xbbeeec72},
44 {0xca3812d5, 0x59b9f8f1}, {0xca383e15, 0x59b9f8f1},
45 {0xcad5eaf6, 0x59b9f8f1}, {0xcb7a04c8, 0xc8d2e345},
46 {0xfb4ce0de, 0xe1633081},
47};
48
49const FPF_SKIAFONTMAP kSkiaSansFontMap[] = {
50 {0x58c5083, 0xd5b8d10f}, {0x14ee2d13, 0xd5b8d10f},
51 {0x779ce19d, 0xd5b8d10f}, {0xcb7a04c8, 0xd5b8d10f},
52 {0xfb4ce0de, 0xd5b8d10f},
53};
54
55uint32_t FPF_SkiaGetSubstFont(uint32_t dwHash,
56 const FPF_SKIAFONTMAP* skFontMap,
57 size_t length) {
58 const FPF_SKIAFONTMAP* pEnd = skFontMap + length;
59 const FPF_SKIAFONTMAP* pFontMap = std::lower_bound(
60 skFontMap, pEnd, dwHash, [](const FPF_SKIAFONTMAP& item, uint32_t hash) {
61 return item.dwFamily < hash;
62 });
63 if (pFontMap < pEnd && pFontMap->dwFamily == dwHash)
64 return pFontMap->dwSubSt;
65 return 0;
66}
67
68enum FPF_SKIACHARSET {
69 FPF_SKIACHARSET_Ansi = 1 << 0,
70 FPF_SKIACHARSET_Default = 1 << 1,
71 FPF_SKIACHARSET_Symbol = 1 << 2,
72 FPF_SKIACHARSET_ShiftJIS = 1 << 3,
73 FPF_SKIACHARSET_Korean = 1 << 4,
74 FPF_SKIACHARSET_Johab = 1 << 5,
75 FPF_SKIACHARSET_GB2312 = 1 << 6,
76 FPF_SKIACHARSET_BIG5 = 1 << 7,
77 FPF_SKIACHARSET_Greek = 1 << 8,
78 FPF_SKIACHARSET_Turkish = 1 << 9,
79 FPF_SKIACHARSET_Vietnamese = 1 << 10,
80 FPF_SKIACHARSET_Hebrew = 1 << 11,
81 FPF_SKIACHARSET_Arabic = 1 << 12,
82 FPF_SKIACHARSET_Baltic = 1 << 13,
83 FPF_SKIACHARSET_Cyrillic = 1 << 14,
84 FPF_SKIACHARSET_Thai = 1 << 15,
85 FPF_SKIACHARSET_EeasternEuropean = 1 << 16,
86 FPF_SKIACHARSET_PC = 1 << 17,
87 FPF_SKIACHARSET_OEM = 1 << 18,
88};
89
90uint32_t FPF_SkiaGetCharset(FX_Charset uCharset) {
91 switch (uCharset) {
93 return FPF_SKIACHARSET_Ansi;
95 return FPF_SKIACHARSET_Default;
97 return FPF_SKIACHARSET_Symbol;
99 return FPF_SKIACHARSET_ShiftJIS;
101 return FPF_SKIACHARSET_Korean;
103 return FPF_SKIACHARSET_GB2312;
105 return FPF_SKIACHARSET_BIG5;
107 return FPF_SKIACHARSET_Greek;
109 return FPF_SKIACHARSET_Turkish;
111 return FPF_SKIACHARSET_Hebrew;
113 return FPF_SKIACHARSET_Arabic;
115 return FPF_SKIACHARSET_Baltic;
117 return FPF_SKIACHARSET_Cyrillic;
119 return FPF_SKIACHARSET_Thai;
121 return FPF_SKIACHARSET_EeasternEuropean;
122 default:
123 return FPF_SKIACHARSET_Default;
124 }
125}
126
127uint32_t FPF_SKIANormalizeFontName(ByteStringView bsFamily) {
128 uint32_t uHashCode = 0;
129 for (unsigned char ch : bsFamily) {
130 if (ch == ' ' || ch == '-' || ch == ',')
131 continue;
132 uHashCode = 31 * uHashCode + tolower(ch);
133 }
134 return uHashCode;
135}
136
137uint32_t FPF_SKIAGetFamilyHash(ByteStringView bsFamily,
138 uint32_t dwStyle,
139 FX_Charset uCharset) {
140 ByteString bsFont(bsFamily);
141 if (FontStyleIsForceBold(dwStyle))
142 bsFont += "Bold";
143 if (FontStyleIsItalic(dwStyle))
144 bsFont += "Italic";
145 if (FontStyleIsSerif(dwStyle))
146 bsFont += "Serif";
147 bsFont += static_cast<uint8_t>(uCharset);
148 return FX_HashCode_GetA(bsFont.AsStringView());
149}
150
151bool FPF_SkiaIsCJK(FX_Charset uCharset) {
152 return FX_CharSetIsCJK(uCharset);
153}
154
155bool FPF_SkiaMaybeSymbol(ByteStringView bsFacename) {
156 ByteString bsName(bsFacename);
157 bsName.MakeLower();
158 return bsName.Contains("symbol");
159}
160
161bool FPF_SkiaMaybeArabic(ByteStringView bsFacename) {
162 ByteString bsName(bsFacename);
163 bsName.MakeLower();
164 return bsName.Contains("arabic");
165}
166
167const uint32_t kFPFSkiaFontCharsets[] = {
168 FPF_SKIACHARSET_Ansi,
169 FPF_SKIACHARSET_EeasternEuropean,
170 FPF_SKIACHARSET_Cyrillic,
171 FPF_SKIACHARSET_Greek,
172 FPF_SKIACHARSET_Turkish,
173 FPF_SKIACHARSET_Hebrew,
174 FPF_SKIACHARSET_Arabic,
175 FPF_SKIACHARSET_Baltic,
176 0,
177 0,
178 0,
179 0,
180 0,
181 0,
182 0,
183 0,
184 FPF_SKIACHARSET_Thai,
185 FPF_SKIACHARSET_ShiftJIS,
186 FPF_SKIACHARSET_GB2312,
187 FPF_SKIACHARSET_Korean,
188 FPF_SKIACHARSET_BIG5,
189 FPF_SKIACHARSET_Johab,
190 0,
191 0,
192 0,
193 0,
194 0,
195 0,
196 0,
197 0,
198 FPF_SKIACHARSET_OEM,
199 FPF_SKIACHARSET_Symbol,
200};
201
202uint32_t FPF_SkiaGetFaceCharset(uint32_t code_range) {
203 uint32_t charset = 0;
204 for (int32_t i = 0; i < 32; i++) {
205 if (code_range & (1 << i)) {
206 charset |= kFPFSkiaFontCharsets[i];
207 }
208 }
209 return charset;
210}
211
212} // namespace
213
215
217 m_FamilyFonts.clear();
218 m_FontFaces.clear();
219}
220
222 if (m_FTLibrary)
223 return true;
224
225 FXFT_LibraryRec* pLibrary = nullptr;
226 FT_Init_FreeType(&pLibrary);
227 if (!pLibrary)
228 return false;
229
230 m_FTLibrary.reset(pLibrary);
231 return true;
232}
233
235 if (m_bLoaded)
236 return;
237 ScanPath("/system/fonts");
238 m_bLoaded = true;
239}
240
241CFPF_SkiaFont* CFPF_SkiaFontMgr::CreateFont(ByteStringView bsFamilyname,
242 FX_Charset uCharset,
243 uint32_t dwStyle) {
244 uint32_t dwHash = FPF_SKIAGetFamilyHash(bsFamilyname, dwStyle, uCharset);
245 auto family_iter = m_FamilyFonts.find(dwHash);
246 if (family_iter != m_FamilyFonts.end())
247 return family_iter->second.get();
248
249 uint32_t dwFaceName = FPF_SKIANormalizeFontName(bsFamilyname);
250 uint32_t dwSubst =
251 FPF_SkiaGetSubstFont(dwFaceName, kSkiaFontmap, std::size(kSkiaFontmap));
252 uint32_t dwSubstSans = FPF_SkiaGetSubstFont(dwFaceName, kSkiaSansFontMap,
253 std::size(kSkiaSansFontMap));
254 bool bMaybeSymbol = FPF_SkiaMaybeSymbol(bsFamilyname);
255 if (uCharset != FX_Charset::kMSWin_Arabic &&
256 FPF_SkiaMaybeArabic(bsFamilyname)) {
257 uCharset = FX_Charset::kMSWin_Arabic;
258 } else if (uCharset == FX_Charset::kANSI) {
259 uCharset = FX_Charset::kDefault;
260 }
261 int32_t nExpectVal = FPF_SKIAMATCHWEIGHT_NAME1 + FPF_SKIAMATCHWEIGHT_1 * 3 +
262 FPF_SKIAMATCHWEIGHT_2 * 2;
263 const CFPF_SkiaPathFont* pBestFont = nullptr;
264 int32_t nMax = -1;
265 int32_t nGlyphNum = 0;
266 for (const std::unique_ptr<CFPF_SkiaPathFont>& font :
267 pdfium::base::Reversed(m_FontFaces)) {
268 if (!(font->charsets() & FPF_SkiaGetCharset(uCharset)))
269 continue;
270 int32_t nFind = 0;
271 uint32_t dwSysFontName = FPF_SKIANormalizeFontName(font->family());
272 if (dwFaceName == dwSysFontName)
273 nFind += FPF_SKIAMATCHWEIGHT_NAME1;
274 bool bMatchedName = (nFind == FPF_SKIAMATCHWEIGHT_NAME1);
275 if (FontStyleIsForceBold(dwStyle) == FontStyleIsForceBold(font->style()))
276 nFind += FPF_SKIAMATCHWEIGHT_1;
277 if (FontStyleIsItalic(dwStyle) == FontStyleIsItalic(font->style()))
278 nFind += FPF_SKIAMATCHWEIGHT_1;
279 if (FontStyleIsFixedPitch(dwStyle) ==
280 FontStyleIsFixedPitch(font->style())) {
281 nFind += FPF_SKIAMATCHWEIGHT_2;
282 }
283 if (FontStyleIsSerif(dwStyle) == FontStyleIsSerif(font->style()))
284 nFind += FPF_SKIAMATCHWEIGHT_1;
285 if (FontStyleIsScript(dwStyle) == FontStyleIsScript(font->style()))
286 nFind += FPF_SKIAMATCHWEIGHT_2;
287 if (dwSubst == dwSysFontName || dwSubstSans == dwSysFontName) {
288 nFind += FPF_SKIAMATCHWEIGHT_NAME2;
289 bMatchedName = true;
290 }
291 if (uCharset == FX_Charset::kDefault || bMaybeSymbol) {
292 if (nFind > nMax && bMatchedName) {
293 nMax = nFind;
294 pBestFont = font.get();
295 }
296 } else if (FPF_SkiaIsCJK(uCharset)) {
297 if (bMatchedName || font->glyph_num() > nGlyphNum) {
298 pBestFont = font.get();
299 nGlyphNum = font->glyph_num();
300 }
301 } else if (nFind > nMax) {
302 nMax = nFind;
303 pBestFont = font.get();
304 }
305 if (nExpectVal <= nFind) {
306 pBestFont = font.get();
307 break;
308 }
309 }
310 if (!pBestFont)
311 return nullptr;
312
313 auto font = std::make_unique<CFPF_SkiaFont>(this, pBestFont, uCharset);
314 if (!font->IsValid())
315 return nullptr;
316
317 CFPF_SkiaFont* ret = font.get();
318 m_FamilyFonts[dwHash] = std::move(font);
319 return ret;
320}
321
322RetainPtr<CFX_Face> CFPF_SkiaFontMgr::GetFontFace(ByteStringView bsFile,
323 int32_t iFaceIndex) {
324 if (bsFile.IsEmpty())
325 return nullptr;
326
327 if (iFaceIndex < 0)
328 return nullptr;
329
330 FT_Open_Args args;
331 args.flags = FT_OPEN_PATHNAME;
332 args.pathname = const_cast<FT_String*>(bsFile.unterminated_c_str());
333 RetainPtr<CFX_Face> face =
334 CFX_Face::Open(m_FTLibrary.get(), &args, iFaceIndex);
335 if (!face)
336 return nullptr;
337
338 FT_Set_Pixel_Sizes(face->GetRec(), 0, 64);
339 return face;
340}
341
342void CFPF_SkiaFontMgr::ScanPath(const ByteString& path) {
343 std::unique_ptr<FX_Folder> handle = FX_Folder::OpenFolder(path);
344 if (!handle)
345 return;
346
347 ByteString filename;
348 bool bFolder = false;
349 while (handle->GetNextFile(&filename, &bFolder)) {
350 if (bFolder) {
351 if (filename == "." || filename == "..")
352 continue;
353 } else {
354 ByteString ext = filename.Last(4);
355 ext.MakeLower();
356 if (ext != ".ttf" && ext != ".ttc" && ext != ".otf")
357 continue;
358 }
359 ByteString fullpath(path);
360 fullpath += "/";
361 fullpath += filename;
362 if (bFolder)
363 ScanPath(fullpath);
364 else
365 ScanFile(fullpath);
366 }
367}
368
369void CFPF_SkiaFontMgr::ScanFile(const ByteString& file) {
370 RetainPtr<CFX_Face> face = GetFontFace(file.AsStringView(), 0);
371 if (!face)
372 return;
373
374 m_FontFaces.push_back(ReportFace(face, file));
375}
376
377std::unique_ptr<CFPF_SkiaPathFont> CFPF_SkiaFontMgr::ReportFace(
378 RetainPtr<CFX_Face> face,
379 const ByteString& file) {
380 uint32_t dwStyle = 0;
381 if (face->IsBold()) {
382 dwStyle |= FXFONT_FORCE_BOLD;
383 }
384 if (face->IsItalic()) {
385 dwStyle |= FXFONT_ITALIC;
386 }
387 if (face->IsFixedWidth()) {
388 dwStyle |= FXFONT_FIXED_PITCH;
389 }
390
391 uint32_t charset = FPF_SKIACHARSET_Default;
392 absl::optional<std::array<uint32_t, 2>> code_page_range =
393 face->GetOs2CodePageRange();
394 if (code_page_range.has_value()) {
395 if (code_page_range.value()[0] & (1 << 31)) {
396 dwStyle |= FXFONT_SYMBOLIC;
397 }
398 charset |= FPF_SkiaGetFaceCharset(code_page_range.value()[0]);
399 }
400
401 absl::optional<std::array<uint8_t, 2>> panose = face->GetOs2Panose();
402 if (panose.has_value() && panose.value()[0] == 2) {
403 uint8_t serif = panose.value()[1];
404 if ((serif > 1 && serif < 10) || serif > 13) {
405 dwStyle |= FXFONT_SERIF;
406 }
407 }
408
409 return std::make_unique<CFPF_SkiaPathFont>(
410 file, face->GetFamilyName(), dwStyle, face->GetRec()->face_index, charset,
411 face->GetGlyphCount());
412}
RetainPtr< CFX_Face > GetFontFace(ByteStringView bsFile, int32_t iFaceIndex)
CFPF_SkiaFont * CreateFont(ByteStringView bsFamilyname, FX_Charset uCharset, uint32_t dwStyle)
ByteString & operator+=(const ByteString &str)
ByteString & operator+=(char ch)
bool operator==(const char *ptr) const
ByteString(const ByteString &other)
ByteString & operator+=(const char *str)
bool operator!=(const char *ptr) const
Definition bytestring.h:130
FX_Charset
Definition fx_codepage.h:70
@ kChineseTraditional
@ kMSWin_EasternEuropean
@ kChineseSimplified
bool FX_CharSetIsCJK(FX_Charset uCharset)
bool FontStyleIsSerif(uint32_t style)
Definition fx_font.h:77
#define FXFONT_SERIF
Definition fx_font.h:29
#define FXFONT_ITALIC
Definition fx_font.h:33
#define FXFONT_SYMBOLIC
Definition fx_font.h:30
bool FontStyleIsItalic(uint32_t style)
Definition fx_font.h:62
#define FXFONT_FORCE_BOLD
Definition fx_font.h:36
bool FontStyleIsForceBold(uint32_t style)
Definition fx_font.h:59
#define FXFONT_FIXED_PITCH
Definition fx_font.h:28