| Index: core/fxge/ge/cfx_folderfontinfo.cpp
|
| diff --git a/core/fxge/ge/cfx_folderfontinfo.cpp b/core/fxge/ge/cfx_folderfontinfo.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5bd5b29c79c1e60b6bda005a4cd39abdaaf63691
|
| --- /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;
|
| +}
|
|
|