7#include "core/fxge/cfx_folderfontinfo.h"
14#include "build/build_config.h"
15#include "core/fxcrt/byteorder.h"
16#include "core/fxcrt/check_op.h"
17#include "core/fxcrt/compiler_specific.h"
18#include "core/fxcrt/containers/contains.h"
19#include "core/fxcrt/fixed_size_data_vector.h"
20#include "core/fxcrt/fx_codepage.h"
21#include "core/fxcrt/fx_extension.h"
22#include "core/fxcrt/fx_folder.h"
23#include "core/fxcrt/fx_safe_types.h"
24#include "core/fxcrt/fx_system.h"
25#include "core/fxcrt/stl_util.h"
26#include "core/fxge/cfx_fontmapper.h"
27#include "core/fxge/fx_font.h"
33 const char* m_pSubstName;
36constexpr auto kBase14Substs =
fxcrt::ToArray<
const FontSubst>({
37 {
"Courier",
"Courier New"},
38 {
"Courier-Bold",
"Courier New Bold"},
39 {
"Courier-BoldOblique",
"Courier New Bold Italic"},
40 {
"Courier-Oblique",
"Courier New Italic"},
41 {
"Helvetica",
"Arial"},
42 {
"Helvetica-Bold",
"Arial Bold"},
43 {
"Helvetica-BoldOblique",
"Arial Bold Italic"},
44 {
"Helvetica-Oblique",
"Arial Italic"},
45 {
"Times-Roman",
"Times New Roman"},
46 {
"Times-Bold",
"Times New Roman Bold"},
47 {
"Times-BoldItalic",
"Times New Roman Bold Italic"},
48 {
"Times-Italic",
"Times New Roman Italic"},
53 inline void operator()(FILE* h)
const {
61 std::optional<size_t> result = installed_font_name.Find(family_name, 0);
62 if (!result.has_value())
65 size_t next_index = result.value() + family_name.GetLength();
70 if (installed_font_name.IsValidIndex(next_index) &&
71 FXSYS_IsLowerASCII(installed_font_name[next_index])) {
78ByteString ReadStringFromFile(FILE* pFile, uint32_t size) {
82 pdfium::span<
char> buffer = result.GetBuffer(size);
83 if (!fread(buffer.data(), size, 1, pFile))
86 result.ReleaseBuffer(size);
91 const uint8_t* pTables,
96 for (uint32_t i = 0; i < nTables; i++) {
98 auto p =
pdfium::make_span(pTables + i * 16, 16u);
100 uint32_t offset = fxcrt::GetUInt32MSBFirst(p.subspan(8));
101 uint32_t size = fxcrt::GetUInt32MSBFirst(p.subspan(12));
102 if (offset >
std::numeric_limits<uint32_t>::max() - size ||
103 static_cast<
FX_FILESIZE>(offset + size) > fileSize ||
104 fseek(pFile, offset, SEEK_SET) < 0) {
107 return ReadStringFromFile(pFile, size);
141 m_PathList.push_back(path);
146 for (
const auto& path : m_PathList)
152 std::unique_ptr<FX_Folder> handle = FX_Folder::OpenFolder(path);
158 while (handle->GetNextFile(&filename, &bFolder)) {
160 if (filename
== "." || filename
== "..")
165 if (ext
!= ".ttf" && ext
!= ".ttc" && ext
!= ".otf")
176 fullpath
+= filename;
182 std::unique_ptr<FILE, FxFileCloser> pFile(fopen(path.c_str(),
"rb"));
186 fseek(pFile.get(), 0, SEEK_END);
190 fseek(pFile.get(), 0, SEEK_SET);
192 size_t items_read = fread(buffer, 12, 1, pFile.get());
193 if (items_read != 1) {
197 fxcrt::GetUInt32MSBFirst(pdfium::make_span(buffer).first<4u>());
204 fxcrt::GetUInt32MSBFirst(pdfium::make_span(buffer).subspan<8u>());
205 FX_SAFE_SIZE_T safe_face_bytes = nFaces;
206 safe_face_bytes *= 4;
207 if (!safe_face_bytes.IsValid())
211 FixedSizeDataVector<uint8_t>::Uninit(safe_face_bytes.ValueOrDie());
212 pdfium::span<uint8_t> offsets_span = offsets.span();
213 items_read = fread(offsets_span.data(), 1,
214 offsets_span.size(), pFile.get());
215 if (items_read != offsets_span.size()) {
219 for (uint32_t i = 0; i < nFaces; i++) {
221 fxcrt::GetUInt32MSBFirst(offsets_span.subspan(i * 4))
);
230 if (fseek(pFile, offset, SEEK_SET) < 0 || !fread(buffer, 12, 1, pFile))
234 fxcrt::GetUInt16MSBFirst(pdfium::as_byte_span(buffer).subspan<4, 2>());
235 ByteString tables = ReadStringFromFile(pFile, nTables * 16);
236 if (tables.IsEmpty())
239 static constexpr uint32_t kNameTag =
241 ByteString names = LoadTableFromTT(pFile, tables.unsigned_str(), nTables,
246 ByteString facename = GetNameFromTT(names.unsigned_span(), 1);
247 if (facename.IsEmpty())
250 ByteString style = GetNameFromTT(names.unsigned_span(), 2);
251 if (style
!= "Regular")
252 facename
+= " " + style;
254 if (pdfium::Contains(m_FontList, facename))
258 std::make_unique<
FontFaceInfo>(path, facename, tables, offset, filesize);
259 static constexpr uint32_t kOs2Tag =
262 LoadTableFromTT(pFile, tables.unsigned_str(), nTables, kOs2Tag, filesize);
263 if (os2.GetLength() >= 86) {
264 pdfium::span<
const uint8_t> p = os2.unsigned_span().subspan(78);
265 uint32_t codepages = fxcrt::GetUInt32MSBFirst(p);
266 if (codepages & (1U << 17)) {
267 m_pMapper->AddInstalledFont(facename, FX_Charset::kShiftJIS);
270 if (codepages & (1U << 18)) {
271 m_pMapper->AddInstalledFont(facename, FX_Charset::kChineseSimplified);
274 if (codepages & (1U << 20)) {
275 m_pMapper->AddInstalledFont(facename, FX_Charset::kChineseTraditional);
278 if ((codepages & (1U << 19)) || (codepages & (1U << 21))) {
279 m_pMapper->AddInstalledFont(facename, FX_Charset::kHangul);
282 if (codepages & (1U << 31)) {
283 m_pMapper->AddInstalledFont(facename, FX_Charset::kSymbol);
287 m_pMapper->AddInstalledFont(facename, FX_Charset::kANSI);
290 if (style.Contains(
"Bold"))
292 if (style.Contains(
"Italic") || style.Contains(
"Oblique"))
294 if (facename.Contains(
"Serif"))
297 m_FontList[facename] = std::move(pInfo);
301 for (size_t iBaseFont = 0; iBaseFont <
std::size(kBase14Substs);
303 if (face == kBase14Substs[iBaseFont].m_pName) {
304 return GetFont(kBase14Substs[iBaseFont].m_pSubstName
);
317 uint32_t charset_flag = GetCharset(charset);
319 int32_t iBestSimilar = 0;
323 auto direct_it = m_FontList.find(family);
324 if (direct_it != m_FontList.end()) {
339 for (
const auto& it : m_FontList) {
340 const ByteString& bsName = it.first;
341 FontFaceInfo* pFont = it.second.get();
342 if (!pFont->IsEligibleForFindFont(charset_flag, charset)) {
345 int32_t iSimilarValue = pFont->SimilarityScore(
346 weight, bItalic, pitch_family,
347 bMatchName && bsFamily.GetLength() == bsName.GetLength());
348 if (iSimilarValue > iBestSimilar) {
349 if (bMatchName && !FindFamilyNameMatch(bsFamily, bsName)) {
352 iBestSimilar = iSimilarValue;
362 auto* courier_new =
GetFont("Courier New");
379 auto it = m_FontList.find(face);
380 return it != m_FontList.end() ? it->second.get() :
nullptr;
385 pdfium::span<uint8_t> buffer) {
390 uint32_t datasize = 0;
397 size_t nTables = pFont->m_FontTables.GetLength() / 16;
398 for (size_t i = 0; i < nTables; i++) {
400 pdfium::span<
const uint8_t> p =
401 pFont->m_FontTables.unsigned_span().subspan(i * 16);
403 offset = fxcrt::GetUInt32MSBFirst(p.subspan(8));
404 datasize = fxcrt::GetUInt32MSBFirst(p.subspan(12));
409 if (!datasize || buffer.size() < datasize)
412 std::unique_ptr<FILE, FxFileCloser> pFile(
413 fopen(pFont->m_FilePath.c_str(),
"rb"));
417 if (fseek(pFile.get(), offset, SEEK_SET) < 0 ||
418 fread(buffer.data(), datasize, 1, pFile.get()) != 1) {
458 bool exact_match_bonus)
const {
475 if (exact_match_bonus) {
fxcrt::ByteString ByteString
#define CHARSET_FLAG_SHIFTJIS
#define CHARSET_FLAG_ANSI
#define CHARSET_FLAG_BIG5
#define CHARSET_FLAG_SYMBOL
#define CHARSET_FLAG_KOREAN
bool IsEligibleForFindFont(uint32_t flag, FX_Charset charset) const
const uint32_t m_FontOffset
int32_t SimilarityScore(int weight, bool italic, int pitch_family, bool exact_match_bonus) const
FontFaceInfo(ByteString filePath, ByteString faceName, ByteString fontTables, uint32_t fontOffset, uint32_t fileSize)
const uint32_t m_FileSize
static constexpr int32_t kSimilarityScoreMax
~CFX_FolderFontInfo() override
void ScanFile(const ByteString &path)
bool GetFontCharset(void *hFont, FX_Charset *charset) override
size_t GetFontData(void *hFont, uint32_t table, pdfium::span< uint8_t > buffer) override
void * GetSubstFont(const ByteString &face)
void DeleteFont(void *hFont) override
void * FindFont(int weight, bool bItalic, FX_Charset charset, int pitch_family, const ByteString &family, bool bMatchName)
void ReportFace(const ByteString &path, FILE *pFile, FX_FILESIZE filesize, uint32_t offset)
bool GetFaceName(void *hFont, ByteString *name) override
void ScanPath(const ByteString &path)
void * MapFont(int weight, bool bItalic, FX_Charset charset, int pitch_family, const ByteString &face) override
void AddPath(const ByteString &path)
void * GetFont(const ByteString &face) override
bool EnumFontList(CFX_FontMapper *pMapper) override
static constexpr uint32_t MakeTag(char c1, char c2, char c3, char c4)
ByteString & operator+=(const ByteString &str)
bool operator==(const char *ptr) const
ByteString & operator+=(const char *str)
bool operator!=(const char *ptr) const
bool FontFamilyIsFixedPitch(uint32_t family)
bool FontStyleIsSerif(uint32_t style)
bool FontStyleIsFixedPitch(uint32_t style)
bool FontFamilyIsScript(int32_t family)
bool FontFamilyIsRoman(uint32_t family)
bool FontStyleIsItalic(uint32_t style)
#define FXFONT_FORCE_BOLD
bool FontStyleIsScript(uint32_t style)
bool FontStyleIsForceBold(uint32_t style)
ByteString operator+(const char *str1, const ByteString &str2)
uint32_t GetUInt32MSBFirst(pdfium::span< const uint8_t, 4 > span)
fxcrt::ByteStringView ByteStringView
constexpr uint32_t kTableTTCF