diff --git a/src/lib/font.h b/src/lib/font.h index cf8630e..d281d97 100644 --- a/src/lib/font.h +++ b/src/lib/font.h @@ -1,3 +1,6 @@ +#ifndef FONT_H +#define FONT_H + #include #include FT_FREETYPE_H #include FT_GLYPH_H @@ -31,6 +34,8 @@ typedef struct { FT_BitmapGlyph glyph_out; } Imlib_Font_Glyph; +#define IMLIB_GLYPH_NONE ((Imlib_Font_Glyph*) 1) /* Glyph not found */ + /* functions */ void __imlib_font_init(void); @@ -39,7 +44,6 @@ int __imlib_font_descent_get(ImlibFont * fn); int __imlib_font_max_ascent_get(ImlibFont * fn); int __imlib_font_max_descent_get(ImlibFont * fn); int __imlib_font_get_line_advance(ImlibFont * fn); -int __imlib_font_utf8_get_next(unsigned char *buf, int *iindex); void __imlib_font_add_font_path(const char *path); void __imlib_font_del_font_path(const char *path); int __imlib_font_path_exists(const char *path); @@ -59,8 +63,6 @@ void __imlib_font_modify_cache_by(ImlibFont * fn, int dir); void __imlib_font_modify_cache_by(ImlibFont * fn, int dir); void __imlib_font_flush_last(void); ImlibFont *__imlib_font_find(const char *name, int size); -ImlibFont *__imlib_font_find_glyph(ImlibFont * fn, int gl, - unsigned int *ret_index); void __imlib_font_query_size(ImlibFont * fn, const char *text, int *w, int *h); @@ -77,6 +79,10 @@ int __imlib_font_query_text_at_pos(ImlibFont * fn, int *cx, int *cy, int *cw, int *ch); +Imlib_Font_Glyph *__imlib_font_get_next_glyph(ImlibFont * fn, + const char *utf8, + int *cindx, + FT_UInt * pindex, int *pkern); Imlib_Font_Glyph *__imlib_font_cache_glyph_get(ImlibFont * fn, FT_UInt index); void __imlib_render_str(ImlibImage * im, ImlibFont * f, int drx, int dry, const char *text, @@ -88,3 +94,5 @@ void __imlib_font_draw(ImlibImage * dst, DATA32 col, ImlibFont * fn, int x, int y, const char *text, int *nextx, int *nexty, int clx, int cly, int clw, int clh); + +#endif /* FONT_H */ diff --git a/src/lib/font_draw.c b/src/lib/font_draw.c index d0326fe..b344447 100644 --- a/src/lib/font_draw.c +++ b/src/lib/font_draw.c @@ -244,45 +244,13 @@ __imlib_render_str(ImlibImage * im, ImlibFont * fn, int drx, int dry, /* TODO this function is purely my art -- check once more */ } -/* - * This function returns the first font in the fallback chain to contain - * the requested glyph. - * The glyph index is returned in ret_index - * If the glyph is not found, then the given font pointer is returned and - * ret_index will be set to 0 - */ -ImlibFont * -__imlib_font_find_glyph(ImlibFont * first_fn, int gl, unsigned int *ret_index) -{ - ImlibFont *fn = first_fn; - - do - { - int index = FT_Get_Char_Index(fn->ft.face, gl); - - if (index <= 0) - fn = fn->fallback_next; - else - { - (*ret_index) = index; - return fn; - } - } - while (fn); - - (*ret_index) = 0; - return first_fn; -} - void __imlib_font_draw(ImlibImage * dst, DATA32 col, ImlibFont * fn, int x, int y, const char *text, int *nextx, int *nexty, int clx, int cly, int clw, int clh) { - int use_kerning; int pen_x, pen_y; int chr; - FT_UInt prev_index; int ext_x, ext_y, ext_w, ext_h; DATA32 *im; int im_w, im_h; @@ -333,30 +301,17 @@ __imlib_font_draw(ImlibImage * dst, DATA32 col, ImlibFont * fn, int x, int y, pen_x = x << 8; pen_y = y << 8; - use_kerning = FT_HAS_KERNING(fn->ft.face); - prev_index = 0; for (chr = 0; text[chr];) { FT_UInt index; Imlib_Font_Glyph *fg; - ImlibFont *fn_in_chain; - int chr_x, chr_y; - int gl; + int chr_x, chr_y, kern; - gl = __imlib_font_utf8_get_next((unsigned char *)text, &chr); - if (gl == 0) - break; - fn_in_chain = __imlib_font_find_glyph(fn, gl, &index); - if ((use_kerning) && (prev_index) && (index)) - { - FT_Vector delta; - - FT_Get_Kerning(fn_in_chain->ft.face, prev_index, index, - ft_kerning_default, &delta); - pen_x += delta.x << 2; - } - fg = __imlib_font_cache_glyph_get(fn_in_chain, index); + fg = __imlib_font_get_next_glyph(fn, text, &chr, &index, &kern); if (!fg) + break; + pen_x += kern; + if (fg == IMLIB_GLYPH_NONE) continue; chr_x = (pen_x + (fg->glyph_out->left << 8)) >> 8; @@ -442,7 +397,6 @@ __imlib_font_draw(ImlibImage * dst, DATA32 col, ImlibFont * fn, int x, int y, else break; pen_x += fg->glyph->advance.x >> 8; - prev_index = index; } if (nextx) diff --git a/src/lib/font_main.c b/src/lib/font_main.c index e5ae648..7c823ac 100644 --- a/src/lib/font_main.c +++ b/src/lib/font_main.c @@ -106,15 +106,17 @@ __imlib_font_get_line_advance(ImlibFont * fn) return ret; } -int -__imlib_font_utf8_get_next(unsigned char *buf, int *iindex) +/* + * Reads UTF8 bytes from @text, starting at *@index and returns the code + * point of the next valid code point. @index is updated ready for the + * next call. + * + * Returns 0 to indicate an error (e.g. invalid UTF8) + */ +static int +_utf8_get_next(const char *text, int *iindex) { - /* Reads UTF8 bytes from @buf, starting at *@index and returns the code - * point of the next valid code point. @index is updated ready for the - * next call. - * - * * Returns 0 to indicate an error (e.g. invalid UTF8) */ - + const unsigned char *buf = (const unsigned char *)text; int index = *iindex, r; unsigned char d = buf[index++], d2, d3, d4; @@ -168,3 +170,65 @@ __imlib_font_utf8_get_next(unsigned char *buf, int *iindex) *iindex = index; return r; } + +/* + * This function returns the first font in the fallback chain to contain + * the requested glyph. + * The glyph index is returned in ret_index + * If the glyph is not found, then the given font pointer is returned and + * ret_index will be set to 0 + */ +static ImlibFont * +__imlib_font_find_glyph(ImlibFont * first_fn, int gl, unsigned int *ret_index) +{ + int index; + ImlibFont *fn = first_fn; + + for (; fn; fn = fn->fallback_next) + { + index = FT_Get_Char_Index(fn->ft.face, gl); + if (index <= 0) + continue; + *ret_index = index; + return fn; + } + + *ret_index = 0; + return first_fn; +} + +Imlib_Font_Glyph * +__imlib_font_get_next_glyph(ImlibFont * fn, const char *utf8, int *cindx, + FT_UInt * pindex, int *pkern) +{ + FT_UInt index; + Imlib_Font_Glyph *fg; + ImlibFont *fn_in_chain; + int gl, kern; + + gl = _utf8_get_next(utf8, cindx); + if (gl == 0) + return NULL; + + fn_in_chain = __imlib_font_find_glyph(fn, gl, &index); + + kern = 0; + if (FT_HAS_KERNING(fn->ft.face) && *pindex && index) + { + FT_Vector delta; + + FT_Get_Kerning(fn_in_chain->ft.face, *pindex, index, + ft_kerning_default, &delta); + kern = delta.x << 2; + } + if (pkern) + *pkern = kern; + + fg = __imlib_font_cache_glyph_get(fn_in_chain, index); + if (!fg) + return IMLIB_GLYPH_NONE; + + *pindex = index; + + return fg; +} diff --git a/src/lib/font_query.c b/src/lib/font_query.c index daede27..a67f62b 100644 --- a/src/lib/font_query.c +++ b/src/lib/font_query.c @@ -21,40 +21,25 @@ extern FT_Library ft_lib; void __imlib_font_query_size(ImlibFont * fn, const char *text, int *w, int *h) { - int use_kerning; int pen_x /*, pen_y */ ; int start_x, end_x; int chr; - FT_UInt prev_index; start_x = 0; end_x = 0; pen_x = 0; /* pen_y = 0; */ - use_kerning = FT_HAS_KERNING(fn->ft.face); - prev_index = 0; for (chr = 0; text[chr];) { FT_UInt index; Imlib_Font_Glyph *fg; - ImlibFont *fn_in_chain; - int chr_x, /*chr_y, */ chr_w; - int gl; + int chr_x, /*chr_y, */ chr_w, kern; - gl = __imlib_font_utf8_get_next((unsigned char *)text, &chr); - if (gl == 0) - break; - fn_in_chain = __imlib_font_find_glyph(fn, gl, &index); - if ((use_kerning) && (prev_index) && (index)) - { - FT_Vector delta; - - FT_Get_Kerning(fn_in_chain->ft.face, prev_index, index, - ft_kerning_default, &delta); - pen_x += delta.x << 2; - } - fg = __imlib_font_cache_glyph_get(fn_in_chain, index); + fg = __imlib_font_get_next_glyph(fn, text, &chr, &index, &kern); if (!fg) + break; + pen_x += kern; + if (fg == IMLIB_GLYPH_NONE) continue; chr_x = (pen_x >> 8) + fg->glyph_out->left; @@ -67,7 +52,6 @@ __imlib_font_query_size(ImlibFont * fn, const char *text, int *w, int *h) end_x = chr_x + chr_w; pen_x += fg->glyph->advance.x >> 8; - prev_index = index; } if (w) *w = (pen_x >> 8) - start_x; @@ -81,20 +65,16 @@ __imlib_font_query_inset(ImlibFont * fn, const char *text) { FT_UInt index; Imlib_Font_Glyph *fg; - ImlibFont *fn_in_chain; int chr; - int gl; chr = 0; if (!text[0]) return 0; - gl = __imlib_font_utf8_get_next((unsigned char *)text, &chr); - if (gl == 0) - return 0; - fn_in_chain = __imlib_font_find_glyph(fn, gl, &index); - fg = __imlib_font_cache_glyph_get(fn_in_chain, index); - if (!fg) + + fg = __imlib_font_get_next_glyph(fn, text, &chr, &index, NULL); + if (!fg || fg == IMLIB_GLYPH_NONE) return 0; + return -fg->glyph_out->left; } @@ -103,41 +83,26 @@ void __imlib_font_query_advance(ImlibFont * fn, const char *text, int *h_adv, int *v_adv) { - int use_kerning; int pen_x; int start_x; int chr; - FT_UInt prev_index; start_x = 0; pen_x = 0; - use_kerning = FT_HAS_KERNING(fn->ft.face); - prev_index = 0; for (chr = 0; text[chr];) { FT_UInt index; Imlib_Font_Glyph *fg; - ImlibFont *fn_in_chain; - int gl; + int kern; - gl = __imlib_font_utf8_get_next((unsigned char *)text, &chr); - if (gl == 0) - break; - fn_in_chain = __imlib_font_find_glyph(fn, gl, &index); - if ((use_kerning) && (prev_index) && (index)) - { - FT_Vector delta; - - FT_Get_Kerning(fn_in_chain->ft.face, prev_index, index, - ft_kerning_default, &delta); - pen_x += delta.x << 2; - } - fg = __imlib_font_cache_glyph_get(fn_in_chain, index); + fg = __imlib_font_get_next_glyph(fn, text, &chr, &index, &kern); if (!fg) + break; + pen_x += kern; + if (fg == IMLIB_GLYPH_NONE) continue; pen_x += fg->glyph->advance.x >> 8; - prev_index = index; } if (v_adv) *v_adv = __imlib_font_get_line_advance(fn); /* TODO: compute this in the loop since we may be dealing with multiple fonts */ @@ -150,16 +115,12 @@ int __imlib_font_query_char_coords(ImlibFont * fn, const char *text, int pos, int *cx, int *cy, int *cw, int *ch) { - int use_kerning; int pen_x; int prev_chr_end; int chr; int asc, desc; - FT_UInt prev_index; pen_x = 0; - use_kerning = FT_HAS_KERNING(fn->ft.face); - prev_index = 0; prev_chr_end = 0; asc = __imlib_font_max_ascent_get(fn); desc = __imlib_font_max_descent_get(fn); @@ -168,26 +129,14 @@ __imlib_font_query_char_coords(ImlibFont * fn, const char *text, int pos, int pchr; FT_UInt index; Imlib_Font_Glyph *fg; - ImlibFont *fn_in_chain; - int chr_x, chr_w; - int gl, kern; - FT_Vector delta; + int chr_x, chr_w, kern; pchr = chr; - gl = __imlib_font_utf8_get_next((unsigned char *)text, &chr); - if (gl == 0) - break; - fn_in_chain = __imlib_font_find_glyph(fn, gl, &index); - kern = 0; - if ((use_kerning) && (prev_index) && (index)) - { - FT_Get_Kerning(fn_in_chain->ft.face, prev_index, index, - ft_kerning_default, &delta); - kern = delta.x << 2; - pen_x += kern; - } - fg = __imlib_font_cache_glyph_get(fn_in_chain, index); + fg = __imlib_font_get_next_glyph(fn, text, &chr, &index, &kern); if (!fg) + break; + pen_x += kern; + if (fg == IMLIB_GLYPH_NONE) continue; if (kern < 0) @@ -221,7 +170,6 @@ __imlib_font_query_char_coords(ImlibFont * fn, const char *text, int pos, } prev_chr_end = chr_x + chr_w; pen_x += fg->glyph->advance.x >> 8; - prev_index = index; } return 0; } @@ -231,16 +179,12 @@ int __imlib_font_query_text_at_pos(ImlibFont * fn, const char *text, int x, int y, int *cx, int *cy, int *cw, int *ch) { - int use_kerning; int pen_x; int prev_chr_end; int chr; int asc, desc; - FT_UInt prev_index; pen_x = 0; - use_kerning = FT_HAS_KERNING(fn->ft.face); - prev_index = 0; prev_chr_end = 0; asc = __imlib_font_max_ascent_get(fn); desc = __imlib_font_max_descent_get(fn); @@ -249,26 +193,14 @@ __imlib_font_query_text_at_pos(ImlibFont * fn, const char *text, int x, int y, int pchr; FT_UInt index; Imlib_Font_Glyph *fg; - ImlibFont *fn_in_chain; - int chr_x, chr_w; - int gl, kern; - FT_Vector delta; + int chr_x, chr_w, kern; pchr = chr; - gl = __imlib_font_utf8_get_next((unsigned char *)text, &chr); - if (gl == 0) - break; - fn_in_chain = __imlib_font_find_glyph(fn, gl, &index); - kern = 0; - if ((use_kerning) && (prev_index) && (index)) - { - FT_Get_Kerning(fn_in_chain->ft.face, prev_index, index, - ft_kerning_default, &delta); - kern = delta.x << 2; - pen_x += kern; - } - fg = __imlib_font_cache_glyph_get(fn_in_chain, index); + fg = __imlib_font_get_next_glyph(fn, text, &chr, &index, &kern); if (!fg) + break; + pen_x += kern; + if (fg == IMLIB_GLYPH_NONE) continue; if (kern < 0) @@ -302,7 +234,6 @@ __imlib_font_query_text_at_pos(ImlibFont * fn, const char *text, int x, int y, } prev_chr_end = chr_x + chr_w; pen_x += fg->glyph->advance.x >> 8; - prev_index = index; } return -1; }