1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
23 #include "../../config.h"
24 #include "core/GP_Debug.h"
25 #include "text/GP_Font.h"
30 #include FT_FREETYPE_H
32 GP_FontFace
*GP_FontFaceLoad(const char *path
, uint32_t width
, uint32_t height
)
38 err
= FT_Init_FreeType(&library
);
41 GP_DEBUG(1, "Failed to initalize Free Type");
45 err
= FT_New_Face(library
, path
, 0, &face
);
48 //TODO: FT_Exit_FreeType() ?
49 GP_DEBUG(1, "Failed to open font '%s'", path
);
53 GP_DEBUG(1, "Opened font '%s'", path
);
54 GP_DEBUG(2, "Font family_name='%s' style_name='%s' num_glyphs=%li",
55 face
->family_name
, face
->style_name
,
56 (long)face
->num_glyphs
);
57 GP_DEBUG(2, "Font ascender=%i descender=%i height=%i",
58 (int)face
->ascender
, (int)face
->descender
, (int)face
->height
);
60 //TODO: not scalable fonts?
61 err
= FT_Set_Pixel_Sizes(face
, width
, height
);
64 GP_DEBUG(1, "Failed to set pixel size");
68 /* Allocate font face structure */
69 unsigned int font_face_size
;
71 font_face_size
= sizeof(GP_FontFace
) +
72 sizeof(uint32_t) * GP_GetGlyphCount(GP_CHARSET_7BIT
);
74 GP_FontFace
*font
= malloc(font_face_size
);
77 GP_DEBUG(1, "Malloc failed :(");
81 /* Copy font metadata */
82 strncpy(font
->family_name
, face
->family_name
,
83 sizeof(font
->family_name
));
84 font
->family_name
[GP_FONT_NAME_MAX
- 1] = '\0';
85 strncpy(font
->style_name
, face
->style_name
,
86 sizeof(font
->style_name
));
87 font
->style_name
[GP_FONT_NAME_MAX
- 1] = '\0';
89 font
->glyph_bitmap_format
= GP_FONT_BITMAP_8BPP
;
90 font
->charset
= GP_CHARSET_7BIT
;
92 /* Count glyph data size */
94 unsigned int glyph_table_size
= 0;
96 for (i
= 0x20; i
< 0x7f; i
++) {
97 FT_UInt glyph_idx
= FT_Get_Char_Index(face
, i
);
99 err
= FT_Load_Glyph(face
, glyph_idx
, FT_LOAD_DEFAULT
);
102 GP_DEBUG(1, "Failed to load glyph '%c'", i
);
106 err
= FT_Render_Glyph(face
->glyph
, FT_RENDER_MODE_NORMAL
);
109 GP_DEBUG(1, "Failed to render glyph '%c'", i
);
113 FT_Bitmap
*bitmap
= &face
->glyph
->bitmap
;
115 GP_DEBUG(2, "Glyph '%c' bitmap rows=%i width=%i pitch=%i",
116 i
, bitmap
->rows
, bitmap
->width
, bitmap
->pitch
);
118 GP_DEBUG(2, " bitmap top=%i left=%i",
119 face
->glyph
->bitmap_top
, face
->glyph
->bitmap_left
);
121 /* count glyph table size and fill offset table */
122 font
->glyph_offsets
[i
- 0x20] = glyph_table_size
;
123 glyph_table_size
+= sizeof(GP_GlyphBitmap
) +
124 bitmap
->rows
* bitmap
->pitch
;
127 GP_DEBUG(2, "Glyph table size %u bytes", glyph_table_size
);
129 font
->glyphs
= malloc(glyph_table_size
);
131 if (font
->glyphs
== NULL
) {
132 GP_DEBUG(1, "Malloc failed :(");
136 font
->max_glyph_width
= 0;
137 font
->max_glyph_advance
= 0;
141 for (i
= 0x20; i
< 0x7f; i
++) {
142 FT_UInt glyph_idx
= FT_Get_Char_Index(face
, i
);
144 err
= FT_Load_Glyph(face
, glyph_idx
, FT_LOAD_DEFAULT
);
146 GP_DEBUG(2, "Loading and rendering glyph '%c'", i
);
149 GP_DEBUG(1, "Failed to load glyph '%c'", i
);
153 err
= FT_Render_Glyph(face
->glyph
, FT_RENDER_MODE_NORMAL
);
156 GP_DEBUG(1, "Failed to render glyph '%c'", i
);
160 GP_GlyphBitmap
*glyph_bitmap
= GP_GetGlyphBitmap(font
, i
);
161 FT_GlyphSlot glyph
= face
->glyph
;
163 glyph_bitmap
->width
= glyph
->bitmap
.width
;
164 glyph_bitmap
->height
= glyph
->bitmap
.rows
;
165 glyph_bitmap
->bearing_x
= glyph
->bitmap_left
;
166 glyph_bitmap
->bearing_y
= glyph
->bitmap_top
;
167 glyph_bitmap
->advance_x
= (glyph
->advance
.x
+ 32)>>6;
169 int16_t width
= glyph_bitmap
->bearing_x
+ glyph_bitmap
->width
;
170 int16_t ascend
= glyph_bitmap
->bearing_y
;
171 int16_t descend
= glyph_bitmap
->height
- ascend
;
173 if (font
->ascend
< ascend
)
174 font
->ascend
= ascend
;
176 if (font
->descend
< descend
)
177 font
->descend
= descend
;
179 if (font
->max_glyph_advance
< glyph_bitmap
->advance_x
)
180 font
->max_glyph_advance
= glyph_bitmap
->advance_x
;
182 if (font
->max_glyph_width
< width
)
183 font
->max_glyph_width
= width
;
187 for (y
= 0; y
< glyph_bitmap
->height
; y
++) {
188 for (x
= 0; x
< glyph_bitmap
->width
; x
++) {
189 unsigned int addr
= glyph_bitmap
->width
* y
+ x
;
191 glyph_bitmap
->bitmap
[addr
] = glyph
->bitmap
.buffer
[y
* glyph
->bitmap
.pitch
+ x
];
202 //TODO FREETYPE CLEANUP
208 GP_FontFace
*GP_FontFaceLoad(const char *path
, uint32_t width
, uint32_t height
)
214 GP_WARN("FreeType support not compiled in.");
219 #endif /* HAVE_FREETYPE */