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 "core/fxcrt/fx_codepage.h"
13 #include "core/fxge/cfx_font.h"
14 #include "core/fxge/cfx_substfont.h"
15 #include "core/fxge/cfx_unicodeencoding.h"
16 #include "core/fxge/cfx_unicodeencodingex.h"
17 #include "third_party/base/ptr_util.h"
18 #include "xfa/fgas/font/fgas_fontutils.h"
19
20 // static
LoadFont(const wchar_t * pszFontFamily,uint32_t dwFontStyles,uint16_t wCodePage,CFGAS_FontMgr * pFontMgr)21 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(const wchar_t* pszFontFamily,
22 uint32_t dwFontStyles,
23 uint16_t wCodePage,
24 CFGAS_FontMgr* pFontMgr) {
25 #if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_
26 if (!pFontMgr)
27 return nullptr;
28
29 return pFontMgr->GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
30 #else
31 auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
32 if (!pFont->LoadFontInternal(pszFontFamily, dwFontStyles, wCodePage))
33 return nullptr;
34 return pFont;
35 #endif
36 }
37
38 // static
LoadFont(CFX_Font * pExternalFont,CFGAS_FontMgr * pFontMgr)39 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(CFX_Font* pExternalFont,
40 CFGAS_FontMgr* pFontMgr) {
41 auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
42 if (!pFont->LoadFontInternal(pExternalFont))
43 return nullptr;
44 return pFont;
45 }
46
47 // static
LoadFont(std::unique_ptr<CFX_Font> pInternalFont,CFGAS_FontMgr * pFontMgr)48 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
49 std::unique_ptr<CFX_Font> pInternalFont,
50 CFGAS_FontMgr* pFontMgr) {
51 auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
52 if (!pFont->LoadFontInternal(std::move(pInternalFont)))
53 return nullptr;
54 return pFont;
55 }
56
CFGAS_GEFont(CFGAS_FontMgr * pFontMgr)57 CFGAS_GEFont::CFGAS_GEFont(CFGAS_FontMgr* pFontMgr)
58 :
59 m_bUseLogFontStyle(false),
60 m_dwLogFontStyle(0),
61 m_pFont(nullptr),
62 m_bExternalFont(false),
63 m_pFontMgr(pFontMgr) {
64 }
65
~CFGAS_GEFont()66 CFGAS_GEFont::~CFGAS_GEFont() {
67 if (!m_bExternalFont)
68 delete m_pFont;
69 }
70
71 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
LoadFontInternal(const wchar_t * pszFontFamily,uint32_t dwFontStyles,uint16_t wCodePage)72 bool CFGAS_GEFont::LoadFontInternal(const wchar_t* pszFontFamily,
73 uint32_t dwFontStyles,
74 uint16_t wCodePage) {
75 if (m_pFont)
76 return false;
77 ByteString csFontFamily;
78 if (pszFontFamily)
79 csFontFamily = ByteString::FromUnicode(pszFontFamily);
80
81 int32_t iWeight =
82 FontStyleIsBold(dwFontStyles) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
83 m_pFont = new CFX_Font;
84 if (FontStyleIsItalic(dwFontStyles) && FontStyleIsBold(dwFontStyles))
85 csFontFamily += ",BoldItalic";
86 else if (FontStyleIsBold(dwFontStyles))
87 csFontFamily += ",Bold";
88 else if (FontStyleIsItalic(dwFontStyles))
89 csFontFamily += ",Italic";
90
91 m_pFont->LoadSubst(csFontFamily, true, dwFontStyles, iWeight, 0, wCodePage,
92 false);
93 if (!m_pFont->GetFace())
94 return false;
95 return InitFont();
96 }
97 #endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
98
LoadFontInternal(CFX_Font * pExternalFont)99 bool CFGAS_GEFont::LoadFontInternal(CFX_Font* pExternalFont) {
100 if (m_pFont || !pExternalFont)
101 return false;
102
103 m_pFont = pExternalFont;
104 m_bExternalFont = true;
105 return InitFont();
106 }
107
LoadFontInternal(std::unique_ptr<CFX_Font> pInternalFont)108 bool CFGAS_GEFont::LoadFontInternal(std::unique_ptr<CFX_Font> pInternalFont) {
109 if (m_pFont || !pInternalFont)
110 return false;
111
112 m_pFont = pInternalFont.release();
113 m_bExternalFont = false;
114 return InitFont();
115 }
116
InitFont()117 bool CFGAS_GEFont::InitFont() {
118 if (!m_pFont)
119 return false;
120
121 if (m_pFontEncoding)
122 return true;
123
124 m_pFontEncoding = FX_CreateFontEncodingEx(m_pFont, FXFM_ENCODING_NONE);
125 return !!m_pFontEncoding;
126 }
127
GetFamilyName() const128 WideString CFGAS_GEFont::GetFamilyName() const {
129 if (!m_pFont->GetSubstFont() ||
130 m_pFont->GetSubstFont()->m_Family.GetLength() == 0) {
131 return WideString::FromLocal(m_pFont->GetFamilyName().AsStringView());
132 }
133 return WideString::FromLocal(
134 m_pFont->GetSubstFont()->m_Family.AsStringView());
135 }
136
GetFontStyles() const137 uint32_t CFGAS_GEFont::GetFontStyles() const {
138 ASSERT(m_pFont);
139 if (m_bUseLogFontStyle)
140 return m_dwLogFontStyle;
141
142 uint32_t dwStyles = 0;
143 auto* pSubstFont = m_pFont->GetSubstFont();
144 if (pSubstFont) {
145 if (pSubstFont->m_Weight == FXFONT_FW_BOLD)
146 dwStyles |= FXFONT_BOLD;
147 if (pSubstFont->m_bFlagItalic)
148 dwStyles |= FXFONT_ITALIC;
149 } else {
150 if (m_pFont->IsBold())
151 dwStyles |= FXFONT_BOLD;
152 if (m_pFont->IsItalic())
153 dwStyles |= FXFONT_ITALIC;
154 }
155 return dwStyles;
156 }
157
GetCharWidth(wchar_t wUnicode,int32_t & iWidth)158 bool CFGAS_GEFont::GetCharWidth(wchar_t wUnicode, int32_t& iWidth) {
159 auto it = m_CharWidthMap.find(wUnicode);
160 iWidth = it != m_CharWidthMap.end() ? it->second : 0;
161 if (iWidth == 65535)
162 return false;
163
164 if (iWidth > 0)
165 return true;
166
167 if (!m_pProvider || !m_pProvider->GetCharWidth(RetainPtr<CFGAS_GEFont>(this),
168 wUnicode, &iWidth)) {
169 RetainPtr<CFGAS_GEFont> pFont;
170 int32_t iGlyph;
171 std::tie(iGlyph, pFont) = GetGlyphIndexAndFont(wUnicode, true);
172 if (iGlyph != 0xFFFF && pFont) {
173 if (pFont.Get() == this) {
174 iWidth = m_pFont->GetGlyphWidth(iGlyph);
175 if (iWidth < 0)
176 iWidth = -1;
177 } else if (pFont->GetCharWidth(wUnicode, iWidth)) {
178 return true;
179 }
180 } else {
181 iWidth = -1;
182 }
183 }
184 m_CharWidthMap[wUnicode] = iWidth;
185 return iWidth > 0;
186 }
187
GetCharBBox(wchar_t wUnicode,CFX_Rect * bbox)188 bool CFGAS_GEFont::GetCharBBox(wchar_t wUnicode, CFX_Rect* bbox) {
189 auto it = m_BBoxMap.find(wUnicode);
190 if (it != m_BBoxMap.end()) {
191 *bbox = it->second;
192 return true;
193 }
194
195 RetainPtr<CFGAS_GEFont> pFont;
196 int32_t iGlyph;
197 std::tie(iGlyph, pFont) = GetGlyphIndexAndFont(wUnicode, true);
198 if (!pFont || iGlyph == 0xFFFF)
199 return false;
200
201 if (pFont.Get() != this)
202 return pFont->GetCharBBox(wUnicode, bbox);
203
204 FX_RECT rtBBox;
205 if (!m_pFont->GetGlyphBBox(iGlyph, rtBBox))
206 return false;
207
208 CFX_Rect rt(rtBBox.left, rtBBox.top, rtBBox.Width(), rtBBox.Height());
209 m_BBoxMap[wUnicode] = rt;
210 *bbox = rt;
211 return true;
212 }
213
GetBBox(CFX_Rect * bbox)214 bool CFGAS_GEFont::GetBBox(CFX_Rect* bbox) {
215 FX_RECT rt(0, 0, 0, 0);
216 if (!m_pFont->GetBBox(rt))
217 return false;
218
219 bbox->left = rt.left;
220 bbox->width = rt.Width();
221 bbox->top = rt.bottom;
222 bbox->height = -rt.Height();
223 return true;
224 }
225
GetGlyphIndex(wchar_t wUnicode)226 int32_t CFGAS_GEFont::GetGlyphIndex(wchar_t wUnicode) {
227 int32_t glyph;
228 RetainPtr<CFGAS_GEFont> font;
229 std::tie(glyph, font) = GetGlyphIndexAndFont(wUnicode, true);
230 return glyph;
231 }
232
GetGlyphIndexAndFont(wchar_t wUnicode,bool bRecursive)233 std::pair<int32_t, RetainPtr<CFGAS_GEFont>> CFGAS_GEFont::GetGlyphIndexAndFont(
234 wchar_t wUnicode,
235 bool bRecursive) {
236 int32_t iGlyphIndex = m_pFontEncoding->GlyphFromCharCode(wUnicode);
237 if (iGlyphIndex > 0)
238 return {iGlyphIndex, RetainPtr<CFGAS_GEFont>(this)};
239
240 const FGAS_FONTUSB* pFontUSB = FGAS_GetUnicodeBitField(wUnicode);
241 if (!pFontUSB)
242 return {0xFFFF, nullptr};
243
244 uint16_t wBitField = pFontUSB->wBitField;
245 if (wBitField >= 128)
246 return {0xFFFF, nullptr};
247
248 auto it = m_FontMapper.find(wUnicode);
249 if (it != m_FontMapper.end() && it->second && it->second.Get() != this) {
250 RetainPtr<CFGAS_GEFont> font;
251 std::tie(iGlyphIndex, font) =
252 it->second->GetGlyphIndexAndFont(wUnicode, false);
253 if (iGlyphIndex != 0xFFFF) {
254 for (size_t i = 0; i < m_SubstFonts.size(); ++i) {
255 if (m_SubstFonts[i] == it->second)
256 return {(iGlyphIndex | ((i + 1) << 24)), it->second};
257 }
258 }
259 }
260 if (!m_pFontMgr || !bRecursive)
261 return {0xFFFF, nullptr};
262
263 WideString wsFamily = GetFamilyName();
264 RetainPtr<CFGAS_GEFont> pFont =
265 m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), wsFamily.c_str());
266 #if _FX_PLATFORM_ != _FX_PLATFORM_WINDOWS_
267 if (!pFont)
268 pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), nullptr);
269 #endif
270 if (!pFont || pFont.Get() == this) // Avoids direct cycles below.
271 return {0xFFFF, nullptr};
272
273 m_FontMapper[wUnicode] = pFont;
274 m_SubstFonts.push_back(pFont);
275
276 RetainPtr<CFGAS_GEFont> font;
277 std::tie(iGlyphIndex, font) = pFont->GetGlyphIndexAndFont(wUnicode, false);
278 if (iGlyphIndex == 0xFFFF)
279 return {0xFFFF, nullptr};
280
281 return {(iGlyphIndex | (m_SubstFonts.size() << 24)), pFont};
282 }
283
GetAscent() const284 int32_t CFGAS_GEFont::GetAscent() const {
285 return m_pFont->GetAscent();
286 }
287
GetDescent() const288 int32_t CFGAS_GEFont::GetDescent() const {
289 return m_pFont->GetDescent();
290 }
291
GetSubstFont(int32_t iGlyphIndex)292 RetainPtr<CFGAS_GEFont> CFGAS_GEFont::GetSubstFont(int32_t iGlyphIndex) {
293 iGlyphIndex = static_cast<uint32_t>(iGlyphIndex) >> 24;
294 if (iGlyphIndex == 0)
295 return RetainPtr<CFGAS_GEFont>(this);
296 return m_SubstFonts[iGlyphIndex - 1];
297 }
298