[gs-cvs] rev 7877 - trunk/gs/src
leonardo at ghostscript.com
leonardo at ghostscript.com
Mon Apr 23 14:46:19 PDT 2007
Author: leonardo
Date: 2007-04-23 14:46:19 -0700 (Mon, 23 Apr 2007)
New Revision: 7877
Modified:
trunk/gs/src/gstype42.c
Log:
Fix (TT fonts) : A faster computation of glyph lengthes.
DETAILS :
This is a partial fix for bug 688971
"huge performace problem (with large TT font?)".
Thanks to SaGS for idea to apply a *stable* sorting algorithm
for computing len_glyphs. See comment in code.
EXPECTED DIFFERENCES :
None.
Modified: trunk/gs/src/gstype42.c
===================================================================
--- trunk/gs/src/gstype42.c 2007-04-23 19:31:20 UTC (rev 7876)
+++ trunk/gs/src/gstype42.c 2007-04-23 21:46:19 UTC (rev 7877)
@@ -34,6 +34,7 @@
#include "gxistate.h"
#include "gzstate.h"
#include "stream.h"
+#include <stdlib.h> /* for qsort */
/* Structure descriptor */
public_st_gs_font_type42();
@@ -93,6 +94,27 @@
* Note that this initializes the type42_data procedures other than
* string_proc, and the font procedures as well.
*/
+
+/* compare fn used by gs_type42_font_init() for sorting the 'loca' table */
+typedef struct gs_type42_font_init_sort_s {
+ ulong glyph_offset;
+ int glyph_num;
+} gs_type42_font_init_sort_t;
+private int
+gs_type42_font_init_compare (const void *a, const void *b)
+{
+ ulong a_offset = ((const gs_type42_font_init_sort_t *)a)->glyph_offset;
+ ulong b_offset = ((const gs_type42_font_init_sort_t *)b)->glyph_offset;
+ if (a_offset < b_offset)
+ return -1;
+ else if (a_offset > b_offset)
+ return +1;
+ else
+ /* make the sort stable */
+ return ((const gs_type42_font_init_sort_t *)a)->glyph_num -
+ ((const gs_type42_font_init_sort_t *)b)->glyph_num;
+}
+
int
gs_type42_font_init(gs_font_type42 * pfont, int subfontID)
{
@@ -105,7 +127,7 @@
int code;
byte head_box[8];
ulong loca_size = 0;
- ulong glyph_start, glyph_offset, glyph_length;
+ ulong glyph_start, glyph_offset, glyph_length, glyph_size = 0;
uint numFonts;
uint OffsetTableOffset;
@@ -148,9 +170,10 @@
if (!memcmp(tab, "cmap", 4))
pfont->data.cmap = offset;
- else if (!memcmp(tab, "glyf", 4))
+ else if (!memcmp(tab, "glyf", 4)) {
pfont->data.glyf = offset;
- else if (!memcmp(tab, "head", 4)) {
+ glyph_size = (uint)u32(tab + 12);
+ } else if (!memcmp(tab, "head", 4)) {
const byte *head;
ACCESS(offset, 54, head);
@@ -223,7 +246,7 @@
pfont->data.get_metrics = gs_type42_default_get_metrics;
/* Now build the len_glyphs array since 'loca' may not be properly sorted */
- pfont->data.len_glyphs = (uint *)gs_alloc_bytes(pfont->memory, pfont->data.numGlyphs * sizeof(uint),
+ pfont->data.len_glyphs = (uint *)gs_alloc_byte_array(pfont->memory, pfont->data.numGlyphs, sizeof(uint),
"gs_type42_font");
if (pfont->data.len_glyphs == 0)
return_error(gs_error_VMerror);
@@ -242,26 +265,44 @@
glyph_start = glyph_offset;
}
if (i < loca_size) {
- uint j;
- ulong trial_glyph_length;
/*
- * loca was out of order, build the len_glyphs the hard way
- * Assume that some of the len_glyphs built so far may be wrong
- * For each starting offset, find the next higher ending offset
- * Note that doing this means that there can only be zero length
- * glyphs that have loca table offset equal to the last 'dummy'
- * entry. Otherwise we assume that it is a duplicated entry.
+ * loca was out of order, build the len_glyphs the hard way.
+ * For each glyph, we use the next higher (but not
+ * equal) starting offset to compute the glyph length.
+ * It implies that only the last glyph may be empty.
+ * Other glyphs, if they have same offsets, are considered as duplicates.
*/
- for (i = 0; i < loca_size - 1; i++) {
- glyph_start = get_glyph_offset(pfont, i);
- for (j = 1, glyph_length = 0x80000000; j < loca_size; j++) {
- glyph_offset = get_glyph_offset(pfont, j);
- trial_glyph_length = glyph_offset - glyph_start;
- if ((trial_glyph_length > 0) && (trial_glyph_length < glyph_length))
- glyph_length = trial_glyph_length;
+ ulong last_glyph_length = 0, last_glyph_offset = glyph_size;
+ gs_type42_font_init_sort_t *psort;
+ gs_type42_font_init_sort_t *psortary =
+ (gs_type42_font_init_sort_t *)gs_alloc_byte_array(pfont->memory,
+ loca_size, sizeof(gs_type42_font_init_sort_t), "gs_type42_font_init(sort loca)");
+
+ if (psortary == 0)
+ return_error(gs_error_VMerror);
+ for (i = 0, psort = psortary; i < loca_size; i++, psort++) {
+ psort->glyph_num = i;
+ psort->glyph_offset = get_glyph_offset(pfont, i);
}
- pfont->data.len_glyphs[i] = glyph_length < 0x80000000 ? glyph_length : 0;
+ qsort(psortary, loca_size, sizeof(gs_type42_font_init_sort_t), gs_type42_font_init_compare);
+ last_glyph_length = 0;
+ if (psortary[loca_size - 1].glyph_offset > glyph_size)
+ return_error(gs_error_invalidfont);
+ for (i = loca_size; i--;) {
+ psort = psortary + i;
+ glyph_length = last_glyph_offset - psort->glyph_offset;
+ if (glyph_length == 0)
+ glyph_length = last_glyph_length;
+ else
+ last_glyph_length = glyph_length;
+ pfont->data.len_glyphs[psort->glyph_num] = glyph_length;
+ last_glyph_offset = psort->glyph_offset;
}
+ /* Well the last element of len_glyphs is never used.
+ We compute it because we're interesting whether it is not zero sometimes.
+ To know that, set a conditional breakpoint at the next statement.
+ */
+ gs_free_object(pfont->memory, psortary, "gs_type42_font_init(sort loca)");
}
/*
* If the font doesn't have a valid FontBBox, compute one from the
More information about the gs-cvs
mailing list