1 // Copyright 2016 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/android/cfpf_skiafont.h"
8
9 #include <algorithm>
10
11 #include "core/fxcrt/fx_codepage.h"
12 #include "core/fxcrt/fx_coordinates.h"
13 #include "core/fxcrt/fx_system.h"
14 #include "core/fxge/android/cfpf_skiafontmgr.h"
15 #include "core/fxge/android/cfpf_skiapathfont.h"
16 #include "core/fxge/freetype/fx_freetype.h"
17 #include "third_party/base/numerics/safe_conversions.h"
18
19 #define FPF_EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em)
20
CFPF_SkiaFont(CFPF_SkiaFontMgr * pFontMgr,const CFPF_SkiaPathFont * pFont,uint32_t dwStyle,FX_Charset uCharset)21 CFPF_SkiaFont::CFPF_SkiaFont(CFPF_SkiaFontMgr* pFontMgr,
22 const CFPF_SkiaPathFont* pFont,
23 uint32_t dwStyle,
24 FX_Charset uCharset)
25 : m_pFontMgr(pFontMgr),
26 m_pFont(pFont),
27 m_Face(m_pFontMgr->GetFontFace(m_pFont->path(), m_pFont->face_index())),
28 m_dwStyle(dwStyle),
29 m_uCharset(uCharset) {}
30
31 CFPF_SkiaFont::~CFPF_SkiaFont() = default;
32
GetFamilyName()33 ByteString CFPF_SkiaFont::GetFamilyName() {
34 if (!m_Face)
35 return ByteString();
36 return ByteString(FXFT_Get_Face_Family_Name(GetFaceRec()));
37 }
38
GetPsName()39 ByteString CFPF_SkiaFont::GetPsName() {
40 if (!m_Face)
41 return ByteString();
42 return FT_Get_Postscript_Name(GetFaceRec());
43 }
44
GetGlyphIndex(wchar_t wUnicode)45 int32_t CFPF_SkiaFont::GetGlyphIndex(wchar_t wUnicode) {
46 if (!m_Face)
47 return wUnicode;
48 if (FXFT_Select_Charmap(GetFaceRec(), FT_ENCODING_UNICODE))
49 return 0;
50 return FT_Get_Char_Index(GetFaceRec(), wUnicode);
51 }
52
GetGlyphWidth(int32_t iGlyphIndex)53 int32_t CFPF_SkiaFont::GetGlyphWidth(int32_t iGlyphIndex) {
54 if (!m_Face)
55 return 0;
56 if (FT_Load_Glyph(GetFaceRec(), iGlyphIndex,
57 FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
58 return 0;
59 }
60 return static_cast<int32_t>(
61 FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
62 FXFT_Get_Glyph_HoriAdvance(GetFaceRec())));
63 }
64
GetAscent() const65 int32_t CFPF_SkiaFont::GetAscent() const {
66 if (!m_Face)
67 return 0;
68 return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
69 FXFT_Get_Face_Ascender(GetFaceRec()));
70 }
71
GetDescent() const72 int32_t CFPF_SkiaFont::GetDescent() const {
73 if (!m_Face)
74 return 0;
75 return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
76 FXFT_Get_Face_Descender(GetFaceRec()));
77 }
78
GetGlyphBBox(int32_t iGlyphIndex,FX_RECT & rtBBox)79 bool CFPF_SkiaFont::GetGlyphBBox(int32_t iGlyphIndex, FX_RECT& rtBBox) {
80 if (!m_Face)
81 return false;
82 if (FXFT_Is_Face_Tricky(GetFaceRec())) {
83 if (FT_Set_Char_Size(GetFaceRec(), 0, 1000 * 64, 72, 72))
84 return false;
85 if (FT_Load_Glyph(GetFaceRec(), iGlyphIndex,
86 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
87 FT_Set_Pixel_Sizes(GetFaceRec(), 0, 64);
88 return false;
89 }
90 FT_Glyph glyph;
91 if (FT_Get_Glyph(GetFaceRec()->glyph, &glyph)) {
92 FT_Set_Pixel_Sizes(GetFaceRec(), 0, 64);
93 return false;
94 }
95 FT_BBox cbox;
96 FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
97 int32_t x_ppem = GetFaceRec()->size->metrics.x_ppem;
98 int32_t y_ppem = GetFaceRec()->size->metrics.y_ppem;
99 rtBBox.left = static_cast<int32_t>(FPF_EM_ADJUST(x_ppem, cbox.xMin));
100 rtBBox.right = static_cast<int32_t>(FPF_EM_ADJUST(x_ppem, cbox.xMax));
101 rtBBox.top = static_cast<int32_t>(FPF_EM_ADJUST(y_ppem, cbox.yMax));
102 rtBBox.bottom = static_cast<int32_t>(FPF_EM_ADJUST(y_ppem, cbox.yMin));
103 rtBBox.top = std::min(rtBBox.top, GetAscent());
104 rtBBox.bottom = std::max(rtBBox.bottom, GetDescent());
105 FT_Done_Glyph(glyph);
106 return FT_Set_Pixel_Sizes(GetFaceRec(), 0, 64) == 0;
107 }
108 if (FT_Load_Glyph(GetFaceRec(), iGlyphIndex,
109 FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
110 return false;
111 }
112 rtBBox.left = static_cast<int32_t>(
113 FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
114 FXFT_Get_Glyph_HoriBearingX(GetFaceRec())));
115 rtBBox.bottom = static_cast<int32_t>(
116 FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
117 FXFT_Get_Glyph_HoriBearingY(GetFaceRec())));
118 rtBBox.right = static_cast<int32_t>(
119 FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
120 FXFT_Get_Glyph_HoriBearingX(GetFaceRec()) +
121 FXFT_Get_Glyph_Width(GetFaceRec())));
122 rtBBox.top = static_cast<int32_t>(
123 FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
124 FXFT_Get_Glyph_HoriBearingY(GetFaceRec()) -
125 FXFT_Get_Glyph_Height(GetFaceRec())));
126 return true;
127 }
128
GetBBox(FX_RECT & rtBBox)129 bool CFPF_SkiaFont::GetBBox(FX_RECT& rtBBox) {
130 if (!m_Face) {
131 return false;
132 }
133 rtBBox.left =
134 static_cast<int32_t>(FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
135 FXFT_Get_Face_xMin(GetFaceRec())));
136 rtBBox.top =
137 static_cast<int32_t>(FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
138 FXFT_Get_Face_yMin(GetFaceRec())));
139 rtBBox.right =
140 static_cast<int32_t>(FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
141 FXFT_Get_Face_xMax(GetFaceRec())));
142 rtBBox.bottom =
143 static_cast<int32_t>(FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
144 FXFT_Get_Face_yMax(GetFaceRec())));
145 return true;
146 }
147
GetHeight() const148 int32_t CFPF_SkiaFont::GetHeight() const {
149 if (!m_Face)
150 return 0;
151 return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
152 FXFT_Get_Face_Height(GetFaceRec()));
153 }
154
GetItalicAngle() const155 int32_t CFPF_SkiaFont::GetItalicAngle() const {
156 if (!m_Face)
157 return 0;
158
159 auto* info = static_cast<TT_Postscript*>(
160 FT_Get_Sfnt_Table(GetFaceRec(), ft_sfnt_post));
161 return info ? static_cast<int32_t>(info->italicAngle) : 0;
162 }
163
GetFontData(uint32_t dwTable,pdfium::span<uint8_t> pBuffer)164 uint32_t CFPF_SkiaFont::GetFontData(uint32_t dwTable,
165 pdfium::span<uint8_t> pBuffer) {
166 if (!m_Face)
167 return 0;
168
169 FT_ULong ulSize = pdfium::base::checked_cast<FT_ULong>(pBuffer.size());
170 if (FT_Load_Sfnt_Table(GetFaceRec(), dwTable, 0, pBuffer.data(), &ulSize))
171 return 0;
172 return pdfium::base::checked_cast<uint32_t>(ulSize);
173 }
174