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 <stdarg.h>
10
11#include <memory>
12#include <utility>
13
14#include "build/build_config.h"
15#include "core/fxcrt/fx_codepage.h"
16#include "core/fxcrt/fx_memcpy_wrappers.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 "include/ports/SkTypeface_win.h" // nogncheck
31#elif BUILDFLAG(IS_APPLE)
32#include "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
45struct UniqueKeyGen {
46 void Generate(int count, ...);
47
48 int key_len_;
49 char key_[128];
50};
51
52void UniqueKeyGen::Generate(int count, ...) {
53 va_list argList;
54 va_start(argList, count);
55 for (int i = 0; i < count; i++) {
56 int p = va_arg(argList, int);
57 reinterpret_cast<uint32_t*>(key_)[i] = p;
58 }
59 va_end(argList);
60 key_len_ = count * sizeof(uint32_t);
61}
62
63void GenKey(UniqueKeyGen* pKeyGen,
64 const CFX_Font* pFont,
65 const CFX_Matrix& matrix,
66 int dest_width,
67 int anti_alias,
68 bool bNative) {
69 int nMatrixA = static_cast<int>(matrix.a * 10000);
70 int nMatrixB = static_cast<int>(matrix.b * 10000);
71 int nMatrixC = static_cast<int>(matrix.c * 10000);
72 int nMatrixD = static_cast<int>(matrix.d * 10000);
73
74#if BUILDFLAG(IS_APPLE)
75 if (bNative) {
76 if (pFont->GetSubstFont()) {
77 pKeyGen->Generate(10, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
78 anti_alias, pFont->GetSubstFont()->m_Weight,
79 pFont->GetSubstFont()->m_ItalicAngle,
80 pFont->IsVertical(), 3);
81 } else {
82 pKeyGen->Generate(7, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
83 anti_alias, 3);
84 }
85 return;
86 }
87#else
88 CHECK(!bNative);
89#endif
90
91 if (pFont->GetSubstFont()) {
92 pKeyGen->Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
93 anti_alias, pFont->GetSubstFont()->m_Weight,
95 pFont->IsVertical());
96 } else {
97 pKeyGen->Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
98 anti_alias);
99 }
100}
101
102} // namespace
103
104CFX_GlyphCache::CFX_GlyphCache(RetainPtr<CFX_Face> face)
105 : m_Face(std::move(face)) {}
106
107CFX_GlyphCache::~CFX_GlyphCache() = default;
108
109std::unique_ptr<CFX_GlyphBitmap> CFX_GlyphCache::RenderGlyph(
110 const CFX_Font* pFont,
111 uint32_t glyph_index,
112 bool bFontStyle,
113 const CFX_Matrix& matrix,
114 int dest_width,
115 int anti_alias) {
116 if (!m_Face) {
117 return nullptr;
118 }
119
120 return m_Face->RenderGlyph(pFont, glyph_index, bFontStyle, matrix, dest_width,
121 anti_alias);
122}
123
124const CFX_Path* CFX_GlyphCache::LoadGlyphPath(const CFX_Font* pFont,
125 uint32_t glyph_index,
126 int dest_width) {
127 if (!GetFace() || glyph_index == kInvalidGlyphIndex) {
128 return nullptr;
129 }
130
131 const auto* pSubstFont = pFont->GetSubstFont();
132 int weight = pSubstFont ? pSubstFont->m_Weight : 0;
133 int angle = pSubstFont ? pSubstFont->m_ItalicAngle : 0;
134 bool vertical = pSubstFont && pFont->IsVertical();
135 const PathMapKey key =
136 std::make_tuple(glyph_index, dest_width, weight, angle, vertical);
137 auto it = m_PathMap.find(key);
138 if (it != m_PathMap.end())
139 return it->second.get();
140
141 m_PathMap[key] = pFont->LoadGlyphPathImpl(glyph_index, dest_width);
142 return m_PathMap[key].get();
143}
144
145const CFX_GlyphBitmap* CFX_GlyphCache::LoadGlyphBitmap(
146 const CFX_Font* pFont,
147 uint32_t glyph_index,
148 bool bFontStyle,
149 const CFX_Matrix& matrix,
150 int dest_width,
151 int anti_alias,
152 CFX_TextRenderOptions* text_options) {
153 if (glyph_index == kInvalidGlyphIndex)
154 return nullptr;
155
156 UniqueKeyGen keygen;
157#if BUILDFLAG(IS_APPLE)
158 const bool bNative = text_options->native_text;
159#else
160 const bool bNative = false;
161#endif
162 GenKey(&keygen, pFont, matrix, dest_width, anti_alias, bNative);
163 ByteString FaceGlyphsKey(keygen.key_, keygen.key_len_);
164
165#if BUILDFLAG(IS_APPLE)
166 const bool bDoLookUp =
167 !text_options->native_text || CFX_DefaultRenderDevice::UseSkiaRenderer();
168#else
169 const bool bDoLookUp = true;
170#endif
171 if (bDoLookUp) {
172 return LookUpGlyphBitmap(pFont, matrix, FaceGlyphsKey, glyph_index,
173 bFontStyle, dest_width, anti_alias);
174 }
175
176#if BUILDFLAG(IS_APPLE)
177 DCHECK(!CFX_DefaultRenderDevice::UseSkiaRenderer());
178
179 std::unique_ptr<CFX_GlyphBitmap> pGlyphBitmap;
180 auto it = m_SizeMap.find(FaceGlyphsKey);
181 if (it != m_SizeMap.end()) {
182 SizeGlyphCache* pSizeCache = &(it->second);
183 auto it2 = pSizeCache->find(glyph_index);
184 if (it2 != pSizeCache->end())
185 return it2->second.get();
186
187 pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, matrix,
188 dest_width, anti_alias);
189 if (pGlyphBitmap) {
190 CFX_GlyphBitmap* pResult = pGlyphBitmap.get();
191 (*pSizeCache)[glyph_index] = std::move(pGlyphBitmap);
192 return pResult;
193 }
194 } else {
195 pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, matrix,
196 dest_width, anti_alias);
197 if (pGlyphBitmap) {
198 CFX_GlyphBitmap* pResult = pGlyphBitmap.get();
199
200 SizeGlyphCache cache;
201 cache[glyph_index] = std::move(pGlyphBitmap);
202
203 m_SizeMap[FaceGlyphsKey] = std::move(cache);
204 return pResult;
205 }
206 }
207 GenKey(&keygen, pFont, matrix, dest_width, anti_alias, /*bNative=*/false);
208 ByteString FaceGlyphsKey2(keygen.key_, keygen.key_len_);
209 text_options->native_text = false;
210 return LookUpGlyphBitmap(pFont, matrix, FaceGlyphsKey2, glyph_index,
211 bFontStyle, dest_width, anti_alias);
212#endif // BUILDFLAG(IS_APPLE)
213}
214
215int CFX_GlyphCache::GetGlyphWidth(const CFX_Font* font,
216 uint32_t glyph_index,
217 int dest_width,
218 int weight) {
219 const WidthMapKey key = std::make_tuple(glyph_index, dest_width, weight);
220 auto it = m_WidthMap.find(key);
221 if (it != m_WidthMap.end()) {
222 return it->second;
223 }
224
225 m_WidthMap[key] = font->GetGlyphWidthImpl(glyph_index, dest_width, weight);
226 return m_WidthMap[key];
227}
228
229#if defined(PDF_USE_SKIA)
230
231namespace {
232// A singleton SkFontMgr which can be used to decode raw font data or
233// otherwise get access to system fonts.
234SkFontMgr* g_fontmgr = nullptr;
235} // namespace
236
237// static
238void CFX_GlyphCache::InitializeGlobals() {
239 CHECK(!g_fontmgr);
240#if BUILDFLAG(IS_WIN)
241 g_fontmgr = SkFontMgr_New_DirectWrite().release();
242#elif BUILDFLAG(IS_APPLE)
243 g_fontmgr = SkFontMgr_New_CoreText(nullptr).release();
244#else
245 // This is a SkFontMgr which will use FreeType to decode font data.
246 g_fontmgr = SkFontMgr_New_Custom_Empty().release();
247#endif
248}
249
250// static
251void CFX_GlyphCache::DestroyGlobals() {
252 CHECK(g_fontmgr);
253 delete g_fontmgr;
254 g_fontmgr = nullptr;
255}
256
257CFX_TypeFace* CFX_GlyphCache::GetDeviceCache(const CFX_Font* pFont) {
258 if (!m_pTypeface && g_fontmgr) {
259 pdfium::span<const uint8_t> span = pFont->GetFontSpan();
260 m_pTypeface = g_fontmgr->makeFromStream(
261 std::make_unique<SkMemoryStream>(span.data(), span.size()));
262 }
263#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
264 // If DirectWrite or CoreText didn't work, try FreeType.
265 if (!m_pTypeface) {
266 sk_sp<SkFontMgr> freetype_mgr = SkFontMgr_New_Custom_Empty();
267 pdfium::span<const uint8_t> span = pFont->GetFontSpan();
268 m_pTypeface = freetype_mgr->makeFromStream(
269 std::make_unique<SkMemoryStream>(span.data(), span.size()));
270 }
271#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
272 return m_pTypeface.get();
273}
274#endif // defined(PDF_USE_SKIA)
275
276CFX_GlyphBitmap* CFX_GlyphCache::LookUpGlyphBitmap(
277 const CFX_Font* pFont,
278 const CFX_Matrix& matrix,
279 const ByteString& FaceGlyphsKey,
280 uint32_t glyph_index,
281 bool bFontStyle,
282 int dest_width,
283 int anti_alias) {
284 SizeGlyphCache* pSizeCache;
285 auto it = m_SizeMap.find(FaceGlyphsKey);
286 if (it == m_SizeMap.end()) {
287 m_SizeMap[FaceGlyphsKey] = SizeGlyphCache();
288 pSizeCache = &(m_SizeMap[FaceGlyphsKey]);
289 } else {
290 pSizeCache = &(it->second);
291 }
292
293 auto it2 = pSizeCache->find(glyph_index);
294 if (it2 != pSizeCache->end())
295 return it2->second.get();
296
297 std::unique_ptr<CFX_GlyphBitmap> pGlyphBitmap = RenderGlyph(
298 pFont, glyph_index, bFontStyle, matrix, dest_width, anti_alias);
299 CFX_GlyphBitmap* pResult = pGlyphBitmap.get();
300 (*pSizeCache)[glyph_index] = std::move(pGlyphBitmap);
301 return pResult;
302}
bool IsVertical() const
Definition cfx_font.h:111
CFX_SubstFont * GetSubstFont() const
Definition cfx_font.h:82
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)