Revert "FX Bool considered harmful, part 3"
[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, const uint8_t*& data, FX_DWORD& size);
12 CFX_Font::CFX_Font()
13 {
14     m_pSubstFont = NULL;
15     m_Face = NULL;
16     m_bEmbedded = FALSE;
17     m_bVertical = FALSE;
18     m_pFontData = NULL;
19     m_pFontDataAllocation = NULL;
20     m_dwSize = 0;
21     m_pOwnedStream = NULL;
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 {
31     delete m_pSubstFont;
32     m_pSubstFont = NULL;
33     if (m_pFontDataAllocation) {
34         FX_Free(m_pFontDataAllocation);
35         m_pFontDataAllocation = NULL;
36     }
37     if (m_Face) {
38         if (FXFT_Get_Face_External_Stream(m_Face)) {
39             FXFT_Clear_Face_External_Stream(m_Face);
40         }
41         if(m_bEmbedded) {
42             DeleteFace();
43         } else {
44             CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face);
45         }
46     }
47     if (m_pOwnedStream) {
48         FX_Free(m_pOwnedStream);
49         m_pOwnedStream = NULL;
50     }
51     if (m_pGsubData) {
52         FX_Free(m_pGsubData);
53         m_pGsubData = NULL;
54     }
55 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_
56     ReleasePlatformResource();
57 #endif
58 }
59 void CFX_Font::DeleteFace()
60 {
61     FXFT_Done_Face(m_Face);
62     m_Face = NULL;
63 }
64 FX_BOOL CFX_Font::LoadSubst(const CFX_ByteString& face_name, FX_BOOL bTrueType, FX_DWORD flags,
65                             int weight, int italic_angle, int CharsetCP, FX_BOOL bVertical)
66 {
67     m_bEmbedded = FALSE;
68     m_bVertical = bVertical;
69     m_pSubstFont = new CFX_SubstFont;
70     m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle,
71              CharsetCP, m_pSubstFont);
72 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_
73     if(m_pSubstFont->m_ExtHandle) {
74         m_pPlatformFont = m_pSubstFont->m_ExtHandle;
75         m_pSubstFont->m_ExtHandle = NULL;
76     }
77 #endif
78     if (m_Face) {
79         m_pFontData = FXFT_Get_Face_Stream_Base(m_Face);
80         m_dwSize = FXFT_Get_Face_Stream_Size(m_Face);
81     }
82     return TRUE;
83 }
84 extern "C" {
85     unsigned long _FTStreamRead(FXFT_Stream stream, unsigned long offset,
86                                 unsigned char* buffer, unsigned long count)
87     {
88         if (count == 0) {
89             return 0;
90         }
91         IFX_FileRead* pFile = (IFX_FileRead*)stream->descriptor.pointer;
92         int res = pFile->ReadBlock(buffer, offset, count);
93         if (res) {
94             return count;
95         }
96         return 0;
97     }
98     void _FTStreamClose(FXFT_Stream stream)
99     {
100     }
101 };
102 FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream)
103 {
104     FXFT_Stream stream1 = (FXFT_Stream)FX_Alloc(uint8_t, sizeof (FXFT_StreamRec));
105     stream1->base = NULL;
106     stream1->size = (unsigned long)pFile->GetSize();
107     stream1->pos = 0;
108     stream1->descriptor.pointer = pFile;
109     stream1->close = _FTStreamClose;
110     stream1->read = _FTStreamRead;
111     FXFT_Open_Args args;
112     args.flags = FT_OPEN_STREAM;
113     args.stream = stream1;
114     if (FXFT_Open_Face(library, &args, 0, Face)) {
115         FX_Free(stream1);
116         return FALSE;
117     }
118     if (stream) {
119         *stream = stream1;
120     }
121     return TRUE;
122 }
123 FX_BOOL CFX_Font::LoadFile(IFX_FileRead* pFile)
124 {
125     m_bEmbedded = FALSE;
126     FXFT_Library library;
127     if (CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary == NULL) {
128         FXFT_Init_FreeType(&CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary);
129     }
130     library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary;
131     FXFT_Stream stream = NULL;
132     if (!_LoadFile(library, &m_Face, pFile, &stream)) {
133         return FALSE;
134     }
135     m_pOwnedStream = stream;
136     FXFT_Set_Pixel_Sizes(m_Face, 0, 64);
137     return TRUE;
138 }
139 int CFX_Font::GetGlyphWidth(FX_DWORD glyph_index)
140 {
141     if (!m_Face) {
142         return 0;
143     }
144     if (m_pSubstFont && (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM)) {
145         AdjustMMParams(glyph_index, 0, 0);
146     }
147     int err = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
148     if (err) {
149         return 0;
150     }
151     int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Glyph_HoriAdvance(m_Face));
152     return width;
153 }
154 static FXFT_Face FT_LoadFont(uint8_t* pData, int size)
155 {
156     FXFT_Library library;
157     if (CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary == NULL) {
158         FXFT_Init_FreeType(&CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary);
159     }
160     library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary;
161     FXFT_Face face = NULL;
162     int error = FXFT_New_Memory_Face(library, pData, size, 0, &face);
163     if (error) {
164         return NULL;
165     }
166     error = FXFT_Set_Pixel_Sizes(face, 64, 64);
167     if (error) {
168         return NULL;
169     }
170     return face;
171 }
172 FX_BOOL CFX_Font::LoadEmbedded(const uint8_t* data, FX_DWORD size)
173 {
174     m_pFontDataAllocation = FX_Alloc(uint8_t, size);
175     FXSYS_memcpy(m_pFontDataAllocation, data, size);
176     m_Face = FT_LoadFont((uint8_t*)m_pFontDataAllocation, size);
177     m_pFontData = (uint8_t*)m_pFontDataAllocation;
178     m_bEmbedded = TRUE;
179     m_dwSize = size;
180     return m_Face != NULL;
181 }
182 FX_BOOL CFX_Font::IsTTFont()
183 {
184     if (m_Face == NULL) {
185         return FALSE;
186     }
187     return FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT;
188 }
189 int CFX_Font::GetAscent() const
190 {
191     if (m_Face == NULL) {
192         return 0;
193     }
194     int ascent = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Ascender(m_Face));
195     return ascent;
196 }
197 int CFX_Font::GetDescent() const
198 {
199     if (m_Face == NULL) {
200         return 0;
201     }
202     int descent = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Descender(m_Face));
203     return descent;
204 }
205 FX_BOOL CFX_Font::GetGlyphBBox(FX_DWORD glyph_index, FX_RECT &bbox)
206 {
207     if (m_Face == NULL) {
208         return FALSE;
209     }
210     if (FXFT_Is_Face_Tricky(m_Face)) {
211         int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72);
212         if (error) {
213             return FALSE;
214         }
215         error = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
216         if (error) {
217             return FALSE;
218         }
219         FXFT_BBox cbox;
220         FT_Glyph glyph;
221         error = FXFT_Get_Glyph(((FXFT_Face)m_Face)->glyph, &glyph);
222         if (error) {
223             return FALSE;
224         }
225         FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox);
226         int pixel_size_x = ((FXFT_Face)m_Face)->size->metrics.x_ppem,
227             pixel_size_y = ((FXFT_Face)m_Face)->size->metrics.y_ppem;
228         if (pixel_size_x == 0 || pixel_size_y == 0) {
229             bbox.left = cbox.xMin;
230             bbox.right = cbox.xMax;
231             bbox.top = cbox.yMax;
232             bbox.bottom = cbox.yMin;
233         } else {
234             bbox.left = cbox.xMin * 1000 / pixel_size_x;
235             bbox.right = cbox.xMax * 1000 / pixel_size_x;
236             bbox.top = cbox.yMax * 1000 / pixel_size_y;
237             bbox.bottom = cbox.yMin * 1000 / pixel_size_y;
238         }
239         if (bbox.top > FXFT_Get_Face_Ascender(m_Face)) {
240             bbox.top = FXFT_Get_Face_Ascender(m_Face);
241         }
242         if (bbox.bottom < FXFT_Get_Face_Descender(m_Face)) {
243             bbox.bottom = FXFT_Get_Face_Descender(m_Face);
244         }
245         FT_Done_Glyph(glyph);
246         return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0;
247     }
248     if (FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
249         return FALSE;
250     }
251     int em = FXFT_Get_Face_UnitsPerEM(m_Face);
252     if (em == 0) {
253         bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face);
254         bbox.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face);
255         bbox.top = bbox.bottom - FXFT_Get_Glyph_Height(m_Face);
256         bbox.right = bbox.left + FXFT_Get_Glyph_Width(m_Face);
257     } else {
258         bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face) * 1000 / em;
259         bbox.top = (FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face)) * 1000 / em;
260         bbox.right = (FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face)) * 1000 / em;
261         bbox.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face)) * 1000 / em;
262     }
263     return TRUE;
264 }
265 FX_BOOL CFX_Font::IsItalic()
266 {
267     if (m_Face == NULL) {
268         return FALSE;
269     }
270     FX_BOOL ret = FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC;
271     if (!ret) {
272         CFX_ByteString str(FXFT_Get_Face_Style_Name(m_Face));
273         str.MakeLower();
274         if (str.Find("italic") != -1) {
275             ret = TRUE;
276         }
277     }
278     return ret;
279 }
280 FX_BOOL CFX_Font::IsBold()
281 {
282     if (m_Face == NULL) {
283         return FALSE;
284     }
285     return FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD;
286 }
287 FX_BOOL CFX_Font::IsFixedWidth()
288 {
289     if (m_Face == NULL) {
290         return FALSE;
291     }
292     return FXFT_Is_Face_fixedwidth(m_Face);
293 }
294 CFX_WideString CFX_Font::GetPsName() const
295 {
296     if (m_Face == NULL) {
297         return CFX_WideString();
298     }
299     CFX_WideString psName = CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(m_Face));
300     if (psName.IsEmpty()) {
301         psName =  CFX_WideString::FromLocal("Untitled");
302     }
303     return psName;
304 }
305 CFX_ByteString CFX_Font::GetFamilyName() const
306 {
307     if (m_Face == NULL && m_pSubstFont == NULL) {
308         return CFX_ByteString();
309     }
310     if (m_Face) {
311         return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face));
312     }
313     return m_pSubstFont->m_Family;
314 }
315 CFX_ByteString CFX_Font::GetFaceName() const
316 {
317     if (m_Face == NULL && m_pSubstFont == NULL) {
318         return CFX_ByteString();
319     }
320     if (m_Face) {
321         CFX_ByteString facename;
322         CFX_ByteString style = CFX_ByteString(FXFT_Get_Face_Style_Name(m_Face));
323         facename = GetFamilyName();
324         if (facename.IsEmpty()) {
325             facename = "Untitled";
326         }
327         if (!style.IsEmpty() && style != "Regular") {
328             facename += " " + style;
329         }
330         return facename;
331     }
332     return m_pSubstFont->m_Family;
333 }
334 FX_BOOL CFX_Font::GetBBox(FX_RECT &bbox)
335 {
336     if (m_Face == NULL) {
337         return FALSE;
338     }
339     int em = FXFT_Get_Face_UnitsPerEM(m_Face);
340     if (em == 0) {
341         bbox.left = FXFT_Get_Face_xMin(m_Face);
342         bbox.bottom = FXFT_Get_Face_yMax(m_Face);
343         bbox.top = FXFT_Get_Face_yMin(m_Face);
344         bbox.right = FXFT_Get_Face_xMax(m_Face);
345     } else {
346         bbox.left = FXFT_Get_Face_xMin(m_Face) * 1000 / em;
347         bbox.top = FXFT_Get_Face_yMin(m_Face) * 1000 / em;
348         bbox.right = FXFT_Get_Face_xMax(m_Face) * 1000 / em;
349         bbox.bottom = FXFT_Get_Face_yMax(m_Face) * 1000 / em;
350     }
351     return TRUE;
352 }
353 int CFX_Font::GetHeight()
354 {
355     if (m_Face == NULL) {
356         return 0;
357     }
358     int height = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Height(m_Face));
359     return height;
360 }
361 int CFX_Font::GetMaxAdvanceWidth()
362 {
363     if (m_Face == NULL) {
364         return 0;
365     }
366     int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_MaxAdvanceWidth(m_Face));
367     return width;
368 }
369 int CFX_Font::GetULPos()
370 {
371     if (m_Face == NULL) {
372         return 0;
373     }
374     int pos = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_UnderLinePosition(m_Face));
375     return pos;
376 }
377 int CFX_Font::GetULthickness()
378 {
379     if (m_Face == NULL) {
380         return 0;
381     }
382     int thickness = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_UnderLineThickness(m_Face));
383     return thickness;
384 }
385 CFX_UnicodeEncoding::CFX_UnicodeEncoding(CFX_Font* pFont)
386 {
387     m_pFont = pFont;
388 }
389 FX_DWORD CFX_UnicodeEncoding::GlyphFromCharCode(FX_DWORD charcode)
390 {
391     FXFT_Face face =  m_pFont->GetFace();
392     if (!face) {
393         return charcode;
394     }
395     if (FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE) == 0) {
396         return FXFT_Get_Char_Index(face, charcode);
397     }
398     if (m_pFont->m_pSubstFont && m_pFont->m_pSubstFont->m_Charset == 2) {
399         FX_DWORD index = 0;
400         if (FXFT_Select_Charmap(face, FXFT_ENCODING_MS_SYMBOL) == 0) {
401             index = FXFT_Get_Char_Index(face, charcode);
402         }
403         if (!index && !FXFT_Select_Charmap(face, FXFT_ENCODING_APPLE_ROMAN)) {
404             return FXFT_Get_Char_Index(face, charcode);
405         }
406     }
407     return charcode;
408 }
409 FX_DWORD CFX_UnicodeEncoding::GlyphFromCharCodeEx(FX_DWORD charcode, int encoding)
410 {
411     FXFT_Face face = m_pFont->GetFace();
412     if (!face) {
413         return charcode;
414     }
415     if (encoding == ENCODING_UNICODE) {
416         return GlyphFromCharCode(charcode);
417     }
418     int nmaps = FXFT_Get_Face_CharmapCount(m_pFont->m_Face);
419     int i = 0;
420     while (i < nmaps) {
421         int encoding = FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i++]);
422         if (encoding != FXFT_ENCODING_UNICODE) {
423             FXFT_Select_Charmap(face, encoding);
424             break;
425         }
426     }
427     return FXFT_Get_Char_Index(face, charcode);
428 }
429 IFX_FontEncoding* FXGE_CreateUnicodeEncoding(CFX_Font* pFont)
430 {
431     return new CFX_UnicodeEncoding(pFont);
432 }