blob: 28a7e1e8d84b84c3abe27cacddda25d6791827bb [file] [log] [blame]
// 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/cfx_fontmgr.h"
#include <memory>
#include <utility>
#include "core/fxge/cfx_fontmapper.h"
#include "core/fxge/cfx_substfont.h"
#include "core/fxge/cttfontdesc.h"
#include "core/fxge/fontdata/chromefontdata/chromefontdata.h"
#include "core/fxge/fx_font.h"
#include "core/fxge/systemfontinfo_iface.h"
#include "third_party/base/ptr_util.h"
namespace {
struct BuiltinFont {
const uint8_t* m_pFontData; // Raw, POD struct.
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},
};
ByteString KeyNameFromFace(const ByteString& face_name,
int weight,
bool bItalic) {
ByteString key(face_name);
key += ',';
key += ByteString::FormatInteger(weight);
key += bItalic ? 'I' : 'N';
return key;
}
ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) {
return ByteString::Format("%d:%d", ttc_size, checksum);
}
int GetTTCIndex(const uint8_t* pFontData,
uint32_t ttc_size,
uint32_t font_offset) {
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;
}
return index < nfont ? index : 0;
}
} // namespace
CFX_FontMgr::CFX_FontMgr()
: m_pBuiltinMapper(pdfium::MakeUnique<CFX_FontMapper>(this)) {}
CFX_FontMgr::~CFX_FontMgr() = default;
void CFX_FontMgr::InitFTLibrary() {
if (m_FTLibrary)
return;
FXFT_LibraryRec* pLibrary = nullptr;
FT_Init_FreeType(&pLibrary);
m_FTLibrary.reset(pLibrary);
m_FTLibrarySupportsHinting =
SetLcdFilterMode() || FreeTypeVersionSupportsHinting();
}
void CFX_FontMgr::SetSystemFontInfo(
std::unique_ptr<SystemFontInfoIface> pFontInfo) {
m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo));
}
FXFT_FaceRec* CFX_FontMgr::FindSubstFont(const ByteString& face_name,
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_FaceRec* CFX_FontMgr::GetCachedFace(const ByteString& face_name,
int weight,
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.get();
*pFontData = pFontDesc->FontData();
pFontDesc->AddRef();
return pFontDesc->GetFace(0);
}
FXFT_FaceRec* CFX_FontMgr::AddCachedFace(
const ByteString& face_name,
int weight,
bool bItalic,
std::unique_ptr<uint8_t, FxFreeDeleter> pData,
uint32_t size,
int face_index) {
InitFTLibrary();
FXFT_FaceRec* face = nullptr;
int ret = FT_New_Memory_Face(m_FTLibrary.get(), pData.get(), size, face_index,
&face);
if (ret)
return nullptr;
ret = FT_Set_Pixel_Sizes(face, 64, 64);
if (ret)
return nullptr;
auto pFontDesc = pdfium::MakeUnique<CTTFontDesc>(std::move(pData));
pFontDesc->SetFace(0, face);
CTTFontDesc* pResult = pFontDesc.get();
m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = std::move(pFontDesc);
return pResult->GetFace(0);
}
FXFT_FaceRec* 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.get();
*pFontData = pFontDesc->FontData();
int face_index = GetTTCIndex(pFontDesc->FontData(), ttc_size, font_offset);
if (!pFontDesc->GetFace(face_index)) {
pFontDesc->SetFace(face_index, GetFixedFace({pFontDesc->FontData(),
static_cast<size_t>(ttc_size)},
face_index));
}
pFontDesc->AddRef();
return pFontDesc->GetFace(face_index);
}
FXFT_FaceRec* CFX_FontMgr::AddCachedTTCFace(
int ttc_size,
uint32_t checksum,
std::unique_ptr<uint8_t, FxFreeDeleter> pData,
uint32_t size,
int font_offset) {
int face_index = GetTTCIndex(pData.get(), ttc_size, font_offset);
FXFT_FaceRec* face =
GetFixedFace({pData.get(), static_cast<size_t>(ttc_size)}, face_index);
auto pFontDesc = pdfium::MakeUnique<CTTFontDesc>(std::move(pData));
pFontDesc->SetFace(face_index, face);
m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = std::move(pFontDesc);
return face;
}
FXFT_FaceRec* CFX_FontMgr::GetFixedFace(pdfium::span<const uint8_t> span,
int face_index) {
InitFTLibrary();
FXFT_FaceRec* face = nullptr;
if (FT_New_Memory_Face(m_FTLibrary.get(), span.data(), span.size(),
face_index, &face)) {
return nullptr;
}
return FT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face;
}
void CFX_FontMgr::ReleaseFace(FXFT_FaceRec* face) {
if (!face)
return;
bool bNeedFaceDone = true;
for (auto it = m_FaceMap.begin(); it != m_FaceMap.end(); ++it) {
CTTFontDesc::ReleaseStatus nRet = it->second->ReleaseFace(face);
if (nRet == CTTFontDesc::kNotAppropriate)
continue;
bNeedFaceDone = false;
if (nRet == CTTFontDesc::kReleased)
m_FaceMap.erase(it);
break;
}
if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face))
FT_Done_Face(face);
}
// static
Optional<pdfium::span<const uint8_t>> CFX_FontMgr::GetBuiltinFont(
size_t index) {
if (index < FX_ArraySize(g_FoxitFonts)) {
return pdfium::make_span(g_FoxitFonts[index].m_pFontData,
g_FoxitFonts[index].m_dwSize);
}
size_t mm_index = index - FX_ArraySize(g_FoxitFonts);
if (mm_index < FX_ArraySize(g_MMFonts)) {
return pdfium::make_span(g_MMFonts[mm_index].m_pFontData,
g_MMFonts[mm_index].m_dwSize);
}
return {};
}
bool CFX_FontMgr::FreeTypeVersionSupportsHinting() const {
FT_Int major;
FT_Int minor;
FT_Int patch;
FT_Library_Version(m_FTLibrary.get(), &major, &minor, &patch);
// Freetype versions >= 2.8.1 support hinting even if subpixel rendering is
// disabled. https://sourceforge.net/projects/freetype/files/freetype2/2.8.1/
return major > 2 || (major == 2 && minor > 8) ||
(major == 2 && minor == 8 && patch >= 1);
}
bool CFX_FontMgr::SetLcdFilterMode() const {
return FT_Library_SetLcdFilter(m_FTLibrary.get(), FT_LCD_FILTER_DEFAULT) !=
FT_Err_Unimplemented_Feature;
}