// 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/fpdfapi/fpdf_font/include/cpdf_font.h"
|
|
#include "core/fpdfapi/fpdf_font/cpdf_truetypefont.h"
|
#include "core/fpdfapi/fpdf_font/cpdf_type1font.h"
|
#include "core/fpdfapi/fpdf_font/cpdf_type3font.h"
|
#include "core/fpdfapi/fpdf_font/font_int.h"
|
#include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h"
|
#include "core/fpdfapi/fpdf_page/cpdf_pagemodule.h"
|
#include "core/fpdfapi/fpdf_page/pageint.h"
|
#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
|
#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
|
#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
|
#include "core/fpdfapi/fpdf_parser/include/cpdf_name.h"
|
#include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h"
|
#include "core/fpdfapi/include/cpdf_modulemgr.h"
|
#include "core/fxge/include/fx_freetype.h"
|
|
namespace {
|
|
const uint8_t ChineseFontNames[][5] = {{0xCB, 0xCE, 0xCC, 0xE5, 0x00},
|
{0xBF, 0xAC, 0xCC, 0xE5, 0x00},
|
{0xBA, 0xDA, 0xCC, 0xE5, 0x00},
|
{0xB7, 0xC2, 0xCB, 0xCE, 0x00},
|
{0xD0, 0xC2, 0xCB, 0xCE, 0x00}};
|
|
FX_BOOL GetPredefinedEncoding(int& basemap, const CFX_ByteString& value) {
|
if (value == "WinAnsiEncoding")
|
basemap = PDFFONT_ENCODING_WINANSI;
|
else if (value == "MacRomanEncoding")
|
basemap = PDFFONT_ENCODING_MACROMAN;
|
else if (value == "MacExpertEncoding")
|
basemap = PDFFONT_ENCODING_MACEXPERT;
|
else if (value == "PDFDocEncoding")
|
basemap = PDFFONT_ENCODING_PDFDOC;
|
else
|
return FALSE;
|
return TRUE;
|
}
|
|
} // namespace
|
|
CPDF_Font::CPDF_Font()
|
: m_pFontFile(nullptr),
|
m_pFontDict(nullptr),
|
m_bToUnicodeLoaded(FALSE),
|
m_Flags(0),
|
m_StemV(0),
|
m_Ascent(0),
|
m_Descent(0),
|
m_ItalicAngle(0) {}
|
|
CPDF_Font::~CPDF_Font() {
|
if (m_pFontFile) {
|
m_pDocument->GetPageData()->ReleaseFontFileStreamAcc(
|
const_cast<CPDF_Stream*>(m_pFontFile->GetStream()->AsStream()));
|
}
|
}
|
|
bool CPDF_Font::IsType1Font() const {
|
return false;
|
}
|
|
bool CPDF_Font::IsTrueTypeFont() const {
|
return false;
|
}
|
|
bool CPDF_Font::IsType3Font() const {
|
return false;
|
}
|
|
bool CPDF_Font::IsCIDFont() const {
|
return false;
|
}
|
|
const CPDF_Type1Font* CPDF_Font::AsType1Font() const {
|
return nullptr;
|
}
|
|
CPDF_Type1Font* CPDF_Font::AsType1Font() {
|
return nullptr;
|
}
|
|
const CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() const {
|
return nullptr;
|
}
|
|
CPDF_TrueTypeFont* CPDF_Font::AsTrueTypeFont() {
|
return nullptr;
|
}
|
|
const CPDF_Type3Font* CPDF_Font::AsType3Font() const {
|
return nullptr;
|
}
|
|
CPDF_Type3Font* CPDF_Font::AsType3Font() {
|
return nullptr;
|
}
|
|
const CPDF_CIDFont* CPDF_Font::AsCIDFont() const {
|
return nullptr;
|
}
|
|
CPDF_CIDFont* CPDF_Font::AsCIDFont() {
|
return nullptr;
|
}
|
|
FX_BOOL CPDF_Font::IsUnicodeCompatible() const {
|
return FALSE;
|
}
|
|
int CPDF_Font::CountChar(const FX_CHAR* pString, int size) const {
|
return size;
|
}
|
|
int CPDF_Font::GetCharSize(uint32_t charcode) const {
|
return 1;
|
}
|
|
int CPDF_Font::GlyphFromCharCodeExt(uint32_t charcode) {
|
return GlyphFromCharCode(charcode, nullptr);
|
}
|
|
FX_BOOL CPDF_Font::IsVertWriting() const {
|
const CPDF_CIDFont* pCIDFont = AsCIDFont();
|
return pCIDFont ? pCIDFont->IsVertWriting() : m_Font.IsVertical();
|
}
|
|
int CPDF_Font::AppendChar(FX_CHAR* buf, uint32_t charcode) const {
|
*buf = static_cast<FX_CHAR>(charcode);
|
return 1;
|
}
|
|
void CPDF_Font::AppendChar(CFX_ByteString& str, uint32_t charcode) const {
|
char buf[4];
|
int len = AppendChar(buf, charcode);
|
if (len == 1) {
|
str += buf[0];
|
} else {
|
str += CFX_ByteString(buf, len);
|
}
|
}
|
|
CFX_WideString CPDF_Font::UnicodeFromCharCode(uint32_t charcode) const {
|
if (!m_bToUnicodeLoaded)
|
LoadUnicodeMap();
|
|
return m_pToUnicodeMap ? m_pToUnicodeMap->Lookup(charcode) : CFX_WideString();
|
}
|
|
uint32_t CPDF_Font::CharCodeFromUnicode(FX_WCHAR unicode) const {
|
if (!m_bToUnicodeLoaded)
|
LoadUnicodeMap();
|
|
return m_pToUnicodeMap ? m_pToUnicodeMap->ReverseLookup(unicode) : 0;
|
}
|
|
void CPDF_Font::LoadFontDescriptor(CPDF_Dictionary* pFontDesc) {
|
m_Flags = pFontDesc->GetIntegerBy("Flags", PDFFONT_NONSYMBOLIC);
|
int ItalicAngle = 0;
|
FX_BOOL bExistItalicAngle = FALSE;
|
if (pFontDesc->KeyExist("ItalicAngle")) {
|
ItalicAngle = pFontDesc->GetIntegerBy("ItalicAngle");
|
bExistItalicAngle = TRUE;
|
}
|
if (ItalicAngle < 0) {
|
m_Flags |= PDFFONT_ITALIC;
|
m_ItalicAngle = ItalicAngle;
|
}
|
FX_BOOL bExistStemV = FALSE;
|
if (pFontDesc->KeyExist("StemV")) {
|
m_StemV = pFontDesc->GetIntegerBy("StemV");
|
bExistStemV = TRUE;
|
}
|
FX_BOOL bExistAscent = FALSE;
|
if (pFontDesc->KeyExist("Ascent")) {
|
m_Ascent = pFontDesc->GetIntegerBy("Ascent");
|
bExistAscent = TRUE;
|
}
|
FX_BOOL bExistDescent = FALSE;
|
if (pFontDesc->KeyExist("Descent")) {
|
m_Descent = pFontDesc->GetIntegerBy("Descent");
|
bExistDescent = TRUE;
|
}
|
FX_BOOL bExistCapHeight = FALSE;
|
if (pFontDesc->KeyExist("CapHeight")) {
|
bExistCapHeight = TRUE;
|
}
|
if (bExistItalicAngle && bExistAscent && bExistCapHeight && bExistDescent &&
|
bExistStemV) {
|
m_Flags |= PDFFONT_USEEXTERNATTR;
|
}
|
if (m_Descent > 10) {
|
m_Descent = -m_Descent;
|
}
|
CPDF_Array* pBBox = pFontDesc->GetArrayBy("FontBBox");
|
if (pBBox) {
|
m_FontBBox.left = pBBox->GetIntegerAt(0);
|
m_FontBBox.bottom = pBBox->GetIntegerAt(1);
|
m_FontBBox.right = pBBox->GetIntegerAt(2);
|
m_FontBBox.top = pBBox->GetIntegerAt(3);
|
}
|
|
CPDF_Stream* pFontFile = pFontDesc->GetStreamBy("FontFile");
|
if (!pFontFile)
|
pFontFile = pFontDesc->GetStreamBy("FontFile2");
|
if (!pFontFile)
|
pFontFile = pFontDesc->GetStreamBy("FontFile3");
|
if (!pFontFile)
|
return;
|
|
m_pFontFile = m_pDocument->LoadFontFile(pFontFile);
|
if (!m_pFontFile)
|
return;
|
|
const uint8_t* pFontData = m_pFontFile->GetData();
|
uint32_t dwFontSize = m_pFontFile->GetSize();
|
if (!m_Font.LoadEmbedded(pFontData, dwFontSize)) {
|
m_pDocument->GetPageData()->ReleaseFontFileStreamAcc(
|
const_cast<CPDF_Stream*>(m_pFontFile->GetStream()->AsStream()));
|
m_pFontFile = nullptr;
|
}
|
}
|
|
void CPDF_Font::CheckFontMetrics() {
|
if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 &&
|
m_FontBBox.right == 0) {
|
FXFT_Face face = m_Font.GetFace();
|
if (face) {
|
m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(face), face);
|
m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(face), face);
|
m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(face), face);
|
m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(face), face);
|
m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face);
|
m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face);
|
} else {
|
FX_BOOL bFirst = TRUE;
|
for (int i = 0; i < 256; i++) {
|
FX_RECT rect = GetCharBBox(i);
|
if (rect.left == rect.right) {
|
continue;
|
}
|
if (bFirst) {
|
m_FontBBox = rect;
|
bFirst = FALSE;
|
} else {
|
if (m_FontBBox.top < rect.top) {
|
m_FontBBox.top = rect.top;
|
}
|
if (m_FontBBox.right < rect.right) {
|
m_FontBBox.right = rect.right;
|
}
|
if (m_FontBBox.left > rect.left) {
|
m_FontBBox.left = rect.left;
|
}
|
if (m_FontBBox.bottom > rect.bottom) {
|
m_FontBBox.bottom = rect.bottom;
|
}
|
}
|
}
|
}
|
}
|
if (m_Ascent == 0 && m_Descent == 0) {
|
FX_RECT rect = GetCharBBox('A');
|
m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top;
|
rect = GetCharBBox('g');
|
m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom;
|
}
|
}
|
|
void CPDF_Font::LoadUnicodeMap() const {
|
m_bToUnicodeLoaded = TRUE;
|
CPDF_Stream* pStream = m_pFontDict->GetStreamBy("ToUnicode");
|
if (!pStream) {
|
return;
|
}
|
m_pToUnicodeMap.reset(new CPDF_ToUnicodeMap);
|
m_pToUnicodeMap->Load(pStream);
|
}
|
|
int CPDF_Font::GetStringWidth(const FX_CHAR* pString, int size) {
|
int offset = 0;
|
int width = 0;
|
while (offset < size) {
|
uint32_t charcode = GetNextChar(pString, size, offset);
|
width += GetCharWidthF(charcode);
|
}
|
return width;
|
}
|
|
CPDF_Font* CPDF_Font::GetStockFont(CPDF_Document* pDoc,
|
const CFX_ByteStringC& name) {
|
CFX_ByteString fontname(name);
|
int font_id = PDF_GetStandardFontName(&fontname);
|
if (font_id < 0) {
|
return nullptr;
|
}
|
CPDF_FontGlobals* pFontGlobals =
|
CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
|
CPDF_Font* pFont = pFontGlobals->Find(pDoc, font_id);
|
if (pFont) {
|
return pFont;
|
}
|
CPDF_Dictionary* pDict = new CPDF_Dictionary;
|
pDict->SetAtName("Type", "Font");
|
pDict->SetAtName("Subtype", "Type1");
|
pDict->SetAtName("BaseFont", fontname);
|
pDict->SetAtName("Encoding", "WinAnsiEncoding");
|
pFont = CPDF_Font::CreateFontF(nullptr, pDict);
|
pFontGlobals->Set(pDoc, font_id, pFont);
|
return pFont;
|
}
|
|
CPDF_Font* CPDF_Font::CreateFontF(CPDF_Document* pDoc,
|
CPDF_Dictionary* pFontDict) {
|
CFX_ByteString type = pFontDict->GetStringBy("Subtype");
|
std::unique_ptr<CPDF_Font> pFont;
|
if (type == "TrueType") {
|
CFX_ByteString tag = pFontDict->GetStringBy("BaseFont").Left(4);
|
for (size_t i = 0; i < FX_ArraySize(ChineseFontNames); ++i) {
|
if (tag == CFX_ByteString(ChineseFontNames[i], 4)) {
|
CPDF_Dictionary* pFontDesc = pFontDict->GetDictBy("FontDescriptor");
|
if (!pFontDesc || !pFontDesc->KeyExist("FontFile2"))
|
pFont.reset(new CPDF_CIDFont);
|
break;
|
}
|
}
|
if (!pFont)
|
pFont.reset(new CPDF_TrueTypeFont);
|
} else if (type == "Type3") {
|
pFont.reset(new CPDF_Type3Font);
|
} else if (type == "Type0") {
|
pFont.reset(new CPDF_CIDFont);
|
} else {
|
pFont.reset(new CPDF_Type1Font);
|
}
|
pFont->m_pFontDict = pFontDict;
|
pFont->m_pDocument = pDoc;
|
pFont->m_BaseFont = pFontDict->GetStringBy("BaseFont");
|
return pFont->Load() ? pFont.release() : nullptr;
|
}
|
|
uint32_t CPDF_Font::GetNextChar(const FX_CHAR* pString,
|
int nStrLen,
|
int& offset) const {
|
if (offset < 0 || nStrLen < 1) {
|
return 0;
|
}
|
uint8_t ch = offset < nStrLen ? pString[offset++] : pString[nStrLen - 1];
|
return static_cast<uint32_t>(ch);
|
}
|
|
void CPDF_Font::LoadPDFEncoding(CPDF_Object* pEncoding,
|
int& iBaseEncoding,
|
CFX_ByteString*& pCharNames,
|
FX_BOOL bEmbedded,
|
FX_BOOL bTrueType) {
|
if (!pEncoding) {
|
if (m_BaseFont == "Symbol") {
|
iBaseEncoding = bTrueType ? PDFFONT_ENCODING_MS_SYMBOL
|
: PDFFONT_ENCODING_ADOBE_SYMBOL;
|
} else if (!bEmbedded && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {
|
iBaseEncoding = PDFFONT_ENCODING_WINANSI;
|
}
|
return;
|
}
|
if (pEncoding->IsName()) {
|
if (iBaseEncoding == PDFFONT_ENCODING_ADOBE_SYMBOL ||
|
iBaseEncoding == PDFFONT_ENCODING_ZAPFDINGBATS) {
|
return;
|
}
|
if ((m_Flags & PDFFONT_SYMBOLIC) && m_BaseFont == "Symbol") {
|
if (!bTrueType) {
|
iBaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;
|
}
|
return;
|
}
|
CFX_ByteString bsEncoding = pEncoding->GetString();
|
if (bsEncoding.Compare("MacExpertEncoding") == 0) {
|
bsEncoding = "WinAnsiEncoding";
|
}
|
GetPredefinedEncoding(iBaseEncoding, bsEncoding);
|
return;
|
}
|
|
CPDF_Dictionary* pDict = pEncoding->AsDictionary();
|
if (!pDict)
|
return;
|
|
if (iBaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL &&
|
iBaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS) {
|
CFX_ByteString bsEncoding = pDict->GetStringBy("BaseEncoding");
|
if (bsEncoding.Compare("MacExpertEncoding") == 0 && bTrueType) {
|
bsEncoding = "WinAnsiEncoding";
|
}
|
GetPredefinedEncoding(iBaseEncoding, bsEncoding);
|
}
|
if ((!bEmbedded || bTrueType) && iBaseEncoding == PDFFONT_ENCODING_BUILTIN) {
|
iBaseEncoding = PDFFONT_ENCODING_STANDARD;
|
}
|
CPDF_Array* pDiffs = pDict->GetArrayBy("Differences");
|
if (!pDiffs) {
|
return;
|
}
|
pCharNames = new CFX_ByteString[256];
|
uint32_t cur_code = 0;
|
for (uint32_t i = 0; i < pDiffs->GetCount(); i++) {
|
CPDF_Object* pElement = pDiffs->GetDirectObjectAt(i);
|
if (!pElement)
|
continue;
|
|
if (CPDF_Name* pName = pElement->AsName()) {
|
if (cur_code < 256)
|
pCharNames[cur_code] = pName->GetString();
|
cur_code++;
|
} else {
|
cur_code = pElement->GetInteger();
|
}
|
}
|
}
|
|
FX_BOOL CPDF_Font::IsStandardFont() const {
|
if (!IsType1Font())
|
return FALSE;
|
if (m_pFontFile)
|
return FALSE;
|
if (AsType1Font()->GetBase14Font() < 0)
|
return FALSE;
|
return TRUE;
|
}
|
|
const FX_CHAR* CPDF_Font::GetAdobeCharName(int iBaseEncoding,
|
const CFX_ByteString* pCharNames,
|
int charcode) {
|
if (charcode < 0 || charcode >= 256) {
|
ASSERT(false);
|
return nullptr;
|
}
|
|
if (pCharNames && !pCharNames[charcode].IsEmpty())
|
return pCharNames[charcode].c_str();
|
|
const FX_CHAR* name = nullptr;
|
if (iBaseEncoding)
|
name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode);
|
return name && name[0] ? name : nullptr;
|
}
|