OLD | NEW |
---|---|
(Empty) | |
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/include/cfx_facecache.h" | |
8 | |
9 #include <algorithm> | |
10 | |
11 #include "core/fxge/ge/fx_text_int.h" | |
12 #include "core/fxge/include/cfx_fontmgr.h" | |
13 #include "core/fxge/include/cfx_gemodule.h" | |
14 #include "core/fxge/include/cfx_pathdata.h" | |
15 #include "core/fxge/include/fx_freetype.h" | |
16 | |
17 #ifdef _SKIA_SUPPORT_ | |
18 #include "third_party/skia/include/core/SkStream.h" | |
19 #include "third_party/skia/include/core/SkTypeface.h" | |
20 #endif | |
21 | |
22 namespace { | |
23 | |
24 void GammaAdjust(uint8_t* pData, | |
25 int nHeight, | |
26 int src_pitch, | |
27 const uint8_t* gammaTable) { | |
28 int count = nHeight * src_pitch; | |
29 for (int i = 0; i < count; i++) | |
30 pData[i] = gammaTable[pData[i]]; | |
31 } | |
32 | |
33 void ContrastAdjust(uint8_t* pDataIn, | |
34 uint8_t* pDataOut, | |
35 int nWidth, | |
36 int nHeight, | |
37 int nSrcRowBytes, | |
38 int nDstRowBytes) { | |
39 int col, row, temp; | |
40 int max = 0, min = 255; | |
41 FX_FLOAT rate; | |
42 for (row = 0; row < nHeight; row++) { | |
43 uint8_t* pRow = pDataIn + row * nSrcRowBytes; | |
44 for (col = 0; col < nWidth; col++) { | |
45 temp = *pRow++; | |
46 max = std::max(temp, max); | |
47 min = std::min(temp, min); | |
48 } | |
49 } | |
50 temp = max - min; | |
51 if (temp == 0 || temp == 255) { | |
52 int rowbytes = std::min(FXSYS_abs(nSrcRowBytes), nDstRowBytes); | |
53 for (row = 0; row < nHeight; row++) { | |
54 FXSYS_memcpy(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes, | |
55 rowbytes); | |
56 } | |
57 return; | |
58 } | |
59 rate = 255.f / temp; | |
60 for (row = 0; row < nHeight; row++) { | |
61 uint8_t* pSrcRow = pDataIn + row * nSrcRowBytes; | |
62 uint8_t* pDstRow = pDataOut + row * nDstRowBytes; | |
63 for (col = 0; col < nWidth; col++) { | |
64 temp = static_cast<int>((*(pSrcRow++) - min) * rate + 0.5); | |
65 temp = std::min(temp, 255); | |
66 temp = std::max(temp, 0); | |
67 *pDstRow++ = (uint8_t)temp; | |
68 } | |
69 } | |
70 } | |
71 } // namespace | |
72 | |
73 CFX_FaceCache::CFX_FaceCache(FXFT_Face face) | |
74 : m_Face(face) | |
75 #ifdef _SKIA_SUPPORT_ | |
76 , | |
77 m_pTypeface(nullptr) | |
78 #endif | |
79 { | |
80 } | |
81 | |
82 CFX_FaceCache::~CFX_FaceCache() { | |
83 #ifdef _SKIA_SUPPORT_ | |
84 SkSafeUnref(m_pTypeface); | |
85 #endif | |
86 } | |
87 | |
88 CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph(CFX_Font* pFont, | |
89 uint32_t glyph_index, | |
90 FX_BOOL bFontStyle, | |
91 const CFX_Matrix* pMatrix, | |
92 int dest_width, | |
93 int anti_alias) { | |
94 if (!m_Face) | |
95 return nullptr; | |
96 | |
97 FXFT_Matrix ft_matrix; | |
98 ft_matrix.xx = (signed long)(pMatrix->GetA() / 64 * 65536); | |
99 ft_matrix.xy = (signed long)(pMatrix->GetC() / 64 * 65536); | |
100 ft_matrix.yx = (signed long)(pMatrix->GetB() / 64 * 65536); | |
101 ft_matrix.yy = (signed long)(pMatrix->GetD() / 64 * 65536); | |
102 bool bUseCJKSubFont = FALSE; | |
Lei Zhang
2016/08/19 22:44:58
s/FALSE/false/
| |
103 const CFX_SubstFont* pSubstFont = pFont->GetSubstFont(); | |
104 if (pSubstFont) { | |
105 bUseCJKSubFont = pSubstFont->m_bSubstCJK && bFontStyle; | |
106 int skew = 0; | |
107 if (bUseCJKSubFont) | |
108 skew = pSubstFont->m_bItalicCJK ? -15 : 0; | |
109 else | |
110 skew = pSubstFont->m_ItalicAngle; | |
111 if (skew) { | |
112 // |skew| is nonpositive so |-skew| is used as the index. We need to make | |
113 // sure |skew| != INT_MIN since -INT_MIN is undefined. | |
114 if (skew <= 0 && skew != std::numeric_limits<int>::min() && | |
115 static_cast<size_t>(-skew) < CFX_Font::kAngleSkewArraySize) { | |
116 skew = -CFX_Font::s_AngleSkew[-skew]; | |
117 } else { | |
118 skew = -58; | |
119 } | |
120 if (pFont->IsVertical()) | |
121 ft_matrix.yx += ft_matrix.yy * skew / 100; | |
122 else | |
123 ft_matrix.xy -= ft_matrix.xx * skew / 100; | |
124 } | |
125 if (pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { | |
126 pFont->AdjustMMParams(glyph_index, dest_width, | |
127 pFont->GetSubstFont()->m_Weight); | |
128 } | |
129 } | |
130 ScopedFontTransform scoped_transform(m_Face, &ft_matrix); | |
131 int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT) | |
132 ? FXFT_LOAD_NO_BITMAP | |
133 : (FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); | |
134 int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); | |
135 if (error) { | |
136 // if an error is returned, try to reload glyphs without hinting. | |
137 if (load_flags & FT_LOAD_NO_HINTING || load_flags & FT_LOAD_NO_SCALE) | |
138 return nullptr; | |
139 | |
140 load_flags |= FT_LOAD_NO_HINTING; | |
141 error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); | |
142 | |
143 if (error) | |
144 return nullptr; | |
145 } | |
146 int weight = 0; | |
147 if (bUseCJKSubFont) | |
148 weight = pSubstFont->m_WeightCJK; | |
149 else | |
150 weight = pSubstFont ? pSubstFont->m_Weight : 0; | |
151 if (pSubstFont && !(pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && | |
152 weight > 400) { | |
153 uint32_t index = (weight - 400) / 10; | |
154 if (index >= CFX_Font::kWeightPowArraySize) | |
155 return nullptr; | |
156 int level = 0; | |
157 if (pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) { | |
158 level = | |
159 CFX_Font::s_WeightPow_SHIFTJIS[index] * 2 * | |
160 (FXSYS_abs((int)(ft_matrix.xx)) + FXSYS_abs((int)(ft_matrix.xy))) / | |
161 36655; | |
162 } else { | |
163 level = | |
164 CFX_Font::s_WeightPow_11[index] * | |
165 (FXSYS_abs((int)(ft_matrix.xx)) + FXSYS_abs((int)(ft_matrix.xy))) / | |
166 36655; | |
167 } | |
168 FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); | |
169 } | |
170 FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(), | |
171 FT_LCD_FILTER_DEFAULT); | |
172 error = FXFT_Render_Glyph(m_Face, anti_alias); | |
173 if (error) | |
174 return nullptr; | |
175 int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(m_Face)); | |
176 int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(m_Face)); | |
177 if (bmwidth > 2048 || bmheight > 2048) | |
178 return nullptr; | |
179 int dib_width = bmwidth; | |
180 CFX_GlyphBitmap* pGlyphBitmap = new CFX_GlyphBitmap; | |
181 pGlyphBitmap->m_Bitmap.Create( | |
182 dib_width, bmheight, | |
183 anti_alias == FXFT_RENDER_MODE_MONO ? FXDIB_1bppMask : FXDIB_8bppMask); | |
184 pGlyphBitmap->m_Left = FXFT_Get_Glyph_BitmapLeft(m_Face); | |
185 pGlyphBitmap->m_Top = FXFT_Get_Glyph_BitmapTop(m_Face); | |
186 int dest_pitch = pGlyphBitmap->m_Bitmap.GetPitch(); | |
187 int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(m_Face)); | |
188 uint8_t* pDestBuf = pGlyphBitmap->m_Bitmap.GetBuffer(); | |
189 uint8_t* pSrcBuf = | |
190 (uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(m_Face)); | |
191 if (anti_alias != FXFT_RENDER_MODE_MONO && | |
192 FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == | |
193 FXFT_PIXEL_MODE_MONO) { | |
194 int bytes = anti_alias == FXFT_RENDER_MODE_LCD ? 3 : 1; | |
195 for (int i = 0; i < bmheight; i++) { | |
196 for (int n = 0; n < bmwidth; n++) { | |
197 uint8_t data = | |
198 (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0; | |
199 for (int b = 0; b < bytes; b++) | |
200 pDestBuf[i * dest_pitch + n * bytes + b] = data; | |
201 } | |
202 } | |
203 } else { | |
204 FXSYS_memset(pDestBuf, 0, dest_pitch * bmheight); | |
205 if (anti_alias == FXFT_RENDER_MODE_MONO && | |
206 FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == | |
207 FXFT_PIXEL_MODE_MONO) { | |
208 int rowbytes = | |
209 FXSYS_abs(src_pitch) > dest_pitch ? dest_pitch : FXSYS_abs(src_pitch); | |
210 for (int row = 0; row < bmheight; row++) { | |
211 FXSYS_memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch, | |
212 rowbytes); | |
213 } | |
214 } else { | |
215 ContrastAdjust(pSrcBuf, pDestBuf, bmwidth, bmheight, src_pitch, | |
216 dest_pitch); | |
217 GammaAdjust(pDestBuf, bmheight, dest_pitch, | |
218 CFX_GEModule::Get()->GetTextGammaTable()); | |
219 } | |
220 } | |
221 return pGlyphBitmap; | |
222 } | |
223 | |
224 const CFX_PathData* CFX_FaceCache::LoadGlyphPath(CFX_Font* pFont, | |
225 uint32_t glyph_index, | |
226 int dest_width) { | |
227 if (!m_Face || glyph_index == (uint32_t)-1) | |
228 return nullptr; | |
229 | |
230 uint32_t key = glyph_index; | |
231 if (pFont->GetSubstFont()) { | |
232 key += (((pFont->GetSubstFont()->m_Weight / 16) << 15) + | |
233 ((pFont->GetSubstFont()->m_ItalicAngle / 2) << 21) + | |
234 ((dest_width / 16) << 25) + (pFont->IsVertical() << 31)); | |
235 } | |
236 auto it = m_PathMap.find(key); | |
237 if (it != m_PathMap.end()) | |
238 return it->second.get(); | |
239 | |
240 CFX_PathData* pGlyphPath = pFont->LoadGlyphPath(glyph_index, dest_width); | |
241 m_PathMap[key] = std::unique_ptr<CFX_PathData>(pGlyphPath); | |
242 return pGlyphPath; | |
243 } | |
244 | |
245 const CFX_GlyphBitmap* CFX_FaceCache::LoadGlyphBitmap(CFX_Font* pFont, | |
246 uint32_t glyph_index, | |
247 FX_BOOL bFontStyle, | |
248 const CFX_Matrix* pMatrix, | |
249 int dest_width, | |
250 int anti_alias, | |
251 int& text_flags) { | |
252 if (glyph_index == (uint32_t)-1) | |
253 return nullptr; | |
254 _CFX_UniqueKeyGen keygen; | |
255 int pMatrixA = static_cast<int>(pMatrix->a * 10000); | |
Lei Zhang
2016/08/19 22:44:58
|nMatrixA| because it's not a pointer?
| |
256 int pMatrixB = static_cast<int>(pMatrix->b * 10000); | |
257 int pMatrixC = static_cast<int>(pMatrix->c * 10000); | |
258 int pMatrixD = static_cast<int>(pMatrix->d * 10000); | |
259 #if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ | |
260 if (pFont->GetSubstFont()) | |
Lei Zhang
2016/08/19 22:44:58
braces braces braces
| |
261 keygen.Generate(9, pMatrixA, pMatrixB, pMatrixC, pMatrixD, dest_width, | |
262 anti_alias, pFont->GetSubstFont()->m_Weight, | |
263 pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); | |
264 else | |
265 keygen.Generate(6, pMatrixA, pMatrixB, pMatrixC, pMatrixD, dest_width, | |
266 anti_alias); | |
267 #else | |
268 if (text_flags & FXTEXT_NO_NATIVETEXT) { | |
269 if (pFont->GetSubstFont()) | |
270 keygen.Generate(9, pMatrixA, pMatrixB, pMatrixC, pMatrixD, dest_width, | |
271 anti_alias, pFont->GetSubstFont()->m_Weight, | |
272 pFont->GetSubstFont()->m_ItalicAngle, | |
273 pFont->IsVertical()); | |
274 else | |
275 keygen.Generate(6, pMatrixA, pMatrixB, pMatrixC, pMatrixD, dest_width, | |
276 anti_alias); | |
277 } else { | |
278 if (pFont->GetSubstFont()) | |
279 keygen.Generate(10, pMatrixA, pMatrixB, pMatrixC, pMatrixD, dest_width, | |
280 anti_alias, pFont->GetSubstFont()->m_Weight, | |
281 pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(), | |
282 3); | |
283 else | |
284 keygen.Generate(7, pMatrixA, pMatrixB, pMatrixC, pMatrixD, dest_width, | |
285 anti_alias, 3); | |
286 } | |
287 #endif | |
288 CFX_ByteString FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); | |
289 #if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_ | |
290 return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, | |
291 bFontStyle, dest_width, anti_alias); | |
292 #else | |
293 if (text_flags & FXTEXT_NO_NATIVETEXT) { | |
294 return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, | |
295 bFontStyle, dest_width, anti_alias); | |
296 } | |
297 CFX_GlyphBitmap* pGlyphBitmap; | |
298 auto it = m_SizeMap.find(FaceGlyphsKey); | |
299 if (it != m_SizeMap.end()) { | |
300 CFX_SizeGlyphCache* pSizeCache = it->second.get(); | |
301 auto it2 = pSizeCache->m_GlyphMap.find(glyph_index); | |
302 if (it2 != pSizeCache->m_GlyphMap.end()) | |
303 return it2->second; | |
304 | |
305 pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, | |
306 dest_width, anti_alias); | |
307 if (pGlyphBitmap) { | |
308 pSizeCache->m_GlyphMap[glyph_index] = pGlyphBitmap; | |
309 return pGlyphBitmap; | |
310 } | |
311 } else { | |
312 pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, | |
313 dest_width, anti_alias); | |
314 if (pGlyphBitmap) { | |
315 CFX_SizeGlyphCache* pSizeCache = new CFX_SizeGlyphCache; | |
316 m_SizeMap[FaceGlyphsKey] = | |
317 std::unique_ptr<CFX_SizeGlyphCache>(pSizeCache); | |
318 pSizeCache->m_GlyphMap[glyph_index] = pGlyphBitmap; | |
319 return pGlyphBitmap; | |
320 } | |
321 } | |
322 if (pFont->GetSubstFont()) | |
Lei Zhang
2016/08/19 22:44:58
braces
| |
323 keygen.Generate(9, pMatrixA, pMatrixB, pMatrixC, pMatrixD, dest_width, | |
324 anti_alias, pFont->GetSubstFont()->m_Weight, | |
325 pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); | |
326 else | |
327 keygen.Generate(6, pMatrixA, pMatrixB, pMatrixC, pMatrixD, dest_width, | |
328 anti_alias); | |
329 CFX_ByteString FaceGlyphsKey2(keygen.m_Key, keygen.m_KeyLen); | |
330 text_flags |= FXTEXT_NO_NATIVETEXT; | |
331 return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey2, glyph_index, | |
332 bFontStyle, dest_width, anti_alias); | |
333 #endif | |
334 } | |
335 | |
336 #ifdef _SKIA_SUPPORT_ | |
337 CFX_TypeFace* CFX_FaceCache::GetDeviceCache(CFX_Font* pFont) { | |
338 if (!m_pTypeface) { | |
339 m_pTypeface = | |
340 SkTypeface::MakeFromStream( | |
341 new SkMemoryStream(pFont->GetFontData(), pFont->GetSize())) | |
342 .release(); | |
343 } | |
344 return m_pTypeface; | |
345 } | |
346 #endif | |
347 | |
348 #if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ | |
349 void CFX_FaceCache::InitPlatform() {} | |
350 #endif | |
351 | |
352 CFX_GlyphBitmap* CFX_FaceCache::LookUpGlyphBitmap( | |
353 CFX_Font* pFont, | |
354 const CFX_Matrix* pMatrix, | |
355 const CFX_ByteString& FaceGlyphsKey, | |
356 uint32_t glyph_index, | |
357 FX_BOOL bFontStyle, | |
358 int dest_width, | |
359 int anti_alias) { | |
360 CFX_SizeGlyphCache* pSizeCache; | |
361 auto it = m_SizeMap.find(FaceGlyphsKey); | |
362 if (it == m_SizeMap.end()) { | |
363 pSizeCache = new CFX_SizeGlyphCache; | |
364 m_SizeMap[FaceGlyphsKey] = std::unique_ptr<CFX_SizeGlyphCache>(pSizeCache); | |
365 } else { | |
366 pSizeCache = it->second.get(); | |
367 } | |
368 auto it2 = pSizeCache->m_GlyphMap.find(glyph_index); | |
369 if (it2 != pSizeCache->m_GlyphMap.end()) | |
370 return it2->second; | |
371 | |
372 CFX_GlyphBitmap* pGlyphBitmap = RenderGlyph(pFont, glyph_index, bFontStyle, | |
373 pMatrix, dest_width, anti_alias); | |
374 if (!pGlyphBitmap) | |
375 return nullptr; | |
376 | |
377 pSizeCache->m_GlyphMap[glyph_index] = pGlyphBitmap; | |
378 return pGlyphBitmap; | |
379 } | |
OLD | NEW |