• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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