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