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