Gitweb links: ...log http://git.netsurf-browser.org/librufl.git/shortlog/421bacf56744d00db7ccef93daa119ab8ea4ac55 ...commit http://git.netsurf-browser.org/librufl.git/commit/421bacf56744d00db7ccef93daa119ab8ea4ac55 ...tree http://git.netsurf-browser.org/librufl.git/tree/421bacf56744d00db7ccef93daa119ab8ea4ac55
The branch, jmb/ac has been updated via 421bacf56744d00db7ccef93daa119ab8ea4ac55 (commit) via d59f17a6fb3d4f20a931ab45bf60ff910685b241 (commit) via 01da1538227f4d139c0665b730211c665c821625 (commit) via b547911ad6cba76439eeb9cd03a6af3fe0dc6be3 (commit) via 5fd0f4c9161c5ab6163386598d04681f12858509 (commit) via 7455528fedc1d6a03ba693307c441ffddcc3c164 (commit) via c69d7fee4ef1820296cb1c0db072e01cf6970ce1 (commit) via 158483bc75ac79cb2699d92e30f30aeefefe56ca (commit) via 5741043b16e81f9673fdef791aeb225e522c9a41 (commit) via a53a1e176218aba04ec13d91bbfbd103608c4eb2 (commit) via c945837b458fc9ff4d37568be74ddb1a685e6431 (commit) from 6dce21aa10a2d5f5a745a2f168d801d4baa7d4b2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=421bacf56744d00db7ccef93daa119ab8ea4ac55 commit 421bacf56744d00db7ccef93daa119ab8ea4ac55 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Make dump of unicode maps optional Add a verbose flag to rufl_dump_state() and use it to control whether to dump the individual unicode maps generated when using a non-UCS Font Manager. Change rufl_test to not dump this state (ordinarily, anyway) as it is generally uninteresting and highly verbose. diff --git a/include/rufl.h b/include/rufl.h index 0164df8..15e889e 100644 --- a/include/rufl.h +++ b/include/rufl.h @@ -185,7 +185,7 @@ rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, * Dump the internal library state to stdout. */ -void rufl_dump_state(void); +void rufl_dump_state(bool verbose); /** diff --git a/src/rufl_dump_state.c b/src/rufl_dump_state.c index 860d57e..f466333 100644 --- a/src/rufl_dump_state.c +++ b/src/rufl_dump_state.c @@ -18,7 +18,7 @@ static void rufl_dump_unicode_map(struct rufl_unicode_map *umap); * Dump the internal library state to stdout. */ -void rufl_dump_state(void) +void rufl_dump_state(bool verbose) { unsigned int i, j; @@ -32,7 +32,7 @@ void rufl_dump_state(void) } else { printf(" (no charset table)\n"); } - if (rufl_font_list[i].umap) { + if (verbose && rufl_font_list[i].umap) { for (j = 0; j < rufl_font_list[i].num_umaps; j++) { struct rufl_unicode_map *map = rufl_font_list[i].umap + j; diff --git a/test/rufl_test.c b/test/rufl_test.c index d939467..5b76f81 100644 --- a/test/rufl_test.c +++ b/test/rufl_test.c @@ -35,7 +35,7 @@ int main(void) int bbox[4]; try(rufl_init(), "rufl_init"); - rufl_dump_state(); + rufl_dump_state(false); try(rufl_paint("NewHall", rufl_WEIGHT_400, 240, utf8_test, sizeof utf8_test - 1, 1200, 1000, 0), "rufl_paint"); commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=d59f17a6fb3d4f20a931ab45bf60ff910685b241 commit d59f17a6fb3d4f20a931ab45bf60ff910685b241 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Ignore UCS fonts if using a non-UCS Font Manager Attempting to use fonts constructed for the UCS Font Manager on older systems generally results in bad outcomes up to, and including, complete system freezes. As fixing the Font Manager on these systems is impractical, simply ignore these fonts completely when scanning for glyph coverage. diff --git a/src/rufl_init.c b/src/rufl_init.c index 79433c3..6cf0be6 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -1028,10 +1028,33 @@ rufl_code rufl_init_scan_font_in_encoding(const char *font_name, if (code != rufl_OK) { LOG("rufl_init_read_encoding(\"%s\", ...): 0x%x", buf, code); + umap->encoding = NULL; xfont_lose_font(font); return code; } + /* Detect attempts to use UCS fonts with a non-UCS Font Manager. + * There is a bug in all known non-UCS Font Managers which is + * often triggered by scanning many fonts. The Font Manager will + * attempt to dereference a bogus pointer (at the start of + * getbbox_unscaled) and thus cause an abort in SVC mode. + * Fallout can be as (relatively) benign as the application + * crashing or escalate to an entire system freeze requiring + * a reset. As there are no "good" outcomes here, and we do + * not have a time machine to go back and fix long-ago released + * Font Managers, ensure we ignore UCS fonts here. */ + if ((uint32_t) umap->encoding > 256) { + static os_error err = { + error_FONT_TOO_MANY_CHUNKS, "Rejecting UCS font"}; + LOG("%s", "Rejecting UCS font"); + umap->encoding = NULL; + xfont_lose_font(font); + rufl_fm_error = &err; + return rufl_FONT_MANAGER_ERROR; + } + /* Eliminate all trace of our (ab)use of the encoding field */ + umap->encoding = NULL; + for (i = 0; i != umap->entries; i++) { u = umap->map[i].u; string[0] = umap->map[i].c; @@ -1102,9 +1125,11 @@ static rufl_code rufl_init_umap_cb(void *pw, uint32_t glyph_idx, uint32_t ucs4) umap->map[umap->entries].u = ucs4; umap->map[umap->entries].c = glyph_idx; umap->entries++; - if (umap->entries == 256) - result = rufl_IO_EOF; } + /* Stash the total number of encoding file entries so that + * rufl_init_scan_font_in_encoding can detect the presence of a + * UCS font on a non-UCS capable system. It will clean up for us. */ + umap->encoding = (void *) (((uint32_t) umap->encoding) + 1); return result; } commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=01da1538227f4d139c0665b730211c665c821625 commit 01da1538227f4d139c0665b730211c665c821625 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Clean up logging in the non-UCS Font Manager path To obtain the full extent of a "language" font's glyph coverage we need to open and scan it in each of the available target encodings. All of the Latin1-6 + Welsh target encodings declare that they are based on the Base0 encoding and thus will cause the Font Manager to demand the existence of corresponding IntMetric0/Outlines0 font data files. A "language" font using a different base encoding (and corresponding target encodings based on it) would thus generate an error from the Font Manager. Additionally, without reinventing the Font Manager's own logic (and poking around the filesystem looking for IntMetrics and Encoding files), we don't know if a font is a "language" or a "symbol" font until we try to use it. Thus, we expect attempts to open "symbol" fonts with an explicit target encoding to generate an error from the Font Manager as well. As these are expected errors, there is no point logging them as it just produces a load of distracting noise. diff --git a/src/rufl_init.c b/src/rufl_init.c index 3a77588..79433c3 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -870,7 +870,20 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) 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 || + rufl_fm_error->errnum == + error_FONT_ENCODING_NOT_FOUND || + /* Neither is a too modern font */ + rufl_fm_error->errnum == + error_FONT_TOO_MANY_CHUNKS)) { + /* Ensure we reuse the currently allocated umap */ + num_umaps--; + } else if (code != rufl_OK) { LOG("rufl_init_scan_font_in_encoding(\"%s\", \"%s\", " "...): 0x%x (0x%x: %s)", font_name, encoding, code, @@ -879,26 +892,11 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) code == rufl_FONT_MANAGER_ERROR ? rufl_fm_error->errmess : ""); - /* 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 && - rufl_fm_error->errnum != - error_FONT_ENCODING_NOT_FOUND && - /* Neither is a too modern font */ - rufl_fm_error->errnum != - error_FONT_TOO_MANY_CHUNKS)) { - 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--; + free(charset); + for (i = 0; i < num_umaps; i++) + free((umap + i)->encoding); + free(umap); + return code; } else { /* If this mapping is identical to an existing one, * then we can discard it */ @@ -937,7 +935,20 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) 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 || + rufl_fm_error->errnum == + error_FONT_ENCODING_NOT_FOUND || + /* Neither is a too modern font */ + rufl_fm_error->errnum == + error_FONT_TOO_MANY_CHUNKS)) { + /* Ensure we reuse the currently allocated umap */ + num_umaps--; + } else if (code != rufl_OK) { LOG("rufl_init_scan_font_in_encoding(\"%s\", NULL, " "...): 0x%x (0x%x: %s)", font_name, code, @@ -946,25 +957,11 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) code == rufl_FONT_MANAGER_ERROR ? rufl_fm_error->errmess : ""); - /* 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 && - rufl_fm_error->errnum != - error_FONT_ENCODING_NOT_FOUND && - /* Neither is a too modern font */ - rufl_fm_error->errnum != - error_FONT_TOO_MANY_CHUNKS)) { - free(charset); - for (i = 0; i < num_umaps; i++) - free((umap + i)->encoding); - free(umap); - return code; - } - - num_umaps--; + free(charset); + for (i = 0; i < num_umaps; i++) + free((umap + i)->encoding); + free(umap); + return code; } } @@ -1023,8 +1020,7 @@ rufl_code rufl_init_scan_font_in_encoding(const char *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", buf, - rufl_fm_error->errnum, rufl_fm_error->errmess); + /* Leave it to our caller to log, if they wish */ return rufl_FONT_MANAGER_ERROR; } commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=b547911ad6cba76439eeb9cd03a6af3fe0dc6be3 commit b547911ad6cba76439eeb9cd03a6af3fe0dc6be3 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Accept non-UCS Font Manager rejecting UCS fonts. If you attempt to use fonts supported by the UCS Font Manager with a non-UCS Font Manager, this will either work (in a limited way) or fail because the font data is incomprehensible to the non-UCS Font Manager. Cope with one particular instance of this. diff --git a/src/rufl_init.c b/src/rufl_init.c index 9beb992..3a77588 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -886,7 +886,10 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) rufl_fm_error->errnum != error_FILE_NOT_FOUND && rufl_fm_error->errnum != - error_FONT_ENCODING_NOT_FOUND)) { + error_FONT_ENCODING_NOT_FOUND && + /* Neither is a too modern font */ + rufl_fm_error->errnum != + error_FONT_TOO_MANY_CHUNKS)) { free(charset); for (i = 0; i < num_umaps; i++) free((umap + i)->encoding); @@ -950,7 +953,10 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) rufl_fm_error->errnum != error_FILE_NOT_FOUND && rufl_fm_error->errnum != - error_FONT_ENCODING_NOT_FOUND)) { + error_FONT_ENCODING_NOT_FOUND && + /* Neither is a too modern font */ + rufl_fm_error->errnum != + error_FONT_TOO_MANY_CHUNKS)) { free(charset); for (i = 0; i < num_umaps; i++) free((umap + i)->encoding); commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=5fd0f4c9161c5ab6163386598d04681f12858509 commit 5fd0f4c9161c5ab6163386598d04681f12858509 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Fix font scanning on non-UCS Font Managers We want to update the umap itself not whatever happens to be on the stack in the vicinity of its address. diff --git a/src/rufl_init.c b/src/rufl_init.c index cf85980..9beb992 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -1118,7 +1118,7 @@ rufl_code rufl_init_populate_unicode_map(font_f f, umap->entries = 0; - result = rufl_init_read_encoding(f, rufl_init_umap_cb, &umap); + result = rufl_init_read_encoding(f, rufl_init_umap_cb, umap); if (result == rufl_OK) { /* sort by unicode */ qsort(umap->map, umap->entries, sizeof umap->map[0], commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=7455528fedc1d6a03ba693307c441ffddcc3c164 commit 7455528fedc1d6a03ba693307c441ffddcc3c164 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Fix initialisation on UCS Font Manager 3.41-3.63 We cannot use Font_ReadEncodingFile to find the path to a font's source encoding because that is not what the API returns (it returns the path to the encoding file corresponding to the target encoding used to open the font handle) and there is no public API for obtaining the path of the source encoding. Additionally, there is no reliable way to replicate the UCS Font Manager's mapping of undefined and duplicate glyph names into the private use space at U+E000-U+EFFF. Therefore, take a different approach to supporting these versions of the Font Manager: abuse Font_EnumerateCharacters by probing every codepoint in the range [0, first_returned) to force the Font Manager to reveal the information we want. Once we have reached the first_returned codepoint, we can happily fall through to the normal flow (which will make use of the sparse nature of the Unicode space). diff --git a/src/rufl_init.c b/src/rufl_init.c index 29ef415..cf85980 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -543,16 +543,56 @@ static rufl_code rufl_init_enumerate_characters(const char *font_name, uint32_t glyph_idx, uint32_t ucs4), void *pw) { - unsigned int u, next; - rufl_code result; + unsigned int u = 0, next, internal; + rufl_code result = rufl_OK; - if (rufl_broken_font_enumerate_characters) - return rufl_init_read_encoding(font, callback, pw); + if (rufl_broken_font_enumerate_characters) { + /* We know that any codepoints in the first chunk will + * be missed because Font_EnumerateCharacters is broken + * on this version of the Font Manager. Find the first + * codepoint it will report. */ + unsigned int first; + rufl_fm_error = xfont_enumerate_characters(font, 0, + (int *) &first, (int *) &internal); + if (rufl_fm_error) { + LOG("xfont_enumerate_characters(\"%s\", " + "U+%x, ...): 0x%x: %s", + font_name, 0, + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } - /* Scan through mapped characters */ - for (u = 0; u != (unsigned int) -1; u = next) { - unsigned int internal; + /* Search the entire space up to the first codepoint it + * reported. */ + for (u = 0; u != (unsigned int) -1 && u != first; u++) { + rufl_fm_error = xfont_enumerate_characters(font, u, + (int *) &next, (int *) &internal); + if (rufl_fm_error) { + LOG("xfont_enumerate_characters(\"%s\", " + "U+%x, ...): 0x%x: %s", + font_name, u, + rufl_fm_error->errnum, + rufl_fm_error->errmess); + result = rufl_FONT_MANAGER_ERROR; + break; + } + + /* Skip unmapped characters */ + if (internal == (unsigned int) -1) + continue; + + /* Character is mapped, emit it */ + result = callback(pw, internal, u); + if (result != rufl_OK) + break; + } + /* Now fall through to the normal path */ + } + + /* Scan through mapped characters */ + for (; u != (unsigned int) -1; u = next) { rufl_fm_error = xfont_enumerate_characters(font, u, (int *) &next, (int *) &internal); if (rufl_fm_error) { @@ -561,6 +601,7 @@ static rufl_code rufl_init_enumerate_characters(const char *font_name, font_name, u, rufl_fm_error->errnum, rufl_fm_error->errmess); + result = rufl_FONT_MANAGER_ERROR; break; } @@ -1225,13 +1266,9 @@ rufl_code rufl_init_read_encoding(font_f font, } fp = fopen(filename, "r"); - if (!fp) { + if (!fp && rufl_old_font_manager) { /* many "symbol" fonts have no encoding file */ - const char *default_path = - "Resources:$.Fonts.Encodings./Default"; - if (rufl_old_font_manager) - default_path = "Resources:$.Fonts.Encodings.Latin1"; - fp = fopen(default_path, "r"); + fp = fopen("Resources:$.Fonts.Encodings.Latin1", "r"); } if (!fp) return rufl_IO_ERROR; commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=c69d7fee4ef1820296cb1c0db072e01cf6970ce1 commit c69d7fee4ef1820296cb1c0db072e01cf6970ce1 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Fix shrinkwrap moving blocks All blocks subsequent to a full one get moved up and all their indices need rewriting. diff --git a/src/rufl_init.c b/src/rufl_init.c index f49ceff..29ef415 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -472,31 +472,26 @@ static void rufl_init_shrinkwrap_plane(struct rufl_character_set *charset) for (byte = 0; byte != 32; byte++) bit &= charset->block[block][byte]; - if (bit == 0xff) { - /* Block is full */ - - /* Find a block whose index is after this one. - * If such a block exists, move its data into - * this block, as this block's bitmap is now free - */ - for (byte = 0; byte != 256; byte++) { - if (charset->index[byte] < BLOCK_EMPTY && - charset->index[byte] > block) { - break; - } - } - if (byte != 256) { - memcpy(charset->block[block], - charset->block[ - charset->index[byte]], - 32); - charset->index[byte] = block; - } - /* Now mark this block as full */ - charset->index[u] = BLOCK_FULL; - last_used--; + if (bit != 0xff) + continue; + + /* Block is full */ + + /* Move subsequent blocks up and rewrite their indices */ + memmove(charset->block[block], + charset->block[block+1], + (254-(block+1)) * 32); + for (byte = 0; byte != 256; byte++) { + if (charset->index[byte] < BLOCK_EMPTY && + charset->index[byte] > block) { + charset->index[byte]--; + } } + + /* Now mark this block as full */ + charset->index[u] = BLOCK_FULL; + last_used--; } /* Fill in this plane's size now we know it */ commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=158483bc75ac79cb2699d92e30f30aeefefe56ca commit 158483bc75ac79cb2699d92e30f30aeefefe56ca Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Ensure dumping doesn't run off the end of a plane diff --git a/src/rufl_dump_state.c b/src/rufl_dump_state.c index 13a1564..860d57e 100644 --- a/src/rufl_dump_state.c +++ b/src/rufl_dump_state.c @@ -90,7 +90,7 @@ static void rufl_dump_character_set(const struct rufl_character_set *charset) u++; } else { t = u; - while (rufl_character_set_test( + while (u != 0x10000 && rufl_character_set_test( charset, plane + u)) u++; printf("%x-%x ", plane + t, plane + u - 1); commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=5741043b16e81f9673fdef791aeb225e522c9a41 commit 5741043b16e81f9673fdef791aeb225e522c9a41 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Fix bug in sparse encoding parser Spaces are valid characters in the sparse encoding so ensure we consume them correctly. diff --git a/src/rufl_init.c b/src/rufl_init.c index 5da9b50..f49ceff 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -1273,8 +1273,9 @@ rufl_code rufl_init_read_encoding(font_f font, (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '.') || (c == '_') || - (c == ';')) { - /* Printable: append */ + (c == ';') || + (c == ' ' && s[0] != '/')) { + /* Printable (or space in new-style): append */ s[n++] = c; if (n >= sizeof(s)) { /* Too long: garbage */ commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=a53a1e176218aba04ec13d91bbfbd103608c4eb2 commit a53a1e176218aba04ec13d91bbfbd103608c4eb2 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Add MedBold and Thin weights diff --git a/src/rufl_init.c b/src/rufl_init.c index a6c895f..5da9b50 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -60,11 +60,13 @@ const struct rufl_weight_table_entry rufl_weight_table[] = { { "ExtraLight", 1 }, { "Heavy", 8 }, { "Light", 2 }, + { "MedBold", 6 }, { "Medium", 5 }, { "Regular", 4 }, { "Semi", 6 }, { "SemiBold", 6 }, { "SemiLight", 3 }, + { "Thin", 1 }, { "UltraBlack", 9 }, { "UltraBold", 9 }, }; commitdiff http://git.netsurf-browser.org/librufl.git/commit/?id=c945837b458fc9ff4d37568be74ddb1a685e6431 commit c945837b458fc9ff4d37568be74ddb1a685e6431 Author: John-Mark Bell <j...@netsurf-browser.org> Commit: John-Mark Bell <j...@netsurf-browser.org> Clean up logging diff --git a/src/rufl_init.c b/src/rufl_init.c index 6ec21b7..a6c895f 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -512,14 +512,11 @@ static struct rufl_character_set *rufl_init_shrinkwrap_planes( /* Shrink-wrap each plane, accumulating total required size as we go */ for (u = 0; u < 17; u++) { if (planes[u]) { - LOG("shrink-wrapping plane %d", u); rufl_init_shrinkwrap_plane(planes[u]); size += PLANE_SIZE(planes[u]->metadata); } } - LOG("shrink-wrapped size: %u", size); - charset = malloc(size); if (!charset) return NULL; @@ -531,8 +528,6 @@ static struct rufl_character_set *rufl_init_shrinkwrap_planes( if (!planes[u-1]) continue; - LOG("merging plane %d", u); - /* Set E bit if not the last plane */ if (pos != size) planes[u-1]->metadata |= (1u<<31); @@ -1430,12 +1425,7 @@ rufl_code rufl_save_cache(void) } /* character set (all planes) */ - LOG("writing character sets for %s", - rufl_font_list[i].identifier); while (EXTENSION_FOLLOWS(charset->metadata)) { - LOG("writing plane %d (%u)", - PLANE_ID(charset->metadata), - PLANE_SIZE(charset->metadata)); if (fwrite(charset, PLANE_SIZE(charset->metadata), 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); @@ -1445,9 +1435,6 @@ rufl_code rufl_save_cache(void) charset = (void *)(((uint8_t *)charset) + PLANE_SIZE(charset->metadata)); } - LOG("writing plane %d (%u)", - PLANE_ID(charset->metadata), - PLANE_SIZE(charset->metadata)); if (fwrite(charset, PLANE_SIZE(charset->metadata), 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); @@ -1606,7 +1593,6 @@ rufl_code rufl_load_cache(void) identifier[len] = 0; /* character set */ - LOG("reading character sets for %s", identifier); do { if (fread(&metadata, sizeof metadata, 1, fp) != 1) { if (feof(fp)) @@ -1618,9 +1604,6 @@ rufl_code rufl_load_cache(void) break; } - LOG("reading plane %d (%u)", - PLANE_ID(metadata), - PLANE_SIZE(metadata)); if (!charset) { charset = cur_charset = malloc( PLANE_SIZE(metadata)); ----------------------------------------------------------------------- Summary of changes: include/rufl.h | 2 +- src/rufl_dump_state.c | 6 +- src/rufl_init.c | 233 +++++++++++++++++++++++++++++-------------------- test/rufl_test.c | 2 +- 4 files changed, 144 insertions(+), 99 deletions(-) diff --git a/include/rufl.h b/include/rufl.h index 0164df8..15e889e 100644 --- a/include/rufl.h +++ b/include/rufl.h @@ -185,7 +185,7 @@ rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, * Dump the internal library state to stdout. */ -void rufl_dump_state(void); +void rufl_dump_state(bool verbose); /** diff --git a/src/rufl_dump_state.c b/src/rufl_dump_state.c index 13a1564..f466333 100644 --- a/src/rufl_dump_state.c +++ b/src/rufl_dump_state.c @@ -18,7 +18,7 @@ static void rufl_dump_unicode_map(struct rufl_unicode_map *umap); * Dump the internal library state to stdout. */ -void rufl_dump_state(void) +void rufl_dump_state(bool verbose) { unsigned int i, j; @@ -32,7 +32,7 @@ void rufl_dump_state(void) } else { printf(" (no charset table)\n"); } - if (rufl_font_list[i].umap) { + if (verbose && rufl_font_list[i].umap) { for (j = 0; j < rufl_font_list[i].num_umaps; j++) { struct rufl_unicode_map *map = rufl_font_list[i].umap + j; @@ -90,7 +90,7 @@ static void rufl_dump_character_set(const struct rufl_character_set *charset) u++; } else { t = u; - while (rufl_character_set_test( + while (u != 0x10000 && rufl_character_set_test( charset, plane + u)) u++; printf("%x-%x ", plane + t, plane + u - 1); diff --git a/src/rufl_init.c b/src/rufl_init.c index 6ec21b7..6cf0be6 100644 --- a/src/rufl_init.c +++ b/src/rufl_init.c @@ -60,11 +60,13 @@ const struct rufl_weight_table_entry rufl_weight_table[] = { { "ExtraLight", 1 }, { "Heavy", 8 }, { "Light", 2 }, + { "MedBold", 6 }, { "Medium", 5 }, { "Regular", 4 }, { "Semi", 6 }, { "SemiBold", 6 }, { "SemiLight", 3 }, + { "Thin", 1 }, { "UltraBlack", 9 }, { "UltraBold", 9 }, }; @@ -470,31 +472,26 @@ static void rufl_init_shrinkwrap_plane(struct rufl_character_set *charset) for (byte = 0; byte != 32; byte++) bit &= charset->block[block][byte]; - if (bit == 0xff) { - /* Block is full */ - /* Find a block whose index is after this one. - * If such a block exists, move its data into - * this block, as this block's bitmap is now free - */ - for (byte = 0; byte != 256; byte++) { - if (charset->index[byte] < BLOCK_EMPTY && - charset->index[byte] > block) { - break; - } - } - if (byte != 256) { - memcpy(charset->block[block], - charset->block[ - charset->index[byte]], - 32); - charset->index[byte] = block; - } + if (bit != 0xff) + continue; - /* Now mark this block as full */ - charset->index[u] = BLOCK_FULL; - last_used--; + /* Block is full */ + + /* Move subsequent blocks up and rewrite their indices */ + memmove(charset->block[block], + charset->block[block+1], + (254-(block+1)) * 32); + for (byte = 0; byte != 256; byte++) { + if (charset->index[byte] < BLOCK_EMPTY && + charset->index[byte] > block) { + charset->index[byte]--; + } } + + /* Now mark this block as full */ + charset->index[u] = BLOCK_FULL; + last_used--; } /* Fill in this plane's size now we know it */ @@ -512,14 +509,11 @@ static struct rufl_character_set *rufl_init_shrinkwrap_planes( /* Shrink-wrap each plane, accumulating total required size as we go */ for (u = 0; u < 17; u++) { if (planes[u]) { - LOG("shrink-wrapping plane %d", u); rufl_init_shrinkwrap_plane(planes[u]); size += PLANE_SIZE(planes[u]->metadata); } } - LOG("shrink-wrapped size: %u", size); - charset = malloc(size); if (!charset) return NULL; @@ -531,8 +525,6 @@ static struct rufl_character_set *rufl_init_shrinkwrap_planes( if (!planes[u-1]) continue; - LOG("merging plane %d", u); - /* Set E bit if not the last plane */ if (pos != size) planes[u-1]->metadata |= (1u<<31); @@ -551,16 +543,56 @@ static rufl_code rufl_init_enumerate_characters(const char *font_name, uint32_t glyph_idx, uint32_t ucs4), void *pw) { - unsigned int u, next; - rufl_code result; + unsigned int u = 0, next, internal; + rufl_code result = rufl_OK; - if (rufl_broken_font_enumerate_characters) - return rufl_init_read_encoding(font, callback, pw); + if (rufl_broken_font_enumerate_characters) { + /* We know that any codepoints in the first chunk will + * be missed because Font_EnumerateCharacters is broken + * on this version of the Font Manager. Find the first + * codepoint it will report. */ + unsigned int first; + rufl_fm_error = xfont_enumerate_characters(font, 0, + (int *) &first, (int *) &internal); + if (rufl_fm_error) { + LOG("xfont_enumerate_characters(\"%s\", " + "U+%x, ...): 0x%x: %s", + font_name, 0, + rufl_fm_error->errnum, + rufl_fm_error->errmess); + return rufl_FONT_MANAGER_ERROR; + } - /* Scan through mapped characters */ - for (u = 0; u != (unsigned int) -1; u = next) { - unsigned int internal; + /* Search the entire space up to the first codepoint it + * reported. */ + for (u = 0; u != (unsigned int) -1 && u != first; u++) { + rufl_fm_error = xfont_enumerate_characters(font, u, + (int *) &next, (int *) &internal); + if (rufl_fm_error) { + LOG("xfont_enumerate_characters(\"%s\", " + "U+%x, ...): 0x%x: %s", + font_name, u, + rufl_fm_error->errnum, + rufl_fm_error->errmess); + result = rufl_FONT_MANAGER_ERROR; + break; + } + + /* Skip unmapped characters */ + if (internal == (unsigned int) -1) + continue; + + /* Character is mapped, emit it */ + result = callback(pw, internal, u); + if (result != rufl_OK) + break; + } + + /* Now fall through to the normal path */ + } + /* Scan through mapped characters */ + for (; u != (unsigned int) -1; u = next) { rufl_fm_error = xfont_enumerate_characters(font, u, (int *) &next, (int *) &internal); if (rufl_fm_error) { @@ -569,6 +601,7 @@ static rufl_code rufl_init_enumerate_characters(const char *font_name, font_name, u, rufl_fm_error->errnum, rufl_fm_error->errmess); + result = rufl_FONT_MANAGER_ERROR; break; } @@ -837,7 +870,20 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) 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 || + rufl_fm_error->errnum == + error_FONT_ENCODING_NOT_FOUND || + /* Neither is a too modern font */ + rufl_fm_error->errnum == + error_FONT_TOO_MANY_CHUNKS)) { + /* Ensure we reuse the currently allocated umap */ + num_umaps--; + } else if (code != rufl_OK) { LOG("rufl_init_scan_font_in_encoding(\"%s\", \"%s\", " "...): 0x%x (0x%x: %s)", font_name, encoding, code, @@ -846,23 +892,11 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) code == rufl_FONT_MANAGER_ERROR ? rufl_fm_error->errmess : ""); - /* 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 && - rufl_fm_error->errnum != - error_FONT_ENCODING_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--; + free(charset); + for (i = 0; i < num_umaps; i++) + free((umap + i)->encoding); + free(umap); + return code; } else { /* If this mapping is identical to an existing one, * then we can discard it */ @@ -901,7 +935,20 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) 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 || + rufl_fm_error->errnum == + error_FONT_ENCODING_NOT_FOUND || + /* Neither is a too modern font */ + rufl_fm_error->errnum == + error_FONT_TOO_MANY_CHUNKS)) { + /* Ensure we reuse the currently allocated umap */ + num_umaps--; + } else if (code != rufl_OK) { LOG("rufl_init_scan_font_in_encoding(\"%s\", NULL, " "...): 0x%x (0x%x: %s)", font_name, code, @@ -910,22 +957,11 @@ rufl_code rufl_init_scan_font_old(unsigned int font_index) code == rufl_FONT_MANAGER_ERROR ? rufl_fm_error->errmess : ""); - /* 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 && - rufl_fm_error->errnum != - error_FONT_ENCODING_NOT_FOUND)) { - free(charset); - for (i = 0; i < num_umaps; i++) - free((umap + i)->encoding); - free(umap); - return code; - } - - num_umaps--; + free(charset); + for (i = 0; i < num_umaps; i++) + free((umap + i)->encoding); + free(umap); + return code; } } @@ -984,8 +1020,7 @@ rufl_code rufl_init_scan_font_in_encoding(const char *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", buf, - rufl_fm_error->errnum, rufl_fm_error->errmess); + /* Leave it to our caller to log, if they wish */ return rufl_FONT_MANAGER_ERROR; } @@ -993,10 +1028,33 @@ rufl_code rufl_init_scan_font_in_encoding(const char *font_name, if (code != rufl_OK) { LOG("rufl_init_read_encoding(\"%s\", ...): 0x%x", buf, code); + umap->encoding = NULL; xfont_lose_font(font); return code; } + /* Detect attempts to use UCS fonts with a non-UCS Font Manager. + * There is a bug in all known non-UCS Font Managers which is + * often triggered by scanning many fonts. The Font Manager will + * attempt to dereference a bogus pointer (at the start of + * getbbox_unscaled) and thus cause an abort in SVC mode. + * Fallout can be as (relatively) benign as the application + * crashing or escalate to an entire system freeze requiring + * a reset. As there are no "good" outcomes here, and we do + * not have a time machine to go back and fix long-ago released + * Font Managers, ensure we ignore UCS fonts here. */ + if ((uint32_t) umap->encoding > 256) { + static os_error err = { + error_FONT_TOO_MANY_CHUNKS, "Rejecting UCS font"}; + LOG("%s", "Rejecting UCS font"); + umap->encoding = NULL; + xfont_lose_font(font); + rufl_fm_error = &err; + return rufl_FONT_MANAGER_ERROR; + } + /* Eliminate all trace of our (ab)use of the encoding field */ + umap->encoding = NULL; + for (i = 0; i != umap->entries; i++) { u = umap->map[i].u; string[0] = umap->map[i].c; @@ -1067,9 +1125,11 @@ static rufl_code rufl_init_umap_cb(void *pw, uint32_t glyph_idx, uint32_t ucs4) umap->map[umap->entries].u = ucs4; umap->map[umap->entries].c = glyph_idx; umap->entries++; - if (umap->entries == 256) - result = rufl_IO_EOF; } + /* Stash the total number of encoding file entries so that + * rufl_init_scan_font_in_encoding can detect the presence of a + * UCS font on a non-UCS capable system. It will clean up for us. */ + umap->encoding = (void *) (((uint32_t) umap->encoding) + 1); return result; } @@ -1085,7 +1145,7 @@ rufl_code rufl_init_populate_unicode_map(font_f f, umap->entries = 0; - result = rufl_init_read_encoding(f, rufl_init_umap_cb, &umap); + result = rufl_init_read_encoding(f, rufl_init_umap_cb, umap); if (result == rufl_OK) { /* sort by unicode */ qsort(umap->map, umap->entries, sizeof umap->map[0], @@ -1233,13 +1293,9 @@ rufl_code rufl_init_read_encoding(font_f font, } fp = fopen(filename, "r"); - if (!fp) { + if (!fp && rufl_old_font_manager) { /* many "symbol" fonts have no encoding file */ - const char *default_path = - "Resources:$.Fonts.Encodings./Default"; - if (rufl_old_font_manager) - default_path = "Resources:$.Fonts.Encodings.Latin1"; - fp = fopen(default_path, "r"); + fp = fopen("Resources:$.Fonts.Encodings.Latin1", "r"); } if (!fp) return rufl_IO_ERROR; @@ -1276,8 +1332,9 @@ rufl_code rufl_init_read_encoding(font_f font, (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '.') || (c == '_') || - (c == ';')) { - /* Printable: append */ + (c == ';') || + (c == ' ' && s[0] != '/')) { + /* Printable (or space in new-style): append */ s[n++] = c; if (n >= sizeof(s)) { /* Too long: garbage */ @@ -1430,12 +1487,7 @@ rufl_code rufl_save_cache(void) } /* character set (all planes) */ - LOG("writing character sets for %s", - rufl_font_list[i].identifier); while (EXTENSION_FOLLOWS(charset->metadata)) { - LOG("writing plane %d (%u)", - PLANE_ID(charset->metadata), - PLANE_SIZE(charset->metadata)); if (fwrite(charset, PLANE_SIZE(charset->metadata), 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); @@ -1445,9 +1497,6 @@ rufl_code rufl_save_cache(void) charset = (void *)(((uint8_t *)charset) + PLANE_SIZE(charset->metadata)); } - LOG("writing plane %d (%u)", - PLANE_ID(charset->metadata), - PLANE_SIZE(charset->metadata)); if (fwrite(charset, PLANE_SIZE(charset->metadata), 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); @@ -1606,7 +1655,6 @@ rufl_code rufl_load_cache(void) identifier[len] = 0; /* character set */ - LOG("reading character sets for %s", identifier); do { if (fread(&metadata, sizeof metadata, 1, fp) != 1) { if (feof(fp)) @@ -1618,9 +1666,6 @@ rufl_code rufl_load_cache(void) break; } - LOG("reading plane %d (%u)", - PLANE_ID(metadata), - PLANE_SIZE(metadata)); if (!charset) { charset = cur_charset = malloc( PLANE_SIZE(metadata)); diff --git a/test/rufl_test.c b/test/rufl_test.c index d939467..5b76f81 100644 --- a/test/rufl_test.c +++ b/test/rufl_test.c @@ -35,7 +35,7 @@ int main(void) int bbox[4]; try(rufl_init(), "rufl_init"); - rufl_dump_state(); + rufl_dump_state(false); try(rufl_paint("NewHall", rufl_WEIGHT_400, 240, utf8_test, sizeof utf8_test - 1, 1200, 1000, 0), "rufl_paint"); -- RISC OS Unicode Font Library _______________________________________________ netsurf-commits mailing list -- netsurf-commits@netsurf-browser.org To unsubscribe send an email to netsurf-commits-le...@netsurf-browser.org