From fcbe2cebae28ef623dceb82ce9501027fea91fb5 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Thu, 26 Sep 2002 21:38:33 +0000 Subject: [project @ 2002-09-26 21:38:32 by bursa] New Unicode font handling and rendering code. svn path=/import/netsurf/; revision=39 --- riscos/font.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++----------- riscos/font.h | 35 ++++----- riscos/gui.c | 16 ++--- 3 files changed, 213 insertions(+), 65 deletions(-) (limited to 'riscos') diff --git a/riscos/font.c b/riscos/font.c index 05faf50cf..3ee42e8ce 100644 --- a/riscos/font.c +++ b/riscos/font.c @@ -1,45 +1,61 @@ /** - * $Id: font.c,v 1.2 2002/09/11 14:24:02 monkeyson Exp $ + * $Id: font.c,v 1.3 2002/09/26 21:38:33 bursa Exp $ */ +#include #include +#include "utf-8.h" #include "netsurf/render/css.h" -#include "netsurf/render/font.h" +#include "netsurf/riscos/font.h" #include "netsurf/render/utils.h" #include "netsurf/desktop/gui.h" #include "oslib/font.h" /** - * functions + * RISC OS fonts are 8-bit, so Unicode is displayed by combining many + * font manager fonts. Each font manager font must have 128 characters of + * Unicode in order, starting at character 128. */ -/** it is rather inefficient calling this all the time **/ -font_f riscos_font_css_to_handle(struct css_style* style) -{ - int width = 12 * 16; - int height = 12 * 16; - char font_name[255]; +/** + * font id = font family * 4 + bold * 2 + slanted + * font family: 0 = sans-serif, 1 = serif, ... + */ - if (style->font_size.size == CSS_FONT_SIZE_LENGTH) - width = height = style->font_size.value.length.value * 16; +const char * const font_table[FONT_FAMILIES * 4][FONT_CHUNKS] = { + /* sans-serif */ + { "Homerton.Medium\\EU0000", + "Homerton.Medium\\EU0080", + "Homerton.Medium\\EU0100" }, + { "Homerton.Medium.Oblique\\EU0000", + "Homerton.Medium.Oblique\\EU0080", + "Homerton.Medium.Oblique\\EU0100" }, + { "Homerton.Bold\\EU0000", + "Homerton.Bold\\EU0080", + "Homerton.Bold\\EU0100" }, + { "Homerton.Bold.Oblique\\EU0000", + "Homerton.Bold.Oblique\\EU0080", + "Homerton.Bold.Oblique\\EU0100" }, +}; - strcpy(font_name, "Homerton."); - if (style->font_weight == CSS_FONT_WEIGHT_BOLD) - strcat(font_name, "Bold"); - else - strcat(font_name, "Medium"); +/* a font_set is just a linked list of font_data for each face for now */ +struct font_set { + struct font_data *font[FONT_FAMILIES * 4]; +}; - if (style->font_style == CSS_FONT_STYLE_ITALIC || style->font_style == CSS_FONT_STYLE_OBLIQUE) - strcat(font_name, ".Oblique"); +void font_close(struct font_data *data); - return font_find_font(font_name, width, height, 0, 0, 0, 0); -} +/** + * functions + */ -unsigned long font_width(struct css_style * style, const char * text, unsigned int length) +unsigned long font_width(struct font_data *font, const char * text, unsigned int length) { font_scan_block block; os_error * error; - font_f font; + char *text2; + + assert(font != 0 && text != 0); if (length == 0) return 0; @@ -48,20 +64,21 @@ unsigned long font_width(struct css_style * style, const char * text, unsigned i block.letter.x = block.letter.y = 0; block.split_char = -1; - font = riscos_font_css_to_handle(style); - - error = xfont_scan_string(font, (char*) text, - font_GIVEN_BLOCK | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | font_RETURN_BBOX, + text2 = font_utf8_to_string(font, text, length); + error = xfont_scan_string(font->handle[0], text2, + font_GIVEN_BLOCK | font_GIVEN_FONT | font_KERN | font_RETURN_BBOX, 0x7fffffff, 0x7fffffff, &block, - 0, length, + 0, 0, 0, 0, 0, 0); if (error != 0) { fprintf(stderr, "%s\n", error->errmess); die("font_scan_string failed"); } -// fprintf(stderr, "Stated length %d, strlen %d\n", (int)length, strlen(text)); +/* fprintf(stderr, "font_width: '%.*s' => '%s' => %i %i %i %i\n", length, text, text2, */ +/* block.bbox.x0, block.bbox.y0, block.bbox.x1, block.bbox.y1); */ + free(text2); if (length < 0x7fffffff) { @@ -82,33 +99,31 @@ unsigned long font_width(struct css_style * style, const char * text, unsigned i // fprintf(stderr, "No space\n");*/ } - font_lose_font(font); - return block.bbox.x1 / 800; } -void font_position_in_string(const char* text, struct css_style* style, int length, int x, int* char_offset, int* pixel_offset) +void font_position_in_string(const char* text, struct font_data* font, + int length, int x, int* char_offset, int* pixel_offset) { - font_f font; font_scan_block block; char* split_point; int x_out, y_out, length_out; + char *text2; + + assert(font != 0 && text != 0); block.space.x = block.space.y = 0; block.letter.x = block.letter.y = 0; block.split_char = -1; - font = riscos_font_css_to_handle(style); - - xfont_scan_string(font, (char*) text, - font_GIVEN_BLOCK | font_GIVEN_LENGTH | - font_GIVEN_FONT | font_KERN | font_RETURN_CARET_POS, + text2 = font_utf8_to_string(font, text, length); + xfont_scan_string(font, text2, + font_GIVEN_BLOCK | font_GIVEN_FONT | font_KERN | font_RETURN_CARET_POS, ro_x_units(x) * 400, 0x7fffffff, - &block, 0, length, + &block, 0, 0, &split_point, &x_out, &y_out, &length_out); - - font_lose_font(font); + free(text2); *char_offset = (int)(split_point - text); *pixel_offset = browser_x_units(x_out / 400); @@ -116,3 +131,135 @@ void font_position_in_string(const char* text, struct css_style* style, int leng return; } + +struct font_set *font_new_set() +{ + struct font_set *set = xcalloc(1, sizeof(*set)); + unsigned int i; + + for (i = 0; i < FONT_FAMILIES * 4; i++) + set->font[i] = 0; + + return set; +} + + +struct font_data *font_open(struct font_set *set, struct css_style *style) +{ + struct font_data *data; + unsigned int i; + unsigned int size = 16 * 11; + unsigned int f = 0; + + assert(set != 0); + + if (style->font_size.size == CSS_FONT_SIZE_LENGTH) + size = style->font_size.value.length.value * 16; + + switch (style->font_weight) { + case CSS_FONT_WEIGHT_BOLD: + case CSS_FONT_WEIGHT_600: + case CSS_FONT_WEIGHT_700: + case CSS_FONT_WEIGHT_800: + case CSS_FONT_WEIGHT_900: + f += FONT_BOLD; + break; + default: + break; + } + + switch (style->font_style) { + case CSS_FONT_STYLE_ITALIC: + case CSS_FONT_STYLE_OBLIQUE: + f += FONT_SLANTED; + break; + default: + break; + } + + for (data = set->font[f]; data != 0; data = data->next) + if (data->size == size) + return data; + + data = xcalloc(1, sizeof(*data)); + + for (i = 0; i < FONT_CHUNKS; i++) { + font_f handle = font_find_font(font_table[f][i], size, size, 0, 0, 0, 0); + data->handle[i] = handle; + } + data->size = size; + + data->next = set->font[f]; + set->font[f] = data; + + return data; +} + + +void font_free_set(struct font_set *set) +{ + unsigned int i; + struct font_data *data, *next; + + assert(set != 0); + + for (i = 0; i < FONT_FAMILIES * 4; i++) { + for (data = set->font[i]; data != 0; data = next) { + next = data->next; + font_close(data); + } + } + + free(set); +} + + +void font_close(struct font_data *data) +{ + unsigned int i; + + for (i = 0; i < FONT_CHUNKS; i++) + font_lose_font(data->handle[i]); + + free(data); +} + +#define BUFFER_CHUNK 100 + +char *font_utf8_to_string(struct font_data *font, const char *s, unsigned int length) +{ + unsigned long buffer_len = BUFFER_CHUNK; + char *d = xcalloc(buffer_len, sizeof(char)); + unsigned int chunk0 = 0, chunk1; + unsigned int u, chars, i = 0, j = 0; + + assert(font != 0 && s != 0); + +/* fprintf(stderr, "font_utf8_to_string: '%s'", s); */ + + while (j < length && s[j] != 0) { + u = sgetu8(s + j, &chars); + j += chars; + if (buffer_len < i + 5) { + buffer_len += BUFFER_CHUNK; + d = xrealloc(d, buffer_len * sizeof(char)); + } + chunk1 = u / 0x80; + if (FONT_CHUNKS <= chunk1 || (u < 0x20 || (0x80 <= u && u <= 0x9f))) { + d[i++] = '?'; + } else { + if (chunk0 != chunk1) { + d[i++] = font_COMMAND_FONT; + d[i++] = font->handle[chunk1]; + chunk0 = chunk1; + } + d[i++] = 0x80 + (u % 0x80); + } + } + d[i] = 0; + +/* fprintf(stderr, " => '%s'\n", d); */ + + return d; +} + diff --git a/riscos/font.h b/riscos/font.h index ee3e4c2b2..24b5d0f5d 100644 --- a/riscos/font.h +++ b/riscos/font.h @@ -1,5 +1,5 @@ /** - * $Id: font.h,v 1.1 2002/09/11 14:24:02 monkeyson Exp $ + * $Id: font.h,v 1.2 2002/09/26 21:38:33 bursa Exp $ */ #ifndef _NETSURF_RISCOS_FONT_H_ @@ -12,28 +12,31 @@ #include "netsurf/render/css.h" #include "oslib/font.h" -struct font_set; typedef unsigned int font_id; -struct font_split { - unsigned long width; - unsigned long height; - const char * end; + +#define FONT_FAMILIES 1 +#define FONT_CHUNKS 3 +#define FONT_BOLD 2 +#define FONT_SLANTED 1 + +struct font_set; +struct font_data { + font_f handle[FONT_CHUNKS]; + unsigned int size; + struct font_data *next; }; /** * interface */ -struct font_set * font_set_create(void); -font_id font_add(struct font_set * font_set, const char * name, unsigned int weight, - unsigned int size); -void font_set_free(struct font_set * font_set); -struct font_split font_split(struct font_set * font_set, font_id id, const char * text, - unsigned long width, int force); -unsigned long font_width(struct css_style * style, const char * text, unsigned int length); - -font_f riscos_font_css_to_handle(struct css_style* style); +unsigned long font_width(struct font_data *font, const char * text, unsigned int length); +void font_position_in_string(const char* text, struct font_data *font, + int length, int x, int* char_offset, int* pixel_offset); -void font_position_in_string(const char* text, struct css_style* style, int length, int x, int* char_offset, int* pixel_offset); +struct font_set *font_new_set(); +struct font_data *font_open(struct font_set *set, struct css_style *style); +void font_free_set(struct font_set *set); +char *font_utf8_to_string(struct font_data *data, const char *s, unsigned int length); #endif diff --git a/riscos/gui.c b/riscos/gui.c index 15d38b540..b66a3b4a8 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -1,5 +1,5 @@ /** - * $Id: gui.c,v 1.1 2002/09/11 14:24:02 monkeyson Exp $ + * $Id: gui.c,v 1.2 2002/09/26 21:38:33 bursa Exp $ */ #include "netsurf/riscos/font.h" @@ -264,7 +264,7 @@ void ro_gui_window_redraw_box(gui_window* g, struct box * box, signed long x, si struct box * c; const char * const noname = ""; const char * name = noname; - font_f font; + char *text; switch (box->type) { @@ -299,8 +299,6 @@ void ro_gui_window_redraw_box(gui_window* g, struct box * box, signed long x, si if (box->type == BOX_INLINE) { - font = riscos_font_css_to_handle(box->style); - if (g->data.browser.bw->current_content->data.html.text_selection.selected == 1) { struct box_position* start; @@ -359,13 +357,13 @@ if (g->data.browser.bw->current_content->data.html.text_selection.selected == 1) } } - font_paint(font, (char*) box->text, - font_OS_UNITS | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN, + text = font_utf8_to_string(box->font, box->text, box->length); + font_paint(box->font->handle[0], text, + font_OS_UNITS | font_GIVEN_FONT | font_KERN, x + box->x * 2, y - box->y * 2 - box->height * 2, NULL, NULL, - box->length); - - font_lose_font(font); + 0); + free(text); } } -- cgit v1.2.3