• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &params);
604   if (pPath->GetPoints().empty())
605     return nullptr;
606 
607   Outline_CheckEmptyContour(&params);
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