Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cfx_glyphcache.cpp
Go to the documentation of this file.
1// Copyright 2016 The PDFium Authors
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 "core/fxge/cfx_glyphcache.h"
8
9#include <initializer_list>
10#include <memory>
11#include <utility>
12
13#include "build/build_config.h"
14#include "core/fxcrt/fx_codepage.h"
15#include "core/fxcrt/fx_memcpy_wrappers.h"
16#include "core/fxcrt/span.h"
17#include "core/fxge/cfx_defaultrenderdevice.h"
18#include "core/fxge/cfx_font.h"
19#include "core/fxge/cfx_glyphbitmap.h"
20#include "core/fxge/cfx_path.h"
21#include "core/fxge/cfx_substfont.h"
22
23#if defined(PDF_USE_SKIA)
24#include "third_party/skia/include/core/SkStream.h" // nogncheck
25#include "third_party/skia/include/core/SkTypeface.h" // nogncheck
26#include "third_party/skia/include/core/SkFontMgr.h" // nogncheck
27#include "third_party/skia/include/ports/SkFontMgr_empty.h" // nogncheck
28
29#if BUILDFLAG(IS_WIN)
30#include "third_party/skia/include/ports/SkTypeface_win.h" // nogncheck
31#elif BUILDFLAG(IS_APPLE)
32#include "third_party/skia/include/ports/SkFontMgr_mac_ct.h" // nogncheck
33#endif
34
35#endif
36
37#if BUILDFLAG(IS_APPLE)
38#include "core/fxge/cfx_textrenderoptions.h"
39#endif
40
41namespace {
42
43constexpr uint32_t kInvalidGlyphIndex = static_cast<uint32_t>(-1);
44
45class UniqueKeyGen {
46 public:
47 UniqueKeyGen(const CFX_Font* pFont,
48 const CFX_Matrix& matrix,
49 int dest_width,
50 int anti_alias,
51 bool bNative);
52
53 pdfium::span<const uint8_t> span() const;
54
55 private:
56 void Initialize(std::initializer_list<const int> args);
57
58 size_t key_len_;
59 uint32_t key_[32];
60};
61
62void UniqueKeyGen::Initialize(std::initializer_list<const int32_t> args) {
63 auto key_span = pdfium::make_span(key_);
64 for (const auto& arg : args) {
65 key_span.front() = arg;
66 key_span = key_span.subspan(1);
67 }
68 key_len_ = args.size();
69}
70
71pdfium::span<const uint8_t> UniqueKeyGen::span() const {
72 return pdfium::as_bytes(pdfium::make_span(key_).first(key_len_));
73}
74
75UniqueKeyGen::UniqueKeyGen(const CFX_Font* pFont,
76 const CFX_Matrix& matrix,
77 int dest_width,
78 int anti_alias,
79 bool bNative) {
80 int nMatrixA = static_cast<int>(matrix.a * 10000);
81 int nMatrixB = static_cast<int>(matrix.b * 10000);
82 int nMatrixC = static_cast<int>(matrix.c * 10000);
83 int nMatrixD = static_cast<int>(matrix.d * 10000);
84
85#if BUILDFLAG(IS_APPLE)
86 if (bNative) {
87 if (pFont->GetSubstFont()) {
88 Initialize({nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
89 anti_alias, pFont->GetSubstFont()->m_Weight,
90 pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(),
91 3});
92 } else {
93 Initialize(
94 {nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, anti_alias, 3});
95 }
96 return;
97 }
98#endif
99
100 CHECK(!bNative);
101 if (pFont->GetSubstFont()) {
102 Initialize({nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, anti_alias,
105 } else {
106 Initialize(
107 {nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, anti_alias});
108 }
109}
110
111} // namespace
112
113CFX_GlyphCache::CFX_GlyphCache(RetainPtr<CFX_Face> face)
114 : m_Face(std::move(face)) {}
115
116CFX_GlyphCache::~CFX_GlyphCache() = default;
117
118std::unique_ptr<CFX_GlyphBitmap> CFX_GlyphCache::RenderGlyph(
119 const CFX_Font* pFont,
120 uint32_t glyph_index,
121 bool bFontStyle,
122 const CFX_Matrix& matrix,
123 int dest_width,
124 int anti_alias) {
125 if (!m_Face) {
126 return nullptr;
127 }
128
129 return m_Face->RenderGlyph(pFont, glyph_index, bFontStyle, matrix, dest_width,
130 anti_alias);
131}
132
133const CFX_Path* CFX_GlyphCache::LoadGlyphPath(const CFX_Font* pFont,
134 uint32_t glyph_index,
135 int dest_width) {
136 if (!GetFace() || glyph_index == kInvalidGlyphIndex) {
137 return nullptr;
138 }
139
140 const auto* pSubstFont = pFont->GetSubstFont();
141 int weight = pSubstFont ? pSubstFont->m_Weight : 0;
142 int angle = pSubstFont ? pSubstFont->m_ItalicAngle : 0;
143 bool vertical = pSubstFont && pFont->IsVertical();
144 const PathMapKey key =
145 std::make_tuple(glyph_index, dest_width, weight, angle, vertical);
146 auto it = m_PathMap.find(key);
147 if (it != m_PathMap.end())
148 return it->second.get();
149
150 m_PathMap[key] = pFont->LoadGlyphPathImpl(glyph_index, dest_width);
151 return m_PathMap[key].get();
152}
153
154const CFX_GlyphBitmap* CFX_GlyphCache::LoadGlyphBitmap(
155 const CFX_Font* pFont,
156 uint32_t glyph_index,
157 bool bFontStyle,
158 const CFX_Matrix& matrix,
159 int dest_width,
160 int anti_alias,
161 CFX_TextRenderOptions* text_options) {
162 if (glyph_index == kInvalidGlyphIndex)
163 return nullptr;
164
165#if BUILDFLAG(IS_APPLE)
166 const bool bNative = text_options->native_text;
167#else
168 const bool bNative = false;
169#endif
170 UniqueKeyGen keygen(pFont, matrix, dest_width, anti_alias, bNative);
171 auto FaceGlyphsKey = ByteString(ByteStringView(keygen.span()));
172
173#if BUILDFLAG(IS_APPLE)
174 const bool bDoLookUp =
175 !text_options->native_text || CFX_DefaultRenderDevice::UseSkiaRenderer();
176#else
177 const bool bDoLookUp = true;
178#endif
179 if (bDoLookUp) {
180 return LookUpGlyphBitmap(pFont, matrix, FaceGlyphsKey, glyph_index,
181 bFontStyle, dest_width, anti_alias);
182 }
183
184#if BUILDFLAG(IS_APPLE)
185 DCHECK(!CFX_DefaultRenderDevice::UseSkiaRenderer());
186
187 std::unique_ptr<CFX_GlyphBitmap> pGlyphBitmap;
188 auto it = m_SizeMap.find(FaceGlyphsKey);
189 if (it != m_SizeMap.end()) {
190 SizeGlyphCache* pSizeCache = &(it->second);
191 auto it2 = pSizeCache->find(glyph_index);
192 if (it2 != pSizeCache->end())
193 return it2->second.get();
194
195 pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, matrix,
196 dest_width, anti_alias);
197 if (pGlyphBitmap) {
198 CFX_GlyphBitmap* pResult = pGlyphBitmap.get();
199 (*pSizeCache)[glyph_index] = std::move(pGlyphBitmap);
200 return pResult;
201 }
202 } else {
203 pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, matrix,
204 dest_width, anti_alias);
205 if (pGlyphBitmap) {
206 CFX_GlyphBitmap* pResult = pGlyphBitmap.get();
207
208 SizeGlyphCache cache;
209 cache[glyph_index] = std::move(pGlyphBitmap);
210
211 m_SizeMap[FaceGlyphsKey] = std::move(cache);
212 return pResult;
213 }
214 }
215 UniqueKeyGen keygen2(pFont, matrix, dest_width, anti_alias,
216 /*bNative=*/false);
217 auto FaceGlyphsKey2 = ByteString(ByteStringView(keygen2.span()));
218 text_options->native_text = false;
219 return LookUpGlyphBitmap(pFont, matrix, FaceGlyphsKey2, glyph_index,
220 bFontStyle, dest_width, anti_alias);
221#endif // BUILDFLAG(IS_APPLE)
222}
223
224int CFX_GlyphCache::GetGlyphWidth(const CFX_Font* font,
225 uint32_t glyph_index,
226 int dest_width,
227 int weight) {
228 const WidthMapKey key = std::make_tuple(glyph_index, dest_width, weight);
229 auto it = m_WidthMap.find(key);
230 if (it != m_WidthMap.end()) {
231 return it->second;
232 }
233
234 m_WidthMap[key] = font->GetGlyphWidthImpl(glyph_index, dest_width, weight);
235 return m_WidthMap[key];
236}
237
238#if defined(PDF_USE_SKIA)
239
240namespace {
241// A singleton SkFontMgr which can be used to decode raw font data or
242// otherwise get access to system fonts.
243SkFontMgr* g_fontmgr = nullptr;
244} // namespace
245
246// static
247void CFX_GlyphCache::InitializeGlobals() {
248 CHECK(!g_fontmgr);
249#if BUILDFLAG(IS_WIN)
250 g_fontmgr = SkFontMgr_New_DirectWrite().release();
251#elif BUILDFLAG(IS_APPLE)
252 g_fontmgr = SkFontMgr_New_CoreText(nullptr).release();
253#else
254 // This is a SkFontMgr which will use FreeType to decode font data.
255 g_fontmgr = SkFontMgr_New_Custom_Empty().release();
256#endif
257}
258
259// static
260void CFX_GlyphCache::DestroyGlobals() {
261 CHECK(g_fontmgr);
262 delete g_fontmgr;
263 g_fontmgr = nullptr;
264}
265
266CFX_TypeFace* CFX_GlyphCache::GetDeviceCache(const CFX_Font* pFont) {
267 if (!m_pTypeface && g_fontmgr) {
268 pdfium::span<const uint8_t> span = pFont->GetFontSpan();
269 m_pTypeface = g_fontmgr->makeFromStream(
270 std::make_unique<SkMemoryStream>(span.data(), span.size()));
271 }
272#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
273 // If DirectWrite or CoreText didn't work, try FreeType.
274 if (!m_pTypeface) {
275 sk_sp<SkFontMgr> freetype_mgr = SkFontMgr_New_Custom_Empty();
276 pdfium::span<const uint8_t> span = pFont->GetFontSpan();
277 m_pTypeface = freetype_mgr->makeFromStream(
278 std::make_unique<SkMemoryStream>(span.data(), span.size()));
279 }
280#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
281 return m_pTypeface.get();
282}
283#endif // defined(PDF_USE_SKIA)
284
285CFX_GlyphBitmap* CFX_GlyphCache::LookUpGlyphBitmap(
286 const CFX_Font* pFont,
287 const CFX_Matrix& matrix,
288 const ByteString& FaceGlyphsKey,
289 uint32_t glyph_index,
290 bool bFontStyle,
291 int dest_width,
292 int anti_alias) {
293 SizeGlyphCache* pSizeCache;
294 auto it = m_SizeMap.find(FaceGlyphsKey);
295 if (it == m_SizeMap.end()) {
296 m_SizeMap[FaceGlyphsKey] = SizeGlyphCache();
297 pSizeCache = &(m_SizeMap[FaceGlyphsKey]);
298 } else {
299 pSizeCache = &(it->second);
300 }
301
302 auto it2 = pSizeCache->find(glyph_index);
303 if (it2 != pSizeCache->end())
304 return it2->second.get();
305
306 std::unique_ptr<CFX_GlyphBitmap> pGlyphBitmap = RenderGlyph(
307 pFont, glyph_index, bFontStyle, matrix, dest_width, anti_alias);
308 CFX_GlyphBitmap* pResult = pGlyphBitmap.get();
309 (*pSizeCache)[glyph_index] = std::move(pGlyphBitmap);
310 return pResult;
311}
fxcrt::ByteString ByteString
Definition bytestring.h:180
bool IsVertical() const
Definition cfx_font.h:108
CFX_SubstFont * GetSubstFont() const
Definition cfx_font.h:79
const CFX_GlyphBitmap * LoadGlyphBitmap(const CFX_Font *pFont, uint32_t glyph_index, bool bFontStyle, const CFX_Matrix &matrix, int dest_width, int anti_alias, CFX_TextRenderOptions *text_options)
int GetGlyphWidth(const CFX_Font *font, uint32_t glyph_index, int dest_width, int weight)
const CFX_Path * LoadGlyphPath(const CFX_Font *pFont, uint32_t glyph_index, int dest_width)
~CFX_GlyphCache() override
#define CHECK(cvref)
fxcrt::ByteStringView ByteStringView