OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 | 97 |
98 CFX_SizeGlyphCache::CFX_SizeGlyphCache() {} | 98 CFX_SizeGlyphCache::CFX_SizeGlyphCache() {} |
99 | 99 |
100 CFX_SizeGlyphCache::~CFX_SizeGlyphCache() { | 100 CFX_SizeGlyphCache::~CFX_SizeGlyphCache() { |
101 for (const auto& pair : m_GlyphMap) { | 101 for (const auto& pair : m_GlyphMap) { |
102 delete pair.second; | 102 delete pair.second; |
103 } | 103 } |
104 m_GlyphMap.clear(); | 104 m_GlyphMap.clear(); |
105 } | 105 } |
106 | 106 |
107 #define CONTRAST_RAMP_STEP 1 | |
108 void CFX_Font::AdjustMMParams(int glyph_index, int dest_width, int weight) { | |
109 FXFT_MM_Var pMasters = nullptr; | |
110 FXFT_Get_MM_Var(m_Face, &pMasters); | |
111 if (!pMasters) { | |
112 return; | |
113 } | |
114 long coords[2]; | |
115 if (weight == 0) { | |
116 coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536; | |
117 } else { | |
118 coords[0] = weight; | |
119 } | |
120 if (dest_width == 0) { | |
121 coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; | |
122 } else { | |
123 int min_param = FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; | |
124 int max_param = FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; | |
125 coords[1] = min_param; | |
126 (void)FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); | |
127 (void)FXFT_Load_Glyph( | |
128 m_Face, glyph_index, | |
129 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); | |
130 int min_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / | |
131 FXFT_Get_Face_UnitsPerEM(m_Face); | |
132 coords[1] = max_param; | |
133 (void)FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); | |
134 (void)FXFT_Load_Glyph( | |
135 m_Face, glyph_index, | |
136 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); | |
137 int max_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / | |
138 FXFT_Get_Face_UnitsPerEM(m_Face); | |
139 if (max_width == min_width) { | |
140 FXFT_Free(m_Face, pMasters); | |
141 return; | |
142 } | |
143 int param = min_param + | |
144 (max_param - min_param) * (dest_width - min_width) / | |
145 (max_width - min_width); | |
146 coords[1] = param; | |
147 } | |
148 FXFT_Free(m_Face, pMasters); | |
149 FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); | |
150 } | |
151 const char CFX_Font::s_AngleSkew[] = { | |
152 0, 2, 3, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, | |
153 27, 29, 31, 32, 34, 36, 38, 40, 42, 45, 47, 49, 51, 53, 55, | |
154 }; | |
155 const uint8_t CFX_Font::s_WeightPow[] = { | |
156 0, 3, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, | |
157 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 36, 37, | |
158 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, | |
159 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, | |
160 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50, | |
161 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, | |
162 }; | |
163 const uint8_t CFX_Font::s_WeightPow_11[] = { | |
164 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24, | |
165 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41, | |
166 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, | |
167 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52, | |
168 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, | |
169 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, | |
170 }; | |
171 const uint8_t CFX_Font::s_WeightPow_SHIFTJIS[] = { | |
172 0, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 21, | |
173 22, 24, 26, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 48, 48, 48, 48, | |
174 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, | |
175 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, | |
176 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, | |
177 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, | |
178 }; | |
179 typedef struct { | |
180 FX_BOOL m_bCount; | |
181 int m_PointCount; | |
182 FX_PATHPOINT* m_pPoints; | |
183 int m_CurX; | |
184 int m_CurY; | |
185 FX_FLOAT m_CoordUnit; | |
186 } OUTLINE_PARAMS; | |
187 void _Outline_CheckEmptyContour(OUTLINE_PARAMS* param) { | |
188 if (param->m_PointCount >= 2 && | |
189 param->m_pPoints[param->m_PointCount - 2].m_Flag == FXPT_MOVETO && | |
190 param->m_pPoints[param->m_PointCount - 2].m_PointX == | |
191 param->m_pPoints[param->m_PointCount - 1].m_PointX && | |
192 param->m_pPoints[param->m_PointCount - 2].m_PointY == | |
193 param->m_pPoints[param->m_PointCount - 1].m_PointY) { | |
194 param->m_PointCount -= 2; | |
195 } | |
196 if (param->m_PointCount >= 4 && | |
197 param->m_pPoints[param->m_PointCount - 4].m_Flag == FXPT_MOVETO && | |
198 param->m_pPoints[param->m_PointCount - 3].m_Flag == FXPT_BEZIERTO && | |
199 param->m_pPoints[param->m_PointCount - 3].m_PointX == | |
200 param->m_pPoints[param->m_PointCount - 4].m_PointX && | |
201 param->m_pPoints[param->m_PointCount - 3].m_PointY == | |
202 param->m_pPoints[param->m_PointCount - 4].m_PointY && | |
203 param->m_pPoints[param->m_PointCount - 2].m_PointX == | |
204 param->m_pPoints[param->m_PointCount - 4].m_PointX && | |
205 param->m_pPoints[param->m_PointCount - 2].m_PointY == | |
206 param->m_pPoints[param->m_PointCount - 4].m_PointY && | |
207 param->m_pPoints[param->m_PointCount - 1].m_PointX == | |
208 param->m_pPoints[param->m_PointCount - 4].m_PointX && | |
209 param->m_pPoints[param->m_PointCount - 1].m_PointY == | |
210 param->m_pPoints[param->m_PointCount - 4].m_PointY) { | |
211 param->m_PointCount -= 4; | |
212 } | |
213 } | |
214 extern "C" { | |
215 static int _Outline_MoveTo(const FXFT_Vector* to, void* user) { | |
216 OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; | |
217 if (!param->m_bCount) { | |
218 _Outline_CheckEmptyContour(param); | |
219 param->m_pPoints[param->m_PointCount].m_PointX = to->x / param->m_CoordUnit; | |
220 param->m_pPoints[param->m_PointCount].m_PointY = to->y / param->m_CoordUnit; | |
221 param->m_pPoints[param->m_PointCount].m_Flag = FXPT_MOVETO; | |
222 param->m_CurX = to->x; | |
223 param->m_CurY = to->y; | |
224 if (param->m_PointCount) { | |
225 param->m_pPoints[param->m_PointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; | |
226 } | |
227 } | |
228 param->m_PointCount++; | |
229 return 0; | |
230 } | |
231 }; | |
232 extern "C" { | |
233 static int _Outline_LineTo(const FXFT_Vector* to, void* user) { | |
234 OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; | |
235 if (!param->m_bCount) { | |
236 param->m_pPoints[param->m_PointCount].m_PointX = to->x / param->m_CoordUnit; | |
237 param->m_pPoints[param->m_PointCount].m_PointY = to->y / param->m_CoordUnit; | |
238 param->m_pPoints[param->m_PointCount].m_Flag = FXPT_LINETO; | |
239 param->m_CurX = to->x; | |
240 param->m_CurY = to->y; | |
241 } | |
242 param->m_PointCount++; | |
243 return 0; | |
244 } | |
245 }; | |
246 extern "C" { | |
247 static int _Outline_ConicTo(const FXFT_Vector* control, | |
248 const FXFT_Vector* to, | |
249 void* user) { | |
250 OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; | |
251 if (!param->m_bCount) { | |
252 param->m_pPoints[param->m_PointCount].m_PointX = | |
253 (param->m_CurX + (control->x - param->m_CurX) * 2 / 3) / | |
254 param->m_CoordUnit; | |
255 param->m_pPoints[param->m_PointCount].m_PointY = | |
256 (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) / | |
257 param->m_CoordUnit; | |
258 param->m_pPoints[param->m_PointCount].m_Flag = FXPT_BEZIERTO; | |
259 param->m_pPoints[param->m_PointCount + 1].m_PointX = | |
260 (control->x + (to->x - control->x) / 3) / param->m_CoordUnit; | |
261 param->m_pPoints[param->m_PointCount + 1].m_PointY = | |
262 (control->y + (to->y - control->y) / 3) / param->m_CoordUnit; | |
263 param->m_pPoints[param->m_PointCount + 1].m_Flag = FXPT_BEZIERTO; | |
264 param->m_pPoints[param->m_PointCount + 2].m_PointX = | |
265 to->x / param->m_CoordUnit; | |
266 param->m_pPoints[param->m_PointCount + 2].m_PointY = | |
267 to->y / param->m_CoordUnit; | |
268 param->m_pPoints[param->m_PointCount + 2].m_Flag = FXPT_BEZIERTO; | |
269 param->m_CurX = to->x; | |
270 param->m_CurY = to->y; | |
271 } | |
272 param->m_PointCount += 3; | |
273 return 0; | |
274 } | |
275 }; | |
276 extern "C" { | |
277 static int _Outline_CubicTo(const FXFT_Vector* control1, | |
278 const FXFT_Vector* control2, | |
279 const FXFT_Vector* to, | |
280 void* user) { | |
281 OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; | |
282 if (!param->m_bCount) { | |
283 param->m_pPoints[param->m_PointCount].m_PointX = | |
284 control1->x / param->m_CoordUnit; | |
285 param->m_pPoints[param->m_PointCount].m_PointY = | |
286 control1->y / param->m_CoordUnit; | |
287 param->m_pPoints[param->m_PointCount].m_Flag = FXPT_BEZIERTO; | |
288 param->m_pPoints[param->m_PointCount + 1].m_PointX = | |
289 control2->x / param->m_CoordUnit; | |
290 param->m_pPoints[param->m_PointCount + 1].m_PointY = | |
291 control2->y / param->m_CoordUnit; | |
292 param->m_pPoints[param->m_PointCount + 1].m_Flag = FXPT_BEZIERTO; | |
293 param->m_pPoints[param->m_PointCount + 2].m_PointX = | |
294 to->x / param->m_CoordUnit; | |
295 param->m_pPoints[param->m_PointCount + 2].m_PointY = | |
296 to->y / param->m_CoordUnit; | |
297 param->m_pPoints[param->m_PointCount + 2].m_Flag = FXPT_BEZIERTO; | |
298 param->m_CurX = to->x; | |
299 param->m_CurY = to->y; | |
300 } | |
301 param->m_PointCount += 3; | |
302 return 0; | |
303 } | |
304 }; | |
305 CFX_PathData* CFX_Font::LoadGlyphPath(uint32_t glyph_index, int dest_width) { | |
306 if (!m_Face) { | |
307 return nullptr; | |
308 } | |
309 FXFT_Set_Pixel_Sizes(m_Face, 0, 64); | |
310 FXFT_Matrix ft_matrix = {65536, 0, 0, 65536}; | |
311 if (m_pSubstFont) { | |
312 if (m_pSubstFont->m_ItalicAngle) { | |
313 int skew = m_pSubstFont->m_ItalicAngle; | |
314 // |skew| is nonpositive so |-skew| is used as the index. We need to make | |
315 // sure |skew| != INT_MIN since -INT_MIN is undefined. | |
316 if (skew <= 0 && skew != std::numeric_limits<int>::min() && | |
317 static_cast<size_t>(-skew) < kAngleSkewArraySize) { | |
318 skew = -s_AngleSkew[-skew]; | |
319 } else { | |
320 skew = -58; | |
321 } | |
322 if (m_bVertical) | |
323 ft_matrix.yx += ft_matrix.yy * skew / 100; | |
324 else | |
325 ft_matrix.xy -= ft_matrix.xx * skew / 100; | |
326 } | |
327 if (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { | |
328 AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight); | |
329 } | |
330 } | |
331 ScopedFontTransform scoped_transform(m_Face, &ft_matrix); | |
332 int load_flags = FXFT_LOAD_NO_BITMAP; | |
333 if (!(m_Face->face_flags & FT_FACE_FLAG_SFNT) || !FT_IS_TRICKY(m_Face)) { | |
334 load_flags |= FT_LOAD_NO_HINTING; | |
335 } | |
336 if (FXFT_Load_Glyph(m_Face, glyph_index, load_flags)) | |
337 return nullptr; | |
338 if (m_pSubstFont && !(m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && | |
339 m_pSubstFont->m_Weight > 400) { | |
340 uint32_t index = (m_pSubstFont->m_Weight - 400) / 10; | |
341 index = std::min(index, static_cast<uint32_t>(kWeightPowArraySize - 1)); | |
342 int level = 0; | |
343 if (m_pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) | |
344 level = s_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655; | |
345 else | |
346 level = s_WeightPow[index] * 2; | |
347 FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); | |
348 } | |
349 FXFT_Outline_Funcs funcs; | |
350 funcs.move_to = _Outline_MoveTo; | |
351 funcs.line_to = _Outline_LineTo; | |
352 funcs.conic_to = _Outline_ConicTo; | |
353 funcs.cubic_to = _Outline_CubicTo; | |
354 funcs.shift = 0; | |
355 funcs.delta = 0; | |
356 OUTLINE_PARAMS params; | |
357 params.m_bCount = TRUE; | |
358 params.m_PointCount = 0; | |
359 FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); | |
360 if (params.m_PointCount == 0) { | |
361 return nullptr; | |
362 } | |
363 CFX_PathData* pPath = new CFX_PathData; | |
364 pPath->SetPointCount(params.m_PointCount); | |
365 params.m_bCount = FALSE; | |
366 params.m_PointCount = 0; | |
367 params.m_pPoints = pPath->GetPoints(); | |
368 params.m_CurX = params.m_CurY = 0; | |
369 params.m_CoordUnit = 64 * 64.0; | |
370 FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); | |
371 _Outline_CheckEmptyContour(¶ms); | |
372 pPath->TrimPoints(params.m_PointCount); | |
373 if (params.m_PointCount) { | |
374 pPath->GetPoints()[params.m_PointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; | |
375 } | |
376 return pPath; | |
377 } | |
378 void _CFX_UniqueKeyGen::Generate(int count, ...) { | 107 void _CFX_UniqueKeyGen::Generate(int count, ...) { |
379 va_list argList; | 108 va_list argList; |
380 va_start(argList, count); | 109 va_start(argList, count); |
381 for (int i = 0; i < count; i++) { | 110 for (int i = 0; i < count; i++) { |
382 int p = va_arg(argList, int); | 111 int p = va_arg(argList, int); |
383 ((uint32_t*)m_Key)[i] = p; | 112 ((uint32_t*)m_Key)[i] = p; |
384 } | 113 } |
385 va_end(argList); | 114 va_end(argList); |
386 m_KeyLen = count * sizeof(uint32_t); | 115 m_KeyLen = count * sizeof(uint32_t); |
387 } | 116 } |
OLD | NEW |