| // 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('-'); |
| FX_STRSIZE iPsLen = bsPsName.GetLength(); |
| FX_STRSIZE nIndex = bsDRName.Find(bsPsName); |
| if (nIndex != FX_STRNPOS && !bStrictMatch) |
| return true; |
| |
| if (nIndex != 0) |
| return false; |
| |
| int32_t iDifferLength = bsDRName.GetLength() - iPsLen; |
| if (iDifferLength > 1 || (bBold || bItalic)) { |
| FX_STRSIZE iBoldIndex = bsDRName.Find("Bold"); |
| bool bBoldFont = iBoldIndex != FX_STRNPOS; |
| if (bBold != bBoldFont) |
| return false; |
| |
| if (bBoldFont) { |
| iDifferLength = |
| std::min(iDifferLength - 4, bsDRName.GetLength() - iBoldIndex - 4); |
| } |
| bool bItalicFont = true; |
| if (bsDRName.Find("Italic") != FX_STRNPOS) { |
| iDifferLength -= 6; |
| } else if (bsDRName.Find("It") != FX_STRNPOS) { |
| iDifferLength -= 2; |
| } else if (bsDRName.Find("Oblique") != FX_STRNPOS) { |
| 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; |
| } |