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