1 // Copyright 2016 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 "core/fxge/android/cfpf_skiafontmgr.h" 8 9 #define FPF_SKIAMATCHWEIGHT_NAME1 62 10 #define FPF_SKIAMATCHWEIGHT_NAME2 60 11 #define FPF_SKIAMATCHWEIGHT_1 16 12 #define FPF_SKIAMATCHWEIGHT_2 8 13 14 #include <algorithm> 15 16 #include "core/fxcrt/fx_codepage.h" 17 #include "core/fxcrt/fx_extension.h" 18 #include "core/fxcrt/fx_memory.h" 19 #include "core/fxcrt/fx_system.h" 20 #include "core/fxge/android/cfpf_skiafont.h" 21 #include "core/fxge/android/cfpf_skiafontdescriptor.h" 22 #include "core/fxge/android/cfpf_skiapathfont.h" 23 #include "core/fxge/fx_freetype.h" 24 25 #ifdef __cplusplus 26 extern "C" { 27 #endif 28 static unsigned long FPF_SkiaStream_Read(FXFT_Stream stream, 29 unsigned long offset, 30 unsigned char* buffer, 31 unsigned long count) { 32 if (count == 0) 33 return 0; 34 35 IFX_SeekableReadStream* pFileRead = 36 static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer); 37 if (!pFileRead) 38 return 0; 39 40 if (!pFileRead->ReadBlock(buffer, (FX_FILESIZE)offset, 41 static_cast<size_t>(count))) 42 return 0; 43 44 return count; 45 } 46 47 static void FPF_SkiaStream_Close(FXFT_Stream stream) {} 48 #ifdef __cplusplus 49 }; 50 #endif 51 52 namespace { 53 54 struct FPF_SKIAFONTMAP { 55 uint32_t dwFamily; 56 uint32_t dwSubSt; 57 }; 58 59 const FPF_SKIAFONTMAP g_SkiaFontmap[] = { 60 {0x58c5083, 0xc8d2e345}, {0x5dfade2, 0xe1633081}, 61 {0x684317d, 0xe1633081}, {0x14ee2d13, 0xc8d2e345}, 62 {0x3918fe2d, 0xbbeeec72}, {0x3b98b31c, 0xe1633081}, 63 {0x3d49f40e, 0xe1633081}, {0x432c41c5, 0xe1633081}, 64 {0x491b6ad0, 0xe1633081}, {0x5612cab1, 0x59b9f8f1}, 65 {0x779ce19d, 0xc8d2e345}, {0x7cc9510b, 0x59b9f8f1}, 66 {0x83746053, 0xbbeeec72}, {0xaaa60c03, 0xbbeeec72}, 67 {0xbf85ff26, 0xe1633081}, {0xc04fe601, 0xbbeeec72}, 68 {0xca3812d5, 0x59b9f8f1}, {0xca383e15, 0x59b9f8f1}, 69 {0xcad5eaf6, 0x59b9f8f1}, {0xcb7a04c8, 0xc8d2e345}, 70 {0xfb4ce0de, 0xe1633081}, 71 }; 72 73 const FPF_SKIAFONTMAP g_SkiaSansFontMap[] = { 74 {0x58c5083, 0xd5b8d10f}, {0x14ee2d13, 0xd5b8d10f}, 75 {0x779ce19d, 0xd5b8d10f}, {0xcb7a04c8, 0xd5b8d10f}, 76 {0xfb4ce0de, 0xd5b8d10f}, 77 }; 78 79 uint32_t FPF_SkiaGetSubstFont(uint32_t dwHash, 80 const FPF_SKIAFONTMAP* skFontMap, 81 size_t length) { 82 const FPF_SKIAFONTMAP* pEnd = skFontMap + length; 83 const FPF_SKIAFONTMAP* pFontMap = std::lower_bound( 84 skFontMap, pEnd, dwHash, [](const FPF_SKIAFONTMAP& item, uint32_t hash) { 85 return item.dwFamily < hash; 86 }); 87 if (pFontMap < pEnd && pFontMap->dwFamily == dwHash) 88 return pFontMap->dwSubSt; 89 return 0; 90 } 91 92 uint32_t FPF_GetHashCode_StringA(const char* pStr, int32_t iLength) { 93 if (!pStr) 94 return 0; 95 if (iLength < 0) 96 iLength = strlen(pStr); 97 const char* pStrEnd = pStr + iLength; 98 uint32_t uHashCode = 0; 99 while (pStr < pStrEnd) 100 uHashCode = 31 * uHashCode + FXSYS_tolower(*pStr++); 101 return uHashCode; 102 } 103 104 enum FPF_SKIACHARSET { 105 FPF_SKIACHARSET_Ansi = 1 << 0, 106 FPF_SKIACHARSET_Default = 1 << 1, 107 FPF_SKIACHARSET_Symbol = 1 << 2, 108 FPF_SKIACHARSET_ShiftJIS = 1 << 3, 109 FPF_SKIACHARSET_Korean = 1 << 4, 110 FPF_SKIACHARSET_Johab = 1 << 5, 111 FPF_SKIACHARSET_GB2312 = 1 << 6, 112 FPF_SKIACHARSET_BIG5 = 1 << 7, 113 FPF_SKIACHARSET_Greek = 1 << 8, 114 FPF_SKIACHARSET_Turkish = 1 << 9, 115 FPF_SKIACHARSET_Vietnamese = 1 << 10, 116 FPF_SKIACHARSET_Hebrew = 1 << 11, 117 FPF_SKIACHARSET_Arabic = 1 << 12, 118 FPF_SKIACHARSET_Baltic = 1 << 13, 119 FPF_SKIACHARSET_Cyrillic = 1 << 14, 120 FPF_SKIACHARSET_Thai = 1 << 15, 121 FPF_SKIACHARSET_EeasternEuropean = 1 << 16, 122 FPF_SKIACHARSET_PC = 1 << 17, 123 FPF_SKIACHARSET_OEM = 1 << 18, 124 }; 125 126 uint32_t FPF_SkiaGetCharset(uint8_t uCharset) { 127 switch (uCharset) { 128 case FX_CHARSET_ANSI: 129 return FPF_SKIACHARSET_Ansi; 130 case FX_CHARSET_Default: 131 return FPF_SKIACHARSET_Default; 132 case FX_CHARSET_Symbol: 133 return FPF_SKIACHARSET_Symbol; 134 case FX_CHARSET_ShiftJIS: 135 return FPF_SKIACHARSET_ShiftJIS; 136 case FX_CHARSET_Hangul: 137 return FPF_SKIACHARSET_Korean; 138 case FX_CHARSET_ChineseSimplified: 139 return FPF_SKIACHARSET_GB2312; 140 case FX_CHARSET_ChineseTraditional: 141 return FPF_SKIACHARSET_BIG5; 142 case FX_CHARSET_MSWin_Greek: 143 return FPF_SKIACHARSET_Greek; 144 case FX_CHARSET_MSWin_Turkish: 145 return FPF_SKIACHARSET_Turkish; 146 case FX_CHARSET_MSWin_Hebrew: 147 return FPF_SKIACHARSET_Hebrew; 148 case FX_CHARSET_MSWin_Arabic: 149 return FPF_SKIACHARSET_Arabic; 150 case FX_CHARSET_MSWin_Baltic: 151 return FPF_SKIACHARSET_Baltic; 152 case FX_CHARSET_MSWin_Cyrillic: 153 return FPF_SKIACHARSET_Cyrillic; 154 case FX_CHARSET_Thai: 155 return FPF_SKIACHARSET_Thai; 156 case FX_CHARSET_MSWin_EasternEuropean: 157 return FPF_SKIACHARSET_EeasternEuropean; 158 } 159 return FPF_SKIACHARSET_Default; 160 } 161 162 uint32_t FPF_SKIANormalizeFontName(const ByteStringView& bsfamily) { 163 uint32_t dwHash = 0; 164 int32_t iLength = bsfamily.GetLength(); 165 const char* pBuffer = bsfamily.unterminated_c_str(); 166 for (int32_t i = 0; i < iLength; i++) { 167 char ch = pBuffer[i]; 168 if (ch == ' ' || ch == '-' || ch == ',') 169 continue; 170 dwHash = 31 * dwHash + FXSYS_tolower(ch); 171 } 172 return dwHash; 173 } 174 175 uint32_t FPF_SKIAGetFamilyHash(const ByteStringView& bsFamily, 176 uint32_t dwStyle, 177 uint8_t uCharset) { 178 ByteString bsFont(bsFamily); 179 if (FontStyleIsBold(dwStyle)) 180 bsFont += "Bold"; 181 if (FontStyleIsItalic(dwStyle)) 182 bsFont += "Italic"; 183 if (FontStyleIsSerif(dwStyle)) 184 bsFont += "Serif"; 185 bsFont += uCharset; 186 return FPF_GetHashCode_StringA(bsFont.c_str(), bsFont.GetLength()); 187 } 188 189 bool FPF_SkiaIsCJK(uint8_t uCharset) { 190 return (uCharset == FX_CHARSET_ChineseSimplified) || 191 (uCharset == FX_CHARSET_ChineseTraditional) || 192 (uCharset == FX_CHARSET_Hangul) || (uCharset == FX_CHARSET_ShiftJIS); 193 } 194 195 bool FPF_SkiaMaybeSymbol(const ByteStringView& bsFacename) { 196 ByteString bsName(bsFacename); 197 bsName.MakeLower(); 198 return bsName.Contains("symbol"); 199 } 200 201 bool FPF_SkiaMaybeArabic(const ByteStringView& bsFacename) { 202 ByteString bsName(bsFacename); 203 bsName.MakeLower(); 204 return bsName.Contains("arabic"); 205 } 206 207 const uint32_t g_FPFSkiaFontCharsets[] = { 208 FPF_SKIACHARSET_Ansi, 209 FPF_SKIACHARSET_EeasternEuropean, 210 FPF_SKIACHARSET_Cyrillic, 211 FPF_SKIACHARSET_Greek, 212 FPF_SKIACHARSET_Turkish, 213 FPF_SKIACHARSET_Hebrew, 214 FPF_SKIACHARSET_Arabic, 215 FPF_SKIACHARSET_Baltic, 216 0, 217 0, 218 0, 219 0, 220 0, 221 0, 222 0, 223 0, 224 FPF_SKIACHARSET_Thai, 225 FPF_SKIACHARSET_ShiftJIS, 226 FPF_SKIACHARSET_GB2312, 227 FPF_SKIACHARSET_Korean, 228 FPF_SKIACHARSET_BIG5, 229 FPF_SKIACHARSET_Johab, 230 0, 231 0, 232 0, 233 0, 234 0, 235 0, 236 0, 237 0, 238 FPF_SKIACHARSET_OEM, 239 FPF_SKIACHARSET_Symbol, 240 }; 241 242 uint32_t FPF_SkiaGetFaceCharset(TT_OS2* pOS2) { 243 uint32_t dwCharset = 0; 244 if (pOS2) { 245 for (int32_t i = 0; i < 32; i++) { 246 if (pOS2->ulCodePageRange1 & (1 << i)) 247 dwCharset |= g_FPFSkiaFontCharsets[i]; 248 } 249 } 250 dwCharset |= FPF_SKIACHARSET_Default; 251 return dwCharset; 252 } 253 254 } // namespace 255 256 CFPF_SkiaFontMgr::CFPF_SkiaFontMgr() : m_bLoaded(false), m_FTLibrary(nullptr) {} 257 258 CFPF_SkiaFontMgr::~CFPF_SkiaFontMgr() { 259 for (const auto& pair : m_FamilyFonts) { 260 if (pair.second) 261 pair.second->Release(); 262 } 263 m_FamilyFonts.clear(); 264 for (auto it = m_FontFaces.begin(); it != m_FontFaces.end(); ++it) 265 delete *it; 266 m_FontFaces.clear(); 267 if (m_FTLibrary) 268 FXFT_Done_FreeType(m_FTLibrary); 269 } 270 271 bool CFPF_SkiaFontMgr::InitFTLibrary() { 272 if (!m_FTLibrary) 273 FXFT_Init_FreeType(&m_FTLibrary); 274 return !!m_FTLibrary; 275 } 276 277 void CFPF_SkiaFontMgr::LoadSystemFonts() { 278 if (m_bLoaded) 279 return; 280 ScanPath("/system/fonts"); 281 m_bLoaded = true; 282 } 283 284 CFPF_SkiaFont* CFPF_SkiaFontMgr::CreateFont(const ByteStringView& bsFamilyname, 285 uint8_t uCharset, 286 uint32_t dwStyle, 287 uint32_t dwMatch) { 288 uint32_t dwHash = FPF_SKIAGetFamilyHash(bsFamilyname, dwStyle, uCharset); 289 auto it = m_FamilyFonts.find(dwHash); 290 if (it != m_FamilyFonts.end() && it->second) 291 return it->second->Retain(); 292 293 uint32_t dwFaceName = FPF_SKIANormalizeFontName(bsFamilyname); 294 uint32_t dwSubst = FPF_SkiaGetSubstFont(dwFaceName, g_SkiaFontmap, 295 FX_ArraySize(g_SkiaFontmap)); 296 uint32_t dwSubstSans = FPF_SkiaGetSubstFont(dwFaceName, g_SkiaSansFontMap, 297 FX_ArraySize(g_SkiaSansFontMap)); 298 bool bMaybeSymbol = FPF_SkiaMaybeSymbol(bsFamilyname); 299 if (uCharset != FX_CHARSET_MSWin_Arabic && 300 FPF_SkiaMaybeArabic(bsFamilyname)) { 301 uCharset = FX_CHARSET_MSWin_Arabic; 302 } else if (uCharset == FX_CHARSET_ANSI && 303 (dwMatch & FPF_MATCHFONT_REPLACEANSI)) { 304 uCharset = FX_CHARSET_Default; 305 } 306 int32_t nExpectVal = FPF_SKIAMATCHWEIGHT_NAME1 + FPF_SKIAMATCHWEIGHT_1 * 3 + 307 FPF_SKIAMATCHWEIGHT_2 * 2; 308 CFPF_SkiaFontDescriptor* pBestFontDes = nullptr; 309 int32_t nMax = -1; 310 int32_t nGlyphNum = 0; 311 for (auto it = m_FontFaces.rbegin(); it != m_FontFaces.rend(); ++it) { 312 CFPF_SkiaPathFont* pFontDes = static_cast<CFPF_SkiaPathFont*>(*it); 313 if (!(pFontDes->m_dwCharsets & FPF_SkiaGetCharset(uCharset))) 314 continue; 315 int32_t nFind = 0; 316 uint32_t dwSysFontName = FPF_SKIANormalizeFontName(pFontDes->m_pFamily); 317 if (dwFaceName == dwSysFontName) 318 nFind += FPF_SKIAMATCHWEIGHT_NAME1; 319 bool bMatchedName = (nFind == FPF_SKIAMATCHWEIGHT_NAME1); 320 if (FontStyleIsBold(dwStyle) == FontStyleIsBold(pFontDes->m_dwStyle)) 321 nFind += FPF_SKIAMATCHWEIGHT_1; 322 if (FontStyleIsItalic(dwStyle) == FontStyleIsItalic(pFontDes->m_dwStyle)) 323 nFind += FPF_SKIAMATCHWEIGHT_1; 324 if (FontStyleIsFixedPitch(dwStyle) == 325 FontStyleIsFixedPitch(pFontDes->m_dwStyle)) { 326 nFind += FPF_SKIAMATCHWEIGHT_2; 327 } 328 if (FontStyleIsSerif(dwStyle) == FontStyleIsSerif(pFontDes->m_dwStyle)) 329 nFind += FPF_SKIAMATCHWEIGHT_1; 330 if (FontStyleIsScript(dwStyle) == FontStyleIsScript(pFontDes->m_dwStyle)) 331 nFind += FPF_SKIAMATCHWEIGHT_2; 332 if (dwSubst == dwSysFontName || dwSubstSans == dwSysFontName) { 333 nFind += FPF_SKIAMATCHWEIGHT_NAME2; 334 bMatchedName = true; 335 } 336 if (uCharset == FX_CHARSET_Default || bMaybeSymbol) { 337 if (nFind > nMax && bMatchedName) { 338 nMax = nFind; 339 pBestFontDes = *it; 340 } 341 } else if (FPF_SkiaIsCJK(uCharset)) { 342 if (bMatchedName || pFontDes->m_iGlyphNum > nGlyphNum) { 343 pBestFontDes = *it; 344 nGlyphNum = pFontDes->m_iGlyphNum; 345 } 346 } else if (nFind > nMax) { 347 nMax = nFind; 348 pBestFontDes = *it; 349 } 350 if (nExpectVal <= nFind) { 351 pBestFontDes = *it; 352 break; 353 } 354 } 355 if (pBestFontDes) { 356 CFPF_SkiaFont* pFont = new CFPF_SkiaFont; 357 if (pFont->InitFont(this, pBestFontDes, bsFamilyname, dwStyle, uCharset)) { 358 m_FamilyFonts[dwHash] = pFont; 359 return pFont->Retain(); 360 } 361 pFont->Release(); 362 } 363 return nullptr; 364 } 365 366 FXFT_Face CFPF_SkiaFontMgr::GetFontFace( 367 const RetainPtr<IFX_SeekableReadStream>& pFileRead, 368 int32_t iFaceIndex) { 369 if (!pFileRead) 370 return nullptr; 371 if (pFileRead->GetSize() == 0) 372 return nullptr; 373 if (iFaceIndex < 0) 374 return nullptr; 375 FXFT_StreamRec streamRec; 376 memset(&streamRec, 0, sizeof(FXFT_StreamRec)); 377 streamRec.size = pFileRead->GetSize(); 378 streamRec.descriptor.pointer = static_cast<void*>(pFileRead.Get()); 379 streamRec.read = FPF_SkiaStream_Read; 380 streamRec.close = FPF_SkiaStream_Close; 381 FXFT_Open_Args args; 382 args.flags = FT_OPEN_STREAM; 383 args.stream = &streamRec; 384 FXFT_Face face; 385 if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face)) 386 return nullptr; 387 FXFT_Set_Pixel_Sizes(face, 0, 64); 388 return face; 389 } 390 391 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(const ByteStringView& bsFile, 392 int32_t iFaceIndex) { 393 if (bsFile.IsEmpty()) 394 return nullptr; 395 if (iFaceIndex < 0) 396 return nullptr; 397 FXFT_Open_Args args; 398 args.flags = FT_OPEN_PATHNAME; 399 args.pathname = const_cast<FT_String*>(bsFile.unterminated_c_str()); 400 FXFT_Face face; 401 if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face)) 402 return nullptr; 403 FXFT_Set_Pixel_Sizes(face, 0, 64); 404 return face; 405 } 406 407 FXFT_Face CFPF_SkiaFontMgr::GetFontFace(const uint8_t* pBuffer, 408 size_t szBuffer, 409 int32_t iFaceIndex) { 410 if (!pBuffer || szBuffer < 1) 411 return nullptr; 412 if (iFaceIndex < 0) 413 return nullptr; 414 FXFT_Open_Args args; 415 args.flags = FT_OPEN_MEMORY; 416 args.memory_base = pBuffer; 417 args.memory_size = szBuffer; 418 FXFT_Face face; 419 if (FXFT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face)) 420 return nullptr; 421 FXFT_Set_Pixel_Sizes(face, 0, 64); 422 return face; 423 } 424 425 void CFPF_SkiaFontMgr::ScanPath(const ByteString& path) { 426 DIR* handle = FX_OpenFolder(path.c_str()); 427 if (!handle) 428 return; 429 ByteString filename; 430 bool bFolder = false; 431 while (FX_GetNextFile(handle, &filename, &bFolder)) { 432 if (bFolder) { 433 if (filename == "." || filename == "..") 434 continue; 435 } else { 436 ByteString ext = filename.Right(4); 437 ext.MakeLower(); 438 if (ext != ".ttf" && ext != ".ttc" && ext != ".otf") 439 continue; 440 } 441 ByteString fullpath(path); 442 fullpath += "/"; 443 fullpath += filename; 444 if (bFolder) 445 ScanPath(fullpath); 446 else 447 ScanFile(fullpath); 448 } 449 FX_CloseFolder(handle); 450 } 451 452 void CFPF_SkiaFontMgr::ScanFile(const ByteString& file) { 453 FXFT_Face face = GetFontFace(file.AsStringView()); 454 if (!face) 455 return; 456 CFPF_SkiaPathFont* pFontDesc = new CFPF_SkiaPathFont; 457 pFontDesc->SetPath(file.c_str()); 458 ReportFace(face, pFontDesc); 459 m_FontFaces.push_back(pFontDesc); 460 FXFT_Done_Face(face); 461 } 462 463 void CFPF_SkiaFontMgr::ReportFace(FXFT_Face face, 464 CFPF_SkiaFontDescriptor* pFontDesc) { 465 if (!face || !pFontDesc) 466 return; 467 pFontDesc->SetFamily(FXFT_Get_Face_Family_Name(face)); 468 if (FXFT_Is_Face_Bold(face)) 469 pFontDesc->m_dwStyle |= FXFONT_BOLD; 470 if (FXFT_Is_Face_Italic(face)) 471 pFontDesc->m_dwStyle |= FXFONT_ITALIC; 472 if (FT_IS_FIXED_WIDTH(face)) 473 pFontDesc->m_dwStyle |= FXFONT_FIXED_PITCH; 474 TT_OS2* pOS2 = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2); 475 if (pOS2) { 476 if (pOS2->ulCodePageRange1 & (1 << 31)) 477 pFontDesc->m_dwStyle |= FXFONT_SYMBOLIC; 478 if (pOS2->panose[0] == 2) { 479 uint8_t uSerif = pOS2->panose[1]; 480 if ((uSerif > 1 && uSerif < 10) || uSerif > 13) 481 pFontDesc->m_dwStyle |= FXFONT_SERIF; 482 } 483 } 484 if (pOS2 && (pOS2->ulCodePageRange1 & (1 << 31))) 485 pFontDesc->m_dwStyle |= FXFONT_SYMBOLIC; 486 pFontDesc->m_dwCharsets = FPF_SkiaGetFaceCharset(pOS2); 487 pFontDesc->m_iFaceIndex = face->face_index; 488 pFontDesc->m_iGlyphNum = face->num_glyphs; 489 } 490