• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The PDFium Authors
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 <stdint.h>
10 
11 #include <algorithm>
12 #include <limits>
13 #include <memory>
14 #include <utility>
15 
16 #include "build/build_config.h"
17 #include "core/fxcrt/data_vector.h"
18 #include "core/fxcrt/fx_codepage.h"
19 #include "core/fxcrt/fx_stream.h"
20 #include "core/fxcrt/unowned_ptr.h"
21 #include "core/fxge/cfx_fontcache.h"
22 #include "core/fxge/cfx_fontmapper.h"
23 #include "core/fxge/cfx_fontmgr.h"
24 #include "core/fxge/cfx_gemodule.h"
25 #include "core/fxge/cfx_glyphcache.h"
26 #include "core/fxge/cfx_path.h"
27 #include "core/fxge/cfx_substfont.h"
28 #include "core/fxge/fx_font.h"
29 #include "core/fxge/scoped_font_transform.h"
30 #include "third_party/base/check.h"
31 #include "third_party/base/numerics/safe_conversions.h"
32 #include "third_party/base/span.h"
33 
34 #define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em)
35 
36 namespace {
37 
38 constexpr int kThousandthMinInt = std::numeric_limits<int>::min() / 1000;
39 constexpr int kThousandthMaxInt = std::numeric_limits<int>::max() / 1000;
40 
41 struct OUTLINE_PARAMS {
42   UnownedPtr<CFX_Path> m_pPath;
43   FT_Pos m_CurX;
44   FT_Pos m_CurY;
45   float m_CoordUnit;
46 };
47 
48 // TODO(crbug.com/pdfium/1400): When FT_Done_MM_Var() is more likely to be
49 // available to all users in the future, remove FreeMMVar() and use
50 // FT_Done_MM_Var() directly.
51 //
52 // Use weak symbols to check if FT_Done_MM_Var() is available at runtime.
53 #if !BUILDFLAG(IS_WIN)
54 extern "C" __attribute__((weak)) decltype(FT_Done_MM_Var) FT_Done_MM_Var;
55 #endif
56 
FreeMMVar(FXFT_FaceRec * rec,FXFT_MM_VarPtr variation_desc)57 void FreeMMVar(FXFT_FaceRec* rec, FXFT_MM_VarPtr variation_desc) {
58 #if BUILDFLAG(IS_WIN)
59   // Assume `use_system_freetype` GN var is never set on Windows.
60   constexpr bool has_ft_done_mm_var_func = true;
61 #else
62   static const bool has_ft_done_mm_var_func = !!FT_Done_MM_Var;
63 #endif
64   if (has_ft_done_mm_var_func) {
65     FT_Done_MM_Var(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(),
66                    variation_desc);
67   } else {
68     FXFT_Free(rec, variation_desc);
69   }
70 }
71 
FXRectFromFTPos(FT_Pos left,FT_Pos top,FT_Pos right,FT_Pos bottom)72 FX_RECT FXRectFromFTPos(FT_Pos left, FT_Pos top, FT_Pos right, FT_Pos bottom) {
73   return FX_RECT(pdfium::base::checked_cast<int32_t>(left),
74                  pdfium::base::checked_cast<int32_t>(top),
75                  pdfium::base::checked_cast<int32_t>(right),
76                  pdfium::base::checked_cast<int32_t>(bottom));
77 }
78 
ScaledFXRectFromFTPos(FT_Pos left,FT_Pos top,FT_Pos right,FT_Pos bottom,int x_scale,int y_scale)79 FX_RECT ScaledFXRectFromFTPos(FT_Pos left,
80                               FT_Pos top,
81                               FT_Pos right,
82                               FT_Pos bottom,
83                               int x_scale,
84                               int y_scale) {
85   if (x_scale == 0 || y_scale == 0)
86     return FXRectFromFTPos(left, top, right, bottom);
87 
88   return FXRectFromFTPos(left * 1000 / x_scale, top * 1000 / y_scale,
89                          right * 1000 / x_scale, bottom * 1000 / y_scale);
90 }
91 
92 #ifdef PDF_ENABLE_XFA
FTStreamRead(FXFT_StreamRec * stream,unsigned long offset,unsigned char * buffer,unsigned long count)93 unsigned long FTStreamRead(FXFT_StreamRec* stream,
94                            unsigned long offset,
95                            unsigned char* buffer,
96                            unsigned long count) {
97   if (count == 0)
98     return 0;
99 
100   IFX_SeekableReadStream* pFile =
101       static_cast<IFX_SeekableReadStream*>(stream->descriptor.pointer);
102   return pFile && pFile->ReadBlockAtOffset({buffer, count}, offset) ? count : 0;
103 }
104 
FTStreamClose(FXFT_StreamRec * stream)105 void FTStreamClose(FXFT_StreamRec* stream) {}
106 #endif  // PDF_ENABLE_XFA
107 
Outline_CheckEmptyContour(OUTLINE_PARAMS * param)108 void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) {
109   size_t size;
110   {
111     pdfium::span<const CFX_Path::Point> points = param->m_pPath->GetPoints();
112     size = points.size();
113 
114     if (size >= 2 &&
115         points[size - 2].IsTypeAndOpen(CFX_Path::Point::Type::kMove) &&
116         points[size - 2].m_Point == points[size - 1].m_Point) {
117       size -= 2;
118     }
119     if (size >= 4 &&
120         points[size - 4].IsTypeAndOpen(CFX_Path::Point::Type::kMove) &&
121         points[size - 3].IsTypeAndOpen(CFX_Path::Point::Type::kBezier) &&
122         points[size - 3].m_Point == points[size - 4].m_Point &&
123         points[size - 2].m_Point == points[size - 4].m_Point &&
124         points[size - 1].m_Point == points[size - 4].m_Point) {
125       size -= 4;
126     }
127   }
128   // Only safe after |points| has been destroyed.
129   param->m_pPath->GetPoints().resize(size);
130 }
131 
Outline_MoveTo(const FT_Vector * to,void * user)132 int Outline_MoveTo(const FT_Vector* to, void* user) {
133   OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
134 
135   Outline_CheckEmptyContour(param);
136 
137   param->m_pPath->ClosePath();
138   param->m_pPath->AppendPoint(
139       CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
140       CFX_Path::Point::Type::kMove);
141 
142   param->m_CurX = to->x;
143   param->m_CurY = to->y;
144   return 0;
145 }
146 
Outline_LineTo(const FT_Vector * to,void * user)147 int Outline_LineTo(const FT_Vector* to, void* user) {
148   OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
149 
150   param->m_pPath->AppendPoint(
151       CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
152       CFX_Path::Point::Type::kLine);
153 
154   param->m_CurX = to->x;
155   param->m_CurY = to->y;
156   return 0;
157 }
158 
Outline_ConicTo(const FT_Vector * control,const FT_Vector * to,void * user)159 int Outline_ConicTo(const FT_Vector* control, const FT_Vector* to, void* user) {
160   OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
161 
162   param->m_pPath->AppendPoint(
163       CFX_PointF((param->m_CurX + (control->x - param->m_CurX) * 2 / 3) /
164                      param->m_CoordUnit,
165                  (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) /
166                      param->m_CoordUnit),
167       CFX_Path::Point::Type::kBezier);
168 
169   param->m_pPath->AppendPoint(
170       CFX_PointF((control->x + (to->x - control->x) / 3) / param->m_CoordUnit,
171                  (control->y + (to->y - control->y) / 3) / param->m_CoordUnit),
172       CFX_Path::Point::Type::kBezier);
173 
174   param->m_pPath->AppendPoint(
175       CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
176       CFX_Path::Point::Type::kBezier);
177 
178   param->m_CurX = to->x;
179   param->m_CurY = to->y;
180   return 0;
181 }
182 
Outline_CubicTo(const FT_Vector * control1,const FT_Vector * control2,const FT_Vector * to,void * user)183 int Outline_CubicTo(const FT_Vector* control1,
184                     const FT_Vector* control2,
185                     const FT_Vector* to,
186                     void* user) {
187   OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
188 
189   param->m_pPath->AppendPoint(CFX_PointF(control1->x / param->m_CoordUnit,
190                                          control1->y / param->m_CoordUnit),
191                               CFX_Path::Point::Type::kBezier);
192 
193   param->m_pPath->AppendPoint(CFX_PointF(control2->x / param->m_CoordUnit,
194                                          control2->y / param->m_CoordUnit),
195                               CFX_Path::Point::Type::kBezier);
196 
197   param->m_pPath->AppendPoint(
198       CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
199       CFX_Path::Point::Type::kBezier);
200 
201   param->m_CurX = to->x;
202   param->m_CurY = to->y;
203   return 0;
204 }
205 
ShouldAppendStyle(const ByteString & style)206 bool ShouldAppendStyle(const ByteString& style) {
207   return !style.IsEmpty() && style != "Regular";
208 }
209 
210 constexpr int8_t kAngleSkew[] = {
211     -0,  -2,  -3,  -5,  -7,  -9,  -11, -12, -14, -16, -18, -19, -21, -23, -25,
212     -27, -29, -31, -32, -34, -36, -38, -40, -42, -45, -47, -49, -51, -53, -55,
213 };
214 
215 constexpr uint8_t kWeightPow[] = {
216     0,   6,   12,  14,  16,  18,  22,  24,  28,  30,  32,  34,  36,  38,  40,
217     42,  44,  46,  48,  50,  52,  54,  56,  58,  60,  62,  64,  66,  68,  70,
218     70,  72,  72,  74,  74,  74,  76,  76,  76,  78,  78,  78,  80,  80,  80,
219     82,  82,  82,  84,  84,  84,  84,  86,  86,  86,  88,  88,  88,  88,  90,
220     90,  90,  90,  92,  92,  92,  92,  94,  94,  94,  94,  96,  96,  96,  96,
221     96,  98,  98,  98,  98,  100, 100, 100, 100, 100, 102, 102, 102, 102, 102,
222     104, 104, 104, 104, 104, 106, 106, 106, 106, 106,
223 };
224 
225 constexpr uint8_t kWeightPow11[] = {
226     0,  4,  7,  8,  9,  10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24,
227     25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41,
228     41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46,
229     46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52,
230     52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55,
231     56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58,
232 };
233 
234 constexpr uint8_t kWeightPowShiftJis[] = {
235     0,   0,   2,   4,   6,   8,   10,  14,  16,  20,  22,  26,  28,  32,  34,
236     38,  42,  44,  48,  52,  56,  60,  64,  66,  70,  74,  78,  82,  86,  90,
237     96,  96,  96,  96,  98,  98,  98,  100, 100, 100, 100, 102, 102, 102, 102,
238     104, 104, 104, 104, 104, 106, 106, 106, 106, 106, 108, 108, 108, 108, 108,
239     110, 110, 110, 110, 110, 112, 112, 112, 112, 112, 112, 114, 114, 114, 114,
240     114, 114, 114, 116, 116, 116, 116, 116, 116, 116, 118, 118, 118, 118, 118,
241     118, 118, 120, 120, 120, 120, 120, 120, 120, 120,
242 };
243 
244 constexpr size_t kWeightPowArraySize = 100;
245 static_assert(kWeightPowArraySize == std::size(kWeightPow), "Wrong size");
246 static_assert(kWeightPowArraySize == std::size(kWeightPow11), "Wrong size");
247 static_assert(kWeightPowArraySize == std::size(kWeightPowShiftJis),
248               "Wrong size");
249 
250 }  // namespace
251 
252 const CFX_Font::CharsetFontMap CFX_Font::kDefaultTTFMap[] = {
253     {static_cast<int>(FX_Charset::kANSI), kDefaultAnsiFontName},
254     {static_cast<int>(FX_Charset::kChineseSimplified), "SimSun"},
255     {static_cast<int>(FX_Charset::kChineseTraditional), "MingLiU"},
256     {static_cast<int>(FX_Charset::kShiftJIS), "MS Gothic"},
257     {static_cast<int>(FX_Charset::kHangul), "Batang"},
258     {static_cast<int>(FX_Charset::kMSWin_Cyrillic), "Arial"},
259 #if BUILDFLAG(IS_WIN)
260     {static_cast<int>(FX_Charset::kMSWin_EasternEuropean), "Tahoma"},
261 #else
262     {static_cast<int>(FX_Charset::kMSWin_EasternEuropean), "Arial"},
263 #endif
264     {static_cast<int>(FX_Charset::kMSWin_Arabic), "Arial"},
265     {-1, nullptr}};
266 
267 // static
268 const char CFX_Font::kUntitledFontName[] = "Untitled";
269 
270 // static
271 const char CFX_Font::kDefaultAnsiFontName[] = "Helvetica";
272 
273 // static
274 const char CFX_Font::kUniversalDefaultFontName[] = "Arial Unicode MS";
275 
276 // static
GetDefaultFontNameByCharset(FX_Charset nCharset)277 ByteString CFX_Font::GetDefaultFontNameByCharset(FX_Charset nCharset) {
278   for (size_t i = 0; i < std::size(kDefaultTTFMap) - 1; ++i) {
279     if (static_cast<int>(nCharset) == kDefaultTTFMap[i].charset)
280       return kDefaultTTFMap[i].fontname;
281   }
282   return kUniversalDefaultFontName;
283 }
284 
285 // static
GetCharSetFromUnicode(uint16_t word)286 FX_Charset CFX_Font::GetCharSetFromUnicode(uint16_t word) {
287   // to avoid CJK Font to show ASCII
288   if (word < 0x7F)
289     return FX_Charset::kANSI;
290 
291   // find new charset
292   if ((word >= 0x4E00 && word <= 0x9FA5) ||
293       (word >= 0xE7C7 && word <= 0xE7F3) ||
294       (word >= 0x3000 && word <= 0x303F) ||
295       (word >= 0x2000 && word <= 0x206F)) {
296     return FX_Charset::kChineseSimplified;
297   }
298 
299   if (((word >= 0x3040) && (word <= 0x309F)) ||
300       ((word >= 0x30A0) && (word <= 0x30FF)) ||
301       ((word >= 0x31F0) && (word <= 0x31FF)) ||
302       ((word >= 0xFF00) && (word <= 0xFFEF))) {
303     return FX_Charset::kShiftJIS;
304   }
305 
306   if (((word >= 0xAC00) && (word <= 0xD7AF)) ||
307       ((word >= 0x1100) && (word <= 0x11FF)) ||
308       ((word >= 0x3130) && (word <= 0x318F))) {
309     return FX_Charset::kHangul;
310   }
311 
312   if (word >= 0x0E00 && word <= 0x0E7F)
313     return FX_Charset::kThai;
314 
315   if ((word >= 0x0370 && word <= 0x03FF) || (word >= 0x1F00 && word <= 0x1FFF))
316     return FX_Charset::kMSWin_Greek;
317 
318   if ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
319     return FX_Charset::kMSWin_Arabic;
320 
321   if (word >= 0x0590 && word <= 0x05FF)
322     return FX_Charset::kMSWin_Hebrew;
323 
324   if (word >= 0x0400 && word <= 0x04FF)
325     return FX_Charset::kMSWin_Cyrillic;
326 
327   if (word >= 0x0100 && word <= 0x024F)
328     return FX_Charset::kMSWin_EasternEuropean;
329 
330   if (word >= 0x1E00 && word <= 0x1EFF)
331     return FX_Charset::kMSWin_Vietnamese;
332 
333   return FX_Charset::kANSI;
334 }
335 
336 CFX_Font::CFX_Font() = default;
337 
GetSubstFontItalicAngle() const338 int CFX_Font::GetSubstFontItalicAngle() const {
339   CFX_SubstFont* subst_font = GetSubstFont();
340   return subst_font ? subst_font->m_ItalicAngle : 0;
341 }
342 
343 #ifdef PDF_ENABLE_XFA
LoadFile(RetainPtr<IFX_SeekableReadStream> pFile,int nFaceIndex)344 bool CFX_Font::LoadFile(RetainPtr<IFX_SeekableReadStream> pFile,
345                         int nFaceIndex) {
346   m_bEmbedded = false;
347   m_ObjectTag = 0;
348 
349   auto pStreamRec = std::make_unique<FXFT_StreamRec>();
350   pStreamRec->base = nullptr;
351   pStreamRec->size = static_cast<unsigned long>(pFile->GetSize());
352   pStreamRec->pos = 0;
353   pStreamRec->descriptor.pointer = static_cast<void*>(pFile.Get());
354   pStreamRec->close = FTStreamClose;
355   pStreamRec->read = FTStreamRead;
356 
357   FT_Open_Args args;
358   args.flags = FT_OPEN_STREAM;
359   args.stream = pStreamRec.get();
360 
361   m_Face = CFX_Face::Open(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(),
362                           &args, nFaceIndex);
363   if (!m_Face)
364     return false;
365 
366   m_pOwnedFile = std::move(pFile);
367   m_pOwnedStreamRec = std::move(pStreamRec);
368   FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64);
369   return true;
370 }
371 
372 #if !BUILDFLAG(IS_WIN)
SetFace(RetainPtr<CFX_Face> face)373 void CFX_Font::SetFace(RetainPtr<CFX_Face> face) {
374   ClearGlyphCache();
375   m_ObjectTag = 0;
376   m_Face = face;
377 }
378 
SetSubstFont(std::unique_ptr<CFX_SubstFont> subst)379 void CFX_Font::SetSubstFont(std::unique_ptr<CFX_SubstFont> subst) {
380   m_pSubstFont = std::move(subst);
381 }
382 #endif  // !BUILDFLAG(IS_WIN)
383 #endif  // PDF_ENABLE_XFA
384 
~CFX_Font()385 CFX_Font::~CFX_Font() {
386   m_FontData = {};  // m_FontData can't outive m_Face.
387   m_Face.Reset();
388 
389 #if BUILDFLAG(IS_APPLE)
390   ReleasePlatformResource();
391 #endif
392 }
393 
LoadSubst(const ByteString & face_name,bool bTrueType,uint32_t flags,int weight,int italic_angle,FX_CodePage code_page,bool bVertical)394 void CFX_Font::LoadSubst(const ByteString& face_name,
395                          bool bTrueType,
396                          uint32_t flags,
397                          int weight,
398                          int italic_angle,
399                          FX_CodePage code_page,
400                          bool bVertical) {
401   m_bEmbedded = false;
402   m_bVertical = bVertical;
403   m_ObjectTag = 0;
404   m_pSubstFont = std::make_unique<CFX_SubstFont>();
405   m_Face = CFX_GEModule::Get()->GetFontMgr()->GetBuiltinMapper()->FindSubstFont(
406       face_name, bTrueType, flags, weight, italic_angle, code_page,
407       m_pSubstFont.get());
408   if (m_Face) {
409     m_FontData = {FXFT_Get_Face_Stream_Base(m_Face->GetRec()),
410                   FXFT_Get_Face_Stream_Size(m_Face->GetRec())};
411   }
412 }
413 
GetGlyphWidth(uint32_t glyph_index) const414 int CFX_Font::GetGlyphWidth(uint32_t glyph_index) const {
415   return GetGlyphWidth(glyph_index, 0, 0);
416 }
417 
GetGlyphWidth(uint32_t glyph_index,int dest_width,int weight) const418 int CFX_Font::GetGlyphWidth(uint32_t glyph_index,
419                             int dest_width,
420                             int weight) const {
421   return GetOrCreateGlyphCache()->GetGlyphWidth(this, glyph_index, dest_width,
422                                                 weight);
423 }
424 
GetGlyphWidthImpl(uint32_t glyph_index,int dest_width,int weight) const425 int CFX_Font::GetGlyphWidthImpl(uint32_t glyph_index,
426                                 int dest_width,
427                                 int weight) const {
428   if (!m_Face)
429     return 0;
430   if (m_pSubstFont && m_pSubstFont->IsBuiltInGenericFont())
431     AdjustMMParams(glyph_index, dest_width, weight);
432   int err =
433       FT_Load_Glyph(m_Face->GetRec(), glyph_index,
434                     FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
435   if (err)
436     return 0;
437 
438   FT_Pos horiAdvance = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec());
439   if (horiAdvance < kThousandthMinInt || horiAdvance > kThousandthMaxInt)
440     return 0;
441 
442   return static_cast<int>(
443       EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), horiAdvance));
444 }
445 
LoadEmbedded(pdfium::span<const uint8_t> src_span,bool force_vertical,uint64_t object_tag)446 bool CFX_Font::LoadEmbedded(pdfium::span<const uint8_t> src_span,
447                             bool force_vertical,
448                             uint64_t object_tag) {
449   m_bVertical = force_vertical;
450   m_ObjectTag = object_tag;
451   m_FontDataAllocation = DataVector<uint8_t>(src_span.begin(), src_span.end());
452   m_Face = CFX_GEModule::Get()->GetFontMgr()->NewFixedFace(
453       nullptr, m_FontDataAllocation, 0);
454   m_bEmbedded = true;
455   m_FontData = m_FontDataAllocation;
456   return !!m_Face;
457 }
458 
IsTTFont() const459 bool CFX_Font::IsTTFont() const {
460   return m_Face && FXFT_Is_Face_TT_OT(m_Face->GetRec()) == FT_FACE_FLAG_SFNT;
461 }
462 
GetAscent() const463 int CFX_Font::GetAscent() const {
464   if (!m_Face)
465     return 0;
466 
467   int ascender = FXFT_Get_Face_Ascender(m_Face->GetRec());
468   if (ascender < kThousandthMinInt || ascender > kThousandthMaxInt)
469     return 0;
470 
471   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), ascender);
472 }
473 
GetDescent() const474 int CFX_Font::GetDescent() const {
475   if (!m_Face)
476     return 0;
477 
478   int descender = FXFT_Get_Face_Descender(m_Face->GetRec());
479   if (descender < kThousandthMinInt || descender > kThousandthMaxInt)
480     return 0;
481 
482   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), descender);
483 }
484 
GetGlyphBBox(uint32_t glyph_index)485 absl::optional<FX_RECT> CFX_Font::GetGlyphBBox(uint32_t glyph_index) {
486   if (!m_Face)
487     return absl::nullopt;
488 
489   if (FXFT_Is_Face_Tricky(m_Face->GetRec())) {
490     int error = FT_Set_Char_Size(m_Face->GetRec(), 0, 1000 * 64, 72, 72);
491     if (error)
492       return absl::nullopt;
493 
494     error = FT_Load_Glyph(m_Face->GetRec(), glyph_index,
495                           FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
496     if (error)
497       return absl::nullopt;
498 
499     FT_Glyph glyph;
500     error = FT_Get_Glyph(m_Face->GetRec()->glyph, &glyph);
501     if (error)
502       return absl::nullopt;
503 
504     FT_BBox cbox;
505     FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
506     int pixel_size_x = m_Face->GetRec()->size->metrics.x_ppem;
507     int pixel_size_y = m_Face->GetRec()->size->metrics.y_ppem;
508     FX_RECT result = ScaledFXRectFromFTPos(
509         cbox.xMin, cbox.yMax, cbox.xMax, cbox.yMin, pixel_size_x, pixel_size_y);
510     result.top =
511         std::min(result.top, pdfium::base::checked_cast<int32_t>(
512                                  FXFT_Get_Face_Ascender(m_Face->GetRec())));
513     result.bottom =
514         std::max(result.bottom, pdfium::base::checked_cast<int32_t>(
515                                     FXFT_Get_Face_Descender(m_Face->GetRec())));
516     FT_Done_Glyph(glyph);
517     if (FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64) != 0)
518       return absl::nullopt;
519     return result;
520   }
521   constexpr int kFlag = FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
522   if (FT_Load_Glyph(m_Face->GetRec(), glyph_index, kFlag) != 0)
523     return absl::nullopt;
524   int em = FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
525   return ScaledFXRectFromFTPos(FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec()),
526                                FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec()) -
527                                    FXFT_Get_Glyph_Height(m_Face->GetRec()),
528                                FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec()) +
529                                    FXFT_Get_Glyph_Width(m_Face->GetRec()),
530                                FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec()),
531                                em, em);
532 }
533 
IsItalic() const534 bool CFX_Font::IsItalic() const {
535   if (!m_Face)
536     return false;
537   if (FXFT_Is_Face_Italic(m_Face->GetRec()) == FT_STYLE_FLAG_ITALIC)
538     return true;
539 
540   ByteString str(FXFT_Get_Face_Style_Name(m_Face->GetRec()));
541   str.MakeLower();
542   return str.Contains("italic");
543 }
544 
IsBold() const545 bool CFX_Font::IsBold() const {
546   return m_Face && FXFT_Is_Face_Bold(m_Face->GetRec()) == FT_STYLE_FLAG_BOLD;
547 }
548 
IsFixedWidth() const549 bool CFX_Font::IsFixedWidth() const {
550   return m_Face && FXFT_Is_Face_fixedwidth(m_Face->GetRec()) != 0;
551 }
552 
553 #if defined(_SKIA_SUPPORT_)
IsSubstFontBold() const554 bool CFX_Font::IsSubstFontBold() const {
555   CFX_SubstFont* subst_font = GetSubstFont();
556   return subst_font && subst_font->GetOriginalWeight() >= FXFONT_FW_BOLD;
557 }
558 #endif
559 
GetPsName() const560 ByteString CFX_Font::GetPsName() const {
561   if (!m_Face)
562     return ByteString();
563 
564   ByteString psName = FT_Get_Postscript_Name(m_Face->GetRec());
565   if (psName.IsEmpty())
566     psName = kUntitledFontName;
567   return psName;
568 }
569 
GetFamilyName() const570 ByteString CFX_Font::GetFamilyName() const {
571   if (!m_Face && !m_pSubstFont)
572     return ByteString();
573   if (m_Face)
574     return ByteString(FXFT_Get_Face_Family_Name(m_Face->GetRec()));
575   return m_pSubstFont->m_Family;
576 }
577 
GetFamilyNameOrUntitled() const578 ByteString CFX_Font::GetFamilyNameOrUntitled() const {
579   ByteString facename = GetFamilyName();
580   return facename.IsEmpty() ? kUntitledFontName : facename;
581 }
582 
GetFaceName() const583 ByteString CFX_Font::GetFaceName() const {
584   if (!m_Face && !m_pSubstFont)
585     return ByteString();
586   if (m_Face) {
587     ByteString style = ByteString(FXFT_Get_Face_Style_Name(m_Face->GetRec()));
588     ByteString facename = GetFamilyNameOrUntitled();
589     if (ShouldAppendStyle(style))
590       facename += " " + style;
591     return facename;
592   }
593   return m_pSubstFont->m_Family;
594 }
595 
GetBaseFontName() const596 ByteString CFX_Font::GetBaseFontName() const {
597   ByteString psname = GetPsName();
598   if (!psname.IsEmpty() && psname != kUntitledFontName)
599     return psname;
600   if (m_Face) {
601     ByteString style = ByteString(FXFT_Get_Face_Style_Name(m_Face->GetRec()));
602     ByteString facename = GetFamilyNameOrUntitled();
603     if (IsTTFont())
604       facename.Remove(' ');
605     if (ShouldAppendStyle(style))
606       facename += (IsTTFont() ? "," : " ") + style;
607     return facename;
608   }
609   if (m_pSubstFont)
610     return m_pSubstFont->m_Family;
611   return ByteString();
612 }
613 
GetRawBBox() const614 absl::optional<FX_RECT> CFX_Font::GetRawBBox() const {
615   if (!m_Face)
616     return absl::nullopt;
617 
618   return FXRectFromFTPos(FXFT_Get_Face_xMin(m_Face->GetRec()),
619                          FXFT_Get_Face_yMin(m_Face->GetRec()),
620                          FXFT_Get_Face_xMax(m_Face->GetRec()),
621                          FXFT_Get_Face_yMax(m_Face->GetRec()));
622 }
623 
GetBBox() const624 absl::optional<FX_RECT> CFX_Font::GetBBox() const {
625   absl::optional<FX_RECT> result = GetRawBBox();
626   if (!result.has_value())
627     return result;
628 
629   int em = FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
630   if (em != 0) {
631     FX_RECT& bbox = result.value();
632     bbox.left = (bbox.left * 1000) / em;
633     bbox.top = (bbox.top * 1000) / em;
634     bbox.right = (bbox.right * 1000) / em;
635     bbox.bottom = (bbox.bottom * 1000) / em;
636   }
637   return result;
638 }
639 
AllocSubData(size_t size)640 void CFX_Font::AllocSubData(size_t size) {
641   m_pSubData.reset(FX_Alloc(uint8_t, size));
642 }
643 
GetOrCreateGlyphCache() const644 RetainPtr<CFX_GlyphCache> CFX_Font::GetOrCreateGlyphCache() const {
645   if (!m_GlyphCache)
646     m_GlyphCache = CFX_GEModule::Get()->GetFontCache()->GetGlyphCache(this);
647   return m_GlyphCache;
648 }
649 
ClearGlyphCache()650 void CFX_Font::ClearGlyphCache() {
651   m_GlyphCache = nullptr;
652 }
653 
AdjustMMParams(int glyph_index,int dest_width,int weight) const654 void CFX_Font::AdjustMMParams(int glyph_index,
655                               int dest_width,
656                               int weight) const {
657   DCHECK(dest_width >= 0);
658   FXFT_MM_VarPtr pMasters = nullptr;
659   FT_Get_MM_Var(m_Face->GetRec(), &pMasters);
660   if (!pMasters)
661     return;
662 
663   FT_Pos coords[2];
664   if (weight == 0)
665     coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536;
666   else
667     coords[0] = weight;
668 
669   if (dest_width == 0) {
670     coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
671   } else {
672     FT_Long min_param =
673         FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
674     FT_Long max_param =
675         FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536;
676     coords[1] = min_param;
677     FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
678     FT_Load_Glyph(m_Face->GetRec(), glyph_index,
679                   FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
680     FT_Pos min_width = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec()) * 1000 /
681                        FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
682     coords[1] = max_param;
683     FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
684     FT_Load_Glyph(m_Face->GetRec(), glyph_index,
685                   FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
686     FT_Pos max_width = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec()) * 1000 /
687                        FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
688     if (max_width == min_width) {
689       FreeMMVar(m_Face->GetRec(), pMasters);
690       return;
691     }
692     FT_Pos param = min_param + (max_param - min_param) *
693                                    (dest_width - min_width) /
694                                    (max_width - min_width);
695     coords[1] = param;
696   }
697   FreeMMVar(m_Face->GetRec(), pMasters);
698   FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
699 }
700 
LoadGlyphPathImpl(uint32_t glyph_index,int dest_width) const701 std::unique_ptr<CFX_Path> CFX_Font::LoadGlyphPathImpl(uint32_t glyph_index,
702                                                       int dest_width) const {
703   if (!m_Face)
704     return nullptr;
705 
706   FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64);
707   FT_Matrix ft_matrix = {65536, 0, 0, 65536};
708   if (m_pSubstFont) {
709     if (m_pSubstFont->m_ItalicAngle) {
710       int skew = GetSkewFromAngle(m_pSubstFont->m_ItalicAngle);
711       if (m_bVertical)
712         ft_matrix.yx += ft_matrix.yy * skew / 100;
713       else
714         ft_matrix.xy -= ft_matrix.xx * skew / 100;
715     }
716     if (m_pSubstFont->IsBuiltInGenericFont())
717       AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight);
718   }
719   ScopedFontTransform scoped_transform(m_Face, &ft_matrix);
720   int load_flags = FT_LOAD_NO_BITMAP;
721   if (!(m_Face->GetRec()->face_flags & FT_FACE_FLAG_SFNT) ||
722       !FT_IS_TRICKY(m_Face->GetRec()))
723     load_flags |= FT_LOAD_NO_HINTING;
724   if (FT_Load_Glyph(m_Face->GetRec(), glyph_index, load_flags))
725     return nullptr;
726   if (m_pSubstFont && !m_pSubstFont->IsBuiltInGenericFont() &&
727       m_pSubstFont->m_Weight > 400) {
728     uint32_t index = std::min<uint32_t>((m_pSubstFont->m_Weight - 400) / 10,
729                                         kWeightPowArraySize - 1);
730     int level;
731     if (m_pSubstFont->m_Charset == FX_Charset::kShiftJIS)
732       level = kWeightPowShiftJis[index] * 65536 / 36655;
733     else
734       level = kWeightPow[index];
735     FT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face->GetRec()), level);
736   }
737 
738   FT_Outline_Funcs funcs;
739   funcs.move_to = Outline_MoveTo;
740   funcs.line_to = Outline_LineTo;
741   funcs.conic_to = Outline_ConicTo;
742   funcs.cubic_to = Outline_CubicTo;
743   funcs.shift = 0;
744   funcs.delta = 0;
745 
746   auto pPath = std::make_unique<CFX_Path>();
747   OUTLINE_PARAMS params;
748   params.m_pPath = pPath.get();
749   params.m_CurX = params.m_CurY = 0;
750   params.m_CoordUnit = 64 * 64.0;
751 
752   FT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face->GetRec()), &funcs,
753                        &params);
754   if (pPath->GetPoints().empty())
755     return nullptr;
756 
757   Outline_CheckEmptyContour(&params);
758   pPath->ClosePath();
759   return pPath;
760 }
761 
LoadGlyphBitmap(uint32_t glyph_index,bool bFontStyle,const CFX_Matrix & matrix,int dest_width,int anti_alias,CFX_TextRenderOptions * text_options) const762 const CFX_GlyphBitmap* CFX_Font::LoadGlyphBitmap(
763     uint32_t glyph_index,
764     bool bFontStyle,
765     const CFX_Matrix& matrix,
766     int dest_width,
767     int anti_alias,
768     CFX_TextRenderOptions* text_options) const {
769   return GetOrCreateGlyphCache()->LoadGlyphBitmap(this, glyph_index, bFontStyle,
770                                                   matrix, dest_width,
771                                                   anti_alias, text_options);
772 }
773 
LoadGlyphPath(uint32_t glyph_index,int dest_width) const774 const CFX_Path* CFX_Font::LoadGlyphPath(uint32_t glyph_index,
775                                         int dest_width) const {
776   return GetOrCreateGlyphCache()->LoadGlyphPath(this, glyph_index, dest_width);
777 }
778 
779 // static
GetWeightLevel(FX_Charset charset,size_t index)780 int CFX_Font::GetWeightLevel(FX_Charset charset, size_t index) {
781   if (index >= kWeightPowArraySize)
782     return -1;
783 
784   if (charset == FX_Charset::kShiftJIS)
785     return kWeightPowShiftJis[index];
786   return kWeightPow11[index];
787 }
788 
789 // static
GetSkewFromAngle(int angle)790 int CFX_Font::GetSkewFromAngle(int angle) {
791   // |angle| is non-positive so |-angle| is used as the index. Need to make sure
792   // |angle| != INT_MIN since -INT_MIN is undefined.
793   if (angle > 0 || angle == std::numeric_limits<int>::min() ||
794       static_cast<size_t>(-angle) >= std::size(kAngleSkew)) {
795     return -58;
796   }
797   return kAngleSkew[-angle];
798 }
799 
800 #if defined(_SKIA_SUPPORT_)
GetDeviceCache() const801 CFX_TypeFace* CFX_Font::GetDeviceCache() const {
802   return GetOrCreateGlyphCache()->GetDeviceCache(this);
803 }
804 #endif
805