xref: /aosp_15_r20/external/pdfium/core/fxge/cfx_glyphcache.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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 <algorithm>
12 #include <limits>
13 #include <memory>
14 #include <utility>
15 
16 #include "build/build_config.h"
17 #include "core/fxcrt/fx_codepage.h"
18 #include "core/fxge/cfx_defaultrenderdevice.h"
19 #include "core/fxge/cfx_font.h"
20 #include "core/fxge/cfx_fontmgr.h"
21 #include "core/fxge/cfx_gemodule.h"
22 #include "core/fxge/cfx_glyphbitmap.h"
23 #include "core/fxge/cfx_path.h"
24 #include "core/fxge/cfx_substfont.h"
25 #include "core/fxge/dib/cfx_dibitmap.h"
26 #include "core/fxge/freetype/fx_freetype.h"
27 #include "core/fxge/scoped_font_transform.h"
28 #include "third_party/base/numerics/safe_math.h"
29 
30 #if defined(_SKIA_SUPPORT_)
31 #include "third_party/skia/include/core/SkStream.h"  // nogncheck
32 #include "third_party/skia/include/core/SkTypeface.h"  // nogncheck
33 
34 #if BUILDFLAG(IS_WIN)
35 #include "third_party/skia/include/core/SkFontMgr.h"  // nogncheck
36 #include "third_party/skia/include/ports/SkFontMgr_empty.h"  // nogncheck
37 #endif
38 #endif
39 
40 #if BUILDFLAG(IS_APPLE)
41 #include "core/fxge/cfx_textrenderoptions.h"
42 #endif
43 
44 namespace {
45 
46 constexpr uint32_t kInvalidGlyphIndex = static_cast<uint32_t>(-1);
47 
48 constexpr int kMaxGlyphDimension = 2048;
49 
50 struct UniqueKeyGen {
51   void Generate(int count, ...);
52 
53   int key_len_;
54   char key_[128];
55 };
56 
Generate(int count,...)57 void UniqueKeyGen::Generate(int count, ...) {
58   va_list argList;
59   va_start(argList, count);
60   for (int i = 0; i < count; i++) {
61     int p = va_arg(argList, int);
62     reinterpret_cast<uint32_t*>(key_)[i] = p;
63   }
64   va_end(argList);
65   key_len_ = count * sizeof(uint32_t);
66 }
67 
GenKey(UniqueKeyGen * pKeyGen,const CFX_Font * pFont,const CFX_Matrix & matrix,int dest_width,int anti_alias,bool bNative)68 void GenKey(UniqueKeyGen* pKeyGen,
69             const CFX_Font* pFont,
70             const CFX_Matrix& matrix,
71             int dest_width,
72             int anti_alias,
73             bool bNative) {
74   int nMatrixA = static_cast<int>(matrix.a * 10000);
75   int nMatrixB = static_cast<int>(matrix.b * 10000);
76   int nMatrixC = static_cast<int>(matrix.c * 10000);
77   int nMatrixD = static_cast<int>(matrix.d * 10000);
78 
79 #if BUILDFLAG(IS_APPLE)
80   if (bNative) {
81     if (pFont->GetSubstFont()) {
82       pKeyGen->Generate(10, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
83                         anti_alias, pFont->GetSubstFont()->m_Weight,
84                         pFont->GetSubstFont()->m_ItalicAngle,
85                         pFont->IsVertical(), 3);
86     } else {
87       pKeyGen->Generate(7, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
88                         anti_alias, 3);
89     }
90     return;
91   }
92 #else
93   CHECK(!bNative);
94 #endif
95 
96   if (pFont->GetSubstFont()) {
97     pKeyGen->Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
98                       anti_alias, pFont->GetSubstFont()->m_Weight,
99                       pFont->GetSubstFont()->m_ItalicAngle,
100                       pFont->IsVertical());
101   } else {
102     pKeyGen->Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
103                       anti_alias);
104   }
105 }
106 
107 }  // namespace
108 
CFX_GlyphCache(RetainPtr<CFX_Face> face)109 CFX_GlyphCache::CFX_GlyphCache(RetainPtr<CFX_Face> face)
110     : m_Face(std::move(face)) {}
111 
112 CFX_GlyphCache::~CFX_GlyphCache() = default;
113 
RenderGlyph(const CFX_Font * pFont,uint32_t glyph_index,bool bFontStyle,const CFX_Matrix & matrix,int dest_width,int anti_alias)114 std::unique_ptr<CFX_GlyphBitmap> CFX_GlyphCache::RenderGlyph(
115     const CFX_Font* pFont,
116     uint32_t glyph_index,
117     bool bFontStyle,
118     const CFX_Matrix& matrix,
119     int dest_width,
120     int anti_alias) {
121   if (!GetFaceRec())
122     return nullptr;
123 
124   FT_Matrix ft_matrix;
125   ft_matrix.xx = matrix.a / 64 * 65536;
126   ft_matrix.xy = matrix.c / 64 * 65536;
127   ft_matrix.yx = matrix.b / 64 * 65536;
128   ft_matrix.yy = matrix.d / 64 * 65536;
129   bool bUseCJKSubFont = false;
130   const CFX_SubstFont* pSubstFont = pFont->GetSubstFont();
131   if (pSubstFont) {
132     bUseCJKSubFont = pSubstFont->m_bSubstCJK && bFontStyle;
133     int angle;
134     if (bUseCJKSubFont)
135       angle = pSubstFont->m_bItalicCJK ? -15 : 0;
136     else
137       angle = pSubstFont->m_ItalicAngle;
138     if (angle) {
139       int skew = CFX_Font::GetSkewFromAngle(angle);
140       if (pFont->IsVertical())
141         ft_matrix.yx += ft_matrix.yy * skew / 100;
142       else
143         ft_matrix.xy -= ft_matrix.xx * skew / 100;
144     }
145     if (pSubstFont->IsBuiltInGenericFont()) {
146       pFont->AdjustMMParams(glyph_index, dest_width,
147                             pFont->GetSubstFont()->m_Weight);
148     }
149   }
150 
151   ScopedFontTransform scoped_transform(GetFace(), &ft_matrix);
152   int load_flags = FT_LOAD_NO_BITMAP | FT_LOAD_PEDANTIC;
153   if (!(GetFaceRec()->face_flags & FT_FACE_FLAG_SFNT))
154     load_flags |= FT_LOAD_NO_HINTING;
155   int error = FT_Load_Glyph(GetFaceRec(), glyph_index, load_flags);
156   if (error) {
157     // if an error is returned, try to reload glyphs without hinting.
158     if (load_flags & FT_LOAD_NO_HINTING)
159       return nullptr;
160 
161     load_flags |= FT_LOAD_NO_HINTING;
162     load_flags &= ~FT_LOAD_PEDANTIC;
163     error = FT_Load_Glyph(GetFaceRec(), glyph_index, load_flags);
164     if (error)
165       return nullptr;
166   }
167 
168   int weight;
169   if (bUseCJKSubFont)
170     weight = pSubstFont->m_WeightCJK;
171   else
172     weight = pSubstFont ? pSubstFont->m_Weight : 0;
173   if (pSubstFont && !pSubstFont->IsBuiltInGenericFont() && weight > 400) {
174     uint32_t index = (weight - 400) / 10;
175     pdfium::base::CheckedNumeric<signed long> level =
176         CFX_Font::GetWeightLevel(pSubstFont->m_Charset, index);
177     if (level.ValueOrDefault(-1) < 0)
178       return nullptr;
179 
180     level = level *
181             (abs(static_cast<int>(ft_matrix.xx)) +
182              abs(static_cast<int>(ft_matrix.xy))) /
183             36655;
184     FT_Outline_Embolden(FXFT_Get_Glyph_Outline(GetFaceRec()),
185                         level.ValueOrDefault(0));
186   }
187   FT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(),
188                           FT_LCD_FILTER_DEFAULT);
189   error = FXFT_Render_Glyph(GetFaceRec(), anti_alias);
190   if (error)
191     return nullptr;
192 
193   int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(GetFaceRec()));
194   int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(GetFaceRec()));
195   if (bmwidth > kMaxGlyphDimension || bmheight > kMaxGlyphDimension)
196     return nullptr;
197   int dib_width = bmwidth;
198   auto pGlyphBitmap =
199       std::make_unique<CFX_GlyphBitmap>(FXFT_Get_Glyph_BitmapLeft(GetFaceRec()),
200                                         FXFT_Get_Glyph_BitmapTop(GetFaceRec()));
201   pGlyphBitmap->GetBitmap()->Create(dib_width, bmheight,
202                                     anti_alias == FT_RENDER_MODE_MONO
203                                         ? FXDIB_Format::k1bppMask
204                                         : FXDIB_Format::k8bppMask);
205   int dest_pitch = pGlyphBitmap->GetBitmap()->GetPitch();
206   int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(GetFaceRec()));
207   uint8_t* pDestBuf = pGlyphBitmap->GetBitmap()->GetWritableBuffer().data();
208   uint8_t* pSrcBuf = static_cast<uint8_t*>(
209       FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(GetFaceRec())));
210   if (anti_alias != FT_RENDER_MODE_MONO &&
211       FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(GetFaceRec())) ==
212           FT_PIXEL_MODE_MONO) {
213     int bytes = anti_alias == FT_RENDER_MODE_LCD ? 3 : 1;
214     for (int i = 0; i < bmheight; i++) {
215       for (int n = 0; n < bmwidth; n++) {
216         uint8_t data =
217             (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0;
218         for (int b = 0; b < bytes; b++)
219           pDestBuf[i * dest_pitch + n * bytes + b] = data;
220       }
221     }
222   } else {
223     memset(pDestBuf, 0, dest_pitch * bmheight);
224     int rowbytes = std::min(abs(src_pitch), dest_pitch);
225     for (int row = 0; row < bmheight; row++)
226       memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch, rowbytes);
227   }
228   return pGlyphBitmap;
229 }
230 
LoadGlyphPath(const CFX_Font * pFont,uint32_t glyph_index,int dest_width)231 const CFX_Path* CFX_GlyphCache::LoadGlyphPath(const CFX_Font* pFont,
232                                               uint32_t glyph_index,
233                                               int dest_width) {
234   if (!GetFaceRec() || glyph_index == kInvalidGlyphIndex)
235     return nullptr;
236 
237   const auto* pSubstFont = pFont->GetSubstFont();
238   int weight = pSubstFont ? pSubstFont->m_Weight : 0;
239   int angle = pSubstFont ? pSubstFont->m_ItalicAngle : 0;
240   bool vertical = pSubstFont && pFont->IsVertical();
241   const PathMapKey key =
242       std::make_tuple(glyph_index, dest_width, weight, angle, vertical);
243   auto it = m_PathMap.find(key);
244   if (it != m_PathMap.end())
245     return it->second.get();
246 
247   m_PathMap[key] = pFont->LoadGlyphPathImpl(glyph_index, dest_width);
248   return m_PathMap[key].get();
249 }
250 
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)251 const CFX_GlyphBitmap* CFX_GlyphCache::LoadGlyphBitmap(
252     const CFX_Font* pFont,
253     uint32_t glyph_index,
254     bool bFontStyle,
255     const CFX_Matrix& matrix,
256     int dest_width,
257     int anti_alias,
258     CFX_TextRenderOptions* text_options) {
259   if (glyph_index == kInvalidGlyphIndex)
260     return nullptr;
261 
262   UniqueKeyGen keygen;
263 #if BUILDFLAG(IS_APPLE)
264   const bool bNative = text_options->native_text;
265 #else
266   const bool bNative = false;
267 #endif
268   GenKey(&keygen, pFont, matrix, dest_width, anti_alias, bNative);
269   ByteString FaceGlyphsKey(keygen.key_, keygen.key_len_);
270 
271 #if BUILDFLAG(IS_APPLE)
272   const bool bDoLookUp = !text_options->native_text ||
273                          CFX_DefaultRenderDevice::SkiaIsDefaultRenderer();
274 #else
275   const bool bDoLookUp = true;
276 #endif
277   if (bDoLookUp) {
278     return LookUpGlyphBitmap(pFont, matrix, FaceGlyphsKey, glyph_index,
279                              bFontStyle, dest_width, anti_alias);
280   }
281 
282 #if BUILDFLAG(IS_APPLE)
283   DCHECK(!CFX_DefaultRenderDevice::SkiaIsDefaultRenderer());
284 
285   std::unique_ptr<CFX_GlyphBitmap> pGlyphBitmap;
286   auto it = m_SizeMap.find(FaceGlyphsKey);
287   if (it != m_SizeMap.end()) {
288     SizeGlyphCache* pSizeCache = &(it->second);
289     auto it2 = pSizeCache->find(glyph_index);
290     if (it2 != pSizeCache->end())
291       return it2->second.get();
292 
293     pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, matrix,
294                                           dest_width, anti_alias);
295     if (pGlyphBitmap) {
296       CFX_GlyphBitmap* pResult = pGlyphBitmap.get();
297       (*pSizeCache)[glyph_index] = std::move(pGlyphBitmap);
298       return pResult;
299     }
300   } else {
301     pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, matrix,
302                                           dest_width, anti_alias);
303     if (pGlyphBitmap) {
304       CFX_GlyphBitmap* pResult = pGlyphBitmap.get();
305 
306       SizeGlyphCache cache;
307       cache[glyph_index] = std::move(pGlyphBitmap);
308 
309       m_SizeMap[FaceGlyphsKey] = std::move(cache);
310       return pResult;
311     }
312   }
313   GenKey(&keygen, pFont, matrix, dest_width, anti_alias, /*bNative=*/false);
314   ByteString FaceGlyphsKey2(keygen.key_, keygen.key_len_);
315   text_options->native_text = false;
316   return LookUpGlyphBitmap(pFont, matrix, FaceGlyphsKey2, glyph_index,
317                            bFontStyle, dest_width, anti_alias);
318 #endif  // BUILDFLAG(IS_APPLE)
319 }
320 
GetGlyphWidth(const CFX_Font * font,uint32_t glyph_index,int dest_width,int weight)321 int CFX_GlyphCache::GetGlyphWidth(const CFX_Font* font,
322                                   uint32_t glyph_index,
323                                   int dest_width,
324                                   int weight) {
325   const WidthMapKey key = std::make_tuple(glyph_index, dest_width, weight);
326   auto it = m_WidthMap.find(key);
327   if (it != m_WidthMap.end()) {
328     return it->second;
329   }
330 
331   m_WidthMap[key] = font->GetGlyphWidthImpl(glyph_index, dest_width, weight);
332   return m_WidthMap[key];
333 }
334 
335 #if defined(_SKIA_SUPPORT_)
GetDeviceCache(const CFX_Font * pFont)336 CFX_TypeFace* CFX_GlyphCache::GetDeviceCache(const CFX_Font* pFont) {
337   if (!m_pTypeface) {
338     pdfium::span<const uint8_t> span = pFont->GetFontSpan();
339     m_pTypeface = SkTypeface::MakeFromStream(
340         std::make_unique<SkMemoryStream>(span.data(), span.size()));
341   }
342 #if BUILDFLAG(IS_WIN)
343   if (!m_pTypeface) {
344     sk_sp<SkFontMgr> customMgr(SkFontMgr_New_Custom_Empty());
345     pdfium::span<const uint8_t> span = pFont->GetFontSpan();
346     m_pTypeface = customMgr->makeFromStream(
347         std::make_unique<SkMemoryStream>(span.data(), span.size()));
348   }
349 #endif  // BUILDFLAG(IS_WIN)
350   return m_pTypeface.get();
351 }
352 #endif  // defined(_SKIA_SUPPORT_)
353 
LookUpGlyphBitmap(const CFX_Font * pFont,const CFX_Matrix & matrix,const ByteString & FaceGlyphsKey,uint32_t glyph_index,bool bFontStyle,int dest_width,int anti_alias)354 CFX_GlyphBitmap* CFX_GlyphCache::LookUpGlyphBitmap(
355     const CFX_Font* pFont,
356     const CFX_Matrix& matrix,
357     const ByteString& FaceGlyphsKey,
358     uint32_t glyph_index,
359     bool bFontStyle,
360     int dest_width,
361     int anti_alias) {
362   SizeGlyphCache* pSizeCache;
363   auto it = m_SizeMap.find(FaceGlyphsKey);
364   if (it == m_SizeMap.end()) {
365     m_SizeMap[FaceGlyphsKey] = SizeGlyphCache();
366     pSizeCache = &(m_SizeMap[FaceGlyphsKey]);
367   } else {
368     pSizeCache = &(it->second);
369   }
370 
371   auto it2 = pSizeCache->find(glyph_index);
372   if (it2 != pSizeCache->end())
373     return it2->second.get();
374 
375   std::unique_ptr<CFX_GlyphBitmap> pGlyphBitmap = RenderGlyph(
376       pFont, glyph_index, bFontStyle, matrix, dest_width, anti_alias);
377   CFX_GlyphBitmap* pResult = pGlyphBitmap.get();
378   (*pSizeCache)[glyph_index] = std::move(pGlyphBitmap);
379   return pResult;
380 }
381