• 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/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