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