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, ¶ms);
669 if (pPath->GetPoints().empty())
670 return nullptr;
671
672 Outline_CheckEmptyContour(¶ms);
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