From d36d5c88aa7ca35235ac5251dc213bdd3b21919c Mon Sep 17 00:00:00 2001 From: James Bursa Date: Mon, 17 Jul 2006 03:24:53 +0000 Subject: Implement rufl_font_bbox (interface to Font_ReadInfo). svn path=/trunk/rufl/; revision=2772 --- rufl.h | 9 +++ rufl_paint.c | 197 ++++++++++++++++++++++++++++++++++++++++------------------- rufl_test.c | 4 ++ 3 files changed, 146 insertions(+), 64 deletions(-) diff --git a/rufl.h b/rufl.h index 7af35f3..b2a8d1f 100644 --- a/rufl.h +++ b/rufl.h @@ -125,6 +125,15 @@ rufl_code rufl_paint_callback(const char *font_family, rufl_style font_style, rufl_callback_t callback, void *context); +/** + * Determine the maximum bounding box of a font. + */ + +rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, + unsigned int font_size, + int *bbox); + + /** * Dump the internal library state to stdout. */ diff --git a/rufl_paint.c b/rufl_paint.c index 3236e9e..024db42 100644 --- a/rufl_paint.c +++ b/rufl_paint.c @@ -15,7 +15,7 @@ typedef enum { rufl_PAINT, rufl_WIDTH, rufl_X_TO_OFFSET, - rufl_SPLIT, rufl_PAINT_CALLBACK } rufl_action; + rufl_SPLIT, rufl_PAINT_CALLBACK, rufl_FONT_BBOX } rufl_action; #define rufl_PROCESS_CHUNK 200 bool rufl_can_background_blend = false; @@ -31,6 +31,8 @@ static rufl_code rufl_process(rufl_action action, int x, int y, unsigned int flags, int *width, int click_x, size_t *char_offset, int *actual_x, rufl_callback_t callback, void *context); +static bool rufl_find_font(const char *font_family, rufl_style font_style, + unsigned int *font_index, unsigned int *slanted); static int rufl_family_list_cmp(const void *keyval, const void *datum); static rufl_code rufl_process_span(rufl_action action, unsigned short *s, unsigned int n, @@ -51,6 +53,7 @@ static rufl_code rufl_process_not_available(rufl_action action, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context); +static font_f rufl_search_cache(unsigned int font, unsigned int font_size); static rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size, font_f f); @@ -136,6 +139,20 @@ rufl_code rufl_paint_callback(const char *font_family, rufl_style font_style, } +/** + * Determine the maximum bounding box of a font. + */ + +rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, + unsigned int font_size, + int *bbox) +{ + return rufl_process(rufl_FONT_BBOX, + font_family, font_style, font_size, 0, + 0, 0, 0, 0, bbox, 0, 0, 0, 0, 0); +} + + /** * Render, measure, or split Unicode text. */ @@ -156,9 +173,7 @@ rufl_code rufl_process(rufl_action action, size_t offset; size_t offset_u; size_t offset_map[rufl_PROCESS_CHUNK]; - char **family; - unsigned int weight, slant, used_weight; - unsigned int search_direction; + unsigned int slant; const char *string = string0; struct rufl_character_set *charset; rufl_code code; @@ -169,7 +184,8 @@ rufl_code rufl_process(rufl_action action, actual_x) || (action == rufl_SPLIT && char_offset && actual_x) || - (action == rufl_PAINT_CALLBACK && callback)); + (action == rufl_PAINT_CALLBACK && callback) || + (action == rufl_FONT_BBOX && width)); if ((flags & rufl_BLEND_FONT) && !rufl_can_background_blend) { /* unsuitable FM => clear blending bit */ @@ -192,45 +208,19 @@ rufl_code rufl_process(rufl_action action, return rufl_OK; } - family = bsearch(font_family, rufl_family_list, - rufl_family_list_entries, - sizeof rufl_family_list[0], rufl_family_list_cmp); - if (!family) + if (!rufl_find_font(font_family, font_style, &font, &slant)) return rufl_FONT_NOT_FOUND; - weight = (font_style & 0xf) - 1; - assert(weight <= 8); - slant = font_style & rufl_SLANTED ? 1 : 0; - struct rufl_family_map_entry *e = - &rufl_family_map[family - rufl_family_list]; - used_weight = weight; - if (weight <= 2) - search_direction = -1; - else - search_direction = +1; - while (1) { - if (e->font[used_weight][slant] != NO_FONT) { - /* the weight and slant is available */ - font = e->font[used_weight][slant]; - break; - } - if (e->font[used_weight][1 - slant] != NO_FONT) { - /* slanted, and non-slanted weight exists, or vv. */ - font = e->font[used_weight][1 - slant]; - break; - } - if (used_weight == 0) { - /* searched down without finding a weight: search up */ - used_weight = weight + 1; - search_direction = +1; - } else if (used_weight == 8) { - /* searched up without finding a weight: search down */ - used_weight = weight - 1; - search_direction = -1; - } else { - /* try the next weight in the current direction */ - used_weight += search_direction; - } + if (action == rufl_FONT_BBOX) { + if (rufl_old_font_manager) + code = rufl_process_span_old(action, 0, 0, font, + font_size, slant, width, 0, 0, + 0, 0, 0, 0); + else + code = rufl_process_span(action, 0, 0, font, + font_size, slant, width, 0, 0, + 0, 0, 0, 0); + return code; } charset = rufl_font_list[font].charset; @@ -306,6 +296,65 @@ rufl_code rufl_process(rufl_action action, } +/** + * Determine the index in rufl_font_list for a font family and style. + */ + +bool rufl_find_font(const char *font_family, rufl_style font_style, + unsigned int *font_index, unsigned int *slanted) +{ + char **family; + unsigned int font, weight, slant, used_weight; + unsigned int search_direction; + + family = bsearch(font_family, rufl_family_list, + rufl_family_list_entries, + sizeof rufl_family_list[0], rufl_family_list_cmp); + if (!family) + return false; + weight = (font_style & 0xf) - 1; + assert(weight <= 8); + slant = font_style & rufl_SLANTED ? 1 : 0; + + struct rufl_family_map_entry *e = + &rufl_family_map[family - rufl_family_list]; + used_weight = weight; + if (weight <= 2) + search_direction = -1; + else + search_direction = +1; + while (1) { + if (e->font[used_weight][slant] != NO_FONT) { + /* the weight and slant is available */ + font = e->font[used_weight][slant]; + break; + } + if (e->font[used_weight][1 - slant] != NO_FONT) { + /* slanted, and non-slanted weight exists, or vv. */ + font = e->font[used_weight][1 - slant]; + break; + } + if (used_weight == 0) { + /* searched down without finding a weight: search up */ + used_weight = weight + 1; + search_direction = +1; + } else if (used_weight == 8) { + /* searched up without finding a weight: search down */ + used_weight = weight - 1; + search_direction = -1; + } else { + /* try the next weight in the current direction */ + used_weight += search_direction; + } + } + + *font_index = font; + *slanted = slant; + + return true; +} + + int rufl_family_list_cmp(const void *keyval, const void *datum) { const char *key = keyval; @@ -334,17 +383,8 @@ rufl_code rufl_process_span(rufl_action action, rufl_code code; /* search cache */ - for (i = 0; i != rufl_CACHE_SIZE; i++) { - if (rufl_cache[i].font == font && - rufl_cache[i].size == font_size) - break; - } - if (i != rufl_CACHE_SIZE) { - /* found in cache */ - f = rufl_cache[i].f; - rufl_cache[i].last_used = rufl_cache_time++; - } else { - /* not found */ + f = rufl_search_cache(font, font_size); + if (!f) { snprintf(font_name, sizeof font_name, "%s\\EUTF8", rufl_font_list[font].identifier); rufl_fm_error = xfont_find_font(font_name, @@ -361,6 +401,13 @@ rufl_code rufl_process_span(rufl_action action, return code; } + if (action == rufl_FONT_BBOX) { + rufl_fm_error = xfont_read_info(f, &x[0], &x[1], &x[2], &x[3]); + if (rufl_fm_error) + return rufl_FONT_MANAGER_ERROR; + return rufl_OK; + } + if (action == rufl_PAINT) { /* paint span */ rufl_fm_error = xfont_paint(f, (const char *) s, @@ -440,17 +487,8 @@ rufl_code rufl_process_span_old(rufl_action action, struct rufl_unicode_map_entry *entry; /* search cache */ - for (i = 0; i != rufl_CACHE_SIZE; i++) { - if (rufl_cache[i].font == font && - rufl_cache[i].size == font_size) - break; - } - if (i != rufl_CACHE_SIZE) { - /* found in cache */ - f = rufl_cache[i].f; - rufl_cache[i].last_used = rufl_cache_time++; - } else { - /* not found */ + f = rufl_search_cache(font, font_size); + if (!f) { rufl_fm_error = xfont_find_font(font_name, font_size, font_size, 0, 0, &f, 0, 0); if (rufl_fm_error) @@ -461,6 +499,13 @@ rufl_code rufl_process_span_old(rufl_action action, return code; } + if (action == rufl_FONT_BBOX) { + rufl_fm_error = xfont_read_info(f, &x[0], &x[1], &x[2], &x[3]); + if (rufl_fm_error) + return rufl_FONT_MANAGER_ERROR; + return rufl_OK; + } + /* convert Unicode string into character string */ for (i = 0; i != n; i++) { entry = bsearch(&s[i], rufl_font_list[font].umap->map, @@ -625,6 +670,30 @@ rufl_code rufl_process_not_available(rufl_action action, } +/** + * Find a font in the recent-use cache. + */ + +font_f rufl_search_cache(unsigned int font, unsigned int font_size) +{ + unsigned int i; + + for (i = 0; i != rufl_CACHE_SIZE; i++) { + if (rufl_cache[i].font == font && + rufl_cache[i].size == font_size) + break; + } + if (i != rufl_CACHE_SIZE) { + /* found in cache */ + rufl_cache[i].last_used = rufl_cache_time++; + return rufl_cache[i].f; + } else { + /* not found */ + return 0; + } +} + + /** * Place a font into the recent-use cache, making space if necessary. */ diff --git a/rufl_test.c b/rufl_test.c index ad536a7..843db1f 100644 --- a/rufl_test.c +++ b/rufl_test.c @@ -26,6 +26,7 @@ int main(void) size_t char_offset; int x; int actual_x; + int bbox[4]; try(rufl_init(), "rufl_init"); rufl_dump_state(); @@ -53,6 +54,9 @@ int main(void) try(rufl_paint_callback("NewHall", rufl_WEIGHT_400, 240, utf8_test, sizeof utf8_test - 1, 1200, 1000, callback, 0), "rufl_paint_callback"); + try(rufl_font_bbox("NewHall", rufl_WEIGHT_400, 240, bbox), + "rufl_font_bbox"); + printf("bbox: %i %i %i %i\n", bbox[0], bbox[1], bbox[2], bbox[3]); rufl_quit(); return 0; -- cgit v1.2.3