[gs-commits] rev 11618 - in trunk/gs: base psi
ken at ghostscript.com
ken at ghostscript.com
Tue Aug 10 09:15:50 UTC 2010
Author: ken
Date: 2010-08-10 09:15:50 +0000 (Tue, 10 Aug 2010)
New Revision: 11618
Modified:
trunk/gs/base/gxfcopy.c
trunk/gs/base/gxfont1.h
trunk/gs/psi/zfont1.c
Log:
Enhancement : pdfwrite
performance enhancement for pdfwrite when handling files with large amounts of text.
Bug #689859 "Performance comparison versions 7.07 and 8.62 on HP-UX ia64" Alex's
analysis shows that pdfwrite was spending a lot of time trying to to see if two type 1
fonts were the same before deciding whether a glyph could be added to a font, or was
already present in a font copy.
Most of the time was spent extracting and comparing /Subrs. The new code creates a hash
(MD5) of both the local and global Subrs (if present) and stores that in the type 1
'data' field in the font (16 bytes). The hashes are created by pdfwrite only as they
are required, so there is no performance penalty for rendering. The hash comparison is
considerably quicker than the long winded Subrs comparison.
For many files the performance difference is minimal but for file containing lots of
pages, mostly composed of text, there is a considerable saving. The text files run in
about 60% of the time they did before this change.
Expected Differences
files 16-01.ps and 16-05.ps exhibit differences, I'm not sure why. However these are of
the 'wrong before, slightly differently wrong now' category, so I don't intend to
worry about these two files.
Modified: trunk/gs/base/gxfcopy.c
===================================================================
--- trunk/gs/base/gxfcopy.c 2010-08-10 08:13:35 UTC (rev 11617)
+++ trunk/gs/base/gxfcopy.c 2010-08-10 09:15:50 UTC (rev 11618)
@@ -37,6 +37,7 @@
#include "gxtype1.h" /* for Type 1 glyph_outline */
#include "gzstate.h" /* for path for BuildChar */
#include "gdevpsf.h"
+#include "smd5.h" /* Create MD5 hash of Subrs when comparing fonts */
#define GLYPHS_SIZE_IS_PRIME 1 /* Old code = 0, new code = 1. */
@@ -1101,57 +1102,47 @@
copied_encode_char, gs_type1_glyph_info, copied_type1_glyph_outline
};
-static bool
-same_type1_subrs(const gs_font_type1 *cfont, const gs_font_type1 *ofont,
- bool global)
+static void hash_subrs(gs_font_type1 *pfont)
{
- gs_glyph_data_t gdata0, gdata1;
- int i, code = 0;
- bool exit = false;
+ gs_type1_data *d0 = &pfont->data;
+ gs_glyph_data_t gdata0;
+ gs_md5_state_t md5;
+ int i, exit = 0;
- gdata0.memory = cfont->memory;
- gdata1.memory = ofont->memory;
+ gs_md5_init(&md5);
+ gdata0.memory = pfont->memory;
/* Scan the font to determine the size of the subrs. */
for (i = 0; !exit; i++) {
- int code0 = cfont->data.procs.subr_data((gs_font_type1 *)cfont,
- i, global, &gdata0);
- int code1 = ofont->data.procs.subr_data((gs_font_type1 *)ofont,
- i, global, &gdata1);
- bool missing0, missing1;
-
- if (code0 == gs_error_rangecheck && code1 == gs_error_rangecheck)
- return 1; /* Both arrays exceeded. */
- /* Some fonts use null for skiping elements in subrs array.
- This gives typecheck.
- */
- missing0 = (code0 == gs_error_rangecheck || code0 == gs_error_typecheck);
- missing1 = (code1 == gs_error_rangecheck || code1 == gs_error_typecheck);
- if (missing0 && missing1)
- continue;
- if (missing0 && !missing1)
- return 0; /* The copy has insufficient subrs. */
- if (missing1)
- continue;
+ int code0 = pfont->data.procs.subr_data((gs_font_type1 *)pfont,
+ i, true, &gdata0);
if (code0 < 0)
- code = code0, exit = true;
- else if (code1 < 0)
- code = code1, exit = true;
- else if (gdata0.bits.size != gdata1.bits.size)
exit = true;
- else if (memcmp(gdata0.bits.data, gdata1.bits.data, gdata0.bits.size))
+ else {
+ gs_md5_append(&md5, gdata0.bits.data, gdata0.bits.size);
+ gs_glyph_data_free(&gdata0, "hash_type1_subrs");
+ }
+ }
+ exit = 0;
+ /* Scan the font to determine the size of the subrs. */
+ for (i = 0; !exit; i++) {
+ int code0 = pfont->data.procs.subr_data((gs_font_type1 *)pfont,
+ i, false, &gdata0);
+ if (code0 < 0)
exit = true;
- if (code0 > 0)
- gs_glyph_data_free(&gdata0, "same_type1_subrs");
- if (code1 > 0)
- gs_glyph_data_free(&gdata1, "same_type1_subrs");
+ else {
+ gs_md5_append(&md5, gdata0.bits.data, gdata0.bits.size);
+ gs_glyph_data_free(&gdata0, "hash_type1_subrs");
}
- return code;
}
+ gs_md5_finish(&md5, d0->hash_subrs);
+}
static bool
same_type1_hinting(const gs_font_type1 *cfont, const gs_font_type1 *ofont)
{
const gs_type1_data *d0 = &cfont->data, *d1 = &ofont->data;
+ int *hash0 = (int *)&d0->hash_subrs;
+ int *hash1 = (int *)&d1->hash_subrs;
if (d0->lenIV != d1->lenIV)
return false;
@@ -1189,10 +1180,12 @@
return false;
if (!compare_tables(d0->WeightVector, d1->WeightVector))
return false;
- if (!same_type1_subrs(cfont, ofont, false))
+ if (hash0[0] == 0x00 && hash0[1] == 0x00 && hash0[2] == 0x00 && hash0[3] == 0x00)
+ hash_subrs((gs_font_type1 *)cfont);
+ if (hash1[0] == 0x00 && hash1[1] == 0x00 && hash1[2] == 0x00 && hash1[3] == 0x00)
+ hash_subrs((gs_font_type1 *)ofont);
+ if (memcmp(d0->hash_subrs, d1->hash_subrs, 16) != 0)
return false;
- if (!same_type1_subrs(cfont, ofont, true))
- return false;
/*
* We ignore differences in OtherSubrs because pdfwrite
* must build without PS interpreter and therefore copied font
Modified: trunk/gs/base/gxfont1.h
===================================================================
--- trunk/gs/base/gxfont1.h 2010-08-10 08:13:35 UTC (rev 11617)
+++ trunk/gs/base/gxfont1.h 2010-08-10 09:15:50 UTC (rev 11618)
@@ -137,6 +137,7 @@
/* Additional information for Multiple Master fonts */
#define max_WeightVector 16
float_array(max_WeightVector) WeightVector;
+ byte hash_subrs[16]; /* Used only for checking font copyign compatibility */
};
#define gs_type1_data_s_DEFINED
Modified: trunk/gs/psi/zfont1.c
===================================================================
--- trunk/gs/psi/zfont1.c 2010-08-10 08:13:35 UTC (rev 11617)
+++ trunk/gs/psi/zfont1.c 2010-08-10 09:15:50 UTC (rev 11618)
@@ -186,6 +186,12 @@
*/
if (pdata1->LanguageGroup > 1 || pdata1->LanguageGroup < 0)
pdata1->LanguageGroup = 0;
+ /* This is used only when determining if its possible to copy glyphs
+ * between fonts. Currenly only by pdfwrite and friends. Rather than
+ * check all the subrs (which we used to do) we hash tehm, store it
+ * and check the hashes. Zero except when in use by pdfwrite..
+ */
+ memset(&pdata1->hash_subrs, 0x00, 16);
return 0;
}
More information about the gs-commits
mailing list