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 ¶ms);
692 if (pPath->GetPoints().empty())
693 return nullptr;
694
695 Outline_CheckEmptyContour(¶ms);
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