• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
41 namespace {
42 
43 constexpr uint32_t kInvalidGlyphIndex = static_cast<uint32_t>(-1);
44 
45 class 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 
Initialize(std::initializer_list<const int32_t> args)62 void 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 
span() const71 pdfium::span<const uint8_t> UniqueKeyGen::span() const {
72   return pdfium::as_bytes(pdfium::make_span(key_).first(key_len_));
73 }
74 
UniqueKeyGen(const CFX_Font * pFont,const CFX_Matrix & matrix,int dest_width,int anti_alias,bool bNative)75 UniqueKeyGen::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,
103                 pFont->GetSubstFont()->m_Weight,
104                 pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()});
105   } else {
106     Initialize(
107         {nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, anti_alias});
108   }
109 }
110 
111 }  // namespace
112 
CFX_GlyphCache(RetainPtr<CFX_Face> face)113 CFX_GlyphCache::CFX_GlyphCache(RetainPtr<CFX_Face> face)
114     : m_Face(std::move(face)) {}
115 
116 CFX_GlyphCache::~CFX_GlyphCache() = default;
117 
RenderGlyph(const CFX_Font * pFont,uint32_t glyph_index,bool bFontStyle,const CFX_Matrix & matrix,int dest_width,int anti_alias)118 std::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 
LoadGlyphPath(const CFX_Font * pFont,uint32_t glyph_index,int dest_width)133 const 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 
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)154 const 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 
GetGlyphWidth(const CFX_Font * font,uint32_t glyph_index,int dest_width,int weight)224 int 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 
240 namespace {
241 // A singleton SkFontMgr which can be used to decode raw font data or
242 // otherwise get access to system fonts.
243 SkFontMgr* g_fontmgr = nullptr;
244 }  // namespace
245 
246 // static
InitializeGlobals()247 void 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
DestroyGlobals()260 void CFX_GlyphCache::DestroyGlobals() {
261   CHECK(g_fontmgr);
262   delete g_fontmgr;
263   g_fontmgr = nullptr;
264 }
265 
GetDeviceCache(const CFX_Font * pFont)266 CFX_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 
LookUpGlyphBitmap(const CFX_Font * pFont,const CFX_Matrix & matrix,const ByteString & FaceGlyphsKey,uint32_t glyph_index,bool bFontStyle,int dest_width,int anti_alias)285 CFX_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 }
312