From 87d2b7aa8e9b6e2209776a73da67398c795cbcb3 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sun, 29 Jan 2006 12:20:25 +0000 Subject: [project @ 2006-01-29 12:20:25 by bursa] Improve handling of font weights. Now detects available weights better and supports up to 9 weights. Ignore control characters and spaces that are not spaces when scanning available characters. svn path=/import/rufl/; revision=2470 --- rufl_paint.c | 145 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 82 insertions(+), 63 deletions(-) (limited to 'rufl_paint.c') diff --git a/rufl_paint.c b/rufl_paint.c index 37ed75b..28144e1 100644 --- a/rufl_paint.c +++ b/rufl_paint.c @@ -2,7 +2,7 @@ * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license - * Copyright 2005 James Bursa + * Copyright 2006 James Bursa */ #include @@ -20,32 +20,35 @@ typedef enum { rufl_PAINT, rufl_WIDTH, rufl_X_TO_OFFSET, bool rufl_can_background_blend = false; +static const os_trfm trfm_oblique = + { { { 65536, 0 }, { 13930, 65536 }, { 0, 0 } } }; + static rufl_code rufl_process(rufl_action action, const char *font_family, rufl_style font_style, unsigned int font_size, const char *string0, size_t length, - int x, int y, os_trfm *trfm, unsigned int flags, + 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 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, - unsigned int font, unsigned int font_size, int *x, int y, - os_trfm *trfm, unsigned int flags, + unsigned int font, unsigned int font_size, unsigned int slant, + int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context); static rufl_code rufl_process_span_old(rufl_action action, unsigned short *s, unsigned int n, - unsigned int font, unsigned int font_size, int *x, int y, - os_trfm *trfm, unsigned int flags, + unsigned int font, unsigned int font_size, unsigned int slant, + int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context); static int rufl_unicode_map_search_cmp(const void *keyval, const void *datum); static rufl_code rufl_process_not_available(rufl_action action, unsigned short *s, unsigned int n, unsigned int font_size, int *x, int y, - os_trfm *trfm, unsigned int flags, + unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context); static rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size, @@ -63,25 +66,7 @@ rufl_code rufl_paint(const char *font_family, rufl_style font_style, { return rufl_process(rufl_PAINT, font_family, font_style, font_size, string, - length, x, y, 0, flags, 0, 0, 0, 0, 0, 0); -} - - -/** - * Render Unicode text with a transformation matrix. - * - * Only transformations which keep the x-axis direction unchanged are - * supported. - */ - -rufl_code rufl_paint_transformed(const char *font_family, rufl_style font_style, - unsigned int font_size, - const char *string, size_t length, - int x, int y, os_trfm *trfm, unsigned int flags) -{ - return rufl_process(rufl_PAINT, - font_family, font_style, font_size, string, - length, x, y, trfm, flags, 0, 0, 0, 0, 0, 0); + length, x, y, flags, 0, 0, 0, 0, 0, 0); } @@ -96,7 +81,7 @@ rufl_code rufl_width(const char *font_family, rufl_style font_style, { return rufl_process(rufl_WIDTH, font_family, font_style, font_size, string, - length, 0, 0, 0, 0, width, 0, 0, 0, 0, 0); + length, 0, 0, 0, width, 0, 0, 0, 0, 0); } @@ -113,7 +98,7 @@ rufl_code rufl_x_to_offset(const char *font_family, rufl_style font_style, { return rufl_process(rufl_X_TO_OFFSET, font_family, font_style, font_size, string, - length, 0, 0, 0, 0, 0, + length, 0, 0, 0, 0, click_x, char_offset, actual_x, 0, 0); } @@ -130,7 +115,7 @@ rufl_code rufl_split(const char *font_family, rufl_style font_style, { return rufl_process(rufl_SPLIT, font_family, font_style, font_size, string, - length, 0, 0, 0, 0, 0, + length, 0, 0, 0, 0, width, char_offset, actual_x, 0, 0); } @@ -147,7 +132,7 @@ rufl_code rufl_paint_callback(const char *font_family, rufl_style font_style, { return rufl_process(rufl_PAINT_CALLBACK, font_family, font_style, font_size, string, - length, x, y, 0, 0, 0, 0, 0, 0, callback, context); + length, x, y, 0, 0, 0, 0, 0, callback, context); } @@ -159,7 +144,7 @@ rufl_code rufl_process(rufl_action action, const char *font_family, rufl_style font_style, unsigned int font_size, const char *string0, size_t length, - int x, int y, os_trfm *trfm, unsigned int flags, + 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) { @@ -172,6 +157,8 @@ rufl_code rufl_process(rufl_action action, size_t offset_u; size_t offset_map[rufl_PROCESS_CHUNK]; char **family; + unsigned int weight, slant, used_weight; + unsigned int search_direction; const char *string = string0; struct rufl_character_set *charset; rufl_code code; @@ -210,13 +197,49 @@ rufl_code rufl_process(rufl_action action, sizeof rufl_family_list[0], rufl_family_list_cmp); if (!family) return rufl_FONT_NOT_FOUND; - font = rufl_family_map[rufl_STYLES * (family - rufl_family_list) + - font_style]; + 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 <= 4) + 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; + } + } + charset = rufl_font_list[font].charset; offset_u = 0; rufl_utf8_read(string, length, u); - if (charset && rufl_character_set_test(charset, u)) + if (u <= 0x001f || (0x007f <= u && u <= 0x009f)) + font1 = NOT_AVAILABLE; + else if (charset && rufl_character_set_test(charset, u)) font1 = font; else if (u < 0x10000) font1 = rufl_substitution_table[u]; @@ -233,7 +256,9 @@ rufl_code rufl_process(rufl_action action, rufl_utf8_read(string, length, u); s[n] = u; offset_map[n] = offset_u; - if (charset && rufl_character_set_test(charset, u)) + if (u <= 0x001f || (0x007f <= u && u <= 0x009f)) + font1 = NOT_AVAILABLE; + else if (charset && rufl_character_set_test(charset, u)) font1 = font; else if (u < 0x10000) font1 = rufl_substitution_table[u]; @@ -251,15 +276,15 @@ rufl_code rufl_process(rufl_action action, if (font0 == NOT_AVAILABLE) code = rufl_process_not_available(action, s, n, - font_size, &x, y, trfm, flags, + font_size, &x, y, flags, click_x, &offset, callback, context); else if (rufl_old_font_manager) code = rufl_process_span_old(action, s, n, font0, - font_size, &x, y, trfm, flags, + font_size, slant, &x, y, flags, click_x, &offset, callback, context); else code = rufl_process_span(action, s, n, font0, - font_size, &x, y, trfm, flags, + font_size, slant, &x, y, flags, click_x, &offset, callback, context); if ((action == rufl_X_TO_OFFSET || action == rufl_SPLIT) && @@ -295,8 +320,8 @@ int rufl_family_list_cmp(const void *keyval, const void *datum) rufl_code rufl_process_span(rufl_action action, unsigned short *s, unsigned int n, - unsigned int font, unsigned int font_size, int *x, int y, - os_trfm *trfm, unsigned int flags, + unsigned int font, unsigned int font_size, unsigned int slant, + int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context) { @@ -304,6 +329,7 @@ rufl_code rufl_process_span(rufl_action action, unsigned short *split_point; int x_out, y_out; unsigned int i; + bool oblique = slant && !rufl_font_list[font].slant; font_f f; rufl_code code; @@ -339,13 +365,13 @@ rufl_code rufl_process_span(rufl_action action, /* paint span */ rufl_fm_error = xfont_paint(f, (const char *) s, font_OS_UNITS | - (trfm ? font_GIVEN_TRFM : 0) | + (oblique ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | font_GIVEN16_BIT | ((flags & rufl_BLEND_FONT) ? font_BLEND_FONT : 0), - *x, y, 0, trfm, n * 2); + *x, y, 0, &trfm_oblique, n * 2); if (rufl_fm_error) { LOG("xfont_paint: 0x%x: %s", rufl_fm_error->errnum, @@ -364,21 +390,19 @@ rufl_code rufl_process_span(rufl_action action, /* increment x by width of span */ if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { rufl_fm_error = xfont_scan_string(f, (const char *) s, - (trfm ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | font_GIVEN16_BIT | ((action == rufl_X_TO_OFFSET) ? font_RETURN_CARET_POS : 0), - (click_x - *x) * 400, 0x7fffffff, 0, trfm, + (click_x - *x) * 400, 0x7fffffff, 0, 0, n * 2, (char **) &split_point, &x_out, &y_out, 0); *offset = split_point - s; } else { rufl_fm_error = xfont_scan_string(f, (const char *) s, - (trfm ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | font_GIVEN16_BIT, - 0x7fffffff, 0x7fffffff, 0, trfm, n * 2, + 0x7fffffff, 0x7fffffff, 0, 0, n * 2, 0, &x_out, &y_out, 0); } if (rufl_fm_error) { @@ -400,8 +424,8 @@ rufl_code rufl_process_span(rufl_action action, rufl_code rufl_process_span_old(rufl_action action, unsigned short *s, unsigned int n, - unsigned int font, unsigned int font_size, int *x, int y, - os_trfm *trfm, unsigned int flags, + unsigned int font, unsigned int font_size, unsigned int slant, + int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context) { @@ -410,6 +434,7 @@ rufl_code rufl_process_span_old(rufl_action action, const char *font_name = rufl_font_list[font].identifier; int x_out, y_out; unsigned int i; + bool oblique = slant && !rufl_font_list[font].slant; font_f f; rufl_code code; struct rufl_unicode_map_entry *entry; @@ -449,12 +474,12 @@ rufl_code rufl_process_span_old(rufl_action action, if (action == rufl_PAINT) { /* paint span */ rufl_fm_error = xfont_paint(f, s2, font_OS_UNITS | - (trfm ? font_GIVEN_TRFM : 0) | + (oblique ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | ((flags & rufl_BLEND_FONT) ? font_BLEND_FONT : 0), - *x, y, 0, trfm, n); + *x, y, 0, &trfm_oblique, n); if (rufl_fm_error) return rufl_FONT_MANAGER_ERROR; } else if (action == rufl_PAINT_CALLBACK) { @@ -464,19 +489,17 @@ rufl_code rufl_process_span_old(rufl_action action, /* increment x by width of span */ if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { rufl_fm_error = xfont_scan_string(f, s2, - (trfm ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | ((action == rufl_X_TO_OFFSET) ? font_RETURN_CARET_POS : 0), - (click_x - *x) * 400, 0x7fffffff, 0, trfm, n, + (click_x - *x) * 400, 0x7fffffff, 0, 0, n, &split_point, &x_out, &y_out, 0); *offset = split_point - s2; } else { rufl_fm_error = xfont_scan_string(f, s2, - (trfm ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN, - 0x7fffffff, 0x7fffffff, 0, trfm, n, + 0x7fffffff, 0x7fffffff, 0, 0, n, 0, &x_out, &y_out, 0); } if (rufl_fm_error) @@ -506,15 +529,13 @@ int rufl_unicode_map_search_cmp(const void *keyval, const void *datum) rufl_code rufl_process_not_available(rufl_action action, unsigned short *s, unsigned int n, unsigned int font_size, int *x, int y, - os_trfm *trfm, unsigned int flags, + unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context) { char missing[] = "0000"; - int dx = 7 * font_size * - (trfm ? trfm->entries[0][0] / 0x10000 : 1) / 64; - int top_y = y + (trfm ? trfm->entries[1][1] / 0x10000 : 1) * 5 * - font_size / 64; + int dx = 7 * font_size / 64; + int top_y = y + 5 * font_size / 64; unsigned int i; font_f f; rufl_code code; @@ -567,12 +588,11 @@ rufl_code rufl_process_not_available(rufl_action action, /* first two characters in top row */ if (action == rufl_PAINT) { rufl_fm_error = xfont_paint(f, missing, font_OS_UNITS | - (trfm ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | ((flags & rufl_BLEND_FONT) ? font_BLEND_FONT : 0), - *x, top_y, 0, trfm, 2); + *x, top_y, 0, 0, 2); if (rufl_fm_error) return rufl_FONT_MANAGER_ERROR; } else { @@ -585,12 +605,11 @@ rufl_code rufl_process_not_available(rufl_action action, if (action == rufl_PAINT) { rufl_fm_error = xfont_paint(f, missing + 2, font_OS_UNITS | - (trfm ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | ((flags & rufl_BLEND_FONT) ? font_BLEND_FONT : 0), - *x, y, 0, trfm, 2); + *x, y, 0, 0, 2); if (rufl_fm_error) return rufl_FONT_MANAGER_ERROR; } else { -- cgit v1.2.3