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