summaryrefslogtreecommitdiff
path: root/src/freetype2/truetype/ttpload.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/freetype2/truetype/ttpload.c')
-rw-r--r--src/freetype2/truetype/ttpload.c81
1 files changed, 65 insertions, 16 deletions
diff --git a/src/freetype2/truetype/ttpload.c b/src/freetype2/truetype/ttpload.c
index 9d3381b..a311b03 100644
--- a/src/freetype2/truetype/ttpload.c
+++ b/src/freetype2/truetype/ttpload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007 by */
+/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -58,18 +58,23 @@
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
-
FT_LOCAL_DEF( FT_Error )
tt_face_load_loca( TT_Face face,
FT_Stream stream )
{
FT_Error error;
FT_ULong table_len;
+ FT_Int shift;
/* we need the size of the `glyf' table for malformed `loca' tables */
error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
- if ( error )
+
+ /* it is possible that a font doesn't have a glyf table at all */
+ /* or its size is zero */
+ if ( error == TT_Err_Table_Missing )
+ face->glyf_len = 0;
+ else if ( error )
goto Exit;
FT_TRACE2(( "Locations " ));
@@ -82,23 +87,65 @@
if ( face->header.Index_To_Loc_Format != 0 )
{
+ shift = 2;
+
if ( table_len >= 0x40000L )
{
- FT_TRACE2(( "table too large!\n" ));
+ FT_TRACE2(( "table too large\n" ));
error = TT_Err_Invalid_Table;
goto Exit;
}
- face->num_locations = (FT_UInt)( table_len >> 2 );
+ face->num_locations = table_len >> shift;
}
else
{
+ shift = 1;
+
if ( table_len >= 0x20000L )
{
- FT_TRACE2(( "table too large!\n" ));
+ FT_TRACE2(( "table too large\n" ));
error = TT_Err_Invalid_Table;
goto Exit;
}
- face->num_locations = (FT_UInt)( table_len >> 1 );
+ face->num_locations = table_len >> shift;
+ }
+
+ if ( face->num_locations != (FT_ULong)face->root.num_glyphs )
+ {
+ FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
+ face->num_locations, face->root.num_glyphs ));
+
+ /* we only handle the case where `maxp' gives a larger value */
+ if ( face->num_locations < (FT_ULong)face->root.num_glyphs )
+ {
+ FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift;
+
+ TT_Table entry = face->dir_tables;
+ TT_Table limit = entry + face->num_tables;
+
+ FT_Long pos = FT_Stream_Pos( stream );
+ FT_Long dist = 0x7FFFFFFFL;
+
+
+ /* compute the distance to next table in font file */
+ for ( ; entry < limit; entry++ )
+ {
+ FT_Long diff = entry->Offset - pos;
+
+
+ if ( diff > 0 && diff < dist )
+ dist = diff;
+ }
+
+ if ( new_loca_len <= dist )
+ {
+ face->num_locations = face->root.num_glyphs;
+ table_len = new_loca_len;
+
+ FT_TRACE2(( "adjusting num_locations to %d\n",
+ face->num_locations ));
+ }
+ }
}
/*
@@ -156,12 +203,14 @@
}
}
- /* It isn't mentioned explicitly that the `loca' table must be */
- /* ordered, but implicitly it refers to the length of an entry */
- /* as the difference between the current and the next position. */
- /* Anyway, there do exist (malformed) fonts which don't obey */
- /* this rule, so we are only able to provide an upper bound for */
- /* the size. */
+ /* The `loca' table must be ordered; it refers to the length of */
+ /* an entry as the difference between the current and the next */
+ /* position. However, there do exist (malformed) fonts which */
+ /* don't obey this rule, so we are only able to provide an */
+ /* upper bound for the size. */
+ /* */
+ /* We get (intentionally) a wrong, non-zero result in case the */
+ /* `glyf' table is missing. */
if ( pos2 >= pos1 )
*asize = (FT_UInt)( pos2 - pos1 );
else
@@ -216,7 +265,7 @@
error = face->goto_table( face, TTAG_cvt, stream, &table_len );
if ( error )
{
- FT_TRACE2(( "is missing!\n" ));
+ FT_TRACE2(( "is missing\n" ));
face->cvt_size = 0;
face->cvt = NULL;
@@ -301,7 +350,7 @@
face->font_program_size = 0;
error = TT_Err_Ok;
- FT_TRACE2(( "is missing!\n" ));
+ FT_TRACE2(( "is missing\n" ));
}
else
{
@@ -362,7 +411,7 @@
face->cvt_program_size = 0;
error = TT_Err_Ok;
- FT_TRACE2(( "is missing!\n" ));
+ FT_TRACE2(( "is missing\n" ));
}
else
{