summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2006-01-29 12:20:25 (GMT)
committer James Bursa <james@netsurf-browser.org>2006-01-29 12:20:25 (GMT)
commit87d2b7aa8e9b6e2209776a73da67398c795cbcb3 (patch)
treefac5f022fcebbfe684643055813f8489138819af
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
-rw-r--r--rufl.h34
-rw-r--r--rufl_chars.c70
-rw-r--r--rufl_dump_state.c21
-rw-r--r--rufl_init.c340
-rw-r--r--rufl_internal.h22
-rw-r--r--rufl_paint.c145
-rw-r--r--rufl_test.c12
7 files changed, 365 insertions, 279 deletions
diff --git a/rufl.h b/rufl.h
index 68cddf3..7af35f3 100644
--- a/rufl.h
+++ b/rufl.h
@@ -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>
*/
#ifndef RUFL_H
@@ -29,15 +29,22 @@ typedef enum {
rufl_IO_EOF,
} rufl_code;
-
+/** Font weight and slant. Normal weight is 400, 700 gives the "Bold" weight of
+ * fonts. */
typedef enum {
- rufl_REGULAR = 0,
- rufl_SLANTED = 1,
- rufl_BOLD = 2,
- rufl_BOLD_SLANTED = 3,
+ rufl_WEIGHT_100 = 1,
+ rufl_WEIGHT_200 = 2,
+ rufl_WEIGHT_300 = 3,
+ rufl_WEIGHT_400 = 4,
+ rufl_WEIGHT_500 = 5,
+ rufl_WEIGHT_600 = 6,
+ rufl_WEIGHT_700 = 7,
+ rufl_WEIGHT_800 = 8,
+ rufl_WEIGHT_900 = 9,
+ rufl_SLANTED = 0x100,
} rufl_style;
-/** rufl_paint(_transformed) flags */
+/** rufl_paint flags */
#define rufl_BLEND_FONT 0x01
/** Last Font Manager error. */
@@ -69,19 +76,6 @@ rufl_code rufl_paint(const char *font_family, rufl_style font_style,
/**
- * 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);
-
-
-/**
* Measure the width of Unicode text.
*/
diff --git a/rufl_chars.c b/rufl_chars.c
index ff7013a..d9b9d6f 100644
--- a/rufl_chars.c
+++ b/rufl_chars.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 <errno.h>
@@ -16,7 +16,7 @@
unsigned int font = 0;
-bool bold = false;
+unsigned int weight = rufl_WEIGHT_400;
bool italic = false;
@@ -73,7 +73,7 @@ int main(void)
try(rufl_init(), "rufl_init");
- menu = malloc(wimp_SIZEOF_MENU(2 + rufl_family_list_entries));
+ menu = malloc(wimp_SIZEOF_MENU(10 + rufl_family_list_entries));
if (!menu)
die("Out of memory");
strcpy(menu->title_data.text, "Fonts");
@@ -84,34 +84,38 @@ int main(void)
menu->width = 200;
menu->height = wimp_MENU_ITEM_HEIGHT;
menu->gap = wimp_MENU_ITEM_GAP;
- menu->entries[0].menu_flags = 0;
- menu->entries[0].sub_menu = wimp_NO_SUB_MENU;
- menu->entries[0].icon_flags = wimp_ICON_TEXT |
- (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
- (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
- strcpy(menu->entries[0].data.text, "Bold");
- menu->entries[1].menu_flags = wimp_MENU_SEPARATE;
- menu->entries[1].sub_menu = wimp_NO_SUB_MENU;
- menu->entries[1].icon_flags = wimp_ICON_TEXT |
+ for (i = 0; i != 10; i++) {
+ menu->entries[i].menu_flags = 0;
+ menu->entries[i].sub_menu = wimp_NO_SUB_MENU;
+ menu->entries[i].icon_flags = wimp_ICON_TEXT |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
+ strcpy(menu->entries[i].data.text, "100");
+ menu->entries[i].data.text[0] = '1' + i;
+ }
+ menu->entries[9].menu_flags = wimp_MENU_SEPARATE;
+ menu->entries[9].sub_menu = wimp_NO_SUB_MENU;
+ menu->entries[9].icon_flags = wimp_ICON_TEXT |
(wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
(wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
- strcpy(menu->entries[1].data.text, "Italic");
+ strcpy(menu->entries[9].data.text, "Italic");
for (i = 0; i != rufl_family_list_entries; i++) {
- menu->entries[2 + i].menu_flags = 0;
- menu->entries[2 + i].sub_menu = wimp_NO_SUB_MENU;
- menu->entries[2 + i].icon_flags = wimp_ICON_TEXT |
+ menu->entries[10 + i].menu_flags = 0;
+ menu->entries[10 + i].sub_menu = wimp_NO_SUB_MENU;
+ menu->entries[10 + i].icon_flags = wimp_ICON_TEXT |
wimp_ICON_INDIRECTED |
(wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
(wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
- menu->entries[2 + i].data.indirected_text.text =
+ menu->entries[10 + i].data.indirected_text.text =
rufl_family_list[i];
- menu->entries[2 + i].data.indirected_text.validation =
+ menu->entries[10 + i].data.indirected_text.validation =
(char *) -1;
- menu->entries[2 + i].data.indirected_text.size =
+ menu->entries[10 + i].data.indirected_text.size =
strlen(rufl_family_list[i]);
}
- menu->entries[2].menu_flags |= wimp_MENU_TICKED;
- menu->entries[i + 1].menu_flags |= wimp_MENU_LAST;
+ menu->entries[3].menu_flags |= wimp_MENU_TICKED;
+ menu->entries[10].menu_flags |= wimp_MENU_TICKED;
+ menu->entries[i + 9].menu_flags |= wimp_MENU_LAST;
error = xwimp_create_window((wimp_window *) &window, &w);
if (error)
@@ -181,17 +185,20 @@ int main(void)
error = xwimp_get_pointer_info(&pointer);
if (error)
die(error->errmess);
- if (block.selection.items[0] == 0) {
- bold = !bold;
- menu->entries[0].menu_flags ^= wimp_MENU_TICKED;
- } else if (block.selection.items[0] == 1) {
+ if (block.selection.items[0] <= 8) {
+ menu->entries[weight - 1].menu_flags ^=
+ wimp_MENU_TICKED;
+ weight = block.selection.items[0] + 1;
+ menu->entries[weight - 1].menu_flags ^=
+ wimp_MENU_TICKED;
+ } else if (block.selection.items[0] == 9) {
italic = !italic;
- menu->entries[1].menu_flags ^= wimp_MENU_TICKED;
+ menu->entries[9].menu_flags ^= wimp_MENU_TICKED;
} else {
- menu->entries[2 + font].menu_flags ^=
+ menu->entries[10 + font].menu_flags ^=
wimp_MENU_TICKED;
- font = block.selection.items[0] - 2;
- menu->entries[2 + font].menu_flags ^=
+ font = block.selection.items[0] - 10;
+ menu->entries[10 + font].menu_flags ^=
wimp_MENU_TICKED;
}
error = xwimp_force_redraw(w,
@@ -239,10 +246,7 @@ rufl_code redraw(int x, int y, int y0, int y1)
unsigned int l;
unsigned int u;
rufl_code code;
- rufl_style style = bold && italic ? rufl_BOLD_SLANTED :
- bold ? rufl_BOLD :
- italic ? rufl_SLANTED :
- rufl_REGULAR;
+ rufl_style style = weight | (italic ? rufl_SLANTED : 0);
for (u = y0 / 40 * 32; (int) u != (y1 / 40 + 1) * 32; u++) {
if (u <= 0x7f)
diff --git a/rufl_dump_state.c b/rufl_dump_state.c
index 81b7fb3..e1ba483 100644
--- a/rufl_dump_state.c
+++ b/rufl_dump_state.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 <stdio.h>
@@ -42,10 +42,21 @@ void rufl_dump_state(void)
printf("rufl_family_list:\n");
for (i = 0; i != rufl_family_list_entries; i++) {
printf(" %u \"%s\"\n", i, rufl_family_list[i]);
- for (j = 0; j != rufl_STYLES; j++)
- printf(" %u \"%s\"\n", j, rufl_font_list
- [rufl_family_map[rufl_STYLES * i + j]]
- .identifier);
+ for (j = 0; j != 9; j++) {
+ struct rufl_family_map_entry *e = &rufl_family_map[i];
+ printf(" %u ", j);
+ if (e->font[j][0] == NO_FONT)
+ printf("- ");
+ else
+ printf("\"%s\" ", rufl_font_list[e->font[j][0]].
+ identifier);
+ if (e->font[j][1] == NO_FONT)
+ printf("- ");
+ else
+ printf("\"%s\" ", rufl_font_list[e->font[j][1]].
+ identifier);
+ printf("\n");
+ }
}
printf("rufl_substitution_table:\n");
diff --git a/rufl_init.c b/rufl_init.c
index ed3d9ff..a195cd9 100644
--- a/rufl_init.c
+++ b/rufl_init.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>
*/
#define _GNU_SOURCE /* for strndup */
@@ -23,7 +23,7 @@ struct rufl_font_list_entry *rufl_font_list = 0;
unsigned int rufl_font_list_entries = 0;
char **rufl_family_list = 0;
unsigned int rufl_family_list_entries = 0;
-unsigned int *rufl_family_map = 0;
+struct rufl_family_map_entry *rufl_family_map = 0;
os_error *rufl_fm_error = 0;
unsigned short *rufl_substitution_table;
struct rufl_cache_entry rufl_cache[rufl_CACHE_SIZE];
@@ -31,31 +31,41 @@ int rufl_cache_time = 0;
bool rufl_old_font_manager = false;
-/** An entry in rufl_style_table. */
-struct rufl_style_table_entry {
+/** An entry in rufl_weight_table. */
+struct rufl_weight_table_entry {
const char *name;
- unsigned int style;
+ unsigned int weight;
};
-/** Map from font name tail to font style. Must be sorted by name. */
-const struct rufl_style_table_entry rufl_style_table[] = {
- { "Bold", rufl_BOLD },
- { "Bold.Italic", rufl_BOLD_SLANTED },
- { "Bold.Oblique", rufl_BOLD_SLANTED },
- { "Italic", rufl_SLANTED },
- { "Medium", rufl_REGULAR },
- { "Medium.Italic", rufl_SLANTED },
- { "Medium.Oblique", rufl_SLANTED },
- { "Oblique", rufl_SLANTED },
- { "Regular", rufl_REGULAR },
- { "Regular.Italic", rufl_SLANTED },
- { "Regular.Oblique", rufl_SLANTED },
+/** Map from font name part to font weight. Must be case-insensitive sorted by
+ * name. */
+const struct rufl_weight_table_entry rufl_weight_table[] = {
+ { "Black", 9 },
+ { "Bold", 7 },
+ { "Book", 3 },
+ { "Demi", 6 },
+ { "DemiBold", 6 },
+ { "Extra", 8 },
+ { "ExtraBlack", 9 },
+ { "ExtraBold", 8 },
+ { "ExtraLight", 1 },
+ { "Heavy", 8 },
+ { "Light", 2 },
+ { "Medium", 5 },
+ { "Regular", 4 },
+ { "Semi", 6 },
+ { "SemiBold", 6 },
+ { "SemiLight", 3 },
+ { "UltraBlack", 9 },
+ { "UltraBold", 9 },
};
static rufl_code rufl_init_font_list(void);
-static int rufl_style_table_cmp(const void *keyval, const void *datum);
+static rufl_code rufl_init_add_font(char *identifier);
+static int rufl_weight_table_cmp(const void *keyval, const void *datum);
static rufl_code rufl_init_scan_font(unsigned int font);
+static bool rufl_is_space(unsigned int u);
static rufl_code rufl_init_scan_font_old(unsigned int font_index);
static rufl_code rufl_init_read_encoding(font_f font,
struct rufl_unicode_map *umap);
@@ -189,137 +199,133 @@ rufl_code rufl_init(void)
rufl_code rufl_init_font_list(void)
{
- int size;
- struct rufl_font_list_entry *font_list;
- char *identifier;
- char *dot;
- char **family_list;
- char *family;
- unsigned int *family_map;
- unsigned int i;
+ rufl_code code;
font_list_context context = 0;
- font_list_context context2;
- struct rufl_style_table_entry *entry;
+ char identifier[80];
while (context != -1) {
- /* find length of next identifier */
- rufl_fm_error = xfont_list_fonts(0,
- font_RETURN_FONT_NAME | context,
- 0, 0, 0, 0,
- &context2, &size, 0);
- if (rufl_fm_error) {
- LOG("xfont_list_fonts: 0x%x: %s",
- rufl_fm_error->errnum,
- rufl_fm_error->errmess);
- return rufl_FONT_MANAGER_ERROR;
- }
- if (context2 == -1)
- break;
-
- /* get next identifier */
- identifier = malloc(size);
- if (!identifier)
- return rufl_OUT_OF_MEMORY;
-
/* read identifier */
rufl_fm_error = xfont_list_fonts(identifier,
font_RETURN_FONT_NAME | context,
- size, 0, 0, 0,
+ sizeof identifier, 0, 0, 0,
&context, 0, 0);
if (rufl_fm_error) {
- free(identifier);
LOG("xfont_list_fonts: 0x%x: %s",
rufl_fm_error->errnum,
rufl_fm_error->errmess);
return rufl_FONT_MANAGER_ERROR;
}
+ if (context == -1)
+ break;
- /* Check that:
- * a) it's got some Outlines data
- * b) it's not a RiScript generated font
- * c) it's not a TeX font
- *
- * If it's any of the above, we ignore it.
- */
- char pathname[size+6]; /* Fontname + ".Out*" + \0 */
- snprintf(pathname, sizeof pathname, "%s.Out*", identifier);
-
- /* Read required buffer size */
- rufl_fm_error = xosfscontrol_canonicalise_path(pathname, 0,
- "Font$Path", 0, 0, &size);
- if (rufl_fm_error) {
- free(identifier);
- LOG("xosfscontrol_canonicalise_path: 0x%x: %s",
- rufl_fm_error->errnum,
- rufl_fm_error->errmess);
- return rufl_FONT_MANAGER_ERROR;
- }
+ code = rufl_init_add_font(identifier);
+ if (code != rufl_OK)
+ return code;
+ }
- /* size is -(space required - 1) so negate and add 1 */
- size = -size + 1;
+ return rufl_OK;
+}
- /* Create buffer and canonicalise path */
- char fullpath[size];
- rufl_fm_error = xosfscontrol_canonicalise_path(pathname,
- fullpath, "Font$Path", 0, size, 0);
- if (rufl_fm_error) {
- free(identifier);
- LOG("xosfscontrol_canonicalise_path: 0x%x: %s",
- rufl_fm_error->errnum,
- rufl_fm_error->errmess);
- return rufl_FONT_MANAGER_ERROR;
- }
- /* LOG("%s (%c)", fullpath, fullpath[size - 2]); */
+rufl_code rufl_init_add_font(char *identifier)
+{
+ char pathname[100];
+ size_t size;
+ struct rufl_font_list_entry *font_list;
+ char *dot;
+ char **family_list;
+ char *family, *part;
+ unsigned int weight = 0;
+ unsigned int slant = 0;
+ bool special = false;
+ struct rufl_family_map_entry *family_map;
+ unsigned int i;
+ struct rufl_weight_table_entry *entry;
- /* If the last character is an asterisk,
- * there's no Outlines file. */
- if (fullpath[size - 2] == '*' ||
- strstr(fullpath, "RiScript") ||
- strstr(fullpath, "!TeXFonts")) {
- /* Ignore this font */
- free(identifier);
- continue;
- }
+ /* Check that:
+ * a) it's got some Outlines data
+ * b) it's not a RiScript generated font
+ * c) it's not a TeX font */
+ snprintf(pathname, sizeof pathname, "%s.Out*", identifier);
- /* (re)allocate buffers */
- font_list = realloc(rufl_font_list, sizeof rufl_font_list[0] *
- (rufl_font_list_entries + 1));
- if (!font_list) {
- free(identifier);
- return rufl_OUT_OF_MEMORY;
- }
- rufl_font_list = font_list;
-
- rufl_font_list[rufl_font_list_entries].identifier = identifier;
- rufl_font_list[rufl_font_list_entries].charset = 0;
- rufl_font_list[rufl_font_list_entries].umap = 0;
- rufl_font_list_entries++;
-
- /*LOG("%u \"%s\"", rufl_font_list_entries - 1, identifier);*/
-
- /* add family to list, if it is new */
- dot = strchr(identifier, '.');
- if (2 <= rufl_font_list_entries && dot &&
- strncmp(identifier, rufl_font_list
- [rufl_font_list_entries - 2].identifier,
- dot - identifier) == 0) {
- /* same family as last font */
- entry = bsearch(dot + 1, rufl_style_table,
- sizeof rufl_style_table /
- sizeof rufl_style_table[0],
- sizeof rufl_style_table[0],
- rufl_style_table_cmp);
- if (entry)
- rufl_family_map[rufl_STYLES *
- (rufl_family_list_entries - 1) +
- entry->style] =
- rufl_font_list_entries - 1;
+ /* Read required buffer size */
+ rufl_fm_error = xosfscontrol_canonicalise_path(pathname, 0,
+ "Font$Path", 0, 0, &size);
+ if (rufl_fm_error) {
+ LOG("xosfscontrol_canonicalise_path: 0x%x: %s",
+ rufl_fm_error->errnum,
+ rufl_fm_error->errmess);
+ return rufl_FONT_MANAGER_ERROR;
+ }
+
+ /* size is -(space required - 1) so negate and add 1 */
+ size = -size + 1;
+
+ /* Create buffer and canonicalise path */
+ char fullpath[size];
+ rufl_fm_error = xosfscontrol_canonicalise_path(pathname,
+ fullpath, "Font$Path", 0, size, 0);
+ if (rufl_fm_error) {
+ LOG("xosfscontrol_canonicalise_path: 0x%x: %s",
+ rufl_fm_error->errnum,
+ rufl_fm_error->errmess);
+ return rufl_FONT_MANAGER_ERROR;
+ }
+
+ /* LOG("%s (%c)", fullpath, fullpath[size - 2]); */
+
+ /* If the last character is an asterisk, there's no Outlines file. */
+ if (fullpath[size - 2] == '*' ||
+ strstr(fullpath, "RiScript") ||
+ strstr(fullpath, "!TeXFonts"))
+ /* Ignore this font */
+ return rufl_OK;
+
+ /* add identifier to rufl_font_list */
+ font_list = realloc(rufl_font_list, sizeof rufl_font_list[0] *
+ (rufl_font_list_entries + 1));
+ if (!font_list)
+ return rufl_OUT_OF_MEMORY;
+ rufl_font_list = font_list;
+ rufl_font_list[rufl_font_list_entries].identifier = strdup(identifier);
+ if (!rufl_font_list[rufl_font_list_entries].identifier)
+ return rufl_OUT_OF_MEMORY;
+ rufl_font_list[rufl_font_list_entries].charset = 0;
+ rufl_font_list[rufl_font_list_entries].umap = 0;
+ rufl_font_list_entries++;
+
+ /* determine family, weight, and slant */
+ dot = strchr(identifier, '.');
+ family = identifier;
+ if (dot)
+ *dot = 0;
+ while (dot && (!weight || !slant)) {
+ part = dot + 1;
+ dot = strchr(part, '.');
+ if (dot)
+ *dot = 0;
+ if (strcasecmp(part, "Italic") == 0 ||
+ strcasecmp(part, "Oblique") == 0) {
+ slant = 1;
continue;
}
+ entry = bsearch(part, rufl_weight_table,
+ sizeof rufl_weight_table /
+ sizeof rufl_weight_table[0],
+ sizeof rufl_weight_table[0],
+ rufl_weight_table_cmp);
+ if (entry)
+ weight = entry->weight;
+ else
+ special = true; /* unknown weight or style */
+ }
+ if (!weight)
+ weight = 4;
+ weight--;
+ if (rufl_family_list_entries == 0 || strcasecmp(family,
+ rufl_family_list[rufl_family_list_entries - 1]) != 0) {
/* new family */
- /*LOG("new family %u", rufl_family_list_entries);*/
family_list = realloc(rufl_family_list,
sizeof rufl_family_list[0] *
(rufl_family_list_entries + 1));
@@ -328,35 +334,45 @@ rufl_code rufl_init_font_list(void)
rufl_family_list = family_list;
family_map = realloc(rufl_family_map,
- rufl_STYLES * sizeof rufl_family_map[0] *
+ sizeof rufl_family_map[0] *
(rufl_family_list_entries + 1));
if (!family_map)
return rufl_OUT_OF_MEMORY;
rufl_family_map = family_map;
- if (dot)
- family = strndup(identifier, dot - identifier);
- else
- family = strdup(identifier);
+ family = strdup(family);
if (!family)
return rufl_OUT_OF_MEMORY;
rufl_family_list[rufl_family_list_entries] = family;
- for (i = 0; i != rufl_STYLES; i++)
- rufl_family_map[rufl_STYLES * rufl_family_list_entries +
- i] = rufl_font_list_entries - 1;
+ for (i = 0; i != 9; i++)
+ rufl_family_map[rufl_family_list_entries].font[i][0] =
+ rufl_family_map[rufl_family_list_entries].font[i][1] =
+ NO_FONT;
rufl_family_list_entries++;
}
+ struct rufl_family_map_entry *e =
+ &rufl_family_map[rufl_family_list_entries - 1];
+ /* prefer fonts with no unknown weight or style in their name, so that,
+ * for example, Alps.Light takes priority over Alps.Cond.Light */
+ if (e->font[weight][slant] == NO_FONT || !special)
+ e->font[weight][slant] = rufl_font_list_entries - 1;
+
+ rufl_font_list[rufl_font_list_entries - 1].family =
+ rufl_family_list_entries - 1;
+ rufl_font_list[rufl_font_list_entries - 1].weight = weight;
+ rufl_font_list[rufl_font_list_entries - 1].slant = slant;
+
return rufl_OK;
}
-int rufl_style_table_cmp(const void *keyval, const void *datum)
+int rufl_weight_table_cmp(const void *keyval, const void *datum)
{
const char *key = keyval;
- const struct rufl_style_table_entry *entry = datum;
- return strcmp(key, entry->name);
+ const struct rufl_weight_table_entry *entry = datum;
+ return strcasecmp(key, entry->name);
}
@@ -397,7 +413,13 @@ rufl_code rufl_init_scan_font(unsigned int font_index)
}
/* scan through all characters */
- for (u = 32; u != 0x10000; u++) {
+ for (u = 0x0020; u != 0x10000; u++) {
+ if (u == 0x007f) {
+ /* skip DELETE and C1 controls */
+ u = 0x009f;
+ continue;
+ }
+
string[0] = u;
rufl_fm_error = xfont_scan_string(font, (char *) string,
font_RETURN_BBOX | font_GIVEN32_BIT |
@@ -409,11 +431,17 @@ rufl_code rufl_init_scan_font(unsigned int font_index)
if (rufl_fm_error)
break;
- if (block.bbox.x0 == 0x20000000 ||
- (x_out == 0 && y_out == 0 &&
+ if (block.bbox.x0 == 0x20000000) {
+ /* absent (no definition) */
+ } else if (x_out == 0 && y_out == 0 &&
block.bbox.x0 == 0 && block.bbox.y0 == 0 &&
- block.bbox.x1 == 0 && block.bbox.y1 == 0)) {
- /* absent */
+ block.bbox.x1 == 0 && block.bbox.y1 == 0) {
+ /* absent (empty) */
+ } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 &&
+ block.bbox.x1 == 0 && block.bbox.y1 == 0 &&
+ !rufl_is_space(u)) {
+ /* absent (space but not a space character - some
+ * fonts do this) */
} else {
/* present */
byte = (u >> 3) & 31;
@@ -467,6 +495,18 @@ rufl_code rufl_init_scan_font(unsigned int font_index)
/**
+ * A character is one of the Unicode space characters.
+ */
+
+bool rufl_is_space(unsigned int u)
+{
+ return u == 0x0020 || u == 0x00a0 ||
+ (0x2000 <= u && u <= 0x200b) ||
+ u == 0x202f || u == 0x3000;
+}
+
+
+/**
* Scan a font for available characters (old font manager version).
*/
@@ -528,11 +568,17 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index)
if (rufl_fm_error)
break;
- if (block.bbox.x0 == 0x20000000 ||
- (x_out == 0 && y_out == 0 &&
+ if (block.bbox.x0 == 0x20000000) {
+ /* absent (no definition) */
+ } else if (x_out == 0 && y_out == 0 &&
block.bbox.x0 == 0 && block.bbox.y0 == 0 &&
- block.bbox.x1 == 0 && block.bbox.y1 == 0)) {
- /* absent */
+ block.bbox.x1 == 0 && block.bbox.y1 == 0) {
+ /* absent (empty) */
+ } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 &&
+ block.bbox.x1 == 0 && block.bbox.y1 == 0 &&
+ !rufl_is_space(u)) {
+ /* absent (space but not a space character - some
+ * fonts do this) */
} else {
/* present */
if (charset->index[u >> 8] == BLOCK_EMPTY) {
diff --git a/rufl_internal.h b/rufl_internal.h
index 8cd1759..670fcb2 100644
--- a/rufl_internal.h
+++ b/rufl_internal.h
@@ -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 <limits.h>
@@ -66,6 +66,13 @@ struct rufl_font_list_entry {
struct rufl_character_set *charset;
/** Mapping from Unicode to character code. */
struct rufl_unicode_map *umap;
+ /** Family that this font belongs to (index in rufl_family_list and
+ * rufl_family_map). */
+ unsigned int family;
+ /** Font weight (0 to 8). */
+ unsigned int weight;
+ /** Font slant (0 or 1). */
+ unsigned int slant;
};
/** List of all available fonts. */
extern struct rufl_font_list_entry *rufl_font_list;
@@ -73,10 +80,15 @@ extern struct rufl_font_list_entry *rufl_font_list;
extern unsigned int rufl_font_list_entries;
-#define rufl_STYLES 4
-
-/** Map from font family to fonts. rufl_STYLES entries per family. */
-extern unsigned int *rufl_family_map;
+/** An entry in rufl_family_map. */
+struct rufl_family_map_entry {
+ /** This style does not exist in this family. */
+# define NO_FONT UINT_MAX
+ /** Map from weight and slant to index in rufl_font_list, or NO_FONT. */
+ unsigned int font[9][2];
+};
+/** Map from font family to fonts, rufl_family_list_entries entries. */
+extern struct rufl_family_map_entry *rufl_family_map;
/** No font contains this character. */
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 {
diff --git a/rufl_test.c b/rufl_test.c
index f851832..ad536a7 100644
--- a/rufl_test.c
+++ b/rufl_test.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 <errno.h>
@@ -29,28 +29,28 @@ int main(void)
try(rufl_init(), "rufl_init");
rufl_dump_state();
- try(rufl_paint("NewHall", rufl_REGULAR, 240,
+ try(rufl_paint("NewHall", rufl_WEIGHT_400, 240,
utf8_test, sizeof utf8_test - 1,
1200, 1000, 0), "rufl_paint");
- try(rufl_width("NewHall", rufl_REGULAR, 240,
+ try(rufl_width("NewHall", rufl_WEIGHT_400, 240,
utf8_test, sizeof utf8_test - 1,
&width), "rufl_width");
printf("width: %i\n", width);
for (x = 0; x < width + 100; x += 100) {
- try(rufl_x_to_offset("NewHall", rufl_REGULAR, 240,
+ try(rufl_x_to_offset("NewHall", rufl_WEIGHT_400, 240,
utf8_test, sizeof utf8_test - 1,
x, &char_offset, &actual_x),
"rufl_x_to_offset");
printf("x to offset: %i -> %i %i \"%s\"\n", x, actual_x,
char_offset, utf8_test + char_offset);
- try(rufl_split("NewHall", rufl_REGULAR, 240,
+ try(rufl_split("NewHall", rufl_WEIGHT_400, 240,
utf8_test, sizeof utf8_test - 1,
x, &char_offset, &actual_x),
"rufl_split");
printf("split: %i -> %i %i \"%s\"\n", x, actual_x,
char_offset, utf8_test + char_offset);
}
- try(rufl_paint_callback("NewHall", rufl_REGULAR, 240,
+ try(rufl_paint_callback("NewHall", rufl_WEIGHT_400, 240,
utf8_test, sizeof utf8_test - 1,
1200, 1000, callback, 0), "rufl_paint_callback");
rufl_quit();