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 21RetainPtr<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 39RetainPtr<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 48RetainPtr<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 57CFGAS_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 66CFGAS_GEFont::~CFGAS_GEFont() { 67 if (!m_bExternalFont) 68 delete m_pFont; 69} 70 71#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ 72bool 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 99bool 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 108bool 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 117bool 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 128WideString 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 137uint32_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 158bool 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 188bool 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 214bool 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 226int32_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 233std::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 284int32_t CFGAS_GEFont::GetAscent() const { 285 return m_pFont->GetAscent(); 286} 287 288int32_t CFGAS_GEFont::GetDescent() const { 289 return m_pFont->GetDescent(); 290} 291 292RetainPtr<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