[gs-cvs] rev 7882 - trunk/gs/src
leonardo at ghostscript.com
leonardo at ghostscript.com
Tue Apr 24 22:50:33 PDT 2007
Author: leonardo
Date: 2007-04-24 22:50:33 -0700 (Tue, 24 Apr 2007)
New Revision: 7882
Modified:
trunk/gs/src/gdevpsft.c
trunk/gs/src/gsfcid2.c
trunk/gs/src/gstype42.c
trunk/gs/src/gxfcopy.c
trunk/gs/src/gxfont42.h
Log:
Fix (TT fonts) : Allow sfnts string breaks inside TT tables.
DETAILS :
The old code is based on an antique Adobe constraint
"the strings must begin at TrueType table boundaries, or
at individual glyph boundaries within the glyf table".
In novadays many of 3d party software do not follow it.
We're dropping this constraint from GS code
because we tired fixing user problems with it.
This change is algorithnically equivalent for fonts,
which follow the constraint.
This change replaces ACCESS macro
(sll 3 definitions through Ghostscript sources)
with a new macro READ_SFNTS, which copies data to a local buffer,
and checks the length of the buffer.
We believe that the performance flaw is not sensible
and it worths the improved stability.
Correspondingly local pointer variables,
which were used with ACCESS macro,
are replaced with local buffers.
Sorry for keeping old names inspite of the popular convention -
we do not want too many changes in a single patch
to simplify its review.
In some places the new data copying could be eliminated because
the old code already copies the data.
We do not optimize it now,
becauase we want to simplify the patch review.
We believe that modern compilers can optimize it.
The new code still have few points,
which are based on the antique constraint.
One example is names in name table.
Will do further improvements someday.
The new code signals an error if
the constraint is used and not satisfied
(the old code doesn't with unpredictable result).
EXPECTED DIFFERENCES :
None.
Modified: trunk/gs/src/gdevpsft.c
===================================================================
--- trunk/gs/src/gdevpsft.c 2007-04-25 03:28:32 UTC (rev 7881)
+++ trunk/gs/src/gdevpsft.c 2007-04-25 05:50:33 UTC (rev 7882)
@@ -61,12 +61,6 @@
/* ---------------- Utilities ---------------- */
-#define ACCESS(base, length, vptr)\
- BEGIN\
- code = string_proc(pfont, (ulong)(base), length, &vptr);\
- if (code < 0) return code;\
- END
-
/* Pad to a multiple of 4 bytes. */
private void
put_pad(stream *s, uint length)
@@ -658,12 +652,9 @@
{
gs_font *const font = (gs_font *)pfont;
gs_const_string font_name;
- int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
- pfont->data.string_proc;
- const byte *OffsetTable;
+ byte OffsetTable[12];
uint numTables_stored, numTables, numTables_out;
-#define MAX_NUM_TABLES 40
- byte tables[MAX_NUM_TABLES * 16];
+ byte tables[MAX_NUM_TT_TABLES * 16];
uint i;
ulong offset;
gs_glyph glyph, glyph_prev;
@@ -706,20 +697,20 @@
* table directory.
*/
- ACCESS(0, 12, OffsetTable);
+ READ_SFNTS(pfont, 0, 12, OffsetTable);
numTables_stored = U16(OffsetTable + 4);
for (i = numTables = 0; i < numTables_stored; ++i) {
- const byte *tab;
- const byte *data;
+ byte tab[16];
+ byte data[54];
ulong start;
uint length;
- if (numTables == MAX_NUM_TABLES)
+ if (numTables == MAX_NUM_TT_TABLES)
return_error(gs_error_limitcheck);
- ACCESS(12 + i * 16, 16, tab);
+ READ_SFNTS(pfont, 12 + i * 16, 16, tab);
start = u32(tab + 8);
length = u32(tab + 12);
- /* Copy the table data now, since another ACCESS may invalidate it. */
+ /* Copy the table data now (a rudiment of old code). */
memcpy(&tables[numTables * 16], tab, 16);
#define W(a,b,c,d)\
@@ -730,7 +721,7 @@
if (length < 54)
return_error(gs_error_invalidfont);
length = 54; /* bug 688409 fig2.eps has length=56. */
- ACCESS(start, length, data);
+ READ_SFNTS(pfont, start, length, data);
memcpy(head, data, length);
continue;
case W('g','l','y','f'): /* synthesized */
@@ -745,7 +736,7 @@
have_cmap = true;
break;
case W('m','a','x','p'):
- ACCESS(start, length, data);
+ READ_SFNTS(pfont, start, length, data);
numGlyphs = U16(data + 4);
break;
case W('n','a','m','e'):
@@ -879,7 +870,7 @@
+ generate_mtx * (have_hvhea[0] + have_hvhea[1]) /* hmtx, vmtx */
+ !have_OS_2 /* OS/2 */
+ !have_cmap + !have_name + !have_post;
- if (numTables_out >= MAX_NUM_TABLES)
+ if (numTables_out >= MAX_NUM_TT_TABLES)
return_error(gs_error_limitcheck);
offset = 12 + numTables_out * 16;
for (i = 0; i < numTables; ++i) {
@@ -1001,10 +992,10 @@
* Adjust the first and last character indices in the OS/2
* table to reflect the values in the generated cmap.
*/
- const byte *pos2;
+ byte pos2[OS_2_LENGTH2];
ttf_OS_2_t os2;
- ACCESS(OS_2_start, OS_2_length, pos2);
+ READ_SFNTS(pfont, OS_2_start, OS_2_length, pos2);
memcpy(&os2, pos2, min(OS_2_length, sizeof(os2)));
update_OS_2(&os2, TT_BIAS, 256);
stream_write(s, &os2, OS_2_length);
Modified: trunk/gs/src/gsfcid2.c
===================================================================
--- trunk/gs/src/gsfcid2.c 2007-04-25 03:28:32 UTC (rev 7881)
+++ trunk/gs/src/gsfcid2.c 2007-04-25 05:50:33 UTC (rev 7882)
@@ -67,12 +67,6 @@
return 0;
}
-/* Set up a pointer to a substring of the font data. */
-#define ACCESS(base, length, vptr)\
- BEGIN\
- code = pfont->data.string_proc(pfont, (ulong)(base), length, &vptr);\
- if ( code < 0 ) return code;\
- END
#define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
#define U32(p) get_u32_msb(p)
#define PUT16(p, v)\
@@ -102,7 +96,7 @@
const gs_cmap_tt_16bit_format4_t *pcmap =
(const gs_cmap_tt_16bit_format4_t *)pcmap_in;
gs_font_type42 *pfont = pcmap->font;
- const byte *ttdata;
+ byte ttdata[2];
int code;
uint chr, value = 0;
uint segment2;
@@ -116,22 +110,22 @@
for (segment2 = 0; segment2 < pcmap->segCount2; segment2 += 2) {
uint start, delta, roff;
- ACCESS(pcmap->endCount + segment2, 2, ttdata);
+ READ_SFNTS(pfont, pcmap->endCount + segment2, 2, ttdata);
if (chr > U16(ttdata))
continue;
- ACCESS(pcmap->startCount + segment2, 2, ttdata);
+ READ_SFNTS(pfont, pcmap->startCount + segment2, 2, ttdata);
start = U16(ttdata);
if (chr < start)
continue;
- ACCESS(pcmap->idDelta + segment2, 2, ttdata);
+ READ_SFNTS(pfont, pcmap->idDelta + segment2, 2, ttdata);
delta = U16(ttdata);
- ACCESS(pcmap->idRangeOffset + segment2, 2, ttdata);
+ READ_SFNTS(pfont, pcmap->idRangeOffset + segment2, 2, ttdata);
roff = U16(ttdata);
if (roff) {
ulong gidoff = pcmap->idRangeOffset + segment2 + roff +
(chr - start) * 2;
- ACCESS(gidoff, 2, ttdata);
+ READ_SFNTS(pfont, gidoff, 2, ttdata);
value = U16(ttdata);
if (value != 0)
value += delta;
@@ -190,7 +184,7 @@
const gs_cmap_tt_16bit_format4_t *pcmap =
(const gs_cmap_tt_16bit_format4_t *)penum->cmap;
gs_font_type42 *pfont = pcmap->font;
- const byte *ttdata;
+ byte ttdata[2];
int code;
uint start, end, delta, roff;
uint value;
@@ -198,26 +192,26 @@
top:
if (segment2 >= pcmap->segCount2)
return 1;
- ACCESS(pcmap->endCount + segment2, 2, ttdata);
+ READ_SFNTS(pfont, pcmap->endCount + segment2, 2, ttdata);
end = U16(ttdata);
if (next > end) {
segment2 += 2;
goto top;
}
- ACCESS(pcmap->startCount + segment2, 2, ttdata);
+ READ_SFNTS(pfont, pcmap->startCount + segment2, 2, ttdata);
start = U16(ttdata);
if (next < start)
next = start;
PUT16(penum->entry.key[0], next);
- ACCESS(pcmap->idDelta + segment2, 2, ttdata);
+ READ_SFNTS(pfont, pcmap->idDelta + segment2, 2, ttdata);
delta = U16(ttdata);
- ACCESS(pcmap->idRangeOffset + segment2, 2, ttdata);
+ READ_SFNTS(pfont, pcmap->idRangeOffset + segment2, 2, ttdata);
roff = U16(ttdata);
if (roff) {
/* Non-zero offset, table lookup. */
ulong gidoff = pcmap->idRangeOffset + segment2 + roff;
- ACCESS(gidoff, 2, ttdata);
+ READ_SFNTS(pfont, gidoff, 2, ttdata);
value = U16(ttdata);
if (value != 0)
value += delta;
@@ -263,7 +257,7 @@
ulong origin = pfont->data.cmap;
gs_cmap_tt_16bit_format4_t *pcmap;
int code;
- const byte *ttdata;
+ byte ttdata[2];
ulong offset = origin;
uint segCount2;
@@ -277,23 +271,23 @@
uint cmap_count;
uint i;
- ACCESS(origin + 2, 2, ttdata);
+ READ_SFNTS(pfont, origin + 2, 2, ttdata);
cmap_count = U16(ttdata);
for (i = 0; i < cmap_count; ++i) {
- ACCESS(origin + 4 + i * 8, 8, ttdata);
+ READ_SFNTS(pfont, origin + 4 + i * 8, 8, ttdata);
if (U16(ttdata) != 3 || /* platform ID */
U16(ttdata + 2) != 1 /* encoding ID */
)
continue;
offset = origin + U32(ttdata + 4);
- ACCESS(offset, 2, ttdata);
+ READ_SFNTS(pfont, offset, 2, ttdata);
if (U16(ttdata) != 4 /* format */)
continue;
break;
}
if (i >= cmap_count) /* not found */
return_error(gs_error_invalidfont);
- ACCESS(offset + 6, 2, ttdata);
+ READ_SFNTS(pfont, offset + 6, 2, ttdata);
segCount2 = U16(ttdata);
}
Modified: trunk/gs/src/gstype42.c
===================================================================
--- trunk/gs/src/gstype42.c 2007-04-25 03:28:32 UTC (rev 7881)
+++ trunk/gs/src/gstype42.c 2007-04-25 05:50:33 UTC (rev 7882)
@@ -49,15 +49,6 @@
font_proc_font_info(gs_type42_font_info); /* Type check. */
font_proc_font_info(gs_truetype_font_info); /* Type check. */
-/* Set up a pointer to a substring of the font data. */
-/* Free variables: pfont, string_proc. */
-#define ACCESS(base, length, vptr)\
- BEGIN\
- code = (*string_proc)(pfont, (ulong)(base), length, &vptr);\
- if ( code < 0 ) return code;\
- if ( code > 0 ) return_error(gs_error_invalidfont);\
- END
-
/* Get 2- or 4-byte quantities from a table. */
#define U8(p) ((uint)((p)[0]))
#define S8(p) (int)((U8(p) ^ 0x80) - 0x80)
@@ -70,7 +61,7 @@
GS_NOTIFY_PROC(gs_len_glyphs_release);
/* Read data from sfnts. */
-private int
+int
gs_type42_read_data(gs_font_type42 * pfont, ulong pos, uint length, byte *buf)
{
int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
@@ -97,23 +88,22 @@
{
ulong result;
byte buf[4];
+ int code;
+ /* Hack : when reading fails, we return a huge offset.
+ Then gs_type42_font_init will fails because it is greater than loca size.
+ Fixme : improve with changing the function prototype.
+ */
if (pfont->data.indexToLocFormat) {
- gs_type42_read_data(pfont, pfont->data.loca + glyph_index * 4, 4, buf);
- result = u32(buf);
+ code = gs_type42_read_data(pfont, pfont->data.loca + glyph_index * 4, 4, buf);
+ result = (code < 0 ? 0xffffffff : u32(buf));
} else {
- gs_type42_read_data(pfont, pfont->data.loca + glyph_index * 2, 2, buf);
- result = (ulong) U16(buf) << 1;
+ code = gs_type42_read_data(pfont, pfont->data.loca + glyph_index * 2, 2, buf);
+ result = (code < 0 ? 0xffffffff : (ulong) U16(buf) << 1);
}
return result;
}
-/*
- * Initialize the cached values in a Type 42 font.
- * 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;
@@ -134,14 +124,20 @@
((const gs_type42_font_init_sort_t *)b)->glyph_num;
}
+/*
+ * Initialize the cached values in a Type 42 font.
+ * Note that this initializes the type42_data procedures other than
+ * string_proc, and the font procedures as well.
+ */
+
int
gs_type42_font_init(gs_font_type42 * pfont, int subfontID)
{
int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
pfont->data.string_proc;
- const byte *OffsetTable;
+ byte OffsetTable[12];
uint numTables;
- const byte *TableDirectory;
+ byte TableDirectory[MAX_NUM_TT_TABLES * 16];
uint i;
int code;
byte head_box[8];
@@ -154,15 +150,15 @@
static const byte version_true[4] = {'t', 'r', 'u', 'e'};
static const byte version_ttcf[4] = {'t', 't', 'c', 'f'};
- ACCESS(0, 12, OffsetTable);
+ READ_SFNTS(pfont, 0, 12, OffsetTable);
if (!memcmp(OffsetTable, version_ttcf, 4))
{
numFonts = u32(OffsetTable + 8);
if (subfontID < 0 || subfontID >= numFonts)
return_error(gs_error_rangecheck);
- ACCESS(12, numFonts * 4, OffsetTable);
- OffsetTableOffset = u32(OffsetTable + subfontID * 4);
- ACCESS(OffsetTableOffset, 12, OffsetTable);
+ READ_SFNTS(pfont, 12 + subfontID * 4, 4, OffsetTable);
+ OffsetTableOffset = u32(OffsetTable);
+ READ_SFNTS(pfont, OffsetTableOffset, 12, OffsetTable);
}
else
{
@@ -174,7 +170,9 @@
return_error(gs_error_invalidfont);
numTables = U16(OffsetTable + 4);
- ACCESS(OffsetTableOffset + 12, numTables * 16, TableDirectory);
+ if (numTables > MAX_NUM_TT_TABLES)
+ return_error(gs_error_invalidfont);
+ READ_SFNTS(pfont, OffsetTableOffset + 12, numTables * 16, TableDirectory);
/* Clear all non-client-supplied data. */
{
void *proc_data = pfont->data.proc_data;
@@ -193,16 +191,16 @@
pfont->data.glyf = offset;
glyph_size = (uint)u32(tab + 12);
} else if (!memcmp(tab, "head", 4)) {
- const byte *head;
+ byte head[54];
- ACCESS(offset, 54, head);
+ READ_SFNTS(pfont, offset, 54, head);
pfont->data.unitsPerEm = U16(head + 18);
memcpy(head_box, head + 36, 8);
pfont->data.indexToLocFormat = U16(head + 50);
} else if (!memcmp(tab, "hhea", 4)) {
- const byte *hhea;
+ byte hhea[36];
- ACCESS(offset, 36, hhea);
+ READ_SFNTS(pfont, offset, 36, hhea);
pfont->data.metrics[0].numMetrics = U16(hhea + 34);
} else if (!memcmp(tab, "hmtx", 4)) {
pfont->data.metrics[0].offset = offset;
@@ -211,16 +209,16 @@
pfont->data.loca = offset;
loca_size = u32(tab + 12);
} else if (!memcmp(tab, "maxp", 4)) {
- const byte *maxp;
+ byte maxp[30];
- ACCESS(offset, 30, maxp);
+ READ_SFNTS(pfont, offset, 30, maxp);
pfont->data.trueNumGlyphs = U16(maxp + 4);
} else if (!memcmp(tab, "name", 4)) {
pfont->data.name_offset = offset;
} else if (!memcmp(tab, "vhea", 4)) {
- const byte *vhea;
+ byte vhea[36];
- ACCESS(offset, 36, vhea);
+ READ_SFNTS(pfont, offset, 36, vhea);
pfont->data.metrics[1].numMetrics = U16(vhea + 34);
} else if (!memcmp(tab, "vmtx", 4)) {
pfont->data.metrics[1].offset = offset;
@@ -774,8 +772,6 @@
simple_glyph_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
float sbw[4])
{
- int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
- pfont->data.string_proc;
double factor = 1.0 / pfont->data.unitsPerEm;
uint width;
int lsb;
@@ -784,24 +780,24 @@
{
const gs_type42_mtx_t *pmtx = &pfont->data.metrics[wmode];
uint num_metrics = pmtx->numMetrics;
- const byte *pmetrics;
+ byte pmetrics[4];
if (pmtx->length == 0)
return_error(gs_error_rangecheck);
if (glyph_index < num_metrics) {
- ACCESS(pmtx->offset + glyph_index * 4, 4, pmetrics);
+ READ_SFNTS(pfont, pmtx->offset + glyph_index * 4, 4, pmetrics);
width = U16(pmetrics);
lsb = S16(pmetrics + 2);
} else {
uint offset = pmtx->offset + num_metrics * 4;
uint glyph_offset = (glyph_index - num_metrics) * 2;
- const byte *plsb;
+ byte plsb[2];
- ACCESS(offset - 4, 4, pmetrics);
+ READ_SFNTS(pfont, offset - 4, 4, pmetrics);
width = U16(pmetrics);
if (glyph_offset >= pmtx->length)
glyph_offset = pmtx->length - 2;
- ACCESS(offset + glyph_offset, 2, plsb);
+ READ_SFNTS(pfont, offset + glyph_offset, 2, plsb);
lsb = S16(plsb);
}
}
@@ -1246,17 +1242,17 @@
{
int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
pfont->data.string_proc;
- const byte *t;
+ byte t[12];
ushort num_records, strings_offset, i, language_id = 0xffff, length0 = 0, offset0 = 0;
int code;
- ACCESS(pfont->data.name_offset + 2, 4, t);
+ READ_SFNTS(pfont, pfont->data.name_offset + 2, 4, t);
num_records = U16(t);
strings_offset = U16(t + 2);
for (i = 0; i < num_records; i++) {
ushort platformID, specificID, languageID, nameID, length, offset;
- ACCESS(pfont->data.name_offset + 6 + i * 12, 12, t);
+ READ_SFNTS(pfont, pfont->data.name_offset + 6 + i * 12, 12, t);
platformID = U16(t + 0);
specificID = U16(t + 2);
languageID = U16(t + 4);
@@ -1276,8 +1272,9 @@
}
if (language_id == 0xffff)
return 0;
- ACCESS(pfont->data.name_offset + strings_offset + offset0, length0, t);
- pmember->data = t;
+ if ((*string_proc)(pfont, pfont->data.name_offset + strings_offset + offset0,
+ length0, &pmember->data) != 0)
+ return_error(gs_error_invalidfont);
pmember->size = length0;
info->members |= member;
return 0;
Modified: trunk/gs/src/gxfcopy.c
===================================================================
--- trunk/gs/src/gxfcopy.c 2007-04-25 03:28:32 UTC (rev 7881)
+++ trunk/gs/src/gxfcopy.c 2007-04-25 05:50:33 UTC (rev 7882)
@@ -1408,7 +1408,6 @@
access_type42_data(gs_font_type42 *pfont, ulong base, ulong length,
const byte **vptr)
{
- /* See ACCESS macro in gstype42.c */
return pfont->data.string_proc(pfont, base, length, vptr);
}
@@ -1489,8 +1488,6 @@
return 1;
}
-#undef ACCESS
-
/* ------ CIDFont shared ------ */
private int
Modified: trunk/gs/src/gxfont42.h
===================================================================
--- trunk/gs/src/gxfont42.h 2007-04-25 03:28:32 UTC (rev 7881)
+++ trunk/gs/src/gxfont42.h 2007-04-25 05:50:33 UTC (rev 7882)
@@ -128,6 +128,21 @@
*/
int gs_type42_font_init(gs_font_type42 *pfont, int subfontid);
+/* Read data from sfnts. */
+int gs_type42_read_data(gs_font_type42 * pfont, ulong pos, uint length, byte *buf);
+
+/* Read data from sfnts. */
+/* A temporary macro for simplifying the old code change. */
+#define READ_SFNTS(pfont, pos, length, buf)\
+ BEGIN\
+ if (length > sizeof(buf))\
+ return_error(gs_error_unregistered);/* Must not happen. */\
+ code = gs_type42_read_data(pfont, (ulong)(pos), length, buf);\
+ if ( code < 0 ) return code;\
+ END
+
+#define MAX_NUM_TT_TABLES 40
+
/* Append the outline of a TrueType character to a path. */
int gs_type42_append(uint glyph_index, gs_state * pgs,
gx_path * ppath, gs_text_enum_t *penum, gs_font *pfont,
More information about the gs-cvs
mailing list