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