1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "xfa/fgas/font/cfgas_gefont.h"
8 
9 #include <memory>
10 #include <utility>
11 
12 #include "build/build_config.h"
13 #include "core/fpdfapi/font/cpdf_font.h"
14 #include "core/fxcrt/fx_codepage.h"
15 #include "core/fxge/cfx_font.h"
16 #include "core/fxge/cfx_substfont.h"
17 #include "core/fxge/cfx_unicodeencodingex.h"
18 #include "core/fxge/fx_font.h"
19 #include "third_party/base/ptr_util.h"
20 #include "xfa/fgas/font/fgas_fontutils.h"
21 
22 // static
LoadFont(const wchar_t * pszFontFamily,uint32_t dwFontStyles,uint16_t wCodePage,CFGAS_FontMgr * pFontMgr)23 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(const wchar_t* pszFontFamily,
24                                                uint32_t dwFontStyles,
25                                                uint16_t wCodePage,
26                                                CFGAS_FontMgr* pFontMgr) {
27 #if defined(OS_WIN)
28   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
29   if (!pFont->LoadFontInternal(pszFontFamily, dwFontStyles, wCodePage))
30     return nullptr;
31   return pFont;
32 #else
33   if (!pFontMgr)
34     return nullptr;
35   return pFontMgr->GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
36 #endif
37 }
38 
39 // static
LoadFont(const RetainPtr<CPDF_Font> & pPDFFont,CFGAS_FontMgr * pFontMgr)40 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
41     const RetainPtr<CPDF_Font>& pPDFFont,
42     CFGAS_FontMgr* pFontMgr) {
43   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
44   if (!pFont->LoadFontInternal(pPDFFont))
45     return nullptr;
46 
47   return pFont;
48 }
49 
50 // static
LoadFont(std::unique_ptr<CFX_Font> pInternalFont,CFGAS_FontMgr * pFontMgr)51 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
52     std::unique_ptr<CFX_Font> pInternalFont,
53     CFGAS_FontMgr* pFontMgr) {
54   auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
55   if (!pFont->LoadFontInternal(std::move(pInternalFont)))
56     return nullptr;
57   return pFont;
58 }
59 
60 // static
LoadStockFont(CPDF_Document * pDoc,CFGAS_FontMgr * pMgr,const ByteString & font_family)61 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadStockFont(
62     CPDF_Document* pDoc,
63     CFGAS_FontMgr* pMgr,
64     const ByteString& font_family) {
65   RetainPtr<CPDF_Font> stock_font =
66       CPDF_Font::GetStockFont(pDoc, font_family.AsStringView());
67   return stock_font ? CFGAS_GEFont::LoadFont(stock_font, pMgr) : nullptr;
68 }
69 
CFGAS_GEFont(CFGAS_FontMgr * pFontMgr)70 CFGAS_GEFont::CFGAS_GEFont(CFGAS_FontMgr* pFontMgr) : m_pFontMgr(pFontMgr) {}
71 
72 CFGAS_GEFont::~CFGAS_GEFont() = default;
73 
74 #if defined(OS_WIN)
LoadFontInternal(const wchar_t * pszFontFamily,uint32_t dwFontStyles,uint16_t wCodePage)75 bool CFGAS_GEFont::LoadFontInternal(const wchar_t* pszFontFamily,
76                                     uint32_t dwFontStyles,
77                                     uint16_t wCodePage) {
78   if (m_pFont)
79     return false;
80   ByteString csFontFamily;
81   if (pszFontFamily)
82     csFontFamily = WideString(pszFontFamily).ToDefANSI();
83 
84   int32_t iWeight =
85       FontStyleIsForceBold(dwFontStyles) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
86   m_pFont = pdfium::MakeUnique<CFX_Font>();
87   if (FontStyleIsItalic(dwFontStyles) && FontStyleIsForceBold(dwFontStyles))
88     csFontFamily += ",BoldItalic";
89   else if (FontStyleIsForceBold(dwFontStyles))
90     csFontFamily += ",Bold";
91   else if (FontStyleIsItalic(dwFontStyles))
92     csFontFamily += ",Italic";
93 
94   m_pFont->LoadSubst(csFontFamily, true, dwFontStyles, iWeight, 0, wCodePage,
95                      false);
96   return m_pFont->GetFaceRec() && InitFont();
97 }
98 #endif  // defined(OS_WIN)
99 
LoadFontInternal(const RetainPtr<CPDF_Font> & pPDFFont)100 bool CFGAS_GEFont::LoadFontInternal(const RetainPtr<CPDF_Font>& pPDFFont) {
101   CFX_Font* pExternalFont = pPDFFont->GetFont();
102   if (m_pFont || !pExternalFont)
103     return false;
104 
105   m_pFont = pExternalFont;
106   if (!InitFont())
107     return false;
108 
109   m_pPDFFont = pPDFFont;  // Keep pPDFFont alive for the duration.
110   return true;
111 }
112 
LoadFontInternal(std::unique_ptr<CFX_Font> pInternalFont)113 bool CFGAS_GEFont::LoadFontInternal(std::unique_ptr<CFX_Font> pInternalFont) {
114   if (m_pFont || !pInternalFont)
115     return false;
116 
117   m_pFont = std::move(pInternalFont);
118   return InitFont();
119 }
120 
InitFont()121 bool CFGAS_GEFont::InitFont() {
122   if (!m_pFont)
123     return false;
124 
125   if (m_pFontEncoding)
126     return true;
127 
128   m_pFontEncoding = FX_CreateFontEncodingEx(m_pFont.Get());
129   return !!m_pFontEncoding;
130 }
131 
GetFamilyName() const132 WideString CFGAS_GEFont::GetFamilyName() const {
133   CFX_SubstFont* subst_font = m_pFont->GetSubstFont();
134   ByteString family_name = subst_font && !subst_font->m_Family.IsEmpty()
135                                ? subst_font->m_Family
136                                : m_pFont->GetFamilyName();
137   return WideString::FromDefANSI(family_name.AsStringView());
138 }
139 
GetFontStyles() const140 uint32_t CFGAS_GEFont::GetFontStyles() const {
141   ASSERT(m_pFont);
142   if (m_dwLogFontStyle.has_value())
143     return m_dwLogFontStyle.value();
144 
145   uint32_t dwStyles = 0;
146   auto* pSubstFont = m_pFont->GetSubstFont();
147   if (pSubstFont) {
148     if (pSubstFont->m_Weight == FXFONT_FW_BOLD)
149       dwStyles |= FXFONT_FORCE_BOLD;
150   } else {
151     if (m_pFont->IsBold())
152       dwStyles |= FXFONT_FORCE_BOLD;
153     if (m_pFont->IsItalic())
154       dwStyles |= FXFONT_ITALIC;
155   }
156   return dwStyles;
157 }
158 
GetCharWidth(wchar_t wUnicode,int32_t * pWidth)159 bool CFGAS_GEFont::GetCharWidth(wchar_t wUnicode, int32_t* pWidth) {
160   auto it = m_CharWidthMap.find(wUnicode);
161   *pWidth = it != m_CharWidthMap.end() ? it->second : 0;
162   if (*pWidth == 65535)
163     return false;
164 
165   if (*pWidth > 0)
166     return true;
167 
168   RetainPtr<CFGAS_GEFont> pFont;
169   int32_t iGlyph;
170   std::tie(iGlyph, pFont) = GetGlyphIndexAndFont(wUnicode, true);
171   if (iGlyph != 0xFFFF && pFont) {
172     if (pFont == this) {
173       *pWidth = m_pFont->GetGlyphWidth(iGlyph);
174       if (*pWidth < 0)
175         *pWidth = -1;
176     } else if (pFont->GetCharWidth(wUnicode, pWidth)) {
177       return true;
178     }
179   } else {
180     *pWidth = -1;
181   }
182 
183   m_CharWidthMap[wUnicode] = *pWidth;
184   return *pWidth > 0;
185 }
186 
GetCharBBox(wchar_t wUnicode,FX_RECT * bbox)187 bool CFGAS_GEFont::GetCharBBox(wchar_t wUnicode, FX_RECT* bbox) {
188   auto it = m_BBoxMap.find(wUnicode);
189   if (it != m_BBoxMap.end()) {
190     *bbox = it->second;
191     return true;
192   }
193 
194   RetainPtr<CFGAS_GEFont> pFont;
195   int32_t iGlyph;
196   std::tie(iGlyph, pFont) = GetGlyphIndexAndFont(wUnicode, true);
197   if (!pFont || iGlyph == 0xFFFF)
198     return false;
199 
200   if (pFont.Get() != this)
201     return pFont->GetCharBBox(wUnicode, bbox);
202 
203   FX_RECT rtBBox;
204   if (!m_pFont->GetGlyphBBox(iGlyph, &rtBBox))
205     return false;
206 
207   m_BBoxMap[wUnicode] = rtBBox;
208   *bbox = rtBBox;
209   return true;
210 }
211 
GetBBox(FX_RECT * bbox)212 bool CFGAS_GEFont::GetBBox(FX_RECT* bbox) {
213   return m_pFont->GetBBox(bbox);
214 }
215 
GetGlyphIndex(wchar_t wUnicode)216 int32_t CFGAS_GEFont::GetGlyphIndex(wchar_t wUnicode) {
217   int32_t glyph;
218   RetainPtr<CFGAS_GEFont> font;
219   std::tie(glyph, font) = GetGlyphIndexAndFont(wUnicode, true);
220   return glyph;
221 }
222 
GetGlyphIndexAndFont(wchar_t wUnicode,bool bRecursive)223 std::pair<int32_t, RetainPtr<CFGAS_GEFont>> CFGAS_GEFont::GetGlyphIndexAndFont(
224     wchar_t wUnicode,
225     bool bRecursive) {
226   int32_t iGlyphIndex = m_pFontEncoding->GlyphFromCharCode(wUnicode);
227   if (iGlyphIndex > 0)
228     return {iGlyphIndex, pdfium::WrapRetain(this)};
229 
230   const FGAS_FONTUSB* pFontUSB = FGAS_GetUnicodeBitField(wUnicode);
231   if (!pFontUSB)
232     return {0xFFFF, nullptr};
233 
234   uint16_t wBitField = pFontUSB->wBitField;
235   if (wBitField >= 128)
236     return {0xFFFF, nullptr};
237 
238   auto it = m_FontMapper.find(wUnicode);
239   if (it != m_FontMapper.end() && it->second && it->second.Get() != this) {
240     RetainPtr<CFGAS_GEFont> font;
241     std::tie(iGlyphIndex, font) =
242         it->second->GetGlyphIndexAndFont(wUnicode, false);
243     if (iGlyphIndex != 0xFFFF) {
244       for (size_t i = 0; i < m_SubstFonts.size(); ++i) {
245         if (m_SubstFonts[i] == it->second)
246           return {(iGlyphIndex | ((i + 1) << 24)), it->second};
247       }
248     }
249   }
250   if (!m_pFontMgr || !bRecursive)
251     return {0xFFFF, nullptr};
252 
253   WideString wsFamily = GetFamilyName();
254   RetainPtr<CFGAS_GEFont> pFont =
255       m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), wsFamily.c_str());
256 #if !defined(OS_WIN)
257   if (!pFont)
258     pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), nullptr);
259 #endif
260   if (!pFont || pFont == this)  // Avoids direct cycles below.
261     return {0xFFFF, nullptr};
262 
263   m_FontMapper[wUnicode] = pFont;
264   m_SubstFonts.push_back(pFont);
265 
266   RetainPtr<CFGAS_GEFont> font;
267   std::tie(iGlyphIndex, font) = pFont->GetGlyphIndexAndFont(wUnicode, false);
268   if (iGlyphIndex == 0xFFFF)
269     return {0xFFFF, nullptr};
270 
271   return {(iGlyphIndex | (m_SubstFonts.size() << 24)), pFont};
272 }
273 
GetAscent() const274 int32_t CFGAS_GEFont::GetAscent() const {
275   return m_pFont->GetAscent();
276 }
277 
GetDescent() const278 int32_t CFGAS_GEFont::GetDescent() const {
279   return m_pFont->GetDescent();
280 }
281 
GetSubstFont(int32_t iGlyphIndex)282 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::GetSubstFont(int32_t iGlyphIndex) {
283   iGlyphIndex = static_cast<uint32_t>(iGlyphIndex) >> 24;
284   if (iGlyphIndex == 0)
285     return pdfium::WrapRetain(this);
286   return m_SubstFonts[iGlyphIndex - 1];
287 }
288