blob: 77c4433f987a431bd0283741cffcf17601842a94 [file] [log] [blame]
// Copyright 2017 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 "xfa/fxfa/cxfa_pdffontmgr.h"
#include <algorithm>
#include "core/fpdfapi/font/cpdf_font.h"
#include "xfa/fgas/font/cfgas_gefont.h"
#include "xfa/fxfa/cxfa_ffapp.h"
namespace {
// The 5 names per entry are: PsName, Normal, Bold, Italic, BoldItalic.
const char* const g_XFAPDFFontName[][5] = {
{"Adobe PI Std", "AdobePIStd", "AdobePIStd", "AdobePIStd", "AdobePIStd"},
{"Myriad Pro Light", "MyriadPro-Light", "MyriadPro-Semibold",
"MyriadPro-LightIt", "MyriadPro-SemiboldIt"},
};
} // namespace
CXFA_PDFFontMgr::CXFA_PDFFontMgr(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {}
CXFA_PDFFontMgr::~CXFA_PDFFontMgr() {}
CFX_RetainPtr<CFGAS_GEFont> CXFA_PDFFontMgr::FindFont(
const CFX_ByteString& strPsName,
bool bBold,
bool bItalic,
CPDF_Font** pDstPDFFont,
bool bStrictMatch) {
CPDF_Document* pDoc = m_pDoc->GetPDFDoc();
if (!pDoc)
return nullptr;
CPDF_Dictionary* pFontSetDict =
pDoc->GetRoot()->GetDictFor("AcroForm")->GetDictFor("DR");
if (!pFontSetDict)
return nullptr;
pFontSetDict = pFontSetDict->GetDictFor("Font");
if (!pFontSetDict)
return nullptr;
CFX_ByteString name = strPsName;
name.Remove(' ');
CFGAS_FontMgr* pFDEFontMgr = m_pDoc->GetApp()->GetFDEFontMgr();
for (const auto& it : *pFontSetDict) {
const CFX_ByteString& key = it.first;
CPDF_Object* pObj = it.second.get();
if (!PsNameMatchDRFontName(name.AsStringC(), bBold, bItalic, key,
bStrictMatch)) {
continue;
}
CPDF_Dictionary* pFontDict = ToDictionary(pObj->GetDirect());
if (!pFontDict || pFontDict->GetStringFor("Type") != "Font") {
return nullptr;
}
CPDF_Font* pPDFFont = pDoc->LoadFont(pFontDict);
if (!pPDFFont) {
return nullptr;
}
if (!pPDFFont->IsEmbedded()) {
*pDstPDFFont = pPDFFont;
return nullptr;
}
return CFGAS_GEFont::LoadFont(pPDFFont->GetFont(), pFDEFontMgr);
}
return nullptr;
}
CFX_RetainPtr<CFGAS_GEFont> CXFA_PDFFontMgr::GetFont(
const CFX_WideStringC& wsFontFamily,
uint32_t dwFontStyles,
CPDF_Font** pPDFFont,
bool bStrictMatch) {
uint32_t dwHashCode = FX_HashCode_GetW(wsFontFamily, false);
CFX_ByteString strKey;
strKey.Format("%u%u", dwHashCode, dwFontStyles);
auto it = m_FontMap.find(strKey);
if (it != m_FontMap.end())
return it->second;
CFX_ByteString bsPsName =
CFX_ByteString::FromUnicode(CFX_WideString(wsFontFamily));
bool bBold = (dwFontStyles & FX_FONTSTYLE_Bold) == FX_FONTSTYLE_Bold;
bool bItalic = (dwFontStyles & FX_FONTSTYLE_Italic) == FX_FONTSTYLE_Italic;
CFX_ByteString strFontName = PsNameToFontName(bsPsName, bBold, bItalic);
CFX_RetainPtr<CFGAS_GEFont> pFont =
FindFont(strFontName, bBold, bItalic, pPDFFont, bStrictMatch);
if (pFont)
m_FontMap[strKey] = pFont;
return pFont;
}
CFX_ByteString CXFA_PDFFontMgr::PsNameToFontName(
const CFX_ByteString& strPsName,
bool bBold,
bool bItalic) {
for (size_t i = 0; i < FX_ArraySize(g_XFAPDFFontName); ++i) {
if (strPsName == g_XFAPDFFontName[i][0]) {
size_t index = 1;
if (bBold)
++index;
if (bItalic)
index += 2;
return g_XFAPDFFontName[i][index];
}
}
return strPsName;
}
bool CXFA_PDFFontMgr::PsNameMatchDRFontName(const CFX_ByteStringC& bsPsName,
bool bBold,
bool bItalic,
const CFX_ByteString& bsDRFontName,
bool bStrictMatch) {
CFX_ByteString bsDRName = bsDRFontName;
bsDRName.Remove('-');
int32_t iPsLen = bsPsName.GetLength();
int32_t nIndex = bsDRName.Find(bsPsName);
if (nIndex != -1 && !bStrictMatch)
return true;
if (nIndex != 0)
return false;
int32_t iDifferLength = bsDRName.GetLength() - iPsLen;
if (iDifferLength > 1 || (bBold || bItalic)) {
int32_t iBoldIndex = bsDRName.Find("Bold");
bool bBoldFont = iBoldIndex > 0;
if (bBold != bBoldFont)
return false;
if (bBoldFont) {
iDifferLength =
std::min(iDifferLength - 4, bsDRName.GetLength() - iBoldIndex - 4);
}
bool bItalicFont = true;
if (bsDRName.Find("Italic") > 0) {
iDifferLength -= 6;
} else if (bsDRName.Find("It") > 0) {
iDifferLength -= 2;
} else if (bsDRName.Find("Oblique") > 0) {
iDifferLength -= 7;
} else {
bItalicFont = false;
}
if (bItalic != bItalicFont)
return false;
if (iDifferLength > 1) {
CFX_ByteString bsDRTailer = bsDRName.Right(iDifferLength);
if (bsDRTailer == "MT" || bsDRTailer == "PSMT" ||
bsDRTailer == "Regular" || bsDRTailer == "Reg") {
return true;
}
if (bBoldFont || bItalicFont)
return false;
bool bMatch = false;
switch (bsPsName.GetAt(iPsLen - 1)) {
case 'L': {
if (bsDRName.Right(5) == "Light") {
bMatch = true;
}
} break;
case 'R': {
if (bsDRName.Right(7) == "Regular" || bsDRName.Right(3) == "Reg") {
bMatch = true;
}
} break;
case 'M': {
if (bsDRName.Right(5) == "Medium") {
bMatch = true;
}
} break;
default:
break;
}
return bMatch;
}
}
return true;
}
bool CXFA_PDFFontMgr::GetCharWidth(const CFX_RetainPtr<CFGAS_GEFont>& pFont,
wchar_t wUnicode,
bool bCharCode,
int32_t* pWidth) {
if (wUnicode != 0x20 || bCharCode)
return false;
auto it = m_FDE2PDFFont.find(pFont);
if (it == m_FDE2PDFFont.end())
return false;
CPDF_Font* pPDFFont = it->second;
*pWidth = pPDFFont->GetCharWidthF(pPDFFont->CharCodeFromUnicode(wUnicode));
return true;
}
void CXFA_PDFFontMgr::SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont,
CPDF_Font* pPDFFont) {
m_FDE2PDFFont[pFont] = pPDFFont;
}