Cleanup CFX_Font a bit.
[pdfium.git] / core / src / fxge / ge / fx_ge_font.cpp
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 "../../../include/fxge/fx_ge.h"
8 #include "../../../include/fxge/fx_freetype.h"
9 #include "text_int.h"
10 #define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em)
11 extern void _FPDFAPI_GetInternalFontData(int id1,
12                                          const uint8_t*& data,
13                                          FX_DWORD& size);
14 CFX_Font::CFX_Font() {
15   m_pSubstFont = NULL;
16   m_Face = NULL;
17   m_bEmbedded = FALSE;
18   m_bVertical = FALSE;
19   m_pFontData = NULL;
20   m_pFontDataAllocation = NULL;
21   m_dwSize = 0;
22   m_pGsubData = NULL;
23   m_pPlatformFont = NULL;
24   m_pPlatformFontCollection = NULL;
25   m_pDwFont = NULL;
26   m_hHandle = NULL;
27   m_bDwLoaded = FALSE;
28 }
29 CFX_Font::~CFX_Font() {
30   delete m_pSubstFont;
31   m_pSubstFont = NULL;
32   FX_Free(m_pFontDataAllocation);
33   m_pFontDataAllocation = NULL;
34   if (m_Face) {
35     if (FXFT_Get_Face_External_Stream(m_Face)) {
36       FXFT_Clear_Face_External_Stream(m_Face);
37     }
38     if (m_bEmbedded) {
39       DeleteFace();
40     } else {
41       CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face);
42     }
43   }
44   FX_Free(m_pGsubData);
45   m_pGsubData = NULL;
46 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
47   ReleasePlatformResource();
48 #endif
49 }
50 void CFX_Font::DeleteFace() {
51   FXFT_Done_Face(m_Face);
52   m_Face = NULL;
53 }
54 FX_BOOL CFX_Font::LoadSubst(const CFX_ByteString& face_name,
55                             FX_BOOL bTrueType,
56                             FX_DWORD flags,
57                             int weight,
58                             int italic_angle,
59                             int CharsetCP,
60                             FX_BOOL bVertical) {
61   m_bEmbedded = FALSE;
62   m_bVertical = bVertical;
63   m_pSubstFont = new CFX_SubstFont;
64   m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont(
65       face_name, bTrueType, flags, weight, italic_angle, CharsetCP,
66       m_pSubstFont);
67 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
68   if (m_pSubstFont->m_ExtHandle) {
69     m_pPlatformFont = m_pSubstFont->m_ExtHandle;
70     m_pSubstFont->m_ExtHandle = NULL;
71   }
72 #endif
73   if (m_Face) {
74     m_pFontData = FXFT_Get_Face_Stream_Base(m_Face);
75     m_dwSize = FXFT_Get_Face_Stream_Size(m_Face);
76   }
77   return TRUE;
78 }
79
80 int CFX_Font::GetGlyphWidth(FX_DWORD glyph_index) {
81   if (!m_Face) {
82     return 0;
83   }
84   if (m_pSubstFont && (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM)) {
85     AdjustMMParams(glyph_index, 0, 0);
86   }
87   int err = FXFT_Load_Glyph(
88       m_Face, glyph_index,
89       FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
90   if (err) {
91     return 0;
92   }
93   int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
94                         FXFT_Get_Glyph_HoriAdvance(m_Face));
95   return width;
96 }
97 static FXFT_Face FT_LoadFont(uint8_t* pData, int size) {
98   FXFT_Library library;
99   if (CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary == NULL) {
100     FXFT_Init_FreeType(&CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary);
101   }
102   library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary;
103   FXFT_Face face = NULL;
104   int error = FXFT_New_Memory_Face(library, pData, size, 0, &face);
105   if (error) {
106     return NULL;
107   }
108   error = FXFT_Set_Pixel_Sizes(face, 64, 64);
109   if (error) {
110     return NULL;
111   }
112   return face;
113 }
114 FX_BOOL CFX_Font::LoadEmbedded(const uint8_t* data, FX_DWORD size) {
115   m_pFontDataAllocation = FX_Alloc(uint8_t, size);
116   FXSYS_memcpy(m_pFontDataAllocation, data, size);
117   m_Face = FT_LoadFont((uint8_t*)m_pFontDataAllocation, size);
118   m_pFontData = (uint8_t*)m_pFontDataAllocation;
119   m_bEmbedded = TRUE;
120   m_dwSize = size;
121   return m_Face != NULL;
122 }
123
124 FX_BOOL CFX_Font::IsTTFont() const {
125   if (!m_Face)
126     return FALSE;
127   return FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT;
128 }
129
130 int CFX_Font::GetAscent() const {
131   if (!m_Face)
132     return 0;
133   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
134                    FXFT_Get_Face_Ascender(m_Face));
135 }
136
137 int CFX_Font::GetDescent() const {
138   if (!m_Face)
139     return 0;
140   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
141                    FXFT_Get_Face_Descender(m_Face));
142 }
143
144 FX_BOOL CFX_Font::GetGlyphBBox(FX_DWORD glyph_index, FX_RECT& bbox) {
145   if (!m_Face)
146     return FALSE;
147
148   if (FXFT_Is_Face_Tricky(m_Face)) {
149     int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72);
150     if (error) {
151       return FALSE;
152     }
153     error = FXFT_Load_Glyph(m_Face, glyph_index,
154                             FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
155     if (error) {
156       return FALSE;
157     }
158     FXFT_BBox cbox;
159     FT_Glyph glyph;
160     error = FXFT_Get_Glyph(((FXFT_Face)m_Face)->glyph, &glyph);
161     if (error) {
162       return FALSE;
163     }
164     FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox);
165     int pixel_size_x = ((FXFT_Face)m_Face)->size->metrics.x_ppem,
166         pixel_size_y = ((FXFT_Face)m_Face)->size->metrics.y_ppem;
167     if (pixel_size_x == 0 || pixel_size_y == 0) {
168       bbox.left = cbox.xMin;
169       bbox.right = cbox.xMax;
170       bbox.top = cbox.yMax;
171       bbox.bottom = cbox.yMin;
172     } else {
173       bbox.left = cbox.xMin * 1000 / pixel_size_x;
174       bbox.right = cbox.xMax * 1000 / pixel_size_x;
175       bbox.top = cbox.yMax * 1000 / pixel_size_y;
176       bbox.bottom = cbox.yMin * 1000 / pixel_size_y;
177     }
178     if (bbox.top > FXFT_Get_Face_Ascender(m_Face)) {
179       bbox.top = FXFT_Get_Face_Ascender(m_Face);
180     }
181     if (bbox.bottom < FXFT_Get_Face_Descender(m_Face)) {
182       bbox.bottom = FXFT_Get_Face_Descender(m_Face);
183     }
184     FT_Done_Glyph(glyph);
185     return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0;
186   }
187   if (FXFT_Load_Glyph(
188           m_Face, glyph_index,
189           FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
190     return FALSE;
191   }
192   int em = FXFT_Get_Face_UnitsPerEM(m_Face);
193   if (em == 0) {
194     bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face);
195     bbox.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face);
196     bbox.top = bbox.bottom - FXFT_Get_Glyph_Height(m_Face);
197     bbox.right = bbox.left + FXFT_Get_Glyph_Width(m_Face);
198   } else {
199     bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face) * 1000 / em;
200     bbox.top =
201         (FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face)) *
202         1000 / em;
203     bbox.right =
204         (FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face)) *
205         1000 / em;
206     bbox.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face)) * 1000 / em;
207   }
208   return TRUE;
209 }
210
211 FX_BOOL CFX_Font::IsItalic() const {
212   if (!m_Face)
213     return FALSE;
214
215   FX_BOOL ret = FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC;
216   if (!ret) {
217     CFX_ByteString str(FXFT_Get_Face_Style_Name(m_Face));
218     str.MakeLower();
219     if (str.Find("italic") != -1) {
220       ret = TRUE;
221     }
222   }
223   return ret;
224 }
225
226 FX_BOOL CFX_Font::IsBold() const {
227   if (!m_Face)
228     return FALSE;
229   return FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD;
230 }
231
232 FX_BOOL CFX_Font::IsFixedWidth() const {
233   if (!m_Face)
234     return FALSE;
235   return FXFT_Is_Face_fixedwidth(m_Face);
236 }
237
238 CFX_WideString CFX_Font::GetPsName() const {
239   if (m_Face == NULL) {
240     return CFX_WideString();
241   }
242   CFX_WideString psName =
243       CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(m_Face));
244   if (psName.IsEmpty()) {
245     psName = CFX_WideString::FromLocal("Untitled");
246   }
247   return psName;
248 }
249 CFX_ByteString CFX_Font::GetFamilyName() const {
250   if (m_Face == NULL && m_pSubstFont == NULL) {
251     return CFX_ByteString();
252   }
253   if (m_Face) {
254     return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face));
255   }
256   return m_pSubstFont->m_Family;
257 }
258 CFX_ByteString CFX_Font::GetFaceName() const {
259   if (m_Face == NULL && m_pSubstFont == NULL) {
260     return CFX_ByteString();
261   }
262   if (m_Face) {
263     CFX_ByteString facename;
264     CFX_ByteString style = CFX_ByteString(FXFT_Get_Face_Style_Name(m_Face));
265     facename = GetFamilyName();
266     if (facename.IsEmpty()) {
267       facename = "Untitled";
268     }
269     if (!style.IsEmpty() && style != "Regular") {
270       facename += " " + style;
271     }
272     return facename;
273   }
274   return m_pSubstFont->m_Family;
275 }
276 FX_BOOL CFX_Font::GetBBox(FX_RECT& bbox) {
277   if (m_Face == NULL) {
278     return FALSE;
279   }
280   int em = FXFT_Get_Face_UnitsPerEM(m_Face);
281   if (em == 0) {
282     bbox.left = FXFT_Get_Face_xMin(m_Face);
283     bbox.bottom = FXFT_Get_Face_yMax(m_Face);
284     bbox.top = FXFT_Get_Face_yMin(m_Face);
285     bbox.right = FXFT_Get_Face_xMax(m_Face);
286   } else {
287     bbox.left = FXFT_Get_Face_xMin(m_Face) * 1000 / em;
288     bbox.top = FXFT_Get_Face_yMin(m_Face) * 1000 / em;
289     bbox.right = FXFT_Get_Face_xMax(m_Face) * 1000 / em;
290     bbox.bottom = FXFT_Get_Face_yMax(m_Face) * 1000 / em;
291   }
292   return TRUE;
293 }
294
295 int CFX_Font::GetHeight() const {
296   if (!m_Face)
297     return 0;
298
299   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
300                    FXFT_Get_Face_Height(m_Face));
301 }
302
303 int CFX_Font::GetMaxAdvanceWidth() const {
304   if (!m_Face)
305     return 0;
306
307   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
308                    FXFT_Get_Face_MaxAdvanceWidth(m_Face));
309 }
310
311 int CFX_Font::GetULPos() const {
312   if (!m_Face)
313     return 0;
314
315   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
316                    FXFT_Get_Face_UnderLinePosition(m_Face));
317 }
318
319 int CFX_Font::GetULthickness() const {
320   if (!m_Face)
321     return 0;
322
323   return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
324                    FXFT_Get_Face_UnderLineThickness(m_Face));
325 }
326
327 CFX_UnicodeEncoding::CFX_UnicodeEncoding(CFX_Font* pFont) : m_pFont(pFont) {
328 }
329
330 CFX_UnicodeEncoding::~CFX_UnicodeEncoding() {
331 }
332
333 FX_DWORD CFX_UnicodeEncoding::GlyphFromCharCode(FX_DWORD charcode) {
334   FXFT_Face face = m_pFont->GetFace();
335   if (!face)
336     return charcode;
337
338   if (FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE) == 0)
339     return FXFT_Get_Char_Index(face, charcode);
340
341   if (m_pFont->GetSubstFont() && m_pFont->GetSubstFont()->m_Charset == 2) {
342     FX_DWORD index = 0;
343     if (FXFT_Select_Charmap(face, FXFT_ENCODING_MS_SYMBOL) == 0)
344       index = FXFT_Get_Char_Index(face, charcode);
345     if (!index && !FXFT_Select_Charmap(face, FXFT_ENCODING_APPLE_ROMAN))
346       return FXFT_Get_Char_Index(face, charcode);
347   }
348   return charcode;
349 }