Define global FX_CharsetFlag and use it in font managers. Move the Android Skia font manager's charset bitmask concept into a global FX_CharsetFlag enum class in core/fxcrt/fx_codepage.h. Refactor CFPF_SkiaFontMgr and CFX_FolderFontInfo to use this new global enum instead of their own local charset representations. -- Document origin of some magic constants. TAG=agy CONV=818eabd3-5feb-4f7e-8419-5bdf50c0ebd6 Change-Id: I89516de04fa4d8a38be827169bbd8e5a4a35ac28 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/149590 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcrt/fx_codepage.cpp b/core/fxcrt/fx_codepage.cpp index 2f9bce6..1fb5e42 100644 --- a/core/fxcrt/fx_codepage.cpp +++ b/core/fxcrt/fx_codepage.cpp
@@ -333,3 +333,44 @@ return wlen; #endif } + +FX_CharsetFlag FX_CharsetFlagForCharset(FX_Charset charset) { + switch (charset) { + case FX_Charset::kANSI: + return FX_CharsetFlag::kANSI; + case FX_Charset::kSymbol: + return FX_CharsetFlag::kSymbol; + case FX_Charset::kShiftJIS: + return FX_CharsetFlag::kShiftJIS; + case FX_Charset::kHangul: + return FX_CharsetFlag::kHangul; + case FX_Charset::kJohab: + return FX_CharsetFlag::kJohab; + case FX_Charset::kChineseSimplified: + return FX_CharsetFlag::kChineseSimplified; + case FX_Charset::kChineseTraditional: + return FX_CharsetFlag::kChineseTraditional; + case FX_Charset::kMSWin_Greek: + return FX_CharsetFlag::kMSWin_Greek; + case FX_Charset::kMSWin_Turkish: + return FX_CharsetFlag::kMSWin_Turkish; + case FX_Charset::kMSWin_Vietnamese: + return FX_CharsetFlag::kMSWin_Vietnamese; + case FX_Charset::kMSWin_Hebrew: + return FX_CharsetFlag::kMSWin_Hebrew; + case FX_Charset::kMSWin_Arabic: + return FX_CharsetFlag::kMSWin_Arabic; + case FX_Charset::kMSWin_Baltic: + return FX_CharsetFlag::kMSWin_Baltic; + case FX_Charset::kMSWin_Cyrillic: + return FX_CharsetFlag::kMSWin_Cyrillic; + case FX_Charset::kThai: + return FX_CharsetFlag::kThai; + case FX_Charset::kMSWin_EasternEuropean: + return FX_CharsetFlag::kMSWin_EasternEuropean; + case FX_Charset::kOEM: + return FX_CharsetFlag::kOEM; + default: + return FX_CharsetFlag::kNone; + } +}
diff --git a/core/fxcrt/fx_codepage.h b/core/fxcrt/fx_codepage.h index 5e6eba0..ddfc115 100644 --- a/core/fxcrt/fx_codepage.h +++ b/core/fxcrt/fx_codepage.h
@@ -16,6 +16,8 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/span.h" +// Corresponds to Windows Code Page Identifiers. +// https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers enum class FX_CodePage : uint16_t { kDefANSI = 0, kSymbol = 42, @@ -68,6 +70,8 @@ kFailure = 65535, }; +// Corresponds to Windows GDI Character Set Identifiers. +// https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-logfonta enum class FX_Charset : uint8_t { kANSI = 0, kDefault = 1, @@ -102,6 +106,28 @@ kOEM = 255, }; +// Compact representation for a set of FX_Charset values. +enum class FX_CharsetFlag : uint32_t { + kNone = 0, + kANSI = 1 << 0, + kSymbol = 1 << 1, + kShiftJIS = 1 << 2, + kHangul = 1 << 3, + kJohab = 1 << 4, + kChineseSimplified = 1 << 5, + kChineseTraditional = 1 << 6, + kMSWin_Greek = 1 << 7, + kMSWin_Turkish = 1 << 8, + kMSWin_Vietnamese = 1 << 9, + kMSWin_Hebrew = 1 << 10, + kMSWin_Arabic = 1 << 11, + kMSWin_Baltic = 1 << 12, + kMSWin_Cyrillic = 1 << 13, + kThai = 1 << 14, + kMSWin_EasternEuropean = 1 << 15, + kOEM = 1 << 16, +}; + // Hi-bytes to unicode codepoint mapping for various code pages. struct FX_CharsetUnicodes { FX_Charset charset_; @@ -114,6 +140,7 @@ FX_CodePage FX_GetCodePageFromCharset(FX_Charset charset); FX_Charset FX_GetCharsetFromCodePage(FX_CodePage codepage); FX_Charset FX_GetCharsetFromInt(int value); +FX_CharsetFlag FX_CharsetFlagForCharset(FX_Charset charset); bool FX_CharSetIsCJK(FX_Charset uCharset); size_t FX_WideCharToMultiByte(FX_CodePage codepage, WideStringView wstr,
diff --git a/core/fxcrt/fx_codepage_forward.h b/core/fxcrt/fx_codepage_forward.h index c67eaf2..45cf189 100644 --- a/core/fxcrt/fx_codepage_forward.h +++ b/core/fxcrt/fx_codepage_forward.h
@@ -12,6 +12,7 @@ // Incomplete definitions of large enumerated type for headers that don't // need the specifics. enum class FX_Charset : uint8_t; +enum class FX_CharsetFlag : uint32_t; enum class FX_CodePage : uint16_t; #endif // CORE_FXCRT_FX_CODEPAGE_FORWARD_H_
diff --git a/core/fxge/android/cfpf_skiafontmgr.cpp b/core/fxge/android/cfpf_skiafontmgr.cpp index 41d1db2..516b52d 100644 --- a/core/fxge/android/cfpf_skiafontmgr.cpp +++ b/core/fxge/android/cfpf_skiafontmgr.cpp
@@ -121,63 +121,54 @@ return nullptr; } -enum SKIACHARSET { - SKIACHARSET_Ansi = 1 << 0, - SKIACHARSET_Default = 1 << 1, - SKIACHARSET_Symbol = 1 << 2, - SKIACHARSET_ShiftJIS = 1 << 3, - SKIACHARSET_Korean = 1 << 4, - SKIACHARSET_Johab = 1 << 5, - SKIACHARSET_GB2312 = 1 << 6, - SKIACHARSET_BIG5 = 1 << 7, - SKIACHARSET_Greek = 1 << 8, - SKIACHARSET_Turkish = 1 << 9, - SKIACHARSET_Vietnamese = 1 << 10, - SKIACHARSET_Hebrew = 1 << 11, - SKIACHARSET_Arabic = 1 << 12, - SKIACHARSET_Baltic = 1 << 13, - SKIACHARSET_Cyrillic = 1 << 14, - SKIACHARSET_Thai = 1 << 15, - SKIACHARSET_EeasternEuropean = 1 << 16, - SKIACHARSET_PC = 1 << 17, - SKIACHARSET_OEM = 1 << 18, -}; +// Map from OS/2 table ulCodePageRange1 bits (0-31) to FX_CharsetFlag. +// See https://learn.microsoft.com/en-us/typography/opentype/spec/os2 +constexpr auto kFPFSkiaFontFXCharsetFlags = + std::to_array<const FX_CharsetFlag>({ + FX_CharsetFlag::kANSI, // 0 (Latin 1) + FX_CharsetFlag::kMSWin_EasternEuropean, // 1 (Latin 2) + FX_CharsetFlag::kMSWin_Cyrillic, // 2 (Cyrillic) + FX_CharsetFlag::kMSWin_Greek, // 3 (Greek) + FX_CharsetFlag::kMSWin_Turkish, // 4 (Turkish) + FX_CharsetFlag::kMSWin_Hebrew, // 5 (Hebrew) + FX_CharsetFlag::kMSWin_Arabic, // 6 (Arabic) + FX_CharsetFlag::kMSWin_Baltic, // 7 (Baltic) + FX_CharsetFlag::kMSWin_Vietnamese, // 8 (Vietnamese) + FX_CharsetFlag::kNone, // 9 (Alt ANSI) + FX_CharsetFlag::kNone, // 10 (Alt ANSI) + FX_CharsetFlag::kNone, // 11 (Alt ANSI) + FX_CharsetFlag::kNone, // 12 (Alt ANSI) + FX_CharsetFlag::kNone, // 13 (Alt ANSI) + FX_CharsetFlag::kNone, // 14 (Alt ANSI) + FX_CharsetFlag::kNone, // 15 (Alt ANSI) + FX_CharsetFlag::kThai, // 16 (Thai) + FX_CharsetFlag::kShiftJIS, // 17 (JIS/Japan) + FX_CharsetFlag::kChineseSimplified, // 18 (CN Simple) + FX_CharsetFlag::kHangul, // 19 (Korean Wansung) + FX_CharsetFlag::kChineseTraditional, // 20 (CN Trad) + FX_CharsetFlag::kJohab, // 21 (Korean Johab) + FX_CharsetFlag::kNone, // 22 (Alt ANSI/OEM) + FX_CharsetFlag::kNone, // 23 (Alt ANSI/OEM) + FX_CharsetFlag::kNone, // 24 (Alt ANSI/OEM) + FX_CharsetFlag::kNone, // 25 (Alt ANSI/OEM) + FX_CharsetFlag::kNone, // 26 (Alt ANSI/OEM) + FX_CharsetFlag::kNone, // 27 (Alt ANSI/OEM) + FX_CharsetFlag::kNone, // 28 (Alt ANSI/OEM) + FX_CharsetFlag::kNone, // 29 (Mac US Roman) + FX_CharsetFlag::kOEM, // 30 (OEM) + FX_CharsetFlag::kSymbol, // 31 (Symbol) + }); -uint32_t SkiaGetCharset(FX_Charset charset) { - switch (charset) { - case FX_Charset::kANSI: - return SKIACHARSET_Ansi; - case FX_Charset::kDefault: - return SKIACHARSET_Default; - case FX_Charset::kSymbol: - return SKIACHARSET_Symbol; - case FX_Charset::kShiftJIS: - return SKIACHARSET_ShiftJIS; - case FX_Charset::kHangul: - return SKIACHARSET_Korean; - case FX_Charset::kChineseSimplified: - return SKIACHARSET_GB2312; - case FX_Charset::kChineseTraditional: - return SKIACHARSET_BIG5; - case FX_Charset::kMSWin_Greek: - return SKIACHARSET_Greek; - case FX_Charset::kMSWin_Turkish: - return SKIACHARSET_Turkish; - case FX_Charset::kMSWin_Hebrew: - return SKIACHARSET_Hebrew; - case FX_Charset::kMSWin_Arabic: - return SKIACHARSET_Arabic; - case FX_Charset::kMSWin_Baltic: - return SKIACHARSET_Baltic; - case FX_Charset::kMSWin_Cyrillic: - return SKIACHARSET_Cyrillic; - case FX_Charset::kThai: - return SKIACHARSET_Thai; - case FX_Charset::kMSWin_EasternEuropean: - return SKIACHARSET_EeasternEuropean; - default: - return SKIACHARSET_Default; +Mask<FX_CharsetFlag> SkiaGetFaceCharsets(uint32_t code_range) { + static_assert(static_cast<uint32_t>(FX_CharsetFlag::kNone) == 0, + "FX_CharsetFlag::kNone must be 0 for ORing to be a no-op"); + Mask<FX_CharsetFlag> charsets; + for (int32_t i = 0; i < 32; i++) { + if (code_range & (1U << i)) { + charsets |= kFPFSkiaFontFXCharsetFlags[i]; + } } + return charsets; } uint32_t SkiaNormalizeFontName(ByteStringView family) { @@ -224,51 +215,6 @@ return name.Contains("arabic"); } -constexpr auto kFPFSkiaFontCharsets = std::to_array<const uint32_t>({ - SKIACHARSET_Ansi, - SKIACHARSET_EeasternEuropean, - SKIACHARSET_Cyrillic, - SKIACHARSET_Greek, - SKIACHARSET_Turkish, - SKIACHARSET_Hebrew, - SKIACHARSET_Arabic, - SKIACHARSET_Baltic, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - SKIACHARSET_Thai, - SKIACHARSET_ShiftJIS, - SKIACHARSET_GB2312, - SKIACHARSET_Korean, - SKIACHARSET_BIG5, - SKIACHARSET_Johab, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - SKIACHARSET_OEM, - SKIACHARSET_Symbol, -}); - -uint32_t SkiaGetFaceCharset(uint32_t code_range) { - uint32_t charset = 0; - for (int32_t i = 0; i < 32; i++) { - if (code_range & (1 << i)) { - charset |= kFPFSkiaFontCharsets[i]; - } - } - return charset; -} - } // namespace CFPF_SkiaFontMgr::CFPF_SkiaFontMgr() = default; @@ -328,8 +274,11 @@ int32_t best_score = -1; int32_t best_glyph_num = 0; for (const std::unique_ptr<Entry>& font : pdfium::Reversed(font_faces_)) { - if (!(font->charsets & SkiaGetCharset(charset))) { - continue; + if (charset != FX_Charset::kDefault) { + FX_CharsetFlag flag = FX_CharsetFlagForCharset(charset); + if (flag != FX_CharsetFlag::kNone && !(font->charsets & flag)) { + continue; + } } int32_t score = 0; const uint32_t sys_font_name_hash = @@ -448,17 +397,17 @@ RetainPtr<CFX_Face> face, const ByteString& file, int face_index) { - uint32_t charset = SKIACHARSET_Default; + Mask<FX_CharsetFlag> charsets; std::optional<std::array<uint32_t, 2>> cp_range = face->GetOs2CodePageRange(); if (cp_range.has_value()) { - charset |= SkiaGetFaceCharset(cp_range.value()[0]); + charsets |= SkiaGetFaceCharsets(cp_range.value()[0]); } auto entry = std::make_unique<Entry>(); entry->path = file; entry->family = face->GetFamilyName(); entry->style = face->GetFontStyle(); entry->face_index = face_index; - entry->charsets = charset; + entry->charsets = charsets; entry->glyph_num = face->GetGlyphCount(); return entry; }
diff --git a/core/fxge/android/cfpf_skiafontmgr.h b/core/fxge/android/cfpf_skiafontmgr.h index aecb417..9aa9af5 100644 --- a/core/fxge/android/cfpf_skiafontmgr.h +++ b/core/fxge/android/cfpf_skiafontmgr.h
@@ -13,6 +13,7 @@ #include "core/fxcrt/bytestring.h" #include "core/fxcrt/fx_codepage_forward.h" +#include "core/fxcrt/mask.h" #include "core/fxcrt/retain_ptr.h" #include "core/fxge/cfx_face.h" @@ -39,7 +40,7 @@ ByteString family; uint32_t style; int32_t face_index; - uint32_t charsets; + Mask<FX_CharsetFlag> charsets; int32_t glyph_num; };
diff --git a/core/fxge/cfx_folderfontinfo.cpp b/core/fxge/cfx_folderfontinfo.cpp index 2a554e4..af92f72 100644 --- a/core/fxge/cfx_folderfontinfo.cpp +++ b/core/fxge/cfx_folderfontinfo.cpp
@@ -256,30 +256,32 @@ LoadTableFromTT(pFile, tables.unsigned_str(), nTables, kOs2Tag, filesize); if (os2.GetLength() >= 86) { pdfium::span<const uint8_t> p = os2.unsigned_span().subspan(78u); + // `codepages` corresponds to OS/2 table ulCodePageRange1. + // See https://learn.microsoft.com/en-us/typography/opentype/spec/os2 uint32_t codepages = fxcrt::GetUInt32MSBFirst(p.first<4u>()); if (codepages & (1U << 17)) { mapper_->AddInstalledFont(facename, FX_Charset::kShiftJIS); - pInfo->charsets_ |= FontFaceInfo::CharsetFlag::kShiftJis; + pInfo->charsets_ |= FX_CharsetFlag::kShiftJIS; } if (codepages & (1U << 18)) { mapper_->AddInstalledFont(facename, FX_Charset::kChineseSimplified); - pInfo->charsets_ |= FontFaceInfo::CharsetFlag::kGb; + pInfo->charsets_ |= FX_CharsetFlag::kChineseSimplified; } if (codepages & (1U << 20)) { mapper_->AddInstalledFont(facename, FX_Charset::kChineseTraditional); - pInfo->charsets_ |= FontFaceInfo::CharsetFlag::kBig5; + pInfo->charsets_ |= FX_CharsetFlag::kChineseTraditional; } if ((codepages & (1U << 19)) || (codepages & (1U << 21))) { mapper_->AddInstalledFont(facename, FX_Charset::kHangul); - pInfo->charsets_ |= FontFaceInfo::CharsetFlag::kKorean; + pInfo->charsets_ |= FX_CharsetFlag::kHangul; } if (codepages & (1U << 31)) { mapper_->AddInstalledFont(facename, FX_Charset::kSymbol); - pInfo->charsets_ |= FontFaceInfo::CharsetFlag::kSymbol; + pInfo->charsets_ |= FX_CharsetFlag::kSymbol; } } mapper_->AddInstalledFont(facename, FX_Charset::kANSI); - pInfo->charsets_ |= FontFaceInfo::CharsetFlag::kAnsi; + pInfo->charsets_ |= FX_CharsetFlag::kANSI; pInfo->styles_ = 0; if (style.Contains("Bold")) { pInfo->styles_ |= pdfium::kFontStyleForceBold; @@ -304,26 +306,6 @@ return nullptr; } -CFX_FolderFontInfo::FontFaceInfo::CharsetFlag -CFX_FolderFontInfo::FontFaceInfo::GetCharset(FX_Charset charset) { - switch (charset) { - case FX_Charset::kShiftJIS: - return CharsetFlag::kShiftJis; - case FX_Charset::kChineseSimplified: - return CharsetFlag::kGb; - case FX_Charset::kChineseTraditional: - return CharsetFlag::kBig5; - case FX_Charset::kHangul: - return CharsetFlag::kKorean; - case FX_Charset::kSymbol: - return CharsetFlag::kSymbol; - case FX_Charset::kANSI: - return CharsetFlag::kAnsi; - default: - return CharsetFlag::kNone; - } -} - void* CFX_FolderFontInfo::FindFont(int weight, bool bItalic, FX_Charset charset, @@ -331,7 +313,7 @@ const ByteString& family, bool bMatchName) { FontFaceInfo* pFind = nullptr; - FontFaceInfo::CharsetFlag charset_flag = FontFaceInfo::GetCharset(charset); + FX_CharsetFlag charset_flag = FX_CharsetFlagForCharset(charset); int32_t iBestSimilar = 0; if (bMatchName) { @@ -470,7 +452,7 @@ file_size_(fileSize) {} bool CFX_FolderFontInfo::FontFaceInfo::IsEligibleForFindFont( - CharsetFlag flag, + FX_CharsetFlag flag, FX_Charset charset) const { return (charsets_ & flag) || charset == FX_Charset::kDefault; }
diff --git a/core/fxge/cfx_folderfontinfo.h b/core/fxge/cfx_folderfontinfo.h index 67b9cc0..98831fa 100644 --- a/core/fxge/cfx_folderfontinfo.h +++ b/core/fxge/cfx_folderfontinfo.h
@@ -44,18 +44,6 @@ class FontFaceInfo { public: - enum class CharsetFlag : uint8_t { - kNone = 0, - kAnsi = 1 << 0, - kSymbol = 1 << 1, - kShiftJis = 1 << 2, - kBig5 = 1 << 3, - kGb = 1 << 4, - kKorean = 1 << 5, - }; - - static CharsetFlag GetCharset(FX_Charset charset); - static constexpr int32_t kSimilarityScoreMax = 68; FontFaceInfo(ByteString filePath, @@ -64,7 +52,7 @@ uint32_t fontOffset, uint32_t fileSize); - bool IsEligibleForFindFont(CharsetFlag flag, FX_Charset charset) const; + bool IsEligibleForFindFont(FX_CharsetFlag flag, FX_Charset charset) const; int32_t SimilarityScore(int weight, bool italic, int pitch_family, @@ -76,7 +64,7 @@ const uint32_t font_offset_; const uint32_t file_size_; uint32_t styles_ = 0; - Mask<CharsetFlag> charsets_; + Mask<FX_CharsetFlag> charsets_; }; void ScanPath(const ByteString& path);
diff --git a/core/fxge/cfx_folderfontinfo_unittest.cpp b/core/fxge/cfx_folderfontinfo_unittest.cpp index 428ef13..a02095e 100644 --- a/core/fxge/cfx_folderfontinfo_unittest.cpp +++ b/core/fxge/cfx_folderfontinfo_unittest.cpp
@@ -34,23 +34,15 @@ class CFXFolderFontInfoTest : public ::testing::Test { public: CFXFolderFontInfoTest() { - AddDummyFont(kArial, CFX_FolderFontInfo::FontFaceInfo::CharsetFlag::kAnsi); - AddDummyFont(kCourierNew, - CFX_FolderFontInfo::FontFaceInfo::CharsetFlag::kAnsi); - AddDummyFont(kTimesNewRoman, - CFX_FolderFontInfo::FontFaceInfo::CharsetFlag::kNone); - AddDummyFont(kBookshelfSymbol7, - CFX_FolderFontInfo::FontFaceInfo::CharsetFlag::kSymbol); - AddDummyFont(kSymbol, - CFX_FolderFontInfo::FontFaceInfo::CharsetFlag::kSymbol); - AddDummyFont(kTofuBold, - CFX_FolderFontInfo::FontFaceInfo::CharsetFlag::kSymbol); - AddDummyFont(kLatoUltraBold, - CFX_FolderFontInfo::FontFaceInfo::CharsetFlag::kAnsi); - AddDummyFont(kOxygenSansSansBold, - CFX_FolderFontInfo::FontFaceInfo::CharsetFlag::kAnsi); - AddDummyFont(kComicSansMS, - CFX_FolderFontInfo::FontFaceInfo::CharsetFlag::kAnsi); + AddDummyFont(kArial, FX_CharsetFlag::kANSI); + AddDummyFont(kCourierNew, FX_CharsetFlag::kANSI); + AddDummyFont(kTimesNewRoman, FX_CharsetFlag::kNone); + AddDummyFont(kBookshelfSymbol7, FX_CharsetFlag::kSymbol); + AddDummyFont(kSymbol, FX_CharsetFlag::kSymbol); + AddDummyFont(kTofuBold, FX_CharsetFlag::kSymbol); + AddDummyFont(kLatoUltraBold, FX_CharsetFlag::kANSI); + AddDummyFont(kOxygenSansSansBold, FX_CharsetFlag::kANSI); + AddDummyFont(kComicSansMS, FX_CharsetFlag::kANSI); } void* FindFont(int weight, @@ -68,8 +60,7 @@ } private: - void AddDummyFont(const char* font_name, - CFX_FolderFontInfo::FontFaceInfo::CharsetFlag charset) { + void AddDummyFont(const char* font_name, FX_CharsetFlag charset) { auto info = std::make_unique<CFX_FolderFontInfo::FontFaceInfo>( /*filePath=*/"", font_name, /*fontTables=*/"", /*fontOffset=*/0, /*fileSize=*/0);