1 // Copyright 2014 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_font.h"
8
9 #include <algorithm>
10 #include <limits>
11 #include <memory>
12 #include <utility>
13 #include <vector>
14
15 #include "core/fpdfapi/font/cpdf_font.h"
16 #include "core/fxcrt/fx_codepage.h"
17 #include "core/fxcrt/fx_stream.h"
18 #include "core/fxge/cfx_facecache.h"
19 #include "core/fxge/cfx_fontcache.h"
20 #include "core/fxge/cfx_fontmgr.h"
21 #include "core/fxge/cfx_gemodule.h"
22 #include "core/fxge/cfx_pathdata.h"
23 #include "core/fxge/cfx_substfont.h"
24 #include "core/fxge/fx_freetype.h"
25 #include "third_party/base/ptr_util.h"
26
27 #define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em)
28
29 namespace {
30
31 constexpr int kThousandthMinInt = std::numeric_limits<int>::min() / 1000;
32 constexpr int kThousandthMaxInt = std::numeric_limits<int>::max() / 1000;
33
34 struct OUTLINE_PARAMS {
35 CFX_PathData* m_pPath;
36 int m_CurX;
37 int m_CurY;
38 float m_CoordUnit;
39 };
40
41 #ifdef PDF_ENABLE_XFA
42
FTStreamRead(FXFT_Stream stream,unsigned long offset,unsigned char * buffer,unsigned long count)43 unsigned long FTStreamRead(FXFT_Stream stream,
44 unsigned long offset,
45 unsigned char* buffer,
46 unsigned long count) {
47 if (count == 0)
48 return 0;
49
50 IFX_SeekableReadStream* pFile =
51 static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer);
52 return pFile && pFile->ReadBlock(buffer, offset, count) ? count : 0;
53 }
54
FTStreamClose(FXFT_Stream stream)55 void FTStreamClose(FXFT_Stream stream) {}
56
LoadFileImp(FXFT_Library library,FXFT_Face * Face,const RetainPtr<IFX_SeekableReadStream> & pFile,int32_t faceIndex,std::unique_ptr<FXFT_StreamRec> * stream)57 bool LoadFileImp(FXFT_Library library,
58 FXFT_Face* Face,
59 const RetainPtr<IFX_SeekableReadStream>& pFile,
60 int32_t faceIndex,
61 std::unique_ptr<FXFT_StreamRec>* stream) {
62 auto stream1 = pdfium::MakeUnique<FXFT_StreamRec>();
63 stream1->base = nullptr;
64 stream1->size = static_cast<unsigned long>(pFile->GetSize());
65 stream1->pos = 0;
66 stream1->descriptor.pointer = static_cast<void*>(pFile.Get());
67 stream1->close = FTStreamClose;
68 stream1->read = FTStreamRead;
69 FXFT_Open_Args args;
70 args.flags = FT_OPEN_STREAM;
71 args.stream = stream1.get();
72 if (FXFT_Open_Face(library, &args, faceIndex, Face))
73 return false;
74 if (stream)
75 *stream = std::move(stream1);
76 return true;
77 }
78 #endif // PDF_ENABLE_XFA
79
FT_LoadFont(const uint8_t * pData,int size)80 FXFT_Face FT_LoadFont(const uint8_t* pData, int size) {
81 return CFX_GEModule::Get()->GetFontMgr()->GetFixedFace(pData, size, 0);
82 }
83
Outline_CheckEmptyContour(OUTLINE_PARAMS * param)84 void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) {
85 std::vector<FX_PATHPOINT>& points = param->m_pPath->GetPoints();
86 size_t size = points.size();
87
88 if (size >= 2 && points[size - 2].IsTypeAndOpen(FXPT_TYPE::MoveTo) &&
89 points[size - 2].m_Point == points[size - 1].m_Point) {
90 size -= 2;
91 }
92 if (size >= 4 && points[size - 4].IsTypeAndOpen(FXPT_TYPE::MoveTo) &&
93 points[size - 3].IsTypeAndOpen(FXPT_TYPE::BezierTo) &&
94 points[size - 3].m_Point == points[size - 4].m_Point &&
95 points[size - 2].m_Point == points[size - 4].m_Point &&
96 points[size - 1].m_Point == points[size - 4].m_Point) {
97 size -= 4;
98 }
99 points.resize(size);
100 }
101
Outline_MoveTo(const FXFT_Vector * to,void * user)102 int Outline_MoveTo(const FXFT_Vector* to, void* user) {
103 OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
104
105 Outline_CheckEmptyContour(param);
106
107 param->m_pPath->ClosePath();
108 param->m_pPath->AppendPoint(
109 CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
110 FXPT_TYPE::MoveTo, false);
111
112 param->m_CurX = to->x;
113 param->m_CurY = to->y;
114 return 0;
115 }
116
Outline_LineTo(const FXFT_Vector * to,void * user)117 int Outline_LineTo(const FXFT_Vector* to, void* user) {
118 OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
119
120 param->m_pPath->AppendPoint(
121 CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
122 FXPT_TYPE::LineTo, false);
123
124 param->m_CurX = to->x;
125 param->m_CurY = to->y;
126 return 0;
127 }
128
Outline_ConicTo(const FXFT_Vector * control,const FXFT_Vector * to,void * user)129 int Outline_ConicTo(const FXFT_Vector* control,
130 const FXFT_Vector* to,
131 void* user) {
132 OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
133
134 param->m_pPath->AppendPoint(
135 CFX_PointF((param->m_CurX + (control->x - param->m_CurX) * 2 / 3) /
136 param->m_CoordUnit,
137 (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) /
138 param->m_CoordUnit),
139 FXPT_TYPE::BezierTo, false);
140
141 param->m_pPath->AppendPoint(
142 CFX_PointF((control->x + (to->x - control->x) / 3) / param->m_CoordUnit,
143 (control->y + (to->y - control->y) / 3) / param->m_CoordUnit),
144 FXPT_TYPE::BezierTo, false);
145
146 param->m_pPath->AppendPoint(
147 CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
148 FXPT_TYPE::BezierTo, false);
149
150 param->m_CurX = to->x;
151 param->m_CurY = to->y;
152 return 0;
153 }
154
Outline_CubicTo(const FXFT_Vector * control1,const FXFT_Vector * control2,const FXFT_Vector * to,void * user)155 int Outline_CubicTo(const FXFT_Vector* control1,
156 const FXFT_Vector* control2,
157 const FXFT_Vector* to,
158 void* user) {
159 OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
160
161 param->m_pPath->AppendPoint(CFX_PointF(control1->x / param->m_CoordUnit,
162 control1->y / param->m_CoordUnit),
163 FXPT_TYPE::BezierTo, false);
164
165 param->m_pPath->AppendPoint(CFX_PointF(control2->x / param->m_CoordUnit,
166 control2->y / param->m_CoordUnit),
167 FXPT_TYPE::BezierTo, false);
168
169 param->m_pPath->AppendPoint(
170 CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
171 FXPT_TYPE::BezierTo, false);
172
173 param->m_CurX = to->x;
174 param->m_CurY = to->y;
175 return 0;
176 }
177
178 } // namespace
179
180 const char CFX_Font::s_AngleSkew[] = {
181 0, 2, 3, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25,
182 27, 29, 31, 32, 34, 36, 38, 40, 42, 45, 47, 49, 51, 53, 55,
183 };
184
185 const uint8_t CFX_Font::s_WeightPow[] = {
186 0, 3, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22,
187 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 36, 37,
188 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42,
189 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47,
190 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50,
191 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53,
192 };
193
194 const uint8_t CFX_Font::s_WeightPow_11[] = {
195 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24,
196 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41,
197 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46,
198 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52,
199 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55,
200 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58,
201 };
202
203 const uint8_t CFX_Font::s_WeightPow_SHIFTJIS[] = {
204 0, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 21,
205 22, 24, 26, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 48, 48, 48, 48,
206 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53,
207 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56,
208 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58,
209 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60,
210 };
211
CFX_Font()212 CFX_Font::CFX_Font()
213 :
214 m_Face(nullptr),
215 m_FaceCache(nullptr),
216 m_pFontData(nullptr),
217 m_pGsubData(nullptr),
218 m_dwSize(0),
219 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
220 m_pPlatformFont(nullptr),
221 #endif
222 m_bEmbedded(false),
223 m_bVertical(false) {
224 }
225
226 #ifdef PDF_ENABLE_XFA
SetFace(FXFT_Face face)227 void CFX_Font::SetFace(FXFT_Face face) {
228 ClearFaceCache();
229 m_Face = face;
230 }
231
SetSubstFont(std::unique_ptr<CFX_SubstFont> subst)232 void CFX_Font::SetSubstFont(std::unique_ptr<CFX_SubstFont> subst) {
233 m_pSubstFont = std::move(subst);
234 }
235 #endif // PDF_ENABLE_XFA
236
~CFX_Font()237 CFX_Font::~CFX_Font() {
238 if (m_Face) {
239 #ifndef PDF_ENABLE_XFA
240 if (FXFT_Get_Face_External_Stream(m_Face)) {
241 FXFT_Clear_Face_External_Stream(m_Face);
242 }
243 #endif // PDF_ENABLE_XFA
244 DeleteFace();
245 }
246 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
247 ReleasePlatformResource();
248 #endif
249 }
250
DeleteFace()251 void CFX_Font::DeleteFace() {
252 ClearFaceCache();
253 if (m_bEmbedded)
254 FXFT_Done_Face(m_Face);
255 else
256 CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face);
257 m_Face = nullptr;
258 }
259
LoadSubst(const ByteString & face_name,bool bTrueType,uint32_t flags,int weight,int italic_angle,int CharsetCP,bool bVertical)260 void CFX_Font::LoadSubst(const ByteString& face_name,
261 bool bTrueType,
262 uint32_t flags,
263 int weight,
264 int italic_angle,
265 int CharsetCP,
266 bool bVertical) {
267 m_bEmbedded = false;
268 m_bVertical = bVertical;
269 m_pSubstFont = pdfium::MakeUnique<CFX_SubstFont>();
270 m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont(
271 face_name, bTrueType, flags, weight, italic_angle, CharsetCP,
272 m_pSubstFont.get());
273 if (m_Face) {
274 m_pFontData = FXFT_Get_Face_Stream_Base(m_Face);
275 m_dwSize = FXFT_Get_Face_Stream_Size(m_Face);
276 }
277 }
278
279 #ifdef PDF_ENABLE_XFA
LoadFile(const RetainPtr<IFX_SeekableReadStream> & pFile,int nFaceIndex)280 bool CFX_Font::LoadFile(const RetainPtr<IFX_SeekableReadStream>& pFile,
281 int nFaceIndex) {
282 m_bEmbedded = false;
283
284 CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr();
285 pFontMgr->InitFTLibrary();
286
287 FXFT_Library library = pFontMgr->GetFTLibrary();
288 std::unique_ptr<FXFT_StreamRec> stream;
289 if (!LoadFileImp(library, &m_Face, pFile, nFaceIndex, &stream))
290 return false;
291
292 m_pOwnedStream = std::move(stream);
293 FXFT_Set_Pixel_Sizes(m_Face, 0, 64);
294 return true;
295 }
296 #endif // PDF_ENABLE_XFA
297
GetGlyphWidth(uint32_t glyph_index)298 int CFX_Font::GetGlyphWidth(uint32_t glyph_index) {
299 if (!m_Face)
300 return 0;
301 if (m_pSubstFont && m_pSubstFont->m_bFlagMM)
302 AdjustMMParams(glyph_index, 0, 0);
303 int err = FXFT_Load_Glyph(
304 m_Face, glyph_index,
305 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
306 if (err)
307 return 0;
308
309 int horiAdvance = FXFT_Get_Glyph_HoriAdvance(m_Face);
310 if (horiAdvance < kThousandthMinInt || horiAdvance > kThousandthMaxInt)
311 return 0;
312
313 return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), horiAdvance);
314 }
315
LoadEmbedded(const uint8_t * data,uint32_t size)316 bool CFX_Font::LoadEmbedded(const uint8_t* data, uint32_t size) {
317 std::vector<uint8_t> temp(data, data + size);
318 m_pFontDataAllocation.swap(temp);
319 m_Face = FT_LoadFont(m_pFontDataAllocation.data(), size);
320 m_pFontData = m_pFontDataAllocation.data();
321 m_bEmbedded = true;
322 m_dwSize = size;
323 return !!m_Face;
324 }
325
IsTTFont() const326 bool CFX_Font::IsTTFont() const {
327 return m_Face && FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT;
328 }
329
GetAscent() const330 int CFX_Font::GetAscent() const {
331 if (!m_Face)
332 return 0;
333
334 int ascender = FXFT_Get_Face_Ascender(m_Face);
335 if (ascender < kThousandthMinInt || ascender > kThousandthMaxInt)
336 return 0;
337
338 return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), ascender);
339 }
340
GetDescent() const341 int CFX_Font::GetDescent() const {
342 if (!m_Face)
343 return 0;
344
345 int descender = FXFT_Get_Face_Descender(m_Face);
346 if (descender < kThousandthMinInt || descender > kThousandthMaxInt)
347 return 0;
348
349 return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), descender);
350 }
351
GetGlyphBBox(uint32_t glyph_index,FX_RECT & bbox)352 bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox) {
353 if (!m_Face)
354 return false;
355
356 if (FXFT_Is_Face_Tricky(m_Face)) {
357 int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72);
358 if (error)
359 return false;
360
361 error = FXFT_Load_Glyph(m_Face, glyph_index,
362 FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
363 if (error)
364 return false;
365
366 FXFT_BBox cbox;
367 FT_Glyph glyph;
368 error = FXFT_Get_Glyph(m_Face->glyph, &glyph);
369 if (error)
370 return false;
371
372 FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox);
373 int pixel_size_x = m_Face->size->metrics.x_ppem,
374 pixel_size_y = m_Face->size->metrics.y_ppem;
375 if (pixel_size_x == 0 || pixel_size_y == 0) {
376 bbox.left = cbox.xMin;
377 bbox.right = cbox.xMax;
378 bbox.top = cbox.yMax;
379 bbox.bottom = cbox.yMin;
380 } else {
381 bbox.left = cbox.xMin * 1000 / pixel_size_x;
382 bbox.right = cbox.xMax * 1000 / pixel_size_x;
383 bbox.top = cbox.yMax * 1000 / pixel_size_y;
384 bbox.bottom = cbox.yMin * 1000 / pixel_size_y;
385 }
386 bbox.top = std::min(bbox.top,
387 static_cast<int32_t>(FXFT_Get_Face_Ascender(m_Face)));
388 bbox.bottom = std::max(
389 bbox.bottom, static_cast<int32_t>(FXFT_Get_Face_Descender(m_Face)));
390 FT_Done_Glyph(glyph);
391 return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0;
392 }
393 if (FXFT_Load_Glyph(
394 m_Face, glyph_index,
395 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
396 return false;
397 }
398 int em = FXFT_Get_Face_UnitsPerEM(m_Face);
399 if (em == 0) {
400 bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face);
401 bbox.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face);
402 bbox.top = bbox.bottom - FXFT_Get_Glyph_Height(m_Face);
403 bbox.right = bbox.left + FXFT_Get_Glyph_Width(m_Face);
404 } else {
405 bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face) * 1000 / em;
406 bbox.top =
407 (FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face)) *
408 1000 / em;
409 bbox.right =
410 (FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face)) *
411 1000 / em;
412 bbox.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face)) * 1000 / em;
413 }
414 return true;
415 }
416
IsItalic() const417 bool CFX_Font::IsItalic() const {
418 if (!m_Face)
419 return false;
420 if (FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC)
421 return true;
422
423 ByteString str(FXFT_Get_Face_Style_Name(m_Face));
424 str.MakeLower();
425 return str.Contains("italic");
426 }
427
IsBold() const428 bool CFX_Font::IsBold() const {
429 return m_Face && FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD;
430 }
431
IsFixedWidth() const432 bool CFX_Font::IsFixedWidth() const {
433 return m_Face && FXFT_Is_Face_fixedwidth(m_Face) != 0;
434 }
435
GetPsName() const436 ByteString CFX_Font::GetPsName() const {
437 if (!m_Face)
438 return ByteString();
439
440 ByteString psName = FXFT_Get_Postscript_Name(m_Face);
441 if (psName.IsEmpty())
442 psName = "Untitled";
443 return psName;
444 }
445
GetFamilyName() const446 ByteString CFX_Font::GetFamilyName() const {
447 if (!m_Face && !m_pSubstFont)
448 return ByteString();
449 if (m_Face)
450 return ByteString(FXFT_Get_Face_Family_Name(m_Face));
451
452 return m_pSubstFont->m_Family;
453 }
454
GetFaceName() const455 ByteString CFX_Font::GetFaceName() const {
456 if (!m_Face && !m_pSubstFont)
457 return ByteString();
458 if (m_Face) {
459 ByteString style = ByteString(FXFT_Get_Face_Style_Name(m_Face));
460 ByteString facename = GetFamilyName();
461 if (facename.IsEmpty())
462 facename = "Untitled";
463 if (!style.IsEmpty() && style != "Regular")
464 facename += " " + style;
465 return facename;
466 }
467 return m_pSubstFont->m_Family;
468 }
469
GetBBox(FX_RECT & bbox)470 bool CFX_Font::GetBBox(FX_RECT& bbox) {
471 if (!m_Face)
472 return false;
473
474 int em = FXFT_Get_Face_UnitsPerEM(m_Face);
475 if (em == 0) {
476 bbox.left = FXFT_Get_Face_xMin(m_Face);
477 bbox.bottom = FXFT_Get_Face_yMax(m_Face);
478 bbox.top = FXFT_Get_Face_yMin(m_Face);
479 bbox.right = FXFT_Get_Face_xMax(m_Face);
480 } else {
481 bbox.left = FXFT_Get_Face_xMin(m_Face) * 1000 / em;
482 bbox.top = FXFT_Get_Face_yMin(m_Face) * 1000 / em;
483 bbox.right = FXFT_Get_Face_xMax(m_Face) * 1000 / em;
484 bbox.bottom = FXFT_Get_Face_yMax(m_Face) * 1000 / em;
485 }
486 return true;
487 }
488
GetFaceCache() const489 CFX_FaceCache* CFX_Font::GetFaceCache() const {
490 if (!m_FaceCache)
491 m_FaceCache = CFX_GEModule::Get()->GetFontCache()->GetCachedFace(this);
492 return m_FaceCache.Get();
493 }
494
ClearFaceCache()495 void CFX_Font::ClearFaceCache() {
496 if (!m_FaceCache)
497 return;
498
499 m_FaceCache = nullptr;
500 CFX_GEModule::Get()->GetFontCache()->ReleaseCachedFace(this);
501 }
502
AdjustMMParams(int glyph_index,int dest_width,int weight) const503 void CFX_Font::AdjustMMParams(int glyph_index,
504 int dest_width,
505 int weight) const {
506 FXFT_MM_Var pMasters = nullptr;
507 FXFT_Get_MM_Var(m_Face, &pMasters);
508 if (!pMasters)
509 return;
510
511 long coords[2];
512 if (weight == 0)
513 coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536;
514 else
515 coords[0] = weight;
516
517 if (dest_width == 0) {
518 coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
519 } else {
520 int min_param = FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
521 int max_param = FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
522 coords[1] = min_param;
523 FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords);
524 FXFT_Load_Glyph(m_Face, glyph_index,
525 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
526 int min_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 /
527 FXFT_Get_Face_UnitsPerEM(m_Face);
528 coords[1] = max_param;
529 FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords);
530 FXFT_Load_Glyph(m_Face, glyph_index,
531 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
532 int max_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 /
533 FXFT_Get_Face_UnitsPerEM(m_Face);
534 if (max_width == min_width) {
535 FXFT_Free(m_Face, pMasters);
536 return;
537 }
538 int param = min_param + (max_param - min_param) * (dest_width - min_width) /
539 (max_width - min_width);
540 coords[1] = param;
541 }
542 FXFT_Free(m_Face, pMasters);
543 FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords);
544 }
545
LoadGlyphPathImpl(uint32_t glyph_index,int dest_width) const546 CFX_PathData* CFX_Font::LoadGlyphPathImpl(uint32_t glyph_index,
547 int dest_width) const {
548 if (!m_Face)
549 return nullptr;
550 FXFT_Set_Pixel_Sizes(m_Face, 0, 64);
551 FXFT_Matrix ft_matrix = {65536, 0, 0, 65536};
552 if (m_pSubstFont) {
553 if (m_pSubstFont->m_ItalicAngle) {
554 int skew = m_pSubstFont->m_ItalicAngle;
555 // |skew| is nonpositive so |-skew| is used as the index. We need to make
556 // sure |skew| != INT_MIN since -INT_MIN is undefined.
557 if (skew <= 0 && skew != std::numeric_limits<int>::min() &&
558 static_cast<size_t>(-skew) < kAngleSkewArraySize) {
559 skew = -s_AngleSkew[-skew];
560 } else {
561 skew = -58;
562 }
563 if (m_bVertical)
564 ft_matrix.yx += ft_matrix.yy * skew / 100;
565 else
566 ft_matrix.xy -= ft_matrix.xx * skew / 100;
567 }
568 if (m_pSubstFont->m_bFlagMM)
569 AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight);
570 }
571 ScopedFontTransform scoped_transform(m_Face, &ft_matrix);
572 int load_flags = FXFT_LOAD_NO_BITMAP;
573 if (!(m_Face->face_flags & FT_FACE_FLAG_SFNT) || !FT_IS_TRICKY(m_Face))
574 load_flags |= FT_LOAD_NO_HINTING;
575 if (FXFT_Load_Glyph(m_Face, glyph_index, load_flags))
576 return nullptr;
577 if (m_pSubstFont && !m_pSubstFont->m_bFlagMM &&
578 m_pSubstFont->m_Weight > 400) {
579 uint32_t index = (m_pSubstFont->m_Weight - 400) / 10;
580 index = std::min(index, static_cast<uint32_t>(kWeightPowArraySize - 1));
581 int level = 0;
582 if (m_pSubstFont->m_Charset == FX_CHARSET_ShiftJIS)
583 level = s_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655;
584 else
585 level = s_WeightPow[index] * 2;
586 FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level);
587 }
588
589 FXFT_Outline_Funcs funcs;
590 funcs.move_to = Outline_MoveTo;
591 funcs.line_to = Outline_LineTo;
592 funcs.conic_to = Outline_ConicTo;
593 funcs.cubic_to = Outline_CubicTo;
594 funcs.shift = 0;
595 funcs.delta = 0;
596
597 OUTLINE_PARAMS params;
598 auto pPath = pdfium::MakeUnique<CFX_PathData>();
599 params.m_pPath = pPath.get();
600 params.m_CurX = params.m_CurY = 0;
601 params.m_CoordUnit = 64 * 64.0;
602
603 FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms);
604 if (pPath->GetPoints().empty())
605 return nullptr;
606
607 Outline_CheckEmptyContour(¶ms);
608 pPath->ClosePath();
609
610 return pPath.release();
611 }
612
LoadGlyphBitmap(uint32_t glyph_index,bool bFontStyle,const CFX_Matrix * pMatrix,int dest_width,int anti_alias,int & text_flags) const613 const CFX_GlyphBitmap* CFX_Font::LoadGlyphBitmap(uint32_t glyph_index,
614 bool bFontStyle,
615 const CFX_Matrix* pMatrix,
616 int dest_width,
617 int anti_alias,
618 int& text_flags) const {
619 return GetFaceCache()->LoadGlyphBitmap(this, glyph_index, bFontStyle, pMatrix,
620 dest_width, anti_alias, text_flags);
621 }
622
LoadGlyphPath(uint32_t glyph_index,int dest_width) const623 const CFX_PathData* CFX_Font::LoadGlyphPath(uint32_t glyph_index,
624 int dest_width) const {
625 return GetFaceCache()->LoadGlyphPath(this, glyph_index, dest_width);
626 }
627
628 #if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_
GetDeviceCache() const629 CFX_TypeFace* CFX_Font::GetDeviceCache() const {
630 return GetFaceCache()->GetDeviceCache(this);
631 }
632 #endif
633