• 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 "build/build_config.h"
16 #include "core/fxcrt/fx_codepage.h"
17 #include "core/fxcrt/fx_stream.h"
18 #include "core/fxge/cfx_fontcache.h"
19 #include "core/fxge/cfx_fontmgr.h"
20 #include "core/fxge/cfx_gemodule.h"
21 #include "core/fxge/cfx_glyphcache.h"
22 #include "core/fxge/cfx_pathdata.h"
23 #include "core/fxge/cfx_substfont.h"
24 #include "core/fxge/fx_font.h"
25 #include "core/fxge/scoped_font_transform.h"
26 #include "third_party/base/ptr_util.h"
27 
28 #define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em)
29 
30 namespace {
31 
32 constexpr int kThousandthMinInt = std::numeric_limits<int>::min() / 1000;
33 constexpr int kThousandthMaxInt = std::numeric_limits<int>::max() / 1000;
34 
35 struct OUTLINE_PARAMS {
36   CFX_PathData* m_pPath;
37   int m_CurX;
38   int m_CurY;
39   float m_CoordUnit;
40 };
41 
42 #ifdef PDF_ENABLE_XFA
43 
FTStreamRead(FXFT_StreamRec * stream,unsigned long offset,unsigned char * buffer,unsigned long count)44 unsigned long FTStreamRead(FXFT_StreamRec* stream,
45                            unsigned long offset,
46                            unsigned char* buffer,
47                            unsigned long count) {
48   if (count == 0)
49     return 0;
50 
51   IFX_SeekableReadStream* pFile =
52       static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer);
53   return pFile && pFile->ReadBlockAtOffset(buffer, offset, count) ? count : 0;
54 }
55 
FTStreamClose(FXFT_StreamRec * stream)56 void FTStreamClose(FXFT_StreamRec* stream) {}
57 
LoadFileImp(FXFT_LibraryRec * library,const RetainPtr<IFX_SeekableReadStream> & pFile,int32_t faceIndex,std::unique_ptr<FXFT_StreamRec> * stream)58 RetainPtr<CFX_Face> LoadFileImp(FXFT_LibraryRec* library,
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 
70   FT_Open_Args args;
71   args.flags = FT_OPEN_STREAM;
72   args.stream = stream1.get();
73 
74   RetainPtr<CFX_Face> face = CFX_Face::Open(library, &args, faceIndex);
75   if (!face)
76     return nullptr;
77 
78   *stream = std::move(stream1);
79   return face;
80 }
81 #endif  // PDF_ENABLE_XFA
82 
Outline_CheckEmptyContour(OUTLINE_PARAMS * param)83 void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) {
84   std::vector<FX_PATHPOINT>& points = param->m_pPath->GetPoints();
85   size_t size = points.size();
86 
87   if (size >= 2 && points[size - 2].IsTypeAndOpen(FXPT_TYPE::MoveTo) &&
88       points[size - 2].m_Point == points[size - 1].m_Point) {
89     size -= 2;
90   }
91   if (size >= 4 && points[size - 4].IsTypeAndOpen(FXPT_TYPE::MoveTo) &&
92       points[size - 3].IsTypeAndOpen(FXPT_TYPE::BezierTo) &&
93       points[size - 3].m_Point == points[size - 4].m_Point &&
94       points[size - 2].m_Point == points[size - 4].m_Point &&
95       points[size - 1].m_Point == points[size - 4].m_Point) {
96     size -= 4;
97   }
98   points.resize(size);
99 }
100 
Outline_MoveTo(const FT_Vector * to,void * user)101 int Outline_MoveTo(const FT_Vector* to, void* user) {
102   OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
103 
104   Outline_CheckEmptyContour(param);
105 
106   param->m_pPath->ClosePath();
107   param->m_pPath->AppendPoint(
108       CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
109       FXPT_TYPE::MoveTo, false);
110 
111   param->m_CurX = to->x;
112   param->m_CurY = to->y;
113   return 0;
114 }
115 
Outline_LineTo(const FT_Vector * to,void * user)116 int Outline_LineTo(const FT_Vector* to, void* user) {
117   OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
118 
119   param->m_pPath->AppendPoint(
120       CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
121       FXPT_TYPE::LineTo, false);
122 
123   param->m_CurX = to->x;
124   param->m_CurY = to->y;
125   return 0;
126 }
127 
Outline_ConicTo(const FT_Vector * control,const FT_Vector * to,void * user)128 int Outline_ConicTo(const FT_Vector* control, const FT_Vector* to, void* user) {
129   OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
130 
131   param->m_pPath->AppendPoint(
132       CFX_PointF((param->m_CurX + (control->x - param->m_CurX) * 2 / 3) /
133                      param->m_CoordUnit,
134                  (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) /
135                      param->m_CoordUnit),
136       FXPT_TYPE::BezierTo, false);
137 
138   param->m_pPath->AppendPoint(
139       CFX_PointF((control->x + (to->x - control->x) / 3) / param->m_CoordUnit,
140                  (control->y + (to->y - control->y) / 3) / param->m_CoordUnit),
141       FXPT_TYPE::BezierTo, false);
142 
143   param->m_pPath->AppendPoint(
144       CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
145       FXPT_TYPE::BezierTo, false);
146 
147   param->m_CurX = to->x;
148   param->m_CurY = to->y;
149   return 0;
150 }
151 
Outline_CubicTo(const FT_Vector * control1,const FT_Vector * control2,const FT_Vector * to,void * user)152 int Outline_CubicTo(const FT_Vector* control1,
153                     const FT_Vector* control2,
154                     const FT_Vector* to,
155                     void* user) {
156   OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
157 
158   param->m_pPath->AppendPoint(CFX_PointF(control1->x / param->m_CoordUnit,
159                                          control1->y / param->m_CoordUnit),
160                               FXPT_TYPE::BezierTo, false);
161 
162   param->m_pPath->AppendPoint(CFX_PointF(control2->x / param->m_CoordUnit,
163                                          control2->y / param->m_CoordUnit),
164                               FXPT_TYPE::BezierTo, false);
165 
166   param->m_pPath->AppendPoint(
167       CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
168       FXPT_TYPE::BezierTo, false);
169 
170   param->m_CurX = to->x;
171   param->m_CurY = to->y;
172   return 0;
173 }
174 
ShouldAppendStyle(const ByteString & style)175 bool ShouldAppendStyle(const ByteString& style) {
176   return !style.IsEmpty() && style != "Regular";
177 }
178 
179 }  // namespace
180 
181 const char CFX_Font::s_AngleSkew[] = {
182     0,  2,  3,  5,  7,  9,  11, 12, 14, 16, 18, 19, 21, 23, 25,
183     27, 29, 31, 32, 34, 36, 38, 40, 42, 45, 47, 49, 51, 53, 55,
184 };
185 
186 const uint8_t CFX_Font::s_WeightPow[] = {
187     0,  3,  6,  7,  8,  9,  11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22,
188     23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 36, 37,
189     37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42,
190     42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47,
191     47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50,
192     51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53,
193 };
194 
195 const uint8_t CFX_Font::s_WeightPow_11[] = {
196     0,  4,  7,  8,  9,  10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24,
197     25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41,
198     41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46,
199     46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52,
200     52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55,
201     56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58,
202 };
203 
204 const uint8_t CFX_Font::s_WeightPow_SHIFTJIS[] = {
205     0,  0,  1,  2,  3,  4,  5,  7,  8,  10, 11, 13, 14, 16, 17, 19, 21,
206     22, 24, 26, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 48, 48, 48, 48,
207     49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53,
208     53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56,
209     56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58,
210     59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60,
211 };
212 
213 const CFX_Font::CharsetFontMap CFX_Font::defaultTTFMap[] = {
214     {FX_CHARSET_ANSI, kDefaultAnsiFontName},
215     {FX_CHARSET_ChineseSimplified, "SimSun"},
216     {FX_CHARSET_ChineseTraditional, "MingLiU"},
217     {FX_CHARSET_ShiftJIS, "MS Gothic"},
218     {FX_CHARSET_Hangul, "Batang"},
219     {FX_CHARSET_MSWin_Cyrillic, "Arial"},
220 #if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ || defined(OS_MACOSX)
221     {FX_CHARSET_MSWin_EasternEuropean, "Arial"},
222 #else
223     {FX_CHARSET_MSWin_EasternEuropean, "Tahoma"},
224 #endif
225     {FX_CHARSET_MSWin_Arabic, "Arial"},
226     {-1, nullptr}};
227 
228 // static
229 const char CFX_Font::kUntitledFontName[] = "Untitled";
230 
231 // static
232 const char CFX_Font::kDefaultAnsiFontName[] = "Helvetica";
233 
234 // static
235 const char CFX_Font::kUniversalDefaultFontName[] = "Arial Unicode MS";
236 
237 // static
GetDefaultFontNameByCharset(uint8_t nCharset)238 ByteString CFX_Font::GetDefaultFontNameByCharset(uint8_t nCharset) {
239   int i = 0;
240   while (defaultTTFMap[i].charset != -1) {
241     if (nCharset == static_cast<uint8_t>(defaultTTFMap[i].charset))
242       return defaultTTFMap[i].fontname;
243     ++i;
244   }
245   return kUniversalDefaultFontName;
246 }
247 
248 // static
GetCharSetFromUnicode(uint16_t word)249 uint8_t CFX_Font::GetCharSetFromUnicode(uint16_t word) {
250   // to avoid CJK Font to show ASCII
251   if (word < 0x7F)
252     return FX_CHARSET_ANSI;
253 
254   // find new charset
255   if ((word >= 0x4E00 && word <= 0x9FA5) ||
256       (word >= 0xE7C7 && word <= 0xE7F3) ||
257       (word >= 0x3000 && word <= 0x303F) ||
258       (word >= 0x2000 && word <= 0x206F)) {
259     return FX_CHARSET_ChineseSimplified;
260   }
261 
262   if (((word >= 0x3040) && (word <= 0x309F)) ||
263       ((word >= 0x30A0) && (word <= 0x30FF)) ||
264       ((word >= 0x31F0) && (word <= 0x31FF)) ||
265       ((word >= 0xFF00) && (word <= 0xFFEF))) {
266     return FX_CHARSET_ShiftJIS;
267   }
268 
269   if (((word >= 0xAC00) && (word <= 0xD7AF)) ||
270       ((word >= 0x1100) && (word <= 0x11FF)) ||
271       ((word >= 0x3130) && (word <= 0x318F))) {
272     return FX_CHARSET_Hangul;
273   }
274 
275   if (word >= 0x0E00 && word <= 0x0E7F)
276     return FX_CHARSET_Thai;
277 
278   if ((word >= 0x0370 && word <= 0x03FF) || (word >= 0x1F00 && word <= 0x1FFF))
279     return FX_CHARSET_MSWin_Greek;
280 
281   if ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
282     return FX_CHARSET_MSWin_Arabic;
283 
284   if (word >= 0x0590 && word <= 0x05FF)
285     return FX_CHARSET_MSWin_Hebrew;
286 
287   if (word >= 0x0400 && word <= 0x04FF)
288     return FX_CHARSET_MSWin_Cyrillic;
289 
290   if (word >= 0x0100 && word <= 0x024F)
291     return FX_CHARSET_MSWin_EasternEuropean;
292 
293   if (word >= 0x1E00 && word <= 0x1EFF)
294     return FX_CHARSET_MSWin_Vietnamese;
295 
296   return FX_CHARSET_ANSI;
297 }
298 
299 CFX_Font::CFX_Font() = default;
300 
GetSubstFontItalicAngle() const301 int CFX_Font::GetSubstFontItalicAngle() const {
302   CFX_SubstFont* subst_font = GetSubstFont();
303   return subst_font ? subst_font->m_ItalicAngle : 0;
304 }
305 
306 #ifdef PDF_ENABLE_XFA
LoadFile(const RetainPtr<IFX_SeekableReadStream> & pFile,int nFaceIndex)307 bool CFX_Font::LoadFile(const RetainPtr<IFX_SeekableReadStream>& pFile,
308                         int nFaceIndex) {
309   m_bEmbedded = false;
310 
311   CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr();
312   std::unique_ptr<FXFT_StreamRec> stream;
313   m_Face = LoadFileImp(pFontMgr->GetFTLibrary(), pFile, nFaceIndex, &stream);
314   if (!m_Face)
315     return false;
316 
317   m_pOwnedStream = std::move(stream);
318   FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64);
319   return true;
320 }
321 
322 #if !defined(OS_WIN)
SetFace(RetainPtr<CFX_Face> face)323 void CFX_Font::SetFace(RetainPtr<CFX_Face> face) {
324   ClearGlyphCache();
325   m_Face = face;
326 }
327 
SetSubstFont(std::unique_ptr<CFX_SubstFont> subst)328 void CFX_Font::SetSubstFont(std::unique_ptr<CFX_SubstFont> subst) {
329   m_pSubstFont = std::move(subst);
330 }
331 #endif  // !defined(OS_WIN)
332 #endif  // PDF_ENABLE_XFA
333 
~CFX_Font()334 CFX_Font::~CFX_Font() {
335   m_FontData = {};  // m_FontData can't outive m_Face.
336   m_Face.Reset();
337 
338 #if defined(OS_MACOSX)
339   ReleasePlatformResource();
340 #endif
341 }
342 
LoadSubst(const ByteString & face_name,bool bTrueType,uint32_t flags,int weight,int italic_angle,int CharsetCP,bool bVertical)343 void CFX_Font::LoadSubst(const ByteString& face_name,
344                          bool bTrueType,
345                          uint32_t flags,
346                          int weight,
347                          int italic_angle,
348                          int CharsetCP,
349                          bool bVertical) {
350   m_bEmbedded = false;
351   m_bVertical = bVertical;
352   m_pSubstFont = pdfium::MakeUnique<CFX_SubstFont>();
353   m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont(
354       face_name, bTrueType, flags, weight, italic_angle, CharsetCP,
355       m_pSubstFont.get());
356   if (m_Face) {
357     m_FontData = {FXFT_Get_Face_Stream_Base(m_Face->GetRec()),
358                   FXFT_Get_Face_Stream_Size(m_Face->GetRec())};
359   }
360 }
361 
GetGlyphWidth(uint32_t glyph_index)362 uint32_t CFX_Font::GetGlyphWidth(uint32_t glyph_index) {
363   if (!m_Face)
364     return 0;
365   if (m_pSubstFont && m_pSubstFont->m_bFlagMM)
366     AdjustMMParams(glyph_index, 0, 0);
367   int err =
368       FT_Load_Glyph(m_Face->GetRec(), glyph_index,
369                     FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
370   if (err)
371     return 0;
372 
373   int horiAdvance = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec());
374   if (horiAdvance < 0 || horiAdvance > kThousandthMaxInt)
375     return 0;
376 
377   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), horiAdvance);
378 }
379 
LoadEmbedded(pdfium::span<const uint8_t> src_span,bool bForceAsVertical)380 bool CFX_Font::LoadEmbedded(pdfium::span<const uint8_t> src_span,
381                             bool bForceAsVertical) {
382   if (bForceAsVertical)
383     m_bVertical = true;
384   m_FontDataAllocation = std::vector<uint8_t, FxAllocAllocator<uint8_t>>(
385       src_span.begin(), src_span.end());
386   m_Face = CFX_GEModule::Get()->GetFontMgr()->NewFixedFace(
387       nullptr, m_FontDataAllocation, 0);
388   m_bEmbedded = true;
389   m_FontData = m_FontDataAllocation;
390   return !!m_Face;
391 }
392 
IsTTFont() const393 bool CFX_Font::IsTTFont() const {
394   return m_Face && FXFT_Is_Face_TT_OT(m_Face->GetRec()) == FT_FACE_FLAG_SFNT;
395 }
396 
GetAscent() const397 int CFX_Font::GetAscent() const {
398   if (!m_Face)
399     return 0;
400 
401   int ascender = FXFT_Get_Face_Ascender(m_Face->GetRec());
402   if (ascender < kThousandthMinInt || ascender > kThousandthMaxInt)
403     return 0;
404 
405   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), ascender);
406 }
407 
GetDescent() const408 int CFX_Font::GetDescent() const {
409   if (!m_Face)
410     return 0;
411 
412   int descender = FXFT_Get_Face_Descender(m_Face->GetRec());
413   if (descender < kThousandthMinInt || descender > kThousandthMaxInt)
414     return 0;
415 
416   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), descender);
417 }
418 
GetGlyphBBox(uint32_t glyph_index,FX_RECT * pBBox)419 bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT* pBBox) {
420   if (!m_Face)
421     return false;
422 
423   if (FXFT_Is_Face_Tricky(m_Face->GetRec())) {
424     int error = FT_Set_Char_Size(m_Face->GetRec(), 0, 1000 * 64, 72, 72);
425     if (error)
426       return false;
427 
428     error = FT_Load_Glyph(m_Face->GetRec(), glyph_index,
429                           FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
430     if (error)
431       return false;
432 
433     FT_BBox cbox;
434     FT_Glyph glyph;
435     error = FT_Get_Glyph(m_Face->GetRec()->glyph, &glyph);
436     if (error)
437       return false;
438 
439     FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
440     int pixel_size_x = m_Face->GetRec()->size->metrics.x_ppem;
441     int pixel_size_y = m_Face->GetRec()->size->metrics.y_ppem;
442     if (pixel_size_x == 0 || pixel_size_y == 0) {
443       pBBox->left = cbox.xMin;
444       pBBox->right = cbox.xMax;
445       pBBox->top = cbox.yMax;
446       pBBox->bottom = cbox.yMin;
447     } else {
448       pBBox->left = cbox.xMin * 1000 / pixel_size_x;
449       pBBox->right = cbox.xMax * 1000 / pixel_size_x;
450       pBBox->top = cbox.yMax * 1000 / pixel_size_y;
451       pBBox->bottom = cbox.yMin * 1000 / pixel_size_y;
452     }
453     pBBox->top = std::min(
454         pBBox->top,
455         static_cast<int32_t>(FXFT_Get_Face_Ascender(m_Face->GetRec())));
456     pBBox->bottom = std::max(
457         pBBox->bottom,
458         static_cast<int32_t>(FXFT_Get_Face_Descender(m_Face->GetRec())));
459     FT_Done_Glyph(glyph);
460     return FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64) == 0;
461   }
462   if (FT_Load_Glyph(m_Face->GetRec(), glyph_index,
463                     FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
464     return false;
465   }
466   int em = FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
467   if (em == 0) {
468     pBBox->left = FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec());
469     pBBox->bottom = FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec());
470     pBBox->top = pBBox->bottom - FXFT_Get_Glyph_Height(m_Face->GetRec());
471     pBBox->right = pBBox->left + FXFT_Get_Glyph_Width(m_Face->GetRec());
472   } else {
473     pBBox->left = FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec()) * 1000 / em;
474     pBBox->top = (FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec()) -
475                   FXFT_Get_Glyph_Height(m_Face->GetRec())) *
476                  1000 / em;
477     pBBox->right = (FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec()) +
478                     FXFT_Get_Glyph_Width(m_Face->GetRec())) *
479                    1000 / em;
480     pBBox->bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec())) * 1000 / em;
481   }
482   return true;
483 }
484 
IsItalic() const485 bool CFX_Font::IsItalic() const {
486   if (!m_Face)
487     return false;
488   if (FXFT_Is_Face_Italic(m_Face->GetRec()) == FT_STYLE_FLAG_ITALIC)
489     return true;
490 
491   ByteString str(FXFT_Get_Face_Style_Name(m_Face->GetRec()));
492   str.MakeLower();
493   return str.Contains("italic");
494 }
495 
IsBold() const496 bool CFX_Font::IsBold() const {
497   return m_Face && FXFT_Is_Face_Bold(m_Face->GetRec()) == FT_STYLE_FLAG_BOLD;
498 }
499 
IsFixedWidth() const500 bool CFX_Font::IsFixedWidth() const {
501   return m_Face && FXFT_Is_Face_fixedwidth(m_Face->GetRec()) != 0;
502 }
503 
GetPsName() const504 ByteString CFX_Font::GetPsName() const {
505   if (!m_Face)
506     return ByteString();
507 
508   ByteString psName = FT_Get_Postscript_Name(m_Face->GetRec());
509   if (psName.IsEmpty())
510     psName = kUntitledFontName;
511   return psName;
512 }
513 
GetFamilyName() const514 ByteString CFX_Font::GetFamilyName() const {
515   if (!m_Face && !m_pSubstFont)
516     return ByteString();
517   if (m_Face)
518     return ByteString(FXFT_Get_Face_Family_Name(m_Face->GetRec()));
519   return m_pSubstFont->m_Family;
520 }
521 
GetFamilyNameOrUntitled() const522 ByteString CFX_Font::GetFamilyNameOrUntitled() const {
523   ByteString facename = GetFamilyName();
524   return facename.IsEmpty() ? kUntitledFontName : facename;
525 }
526 
GetFaceName() const527 ByteString CFX_Font::GetFaceName() const {
528   if (!m_Face && !m_pSubstFont)
529     return ByteString();
530   if (m_Face) {
531     ByteString style = ByteString(FXFT_Get_Face_Style_Name(m_Face->GetRec()));
532     ByteString facename = GetFamilyNameOrUntitled();
533     if (ShouldAppendStyle(style))
534       facename += " " + style;
535     return facename;
536   }
537   return m_pSubstFont->m_Family;
538 }
539 
GetBaseFontName(bool restrict_to_psname) const540 ByteString CFX_Font::GetBaseFontName(bool restrict_to_psname) const {
541   ByteString psname = GetPsName();
542   if (restrict_to_psname || (!psname.IsEmpty() && psname != kUntitledFontName))
543     return psname;
544   if (!m_Face && !m_pSubstFont)
545     return ByteString();
546   if (m_Face) {
547     ByteString style = ByteString(FXFT_Get_Face_Style_Name(m_Face->GetRec()));
548     ByteString facename = GetFamilyNameOrUntitled();
549     if (IsTTFont())
550       facename.Remove(' ');
551     if (ShouldAppendStyle(style))
552       facename += (IsTTFont() ? "," : " ") + style;
553     return facename;
554   }
555   return m_pSubstFont->m_Family;
556 }
557 
GetBBox(FX_RECT * pBBox)558 bool CFX_Font::GetBBox(FX_RECT* pBBox) {
559   if (!m_Face)
560     return false;
561 
562   int em = FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
563   if (em == 0) {
564     pBBox->left = FXFT_Get_Face_xMin(m_Face->GetRec());
565     pBBox->bottom = FXFT_Get_Face_yMax(m_Face->GetRec());
566     pBBox->top = FXFT_Get_Face_yMin(m_Face->GetRec());
567     pBBox->right = FXFT_Get_Face_xMax(m_Face->GetRec());
568   } else {
569     pBBox->left = FXFT_Get_Face_xMin(m_Face->GetRec()) * 1000 / em;
570     pBBox->top = FXFT_Get_Face_yMin(m_Face->GetRec()) * 1000 / em;
571     pBBox->right = FXFT_Get_Face_xMax(m_Face->GetRec()) * 1000 / em;
572     pBBox->bottom = FXFT_Get_Face_yMax(m_Face->GetRec()) * 1000 / em;
573   }
574   return true;
575 }
576 
GetOrCreateGlyphCache() const577 RetainPtr<CFX_GlyphCache> CFX_Font::GetOrCreateGlyphCache() const {
578   if (!m_GlyphCache)
579     m_GlyphCache = CFX_GEModule::Get()->GetFontCache()->GetGlyphCache(this);
580   return m_GlyphCache;
581 }
582 
ClearGlyphCache()583 void CFX_Font::ClearGlyphCache() {
584   m_GlyphCache = nullptr;
585 }
586 
AdjustMMParams(int glyph_index,int dest_width,int weight) const587 void CFX_Font::AdjustMMParams(int glyph_index,
588                               int dest_width,
589                               int weight) const {
590   ASSERT(dest_width >= 0);
591   FXFT_MM_VarPtr pMasters = nullptr;
592   FT_Get_MM_Var(m_Face->GetRec(), &pMasters);
593   if (!pMasters)
594     return;
595 
596   long coords[2];
597   if (weight == 0)
598     coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536;
599   else
600     coords[0] = weight;
601 
602   if (dest_width == 0) {
603     coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
604   } else {
605     int min_param = FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
606     int max_param = FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
607     coords[1] = min_param;
608     FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
609     FT_Load_Glyph(m_Face->GetRec(), glyph_index,
610                   FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
611     int min_width = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec()) * 1000 /
612                     FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
613     coords[1] = max_param;
614     FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
615     FT_Load_Glyph(m_Face->GetRec(), glyph_index,
616                   FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
617     int max_width = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec()) * 1000 /
618                     FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
619     if (max_width == min_width) {
620       FXFT_Free(m_Face->GetRec(), pMasters);
621       return;
622     }
623     int param = min_param + (max_param - min_param) * (dest_width - min_width) /
624                                 (max_width - min_width);
625     coords[1] = param;
626   }
627   FXFT_Free(m_Face->GetRec(), pMasters);
628   FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
629 }
630 
LoadGlyphPathImpl(uint32_t glyph_index,uint32_t dest_width) const631 CFX_PathData* CFX_Font::LoadGlyphPathImpl(uint32_t glyph_index,
632                                           uint32_t dest_width) const {
633   if (!m_Face)
634     return nullptr;
635 
636   FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64);
637   FT_Matrix ft_matrix = {65536, 0, 0, 65536};
638   if (m_pSubstFont) {
639     if (m_pSubstFont->m_ItalicAngle) {
640       int skew = m_pSubstFont->m_ItalicAngle;
641       // |skew| is nonpositive so |-skew| is used as the index. We need to make
642       // sure |skew| != INT_MIN since -INT_MIN is undefined.
643       if (skew <= 0 && skew != std::numeric_limits<int>::min() &&
644           static_cast<size_t>(-skew) < kAngleSkewArraySize) {
645         skew = -s_AngleSkew[-skew];
646       } else {
647         skew = -58;
648       }
649       if (m_bVertical)
650         ft_matrix.yx += ft_matrix.yy * skew / 100;
651       else
652         ft_matrix.xy -= ft_matrix.xx * skew / 100;
653     }
654     if (m_pSubstFont->m_bFlagMM)
655       AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight);
656   }
657   ScopedFontTransform scoped_transform(m_Face, &ft_matrix);
658   int load_flags = FT_LOAD_NO_BITMAP;
659   if (!(m_Face->GetRec()->face_flags & FT_FACE_FLAG_SFNT) ||
660       !FT_IS_TRICKY(m_Face->GetRec()))
661     load_flags |= FT_LOAD_NO_HINTING;
662   if (FT_Load_Glyph(m_Face->GetRec(), glyph_index, load_flags))
663     return nullptr;
664   if (m_pSubstFont && !m_pSubstFont->m_bFlagMM &&
665       m_pSubstFont->m_Weight > 400) {
666     uint32_t index = (m_pSubstFont->m_Weight - 400) / 10;
667     index = std::min(index, static_cast<uint32_t>(kWeightPowArraySize - 1));
668     int level = 0;
669     if (m_pSubstFont->m_Charset == FX_CHARSET_ShiftJIS)
670       level = s_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655;
671     else
672       level = s_WeightPow[index] * 2;
673     FT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face->GetRec()), level);
674   }
675 
676   FT_Outline_Funcs funcs;
677   funcs.move_to = Outline_MoveTo;
678   funcs.line_to = Outline_LineTo;
679   funcs.conic_to = Outline_ConicTo;
680   funcs.cubic_to = Outline_CubicTo;
681   funcs.shift = 0;
682   funcs.delta = 0;
683 
684   OUTLINE_PARAMS params;
685   auto pPath = pdfium::MakeUnique<CFX_PathData>();
686   params.m_pPath = pPath.get();
687   params.m_CurX = params.m_CurY = 0;
688   params.m_CoordUnit = 64 * 64.0;
689 
690   FT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face->GetRec()), &funcs,
691                        &params);
692   if (pPath->GetPoints().empty())
693     return nullptr;
694 
695   Outline_CheckEmptyContour(&params);
696   pPath->ClosePath();
697 
698   return pPath.release();
699 }
700 
LoadGlyphBitmap(uint32_t glyph_index,bool bFontStyle,const CFX_Matrix & matrix,uint32_t dest_width,int anti_alias,int * pTextFlags) const701 const CFX_GlyphBitmap* CFX_Font::LoadGlyphBitmap(uint32_t glyph_index,
702                                                  bool bFontStyle,
703                                                  const CFX_Matrix& matrix,
704                                                  uint32_t dest_width,
705                                                  int anti_alias,
706                                                  int* pTextFlags) const {
707   return GetOrCreateGlyphCache()->LoadGlyphBitmap(this, glyph_index, bFontStyle,
708                                                   matrix, dest_width,
709                                                   anti_alias, pTextFlags);
710 }
711 
LoadGlyphPath(uint32_t glyph_index,uint32_t dest_width) const712 const CFX_PathData* CFX_Font::LoadGlyphPath(uint32_t glyph_index,
713                                             uint32_t dest_width) const {
714   return GetOrCreateGlyphCache()->LoadGlyphPath(this, glyph_index, dest_width);
715 }
716 
717 #if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_
GetDeviceCache() const718 CFX_TypeFace* CFX_Font::GetDeviceCache() const {
719   return GetOrCreateGlyphCache()->GetDeviceCache(this);
720 }
721 #endif
722