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