diff options
author | npm <npm@chromium.org> | 2016-07-27 13:54:25 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-07-27 13:54:25 -0700 |
commit | f73893a6110f2d4960b372fb4fe38e4fd629ce8f (patch) | |
tree | e90128b1eb13a8d5c623fb91b30b07a5cf58eb86 /core/fxge/ge | |
parent | 461eeafe191068ac8c32f2717907fc6a22a667d2 (diff) | |
download | pdfium-f73893a6110f2d4960b372fb4fe38e4fd629ce8f.tar.xz |
Splitting fx_ge_fontmap.cpp
Move CFX_FolderFontInfo, CFX_FontMgr, and CFX_FontMapper into their own
classes. There are namespaces in each of the new files, having methods
from the original namespace in fx_ge_fontmap, according to what each
class needs.
Review-Url: https://codereview.chromium.org/2185533006
Diffstat (limited to 'core/fxge/ge')
-rw-r--r-- | core/fxge/ge/cfx_folderfontinfo.cpp | 377 | ||||
-rw-r--r-- | core/fxge/ge/cfx_folderfontinfo.h | 67 | ||||
-rw-r--r-- | core/fxge/ge/cfx_fontmapper.cpp | 910 | ||||
-rw-r--r-- | core/fxge/ge/cfx_fontmgr.cpp | 257 | ||||
-rw-r--r-- | core/fxge/ge/fx_ge.cpp | 2 | ||||
-rw-r--r-- | core/fxge/ge/fx_ge_font.cpp | 1 | ||||
-rw-r--r-- | core/fxge/ge/fx_ge_fontmap.cpp | 1525 | ||||
-rw-r--r-- | core/fxge/ge/fx_ge_linux.cpp | 2 | ||||
-rw-r--r-- | core/fxge/ge/fx_ge_text.cpp | 1 |
9 files changed, 1619 insertions, 1523 deletions
diff --git a/core/fxge/ge/cfx_folderfontinfo.cpp b/core/fxge/ge/cfx_folderfontinfo.cpp new file mode 100644 index 0000000000..5bd5b29c79 --- /dev/null +++ b/core/fxge/ge/cfx_folderfontinfo.cpp @@ -0,0 +1,377 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/ge/cfx_folderfontinfo.h" + +#include "core/fxge/include/cfx_fontmapper.h" +#include "core/fxge/include/fx_font.h" + +#include "third_party/base/stl_util.h" + +namespace { + +const struct { + const FX_CHAR* m_pName; + const FX_CHAR* m_pSubstName; +} Base14Substs[] = { + {"Courier", "Courier New"}, + {"Courier-Bold", "Courier New Bold"}, + {"Courier-BoldOblique", "Courier New Bold Italic"}, + {"Courier-Oblique", "Courier New Italic"}, + {"Helvetica", "Arial"}, + {"Helvetica-Bold", "Arial Bold"}, + {"Helvetica-BoldOblique", "Arial Bold Italic"}, + {"Helvetica-Oblique", "Arial Italic"}, + {"Times-Roman", "Times New Roman"}, + {"Times-Bold", "Times New Roman Bold"}, + {"Times-BoldItalic", "Times New Roman Bold Italic"}, + {"Times-Italic", "Times New Roman Italic"}, +}; + +CFX_ByteString FPDF_ReadStringFromFile(FXSYS_FILE* pFile, uint32_t size) { + CFX_ByteString buffer; + if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) + return CFX_ByteString(); + buffer.ReleaseBuffer(size); + return buffer; +} + +CFX_ByteString FPDF_LoadTableFromTT(FXSYS_FILE* pFile, + const uint8_t* pTables, + uint32_t nTables, + uint32_t tag) { + for (uint32_t i = 0; i < nTables; i++) { + const uint8_t* p = pTables + i * 16; + if (GET_TT_LONG(p) == tag) { + uint32_t offset = GET_TT_LONG(p + 8); + uint32_t size = GET_TT_LONG(p + 12); + FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); + return FPDF_ReadStringFromFile(pFile, size); + } + } + return CFX_ByteString(); +} + +uint32_t GetCharset(int charset) { + switch (charset) { + case FXFONT_SHIFTJIS_CHARSET: + return CHARSET_FLAG_SHIFTJIS; + case FXFONT_GB2312_CHARSET: + return CHARSET_FLAG_GB; + case FXFONT_CHINESEBIG5_CHARSET: + return CHARSET_FLAG_BIG5; + case FXFONT_HANGEUL_CHARSET: + return CHARSET_FLAG_KOREAN; + case FXFONT_SYMBOL_CHARSET: + return CHARSET_FLAG_SYMBOL; + case FXFONT_ANSI_CHARSET: + return CHARSET_FLAG_ANSI; + default: + break; + } + return 0; +} + +int32_t GetSimilarValue(int weight, + FX_BOOL bItalic, + int pitch_family, + uint32_t style) { + int32_t iSimilarValue = 0; + if (!!(style & FXFONT_BOLD) == (weight > 400)) + iSimilarValue += 16; + if (!!(style & FXFONT_ITALIC) == bItalic) + iSimilarValue += 16; + if (!!(style & FXFONT_SERIF) == !!(pitch_family & FXFONT_FF_ROMAN)) + iSimilarValue += 16; + if (!!(style & FXFONT_SCRIPT) == !!(pitch_family & FXFONT_FF_SCRIPT)) + iSimilarValue += 8; + if (!!(style & FXFONT_FIXED_PITCH) == + !!(pitch_family & FXFONT_FF_FIXEDPITCH)) { + iSimilarValue += 8; + } + return iSimilarValue; +} + +} // namespace + +CFX_FolderFontInfo::CFX_FolderFontInfo() {} + +CFX_FolderFontInfo::~CFX_FolderFontInfo() { + for (const auto& pair : m_FontList) + delete pair.second; +} + +void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) { + m_PathList.push_back(CFX_ByteString(path)); +} + +FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) { + m_pMapper = pMapper; + for (const auto& path : m_PathList) + ScanPath(path); + return TRUE; +} + +void CFX_FolderFontInfo::ScanPath(const CFX_ByteString& path) { + void* handle = FX_OpenFolder(path.c_str()); + if (!handle) + return; + + CFX_ByteString filename; + FX_BOOL bFolder; + while (FX_GetNextFile(handle, filename, bFolder)) { + if (bFolder) { + if (filename == "." || filename == "..") + continue; + } else { + CFX_ByteString ext = filename.Right(4); + ext.MakeUpper(); + if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") + continue; + } + + CFX_ByteString fullpath = path; +#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ + fullpath += "\\"; +#else + fullpath += "/"; +#endif + + fullpath += filename; + bFolder ? ScanPath(fullpath) : ScanFile(fullpath); + } + FX_CloseFolder(handle); +} + +void CFX_FolderFontInfo::ScanFile(const CFX_ByteString& path) { + FXSYS_FILE* pFile = FXSYS_fopen(path.c_str(), "rb"); + if (!pFile) + return; + + FXSYS_fseek(pFile, 0, FXSYS_SEEK_END); + + uint32_t filesize = FXSYS_ftell(pFile); + uint8_t buffer[16]; + FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET); + + size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile); + if (readCnt != 1) { + FXSYS_fclose(pFile); + return; + } + + if (GET_TT_LONG(buffer) == kTableTTCF) { + uint32_t nFaces = GET_TT_LONG(buffer + 8); + if (nFaces > std::numeric_limits<uint32_t>::max() / 4) { + FXSYS_fclose(pFile); + return; + } + uint32_t face_bytes = nFaces * 4; + uint8_t* offsets = FX_Alloc(uint8_t, face_bytes); + readCnt = FXSYS_fread(offsets, 1, face_bytes, pFile); + if (readCnt != face_bytes) { + FX_Free(offsets); + FXSYS_fclose(pFile); + return; + } + for (uint32_t i = 0; i < nFaces; i++) { + uint8_t* p = offsets + i * 4; + ReportFace(path, pFile, filesize, GET_TT_LONG(p)); + } + FX_Free(offsets); + } else { + ReportFace(path, pFile, filesize, 0); + } + FXSYS_fclose(pFile); +} + +void CFX_FolderFontInfo::ReportFace(const CFX_ByteString& path, + FXSYS_FILE* pFile, + uint32_t filesize, + uint32_t offset) { + FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); + char buffer[16]; + if (!FXSYS_fread(buffer, 12, 1, pFile)) + return; + + uint32_t nTables = GET_TT_SHORT(buffer + 4); + CFX_ByteString tables = FPDF_ReadStringFromFile(pFile, nTables * 16); + if (tables.IsEmpty()) + return; + + CFX_ByteString names = + FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x6e616d65); + if (names.IsEmpty()) + return; + + CFX_ByteString facename = + GetNameFromTT(names.raw_str(), names.GetLength(), 1); + if (facename.IsEmpty()) + return; + + CFX_ByteString style = GetNameFromTT(names.raw_str(), names.GetLength(), 2); + if (style != "Regular") + facename += " " + style; + + if (pdfium::ContainsKey(m_FontList, facename)) + return; + + CFX_FontFaceInfo* pInfo = + new CFX_FontFaceInfo(path, facename, tables, offset, filesize); + CFX_ByteString os2 = + FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x4f532f32); + if (os2.GetLength() >= 86) { + const uint8_t* p = os2.raw_str() + 78; + uint32_t codepages = GET_TT_LONG(p); + if (codepages & (1 << 17)) { + m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS; + } + if (codepages & (1 << 18)) { + m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_GB; + } + if (codepages & (1 << 20)) { + m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_BIG5; + } + if ((codepages & (1 << 19)) || (codepages & (1 << 21))) { + m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_KOREAN; + } + if (codepages & (1 << 31)) { + m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL; + } + } + m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_ANSI; + pInfo->m_Styles = 0; + if (style.Find("Bold") > -1) + pInfo->m_Styles |= FXFONT_BOLD; + if (style.Find("Italic") > -1 || style.Find("Oblique") > -1) + pInfo->m_Styles |= FXFONT_ITALIC; + if (facename.Find("Serif") > -1) + pInfo->m_Styles |= FXFONT_SERIF; + + m_FontList[facename] = pInfo; +} + +void* CFX_FolderFontInfo::GetSubstFont(const CFX_ByteString& face) { + for (size_t iBaseFont = 0; iBaseFont < FX_ArraySize(Base14Substs); + iBaseFont++) { + if (face == Base14Substs[iBaseFont].m_pName) + return GetFont(Base14Substs[iBaseFont].m_pSubstName); + } + return nullptr; +} + +void* CFX_FolderFontInfo::FindFont(int weight, + FX_BOOL bItalic, + int charset, + int pitch_family, + const FX_CHAR* family, + FX_BOOL bMatchName) { + CFX_FontFaceInfo* pFind = nullptr; + if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) + return GetFont("Courier New"); + uint32_t charset_flag = GetCharset(charset); + int32_t iBestSimilar = 0; + for (const auto& it : m_FontList) { + const CFX_ByteString& bsName = it.first; + CFX_FontFaceInfo* pFont = it.second; + if (!(pFont->m_Charsets & charset_flag) && + charset != FXFONT_DEFAULT_CHARSET) { + continue; + } + int32_t index = bsName.Find(family); + if (bMatchName && index < 0) + continue; + int32_t iSimilarValue = + GetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles); + if (iSimilarValue > iBestSimilar) { + iBestSimilar = iSimilarValue; + pFind = pFont; + } + } + return pFind; +} + +void* CFX_FolderFontInfo::MapFont(int weight, + FX_BOOL bItalic, + int charset, + int pitch_family, + const FX_CHAR* family, + int& iExact) { + return nullptr; +} + +#ifdef PDF_ENABLE_XFA +void* CFX_FolderFontInfo::MapFontByUnicode(uint32_t dwUnicode, + int weight, + FX_BOOL bItalic, + int pitch_family) { + return nullptr; +} +#endif // PDF_ENABLE_XFA + +void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face) { + auto it = m_FontList.find(face); + return it != m_FontList.end() ? it->second : nullptr; +} + +uint32_t CFX_FolderFontInfo::GetFontData(void* hFont, + uint32_t table, + uint8_t* buffer, + uint32_t size) { + if (!hFont) + return 0; + + const CFX_FontFaceInfo* pFont = static_cast<CFX_FontFaceInfo*>(hFont); + uint32_t datasize = 0; + uint32_t offset = 0; + if (table == 0) { + datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize; + } else if (table == kTableTTCF) { + datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0; + } else { + uint32_t nTables = pFont->m_FontTables.GetLength() / 16; + for (uint32_t i = 0; i < nTables; i++) { + const uint8_t* p = pFont->m_FontTables.raw_str() + i * 16; + if (GET_TT_LONG(p) == table) { + offset = GET_TT_LONG(p + 8); + datasize = GET_TT_LONG(p + 12); + } + } + } + + if (!datasize || size < datasize) + return datasize; + + FXSYS_FILE* pFile = FXSYS_fopen(pFont->m_FilePath.c_str(), "rb"); + if (!pFile) + return 0; + + if (FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET) < 0 || + FXSYS_fread(buffer, datasize, 1, pFile) != 1) { + datasize = 0; + } + FXSYS_fclose(pFile); + return datasize; +} + +void CFX_FolderFontInfo::DeleteFont(void* hFont) {} +FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) { + if (!hFont) + return FALSE; + CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont; + name = pFont->m_FaceName; + return TRUE; +} + +FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) { + return FALSE; +} diff --git a/core/fxge/ge/cfx_folderfontinfo.h b/core/fxge/ge/cfx_folderfontinfo.h new file mode 100644 index 0000000000..c0ce01cd36 --- /dev/null +++ b/core/fxge/ge/cfx_folderfontinfo.h @@ -0,0 +1,67 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_GE_CFX_FOLDERFONTINFO_H_ +#define CORE_FXGE_GE_CFX_FOLDERFONTINFO_H_ + +#include <map> +#include <vector> + +#include "core/fxge/include/cfx_fontmapper.h" +#include "core/fxge/include/ifx_systemfontinfo.h" +#include "core/fxge/include/fx_font.h" + +class CFX_FolderFontInfo : public IFX_SystemFontInfo { + public: + CFX_FolderFontInfo(); + ~CFX_FolderFontInfo() override; + + void AddPath(const CFX_ByteStringC& path); + + // IFX_SytemFontInfo: + FX_BOOL EnumFontList(CFX_FontMapper* pMapper) override; + void* MapFont(int weight, + FX_BOOL bItalic, + int charset, + int pitch_family, + const FX_CHAR* face, + int& bExact) override; +#ifdef PDF_ENABLE_XFA + void* MapFontByUnicode(uint32_t dwUnicode, + int weight, + FX_BOOL bItalic, + int pitch_family) override; +#endif // PDF_ENABLE_XFA + void* GetFont(const FX_CHAR* face) override; + uint32_t GetFontData(void* hFont, + uint32_t table, + uint8_t* buffer, + uint32_t size) override; + void DeleteFont(void* hFont) override; + FX_BOOL GetFaceName(void* hFont, CFX_ByteString& name) override; + FX_BOOL GetFontCharset(void* hFont, int& charset) override; + + protected: + void ScanPath(const CFX_ByteString& path); + void ScanFile(const CFX_ByteString& path); + void ReportFace(const CFX_ByteString& path, + FXSYS_FILE* pFile, + uint32_t filesize, + uint32_t offset); + void* GetSubstFont(const CFX_ByteString& face); + void* FindFont(int weight, + FX_BOOL bItalic, + int charset, + int pitch_family, + const FX_CHAR* family, + FX_BOOL bMatchName); + + std::map<CFX_ByteString, CFX_FontFaceInfo*> m_FontList; + std::vector<CFX_ByteString> m_PathList; + CFX_FontMapper* m_pMapper; +}; + +#endif // CORE_FXGE_GE_CFX_FOLDERFONTINFO_H_ diff --git a/core/fxge/ge/cfx_fontmapper.cpp b/core/fxge/ge/cfx_fontmapper.cpp new file mode 100644 index 0000000000..5846574ce4 --- /dev/null +++ b/core/fxge/ge/cfx_fontmapper.cpp @@ -0,0 +1,910 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/include/cfx_fontmapper.h" + +#include "core/fxge/include/ifx_systemfontinfo.h" +#include "core/fxge/include/fx_font.h" + +#include "third_party/base/stl_util.h" + +#define FX_FONT_STYLE_None 0x00 +#define FX_FONT_STYLE_Bold 0x01 +#define FX_FONT_STYLE_Italic 0x02 +#define FX_FONT_STYLE_BoldBold 0x04 + +namespace { + +const FX_CHAR* const g_Base14FontNames[14] = { + "Courier", + "Courier-Bold", + "Courier-BoldOblique", + "Courier-Oblique", + "Helvetica", + "Helvetica-Bold", + "Helvetica-BoldOblique", + "Helvetica-Oblique", + "Times-Roman", + "Times-Bold", + "Times-BoldItalic", + "Times-Italic", + "Symbol", + "ZapfDingbats", +}; + +const struct AltFontName { + const FX_CHAR* m_pName; + int m_Index; +} g_AltFontNames[] = { + {"Arial", 4}, + {"Arial,Bold", 5}, + {"Arial,BoldItalic", 6}, + {"Arial,Italic", 7}, + {"Arial-Bold", 5}, + {"Arial-BoldItalic", 6}, + {"Arial-BoldItalicMT", 6}, + {"Arial-BoldMT", 5}, + {"Arial-Italic", 7}, + {"Arial-ItalicMT", 7}, + {"ArialBold", 5}, + {"ArialBoldItalic", 6}, + {"ArialItalic", 7}, + {"ArialMT", 4}, + {"ArialMT,Bold", 5}, + {"ArialMT,BoldItalic", 6}, + {"ArialMT,Italic", 7}, + {"ArialRoundedMTBold", 5}, + {"Courier", 0}, + {"Courier,Bold", 1}, + {"Courier,BoldItalic", 2}, + {"Courier,Italic", 3}, + {"Courier-Bold", 1}, + {"Courier-BoldOblique", 2}, + {"Courier-Oblique", 3}, + {"CourierBold", 1}, + {"CourierBoldItalic", 2}, + {"CourierItalic", 3}, + {"CourierNew", 0}, + {"CourierNew,Bold", 1}, + {"CourierNew,BoldItalic", 2}, + {"CourierNew,Italic", 3}, + {"CourierNew-Bold", 1}, + {"CourierNew-BoldItalic", 2}, + {"CourierNew-Italic", 3}, + {"CourierNewBold", 1}, + {"CourierNewBoldItalic", 2}, + {"CourierNewItalic", 3}, + {"CourierNewPS-BoldItalicMT", 2}, + {"CourierNewPS-BoldMT", 1}, + {"CourierNewPS-ItalicMT", 3}, + {"CourierNewPSMT", 0}, + {"CourierStd", 0}, + {"CourierStd-Bold", 1}, + {"CourierStd-BoldOblique", 2}, + {"CourierStd-Oblique", 3}, + {"Helvetica", 4}, + {"Helvetica,Bold", 5}, + {"Helvetica,BoldItalic", 6}, + {"Helvetica,Italic", 7}, + {"Helvetica-Bold", 5}, + {"Helvetica-BoldItalic", 6}, + {"Helvetica-BoldOblique", 6}, + {"Helvetica-Italic", 7}, + {"Helvetica-Oblique", 7}, + {"HelveticaBold", 5}, + {"HelveticaBoldItalic", 6}, + {"HelveticaItalic", 7}, + {"Symbol", 12}, + {"SymbolMT", 12}, + {"Times-Bold", 9}, + {"Times-BoldItalic", 10}, + {"Times-Italic", 11}, + {"Times-Roman", 8}, + {"TimesBold", 9}, + {"TimesBoldItalic", 10}, + {"TimesItalic", 11}, + {"TimesNewRoman", 8}, + {"TimesNewRoman,Bold", 9}, + {"TimesNewRoman,BoldItalic", 10}, + {"TimesNewRoman,Italic", 11}, + {"TimesNewRoman-Bold", 9}, + {"TimesNewRoman-BoldItalic", 10}, + {"TimesNewRoman-Italic", 11}, + {"TimesNewRomanBold", 9}, + {"TimesNewRomanBoldItalic", 10}, + {"TimesNewRomanItalic", 11}, + {"TimesNewRomanPS", 8}, + {"TimesNewRomanPS-Bold", 9}, + {"TimesNewRomanPS-BoldItalic", 10}, + {"TimesNewRomanPS-BoldItalicMT", 10}, + {"TimesNewRomanPS-BoldMT", 9}, + {"TimesNewRomanPS-Italic", 11}, + {"TimesNewRomanPS-ItalicMT", 11}, + {"TimesNewRomanPSMT", 8}, + {"TimesNewRomanPSMT,Bold", 9}, + {"TimesNewRomanPSMT,BoldItalic", 10}, + {"TimesNewRomanPSMT,Italic", 11}, + {"ZapfDingbats", 13}, +}; + +const struct AltFontFamily { + const FX_CHAR* m_pFontName; + const FX_CHAR* m_pFontFamily; +} g_AltFontFamilies[] = { + {"AGaramondPro", "Adobe Garamond Pro"}, + {"BankGothicBT-Medium", "BankGothic Md BT"}, + {"ForteMT", "Forte"}, +}; + +const struct FX_FontStyle { + const FX_CHAR* style; + int32_t len; +} g_FontStyles[] = { + {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7}, +}; + +const struct CODEPAGE_MAP { + uint16_t codepage; + uint8_t charset; +} g_Codepage2CharsetTable[] = { + {0, 1}, {42, 2}, {437, 254}, {850, 255}, {874, 222}, + {932, 128}, {936, 134}, {949, 129}, {950, 136}, {1250, 238}, + {1251, 204}, {1252, 0}, {1253, 161}, {1254, 162}, {1255, 177}, + {1256, 178}, {1257, 186}, {1258, 163}, {1361, 130}, {10000, 77}, + {10001, 78}, {10002, 81}, {10003, 79}, {10004, 84}, {10005, 83}, + {10006, 85}, {10007, 89}, {10008, 80}, {10021, 87}, {10029, 88}, + {10081, 86}, +}; + +int CompareFontFamilyString(const void* key, const void* element) { + CFX_ByteString str_key((const FX_CHAR*)key); + if (str_key.Find(((AltFontFamily*)element)->m_pFontName) != -1) { + return 0; + } + return FXSYS_stricmp((const FX_CHAR*)key, + ((AltFontFamily*)element)->m_pFontName); +} + +int CompareString(const void* key, const void* element) { + return FXSYS_stricmp((const FX_CHAR*)key, ((AltFontName*)element)->m_pName); +} + +CFX_ByteString TT_NormalizeName(const FX_CHAR* family) { + CFX_ByteString norm(family); + norm.Remove(' '); + norm.Remove('-'); + norm.Remove(','); + int pos = norm.Find('+'); + if (pos > 0) { + norm = norm.Left(pos); + } + norm.MakeLower(); + return norm; +} + +uint8_t GetCharsetFromCodePage(uint16_t codepage) { + const CODEPAGE_MAP* pEnd = + g_Codepage2CharsetTable + FX_ArraySize(g_Codepage2CharsetTable); + const CODEPAGE_MAP* pCharmap = + std::lower_bound(g_Codepage2CharsetTable, pEnd, codepage, + [](const CODEPAGE_MAP& charset, uint16_t page) { + return charset.codepage < page; + }); + if (pCharmap < pEnd && codepage == pCharmap->codepage) + return pCharmap->charset; + return FXFONT_DEFAULT_CHARSET; +} + +CFX_ByteString GetFontFamily(CFX_ByteString fontName, int nStyle) { + if (fontName.Find("Script") >= 0) { + if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) { + fontName = "ScriptMTBold"; + } else if (fontName.Find("Palace") >= 0) { + fontName = "PalaceScriptMT"; + } else if (fontName.Find("French") >= 0) { + fontName = "FrenchScriptMT"; + } else if (fontName.Find("FreeStyle") >= 0) { + fontName = "FreeStyleScript"; + } + return fontName; + } + AltFontFamily* found = (AltFontFamily*)FXSYS_bsearch( + fontName.c_str(), g_AltFontFamilies, + sizeof g_AltFontFamilies / sizeof(AltFontFamily), sizeof(AltFontFamily), + CompareFontFamilyString); + return found ? CFX_ByteString(found->m_pFontFamily) : fontName; +} + +CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex) { + CFX_ByteTextBuf buf; + if (!iLen || iLen <= iIndex) { + return buf.MakeString(); + } + while (iIndex < iLen) { + if (pStyle[iIndex] == ',') { + break; + } + buf.AppendChar(pStyle[iIndex]); + ++iIndex; + } + return buf.MakeString(); +} + +int32_t GetStyleType(const CFX_ByteString& bsStyle, FX_BOOL bRevert) { + int32_t iLen = bsStyle.GetLength(); + if (!iLen) { + return -1; + } + int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle); + const FX_FontStyle* pStyle = nullptr; + for (int i = iSize - 1; i >= 0; --i) { + pStyle = g_FontStyles + i; + if (!pStyle || pStyle->len > iLen) { + continue; + } + if (!bRevert) { + if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) { + return i; + } + } else { + if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) { + return i; + } + } + } + return -1; +} + +FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) { + if (name == "MyriadPro") { + PitchFamily &= ~FXFONT_FF_ROMAN; + return TRUE; + } + return FALSE; +} + +} // namespace + +CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) + : m_bListLoaded(FALSE), m_pFontMgr(mgr) { + m_MMFaces[0] = nullptr; + m_MMFaces[1] = nullptr; + FXSYS_memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces)); +} + +CFX_FontMapper::~CFX_FontMapper() { + for (size_t i = 0; i < FX_ArraySize(m_FoxitFaces); ++i) { + if (m_FoxitFaces[i]) + FXFT_Done_Face(m_FoxitFaces[i]); + } + if (m_MMFaces[0]) + FXFT_Done_Face(m_MMFaces[0]); + if (m_MMFaces[1]) + FXFT_Done_Face(m_MMFaces[1]); +} + +void CFX_FontMapper::SetSystemFontInfo( + std::unique_ptr<IFX_SystemFontInfo> pFontInfo) { + if (!pFontInfo) + return; + + m_pFontInfo = std::move(pFontInfo); +} + +CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) { + if (!m_pFontInfo) + return CFX_ByteString(); + + uint32_t size = m_pFontInfo->GetFontData(hFont, kTableNAME, nullptr, 0); + if (!size) + return CFX_ByteString(); + + std::vector<uint8_t> buffer(size); + uint8_t* buffer_ptr = buffer.data(); + uint32_t bytes_read = + m_pFontInfo->GetFontData(hFont, kTableNAME, buffer_ptr, size); + return bytes_read == size ? GetNameFromTT(buffer_ptr, bytes_read, 6) + : CFX_ByteString(); +} + +void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) { + if (!m_pFontInfo) + return; + + m_FaceArray.push_back({name, static_cast<uint32_t>(charset)}); + if (name == m_LastFamily) + return; + + const uint8_t* ptr = name.raw_str(); + FX_BOOL bLocalized = FALSE; + for (int i = 0; i < name.GetLength(); i++) { + if (ptr[i] > 0x80) { + bLocalized = TRUE; + break; + } + } + + if (bLocalized) { + void* hFont = m_pFontInfo->GetFont(name.c_str()); + if (!hFont) { + int iExact; + hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, + name.c_str(), iExact); + if (!hFont) + return; + } + + CFX_ByteString new_name = GetPSNameFromTT(hFont); + if (!new_name.IsEmpty()) { + new_name.Insert(0, ' '); + m_InstalledTTFonts.push_back(new_name); + } + m_pFontInfo->DeleteFont(hFont); + } + m_InstalledTTFonts.push_back(name); + m_LastFamily = name; +} + +void CFX_FontMapper::LoadInstalledFonts() { + if (!m_pFontInfo || m_bListLoaded) + return; + + m_pFontInfo->EnumFontList(this); + m_bListLoaded = TRUE; +} + +CFX_ByteString CFX_FontMapper::MatchInstalledFonts( + const CFX_ByteString& norm_name) { + LoadInstalledFonts(); + int i; + for (i = pdfium::CollectionSize<int>(m_InstalledTTFonts) - 1; i >= 0; i--) { + CFX_ByteString norm1 = TT_NormalizeName(m_InstalledTTFonts[i].c_str()); + if (norm1 == norm_name) { + break; + } + } + if (i < 0) { + return CFX_ByteString(); + } + CFX_ByteString match = m_InstalledTTFonts[i]; + if (match[0] == ' ') { + match = m_InstalledTTFonts[i + 1]; + } + return match; +} + +FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, + int iBaseFont, + int italic_angle, + int weight, + int picthfamily) { + if (iBaseFont < 12) { + if (m_FoxitFaces[iBaseFont]) { + return m_FoxitFaces[iBaseFont]; + } + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + if (m_pFontMgr->GetBuiltinFont(iBaseFont, &pFontData, &size)) { + m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[iBaseFont]; + } + } + pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM; + pSubstFont->m_ItalicAngle = italic_angle; + if (weight) { + pSubstFont->m_Weight = weight; + } + if (picthfamily & FXFONT_FF_ROMAN) { + pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; + pSubstFont->m_Family = "Chrome Serif"; + if (m_MMFaces[1]) { + return m_MMFaces[1]; + } + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + m_pFontMgr->GetBuiltinFont(14, &pFontData, &size); + m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_MMFaces[1]; + } + pSubstFont->m_Family = "Chrome Sans"; + if (m_MMFaces[0]) { + return m_MMFaces[0]; + } + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + m_pFontMgr->GetBuiltinFont(15, &pFontData, &size); + m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_MMFaces[0]; +} + +FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, + FX_BOOL bTrueType, + uint32_t flags, + int weight, + int italic_angle, + int WindowCP, + CFX_SubstFont* pSubstFont) { + if (!(flags & FXFONT_USEEXTERNATTR)) { + weight = FXFONT_FW_NORMAL; + italic_angle = 0; + } + CFX_ByteString SubstName = name; + SubstName.Remove(0x20); + if (bTrueType) { + if (name[0] == '@') { + SubstName = name.Mid(1); + } + } + PDF_GetStandardFontName(&SubstName); + if (SubstName == "Symbol" && !bTrueType) { + pSubstFont->m_Family = "Chrome Symbol"; + pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + if (m_FoxitFaces[12]) { + return m_FoxitFaces[12]; + } + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + m_pFontMgr->GetBuiltinFont(12, &pFontData, &size); + m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[12]; + } + if (SubstName == "ZapfDingbats") { + pSubstFont->m_Family = "Chrome Dingbats"; + pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + if (m_FoxitFaces[13]) { + return m_FoxitFaces[13]; + } + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + m_pFontMgr->GetBuiltinFont(13, &pFontData, &size); + m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[13]; + } + int iBaseFont = 0; + CFX_ByteString family, style; + FX_BOOL bHasComma = FALSE; + FX_BOOL bHasHypen = FALSE; + int find = SubstName.Find(",", 0); + if (find >= 0) { + family = SubstName.Left(find); + PDF_GetStandardFontName(&family); + style = SubstName.Mid(find + 1); + bHasComma = TRUE; + } else { + family = SubstName; + } + for (; iBaseFont < 12; iBaseFont++) + if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) { + break; + } + int PitchFamily = 0; + FX_BOOL bItalic = FALSE; + uint32_t nStyle = 0; + FX_BOOL bStyleAvail = FALSE; + if (iBaseFont < 12) { + family = g_Base14FontNames[iBaseFont]; + if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) { + nStyle |= FX_FONT_STYLE_Bold; + } + if ((iBaseFont % 4) / 2) { + nStyle |= FX_FONT_STYLE_Italic; + } + if (iBaseFont < 4) { + PitchFamily |= FXFONT_FF_FIXEDPITCH; + } + if (iBaseFont >= 8) { + PitchFamily |= FXFONT_FF_ROMAN; + } + } else { + if (!bHasComma) { + find = family.ReverseFind('-'); + if (find >= 0) { + style = family.Mid(find + 1); + family = family.Left(find); + bHasHypen = TRUE; + } + } + if (!bHasHypen) { + int nLen = family.GetLength(); + int32_t nRet = GetStyleType(family, TRUE); + if (nRet > -1) { + family = family.Left(nLen - g_FontStyles[nRet].len); + if (nRet == 0) { + nStyle |= FX_FONT_STYLE_Bold; + } + if (nRet == 1) { + nStyle |= FX_FONT_STYLE_Italic; + } + if (nRet == 2) { + nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic); + } + } + } + if (flags & FXFONT_SERIF) { + PitchFamily |= FXFONT_FF_ROMAN; + } + if (flags & FXFONT_SCRIPT) { + PitchFamily |= FXFONT_FF_SCRIPT; + } + if (flags & FXFONT_FIXED_PITCH) { + PitchFamily |= FXFONT_FF_FIXEDPITCH; + } + } + if (!style.IsEmpty()) { + int nLen = style.GetLength(); + const FX_CHAR* pStyle = style.c_str(); + int i = 0; + FX_BOOL bFirstItem = TRUE; + CFX_ByteString buf; + while (i < nLen) { + buf = ParseStyle(pStyle, nLen, i); + int32_t nRet = GetStyleType(buf, FALSE); + if ((i && !bStyleAvail) || (!i && nRet < 0)) { + family = SubstName; + iBaseFont = 12; + break; + } else if (nRet >= 0) { + bStyleAvail = TRUE; + } + if (nRet == 0) { + if (nStyle & FX_FONT_STYLE_Bold) { + nStyle |= FX_FONT_STYLE_BoldBold; + } else { + nStyle |= FX_FONT_STYLE_Bold; + } + bFirstItem = FALSE; + } + if (nRet == 1) { + if (bFirstItem) { + nStyle |= FX_FONT_STYLE_Italic; + } else { + family = SubstName; + iBaseFont = 12; + } + break; + } + if (nRet == 2) { + nStyle |= FX_FONT_STYLE_Italic; + if (nStyle & FX_FONT_STYLE_Bold) { + nStyle |= FX_FONT_STYLE_BoldBold; + } else { + nStyle |= FX_FONT_STYLE_Bold; + } + bFirstItem = FALSE; + } + i += buf.GetLength() + 1; + } + } + weight = weight ? weight : FXFONT_FW_NORMAL; + int old_weight = weight; + if (nStyle) { + weight = + nStyle & FX_FONT_STYLE_BoldBold + ? 900 + : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); + } + if (nStyle & FX_FONT_STYLE_Italic) { + bItalic = TRUE; + } + FX_BOOL bCJK = FALSE; + int iExact = 0; + int Charset = FXFONT_ANSI_CHARSET; + if (WindowCP) { + Charset = GetCharsetFromCodePage(WindowCP); + } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) { + Charset = FXFONT_SYMBOL_CHARSET; + } + if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET || + Charset == FXFONT_HANGEUL_CHARSET || + Charset == FXFONT_CHINESEBIG5_CHARSET) { + bCJK = TRUE; + } + if (!m_pFontInfo) { + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + family = GetFontFamily(family, nStyle); + CFX_ByteString match = MatchInstalledFonts(TT_NormalizeName(family.c_str())); + if (match.IsEmpty() && family != SubstName && + (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) { + match = MatchInstalledFonts(TT_NormalizeName(SubstName.c_str())); + } + if (match.IsEmpty() && iBaseFont >= 12) { + if (!bCJK) { + if (!CheckSupportThirdPartFont(family, PitchFamily)) { + if (italic_angle != 0) { + bItalic = TRUE; + } else { + bItalic = FALSE; + } + weight = old_weight; + } + } else { + pSubstFont->m_bSubstCJK = true; + if (nStyle) { + pSubstFont->m_WeightCJK = weight; + } else { + pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL; + } + if (nStyle & FX_FONT_STYLE_Italic) { + pSubstFont->m_bItalicCJK = true; + } + } + } else { + italic_angle = 0; + weight = + nStyle & FX_FONT_STYLE_BoldBold + ? 900 + : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); + } + if (!match.IsEmpty() || iBaseFont < 12) { + if (!match.IsEmpty()) { + family = match; + } + if (iBaseFont < 12) { + if (nStyle && !(iBaseFont % 4)) { + if ((nStyle & 0x3) == 1) { + iBaseFont += 1; + } + if ((nStyle & 0x3) == 2) { + iBaseFont += 3; + } + if ((nStyle & 0x3) == 3) { + iBaseFont += 2; + } + } + family = g_Base14FontNames[iBaseFont]; + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + } + } else { + if (flags & FXFONT_ITALIC) { + bItalic = TRUE; + } + } + iExact = !match.IsEmpty(); + void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, + family.c_str(), iExact); + if (iExact) { + pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT; + } + if (!hFont) { +#ifdef PDF_ENABLE_XFA + if (flags & FXFONT_EXACTMATCH) { + return nullptr; + } +#endif // PDF_ENABLE_XFA + if (bCJK) { + if (italic_angle != 0) { + bItalic = TRUE; + } else { + bItalic = FALSE; + } + weight = old_weight; + } + if (!match.IsEmpty()) { + hFont = m_pFontInfo->GetFont(match.c_str()); + if (!hFont) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + } else { + if (Charset == FXFONT_SYMBOL_CHARSET) { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ + _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ + if (SubstName == "Symbol") { + pSubstFont->m_Family = "Chrome Symbol"; + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; + if (m_FoxitFaces[12]) { + return m_FoxitFaces[12]; + } + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + m_pFontMgr->GetBuiltinFont(12, &pFontData, &size); + m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[12]; + } +#endif + pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL; + return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, + weight, italic_angle, 0, pSubstFont); + } + if (Charset == FXFONT_ANSI_CHARSET) { + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + + auto it = + std::find_if(m_FaceArray.begin(), m_FaceArray.end(), + [Charset](const FaceData& face) { + return face.charset == static_cast<uint32_t>(Charset); + }); + if (it == m_FaceArray.end()) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + hFont = m_pFontInfo->GetFont(it->name.c_str()); + } + } + pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont); + if (!hFont) + return nullptr; + + m_pFontInfo->GetFaceName(hFont, SubstName); + if (Charset == FXFONT_DEFAULT_CHARSET) { + m_pFontInfo->GetFontCharset(hFont, Charset); + } + uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, kTableTTCF, nullptr, 0); + uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); + if (font_size == 0 && ttc_size == 0) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + FXFT_Face face = nullptr; + if (ttc_size) { + uint8_t temp[1024]; + m_pFontInfo->GetFontData(hFont, kTableTTCF, temp, 1024); + uint32_t checksum = 0; + for (int i = 0; i < 256; i++) { + checksum += ((uint32_t*)temp)[i]; + } + uint8_t* pFontData; + face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, + ttc_size - font_size, pFontData); + if (!face) { + pFontData = FX_Alloc(uint8_t, ttc_size); + m_pFontInfo->GetFontData(hFont, kTableTTCF, pFontData, ttc_size); + face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, + ttc_size, ttc_size - font_size); + } + } else { + uint8_t* pFontData; + face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); + if (!face) { + pFontData = FX_Alloc(uint8_t, font_size); + m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); + face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, + font_size, + m_pFontInfo->GetFaceIndex(hFont)); + } + } + if (!face) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + pSubstFont->m_Family = SubstName; + pSubstFont->m_Charset = Charset; + FX_BOOL bNeedUpdateWeight = FALSE; + if (FXFT_Is_Face_Bold(face)) { + if (weight == FXFONT_FW_BOLD) { + bNeedUpdateWeight = FALSE; + } else { + bNeedUpdateWeight = TRUE; + } + } else { + if (weight == FXFONT_FW_NORMAL) { + bNeedUpdateWeight = FALSE; + } else { + bNeedUpdateWeight = TRUE; + } + } + if (bNeedUpdateWeight) { + pSubstFont->m_Weight = weight; + } + if (bItalic && !FXFT_Is_Face_Italic(face)) { + if (italic_angle == 0) { + italic_angle = -12; + } else if (FXSYS_abs(italic_angle) < 5) { + italic_angle = 0; + } + pSubstFont->m_ItalicAngle = italic_angle; + } + m_pFontInfo->DeleteFont(hFont); + return face; +} +#ifdef PDF_ENABLE_XFA +FXFT_Face CFX_FontMapper::FindSubstFontByUnicode(uint32_t dwUnicode, + uint32_t flags, + int weight, + int italic_angle) { + if (!m_pFontInfo) + return nullptr; + + FX_BOOL bItalic = (flags & FXFONT_ITALIC) != 0; + int PitchFamily = 0; + if (flags & FXFONT_SERIF) { + PitchFamily |= FXFONT_FF_ROMAN; + } + if (flags & FXFONT_SCRIPT) { + PitchFamily |= FXFONT_FF_SCRIPT; + } + if (flags & FXFONT_FIXED_PITCH) { + PitchFamily |= FXFONT_FF_FIXEDPITCH; + } + void* hFont = + m_pFontInfo->MapFontByUnicode(dwUnicode, weight, bItalic, PitchFamily); + if (!hFont) + return nullptr; + + uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, nullptr, 0); + uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); + if (font_size == 0 && ttc_size == 0) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + FXFT_Face face = nullptr; + if (ttc_size) { + uint8_t temp[1024]; + m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024); + uint32_t checksum = 0; + for (int i = 0; i < 256; i++) { + checksum += ((uint32_t*)temp)[i]; + } + uint8_t* pFontData; + face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, + ttc_size - font_size, pFontData); + if (!face) { + pFontData = FX_Alloc(uint8_t, ttc_size); + if (pFontData) { + m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size); + face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, + ttc_size, ttc_size - font_size); + } + } + } else { + CFX_ByteString SubstName; + m_pFontInfo->GetFaceName(hFont, SubstName); + uint8_t* pFontData; + face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); + if (!face) { + pFontData = FX_Alloc(uint8_t, font_size); + if (!pFontData) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); + face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, + font_size, + m_pFontInfo->GetFaceIndex(hFont)); + } + } + m_pFontInfo->DeleteFont(hFont); + return face; +} +#endif // PDF_ENABLE_XFA + +int CFX_FontMapper::GetFaceSize() const { + return pdfium::CollectionSize<int>(m_FaceArray); +} + +FX_BOOL CFX_FontMapper::IsBuiltinFace(const FXFT_Face face) const { + for (size_t i = 0; i < MM_FACE_COUNT; ++i) { + if (m_MMFaces[i] == face) { + return TRUE; + } + } + for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) { + if (m_FoxitFaces[i] == face) { + return TRUE; + } + } + return FALSE; +} + +int PDF_GetStandardFontName(CFX_ByteString* name) { + AltFontName* found = static_cast<AltFontName*>( + FXSYS_bsearch(name->c_str(), g_AltFontNames, FX_ArraySize(g_AltFontNames), + sizeof(AltFontName), CompareString)); + if (!found) + return -1; + + *name = g_Base14FontNames[found->m_Index]; + return found->m_Index; +} diff --git a/core/fxge/ge/cfx_fontmgr.cpp b/core/fxge/ge/cfx_fontmgr.cpp new file mode 100644 index 0000000000..3f03988cb7 --- /dev/null +++ b/core/fxge/ge/cfx_fontmgr.cpp @@ -0,0 +1,257 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/include/cfx_fontmgr.h" + +#include "core/fxge/fontdata/chromefontdata/chromefontdata.h" +#include "core/fxge/include/cfx_fontmapper.h" +#include "core/fxge/include/ifx_systemfontinfo.h" +#include "core/fxge/include/fx_font.h" + +namespace { + +struct BuiltinFont { + const uint8_t* m_pFontData; + uint32_t m_dwSize; +}; + +const BuiltinFont g_FoxitFonts[14] = { + {g_FoxitFixedFontData, 17597}, + {g_FoxitFixedBoldFontData, 18055}, + {g_FoxitFixedBoldItalicFontData, 19151}, + {g_FoxitFixedItalicFontData, 18746}, + {g_FoxitSansFontData, 15025}, + {g_FoxitSansBoldFontData, 16344}, + {g_FoxitSansBoldItalicFontData, 16418}, + {g_FoxitSansItalicFontData, 16339}, + {g_FoxitSerifFontData, 19469}, + {g_FoxitSerifBoldFontData, 19395}, + {g_FoxitSerifBoldItalicFontData, 20733}, + {g_FoxitSerifItalicFontData, 21227}, + {g_FoxitSymbolFontData, 16729}, + {g_FoxitDingbatsFontData, 29513}, +}; + +const BuiltinFont g_MMFonts[2] = { + {g_FoxitSerifMMFontData, 113417}, + {g_FoxitSansMMFontData, 66919}, +}; + +CFX_ByteString KeyNameFromFace(const CFX_ByteString& face_name, + int weight, + FX_BOOL bItalic) { + CFX_ByteString key(face_name); + key += ','; + key += CFX_ByteString::FormatInteger(weight); + key += bItalic ? 'I' : 'N'; + return key; +} + +CFX_ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) { + CFX_ByteString key; + key.Format("%d:%d", ttc_size, checksum); + return key; +} + +int GetTTCIndex(const uint8_t* pFontData, + uint32_t ttc_size, + uint32_t font_offset) { + int face_index = 0; + const uint8_t* p = pFontData + 8; + uint32_t nfont = GET_TT_LONG(p); + uint32_t index; + for (index = 0; index < nfont; index++) { + p = pFontData + 12 + index * 4; + if (GET_TT_LONG(p) == font_offset) + break; + } + if (index >= nfont) + face_index = 0; + else + face_index = index; + return face_index; +} + +} // namespace + +CFX_FontMgr::CFX_FontMgr() + : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) { + m_pBuiltinMapper.reset(new CFX_FontMapper(this)); +} + +CFX_FontMgr::~CFX_FontMgr() { + for (const auto& pair : m_FaceMap) + delete pair.second; + + // |m_pBuiltinMapper| references |m_FTLibrary|, so it has to be destroyed + // first. + m_pBuiltinMapper.reset(); + FXFT_Done_FreeType(m_FTLibrary); +} + +void CFX_FontMgr::InitFTLibrary() { + if (m_FTLibrary) + return; + FXFT_Init_FreeType(&m_FTLibrary); + m_FTLibrarySupportsHinting = + FXFT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) != + FT_Err_Unimplemented_Feature; +} + +void CFX_FontMgr::SetSystemFontInfo( + std::unique_ptr<IFX_SystemFontInfo> pFontInfo) { + m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo)); +} + +FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, + FX_BOOL bTrueType, + uint32_t flags, + int weight, + int italic_angle, + int CharsetCP, + CFX_SubstFont* pSubstFont) { + InitFTLibrary(); + return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, + italic_angle, CharsetCP, pSubstFont); +} + +FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name, + int weight, + FX_BOOL bItalic, + uint8_t*& pFontData) { + auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic)); + if (it == m_FaceMap.end()) + return nullptr; + + CTTFontDesc* pFontDesc = it->second; + pFontData = pFontDesc->m_pFontData; + pFontDesc->m_RefCount++; + return pFontDesc->m_SingleFace.m_pFace; +} + +FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name, + int weight, + FX_BOOL bItalic, + uint8_t* pData, + uint32_t size, + int face_index) { + CTTFontDesc* pFontDesc = new CTTFontDesc; + pFontDesc->m_Type = 1; + pFontDesc->m_SingleFace.m_pFace = nullptr; + pFontDesc->m_SingleFace.m_bBold = weight; + pFontDesc->m_SingleFace.m_bItalic = bItalic; + pFontDesc->m_pFontData = pData; + pFontDesc->m_RefCount = 1; + + InitFTLibrary(); + FXFT_Library library = m_FTLibrary; + int ret = FXFT_New_Memory_Face(library, pData, size, face_index, + &pFontDesc->m_SingleFace.m_pFace); + if (ret) { + delete pFontDesc; + return nullptr; + } + ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace.m_pFace, 64, 64); + if (ret) { + delete pFontDesc; + return nullptr; + } + m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = pFontDesc; + return pFontDesc->m_SingleFace.m_pFace; +} + +FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, + uint32_t checksum, + int font_offset, + uint8_t*& pFontData) { + auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum)); + if (it == m_FaceMap.end()) + return nullptr; + + CTTFontDesc* pFontDesc = it->second; + pFontData = pFontDesc->m_pFontData; + pFontDesc->m_RefCount++; + int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); + if (!pFontDesc->m_TTCFace.m_pFaces[face_index]) { + pFontDesc->m_TTCFace.m_pFaces[face_index] = + GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); + } + return pFontDesc->m_TTCFace.m_pFaces[face_index]; +} + +FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, + uint32_t checksum, + uint8_t* pData, + uint32_t size, + int font_offset) { + CTTFontDesc* pFontDesc = new CTTFontDesc; + pFontDesc->m_Type = 2; + pFontDesc->m_pFontData = pData; + for (int i = 0; i < 16; i++) + pFontDesc->m_TTCFace.m_pFaces[i] = nullptr; + pFontDesc->m_RefCount++; + m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = pFontDesc; + int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); + pFontDesc->m_TTCFace.m_pFaces[face_index] = + GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); + return pFontDesc->m_TTCFace.m_pFaces[face_index]; +} + +FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, + uint32_t size, + int face_index) { + InitFTLibrary(); + FXFT_Library library = m_FTLibrary; + FXFT_Face face = nullptr; + if (FXFT_New_Memory_Face(library, pData, size, face_index, &face)) + return nullptr; + return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; +} + +FXFT_Face CFX_FontMgr::GetFileFace(const FX_CHAR* filename, int face_index) { + InitFTLibrary(); + FXFT_Library library = m_FTLibrary; + FXFT_Face face = nullptr; + if (FXFT_New_Face(library, filename, face_index, &face)) + return nullptr; + return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; +} + +void CFX_FontMgr::ReleaseFace(FXFT_Face face) { + if (!face) + return; + FX_BOOL bNeedFaceDone = TRUE; + auto it = m_FaceMap.begin(); + while (it != m_FaceMap.end()) { + auto temp = it++; + int nRet = temp->second->ReleaseFace(face); + if (nRet == -1) + continue; + bNeedFaceDone = FALSE; + if (nRet == 0) + m_FaceMap.erase(temp); + break; + } + if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face)) + FXFT_Done_Face(face); +} + +bool CFX_FontMgr::GetBuiltinFont(size_t index, + const uint8_t** pFontData, + uint32_t* size) { + if (index < FX_ArraySize(g_FoxitFonts)) { + *pFontData = g_FoxitFonts[index].m_pFontData; + *size = g_FoxitFonts[index].m_dwSize; + return true; + } + index -= FX_ArraySize(g_FoxitFonts); + if (index < FX_ArraySize(g_MMFonts)) { + *pFontData = g_MMFonts[index].m_pFontData; + *size = g_MMFonts[index].m_dwSize; + return true; + } + return false; +} diff --git a/core/fxge/ge/fx_ge.cpp b/core/fxge/ge/fx_ge.cpp index fe0cc2c3eb..0a1b1ab041 100644 --- a/core/fxge/ge/fx_ge.cpp +++ b/core/fxge/ge/fx_ge.cpp @@ -6,7 +6,9 @@ #include "core/fxge/include/fx_ge.h" +#include "core/fxge/ge/cfx_folderfontinfo.h" #include "core/fxge/ge/fx_text_int.h" +#include "core/fxge/include/cfx_fontmgr.h" namespace { diff --git a/core/fxge/ge/fx_ge_font.cpp b/core/fxge/ge/fx_ge_font.cpp index 1aa5f9fd1a..bbbe10adb8 100644 --- a/core/fxge/ge/fx_ge_font.cpp +++ b/core/fxge/ge/fx_ge_font.cpp @@ -7,6 +7,7 @@ #include "core/fxge/include/fx_font.h" #include "core/fpdfapi/fpdf_font/include/cpdf_font.h" +#include "core/fxge/include/cfx_fontmgr.h" #include "core/fxge/ge/fx_text_int.h" #include "core/fxge/include/fx_freetype.h" #include "core/fxge/include/fx_ge.h" diff --git a/core/fxge/ge/fx_ge_fontmap.cpp b/core/fxge/ge/fx_ge_fontmap.cpp index cc7e9f1aa2..70fcd88e2e 100644 --- a/core/fxge/ge/fx_ge_fontmap.cpp +++ b/core/fxge/ge/fx_ge_fontmap.cpp @@ -4,411 +4,9 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#include <algorithm> -#include <limits> -#include <utility> -#include <vector> - -#include "core/fxge/include/fx_font.h" - -#include "core/fxge/fontdata/chromefontdata/chromefontdata.h" -#include "core/fxge/include/fx_freetype.h" +#include "core/fxge/include/cfx_fontmapper.h" +#include "core/fxge/include/ifx_systemfontinfo.h" #include "core/fxge/include/fx_ge.h" -#include "third_party/base/stl_util.h" - -#define GET_TT_SHORT(w) (uint16_t)(((w)[0] << 8) | (w)[1]) -#define GET_TT_LONG(w) \ - (uint32_t)(((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) - -#define FX_FONT_STYLE_None 0x00 -#define FX_FONT_STYLE_Bold 0x01 -#define FX_FONT_STYLE_Italic 0x02 -#define FX_FONT_STYLE_BoldBold 0x04 - -namespace { - -struct BuiltinFont { - const uint8_t* m_pFontData; - uint32_t m_dwSize; -}; - -const BuiltinFont g_FoxitFonts[14] = { - {g_FoxitFixedFontData, 17597}, - {g_FoxitFixedBoldFontData, 18055}, - {g_FoxitFixedBoldItalicFontData, 19151}, - {g_FoxitFixedItalicFontData, 18746}, - {g_FoxitSansFontData, 15025}, - {g_FoxitSansBoldFontData, 16344}, - {g_FoxitSansBoldItalicFontData, 16418}, - {g_FoxitSansItalicFontData, 16339}, - {g_FoxitSerifFontData, 19469}, - {g_FoxitSerifBoldFontData, 19395}, - {g_FoxitSerifBoldItalicFontData, 20733}, - {g_FoxitSerifItalicFontData, 21227}, - {g_FoxitSymbolFontData, 16729}, - {g_FoxitDingbatsFontData, 29513}, -}; - -const BuiltinFont g_MMFonts[2] = { - {g_FoxitSerifMMFontData, 113417}, - {g_FoxitSansMMFontData, 66919}, -}; - -const FX_CHAR* const g_Base14FontNames[14] = { - "Courier", - "Courier-Bold", - "Courier-BoldOblique", - "Courier-Oblique", - "Helvetica", - "Helvetica-Bold", - "Helvetica-BoldOblique", - "Helvetica-Oblique", - "Times-Roman", - "Times-Bold", - "Times-BoldItalic", - "Times-Italic", - "Symbol", - "ZapfDingbats", -}; - -const struct AltFontName { - const FX_CHAR* m_pName; - int m_Index; -} g_AltFontNames[] = { - {"Arial", 4}, - {"Arial,Bold", 5}, - {"Arial,BoldItalic", 6}, - {"Arial,Italic", 7}, - {"Arial-Bold", 5}, - {"Arial-BoldItalic", 6}, - {"Arial-BoldItalicMT", 6}, - {"Arial-BoldMT", 5}, - {"Arial-Italic", 7}, - {"Arial-ItalicMT", 7}, - {"ArialBold", 5}, - {"ArialBoldItalic", 6}, - {"ArialItalic", 7}, - {"ArialMT", 4}, - {"ArialMT,Bold", 5}, - {"ArialMT,BoldItalic", 6}, - {"ArialMT,Italic", 7}, - {"ArialRoundedMTBold", 5}, - {"Courier", 0}, - {"Courier,Bold", 1}, - {"Courier,BoldItalic", 2}, - {"Courier,Italic", 3}, - {"Courier-Bold", 1}, - {"Courier-BoldOblique", 2}, - {"Courier-Oblique", 3}, - {"CourierBold", 1}, - {"CourierBoldItalic", 2}, - {"CourierItalic", 3}, - {"CourierNew", 0}, - {"CourierNew,Bold", 1}, - {"CourierNew,BoldItalic", 2}, - {"CourierNew,Italic", 3}, - {"CourierNew-Bold", 1}, - {"CourierNew-BoldItalic", 2}, - {"CourierNew-Italic", 3}, - {"CourierNewBold", 1}, - {"CourierNewBoldItalic", 2}, - {"CourierNewItalic", 3}, - {"CourierNewPS-BoldItalicMT", 2}, - {"CourierNewPS-BoldMT", 1}, - {"CourierNewPS-ItalicMT", 3}, - {"CourierNewPSMT", 0}, - {"CourierStd", 0}, - {"CourierStd-Bold", 1}, - {"CourierStd-BoldOblique", 2}, - {"CourierStd-Oblique", 3}, - {"Helvetica", 4}, - {"Helvetica,Bold", 5}, - {"Helvetica,BoldItalic", 6}, - {"Helvetica,Italic", 7}, - {"Helvetica-Bold", 5}, - {"Helvetica-BoldItalic", 6}, - {"Helvetica-BoldOblique", 6}, - {"Helvetica-Italic", 7}, - {"Helvetica-Oblique", 7}, - {"HelveticaBold", 5}, - {"HelveticaBoldItalic", 6}, - {"HelveticaItalic", 7}, - {"Symbol", 12}, - {"SymbolMT", 12}, - {"Times-Bold", 9}, - {"Times-BoldItalic", 10}, - {"Times-Italic", 11}, - {"Times-Roman", 8}, - {"TimesBold", 9}, - {"TimesBoldItalic", 10}, - {"TimesItalic", 11}, - {"TimesNewRoman", 8}, - {"TimesNewRoman,Bold", 9}, - {"TimesNewRoman,BoldItalic", 10}, - {"TimesNewRoman,Italic", 11}, - {"TimesNewRoman-Bold", 9}, - {"TimesNewRoman-BoldItalic", 10}, - {"TimesNewRoman-Italic", 11}, - {"TimesNewRomanBold", 9}, - {"TimesNewRomanBoldItalic", 10}, - {"TimesNewRomanItalic", 11}, - {"TimesNewRomanPS", 8}, - {"TimesNewRomanPS-Bold", 9}, - {"TimesNewRomanPS-BoldItalic", 10}, - {"TimesNewRomanPS-BoldItalicMT", 10}, - {"TimesNewRomanPS-BoldMT", 9}, - {"TimesNewRomanPS-Italic", 11}, - {"TimesNewRomanPS-ItalicMT", 11}, - {"TimesNewRomanPSMT", 8}, - {"TimesNewRomanPSMT,Bold", 9}, - {"TimesNewRomanPSMT,BoldItalic", 10}, - {"TimesNewRomanPSMT,Italic", 11}, - {"ZapfDingbats", 13}, -}; - -const struct { - const FX_CHAR* m_pName; - const FX_CHAR* m_pSubstName; -} Base14Substs[] = { - {"Courier", "Courier New"}, - {"Courier-Bold", "Courier New Bold"}, - {"Courier-BoldOblique", "Courier New Bold Italic"}, - {"Courier-Oblique", "Courier New Italic"}, - {"Helvetica", "Arial"}, - {"Helvetica-Bold", "Arial Bold"}, - {"Helvetica-BoldOblique", "Arial Bold Italic"}, - {"Helvetica-Oblique", "Arial Italic"}, - {"Times-Roman", "Times New Roman"}, - {"Times-Bold", "Times New Roman Bold"}, - {"Times-BoldItalic", "Times New Roman Bold Italic"}, - {"Times-Italic", "Times New Roman Italic"}, -}; - -const struct AltFontFamily { - const FX_CHAR* m_pFontName; - const FX_CHAR* m_pFontFamily; -} g_AltFontFamilies[] = { - {"AGaramondPro", "Adobe Garamond Pro"}, - {"BankGothicBT-Medium", "BankGothic Md BT"}, - {"ForteMT", "Forte"}, -}; - -const struct FX_FontStyle { - const FX_CHAR* style; - int32_t len; -} g_FontStyles[] = { - {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7}, -}; - -const struct CODEPAGE_MAP { - uint16_t codepage; - uint8_t charset; -} g_Codepage2CharsetTable[] = { - {0, 1}, {42, 2}, {437, 254}, {850, 255}, {874, 222}, - {932, 128}, {936, 134}, {949, 129}, {950, 136}, {1250, 238}, - {1251, 204}, {1252, 0}, {1253, 161}, {1254, 162}, {1255, 177}, - {1256, 178}, {1257, 186}, {1258, 163}, {1361, 130}, {10000, 77}, - {10001, 78}, {10002, 81}, {10003, 79}, {10004, 84}, {10005, 83}, - {10006, 85}, {10007, 89}, {10008, 80}, {10021, 87}, {10029, 88}, - {10081, 86}, -}; - -const uint32_t kTableNAME = FXDWORD_GET_MSBFIRST("name"); -const uint32_t kTableTTCF = FXDWORD_GET_MSBFIRST("ttcf"); - -int CompareFontFamilyString(const void* key, const void* element) { - CFX_ByteString str_key((const FX_CHAR*)key); - if (str_key.Find(((AltFontFamily*)element)->m_pFontName) != -1) { - return 0; - } - return FXSYS_stricmp((const FX_CHAR*)key, - ((AltFontFamily*)element)->m_pFontName); -} - -int CompareString(const void* key, const void* element) { - return FXSYS_stricmp((const FX_CHAR*)key, ((AltFontName*)element)->m_pName); -} - -CFX_ByteString KeyNameFromFace(const CFX_ByteString& face_name, - int weight, - FX_BOOL bItalic) { - CFX_ByteString key(face_name); - key += ','; - key += CFX_ByteString::FormatInteger(weight); - key += bItalic ? 'I' : 'N'; - return key; -} - -CFX_ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) { - CFX_ByteString key; - key.Format("%d:%d", ttc_size, checksum); - return key; -} - -CFX_ByteString TT_NormalizeName(const FX_CHAR* family) { - CFX_ByteString norm(family); - norm.Remove(' '); - norm.Remove('-'); - norm.Remove(','); - int pos = norm.Find('+'); - if (pos > 0) { - norm = norm.Left(pos); - } - norm.MakeLower(); - return norm; -} - -CFX_ByteString FPDF_ReadStringFromFile(FXSYS_FILE* pFile, uint32_t size) { - CFX_ByteString buffer; - if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) { - return CFX_ByteString(); - } - buffer.ReleaseBuffer(size); - return buffer; -} - -CFX_ByteString FPDF_LoadTableFromTT(FXSYS_FILE* pFile, - const uint8_t* pTables, - uint32_t nTables, - uint32_t tag) { - for (uint32_t i = 0; i < nTables; i++) { - const uint8_t* p = pTables + i * 16; - if (GET_TT_LONG(p) == tag) { - uint32_t offset = GET_TT_LONG(p + 8); - uint32_t size = GET_TT_LONG(p + 12); - FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); - return FPDF_ReadStringFromFile(pFile, size); - } - } - return CFX_ByteString(); -} - -uint8_t GetCharsetFromCodePage(uint16_t codepage) { - const CODEPAGE_MAP* pEnd = - g_Codepage2CharsetTable + FX_ArraySize(g_Codepage2CharsetTable); - const CODEPAGE_MAP* pCharmap = - std::lower_bound(g_Codepage2CharsetTable, pEnd, codepage, - [](const CODEPAGE_MAP& charset, uint16_t page) { - return charset.codepage < page; - }); - if (pCharmap < pEnd && codepage == pCharmap->codepage) - return pCharmap->charset; - return FXFONT_DEFAULT_CHARSET; -} - -CFX_ByteString GetFontFamily(CFX_ByteString fontName, int nStyle) { - if (fontName.Find("Script") >= 0) { - if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) { - fontName = "ScriptMTBold"; - } else if (fontName.Find("Palace") >= 0) { - fontName = "PalaceScriptMT"; - } else if (fontName.Find("French") >= 0) { - fontName = "FrenchScriptMT"; - } else if (fontName.Find("FreeStyle") >= 0) { - fontName = "FreeStyleScript"; - } - return fontName; - } - AltFontFamily* found = (AltFontFamily*)FXSYS_bsearch( - fontName.c_str(), g_AltFontFamilies, - sizeof g_AltFontFamilies / sizeof(AltFontFamily), sizeof(AltFontFamily), - CompareFontFamilyString); - return found ? CFX_ByteString(found->m_pFontFamily) : fontName; -} - -CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex) { - CFX_ByteTextBuf buf; - if (!iLen || iLen <= iIndex) { - return buf.MakeString(); - } - while (iIndex < iLen) { - if (pStyle[iIndex] == ',') { - break; - } - buf.AppendChar(pStyle[iIndex]); - ++iIndex; - } - return buf.MakeString(); -} - -int32_t GetStyleType(const CFX_ByteString& bsStyle, FX_BOOL bRevert) { - int32_t iLen = bsStyle.GetLength(); - if (!iLen) { - return -1; - } - int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle); - const FX_FontStyle* pStyle = nullptr; - for (int i = iSize - 1; i >= 0; --i) { - pStyle = g_FontStyles + i; - if (!pStyle || pStyle->len > iLen) { - continue; - } - if (!bRevert) { - if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) { - return i; - } - } else { - if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) { - return i; - } - } - } - return -1; -} - -FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) { - if (name == "MyriadPro") { - PitchFamily &= ~FXFONT_FF_ROMAN; - return TRUE; - } - return FALSE; -} - -uint32_t GetCharset(int charset) { - switch (charset) { - case FXFONT_SHIFTJIS_CHARSET: - return CHARSET_FLAG_SHIFTJIS; - case FXFONT_GB2312_CHARSET: - return CHARSET_FLAG_GB; - case FXFONT_CHINESEBIG5_CHARSET: - return CHARSET_FLAG_BIG5; - case FXFONT_HANGEUL_CHARSET: - return CHARSET_FLAG_KOREAN; - case FXFONT_SYMBOL_CHARSET: - return CHARSET_FLAG_SYMBOL; - case FXFONT_ANSI_CHARSET: - return CHARSET_FLAG_ANSI; - default: - break; - } - return 0; -} - -int32_t GetSimilarValue(int weight, - FX_BOOL bItalic, - int pitch_family, - uint32_t style) { - int32_t iSimilarValue = 0; - if (!!(style & FXFONT_BOLD) == (weight > 400)) { - iSimilarValue += 16; - } - if (!!(style & FXFONT_ITALIC) == bItalic) { - iSimilarValue += 16; - } - if (!!(style & FXFONT_SERIF) == !!(pitch_family & FXFONT_FF_ROMAN)) { - iSimilarValue += 16; - } - if (!!(style & FXFONT_SCRIPT) == !!(pitch_family & FXFONT_FF_SCRIPT)) { - iSimilarValue += 8; - } - if (!!(style & FXFONT_FIXED_PITCH) == - !!(pitch_family & FXFONT_FF_FIXEDPITCH)) { - iSimilarValue += 8; - } - return iSimilarValue; -} - -} // namespace CFX_SubstFont::CFX_SubstFont() { m_ExtHandle = nullptr; @@ -457,232 +55,6 @@ int CTTFontDesc::ReleaseFace(FXFT_Face face) { return 0; } -CFX_FontMgr::CFX_FontMgr() - : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) { - m_pBuiltinMapper.reset(new CFX_FontMapper(this)); -} - -CFX_FontMgr::~CFX_FontMgr() { - for (const auto& pair : m_FaceMap) - delete pair.second; - - // |m_pBuiltinMapper| references |m_FTLibrary|, so it has to be destroyed - // first. - m_pBuiltinMapper.reset(); - FXFT_Done_FreeType(m_FTLibrary); -} - -void CFX_FontMgr::InitFTLibrary() { - if (m_FTLibrary) - return; - FXFT_Init_FreeType(&m_FTLibrary); - m_FTLibrarySupportsHinting = - FXFT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) != - FT_Err_Unimplemented_Feature; -} - -void CFX_FontMgr::SetSystemFontInfo( - std::unique_ptr<IFX_SystemFontInfo> pFontInfo) { - m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo)); -} - -FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, - FX_BOOL bTrueType, - uint32_t flags, - int weight, - int italic_angle, - int CharsetCP, - CFX_SubstFont* pSubstFont) { - InitFTLibrary(); - return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, - italic_angle, CharsetCP, pSubstFont); -} - -FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name, - int weight, - FX_BOOL bItalic, - uint8_t*& pFontData) { - auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic)); - if (it == m_FaceMap.end()) - return nullptr; - - CTTFontDesc* pFontDesc = it->second; - pFontData = pFontDesc->m_pFontData; - pFontDesc->m_RefCount++; - return pFontDesc->m_SingleFace.m_pFace; -} -FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name, - int weight, - FX_BOOL bItalic, - uint8_t* pData, - uint32_t size, - int face_index) { - CTTFontDesc* pFontDesc = new CTTFontDesc; - pFontDesc->m_Type = 1; - pFontDesc->m_SingleFace.m_pFace = nullptr; - pFontDesc->m_SingleFace.m_bBold = weight; - pFontDesc->m_SingleFace.m_bItalic = bItalic; - pFontDesc->m_pFontData = pData; - pFontDesc->m_RefCount = 1; - - InitFTLibrary(); - FXFT_Library library = m_FTLibrary; - int ret = FXFT_New_Memory_Face(library, pData, size, face_index, - &pFontDesc->m_SingleFace.m_pFace); - if (ret) { - delete pFontDesc; - return nullptr; - } - ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace.m_pFace, 64, 64); - if (ret) { - delete pFontDesc; - return nullptr; - } - m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = pFontDesc; - return pFontDesc->m_SingleFace.m_pFace; -} - -int GetTTCIndex(const uint8_t* pFontData, - uint32_t ttc_size, - uint32_t font_offset) { - int face_index = 0; - const uint8_t* p = pFontData + 8; - uint32_t nfont = GET_TT_LONG(p); - uint32_t index; - for (index = 0; index < nfont; index++) { - p = pFontData + 12 + index * 4; - if (GET_TT_LONG(p) == font_offset) { - break; - } - } - if (index >= nfont) { - face_index = 0; - } else { - face_index = index; - } - return face_index; -} -FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, - uint32_t checksum, - int font_offset, - uint8_t*& pFontData) { - auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum)); - if (it == m_FaceMap.end()) - return nullptr; - - CTTFontDesc* pFontDesc = it->second; - pFontData = pFontDesc->m_pFontData; - pFontDesc->m_RefCount++; - int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); - if (!pFontDesc->m_TTCFace.m_pFaces[face_index]) { - pFontDesc->m_TTCFace.m_pFaces[face_index] = - GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); - } - return pFontDesc->m_TTCFace.m_pFaces[face_index]; -} -FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, - uint32_t checksum, - uint8_t* pData, - uint32_t size, - int font_offset) { - CTTFontDesc* pFontDesc = new CTTFontDesc; - pFontDesc->m_Type = 2; - pFontDesc->m_pFontData = pData; - for (int i = 0; i < 16; i++) { - pFontDesc->m_TTCFace.m_pFaces[i] = nullptr; - } - pFontDesc->m_RefCount++; - m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = pFontDesc; - int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); - pFontDesc->m_TTCFace.m_pFaces[face_index] = - GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); - return pFontDesc->m_TTCFace.m_pFaces[face_index]; -} - -FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, - uint32_t size, - int face_index) { - InitFTLibrary(); - FXFT_Library library = m_FTLibrary; - FXFT_Face face = nullptr; - if (FXFT_New_Memory_Face(library, pData, size, face_index, &face)) - return nullptr; - return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; -} - -FXFT_Face CFX_FontMgr::GetFileFace(const FX_CHAR* filename, int face_index) { - InitFTLibrary(); - FXFT_Library library = m_FTLibrary; - FXFT_Face face = nullptr; - if (FXFT_New_Face(library, filename, face_index, &face)) - return nullptr; - return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; -} - -void CFX_FontMgr::ReleaseFace(FXFT_Face face) { - if (!face) { - return; - } - FX_BOOL bNeedFaceDone = TRUE; - auto it = m_FaceMap.begin(); - while (it != m_FaceMap.end()) { - auto temp = it++; - int nRet = temp->second->ReleaseFace(face); - if (nRet == -1) - continue; - bNeedFaceDone = FALSE; - if (nRet == 0) - m_FaceMap.erase(temp); - break; - } - if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face)) - FXFT_Done_Face(face); -} - -bool CFX_FontMgr::GetBuiltinFont(size_t index, - const uint8_t** pFontData, - uint32_t* size) { - if (index < FX_ArraySize(g_FoxitFonts)) { - *pFontData = g_FoxitFonts[index].m_pFontData; - *size = g_FoxitFonts[index].m_dwSize; - return true; - } - index -= FX_ArraySize(g_FoxitFonts); - if (index < FX_ArraySize(g_MMFonts)) { - *pFontData = g_MMFonts[index].m_pFontData; - *size = g_MMFonts[index].m_dwSize; - return true; - } - return false; -} - -CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) - : m_bListLoaded(FALSE), - m_pFontMgr(mgr) { - m_MMFaces[0] = nullptr; - m_MMFaces[1] = nullptr; - FXSYS_memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces)); -} - -CFX_FontMapper::~CFX_FontMapper() { - for (size_t i = 0; i < FX_ArraySize(m_FoxitFaces); ++i) { - if (m_FoxitFaces[i]) - FXFT_Done_Face(m_FoxitFaces[i]); - } - if (m_MMFaces[0]) - FXFT_Done_Face(m_MMFaces[0]); - if (m_MMFaces[1]) - FXFT_Done_Face(m_MMFaces[1]); -} - -void CFX_FontMapper::SetSystemFontInfo( - std::unique_ptr<IFX_SystemFontInfo> pFontInfo) { - if (!pFontInfo) - return; - - m_pFontInfo = std::move(pFontInfo); -} - static CFX_ByteString GetStringFromTable(const uint8_t* string_ptr, uint32_t string_ptr_length, uint16_t offset, @@ -725,592 +97,7 @@ CFX_ByteString GetNameFromTT(const uint8_t* name_table, } return CFX_ByteString(); } - -CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) { - if (!m_pFontInfo) - return CFX_ByteString(); - - uint32_t size = m_pFontInfo->GetFontData(hFont, kTableNAME, nullptr, 0); - if (!size) - return CFX_ByteString(); - - std::vector<uint8_t> buffer(size); - uint8_t* buffer_ptr = buffer.data(); - uint32_t bytes_read = - m_pFontInfo->GetFontData(hFont, kTableNAME, buffer_ptr, size); - return bytes_read == size ? GetNameFromTT(buffer_ptr, bytes_read, 6) - : CFX_ByteString(); -} - -void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) { - if (!m_pFontInfo) - return; - - m_FaceArray.push_back({name, static_cast<uint32_t>(charset)}); - if (name == m_LastFamily) - return; - - const uint8_t* ptr = name.raw_str(); - FX_BOOL bLocalized = FALSE; - for (int i = 0; i < name.GetLength(); i++) { - if (ptr[i] > 0x80) { - bLocalized = TRUE; - break; - } - } - - if (bLocalized) { - void* hFont = m_pFontInfo->GetFont(name.c_str()); - if (!hFont) { - int iExact; - hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, - name.c_str(), iExact); - if (!hFont) - return; - } - - CFX_ByteString new_name = GetPSNameFromTT(hFont); - if (!new_name.IsEmpty()) { - new_name.Insert(0, ' '); - m_InstalledTTFonts.push_back(new_name); - } - m_pFontInfo->DeleteFont(hFont); - } - m_InstalledTTFonts.push_back(name); - m_LastFamily = name; -} - -void CFX_FontMapper::LoadInstalledFonts() { - if (!m_pFontInfo || m_bListLoaded) - return; - - m_pFontInfo->EnumFontList(this); - m_bListLoaded = TRUE; -} - -CFX_ByteString CFX_FontMapper::MatchInstalledFonts( - const CFX_ByteString& norm_name) { - LoadInstalledFonts(); - int i; - for (i = pdfium::CollectionSize<int>(m_InstalledTTFonts) - 1; i >= 0; i--) { - CFX_ByteString norm1 = TT_NormalizeName(m_InstalledTTFonts[i].c_str()); - if (norm1 == norm_name) { - break; - } - } - if (i < 0) { - return CFX_ByteString(); - } - CFX_ByteString match = m_InstalledTTFonts[i]; - if (match[0] == ' ') { - match = m_InstalledTTFonts[i + 1]; - } - return match; -} - -FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, - int iBaseFont, - int italic_angle, - int weight, - int picthfamily) { - if (iBaseFont < 12) { - if (m_FoxitFaces[iBaseFont]) { - return m_FoxitFaces[iBaseFont]; - } - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - if (m_pFontMgr->GetBuiltinFont(iBaseFont, &pFontData, &size)) { - m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[iBaseFont]; - } - } - pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM; - pSubstFont->m_ItalicAngle = italic_angle; - if (weight) { - pSubstFont->m_Weight = weight; - } - if (picthfamily & FXFONT_FF_ROMAN) { - pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; - pSubstFont->m_Family = "Chrome Serif"; - if (m_MMFaces[1]) { - return m_MMFaces[1]; - } - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - m_pFontMgr->GetBuiltinFont(14, &pFontData, &size); - m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_MMFaces[1]; - } - pSubstFont->m_Family = "Chrome Sans"; - if (m_MMFaces[0]) { - return m_MMFaces[0]; - } - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - m_pFontMgr->GetBuiltinFont(15, &pFontData, &size); - m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_MMFaces[0]; -} - -FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, - FX_BOOL bTrueType, - uint32_t flags, - int weight, - int italic_angle, - int WindowCP, - CFX_SubstFont* pSubstFont) { - if (!(flags & FXFONT_USEEXTERNATTR)) { - weight = FXFONT_FW_NORMAL; - italic_angle = 0; - } - CFX_ByteString SubstName = name; - SubstName.Remove(0x20); - if (bTrueType) { - if (name[0] == '@') { - SubstName = name.Mid(1); - } - } - PDF_GetStandardFontName(&SubstName); - if (SubstName == "Symbol" && !bTrueType) { - pSubstFont->m_Family = "Chrome Symbol"; - pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - if (m_FoxitFaces[12]) { - return m_FoxitFaces[12]; - } - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - m_pFontMgr->GetBuiltinFont(12, &pFontData, &size); - m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[12]; - } - if (SubstName == "ZapfDingbats") { - pSubstFont->m_Family = "Chrome Dingbats"; - pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - if (m_FoxitFaces[13]) { - return m_FoxitFaces[13]; - } - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - m_pFontMgr->GetBuiltinFont(13, &pFontData, &size); - m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[13]; - } - int iBaseFont = 0; - CFX_ByteString family, style; - FX_BOOL bHasComma = FALSE; - FX_BOOL bHasHypen = FALSE; - int find = SubstName.Find(",", 0); - if (find >= 0) { - family = SubstName.Left(find); - PDF_GetStandardFontName(&family); - style = SubstName.Mid(find + 1); - bHasComma = TRUE; - } else { - family = SubstName; - } - for (; iBaseFont < 12; iBaseFont++) - if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) { - break; - } - int PitchFamily = 0; - FX_BOOL bItalic = FALSE; - uint32_t nStyle = 0; - FX_BOOL bStyleAvail = FALSE; - if (iBaseFont < 12) { - family = g_Base14FontNames[iBaseFont]; - if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) { - nStyle |= FX_FONT_STYLE_Bold; - } - if ((iBaseFont % 4) / 2) { - nStyle |= FX_FONT_STYLE_Italic; - } - if (iBaseFont < 4) { - PitchFamily |= FXFONT_FF_FIXEDPITCH; - } - if (iBaseFont >= 8) { - PitchFamily |= FXFONT_FF_ROMAN; - } - } else { - if (!bHasComma) { - find = family.ReverseFind('-'); - if (find >= 0) { - style = family.Mid(find + 1); - family = family.Left(find); - bHasHypen = TRUE; - } - } - if (!bHasHypen) { - int nLen = family.GetLength(); - int32_t nRet = GetStyleType(family, TRUE); - if (nRet > -1) { - family = family.Left(nLen - g_FontStyles[nRet].len); - if (nRet == 0) { - nStyle |= FX_FONT_STYLE_Bold; - } - if (nRet == 1) { - nStyle |= FX_FONT_STYLE_Italic; - } - if (nRet == 2) { - nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic); - } - } - } - if (flags & FXFONT_SERIF) { - PitchFamily |= FXFONT_FF_ROMAN; - } - if (flags & FXFONT_SCRIPT) { - PitchFamily |= FXFONT_FF_SCRIPT; - } - if (flags & FXFONT_FIXED_PITCH) { - PitchFamily |= FXFONT_FF_FIXEDPITCH; - } - } - if (!style.IsEmpty()) { - int nLen = style.GetLength(); - const FX_CHAR* pStyle = style.c_str(); - int i = 0; - FX_BOOL bFirstItem = TRUE; - CFX_ByteString buf; - while (i < nLen) { - buf = ParseStyle(pStyle, nLen, i); - int32_t nRet = GetStyleType(buf, FALSE); - if ((i && !bStyleAvail) || (!i && nRet < 0)) { - family = SubstName; - iBaseFont = 12; - break; - } else if (nRet >= 0) { - bStyleAvail = TRUE; - } - if (nRet == 0) { - if (nStyle & FX_FONT_STYLE_Bold) { - nStyle |= FX_FONT_STYLE_BoldBold; - } else { - nStyle |= FX_FONT_STYLE_Bold; - } - bFirstItem = FALSE; - } - if (nRet == 1) { - if (bFirstItem) { - nStyle |= FX_FONT_STYLE_Italic; - } else { - family = SubstName; - iBaseFont = 12; - } - break; - } - if (nRet == 2) { - nStyle |= FX_FONT_STYLE_Italic; - if (nStyle & FX_FONT_STYLE_Bold) { - nStyle |= FX_FONT_STYLE_BoldBold; - } else { - nStyle |= FX_FONT_STYLE_Bold; - } - bFirstItem = FALSE; - } - i += buf.GetLength() + 1; - } - } - weight = weight ? weight : FXFONT_FW_NORMAL; - int old_weight = weight; - if (nStyle) { - weight = - nStyle & FX_FONT_STYLE_BoldBold - ? 900 - : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); - } - if (nStyle & FX_FONT_STYLE_Italic) { - bItalic = TRUE; - } - FX_BOOL bCJK = FALSE; - int iExact = 0; - int Charset = FXFONT_ANSI_CHARSET; - if (WindowCP) { - Charset = GetCharsetFromCodePage(WindowCP); - } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) { - Charset = FXFONT_SYMBOL_CHARSET; - } - if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET || - Charset == FXFONT_HANGEUL_CHARSET || - Charset == FXFONT_CHINESEBIG5_CHARSET) { - bCJK = TRUE; - } - if (!m_pFontInfo) { - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - family = GetFontFamily(family, nStyle); - CFX_ByteString match = MatchInstalledFonts(TT_NormalizeName(family.c_str())); - if (match.IsEmpty() && family != SubstName && - (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) { - match = MatchInstalledFonts(TT_NormalizeName(SubstName.c_str())); - } - if (match.IsEmpty() && iBaseFont >= 12) { - if (!bCJK) { - if (!CheckSupportThirdPartFont(family, PitchFamily)) { - if (italic_angle != 0) { - bItalic = TRUE; - } else { - bItalic = FALSE; - } - weight = old_weight; - } - } else { - pSubstFont->m_bSubstCJK = true; - if (nStyle) { - pSubstFont->m_WeightCJK = weight; - } else { - pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL; - } - if (nStyle & FX_FONT_STYLE_Italic) { - pSubstFont->m_bItalicCJK = true; - } - } - } else { - italic_angle = 0; - weight = - nStyle & FX_FONT_STYLE_BoldBold - ? 900 - : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); - } - if (!match.IsEmpty() || iBaseFont < 12) { - if (!match.IsEmpty()) { - family = match; - } - if (iBaseFont < 12) { - if (nStyle && !(iBaseFont % 4)) { - if ((nStyle & 0x3) == 1) { - iBaseFont += 1; - } - if ((nStyle & 0x3) == 2) { - iBaseFont += 3; - } - if ((nStyle & 0x3) == 3) { - iBaseFont += 2; - } - } - family = g_Base14FontNames[iBaseFont]; - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - } - } else { - if (flags & FXFONT_ITALIC) { - bItalic = TRUE; - } - } - iExact = !match.IsEmpty(); - void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, - family.c_str(), iExact); - if (iExact) { - pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT; - } - if (!hFont) { #ifdef PDF_ENABLE_XFA - if (flags & FXFONT_EXACTMATCH) { - return nullptr; - } -#endif // PDF_ENABLE_XFA - if (bCJK) { - if (italic_angle != 0) { - bItalic = TRUE; - } else { - bItalic = FALSE; - } - weight = old_weight; - } - if (!match.IsEmpty()) { - hFont = m_pFontInfo->GetFont(match.c_str()); - if (!hFont) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - } else { - if (Charset == FXFONT_SYMBOL_CHARSET) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ - if (SubstName == "Symbol") { - pSubstFont->m_Family = "Chrome Symbol"; - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; - if (m_FoxitFaces[12]) { - return m_FoxitFaces[12]; - } - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - m_pFontMgr->GetBuiltinFont(12, &pFontData, &size); - m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[12]; - } -#endif - pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL; - return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, - weight, italic_angle, 0, pSubstFont); - } - if (Charset == FXFONT_ANSI_CHARSET) { - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - - auto it = - std::find_if(m_FaceArray.begin(), m_FaceArray.end(), - [Charset](const FaceData& face) { - return face.charset == static_cast<uint32_t>(Charset); - }); - if (it == m_FaceArray.end()) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - hFont = m_pFontInfo->GetFont(it->name.c_str()); - } - } - pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont); - if (!hFont) - return nullptr; - - m_pFontInfo->GetFaceName(hFont, SubstName); - if (Charset == FXFONT_DEFAULT_CHARSET) { - m_pFontInfo->GetFontCharset(hFont, Charset); - } - uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, kTableTTCF, nullptr, 0); - uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); - if (font_size == 0 && ttc_size == 0) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - FXFT_Face face = nullptr; - if (ttc_size) { - uint8_t temp[1024]; - m_pFontInfo->GetFontData(hFont, kTableTTCF, temp, 1024); - uint32_t checksum = 0; - for (int i = 0; i < 256; i++) { - checksum += ((uint32_t*)temp)[i]; - } - uint8_t* pFontData; - face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, - ttc_size - font_size, pFontData); - if (!face) { - pFontData = FX_Alloc(uint8_t, ttc_size); - m_pFontInfo->GetFontData(hFont, kTableTTCF, pFontData, ttc_size); - face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, - ttc_size, ttc_size - font_size); - } - } else { - uint8_t* pFontData; - face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); - if (!face) { - pFontData = FX_Alloc(uint8_t, font_size); - m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); - face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, - font_size, - m_pFontInfo->GetFaceIndex(hFont)); - } - } - if (!face) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - pSubstFont->m_Family = SubstName; - pSubstFont->m_Charset = Charset; - FX_BOOL bNeedUpdateWeight = FALSE; - if (FXFT_Is_Face_Bold(face)) { - if (weight == FXFONT_FW_BOLD) { - bNeedUpdateWeight = FALSE; - } else { - bNeedUpdateWeight = TRUE; - } - } else { - if (weight == FXFONT_FW_NORMAL) { - bNeedUpdateWeight = FALSE; - } else { - bNeedUpdateWeight = TRUE; - } - } - if (bNeedUpdateWeight) { - pSubstFont->m_Weight = weight; - } - if (bItalic && !FXFT_Is_Face_Italic(face)) { - if (italic_angle == 0) { - italic_angle = -12; - } else if (FXSYS_abs(italic_angle) < 5) { - italic_angle = 0; - } - pSubstFont->m_ItalicAngle = italic_angle; - } - m_pFontInfo->DeleteFont(hFont); - return face; -} -#ifdef PDF_ENABLE_XFA -FXFT_Face CFX_FontMapper::FindSubstFontByUnicode(uint32_t dwUnicode, - uint32_t flags, - int weight, - int italic_angle) { - if (!m_pFontInfo) - return nullptr; - - FX_BOOL bItalic = (flags & FXFONT_ITALIC) != 0; - int PitchFamily = 0; - if (flags & FXFONT_SERIF) { - PitchFamily |= FXFONT_FF_ROMAN; - } - if (flags & FXFONT_SCRIPT) { - PitchFamily |= FXFONT_FF_SCRIPT; - } - if (flags & FXFONT_FIXED_PITCH) { - PitchFamily |= FXFONT_FF_FIXEDPITCH; - } - void* hFont = - m_pFontInfo->MapFontByUnicode(dwUnicode, weight, bItalic, PitchFamily); - if (!hFont) - return nullptr; - - uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, nullptr, 0); - uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); - if (font_size == 0 && ttc_size == 0) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - FXFT_Face face = nullptr; - if (ttc_size) { - uint8_t temp[1024]; - m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024); - uint32_t checksum = 0; - for (int i = 0; i < 256; i++) { - checksum += ((uint32_t*)temp)[i]; - } - uint8_t* pFontData; - face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, - ttc_size - font_size, pFontData); - if (!face) { - pFontData = FX_Alloc(uint8_t, ttc_size); - if (pFontData) { - m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size); - face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, - ttc_size, ttc_size - font_size); - } - } - } else { - CFX_ByteString SubstName; - m_pFontInfo->GetFaceName(hFont, SubstName); - uint8_t* pFontData; - face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); - if (!face) { - pFontData = FX_Alloc(uint8_t, font_size); - if (!pFontData) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); - face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, - font_size, - m_pFontInfo->GetFaceIndex(hFont)); - } - } - m_pFontInfo->DeleteFont(hFont); - return face; -} - void* IFX_SystemFontInfo::MapFontByUnicode(uint32_t dwUnicode, int weight, FX_BOOL bItalic, @@ -1327,24 +114,6 @@ void* IFX_SystemFontInfo::RetainFont(void* hFont) { return nullptr; } -int CFX_FontMapper::GetFaceSize() const { - return pdfium::CollectionSize<int>(m_FaceArray); -} - -FX_BOOL CFX_FontMapper::IsBuiltinFace(const FXFT_Face face) const { - for (size_t i = 0; i < MM_FACE_COUNT; ++i) { - if (m_MMFaces[i] == face) { - return TRUE; - } - } - for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) { - if (m_FoxitFaces[i] == face) { - return TRUE; - } - } - return FALSE; -} - extern "C" { unsigned long _FTStreamRead(FXFT_Stream stream, unsigned long offset, @@ -1372,293 +141,3 @@ CFX_FontFaceInfo::CFX_FontFaceInfo(CFX_ByteString filePath, m_FileSize(fileSize), m_Styles(0), m_Charsets(0) {} - -CFX_FolderFontInfo::CFX_FolderFontInfo() {} - -CFX_FolderFontInfo::~CFX_FolderFontInfo() { - for (const auto& pair : m_FontList) { - delete pair.second; - } -} - -void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) { - m_PathList.push_back(CFX_ByteString(path)); -} - -FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) { - m_pMapper = pMapper; - for (const auto& path : m_PathList) - ScanPath(path); - return TRUE; -} -void CFX_FolderFontInfo::ScanPath(const CFX_ByteString& path) { - void* handle = FX_OpenFolder(path.c_str()); - if (!handle) - return; - - CFX_ByteString filename; - FX_BOOL bFolder; - while (FX_GetNextFile(handle, filename, bFolder)) { - if (bFolder) { - if (filename == "." || filename == "..") - continue; - } else { - CFX_ByteString ext = filename.Right(4); - ext.MakeUpper(); - if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") - continue; - } - - CFX_ByteString fullpath = path; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - fullpath += "\\"; -#else - fullpath += "/"; -#endif - - fullpath += filename; - bFolder ? ScanPath(fullpath) : ScanFile(fullpath); - } - FX_CloseFolder(handle); -} - -void CFX_FolderFontInfo::ScanFile(const CFX_ByteString& path) { - FXSYS_FILE* pFile = FXSYS_fopen(path.c_str(), "rb"); - if (!pFile) - return; - - FXSYS_fseek(pFile, 0, FXSYS_SEEK_END); - - uint32_t filesize = FXSYS_ftell(pFile); - uint8_t buffer[16]; - FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET); - - size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile); - if (readCnt != 1) { - FXSYS_fclose(pFile); - return; - } - - if (GET_TT_LONG(buffer) == kTableTTCF) { - uint32_t nFaces = GET_TT_LONG(buffer + 8); - if (nFaces > std::numeric_limits<uint32_t>::max() / 4) { - FXSYS_fclose(pFile); - return; - } - uint32_t face_bytes = nFaces * 4; - uint8_t* offsets = FX_Alloc(uint8_t, face_bytes); - readCnt = FXSYS_fread(offsets, 1, face_bytes, pFile); - if (readCnt != face_bytes) { - FX_Free(offsets); - FXSYS_fclose(pFile); - return; - } - for (uint32_t i = 0; i < nFaces; i++) { - uint8_t* p = offsets + i * 4; - ReportFace(path, pFile, filesize, GET_TT_LONG(p)); - } - FX_Free(offsets); - } else { - ReportFace(path, pFile, filesize, 0); - } - FXSYS_fclose(pFile); -} -void CFX_FolderFontInfo::ReportFace(const CFX_ByteString& path, - FXSYS_FILE* pFile, - uint32_t filesize, - uint32_t offset) { - FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); - char buffer[16]; - if (!FXSYS_fread(buffer, 12, 1, pFile)) - return; - - uint32_t nTables = GET_TT_SHORT(buffer + 4); - CFX_ByteString tables = FPDF_ReadStringFromFile(pFile, nTables * 16); - if (tables.IsEmpty()) - return; - - CFX_ByteString names = - FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x6e616d65); - if (names.IsEmpty()) - return; - - CFX_ByteString facename = - GetNameFromTT(names.raw_str(), names.GetLength(), 1); - if (facename.IsEmpty()) - return; - - CFX_ByteString style = GetNameFromTT(names.raw_str(), names.GetLength(), 2); - if (style != "Regular") - facename += " " + style; - - if (pdfium::ContainsKey(m_FontList, facename)) - return; - - CFX_FontFaceInfo* pInfo = - new CFX_FontFaceInfo(path, facename, tables, offset, filesize); - CFX_ByteString os2 = - FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x4f532f32); - if (os2.GetLength() >= 86) { - const uint8_t* p = os2.raw_str() + 78; - uint32_t codepages = GET_TT_LONG(p); - if (codepages & (1 << 17)) { - m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS; - } - if (codepages & (1 << 18)) { - m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_GB; - } - if (codepages & (1 << 20)) { - m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_BIG5; - } - if ((codepages & (1 << 19)) || (codepages & (1 << 21))) { - m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_KOREAN; - } - if (codepages & (1 << 31)) { - m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL; - } - } - m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_ANSI; - pInfo->m_Styles = 0; - if (style.Find("Bold") > -1) - pInfo->m_Styles |= FXFONT_BOLD; - if (style.Find("Italic") > -1 || style.Find("Oblique") > -1) - pInfo->m_Styles |= FXFONT_ITALIC; - if (facename.Find("Serif") > -1) - pInfo->m_Styles |= FXFONT_SERIF; - - m_FontList[facename] = pInfo; -} - -void* CFX_FolderFontInfo::GetSubstFont(const CFX_ByteString& face) { - for (size_t iBaseFont = 0; iBaseFont < FX_ArraySize(Base14Substs); - iBaseFont++) { - if (face == Base14Substs[iBaseFont].m_pName) - return GetFont(Base14Substs[iBaseFont].m_pSubstName); - } - return nullptr; -} - -void* CFX_FolderFontInfo::FindFont(int weight, - FX_BOOL bItalic, - int charset, - int pitch_family, - const FX_CHAR* family, - FX_BOOL bMatchName) { - CFX_FontFaceInfo* pFind = nullptr; - if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) { - return GetFont("Courier New"); - } - uint32_t charset_flag = GetCharset(charset); - int32_t iBestSimilar = 0; - for (const auto& it : m_FontList) { - const CFX_ByteString& bsName = it.first; - CFX_FontFaceInfo* pFont = it.second; - if (!(pFont->m_Charsets & charset_flag) && - charset != FXFONT_DEFAULT_CHARSET) { - continue; - } - int32_t index = bsName.Find(family); - if (bMatchName && index < 0) { - continue; - } - int32_t iSimilarValue = - GetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles); - if (iSimilarValue > iBestSimilar) { - iBestSimilar = iSimilarValue; - pFind = pFont; - } - } - return pFind; -} -void* CFX_FolderFontInfo::MapFont(int weight, - FX_BOOL bItalic, - int charset, - int pitch_family, - const FX_CHAR* family, - int& iExact) { - return nullptr; -} - -#ifdef PDF_ENABLE_XFA -void* CFX_FolderFontInfo::MapFontByUnicode(uint32_t dwUnicode, - int weight, - FX_BOOL bItalic, - int pitch_family) { - return nullptr; -} -#endif // PDF_ENABLE_XFA - -void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face) { - auto it = m_FontList.find(face); - return it != m_FontList.end() ? it->second : nullptr; -} - -uint32_t CFX_FolderFontInfo::GetFontData(void* hFont, - uint32_t table, - uint8_t* buffer, - uint32_t size) { - if (!hFont) - return 0; - - const CFX_FontFaceInfo* pFont = static_cast<CFX_FontFaceInfo*>(hFont); - uint32_t datasize = 0; - uint32_t offset = 0; - if (table == 0) { - datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize; - } else if (table == kTableTTCF) { - datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0; - } else { - uint32_t nTables = pFont->m_FontTables.GetLength() / 16; - for (uint32_t i = 0; i < nTables; i++) { - const uint8_t* p = pFont->m_FontTables.raw_str() + i * 16; - if (GET_TT_LONG(p) == table) { - offset = GET_TT_LONG(p + 8); - datasize = GET_TT_LONG(p + 12); - } - } - } - - if (!datasize || size < datasize) - return datasize; - - FXSYS_FILE* pFile = FXSYS_fopen(pFont->m_FilePath.c_str(), "rb"); - if (!pFile) - return 0; - - if (FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET) < 0 || - FXSYS_fread(buffer, datasize, 1, pFile) != 1) { - datasize = 0; - } - FXSYS_fclose(pFile); - return datasize; -} - -void CFX_FolderFontInfo::DeleteFont(void* hFont) {} -FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) { - if (!hFont) { - return FALSE; - } - CFX_FontFaceInfo* pFont = (CFX_FontFaceInfo*)hFont; - name = pFont->m_FaceName; - return TRUE; -} -FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) { - return FALSE; -} - -int PDF_GetStandardFontName(CFX_ByteString* name) { - AltFontName* found = static_cast<AltFontName*>( - FXSYS_bsearch(name->c_str(), g_AltFontNames, FX_ArraySize(g_AltFontNames), - sizeof(AltFontName), CompareString)); - if (!found) - return -1; - - *name = g_Base14FontNames[found->m_Index]; - return found->m_Index; -} diff --git a/core/fxge/ge/fx_ge_linux.cpp b/core/fxge/ge/fx_ge_linux.cpp index 712d9e07b0..6406d82570 100644 --- a/core/fxge/ge/fx_ge_linux.cpp +++ b/core/fxge/ge/fx_ge_linux.cpp @@ -8,8 +8,10 @@ #include "core/fxge/agg/fx_agg_driver.h" #endif +#include "core/fxge/ge/cfx_folderfontinfo.h" #include "core/fxge/ge/fx_text_int.h" #include "core/fxge/include/fx_ge.h" +#include "core/fxge/include/ifx_systemfontinfo.h" #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ class CFX_LinuxFontInfo : public CFX_FolderFontInfo { diff --git a/core/fxge/ge/fx_ge_text.cpp b/core/fxge/ge/fx_ge_text.cpp index c97b88e27b..eb6aafd5c6 100644 --- a/core/fxge/ge/fx_ge_text.cpp +++ b/core/fxge/ge/fx_ge_text.cpp @@ -9,6 +9,7 @@ #include "core/fxcodec/include/fx_codec.h" #include "core/fxge/ge/fx_text_int.h" +#include "core/fxge/include/cfx_fontmgr.h" #include "core/fxge/include/fx_freetype.h" #include "core/fxge/include/fx_ge.h" #include "core/fxge/include/ifx_renderdevicedriver.h" |