summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-05-06 23:35:37 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-05-06 23:35:37 +0000
commita1d61c4f2f32f1dfb1f8a2dbef140050e6179da4 (patch)
tree9cfc1b00b3c856e7b2f8e7af65efce1936e4daf7
parentf6977c13760a70589931c487a37f53f4c7700596 (diff)
downloadlibrufl-a1d61c4f2f32f1dfb1f8a2dbef140050e6179da4.tar.gz
librufl-a1d61c4f2f32f1dfb1f8a2dbef140050e6179da4.tar.bz2
Make RUfl take account of the multitude of font encodings on old font managers.
This now utilises the Latin2, 3, and 4 sets in the standard ROM fonts, for example. svn path=/trunk/rufl/; revision=7410
-rw-r--r--rufl_dump_state.c14
-rw-r--r--rufl_find.c18
-rw-r--r--rufl_init.c364
-rw-r--r--rufl_internal.h19
-rw-r--r--rufl_metrics.c36
-rw-r--r--rufl_paint.c168
6 files changed, 498 insertions, 121 deletions
diff --git a/rufl_dump_state.c b/rufl_dump_state.c
index e1ba483..06a1f22 100644
--- a/rufl_dump_state.c
+++ b/rufl_dump_state.c
@@ -33,9 +33,14 @@ void rufl_dump_state(void)
printf(" (no charset table)\n");
}
if (rufl_font_list[i].umap) {
- printf(" ");
- rufl_dump_unicode_map(rufl_font_list[i].umap);
- printf("\n");
+ for (j = 0; j < rufl_font_list[i].num_umaps; j++) {
+ struct rufl_unicode_map *map =
+ rufl_font_list[i].umap + j;
+
+ printf(" ");
+ rufl_dump_unicode_map(map);
+ printf("\n");
+ }
}
}
@@ -103,6 +108,9 @@ void rufl_dump_unicode_map(struct rufl_unicode_map *umap)
{
unsigned int i;
+ if (umap->encoding)
+ printf("%s: ", umap->encoding);
+
for (i = 0; i != umap->entries; i++)
printf("%x:%x ", umap->map[i].u, umap->map[i].c);
}
diff --git a/rufl_find.c b/rufl_find.c
index 6aad027..a1c2785 100644
--- a/rufl_find.c
+++ b/rufl_find.c
@@ -16,7 +16,7 @@
static int rufl_family_list_cmp(const void *keyval, const void *datum);
static rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size,
- font_f f);
+ const char *encoding, font_f f);
/**
* Find a font family.
@@ -99,8 +99,17 @@ rufl_code rufl_find_font(unsigned int font, unsigned int font_size,
assert(fhandle != NULL);
for (i = 0; i != rufl_CACHE_SIZE; i++) {
+ /* Comparing pointers for the encoding is fine, as the
+ * encoding string passed to us is either:
+ *
+ * a) NULL
+ * or b) statically allocated
+ * or c) resides in the font's umap, which is constant
+ * for the lifetime of the application.
+ */
if (rufl_cache[i].font == font &&
- rufl_cache[i].size == font_size)
+ rufl_cache[i].size == font_size &&
+ rufl_cache[i].encoding == encoding)
break;
}
if (i != rufl_CACHE_SIZE) {
@@ -136,7 +145,7 @@ rufl_code rufl_find_font(unsigned int font, unsigned int font_size,
return rufl_FONT_MANAGER_ERROR;
}
/* place in cache */
- code = rufl_place_in_cache(font, font_size, f);
+ code = rufl_place_in_cache(font, font_size, encoding, f);
if (code != rufl_OK)
return code;
}
@@ -160,7 +169,7 @@ int rufl_family_list_cmp(const void *keyval, const void *datum)
*/
rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size,
- font_f f)
+ const char *encoding, font_f f)
{
unsigned int i;
unsigned int max_age = 0;
@@ -184,6 +193,7 @@ rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size,
}
rufl_cache[evict].font = font;
rufl_cache[evict].size = font_size;
+ rufl_cache[evict].encoding = encoding;
rufl_cache[evict].f = f;
rufl_cache[evict].last_used = rufl_cache_time++;
diff --git a/rufl_init.c b/rufl_init.c
index 6e75758..5f4089b 100644
--- a/rufl_init.c
+++ b/rufl_init.c
@@ -25,7 +25,7 @@
struct rufl_font_list_entry *rufl_font_list = 0;
-unsigned int rufl_font_list_entries = 0;
+size_t rufl_font_list_entries = 0;
const char **rufl_family_list = 0;
unsigned int rufl_family_list_entries = 0;
struct rufl_family_map_entry *rufl_family_map = 0;
@@ -70,11 +70,15 @@ const struct rufl_weight_table_entry rufl_weight_table[] = {
static rufl_code rufl_init_font_list(void);
-static rufl_code rufl_init_add_font(const char *identifier, const char *local_name);
+static rufl_code rufl_init_add_font(const char *identifier,
+ const char *local_name);
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_scan_font_in_encoding(const char *font_name,
+ const char *encoding, struct rufl_character_set *charset,
+ struct rufl_unicode_map *umap, unsigned int *last);
static rufl_code rufl_init_read_encoding(font_f font,
struct rufl_unicode_map *umap);
static int rufl_glyph_map_cmp(const void *keyval, const void *datum);
@@ -112,7 +116,7 @@ rufl_code rufl_init(void)
rufl_init_status_open();
- /* determine if the font manager support Unicode */
+ /* determine if the font manager supports Unicode */
rufl_fm_error = xfont_find_font("Homerton.Medium\\EUTF8", 160, 160,
0, 0, &font, 0, 0);
if (rufl_fm_error) {
@@ -142,7 +146,7 @@ rufl_code rufl_init(void)
xhourglass_off();
return code;
}
- LOG("%u faces, %zu families", rufl_font_list_entries,
+ LOG("%zu faces, %u families", rufl_font_list_entries,
rufl_family_list_entries);
code = rufl_load_cache();
@@ -540,18 +544,15 @@ bool rufl_is_space(unsigned int u)
rufl_code rufl_init_scan_font_old(unsigned int font_index)
{
const char *font_name = rufl_font_list[font_index].identifier;
- char string[2] = { 0, 0 };
- int x_out, y_out;
- unsigned int byte, bit;
- unsigned int i;
- unsigned int last_used = 0;
- unsigned int u;
struct rufl_character_set *charset;
struct rufl_character_set *charset2;
- struct rufl_unicode_map *umap;
+ struct rufl_unicode_map *umap = NULL;
+ unsigned int num_umaps = 0;
+ unsigned int i;
+ unsigned int last_used = 0;
rufl_code code;
- font_f font;
- font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } };
+ font_list_context context = 0;
+ char encoding[80];
/*LOG("font %u \"%s\"", font_index, font_name);*/
@@ -561,25 +562,171 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index)
for (i = 0; i != 256; i++)
charset->index[i] = BLOCK_EMPTY;
- umap = calloc(1, sizeof *umap);
- if (!umap) {
+ /* Firstly, search through available encodings (Symbol fonts fail) */
+ while (context != -1) {
+ struct rufl_unicode_map *temp;
+
+ rufl_fm_error = xfont_list_fonts((byte *) encoding,
+ font_RETURN_FONT_NAME |
+ 0x400000 /* Return encoding name, instead */ |
+ context,
+ sizeof(encoding), NULL, 0, NULL,
+ &context, NULL, NULL);
+ if (rufl_fm_error) {
+ LOG("xfont_list_fonts: 0x%x: %s",
+ rufl_fm_error->errnum,
+ rufl_fm_error->errmess);
+ free(charset);
+ for (i = 0; i < num_umaps; i++)
+ free((umap + i)->encoding);
+ free(umap);
+ return rufl_FONT_MANAGER_ERROR;
+ }
+ if (context == -1)
+ break;
+
+ temp = realloc(umap, (num_umaps + 1) * sizeof *umap);
+ if (!temp) {
+ free(charset);
+ for (i = 0; i < num_umaps; i++)
+ free((umap + i)->encoding);
+ free(umap);
+ return rufl_OUT_OF_MEMORY;
+ }
+
+ memset(temp + num_umaps, 0, sizeof *umap);
+
+ umap = temp;
+ num_umaps++;
+
+ code = rufl_init_scan_font_in_encoding(font_name, encoding,
+ charset, umap + (num_umaps - 1), &last_used);
+ if (code != rufl_OK) {
+ /* Not finding the font isn't fatal */
+ if (code != rufl_FONT_MANAGER_ERROR ||
+ (rufl_fm_error->errnum !=
+ error_FONT_NOT_FOUND &&
+ rufl_fm_error->errnum !=
+ error_FILE_NOT_FOUND)) {
+ free(charset);
+ for (i = 0; i < num_umaps; i++)
+ free((umap + i)->encoding);
+ free(umap);
+ return code;
+ }
+
+ /* Ensure we reuse the currently allocated umap */
+ num_umaps--;
+ } else {
+ /* If this mapping is identical to an existing one,
+ * then we can discard it */
+ for (i = 0; i != num_umaps - 1; i++) {
+ const struct rufl_unicode_map *a = (umap + i);
+ const struct rufl_unicode_map *b =
+ (umap + num_umaps - 1);
+
+ if (a->entries == b->entries &&
+ memcmp(a->map, b->map,
+ sizeof a->map) == 0) {
+ /* Found identical map; discard */
+ num_umaps--;
+ break;
+ }
+ }
+ }
+ }
+
+ if (num_umaps == 0) {
+ /* This is a symbol font and can only be used
+ * without an encoding */
+ struct rufl_unicode_map *temp;
+
+ temp = realloc(umap, (num_umaps + 1) * sizeof *umap);
+ if (!temp) {
+ free(charset);
+ free(umap);
+ return rufl_OUT_OF_MEMORY;
+ }
+
+ memset(temp + num_umaps, 0, sizeof *umap);
+
+ umap = temp;
+ num_umaps++;
+
+ code = rufl_init_scan_font_in_encoding(font_name, NULL,
+ charset, umap, &last_used);
+ if (code != rufl_OK) {
+ /* Not finding the font isn't fatal */
+ if (code != rufl_FONT_MANAGER_ERROR ||
+ (rufl_fm_error->errnum !=
+ error_FONT_NOT_FOUND &&
+ rufl_fm_error->errnum !=
+ error_FILE_NOT_FOUND)) {
+ free(charset);
+ for (i = 0; i < num_umaps; i++)
+ free((umap + i)->encoding);
+ free(umap);
+ return code;
+ }
+
+ num_umaps--;
+ }
+ }
+
+ /* shrink-wrap */
+ charset->size = offsetof(struct rufl_character_set, block) +
+ 32 * last_used;
+ charset2 = realloc(charset, charset->size);
+ if (!charset2) {
+ for (i = 0; i < num_umaps; i++)
+ free((umap + i)->encoding);
+ free(umap);
free(charset);
return rufl_OUT_OF_MEMORY;
}
- rufl_fm_error = xfont_find_font(font_name, 160, 160, 0, 0, &font, 0, 0);
+ rufl_font_list[font_index].charset = charset;
+ rufl_font_list[font_index].umap = umap;
+ rufl_font_list[font_index].num_umaps = num_umaps;
+
+ return rufl_OK;
+}
+
+/**
+ * Helper function for rufl_init_scan_font_old.
+ * Scans the given font using the given font encoding (or none, if NULL)
+ */
+
+rufl_code rufl_init_scan_font_in_encoding(const char *font_name,
+ const char *encoding, struct rufl_character_set *charset,
+ struct rufl_unicode_map *umap, unsigned int *last)
+{
+ char string[2] = { 0, 0 };
+ int x_out, y_out;
+ unsigned int byte, bit;
+ unsigned int i;
+ unsigned int last_used = *last;
+ unsigned int u;
+ rufl_code code;
+ font_f font;
+ font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } };
+ char buf[80];
+
+ if (encoding)
+ snprintf(buf, sizeof buf, "%s\\E%s", font_name, encoding);
+ else
+ snprintf(buf, sizeof buf, "%s", font_name);
+
+ rufl_fm_error = xfont_find_font(buf, 160, 160, 0, 0, &font, 0, 0);
if (rufl_fm_error) {
- LOG("xfont_find_font(\"%s\"): 0x%x: %s", font_name,
+ LOG("xfont_find_font(\"%s\"): 0x%x: %s", buf,
rufl_fm_error->errnum, rufl_fm_error->errmess);
- free(umap);
- free(charset);
- return rufl_OK;
+ return rufl_FONT_MANAGER_ERROR;
}
code = rufl_init_read_encoding(font, umap);
if (code != rufl_OK) {
- free(umap);
- free(charset);
+ xfont_lose_font(font);
return code;
}
@@ -618,32 +765,26 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index)
byte = (u >> 3) & 31;
bit = u & 7;
- charset->block[last_used - 1][byte] |= 1 << bit;
+ charset->block[charset->index[u >> 8]][byte] |=
+ 1 << bit;
}
}
xfont_lose_font(font);
if (rufl_fm_error) {
- free(umap);
- free(charset);
LOG("xfont_scan_string: 0x%x: %s",
rufl_fm_error->errnum, rufl_fm_error->errmess);
return rufl_FONT_MANAGER_ERROR;
}
- /* shrink-wrap */
- charset->size = offsetof(struct rufl_character_set, block) +
- 32 * last_used;
- charset2 = realloc(charset, charset->size);
- if (!charset2) {
- free(umap);
- free(charset);
- return rufl_OUT_OF_MEMORY;
+ if (encoding) {
+ umap->encoding = strdup(encoding);
+ if (!umap->encoding)
+ return rufl_OUT_OF_MEMORY;
}
- rufl_font_list[font_index].charset = charset;
- rufl_font_list[font_index].umap = umap;
+ *last = last_used;
return rufl_OK;
}
@@ -865,13 +1006,57 @@ rufl_code rufl_save_cache(void)
/* unicode map */
if (rufl_old_font_manager) {
- if (fwrite(rufl_font_list[i].umap,
- sizeof *rufl_font_list[i].umap, 1,
+ unsigned int j;
+
+ if (fwrite(&rufl_font_list[i].num_umaps,
+ sizeof rufl_font_list[i].num_umaps, 1,
fp) != 1) {
LOG("fwrite: 0x%x: %s", errno, strerror(errno));
fclose(fp);
return rufl_OK;
}
+
+ for (j = 0; j < rufl_font_list[i].num_umaps; j++) {
+ const struct rufl_unicode_map *umap =
+ rufl_font_list[i].umap + j;
+
+ len = umap->encoding ?
+ strlen(umap->encoding) : 0;
+
+ if (fwrite(&len, sizeof len, 1, fp) != 1) {
+ LOG("fwrite: 0x%x: %s",
+ errno, strerror(errno));
+ fclose(fp);
+ return rufl_OK;
+ }
+
+ if (umap->encoding) {
+ if (fwrite(umap->encoding, len, 1,
+ fp) != 1) {
+ LOG("fwrite: 0x%x: %s",
+ errno, strerror(errno));
+ fclose(fp);
+ return rufl_OK;
+ }
+ }
+
+ if (fwrite(&umap->entries, sizeof umap->entries,
+ 1, fp) != 1) {
+ LOG("fwrite: 0x%x: %s",
+ errno, strerror(errno));
+ fclose(fp);
+ return rufl_OK;
+ }
+
+ if (fwrite(umap->map, umap->entries *
+ sizeof(struct rufl_unicode_map_entry),
+ 1, fp) != 1) {
+ LOG("fwrite: 0x%x: %s",
+ errno, strerror(errno));
+ fclose(fp);
+ return rufl_OK;
+ }
+ }
}
}
@@ -901,6 +1086,7 @@ rufl_code rufl_load_cache(void)
struct rufl_font_list_entry *entry;
struct rufl_character_set *charset;
struct rufl_unicode_map *umap = 0;
+ unsigned int num_umaps;
fp = fopen(rufl_CACHE, "rb");
if (!fp) {
@@ -1000,7 +1186,22 @@ rufl_code rufl_load_cache(void)
/* unicode map */
if (rufl_old_font_manager) {
- umap = malloc(sizeof *umap);
+ rufl_code code = rufl_OK;
+ unsigned int entry;
+
+ /* Number of maps */
+ if (fread(&num_umaps, sizeof num_umaps, 1, fp) != 1) {
+ if (feof(fp))
+ LOG("fread: %s", "unexpected eof");
+ else
+ LOG("fread: 0x%x: %s", errno,
+ strerror(errno));
+ free(charset);
+ free(identifier);
+ break;
+ }
+
+ umap = calloc(num_umaps, sizeof *umap);
if (!umap) {
LOG("malloc(%zu) failed", sizeof *umap);
free(charset);
@@ -1009,15 +1210,83 @@ rufl_code rufl_load_cache(void)
return rufl_OUT_OF_MEMORY;
}
- if (fread(umap, sizeof *umap, 1, fp) != 1) {
- if (feof(fp))
- LOG("fread: %s", "unexpected eof");
- else
- LOG("fread: 0x%x: %s", errno,
+ /* Load them */
+ for (entry = 0; entry < num_umaps; entry++) {
+ struct rufl_unicode_map *map = umap + entry;
+
+ if (fread(&len, sizeof(len), 1, fp) != 1) {
+ if (feof(fp))
+ LOG("fread: %s",
+ "unexpected eof");
+ else
+ LOG("fread: 0x%x: %s", errno,
+ strerror(errno));
+ break;
+ }
+
+ if (len > 0) {
+ map->encoding = malloc(len + 1);
+ if (!map->encoding) {
+ LOG("malloc(%zu) failed",
+ len + 1);
+ code = rufl_OUT_OF_MEMORY;
+ break;
+ }
+
+ if (fread(map->encoding, len, 1,
+ fp) != 1) {
+ if (feof(fp))
+ LOG("fread: %s",
+ "unexpected eof");
+ else
+ LOG("fread: 0x%x: %s",
+ errno,
strerror(errno));
+ break;
+ }
+ map->encoding[len] = 0;
+ }
+
+ if (fread(&map->entries, sizeof(map->entries),
+ 1, fp) != 1) {
+ if (feof(fp))
+ LOG("fread: %s",
+ "unexpected eof");
+ else
+ LOG("fread: 0x%x: %s", errno,
+ strerror(errno));
+ break;
+ }
+
+ if (fread(map->map, map->entries *
+ sizeof(struct rufl_unicode_map_entry),
+ 1, fp) != 1) {
+ if (feof(fp))
+ LOG("fread: %s",
+ "unexpected eof");
+ else
+ LOG("fread: 0x%x: %s", errno,
+ strerror(errno));
+ break;
+ }
+ }
+
+ /* Clean up if loading failed */
+ if (entry != num_umaps) {
+ for (num_umaps = 0; num_umaps <= entry;
+ num_umaps++) {
+ struct rufl_unicode_map *map =
+ umap + num_umaps;
+
+ free(map->encoding);
+ }
free(umap);
free(charset);
free(identifier);
+
+ if (code != rufl_OK)
+ return code;
+
break;
}
}
@@ -1029,9 +1298,18 @@ rufl_code rufl_load_cache(void)
if (entry) {
entry->charset = charset;
entry->umap = umap;
+ entry->num_umaps = num_umaps;
i++;
} else {
LOG("\"%s\" not in font list", identifier);
+ while (num_umaps > 0) {
+ struct rufl_unicode_map *map =
+ umap + num_umaps - 1;
+
+ free(map->encoding);
+
+ num_umaps--;
+ }
free(umap);
free(charset);
}
diff --git a/rufl_internal.h b/rufl_internal.h
index 407ef01..1c01e36 100644
--- a/rufl_internal.h
+++ b/rufl_internal.h
@@ -49,9 +49,14 @@ struct rufl_unicode_map_entry {
/** Old font manager: mapping from Unicode to character code. This is simply
- * an array sorted by Unicode value, suitable for bsearch(). */
+ * an array sorted by Unicode value, suitable for bsearch(). If a font has
+ * support for multiple encodings, then it will have multiple unicode maps.
+ * The encoding field contains the name of the encoding to pass to the
+ * font manager. This will be NULL if the font is a Symbol font. */
struct rufl_unicode_map {
- /** Number of valid entries in u and c. */
+ /** Corresponding encoding name */
+ char *encoding;
+ /** Number of valid entries in map. */
unsigned int entries;
/** Map from Unicode to character code. */
struct rufl_unicode_map_entry map[256];
@@ -64,7 +69,9 @@ struct rufl_font_list_entry {
char *identifier;
/** Character set of font. */
struct rufl_character_set *charset;
- /** Mapping from Unicode to character code. */
+ /** Number of Unicode mapping tables */
+ unsigned int num_umaps;
+ /** Mappings 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). */
@@ -77,7 +84,7 @@ struct rufl_font_list_entry {
/** List of all available fonts. */
extern struct rufl_font_list_entry *rufl_font_list;
/** Number of entries in rufl_font_list. */
-extern unsigned int rufl_font_list_entries;
+extern size_t rufl_font_list_entries;
/** An entry in rufl_family_map. */
@@ -111,6 +118,8 @@ struct rufl_cache_entry {
#define rufl_CACHE_CORPUS (UINT_MAX - 1)
/** Font size. */
unsigned int size;
+ /** Font encoding */
+ const char *encoding;
/** Value of rufl_cache_time when last used. */
unsigned int last_used;
/** RISC OS font handle. */
@@ -161,7 +170,7 @@ bool rufl_character_set_test(struct rufl_character_set *charset,
}
#define rufl_CACHE "<Wimp$ScrapDir>.RUfl_cache"
-#define rufl_CACHE_VERSION 2
+#define rufl_CACHE_VERSION 3
struct rufl_glyph_map_entry {
diff --git a/rufl_metrics.c b/rufl_metrics.c
index 2ed4681..af4727f 100644
--- a/rufl_metrics.c
+++ b/rufl_metrics.c
@@ -119,15 +119,18 @@ rufl_code rufl_glyph_metrics(const char *font_family,
int *width, int *height,
int *x_advance, int *y_advance)
{
+ const char *font_encoding = NULL;
unsigned int font, font1, u;
unsigned short u1[2];
struct rufl_character_set *charset;
+ struct rufl_unicode_map_entry *umap_entry = NULL;
font_f f;
rufl_code code;
font_scan_block block;
font_string_flags flags;
int xa, ya;
+ /* Find font family containing glyph */
code = rufl_find_font_family(font_family, font_style,
&font, NULL, &charset);
if (code != rufl_OK)
@@ -141,7 +144,28 @@ rufl_code rufl_glyph_metrics(const char *font_family,
else
font1 = rufl_CACHE_CORPUS;
- code = rufl_find_font(font1, font_size, NULL, &f);
+ /* Old font managers need the font encoding, too */
+ if (rufl_old_font_manager && font1 != rufl_CACHE_CORPUS) {
+ unsigned int i;
+ unsigned short u16 = (unsigned short) u;
+
+ for (i = 0; i < rufl_font_list[font1].num_umaps; i++) {
+ struct rufl_unicode_map *map =
+ rufl_font_list[font1].umap + i;
+
+ umap_entry = bsearch(&u16, map->map, map->entries,
+ sizeof map->map[0],
+ rufl_unicode_map_search_cmp);
+ if (umap_entry) {
+ font_encoding = map->encoding;
+ break;
+ }
+ }
+
+ assert(umap_entry != NULL);
+ }
+
+ code = rufl_find_font(font1, font_size, font_encoding, &f);
if (code != rufl_OK)
return code;
@@ -224,12 +248,10 @@ rufl_code rufl_glyph_metrics(const char *font_family,
} else if (rufl_old_font_manager) {
/* Old Font Manager */
char s[2];
- struct rufl_unicode_map_entry *entry;
- entry = bsearch(&u1[0], rufl_font_list[font1].umap->map,
- rufl_font_list[font1].umap->entries,
- sizeof rufl_font_list[font1].umap->map[0],
- rufl_unicode_map_search_cmp);
- s[0] = entry->c;
+
+ /* We found the correct umap entry when
+ * looking for the font encoding */
+ s[0] = umap_entry->c;
s[1] = 0;
rufl_fm_error = xfont_scan_string(f, s, flags,
diff --git a/rufl_paint.c b/rufl_paint.c
index 8a8392a..084fea5 100644
--- a/rufl_paint.c
+++ b/rufl_paint.c
@@ -355,7 +355,8 @@ rufl_code rufl_process_span(rufl_action action,
font_RETURN_CARET_POS : 0),
(click_x - *x) * 400, 0x7fffffff, 0, 0,
n * 2,
- (char **)(void *)&split_point, &x_out, &y_out, 0);
+ (char **)(void *)&split_point,
+ &x_out, &y_out, 0);
*offset = split_point - s;
} else {
rufl_fm_error = xfont_scan_string(f, (const char *) s,
@@ -395,13 +396,13 @@ rufl_code rufl_process_span_old(rufl_action action,
bool oblique = slant && !rufl_font_list[font].slant;
font_f f;
rufl_code code;
- struct rufl_unicode_map_entry *entry;
-
- code = rufl_find_font(font, font_size, NULL, &f);
- if (code != rufl_OK)
- return code;
if (action == rufl_FONT_BBOX) {
+ /* Don't need encoding for bounding box */
+ code = rufl_find_font(font, font_size, NULL, &f);
+ if (code != rufl_OK)
+ return code;
+
rufl_fm_error = xfont_read_info(f, &x[0], &x[1], &x[2], &x[3]);
if (rufl_fm_error) {
LOG("xfont_read_info: 0x%x: %s",
@@ -412,68 +413,117 @@ rufl_code rufl_process_span_old(rufl_action action,
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,
- rufl_font_list[font].umap->entries,
- sizeof rufl_font_list[font].umap->map[0],
+ if (offset)
+ *offset = 0;
+
+ /* Process the span in map-coherent chunks */
+ do {
+ struct rufl_unicode_map *map;
+ struct rufl_unicode_map_entry *entry = NULL;
+ unsigned int j;
+
+ i = 0;
+
+ /* Find map for first character */
+ for (j = 0; j < rufl_font_list[font].num_umaps; j++) {
+ map = rufl_font_list[font].umap + j;
+
+ entry = bsearch(&s[i], map->map, map->entries,
+ sizeof map->map[0],
rufl_unicode_map_search_cmp);
- s2[i] = entry->c;
- }
- s2[i] = 0;
+ if (entry)
+ break;
+ }
+ assert(map != NULL);
+ assert(entry != NULL);
- if (action == rufl_PAINT) {
- /* paint span */
- /* call Font_SetFont to work around broken PS printer driver,
- * which doesn't use the font handle from Font_Paint */
- rufl_fm_error = xfont_set_font(f);
- if (rufl_fm_error) {
- LOG("xfont_set_font: 0x%x: %s",
- rufl_fm_error->errnum,
- rufl_fm_error->errmess);
- return rufl_FONT_MANAGER_ERROR;
+ /* Collect characters: s[0..i) use map */
+ do {
+ entry = bsearch(&s[i], map->map, map->entries,
+ sizeof map->map[0],
+ rufl_unicode_map_search_cmp);
+
+ if (entry)
+ s2[i++] = entry->c;
+ } while (i != n && entry != NULL);
+
+ s2[i] = 0;
+
+ code = rufl_find_font(font, font_size, map->encoding, &f);
+ if (code != rufl_OK)
+ return code;
+
+ if (action == rufl_PAINT) {
+ /* paint span */
+ /* call Font_SetFont to work around broken PS printer
+ * driver, which doesn't use the font handle from
+ * Font_Paint */
+ rufl_fm_error = xfont_set_font(f);
+ if (rufl_fm_error) {
+ LOG("xfont_set_font: 0x%x: %s",
+ rufl_fm_error->errnum,
+ rufl_fm_error->errmess);
+ return rufl_FONT_MANAGER_ERROR;
+ }
+
+ rufl_fm_error = xfont_paint(f, s2, font_OS_UNITS |
+ (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_oblique, i);
+ if (rufl_fm_error) {
+ LOG("xfont_paint: 0x%x: %s",
+ rufl_fm_error->errnum,
+ rufl_fm_error->errmess);
+ return rufl_FONT_MANAGER_ERROR;
+ }
+ } else if (action == rufl_PAINT_CALLBACK) {
+ char font_name[80];
+
+ if (map->encoding)
+ snprintf(font_name, sizeof font_name, "%s\\E%s",
+ rufl_font_list[font].identifier,
+ map->encoding);
+ else
+ snprintf(font_name, sizeof font_name, "%s",
+ rufl_font_list[font].identifier);
+
+ callback(context, font_name, font_size,
+ s2, 0, i, *x, y);
+ }
+
+ /* increment x by width of span */
+ if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) {
+ rufl_fm_error = xfont_scan_string(f, s2,
+ font_GIVEN_LENGTH | font_GIVEN_FONT |
+ font_KERN |
+ ((action == rufl_X_TO_OFFSET) ?
+ font_RETURN_CARET_POS : 0),
+ (click_x - *x) * 400, 0x7fffffff,
+ 0, 0, i,
+ &split_point, &x_out, &y_out, 0);
+ *offset += split_point - s2;
+ } else {
+ rufl_fm_error = xfont_scan_string(f, s2,
+ font_GIVEN_LENGTH | font_GIVEN_FONT |
+ font_KERN,
+ 0x7fffffff, 0x7fffffff, 0, 0, i,
+ 0, &x_out, &y_out, 0);
}
- rufl_fm_error = xfont_paint(f, s2, font_OS_UNITS |
- (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_oblique, n);
if (rufl_fm_error) {
- LOG("xfont_paint: 0x%x: %s",
+ LOG("xfont_scan_string: 0x%x: %s",
rufl_fm_error->errnum,
rufl_fm_error->errmess);
return rufl_FONT_MANAGER_ERROR;
}
- } else if (action == rufl_PAINT_CALLBACK) {
- callback(context, rufl_font_list[font].identifier,
- font_size, s2, 0, n, *x, y);
- }
+ *x += x_out / 400;
- /* increment x by width of span */
- if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) {
- rufl_fm_error = xfont_scan_string(f, s2,
- font_GIVEN_LENGTH | font_GIVEN_FONT |
- font_KERN |
- ((action == rufl_X_TO_OFFSET) ?
- font_RETURN_CARET_POS : 0),
- (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,
- font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN,
- 0x7fffffff, 0x7fffffff, 0, 0, n,
- 0, &x_out, &y_out, 0);
- }
- if (rufl_fm_error) {
- LOG("xfont_scan_string: 0x%x: %s",
- rufl_fm_error->errnum,
- rufl_fm_error->errmess);
- return rufl_FONT_MANAGER_ERROR;
- }
- *x += x_out / 400;
+ /* Now update s and n for the next chunk */
+ s += i;
+ n -= i;
+ } while (n != 0);
return rufl_OK;
}