[gs-commits] rev 12279 - trunk/gs/psi
chrisl at ghostscript.com
chrisl at ghostscript.com
Fri Mar 11 09:04:24 UTC 2011
Author: chrisl
Date: 2011-03-11 09:04:24 +0000 (Fri, 11 Mar 2011)
New Revision: 12279
Modified:
trunk/gs/psi/fapi_ft.c
trunk/gs/psi/zfapi.c
Log:
Some (broken) TrueType fonts have out of order loca tables, which can result
in the calculated glyph data lengths being larger than the actual
available glyph data. Normally this does not cause a problem, but if the glyph
in question is in the final bytes of the stream, we encounter an unexpected
end of data condition when creating the glyph data buffer to pass into
Freetype.
So the FAPI interface code will now ignore that error, and adjust the byte
length to correctly reflect the number of bytes available in the buffer.
It is safe to do this because, in the event we have a genuine out-of-data
condition, Freetype will return an error when it tries to interpret the
glyph outline.
Bug 692043
No cluster differences expected.
Modified: trunk/gs/psi/fapi_ft.c
===================================================================
--- trunk/gs/psi/fapi_ft.c 2011-03-11 07:10:56 UTC (rev 12278)
+++ trunk/gs/psi/fapi_ft.c 2011-03-11 09:04:24 UTC (rev 12279)
@@ -210,7 +210,9 @@
buffer = gs_malloc ((gs_memory_t *)a_info->fapi_font->memory, length, 1, "get_fapi_glyph_data");
if (!buffer)
return FT_Err_Out_Of_Memory;
- if (ff->get_glyph(ff, a_index, buffer, length) == 65535) {
+
+ length = ff->get_glyph(ff, a_index, buffer, length);
+ if (length == 65535) {
gs_free ((gs_memory_t *)a_info->fapi_font->memory, buffer, 0, 0, "get_fapi_glyph_data");
return FT_Err_Invalid_Glyph_Index;
}
@@ -245,7 +247,8 @@
}
a_info->glyph_data_length = length;
ff->char_data = saved_char_data;
- if ((ff->get_glyph(ff, a_index, a_info->glyph_data, length)) == -1)
+ length = ff->get_glyph(ff, a_index, a_info->glyph_data, length);
+ if (length == -1)
return FT_Err_Invalid_File_Format;
}
Modified: trunk/gs/psi/zfapi.c
===================================================================
--- trunk/gs/psi/zfapi.c 2011-03-11 07:10:56 UTC (rev 12278)
+++ trunk/gs/psi/zfapi.c 2011-03-11 09:04:24 UTC (rev 12279)
@@ -181,17 +181,25 @@
byte (*rbyte)(sfnts_reader *r);
ushort (*rword)(sfnts_reader *r);
ulong (*rlong)(sfnts_reader *r);
- void (*rstring)(sfnts_reader *r, byte *v, int length);
+ int (*rstring)(sfnts_reader *r, byte *v, int length);
void (*seek)(sfnts_reader *r, ulong pos);
};
static void sfnts_next_elem(sfnts_reader *r)
-{ ref s;
+{
+ ref s;
+ int code;
if (r->error)
return;
r->index++;
- r->error |= (array_get(r->memory, r->sfnts, r->index, &s) < 0);
+ code = array_get(r->memory, r->sfnts, r->index, &s);
+ if (code == e_rangecheck) {
+ r->error |= 2;
+ }
+ else if (code < 0) {
+ r->error |= 1;
+ }
if (r->error)
return;
r->p = s.value.const_bytes;
@@ -218,19 +226,23 @@
(sfnts_reader_rbyte_inline(r) << 8) + sfnts_reader_rbyte_inline(r);
}
-static void sfnts_reader_rstring(sfnts_reader *r, byte *v, int length)
-{ if (length < 0)
- return;
+static int sfnts_reader_rstring(sfnts_reader *r, byte *v, int length)
+{
+ int rlength = length;
+
+ if (length <= 0)
+ return(0);
while (!r->error) {
int l = min(length, r->length - r->offset);
memcpy(v, r->p + r->offset, l);
length -= l;
r->offset += l;
if (length <= 0)
- return;
+ return(rlength);
v += l;
sfnts_next_elem(r);
}
+ return(rlength - length);
}
static void sfnts_reader_seek(sfnts_reader *r, ulong pos)
@@ -327,7 +339,7 @@
while (length > 0 && !r->error) {
int l = min(length, sizeof(buf));
- r->rstring(r, buf, l);
+ (void)r->rstring(r, buf, l);
w->wstring(w, buf, l);
length -= l;
}
@@ -353,7 +365,7 @@
for (i = 0; i < num_tables; i++) {
if (r->error)
return 0;
- r->rstring(r, tables[i].tag, 4);
+ (void)r->rstring(r, tables[i].tag, 4);
tables[i].checkSum = r->rlong(r);
tables[i].offset = r->rlong(r);
tables[i].length = r->rlong(r);
@@ -642,10 +654,8 @@
}
else {
FontMatrix_div = (ff->is_cid && !IsCIDFont(pbfont) ? 1000 : 1);
-
mptr = &(pbfont->base->FontMatrix);
}
-
switch(index) {
case 0 : return mptr->xx / FontMatrix_div;
case 1 : return mptr->xy / FontMatrix_div;
@@ -1063,22 +1073,31 @@
memcpy(buf, data_ptr + mc, min(glyph_length, buf_length)/* safety */);
} else {
gs_font_type42 *pfont42 = (gs_font_type42 *)ff->client_font_data;
- ulong offset0;
+ ulong offset0, length_read;
bool error = sfnt_get_glyph_offset(pdr, pfont42, char_code, &offset0);
glyph_length = (error ? -1 : pfont42->data.len_glyphs[char_code]);
+
if (buf != 0 && !error) {
sfnts_reader r;
sfnts_reader_init(&r, pdr);
r.seek(&r, offset0);
- r.rstring(&r, buf, min(glyph_length, buf_length)/* safety */);
- if (r.error)
+ length_read = r.rstring(&r, buf, min(glyph_length, buf_length)/* safety */);
+ if (r.error == 1) {
glyph_length = -1;
}
+ /* r.error == 2 means a rangecheck, and probably means that the
+ * font is broken, and the final glyph length is longer than the data available for it.
+ * In which case we need to return the number of bytes read.
+ */
+ if (r.error == 2) {
+ glyph_length = length_read;
}
}
}
+ }
+ }
return glyph_length;
}
@@ -2570,12 +2589,12 @@
ref_assign(op, proc);
push_op_estack(zexec); /* execute the operand */
return o_push_estack;
- } else {
- if ((code = renderer_retcode(i_ctx_p, I, code)) < 0)
- return code;
}
}
+ if ((code = renderer_retcode(i_ctx_p, I, code)) < 0)
+ return code;
+
compute_em_scale(pbfont, &metrics, FontMatrix_div, &em_scale_x, &em_scale_y);
char_bbox.p.x = metrics.bbox_x0 / em_scale_x;
char_bbox.p.y = metrics.bbox_y0 / em_scale_y;
More information about the gs-commits
mailing list