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 |