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/fxge/cfx_substfont.h"
13 #include "core/fxge/cfx_unicodeencoding.h"
14 #include "core/fxge/cfx_unicodeencodingex.h"
15 #include "third_party/base/ptr_util.h"
16 #include "xfa/fgas/crt/fgas_codepage.h"
17 #include "xfa/fgas/font/fgas_fontutils.h"
18 #include "xfa/fxfa/xfa_fontmgr.h"
19
20 // static
LoadFont(const FX_WCHAR * pszFontFamily,uint32_t dwFontStyles,uint16_t wCodePage,CFGAS_FontMgr * pFontMgr)21 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
22 const FX_WCHAR* pszFontFamily,
23 uint32_t dwFontStyles,
24 uint16_t wCodePage,
25 CFGAS_FontMgr* pFontMgr) {
26 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
27 if (!pFontMgr)
28 return nullptr;
29
30 return pFontMgr->GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
31 #else
32 auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
33 if (!pFont->LoadFontInternal(pszFontFamily, dwFontStyles, wCodePage))
34 return nullptr;
35 return pFont;
36 #endif
37 }
38
39 // static
LoadFont(CFX_Font * pExternalFont,CFGAS_FontMgr * pFontMgr)40 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(CFX_Font* pExternalFont,
41 CFGAS_FontMgr* pFontMgr) {
42 auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
43 if (!pFont->LoadFontInternal(pExternalFont))
44 return nullptr;
45 return pFont;
46 }
47
48 // static
LoadFont(std::unique_ptr<CFX_Font> pInternalFont,CFGAS_FontMgr * pFontMgr)49 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
50 std::unique_ptr<CFX_Font> pInternalFont,
51 CFGAS_FontMgr* pFontMgr) {
52 auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
53 if (!pFont->LoadFontInternal(std::move(pInternalFont)))
54 return nullptr;
55 return pFont;
56 }
57
58 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
59 // static
LoadFont(const uint8_t * pBuffer,int32_t iLength,CFGAS_FontMgr * pFontMgr)60 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(const uint8_t* pBuffer,
61 int32_t iLength,
62 CFGAS_FontMgr* pFontMgr) {
63 auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
64 if (pFont->LoadFontInternal(pBuffer, iLength))
65 return nullptr;
66 return pFont;
67 }
68
69 // static
LoadFont(const CFX_RetainPtr<IFGAS_Stream> & pFontStream,CFGAS_FontMgr * pFontMgr,bool bSaveStream)70 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::LoadFont(
71 const CFX_RetainPtr<IFGAS_Stream>& pFontStream,
72 CFGAS_FontMgr* pFontMgr,
73 bool bSaveStream) {
74 auto pFont = pdfium::MakeRetain<CFGAS_GEFont>(pFontMgr);
75 if (!pFont->LoadFontInternal(pFontStream, bSaveStream))
76 return nullptr;
77 return pFont;
78 }
79 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
80
CFGAS_GEFont(CFGAS_FontMgr * pFontMgr)81 CFGAS_GEFont::CFGAS_GEFont(CFGAS_FontMgr* pFontMgr)
82 :
83 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
84 m_bUseLogFontStyle(false),
85 m_dwLogFontStyle(0),
86 #endif
87 m_pFont(nullptr),
88 m_pFontMgr(pFontMgr),
89 m_bExternalFont(false),
90 m_pProvider(nullptr) {
91 }
92
CFGAS_GEFont(const CFX_RetainPtr<CFGAS_GEFont> & src,uint32_t dwFontStyles)93 CFGAS_GEFont::CFGAS_GEFont(const CFX_RetainPtr<CFGAS_GEFont>& src,
94 uint32_t dwFontStyles)
95 :
96 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
97 m_bUseLogFontStyle(false),
98 m_dwLogFontStyle(0),
99 #endif
100 m_pFont(nullptr),
101 m_pSrcFont(src),
102 m_pFontMgr(src->m_pFontMgr),
103 m_bExternalFont(false),
104 m_pProvider(nullptr) {
105 ASSERT(m_pSrcFont->m_pFont);
106 m_pFont = new CFX_Font;
107 m_pFont->LoadClone(m_pSrcFont->m_pFont);
108 CFX_SubstFont* pSubst = m_pFont->GetSubstFont();
109 if (!pSubst) {
110 pSubst = new CFX_SubstFont;
111 m_pFont->SetSubstFont(std::unique_ptr<CFX_SubstFont>(pSubst));
112 }
113 pSubst->m_Weight =
114 (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
115 if (dwFontStyles & FX_FONTSTYLE_Italic)
116 pSubst->m_SubstFlags |= FXFONT_SUBST_ITALIC;
117 InitFont();
118 }
119
~CFGAS_GEFont()120 CFGAS_GEFont::~CFGAS_GEFont() {
121 if (!m_bExternalFont)
122 delete m_pFont;
123 }
124
125 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
LoadFontInternal(const FX_WCHAR * pszFontFamily,uint32_t dwFontStyles,uint16_t wCodePage)126 bool CFGAS_GEFont::LoadFontInternal(const FX_WCHAR* pszFontFamily,
127 uint32_t dwFontStyles,
128 uint16_t wCodePage) {
129 if (m_pFont)
130 return false;
131 CFX_ByteString csFontFamily;
132 if (pszFontFamily)
133 csFontFamily = CFX_ByteString::FromUnicode(pszFontFamily);
134 uint32_t dwFlags = 0;
135 if (dwFontStyles & FX_FONTSTYLE_FixedPitch)
136 dwFlags |= FXFONT_FIXED_PITCH;
137 if (dwFontStyles & FX_FONTSTYLE_Serif)
138 dwFlags |= FXFONT_SERIF;
139 if (dwFontStyles & FX_FONTSTYLE_Symbolic)
140 dwFlags |= FXFONT_SYMBOLIC;
141 if (dwFontStyles & FX_FONTSTYLE_Script)
142 dwFlags |= FXFONT_SCRIPT;
143 if (dwFontStyles & FX_FONTSTYLE_Italic)
144 dwFlags |= FXFONT_ITALIC;
145 if (dwFontStyles & FX_FONTSTYLE_Bold)
146 dwFlags |= FXFONT_BOLD;
147 if (dwFontStyles & FX_FONTSTYLE_ExactMatch)
148 dwFlags |= FXFONT_EXACTMATCH;
149 int32_t iWeight =
150 (dwFontStyles & FX_FONTSTYLE_Bold) ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL;
151 m_pFont = new CFX_Font;
152 if ((dwFlags & FXFONT_ITALIC) && (dwFlags & FXFONT_BOLD))
153 csFontFamily += ",BoldItalic";
154 else if (dwFlags & FXFONT_BOLD)
155 csFontFamily += ",Bold";
156 else if (dwFlags & FXFONT_ITALIC)
157 csFontFamily += ",Italic";
158 m_pFont->LoadSubst(csFontFamily, true, dwFlags, iWeight, 0, wCodePage, false);
159 if (!m_pFont->GetFace())
160 return false;
161 return InitFont();
162 }
163
LoadFontInternal(const uint8_t * pBuffer,int32_t length)164 bool CFGAS_GEFont::LoadFontInternal(const uint8_t* pBuffer, int32_t length) {
165 if (m_pFont)
166 return false;
167
168 m_pFont = new CFX_Font;
169 if (!m_pFont->LoadEmbedded(pBuffer, length))
170 return false;
171 return InitFont();
172 }
173
LoadFontInternal(const CFX_RetainPtr<IFGAS_Stream> & pFontStream,bool bSaveStream)174 bool CFGAS_GEFont::LoadFontInternal(
175 const CFX_RetainPtr<IFGAS_Stream>& pFontStream,
176 bool bSaveStream) {
177 if (m_pFont || m_pFileRead || !pFontStream || pFontStream->GetLength() < 1)
178 return false;
179 if (bSaveStream)
180 m_pStream = pFontStream;
181
182 m_pFileRead = pFontStream->MakeSeekableReadStream();
183 m_pFont = new CFX_Font;
184 if (!m_pFont->LoadFile(m_pFileRead)) {
185 m_pFileRead.Reset();
186 return false;
187 }
188 return InitFont();
189 }
190 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
191
LoadFontInternal(CFX_Font * pExternalFont)192 bool CFGAS_GEFont::LoadFontInternal(CFX_Font* pExternalFont) {
193 if (m_pFont || !pExternalFont)
194 return false;
195
196 m_pFont = pExternalFont;
197 m_bExternalFont = true;
198 return InitFont();
199 }
200
LoadFontInternal(std::unique_ptr<CFX_Font> pInternalFont)201 bool CFGAS_GEFont::LoadFontInternal(std::unique_ptr<CFX_Font> pInternalFont) {
202 if (m_pFont || !pInternalFont)
203 return false;
204
205 m_pFont = pInternalFont.release();
206 m_bExternalFont = false;
207 return InitFont();
208 }
209
InitFont()210 bool CFGAS_GEFont::InitFont() {
211 if (!m_pFont)
212 return false;
213
214 if (!m_pFontEncoding) {
215 m_pFontEncoding.reset(FX_CreateFontEncodingEx(m_pFont));
216 if (!m_pFontEncoding)
217 return false;
218 }
219 if (!m_pCharWidthMap) {
220 m_pCharWidthMap =
221 pdfium::MakeUnique<CFX_DiscreteArrayTemplate<uint16_t>>(1024);
222 }
223 return true;
224 }
225
Derive(uint32_t dwFontStyles,uint16_t wCodePage)226 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::Derive(uint32_t dwFontStyles,
227 uint16_t wCodePage) {
228 CFX_RetainPtr<CFGAS_GEFont> pFont(this);
229 if (GetFontStyles() == dwFontStyles)
230 return pFont;
231 return pdfium::MakeRetain<CFGAS_GEFont>(pFont, dwFontStyles);
232 }
233
GetFamilyName() const234 CFX_WideString CFGAS_GEFont::GetFamilyName() const {
235 if (!m_pFont->GetSubstFont() ||
236 m_pFont->GetSubstFont()->m_Family.GetLength() == 0) {
237 return CFX_WideString::FromLocal(m_pFont->GetFamilyName().AsStringC());
238 }
239 return CFX_WideString::FromLocal(
240 m_pFont->GetSubstFont()->m_Family.AsStringC());
241 }
242
GetFontStyles() const243 uint32_t CFGAS_GEFont::GetFontStyles() const {
244 ASSERT(m_pFont);
245 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
246 if (m_bUseLogFontStyle)
247 return m_dwLogFontStyle;
248 #endif
249
250 uint32_t dwStyles = 0;
251 auto* pSubstFont = m_pFont->GetSubstFont();
252 if (pSubstFont) {
253 if (pSubstFont->m_Weight == FXFONT_FW_BOLD)
254 dwStyles |= FX_FONTSTYLE_Bold;
255 if (pSubstFont->m_SubstFlags & FXFONT_SUBST_ITALIC)
256 dwStyles |= FX_FONTSTYLE_Italic;
257 } else {
258 if (m_pFont->IsBold())
259 dwStyles |= FX_FONTSTYLE_Bold;
260 if (m_pFont->IsItalic())
261 dwStyles |= FX_FONTSTYLE_Italic;
262 }
263 return dwStyles;
264 }
265
GetCharWidth(FX_WCHAR wUnicode,int32_t & iWidth,bool bCharCode)266 bool CFGAS_GEFont::GetCharWidth(FX_WCHAR wUnicode,
267 int32_t& iWidth,
268 bool bCharCode) {
269 return GetCharWidthInternal(wUnicode, iWidth, true, bCharCode);
270 }
271
GetCharWidthInternal(FX_WCHAR wUnicode,int32_t & iWidth,bool bRecursive,bool bCharCode)272 bool CFGAS_GEFont::GetCharWidthInternal(FX_WCHAR wUnicode,
273 int32_t& iWidth,
274 bool bRecursive,
275 bool bCharCode) {
276 ASSERT(m_pCharWidthMap);
277 iWidth = m_pCharWidthMap->GetAt(wUnicode, 0);
278 if (iWidth == 65535)
279 return false;
280
281 if (iWidth > 0)
282 return true;
283
284 if (!m_pProvider ||
285 !m_pProvider->GetCharWidth(CFX_RetainPtr<CFGAS_GEFont>(this), wUnicode,
286 bCharCode, &iWidth)) {
287 CFX_RetainPtr<CFGAS_GEFont> pFont;
288 int32_t iGlyph = GetGlyphIndex(wUnicode, true, &pFont, bCharCode);
289 if (iGlyph != 0xFFFF && pFont) {
290 if (pFont.Get() == this) {
291 iWidth = m_pFont->GetGlyphWidth(iGlyph);
292 if (iWidth < 0)
293 iWidth = -1;
294 } else if (pFont->GetCharWidthInternal(wUnicode, iWidth, false,
295 bCharCode)) {
296 return true;
297 }
298 } else {
299 iWidth = -1;
300 }
301 }
302 m_pCharWidthMap->SetAtGrow(wUnicode, iWidth);
303 return iWidth > 0;
304 }
305
GetCharBBox(FX_WCHAR wUnicode,CFX_Rect * bbox,bool bCharCode)306 bool CFGAS_GEFont::GetCharBBox(FX_WCHAR wUnicode,
307 CFX_Rect* bbox,
308 bool bCharCode) {
309 return GetCharBBoxInternal(wUnicode, bbox, true, bCharCode);
310 }
311
GetCharBBoxInternal(FX_WCHAR wUnicode,CFX_Rect * bbox,bool bRecursive,bool bCharCode)312 bool CFGAS_GEFont::GetCharBBoxInternal(FX_WCHAR wUnicode,
313 CFX_Rect* bbox,
314 bool bRecursive,
315 bool bCharCode) {
316 auto it = m_BBoxMap.find(wUnicode);
317 if (it != m_BBoxMap.end()) {
318 *bbox = it->second;
319 return true;
320 }
321
322 CFX_RetainPtr<CFGAS_GEFont> pFont;
323 int32_t iGlyph = GetGlyphIndex(wUnicode, true, &pFont, bCharCode);
324 if (!pFont || iGlyph == 0xFFFF)
325 return false;
326
327 if (pFont.Get() != this)
328 return pFont->GetCharBBoxInternal(wUnicode, bbox, false, bCharCode);
329
330 FX_RECT rtBBox;
331 if (!m_pFont->GetGlyphBBox(iGlyph, rtBBox))
332 return false;
333
334 CFX_Rect rt(rtBBox.left, rtBBox.top, rtBBox.Width(), rtBBox.Height());
335 m_BBoxMap[wUnicode] = rt;
336 *bbox = rt;
337 return true;
338 }
339
GetBBox(CFX_Rect * bbox)340 bool CFGAS_GEFont::GetBBox(CFX_Rect* bbox) {
341 FX_RECT rt(0, 0, 0, 0);
342 if (!m_pFont->GetBBox(rt))
343 return false;
344
345 bbox->left = rt.left;
346 bbox->width = rt.Width();
347 bbox->top = rt.bottom;
348 bbox->height = -rt.Height();
349 return true;
350 }
351
GetGlyphIndex(FX_WCHAR wUnicode,bool bCharCode)352 int32_t CFGAS_GEFont::GetGlyphIndex(FX_WCHAR wUnicode, bool bCharCode) {
353 return GetGlyphIndex(wUnicode, true, nullptr, bCharCode);
354 }
355
GetGlyphIndex(FX_WCHAR wUnicode,bool bRecursive,CFX_RetainPtr<CFGAS_GEFont> * ppFont,bool bCharCode)356 int32_t CFGAS_GEFont::GetGlyphIndex(FX_WCHAR wUnicode,
357 bool bRecursive,
358 CFX_RetainPtr<CFGAS_GEFont>* ppFont,
359 bool bCharCode) {
360 int32_t iGlyphIndex = m_pFontEncoding->GlyphFromCharCode(wUnicode);
361 if (iGlyphIndex > 0) {
362 if (ppFont)
363 ppFont->Reset(this);
364 return iGlyphIndex;
365 }
366 const FGAS_FONTUSB* pFontUSB = FGAS_GetUnicodeBitField(wUnicode);
367 if (!pFontUSB)
368 return 0xFFFF;
369
370 uint16_t wBitField = pFontUSB->wBitField;
371 if (wBitField >= 128)
372 return 0xFFFF;
373
374 auto it = m_FontMapper.find(wUnicode);
375 if (it != m_FontMapper.end() && it->second && it->second.Get() != this) {
376 iGlyphIndex =
377 it->second->GetGlyphIndex(wUnicode, false, nullptr, bCharCode);
378 if (iGlyphIndex != 0xFFFF) {
379 for (size_t i = 0; i < m_SubstFonts.size(); ++i) {
380 if (m_SubstFonts[i] == it->second) {
381 if (ppFont)
382 *ppFont = it->second;
383 return (iGlyphIndex | ((i + 1) << 24));
384 }
385 }
386 }
387 }
388 if (!m_pFontMgr || !bRecursive)
389 return 0xFFFF;
390
391 CFX_WideString wsFamily = GetFamilyName();
392 CFX_RetainPtr<CFGAS_GEFont> pFont =
393 m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), wsFamily.c_str());
394 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
395 if (!pFont)
396 pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), nullptr);
397 #endif
398 if (!pFont || pFont.Get() == this) // Avoids direct cycles below.
399 return 0xFFFF;
400
401 m_FontMapper[wUnicode] = pFont;
402 m_SubstFonts.push_back(pFont);
403 iGlyphIndex = pFont->GetGlyphIndex(wUnicode, false, nullptr, bCharCode);
404 if (iGlyphIndex == 0xFFFF)
405 return 0xFFFF;
406
407 if (ppFont)
408 *ppFont = pFont;
409 return (iGlyphIndex | (m_SubstFonts.size() << 24));
410 }
411
GetAscent() const412 int32_t CFGAS_GEFont::GetAscent() const {
413 return m_pFont->GetAscent();
414 }
415
GetDescent() const416 int32_t CFGAS_GEFont::GetDescent() const {
417 return m_pFont->GetDescent();
418 }
419
GetSubstFont(int32_t iGlyphIndex)420 CFX_RetainPtr<CFGAS_GEFont> CFGAS_GEFont::GetSubstFont(int32_t iGlyphIndex) {
421 iGlyphIndex = static_cast<uint32_t>(iGlyphIndex) >> 24;
422 if (iGlyphIndex == 0)
423 return CFX_RetainPtr<CFGAS_GEFont>(this);
424 return m_SubstFonts[iGlyphIndex - 1];
425 }
426