3 #include <fontconfig/fontconfig.h>
14 #include <freetype/ftglyph.h>
21 #include "font_freetype.h"
23 #ifndef HAVE_LOOKUP_SCALER
24 #if FREETYPE_MAJOR * 10000 + FREETYPE_MINOR * 100 + FREETYPE_PATCH > 20304
25 #define HAVE_LOOKUP_SCALER 1
27 #define HAVE_LOOJUP_SCALER 0
31 struct font_freetype_font {
34 #if HAVE_LOOKUP_SCALER
37 FTC_ImageTypeRec scaler;
48 static struct font_priv dummy;
49 static FT_Library library;
51 static FTC_Manager manager;
52 static FTC_ImageCache image_cache;
53 static FTC_CMapCache charmap_cache;
54 static FTC_SBitCache sbit_cache;
56 static int library_init;
60 font_freetype_get_text_bbox(struct graphics_priv *gr,
61 struct font_freetype_font *font, char *text,
62 int dx, int dy, struct point *ret,
86 int n, len, x = 0, y = 0;
88 len = g_utf8_strlen(text, -1);
92 bbox.yMax = 13*font->size/256;
93 bbox.xMax = 9*font->size*len/256;
95 bbox.xMin = bbox.yMin = 32000;
96 bbox.xMax = bbox.yMax = -32000;
98 FT_Set_Transform(font->face, &matrix, &pen);
100 for (n = 0; n < len; n++) {
103 FTC_Node anode = NULL;
104 glyph_index = FTC_CMapCache_Lookup(charmap_cache, font->scaler.face_id, font->charmap_index, g_utf8_get_char(p));
105 FT_Glyph cached_glyph;
106 #if HAVE_LOOKUP_SCALER
107 FTC_ImageCache_LookupScaler(image_cache, &font->scaler, FT_LOAD_DEFAULT, glyph_index, &cached_glyph, &anode);
109 FTC_ImageCache_Lookup(image_cache, &font->scaler, glyph_index, &cached_glyph, &anode);
111 FT_Glyph_Copy(cached_glyph, &glyph);
112 FT_Glyph_Transform(glyph, &matrix, &pen);
114 glyph_index = FT_Get_Char_Index(font->face, g_utf8_get_char(p));
115 FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT);
116 FT_Get_Glyph(font->face->glyph, &glyph);
118 FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox);
120 glyph_bbox.xMin += x >> 6;
121 glyph_bbox.xMax += x >> 6;
122 glyph_bbox.yMin += y >> 6;
123 glyph_bbox.yMax += y >> 6;
124 x += glyph->advance.x >> 10;
125 y -= glyph->advance.y >> 10;
126 if (glyph_bbox.xMin < bbox.xMin)
127 bbox.xMin = glyph_bbox.xMin;
128 if (glyph_bbox.yMin < bbox.yMin)
129 bbox.yMin = glyph_bbox.yMin;
130 if (glyph_bbox.xMax > bbox.xMax)
131 bbox.xMax = glyph_bbox.xMax;
132 if (glyph_bbox.yMax > bbox.yMax)
133 bbox.yMax = glyph_bbox.yMax;
134 p = g_utf8_next_char(p);
136 FT_Done_Glyph(glyph);
137 FTC_Node_Unref(anode, manager);
139 FT_Done_Glyph(glyph);
142 if (bbox.xMin > bbox.xMax) {
149 ret[0].x = bbox.xMin;
150 ret[0].y = -bbox.yMin;
151 ret[1].x = bbox.xMin;
152 ret[1].y = -bbox.yMax;
153 ret[2].x = bbox.xMax;
154 ret[2].y = -bbox.yMax;
155 ret[3].x = bbox.xMax;
156 ret[3].y = -bbox.yMin;
157 if (dy != 0 || dx != 0x10000) {
158 for (i = 0 ; i < 4 ; i++) {
160 ret[i].x=(pt.x*dx-pt.y*dy)/0x10000;
161 ret[i].y=(pt.y*dx+pt.x*dy)/0x10000;
166 static struct font_freetype_text *
167 font_freetype_text_new(char *text, struct font_freetype_font *font, int dx,
173 int y, n, len, w, h, pixmap_len;
174 struct font_freetype_text *ret;
175 struct font_freetype_glyph *curr;
177 unsigned char *gl, *pm;
178 FT_BitmapGlyph glyph_bitmap;
181 len = g_utf8_strlen(text, -1);
182 ret = g_malloc(sizeof(*ret) + len * sizeof(struct text_glyph *));
183 ret->glyph_count = len;
193 FT_Set_Transform(font->face, &matrix, &pen);
196 for (n = 0; n < len; n++) {
200 FT_Glyph cached_glyph;
201 glyph_index = FTC_CMapCache_Lookup(charmap_cache, font->scaler.face_id, font->charmap_index, g_utf8_get_char(p));
202 #if HAVE_LOOKUP_SCALER
203 FTC_ImageCache_LookupScaler(image_cache, &font->scaler, FT_LOAD_DEFAULT, glyph_index, &cached_glyph, &anode);
205 FTC_ImageCache_Lookup(image_cache, &font->scaler, glyph_index, &cached_glyph, &anode);
207 FT_Glyph_Copy(cached_glyph, &glyph);
208 FT_Glyph_Transform(glyph, &matrix, &pen);
209 FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, NULL, TRUE);
211 glyph_index = FT_Get_Char_Index(font->face, g_utf8_get_char(p));
212 FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT);
213 FT_Get_Glyph(font->face->glyph, &glyph);
215 FT_Glyph_To_Bitmap(&glyph, ft_render_mode_normal, NULL, TRUE);
216 glyph_bitmap = (FT_BitmapGlyph)glyph;
218 w = glyph_bitmap->bitmap.width;
219 h = glyph_bitmap->bitmap.rows;
221 pixmap_len = (w + 2) * (h + 2);
224 curr = g_malloc0(sizeof(*curr) + pixmap_len);
229 curr->pixmap = (unsigned char *) (curr + 1);
230 ret->glyph[n] = curr;
232 curr->x = glyph_bitmap->left << 6;
233 curr->y = -glyph_bitmap->top << 6;
234 for (y = 0; y < h; y++) {
235 gl = glyph_bitmap->bitmap.buffer + y * glyph_bitmap->bitmap.pitch;
236 pm = curr->pixmap + y * w;
240 curr->dx = glyph->advance.x >> 10;
241 curr->dy = -glyph->advance.y >> 10;
243 FT_Done_Glyph(glyph);
244 FTC_Node_Unref(anode, manager);
246 p = g_utf8_next_char(p);
248 ret->glyph_count = len;
253 * List of font families to use, in order of preference
255 static char *fontfamilies[] = {
266 font_destroy(struct graphics_font_priv *font)
269 /* TODO: free font->face */
272 static struct graphics_font_methods font_methods = {
278 font_freetype_text_destroy(struct font_freetype_text *text)
281 struct font_freetype_glyph **gp;
284 i = text->glyph_count;
291 static FT_Error face_requester( FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face* aface )
294 char *fontfile,*fontindex;
296 return FT_Err_Invalid_Handle;
297 fontfile=g_strdup((char *)face_id);
298 dbg(1,"fontfile=%s\n", fontfile);
299 fontindex=strrchr(fontfile,'/');
302 return FT_Err_Invalid_Handle;
305 dbg(1,"new face %s %d\n", fontfile, atoi(fontindex));
306 ret = FT_New_Face( library, fontfile, atoi(fontindex), aface );
308 dbg(0,"Error while creating freetype face: %d\n", ret);
311 if((ret = FT_Select_Charmap(*aface, FT_ENCODING_UNICODE))) {
312 dbg(0,"Error while creating freetype face: %d\n", ret);
319 * Load a new font using the fontconfig library.
320 * First search for each of the font families and require and exact match on family
321 * If no font found, let fontconfig pick the best match
322 * @param graphics_priv FIXME
323 * @param graphics_font_methods FIXME
324 * @param fontfamily the preferred font family
325 * @param size requested size of fonts
326 * @param flags extra flags for the font (bold,etc)
329 static struct font_freetype_font *
330 font_freetype_font_new(struct graphics_priv *gr,
331 struct graphics_font_methods *meth,
332 char *fontfamily, int size, int flags)
334 struct font_freetype_font *font =
335 g_new(struct font_freetype_font, 1);
337 *meth = font_methods;
339 char **family, **family_sav;
344 #ifndef HAVE_FONTCONFIG
349 FT_Init_FreeType(&library);
351 FTC_Manager_New( library, 0, 0, 0, &face_requester, NULL, &manager);
352 FTC_ImageCache_New( manager, &image_cache);
353 FTC_CMapCache_New( manager, &charmap_cache);
354 FTC_SBitCache_New( manager, &sbit_cache);
359 #ifdef HAVE_FONTCONFIG
360 dbg(2, " about to search for fonts, prefered = %s\n", fontfamily);
361 family = g_malloc(sizeof(fontfamilies) + sizeof(fontfamily));
363 memcpy(family, &fontfamily, sizeof(fontfamily));
364 memcpy(family + 1, fontfamilies, sizeof(fontfamilies));
366 memcpy(family, fontfamilies, sizeof(fontfamilies));
369 for (exact = 1; !found && exact >= 0; exact--) {
373 while (*family && !found) {
374 dbg(2, "Looking for font family %s. exact=%d\n",
376 FcPattern *required =
377 FcPatternBuild(NULL, FC_FAMILY, FcTypeString,
380 FcPatternAddInteger(required, FC_WEIGHT,
382 FcConfigSubstitute(FcConfigGetCurrent(), required,
384 FcDefaultSubstitute(required);
387 FcFontMatch(FcConfigGetCurrent(), required,
393 FcPatternGet(required, FC_FAMILY, 0, &v1);
394 FcPatternGet(matched, FC_FAMILY, 0, &v2);
396 FcPatternGetString(matched, FC_FILE, 0,
399 FcPatternGetInteger(matched, FC_INDEX,
401 if ((r1 == FcResultMatch)
402 && (r2 == FcResultMatch)
403 && (FcValueEqual(v1, v2) || !exact)) {
405 "About to load font from file %s index %d\n",
406 fontfile, fontindex);
408 idstr=g_strdup_printf("%s/%d", fontfile, fontindex);
409 font->scaler.face_id=(FTC_FaceID)atom(idstr);
411 #if HAVE_LOOKUP_SCALER
412 font->scaler.width=0;
413 font->scaler.height=size;
414 font->scaler.pixel=0;
415 font->scaler.x_res=300;
416 font->scaler.y_res=300;
418 font->scaler.width=size/15;
419 font->scaler.height=size/15;
420 font->scaler.flags=FT_LOAD_DEFAULT;
422 FTC_Manager_LookupFace(manager, font->scaler.face_id, &face);
423 font->charmap_index=face->charmap ? FT_Get_Charmap_Index(face->charmap) : 0;
432 FcPatternDestroy(matched);
434 FcPatternDestroy(required);
440 name=g_strdup_printf("%s/fonts/%s-%s.ttf",getenv("NAVIT_SHAREDIR"),"LiberationSans",flags ? "Bold":"Regular");
442 idstr=g_strdup_printf("%s/%d", name, 0);
443 font->scaler.face_id=(FTC_FaceID)atom(idstr);
445 #if HAVE_LOOKUP_SCALER
446 font->scaler.width=0;
447 font->scaler.height=size;
448 font->scaler.pixel=0;
449 font->scaler.x_res=300;
450 font->scaler.y_res=300;
452 font->scaler.width=size/15;
453 font->scaler.height=size/15;
454 font->scaler.flags=FT_LOAD_DEFAULT;
458 if (!FT_New_Face(library, name, 0, &font->face))
464 dbg(0,"Failed to load font, no labelling\n");
469 FT_Set_Char_Size(font->face, 0, size, 300, 300);
470 FT_Select_Charmap(font->face, FT_ENCODING_UNICODE);
476 font_freetype_glyph_get_shadow(struct font_freetype_glyph *g,
477 unsigned char *data, int depth, int stride, struct color *foreground, struct color *background)
479 int mask0, mask1, mask2, x, y, w = g->w, h = g->h;
481 unsigned char *pm, *psp,*ps,*psn;
493 fg=((foreground->a>>8)<<24)|
494 ((foreground->r>>8)<<16)|
495 ((foreground->g>>8)<<8)|
496 ((foreground->b>>8)<<0);
497 bg=((background->a>>8)<<24)|
498 ((background->r>>8)<<16)|
499 ((background->g>>8)<<8)|
500 ((background->b>>8)<<0);
505 for (y = 0; y < h+2; y++) {
507 ps = data + stride * y;
509 unsigned char **dataptr=(unsigned char **)data;
514 memset(ps, bg, (w+9)/2);
520 for (x = 0 ; x < w+2 ; x++) {
527 for (x = 0 ; x < w+2 ; x++)
528 ((unsigned int *)ps)[x]=bg;
532 for (y = 0; y < h; y++) {
533 pm = g->pixmap + y * w;
535 psp = data + stride * y;
539 unsigned char **dataptr=(unsigned char **)data;
549 for (x = 0; x < w; x++) {
551 psp[0] |= (mask0 >> 8);
554 ps[0] |= (mask1 >> 8);
557 psn[0] |= (mask2 >> 8);
565 ((mask0 >> 8) | (mask1 >> 8) |
578 for (x = 0; x < w; x++) {
593 for (x = 0; x < w; x++) {
618 for (x = 0; x < w; x++) {
620 ((unsigned int *)psp)[1]=fg;
621 ((unsigned int *)ps)[0]=fg;
622 ((unsigned int *)ps)[1]=fg;
623 ((unsigned int *)ps)[2]=fg;
624 ((unsigned int *)psn)[1]=fg;
638 font_freetype_glyph_get_glyph(struct font_freetype_glyph *g,
639 unsigned char *data, int depth, int stride, struct color *fg, struct color *bg, struct color *transparent)
641 int x, y, w = g->w, h = g->h;
643 unsigned char v,vi,*pm, *ps;
646 tr=transparent->a>>8;
650 tr=((transparent->a>>8)<<24)|
651 ((transparent->r>>8)<<16)|
652 ((transparent->g>>8)<<8)|
653 ((transparent->b>>8)<<0);
658 for (y = 0; y < h; y++) {
659 pm = g->pixmap + y * w;
661 ps = data + stride*y;
663 unsigned char **dataptr=(unsigned char **)data;
668 for (x = 0; x < w; x++) {
679 for (x = 0; x < w; x++) {
683 ps[0]=(((fg->r*v+bg->r*vi)/255)>>8);
684 ps[1]=(((fg->g*v+bg->g*vi)/255)>>8);
685 ps[2]=(((fg->b*v+bg->b*vi)/255)>>8);
696 for (x = 0; x < w; x++) {
700 ((unsigned int *)ps)[0]=
701 ((((fg->a*v+bg->a*vi)/255)>>8)<<24)|
702 ((((fg->r*v+bg->r*vi)/255)>>8)<<16)|
703 ((((fg->g*v+bg->g*vi)/255)>>8)<<8)|
704 ((((fg->b*v+bg->b*vi)/255)>>8)<<0);
706 ((unsigned int *)ps)[0]=tr;
716 static struct font_freetype_methods methods = {
717 font_freetype_font_new,
718 font_freetype_get_text_bbox,
719 font_freetype_text_new,
720 font_freetype_text_destroy,
721 font_freetype_glyph_get_shadow,
722 font_freetype_glyph_get_glyph,
725 static struct font_priv *
726 font_freetype_new(void *meth)
728 *((struct font_freetype_methods *) meth) = methods;
735 plugin_register_font_type("freetype", font_freetype_new);
736 #ifdef HAVE_FONTCONFIG