diff options
Diffstat (limited to 'xfa/fxfa/cxfa_pdffontmgr.cpp')
-rw-r--r-- | xfa/fxfa/cxfa_pdffontmgr.cpp | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/xfa/fxfa/cxfa_pdffontmgr.cpp b/xfa/fxfa/cxfa_pdffontmgr.cpp new file mode 100644 index 0000000000..cadb7cbab5 --- /dev/null +++ b/xfa/fxfa/cxfa_pdffontmgr.cpp @@ -0,0 +1,208 @@ +// 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/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->m_Font, 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; +} |