summaryrefslogtreecommitdiff
path: root/rufl_paint.c
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2006-01-29 12:20:25 +0000
committerJames Bursa <james@netsurf-browser.org>2006-01-29 12:20:25 +0000
commit87d2b7aa8e9b6e2209776a73da67398c795cbcb3 (patch)
treefac5f022fcebbfe684643055813f8489138819af /rufl_paint.c
parent4581f7a89f79a828d161191f336a4444c8d2f9e8 (diff)
downloadlibrufl-87d2b7aa8e9b6e2209776a73da67398c795cbcb3.tar.gz
librufl-87d2b7aa8e9b6e2209776a73da67398c795cbcb3.tar.bz2
[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
Diffstat (limited to 'rufl_paint.c')
-rw-r--r--rufl_paint.c145
1 files changed, 82 insertions, 63 deletions
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 <james@semichrome.net>
+ * Copyright 2006 James Bursa <james@semichrome.net>
*/
#include <assert.h>
@@ -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 {