From aacb8e1368a883fcbc9fe64fd0e460cef9c9b20c Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Tue, 14 Sep 2010 17:02:58 -0700 Subject: upgrade freetype to 2.4.2. Bug: 2969145 Change-Id: I8debbbe0bd478d9cf8c39cff5179981b5f3b371a --- src/autofit/afcjk.c | 8 +- src/autofit/afglobal.c | 11 +- src/autofit/afglobal.h | 2 +- src/autofit/afhints.c | 133 +-------------- src/autofit/afhints.h | 5 +- src/autofit/aflatin.c | 6 +- src/autofit/aflatin2.c | 83 ++++----- src/autofit/afloader.c | 14 +- src/autofit/afpic.c | 18 +- src/base/ftbbox.c | 10 +- src/base/ftgloadr.c | 4 +- src/base/ftglyph.c | 4 +- src/base/ftinit.c | 5 +- src/base/ftlcdfil.c | 37 +++- src/base/ftobjs.c | 279 +++++++++++++++++++++++-------- src/base/ftoutln.c | 7 +- src/base/ftpatent.c | 2 +- src/base/ftrfork.c | 4 +- src/base/ftstream.c | 16 +- src/base/ftsystem.c | 9 +- src/cff/cffcmap.c | 31 ++-- src/cff/cffdrivr.c | 78 ++++----- src/cff/cffgload.c | 132 +++++++++------ src/cff/cffload.c | 193 ++++++++++++--------- src/cff/cffload.h | 16 +- src/cff/cffobjs.c | 134 +++++++++------ src/cff/cffparse.c | 21 ++- src/cff/cffpic.c | 16 +- src/cff/cfftypes.h | 21 ++- src/psaux/afmparse.c | 4 +- src/psaux/afmparse.h | 3 +- src/psaux/psobjs.c | 12 +- src/psaux/t1decode.c | 8 +- src/pshinter/pshalgo.c | 12 +- src/pshinter/pshglob.c | 4 +- src/pshinter/pshpic.c | 16 +- src/psnames/psmodule.c | 6 +- src/psnames/pspic.c | 14 +- src/raster/ftmisc.h | 16 +- src/raster/ftraster.c | 28 ++-- src/raster/rastpic.c | 13 +- src/sfnt/sfdriver.c | 16 +- src/sfnt/sfntpic.c | 13 +- src/sfnt/sfobjs.c | 12 +- src/sfnt/ttbdf.c | 16 +- src/sfnt/ttcmap.c | 22 ++- src/sfnt/ttkern.c | 6 +- src/sfnt/ttload.c | 15 +- src/sfnt/ttsbit.c | 5 +- src/smooth/ftgrays.c | 53 +++--- src/smooth/ftsmooth.c | 4 +- src/smooth/ftspic.c | 13 +- src/truetype/ttgload.c | 109 +++++++++--- src/truetype/ttgxvar.c | 12 +- src/truetype/ttinterp.c | 436 ++++++++++++++++++++++++++++++++++++++++-------- src/truetype/ttinterp.h | 12 +- src/truetype/ttpic.c | 14 +- 57 files changed, 1393 insertions(+), 800 deletions(-) (limited to 'src') diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c index ae64422..f3b1067 100644 --- a/src/autofit/afcjk.c +++ b/src/autofit/afcjk.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for CJK script (body). */ /* */ -/* Copyright 2006, 2007, 2008, 2009 by */ +/* Copyright 2006, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -60,8 +60,8 @@ face->charmap = NULL; else { - /* latin's version would suffice */ - af_latin_metrics_init_widths( metrics, face, 0x7530 ); + /* latin's version would suffice */ + af_latin_metrics_init_widths( metrics, face, 0x7530 ); af_latin_metrics_check_digits( metrics, face ); } @@ -1371,7 +1371,7 @@ FT_UNUSED( metrics ); - error = af_glyph_hints_reload( hints, outline, 0 ); + error = af_glyph_hints_reload( hints, outline ); if ( error ) goto Exit; diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c index ac29361..178c884 100644 --- a/src/autofit/afglobal.c +++ b/src/autofit/afglobal.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter routines to compute global hinting values (body). */ /* */ -/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -167,8 +167,11 @@ for ( nn = 0; nn < globals->glyph_count; nn++ ) { - if ( gscripts[nn] == AF_SCRIPT_LIST_NONE ) - gscripts[nn] = AF_SCRIPT_LIST_DEFAULT; + if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_LIST_NONE ) + { + gscripts[nn] &= ~AF_SCRIPT_LIST_NONE; + gscripts[nn] |= AF_SCRIPT_LIST_DEFAULT; + } } } @@ -183,7 +186,7 @@ { FT_Error error; FT_Memory memory; - AF_FaceGlobals globals; + AF_FaceGlobals globals = NULL; memory = face->memory; diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h index 0d8fb5f..2a68e19 100644 --- a/src/autofit/afglobal.h +++ b/src/autofit/afglobal.h @@ -60,7 +60,7 @@ FT_BEGIN_HEADER af_face_globals_is_digit( AF_FaceGlobals globals, FT_UInt gindex ); - /* */ + /* */ FT_END_HEADER diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c index a5aec80..c349709 100644 --- a/src/autofit/afhints.c +++ b/src/autofit/afhints.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines (body). */ /* */ -/* Copyright 2003, 2004, 2005, 2006, 2007, 2009 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -377,120 +377,6 @@ } - /* compute all inflex points in a given glyph */ - - static void - af_glyph_hints_compute_inflections( AF_GlyphHints hints ) - { - AF_Point* contour = hints->contours; - AF_Point* contour_limit = contour + hints->num_contours; - - - /* do each contour separately */ - for ( ; contour < contour_limit; contour++ ) - { - AF_Point point = contour[0]; - AF_Point first = point; - AF_Point start = point; - AF_Point end = point; - AF_Point before; - AF_Point after; - FT_Pos in_x, in_y, out_x, out_y; - AF_Angle orient_prev, orient_cur; - FT_Int finished = 0; - - - /* compute first segment in contour */ - first = point; - - start = end = first; - do - { - end = end->next; - if ( end == first ) - goto Skip; - - in_x = end->fx - start->fx; - in_y = end->fy - start->fy; - - } while ( in_x == 0 && in_y == 0 ); - - /* extend the segment start whenever possible */ - before = start; - do - { - do - { - start = before; - before = before->prev; - if ( before == first ) - goto Skip; - - out_x = start->fx - before->fx; - out_y = start->fy - before->fy; - - } while ( out_x == 0 && out_y == 0 ); - - orient_prev = ft_corner_orientation( in_x, in_y, out_x, out_y ); - - } while ( orient_prev == 0 ); - - first = start; - - in_x = out_x; - in_y = out_y; - - /* now process all segments in the contour */ - do - { - /* first, extend current segment's end whenever possible */ - after = end; - do - { - do - { - end = after; - after = after->next; - if ( after == first ) - finished = 1; - - out_x = after->fx - end->fx; - out_y = after->fy - end->fy; - - } while ( out_x == 0 && out_y == 0 ); - - orient_cur = ft_corner_orientation( in_x, in_y, out_x, out_y ); - - } while ( orient_cur == 0 ); - - if ( ( orient_prev + orient_cur ) == 0 ) - { - /* we have an inflection point here */ - do - { - start->flags |= AF_FLAG_INFLECTION; - start = start->next; - - } while ( start != end ); - - start->flags |= AF_FLAG_INFLECTION; - } - - start = end; - end = after; - - orient_prev = orient_cur; - in_x = out_x; - in_y = out_y; - - } while ( !finished ); - - Skip: - ; - } - } - - FT_LOCAL_DEF( void ) af_glyph_hints_init( AF_GlyphHints hints, FT_Memory memory ) @@ -551,8 +437,7 @@ FT_LOCAL_DEF( FT_Error ) af_glyph_hints_reload( AF_GlyphHints hints, - FT_Outline* outline, - FT_Bool get_inflections ) + FT_Outline* outline ) { FT_Error error = AF_Err_Ok; AF_Point points; @@ -639,13 +524,11 @@ { FT_Vector* vec = outline->points; char* tag = outline->tags; - AF_Point first = points; AF_Point end = points + outline->contours[0]; AF_Point prev = end; FT_Int contour_index = 0; - FT_UNUSED( first ); for ( point = points; point < point_limit; point++, vec++, tag++ ) { point->fx = (FT_Short)vec->x; @@ -673,9 +556,8 @@ { if ( ++contour_index < outline->n_contours ) { - first = point + 1; - end = points + outline->contours[contour_index]; - prev = end; + end = points + outline->contours[contour_index]; + prev = end; } } } @@ -752,11 +634,6 @@ } } - /* compute inflection points -- */ - /* disabled due to no longer perceived benefits */ - if ( 0 && get_inflections ) - af_glyph_hints_compute_inflections( hints ); - Exit: return error; } @@ -942,7 +819,7 @@ { FT_PtrDist min, max, mid; - FT_Pos fpos; + FT_Pos fpos; /* find enclosing edges */ diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h index 6758268..10e673b 100644 --- a/src/autofit/afhints.h +++ b/src/autofit/afhints.h @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines (specification). */ /* */ -/* Copyright 2003, 2004, 2005, 2006, 2007, 2008 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -286,8 +286,7 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) af_glyph_hints_reload( AF_GlyphHints hints, - FT_Outline* outline, - FT_Bool get_inflections ); + FT_Outline* outline ); FT_LOCAL( void ) af_glyph_hints_save( AF_GlyphHints hints, diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c index e6882d5..8c6c430 100644 --- a/src/autofit/aflatin.c +++ b/src/autofit/aflatin.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for latin script (body). */ /* */ -/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -77,7 +77,7 @@ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy ); - error = af_glyph_hints_reload( hints, &face->glyph->outline, 0 ); + error = af_glyph_hints_reload( hints, &face->glyph->outline ); if ( error ) goto Exit; @@ -2105,7 +2105,7 @@ int dim; - error = af_glyph_hints_reload( hints, outline, 1 ); + error = af_glyph_hints_reload( hints, outline ); if ( error ) goto Exit; diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c index f58ef38..6546475 100644 --- a/src/autofit/aflatin2.c +++ b/src/autofit/aflatin2.c @@ -4,7 +4,7 @@ /* */ /* Auto-fitter hinting routines for latin script (body). */ /* */ -/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -84,7 +84,7 @@ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy ); - error = af_glyph_hints_reload( hints, &face->glyph->outline, 0 ); + error = af_glyph_hints_reload( hints, &face->glyph->outline ); if ( error ) goto Exit; @@ -545,7 +545,8 @@ FT_Pos fitted = ( scaled + 40 ) & ~63; #if 1 - if ( scaled != fitted ) { + if ( scaled != fitted ) + { scale = FT_MulDiv( scale, fitted, scaled ); AF_LOG(( "== scaled x-top = %.2g fitted = %.2g, scaling = %.4g\n", scaled/64.0, fitted/64.0, (fitted*1.0)/scaled )); } @@ -2104,52 +2105,52 @@ FT_Int n_edges = edge_limit - edges; - if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) ) - { - AF_Edge edge1, edge2, edge3; - FT_Pos dist1, dist2, span, delta; - - - if ( n_edges == 6 ) + if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) ) { - edge1 = edges; - edge2 = edges + 2; - edge3 = edges + 4; - } - else - { - edge1 = edges + 1; - edge2 = edges + 5; - edge3 = edges + 9; - } + AF_Edge edge1, edge2, edge3; + FT_Pos dist1, dist2, span, delta; - dist1 = edge2->opos - edge1->opos; - dist2 = edge3->opos - edge2->opos; - span = dist1 - dist2; - if ( span < 0 ) - span = -span; + if ( n_edges == 6 ) + { + edge1 = edges; + edge2 = edges + 2; + edge3 = edges + 4; + } + else + { + edge1 = edges + 1; + edge2 = edges + 5; + edge3 = edges + 9; + } - if ( span < 8 ) - { - delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); - edge3->pos -= delta; - if ( edge3->link ) - edge3->link->pos -= delta; + dist1 = edge2->opos - edge1->opos; + dist2 = edge3->opos - edge2->opos; - /* move the serifs along with the stem */ - if ( n_edges == 12 ) + span = dist1 - dist2; + if ( span < 0 ) + span = -span; + + if ( span < 8 ) { - ( edges + 8 )->pos -= delta; - ( edges + 11 )->pos -= delta; - } + delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); + edge3->pos -= delta; + if ( edge3->link ) + edge3->link->pos -= delta; - edge3->flags |= AF_EDGE_DONE; - if ( edge3->link ) - edge3->link->flags |= AF_EDGE_DONE; + /* move the serifs along with the stem */ + if ( n_edges == 12 ) + { + ( edges + 8 )->pos -= delta; + ( edges + 11 )->pos -= delta; + } + + edge3->flags |= AF_EDGE_DONE; + if ( edge3->link ) + edge3->link->flags |= AF_EDGE_DONE; + } } } - } #endif if ( has_serifs || !anchor ) @@ -2249,7 +2250,7 @@ int dim; - error = af_glyph_hints_reload( hints, outline, 1 ); + error = af_glyph_hints_reload( hints, outline ); if ( error ) goto Exit; diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c index bf25cd1..6dd9f2a 100644 --- a/src/autofit/afloader.c +++ b/src/autofit/afloader.c @@ -183,9 +183,9 @@ if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) ) { - old_rsb = loader->pp2.x - edge2->opos; - old_lsb = edge1->opos; - new_lsb = edge1->pos; + old_rsb = loader->pp2.x - edge2->opos; + old_lsb = edge1->opos; + new_lsb = edge1->pos; /* remember unhinted values to later account */ /* for rounding errors */ @@ -216,8 +216,8 @@ } else { - FT_Pos pp1x = loader->pp1.x; - FT_Pos pp2x = loader->pp2.x; + FT_Pos pp1x = loader->pp1.x; + FT_Pos pp2x = loader->pp2.x; loader->pp1.x = FT_PIX_ROUND( pp1x ); @@ -229,8 +229,8 @@ } else { - FT_Pos pp1x = loader->pp1.x; - FT_Pos pp2x = loader->pp2.x; + FT_Pos pp1x = loader->pp1.x; + FT_Pos pp2x = loader->pp2.x; loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta ); diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c index 76822c3..5b9aba6 100644 --- a/src/autofit/afpic.c +++ b/src/autofit/afpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for autofit module. */ /* */ -/* Copyright 2009 by */ +/* Copyright 2009, 2010 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -45,19 +45,21 @@ } } + FT_Error - autofit_module_class_pic_init( FT_Library library ) + autofit_module_class_pic_init( FT_Library library ) { - FT_PIC_Container* pic_container = &library->pic_container; - FT_UInt ss; - FT_Error error = FT_Err_Ok; - AFModulePIC* container; - FT_Memory memory = library->memory; + FT_PIC_Container* pic_container = &library->pic_container; + FT_UInt ss; + FT_Error error = AF_Err_Ok; + AFModulePIC* container; + FT_Memory memory = library->memory; + /* allocate pointer, clear and set global container pointer */ if ( FT_ALLOC ( container, sizeof ( *container ) ) ) return error; - FT_MEM_SET( container, 0, sizeof(*container) ); + FT_MEM_SET( container, 0, sizeof ( *container ) ); pic_container->autofit = container; /* initialize pointer table - this is how the module usually expects this data */ diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c index 2de592d..4b8e911 100644 --- a/src/base/ftbbox.c +++ b/src/base/ftbbox.c @@ -561,11 +561,11 @@ } FT_DEFINE_OUTLINE_FUNCS(bbox_interface, - (FT_Outline_MoveTo_Func) BBox_Move_To, - (FT_Outline_LineTo_Func) BBox_Move_To, - (FT_Outline_ConicTo_Func)BBox_Conic_To, - (FT_Outline_CubicTo_Func)BBox_Cubic_To, - 0, 0 + (FT_Outline_MoveTo_Func) BBox_Move_To, + (FT_Outline_LineTo_Func) BBox_Move_To, + (FT_Outline_ConicTo_Func)BBox_Conic_To, + (FT_Outline_CubicTo_Func)BBox_Cubic_To, + 0, 0 ) /* documentation is in ftbbox.h */ diff --git a/src/base/ftgloadr.c b/src/base/ftgloadr.c index ac0010d..8483450 100644 --- a/src/base/ftgloadr.c +++ b/src/base/ftgloadr.c @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph loader (body). */ /* */ -/* Copyright 2002, 2003, 2004, 2005, 2006 by */ +/* Copyright 2002, 2003, 2004, 2005, 2006, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -69,7 +69,7 @@ FT_GlyphLoader_New( FT_Memory memory, FT_GlyphLoader *aloader ) { - FT_GlyphLoader loader; + FT_GlyphLoader loader = NULL; FT_Error error; diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c index 3505d6d..b220508 100644 --- a/src/base/ftglyph.c +++ b/src/base/ftglyph.c @@ -4,7 +4,7 @@ /* */ /* FreeType convenience functions to handle glyphs (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007, 2008 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -282,7 +282,7 @@ { FT_Memory memory = library->memory; FT_Error error; - FT_Glyph glyph; + FT_Glyph glyph = NULL; *aglyph = 0; diff --git a/src/base/ftinit.c b/src/base/ftinit.c index 1914228..305177a 100644 --- a/src/base/ftinit.c +++ b/src/base/ftinit.c @@ -98,7 +98,8 @@ #undef FT_USE_MODULE #define FT_USE_MODULE( type, x ) MODULE_CLASS_##x, - enum { + enum + { #include FT_CONFIG_MODULES_H FT_NUM_MODULE_CLASSES }; @@ -190,7 +191,7 @@ Exit: if ( error ) FT_TRACE0(( "FT_Add_Default_Module:" " Cannot install `%s', error = 0x%x\n", - (*cur)->module_name, error )); + (*cur)->module_name, error )); cur++; } } diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c index 8064011..0da4ba1 100644 --- a/src/base/ftlcdfil.c +++ b/src/base/ftlcdfil.c @@ -4,7 +4,7 @@ /* */ /* FreeType API for color filtering of subpixel bitmap glyphs (body). */ /* */ -/* Copyright 2006, 2008, 2009 by */ +/* Copyright 2006, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -267,18 +267,31 @@ FT_EXPORT_DEF( FT_Error ) - FT_Library_SetLcdFilter( FT_Library library, - FT_LcdFilter filter ) + FT_Library_SetLcdFilterWeights( FT_Library library, + unsigned char *weights ) + { + if ( !library || !weights ) + return FT_Err_Invalid_Argument; + + ft_memcpy( library->lcd_weights, weights, 5 ); + + return FT_Err_Ok; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Library_SetLcdFilter( FT_Library library, + FT_LcdFilter filter ) { static const FT_Byte light_filter[5] = - { 0, 85, 86, 85, 0 }; + { 0x00, 0x55, 0x56, 0x55, 0x00 }; /* the values here sum up to a value larger than 256, */ /* providing a cheap gamma correction */ static const FT_Byte default_filter[5] = { 0x10, 0x40, 0x70, 0x40, 0x10 }; - if ( library == NULL ) + if ( !library ) return FT_Err_Invalid_Argument; switch ( filter ) @@ -330,11 +343,23 @@ } library->lcd_filter = filter; - return 0; + + return FT_Err_Ok; } #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + FT_EXPORT_DEF( FT_Error ) + FT_Library_SetLcdFilterWeights( FT_Library library, + unsigned char *weights ) + { + FT_UNUSED( library ); + FT_UNUSED( weights ); + + return FT_Err_Unimplemented_Feature; + } + + FT_EXPORT_DEF( FT_Error ) FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ) diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index a32b2cd..7f38df0 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -29,7 +29,6 @@ #include FT_TRUETYPE_TABLES_H #include FT_TRUETYPE_TAGS_H #include FT_TRUETYPE_IDS_H -#include FT_OUTLINE_H #include FT_SERVICE_SFNT_H #include FT_SERVICE_POSTSCRIPT_NAME_H @@ -143,7 +142,7 @@ if ( !args ) return FT_Err_Invalid_Argument; - memory = library->memory; + memory = library->memory; if ( FT_NEW( stream ) ) goto Exit; @@ -230,11 +229,11 @@ static FT_Error ft_glyphslot_init( FT_GlyphSlot slot ) { - FT_Driver driver = slot->face->driver; - FT_Driver_Class clazz = driver->clazz; - FT_Memory memory = driver->root.memory; - FT_Error error = FT_Err_Ok; - FT_Slot_Internal internal; + FT_Driver driver = slot->face->driver; + FT_Driver_Class clazz = driver->clazz; + FT_Memory memory = driver->root.memory; + FT_Error error = FT_Err_Ok; + FT_Slot_Internal internal = NULL; slot->library = driver->root.library; @@ -354,14 +353,14 @@ /* slot->internal might be NULL in out-of-memory situations */ if ( slot->internal ) { - /* free glyph loader */ - if ( FT_DRIVER_USES_OUTLINES( driver ) ) - { - FT_GlyphLoader_Done( slot->internal->loader ); - slot->internal->loader = 0; - } + /* free glyph loader */ + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + { + FT_GlyphLoader_Done( slot->internal->loader ); + slot->internal->loader = 0; + } - FT_FREE( slot->internal ); + FT_FREE( slot->internal ); } } @@ -608,12 +607,12 @@ * load properly. */ - if ( hinter && - !( load_flags & FT_LOAD_NO_HINTING ) && - !( load_flags & FT_LOAD_NO_AUTOHINT ) && - FT_DRIVER_IS_SCALABLE( driver ) && - FT_DRIVER_USES_OUTLINES( driver ) && - !FT_IS_TRICKY( face ) && + if ( hinter && + !( load_flags & FT_LOAD_NO_HINTING ) && + !( load_flags & FT_LOAD_NO_AUTOHINT ) && + FT_DRIVER_IS_SCALABLE( driver ) && + FT_DRIVER_USES_OUTLINES( driver ) && + !FT_IS_TRICKY( face ) && ( ( face->internal->transform_matrix.yx == 0 && face->internal->transform_matrix.xx != 0 ) || ( face->internal->transform_matrix.xx == 0 && @@ -711,8 +710,8 @@ } /* compute the linear advance in 16.16 pixels */ - if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 && - ( FT_IS_SCALABLE( face ) ) ) + if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 && + ( FT_IS_SCALABLE( face ) ) ) { FT_Size_Metrics* metrics = &face->size->metrics; @@ -992,6 +991,14 @@ ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) ) { +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - first > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found " + "at too late position (%d)\n", cur - first )); + continue; + } +#endif face->charmap = cur[0]; return FT_Err_Ok; } @@ -1006,6 +1013,14 @@ { if ( cur[0]->encoding == FT_ENCODING_UNICODE ) { +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - first > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found " + "at too late position (%d)\n", cur - first )); + continue; + } +#endif face->charmap = cur[0]; return FT_Err_Ok; } @@ -1047,6 +1062,14 @@ if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR && FT_Get_CMap_Format( cur[0] ) == 14 ) +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - first > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "find_unicode_charmap: UVS cmap is found " + "at too late position (%d)\n", cur - first )); + continue; + } +#endif return cur[0]; } @@ -1548,11 +1571,26 @@ goto Exit; if ( FT_READ_USHORT( flags ) ) goto Exit; - rlen -= 2; /* the flags are part of the resource */ + FT_TRACE3(( "POST fragment[%d]: offsets=0x%08x, rlen=0x%08x, flags=0x%04x\n", + i, offsets[i], rlen, flags )); + + /* postpone the check of rlen longer than buffer until FT_Stream_Read() */ + if ( ( flags >> 8 ) == 0 ) /* Comment, should not be loaded */ + continue; + + /* the flags are part of the resource, so rlen >= 2. */ + /* but some fonts declare rlen = 0 for empty fragment */ + if ( rlen > 2 ) + rlen -= 2; + else + rlen = 0; + if ( ( flags >> 8 ) == type ) len += rlen; else { + if ( pfb_lenpos + 3 > pfb_len + 2 ) + goto Exit2; pfb_data[pfb_lenpos ] = (FT_Byte)( len ); pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); @@ -1561,6 +1599,8 @@ if ( ( flags >> 8 ) == 5 ) /* End of font mark */ break; + if ( pfb_pos + 6 > pfb_len + 2 ) + goto Exit2; pfb_data[pfb_pos++] = 0x80; type = flags >> 8; @@ -1574,13 +1614,23 @@ pfb_data[pfb_pos++] = 0; } + error = FT_Err_Cannot_Open_Resource; + if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len ) + goto Exit2; + error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen ); + if ( error ) + goto Exit2; pfb_pos += rlen; } + if ( pfb_pos + 2 > pfb_len + 2 ) + goto Exit2; pfb_data[pfb_pos++] = 0x80; pfb_data[pfb_pos++] = 3; + if ( pfb_lenpos + 3 > pfb_len + 2 ) + goto Exit2; pfb_data[pfb_lenpos ] = (FT_Byte)( len ); pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); @@ -1915,9 +1965,9 @@ FT_Error error; FT_Driver driver; FT_Memory memory; - FT_Stream stream = 0; - FT_Face face = 0; - FT_ListNode node = 0; + FT_Stream stream = NULL; + FT_Face face = NULL; + FT_ListNode node = NULL; FT_Bool external_stream; FT_Module* cur; FT_Module* limit; @@ -2141,6 +2191,8 @@ internal->transform_delta.x = 0; internal->transform_delta.y = 0; + + internal->refcount = 1; } if ( aface ) @@ -2226,6 +2278,17 @@ } + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Reference_Face( FT_Face face ) + { + face->internal->refcount++; + + return FT_Err_Ok; + } + + /* documentation is in freetype.h */ FT_EXPORT_DEF( FT_Error ) @@ -2240,22 +2303,29 @@ error = FT_Err_Invalid_Face_Handle; if ( face && face->driver ) { - driver = face->driver; - memory = driver->root.memory; - - /* find face in driver's list */ - node = FT_List_Find( &driver->faces_list, face ); - if ( node ) + face->internal->refcount--; + if ( face->internal->refcount > 0 ) + error = FT_Err_Ok; + else { - /* remove face object from the driver's list */ - FT_List_Remove( &driver->faces_list, node ); - FT_FREE( node ); + driver = face->driver; + memory = driver->root.memory; - /* now destroy the object proper */ - destroy_face( memory, face, driver ); - error = FT_Err_Ok; + /* find face in driver's list */ + node = FT_List_Find( &driver->faces_list, face ); + if ( node ) + { + /* remove face object from the driver's list */ + FT_List_Remove( &driver->faces_list, node ); + FT_FREE( node ); + + /* now destroy the object proper */ + destroy_face( memory, face, driver ); + error = FT_Err_Ok; + } } } + return error; } @@ -2901,6 +2971,15 @@ { if ( cur[0]->encoding == encoding ) { +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), " + "but in too late position to cache\n", + cur - face->charmaps )); + continue; + } +#endif face->charmap = cur[0]; return 0; } @@ -2935,6 +3014,15 @@ { if ( cur[0] == charmap ) { +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), " + "but in too late position to cache\n", + cur - face->charmaps )); + continue; + } +#endif face->charmap = cur[0]; return 0; } @@ -2951,12 +3039,24 @@ FT_Int i; + if ( !charmap || !charmap->face ) + return -1; + for ( i = 0; i < charmap->face->num_charmaps; i++ ) if ( charmap->face->charmaps[i] == charmap ) break; FT_ASSERT( i < charmap->face->num_charmaps ); +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( i > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), " + "but in too late position to cache\n", + i )); + return -i; + } +#endif return i; } @@ -3095,7 +3195,7 @@ } result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode ); } - return result; + return result; } @@ -3109,14 +3209,14 @@ FT_UInt gindex = 0; - if ( face && face->charmap ) + if ( face && face->charmap && face->num_glyphs ) { gindex = FT_Get_Char_Index( face, 0 ); - if ( gindex == 0 ) + if ( gindex == 0 || gindex >= (FT_UInt)face->num_glyphs ) result = FT_Get_Next_Char( face, 0, &gindex ); } - if ( agindex ) + if ( agindex ) *agindex = gindex; return result; @@ -3134,13 +3234,16 @@ FT_UInt gindex = 0; - if ( face && face->charmap ) + if ( face && face->charmap && face->num_glyphs ) { FT_UInt32 code = (FT_UInt32)charcode; FT_CMap cmap = FT_CMAP( face->charmap ); - gindex = cmap->clazz->char_next( cmap, &code ); + do { + gindex = cmap->clazz->char_next( cmap, &code ); + } while ( gindex >= (FT_UInt)face->num_glyphs ); + result = ( gindex == 0 ) ? 0 : code; } @@ -3645,7 +3748,7 @@ FT_Library library = module->library; FT_Memory memory = library->memory; FT_Error error; - FT_ListNode node; + FT_ListNode node = NULL; if ( FT_NEW( node ) ) @@ -3661,7 +3764,7 @@ /* allocate raster object if needed */ if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && - clazz->raster_class->raster_new ) + clazz->raster_class->raster_new ) { error = clazz->raster_class->raster_new( memory, &render->raster ); if ( error ) @@ -3702,7 +3805,8 @@ /* release raster object, if any */ - if ( render->raster ) + if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && + render->raster ) render->clazz->raster_class->raster_done( render->raster ); /* remove from list */ @@ -3808,7 +3912,7 @@ while ( renderer ) { error = renderer->render( renderer, slot, render_mode, NULL ); - if ( !error || + if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) break; @@ -3842,7 +3946,7 @@ FT_Library library; - if ( !slot ) + if ( !slot || !slot->face ) return FT_Err_Invalid_Argument; library = FT_FACE_LIBRARY( slot->face ); @@ -4029,7 +4133,8 @@ FT_Renderer renderer = FT_RENDERER( module ); - if ( renderer->raster ) + if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && + renderer->raster ) renderer->clazz->raster_class->raster_done( renderer->raster ); } @@ -4182,13 +4287,24 @@ /*************************************************************************/ + /* documentation is in ftmodapi.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Reference_Library( FT_Library library ) + { + library->refcount++; + + return FT_Err_Ok; + } + + /* documentation is in ftmodapi.h */ FT_EXPORT_DEF( FT_Error ) FT_New_Library( FT_Memory memory, FT_Library *alibrary ) { - FT_Library library = 0; + FT_Library library = NULL; FT_Error error; @@ -4224,6 +4340,8 @@ library->version_minor = FREETYPE_MINOR; library->version_patch = FREETYPE_PATCH; + library->refcount = 1; + /* That's ok now */ *alibrary = library; @@ -4280,40 +4398,64 @@ if ( !library ) return FT_Err_Invalid_Library_Handle; + library->refcount--; + if ( library->refcount > 0 ) + goto Exit; + memory = library->memory; /* Discard client-data */ if ( library->generic.finalizer ) library->generic.finalizer( library ); - /* Close all faces in the library. If we don't do - * this, we can have some subtle memory leaks. + /* + * Close all faces in the library. If we don't do this, we can have + * some subtle memory leaks. + * * Example: * * - the cff font driver uses the pshinter module in cff_size_done * - if the pshinter module is destroyed before the cff font driver, * opened FT_Face objects managed by the driver are not properly * destroyed, resulting in a memory leak + * + * Some faces are dependent on other faces, like Type42 faces that + * depend on TrueType faces synthesized internally. + * + * The order of drivers should be specified in driver_name[]. */ { - FT_UInt n; + FT_UInt m, n; + const char* driver_name[] = { "type42", NULL }; - for ( n = 0; n < library->num_modules; n++ ) + for ( m = 0; + m < sizeof ( driver_name ) / sizeof ( driver_name[0] ); + m++ ) { - FT_Module module = library->modules[n]; - FT_List faces; + for ( n = 0; n < library->num_modules; n++ ) + { + FT_Module module = library->modules[n]; + const char* module_name = module->clazz->module_name; + FT_List faces; - if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 ) - continue; + if ( driver_name[m] && + ft_strcmp( module_name, driver_name[m] ) != 0 ) + continue; - faces = &FT_DRIVER(module)->faces_list; - while ( faces->head ) - { - FT_Done_Face( FT_FACE( faces->head->data ) ); - if ( faces->head ) - FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" )); + if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER ) == 0 ) + continue; + + FT_TRACE7(( "FT_Done_Library: close faces for %s\n", module_name )); + + faces = &FT_DRIVER( module )->faces_list; + while ( faces->head ) + { + FT_Done_Face( FT_FACE( faces->head->data ) ); + if ( faces->head ) + FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" )); + } } } } @@ -4355,6 +4497,8 @@ #endif FT_FREE( library ); + + Exit: return FT_Err_Ok; } @@ -4467,6 +4611,8 @@ #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ + /* documentation is in freetype.h */ + FT_EXPORT_DEF( FT_Error ) FT_Get_SubGlyph_Info( FT_GlyphSlot glyph, FT_UInt sub_index, @@ -4479,7 +4625,8 @@ FT_Error error = FT_Err_Invalid_Argument; - if ( glyph != NULL && + if ( glyph && + glyph->subglyphs && glyph->format == FT_GLYPH_FORMAT_COMPOSITE && sub_index < glyph->num_subglyphs ) { diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c index 5bb6ef3..356b156 100644 --- a/src/base/ftoutln.c +++ b/src/base/ftoutln.c @@ -305,8 +305,8 @@ *anoutline = null_outline; if ( FT_NEW_ARRAY( anoutline->points, numPoints ) || - FT_NEW_ARRAY( anoutline->tags, numPoints ) || - FT_NEW_ARRAY( anoutline->contours, numContours ) ) + FT_NEW_ARRAY( anoutline->tags, numPoints ) || + FT_NEW_ARRAY( anoutline->contours, numContours ) ) goto Fail; anoutline->n_points = (FT_UShort)numPoints; @@ -990,7 +990,8 @@ int i; FT_Pos ray_y[3]; - FT_Orientation result[3]; + FT_Orientation result[3] = + { FT_ORIENTATION_NONE, FT_ORIENTATION_NONE, FT_ORIENTATION_NONE }; if ( !outline || outline->n_points <= 0 ) diff --git a/src/base/ftpatent.c b/src/base/ftpatent.c index af29786..501cab5 100644 --- a/src/base/ftpatent.c +++ b/src/base/ftpatent.c @@ -131,7 +131,7 @@ error = service->table_info( face, i, &tag_i, &offset_i, &length_i ); - if ( error || + if ( error || FT_STREAM_SEEK( offset_i ) ) goto Exit; diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c index 133c2de..f64d28b 100644 --- a/src/base/ftrfork.c +++ b/src/base/ftrfork.c @@ -4,7 +4,7 @@ /* */ /* Embedded resource forks accessor (body). */ /* */ -/* Copyright 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */ /* Masatake YAMATO and Redhat K.K. */ /* */ /* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */ @@ -751,7 +751,7 @@ const char *original_name, const char *insertion ) { - char* new_name; + char* new_name = NULL; const char* tmp; const char* slash; size_t new_length; diff --git a/src/base/ftstream.c b/src/base/ftstream.c index b638599..210aaa4 100644 --- a/src/base/ftstream.c +++ b/src/base/ftstream.c @@ -4,7 +4,7 @@ /* */ /* I/O stream support (body). */ /* */ -/* Copyright 2000-2001, 2002, 2004, 2005, 2006, 2008, 2009 by */ +/* Copyright 2000-2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -246,6 +246,18 @@ /* allocate the frame in memory */ FT_Memory memory = stream->memory; + + /* simple sanity check */ + if ( count > stream->size ) + { + FT_ERROR(( "FT_Stream_EnterFrame:" + " frame size (%lu) larger than stream size (%lu)\n", + count, stream->size )); + + error = FT_Err_Invalid_Stream_Operation; + goto Exit; + } + #ifdef FT_DEBUG_MEMORY /* assume _ft_debug_file and _ft_debug_lineno are already set */ stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error ); @@ -275,7 +287,7 @@ { /* check current and new position */ if ( stream->pos >= stream->size || - stream->pos + count > stream->size ) + stream->size - stream->pos < count ) { FT_ERROR(( "FT_Stream_EnterFrame:" " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n", diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c index 4d06d6d..ba86005 100644 --- a/src/base/ftsystem.c +++ b/src/base/ftsystem.c @@ -4,7 +4,7 @@ /* */ /* ANSI-specific FreeType low-level system interface (body). */ /* */ -/* Copyright 1996-2001, 2002, 2006, 2008, 2009 by */ +/* Copyright 1996-2001, 2002, 2006, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -192,7 +192,9 @@ /* count :: The number of bytes to read from the stream. */ /* */ /* */ - /* The number of bytes actually read. */ + /* The number of bytes actually read. If `count' is zero (this is, */ + /* the function is used for seeking), a non-zero return value */ + /* indicates an error. */ /* */ FT_CALLBACK_DEF( unsigned long ) ft_ansi_stream_io( FT_Stream stream, @@ -203,6 +205,9 @@ FT_FILE* file; + if ( !count && offset > stream->size ) + return 1; + file = STREAM_FILE( stream ); if ( stream->pos != offset ) diff --git a/src/cff/cffcmap.c b/src/cff/cffcmap.c index 46d603e..1298371 100644 --- a/src/cff/cffcmap.c +++ b/src/cff/cffcmap.c @@ -4,7 +4,7 @@ /* */ /* CFF character mapping table (cmap) support (body). */ /* */ -/* Copyright 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -120,27 +120,15 @@ /*************************************************************************/ FT_CALLBACK_DEF( const char* ) - cff_sid_to_glyph_name( TT_Face face, - FT_UInt idx ) + cff_sid_to_glyph_name( TT_Face face, + FT_UInt idx ) { - CFF_Font cff = (CFF_Font)face->extra.data; - CFF_Charset charset = &cff->charset; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; - FT_UInt sid = charset->sids[idx]; - - - return cff_index_get_sid_string( &cff->string_index, sid, psnames ); - } - - - FT_CALLBACK_DEF( void ) - cff_sid_free_glyph_name( TT_Face face, - const char* gname ) - { - FT_Memory memory = FT_FACE_MEMORY( face ); + CFF_Font cff = (CFF_Font)face->extra.data; + CFF_Charset charset = &cff->charset; + FT_UInt sid = charset->sids[idx]; - FT_FREE( gname ); + return cff_index_get_sid_string( cff, sid ); } @@ -155,14 +143,15 @@ /* can't build Unicode map for CID-keyed font */ + /* because we don't know glyph names. */ if ( !charset->sids ) - return CFF_Err_Invalid_Argument; + return CFF_Err_No_Unicode_Glyph_Name; return psnames->unicodes_init( memory, unicodes, cff->num_glyphs, (PS_GetGlyphNameFunc)&cff_sid_to_glyph_name, - (PS_FreeGlyphNameFunc)&cff_sid_free_glyph_name, + (PS_FreeGlyphNameFunc)NULL, (FT_Pointer)face ); } diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c index dad0b65..39f04ee 100644 --- a/src/cff/cffdrivr.c +++ b/src/cff/cffdrivr.c @@ -4,7 +4,8 @@ /* */ /* OpenType font driver implementation (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,7 +23,6 @@ #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H #include FT_SERVICE_CID_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H #include FT_SERVICE_POSTSCRIPT_INFO_H #include FT_SERVICE_POSTSCRIPT_NAME_H #include FT_SERVICE_TT_CMAP_H @@ -228,16 +228,13 @@ FT_Pointer buffer, FT_UInt buffer_max ) { - CFF_Font font = (CFF_Font)face->extra.data; - FT_Memory memory = FT_FACE_MEMORY( face ); - FT_String* gname; - FT_UShort sid; - FT_Service_PsCMaps psnames; - FT_Error error; + CFF_Font font = (CFF_Font)face->extra.data; + FT_String* gname; + FT_UShort sid; + FT_Error error; - FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); - if ( !psnames ) + if ( !font->psnames ) { FT_ERROR(( "cff_get_glyph_name:" " cannot get glyph name from CFF & CEF fonts\n" @@ -251,12 +248,11 @@ sid = font->charset.sids[glyph_index]; /* now, lookup the name itself */ - gname = cff_index_get_sid_string( &font->string_index, sid, psnames ); + gname = cff_index_get_sid_string( font, sid ); if ( gname ) FT_STRCPYN( buffer, gname, buffer_max ); - FT_FREE( gname ); error = CFF_Err_Ok; Exit: @@ -271,11 +267,9 @@ CFF_Font cff; CFF_Charset charset; FT_Service_PsCMaps psnames; - FT_Memory memory = FT_FACE_MEMORY( face ); FT_String* name; FT_UShort sid; FT_UInt i; - FT_Int result; cff = (CFF_FontRec *)face->extra.data; @@ -290,19 +284,14 @@ sid = charset->sids[i]; if ( sid > 390 ) - name = cff_index_get_name( &cff->string_index, sid - 391 ); + name = cff_index_get_string( cff, sid - 391 ); else name = (FT_String *)psnames->adobe_std_strings( sid ); if ( !name ) continue; - result = ft_strcmp( glyph_name, name ); - - if ( sid > 390 ) - FT_FREE( name ); - - if ( !result ) + if ( !ft_strcmp( glyph_name, name ) ) return i; } @@ -333,35 +322,29 @@ PS_FontInfoRec* afont_info ) { CFF_Font cff = (CFF_Font)face->extra.data; - FT_Error error = FT_Err_Ok; + FT_Error error = CFF_Err_Ok; if ( cff && cff->font_info == NULL ) { - CFF_FontRecDict dict = &cff->top_font.font_dict; - PS_FontInfoRec *font_info; - FT_Memory memory = face->root.memory; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + CFF_FontRecDict dict = &cff->top_font.font_dict; + PS_FontInfoRec *font_info; + FT_Memory memory = face->root.memory; if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) ) goto Fail; - font_info->version = cff_index_get_sid_string( &cff->string_index, - dict->version, - psnames ); - font_info->notice = cff_index_get_sid_string( &cff->string_index, - dict->notice, - psnames ); - font_info->full_name = cff_index_get_sid_string( &cff->string_index, - dict->full_name, - psnames ); - font_info->family_name = cff_index_get_sid_string( &cff->string_index, - dict->family_name, - psnames ); - font_info->weight = cff_index_get_sid_string( &cff->string_index, - dict->weight, - psnames ); + font_info->version = cff_index_get_sid_string( cff, + dict->version ); + font_info->notice = cff_index_get_sid_string( cff, + dict->notice ); + font_info->full_name = cff_index_get_sid_string( cff, + dict->full_name ); + font_info->family_name = cff_index_get_sid_string( cff, + dict->family_name ); + font_info->weight = cff_index_get_sid_string( cff, + dict->weight ); font_info->italic_angle = dict->italic_angle; font_info->is_fixed_pitch = dict->is_fixed_pitch; font_info->underline_position = (FT_Short)dict->underline_position; @@ -467,8 +450,7 @@ if ( cff ) { - CFF_FontRecDict dict = &cff->top_font.font_dict; - FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + CFF_FontRecDict dict = &cff->top_font.font_dict; if ( dict->cid_registry == 0xFFFFU ) @@ -480,18 +462,16 @@ if ( registry ) { if ( cff->registry == NULL ) - cff->registry = cff_index_get_sid_string( &cff->string_index, - dict->cid_registry, - psnames ); + cff->registry = cff_index_get_sid_string( cff, + dict->cid_registry ); *registry = cff->registry; } if ( ordering ) { if ( cff->ordering == NULL ) - cff->ordering = cff_index_get_sid_string( &cff->string_index, - dict->cid_ordering, - psnames ); + cff->ordering = cff_index_get_sid_string( cff, + dict->cid_ordering ); *ordering = cff->ordering; } diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index 4e17eb6..e99ee70 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -22,7 +22,6 @@ #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H #include FT_OUTLINE_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H #include "cffobjs.h" #include "cffload.h" @@ -394,7 +393,7 @@ /* initialize Type2 decoder */ decoder->cff = cff; - decoder->num_globals = cff->num_global_subrs; + decoder->num_globals = cff->global_subrs_index.count; decoder->globals = cff->global_subrs; decoder->globals_bias = cff_compute_bias( cff->top_font.font_dict.charstring_type, @@ -430,7 +429,7 @@ goto Exit; } - FT_TRACE4(( "glyph index %d (subfont %d):\n", glyph_index, fd_index )); + FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index )); sub = cff->subfonts[fd_index]; @@ -445,10 +444,10 @@ } #ifdef FT_DEBUG_LEVEL_TRACE else - FT_TRACE4(( "glyph index %d:\n", glyph_index )); + FT_TRACE3(( "glyph index %d:\n", glyph_index )); #endif - decoder->num_locals = sub->num_local_subrs; + decoder->num_locals = sub->local_subrs_index.count; decoder->locals = sub->local_subrs; decoder->locals_bias = cff_compute_bias( decoder->cff->top_font.font_dict.charstring_type, @@ -812,10 +811,10 @@ charstring_len ); decoder->seac = FALSE; + cff_free_glyph_data( face, &charstring, charstring_len ); + if ( error ) goto Exit; - - cff_free_glyph_data( face, &charstring, charstring_len ); } /* Save the left bearing, advance and glyph width of the base */ @@ -842,10 +841,10 @@ charstring_len ); decoder->seac = FALSE; + cff_free_glyph_data( face, &charstring, charstring_len ); + if ( error ) goto Exit; - - cff_free_glyph_data( face, &charstring, charstring_len ); } /* Restore the left side bearing, advance and glyph width */ @@ -1340,6 +1339,14 @@ decoder->num_hints += num_args / 2; } + /* In a valid charstring there must be at least one byte */ + /* after `hintmask' or `cntrmask' (e.g., for a `return' */ + /* instruction). Additionally, there must be space for */ + /* `num_hints' bits. */ + + if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit ) + goto Syntax_Error; + if ( hinter ) { if ( op == cff_op_hintmask ) @@ -1358,20 +1365,18 @@ FT_UInt maskbyte; - FT_TRACE4(( " (maskbytes: " )); + FT_TRACE4(( " (maskbytes:" )); for ( maskbyte = 0; - maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3); + maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 ); maskbyte++, ip++ ) - FT_TRACE4(( "0x%02X", *ip )); + FT_TRACE4(( " 0x%02X", *ip )); FT_TRACE4(( ")\n" )); } #else ip += ( decoder->num_hints + 7 ) >> 3; #endif - if ( ip >= limit ) - goto Syntax_Error; args = stack; break; @@ -2275,7 +2280,11 @@ /* subsequent `pop' operands should add the arguments, */ /* this is the implementation described for `unknown' other */ /* subroutines in the Type1 spec. */ + /* */ + /* XXX Fix return arguments (see discussion below). */ args -= 2 + ( args[-2] >> 16 ); + if ( args < stack ) + goto Stack_Underflow; break; case cff_op_pop: @@ -2285,6 +2294,22 @@ FT_TRACE4(( " pop (invalid op)\n" )); + /* XXX Increasing `args' is wrong: After a certain number of */ + /* `pop's we get a stack overflow. Reason for doing it is */ + /* code like this (actually found in a CFF font): */ + /* */ + /* 17 1 3 callothersubr */ + /* pop */ + /* callsubr */ + /* */ + /* Since we handle `callothersubr' as a no-op, and */ + /* `callsubr' needs at least one argument, `pop' can't be a */ + /* no-op too as it basically should be. */ + /* */ + /* The right solution would be to provide real support for */ + /* `callothersubr' as done in `t1decode.c', however, given */ + /* the fact that CFF fonts with `pop' are invalid, it is */ + /* questionable whether it is worth the time. */ args++; break; @@ -2671,11 +2696,15 @@ /* this scaling is only relevant if the PS hinter isn't active */ if ( cff->num_subfonts ) { - FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, - glyph_index ); + FT_ULong top_upm, sub_upm; + FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, + glyph_index ); - FT_ULong top_upm = cff->top_font.font_dict.units_per_em; - FT_ULong sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em; + if ( fd_index >= cff->num_subfonts ) + fd_index = cff->num_subfonts - 1; + + top_upm = cff->top_font.font_dict.units_per_em; + sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em; font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; @@ -2720,48 +2749,53 @@ /* now load the unscaled outline */ error = cff_get_glyph_data( face, glyph_index, &charstring, &charstring_len ); - if ( !error ) - { - error = cff_decoder_prepare( &decoder, size, glyph_index ); - if ( !error ) - { - error = cff_decoder_parse_charstrings( &decoder, - charstring, - charstring_len ); + if ( error ) + goto Glyph_Build_Finished; + + error = cff_decoder_prepare( &decoder, size, glyph_index ); + if ( error ) + goto Glyph_Build_Finished; - cff_free_glyph_data( face, &charstring, charstring_len ); + error = cff_decoder_parse_charstrings( &decoder, + charstring, + charstring_len ); + cff_free_glyph_data( face, &charstring, charstring_len ); + + if ( error ) + goto Glyph_Build_Finished; #ifdef FT_CONFIG_OPTION_INCREMENTAL - /* Control data and length may not be available for incremental */ - /* fonts. */ - if ( face->root.internal->incremental_interface ) - { - glyph->root.control_data = 0; - glyph->root.control_len = 0; - } - else + /* Control data and length may not be available for incremental */ + /* fonts. */ + if ( face->root.internal->incremental_interface ) + { + glyph->root.control_data = 0; + glyph->root.control_len = 0; + } + else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - /* We set control_data and control_len if charstrings is loaded. */ - /* See how charstring loads at cff_index_access_element() in */ - /* cffload.c. */ - { - CFF_Index csindex = &cff->charstrings_index; + /* We set control_data and control_len if charstrings is loaded. */ + /* See how charstring loads at cff_index_access_element() in */ + /* cffload.c. */ + { + CFF_Index csindex = &cff->charstrings_index; - if ( csindex->offsets ) - { - glyph->root.control_data = csindex->bytes + - csindex->offsets[glyph_index] - 1; - glyph->root.control_len = charstring_len; - } - } + if ( csindex->offsets ) + { + glyph->root.control_data = csindex->bytes + + csindex->offsets[glyph_index] - 1; + glyph->root.control_len = charstring_len; } } - /* save new glyph tables */ - cff_builder_done( &decoder.builder ); + Glyph_Build_Finished: + /* save new glyph tables, if no error */ + if ( !error ) + cff_builder_done( &decoder.builder ); + /* XXX: anything to do for broken glyph entry? */ } #ifdef FT_CONFIG_OPTION_INCREMENTAL diff --git a/src/cff/cffload.c b/src/cff/cffload.c index 64d1395..42e7730 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -4,7 +4,8 @@ /* */ /* OpenType and CFF data/program tables loader (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,7 +21,6 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_STREAM_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H #include FT_TRUETYPE_TAGS_H #include FT_TYPE1_TABLES_H @@ -251,7 +251,7 @@ if ( offsize < 1 || offsize > 4 ) { - error = FT_Err_Invalid_Table; + error = CFF_Err_Invalid_Table; goto Exit; } @@ -377,18 +377,21 @@ } - /* allocate a table containing pointers to an index's elements */ + /* Allocate a table containing pointers to an index's elements. */ + /* The `pool' argument makes this function convert the index */ + /* entries to C-style strings (this is, NULL-terminated). */ static FT_Error cff_index_get_pointers( CFF_Index idx, - FT_Byte*** table ) + FT_Byte*** table, + FT_Byte** pool ) { - FT_Error error = CFF_Err_Ok; - FT_Memory memory = idx->stream->memory; - FT_ULong n, offset, old_offset; + FT_Error error = CFF_Err_Ok; + FT_Memory memory = idx->stream->memory; FT_Byte** t; + FT_Byte* new_bytes = NULL; - *table = 0; + *table = NULL; if ( idx->offsets == NULL ) { @@ -397,28 +400,65 @@ goto Exit; } - if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) ) + if ( idx->count > 0 && + !FT_NEW_ARRAY( t, idx->count + 1 ) && + ( !pool || !FT_ALLOC( new_bytes, + idx->data_size + idx->count ) ) ) { - old_offset = 1; - for ( n = 0; n <= idx->count; n++ ) + FT_ULong n, cur_offset; + FT_ULong extra = 0; + FT_Byte* org_bytes = idx->bytes; + + + /* at this point, `idx->offsets' can't be NULL */ + cur_offset = idx->offsets[0] - 1; + + /* sanity check */ + if ( cur_offset >= idx->data_size ) { - /* at this point, `idx->offsets' can't be NULL */ - offset = idx->offsets[n]; - if ( !offset ) - offset = old_offset; + FT_TRACE0(( "cff_index_get_pointers:" + " invalid first offset value %d set to zero\n", + cur_offset )); + cur_offset = 0; + } - /* two sanity checks for invalid offset tables */ - else if ( offset < old_offset ) - offset = old_offset; + if ( !pool ) + t[0] = org_bytes + cur_offset; + else + t[0] = new_bytes + cur_offset; + + for ( n = 1; n <= idx->count; n++ ) + { + FT_ULong next_offset = idx->offsets[n] - 1; - else if ( offset - 1 >= idx->data_size && n < idx->count ) - offset = old_offset; - t[n] = idx->bytes + offset - 1; + /* empty slot + two sanity checks for invalid offset tables */ + if ( next_offset == 0 || + next_offset < cur_offset || + ( next_offset >= idx->data_size && n < idx->count ) ) + next_offset = cur_offset; - old_offset = offset; + if ( !pool ) + t[n] = org_bytes + next_offset; + else + { + t[n] = new_bytes + next_offset + extra; + + if ( next_offset != cur_offset ) + { + FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] ); + t[n][0] = '\0'; + t[n] += 1; + extra++; + } + } + + cur_offset = next_offset; } *table = t; + + if ( pool ) + *pool = new_bytes; } Exit: @@ -526,10 +566,12 @@ } + /* get an entry from Name INDEX */ FT_LOCAL_DEF( FT_String* ) - cff_index_get_name( CFF_Index idx, - FT_UInt element ) + cff_index_get_name( CFF_Font font, + FT_UInt element ) { + CFF_Index idx = &font->name_index; FT_Memory memory = idx->stream->memory; FT_Byte* bytes; FT_ULong byte_len; @@ -553,42 +595,35 @@ } + /* get an entry from String INDEX */ FT_LOCAL_DEF( FT_String* ) - cff_index_get_sid_string( CFF_Index idx, - FT_UInt sid, - FT_Service_PsCMaps psnames ) + cff_index_get_string( CFF_Font font, + FT_UInt element ) + { + return ( element < font->num_strings ) + ? (FT_String*)font->strings[element] + : NULL; + } + + + FT_LOCAL_DEF( FT_String* ) + cff_index_get_sid_string( CFF_Font font, + FT_UInt sid ) { /* value 0xFFFFU indicates a missing dictionary entry */ if ( sid == 0xFFFFU ) - return 0; + return NULL; /* if it is not a standard string, return it */ if ( sid > 390 ) - return cff_index_get_name( idx, sid - 391 ); + return cff_index_get_string( font, sid - 391 ); /* CID-keyed CFF fonts don't have glyph names */ - if ( !psnames ) - return 0; - - /* that's a standard string, fetch a copy from the PSName module */ - { - FT_String* name = 0; - const char* adobe_name = psnames->adobe_std_strings( sid ); - - - if ( adobe_name ) - { - FT_Memory memory = idx->stream->memory; - FT_Error error; - - - (void)FT_STRDUP( name, adobe_name ); - - FT_UNUSED( error ); - } + if ( !font->psnames ) + return NULL; - return name; - } + /* this is a standard string */ + return (FT_String *)font->psnames->adobe_std_strings( sid ); } @@ -734,7 +769,7 @@ FT_UInt num_glyphs, FT_Memory memory ) { - FT_Error error = FT_Err_Ok; + FT_Error error = CFF_Err_Ok; FT_UInt i; FT_Long j; FT_UShort max_cid = 0; @@ -894,14 +929,16 @@ /* check whether the range contains at least one valid glyph; */ /* the constant is given in the CFF specification */ - if ( glyph_sid >= 65000L ) { + if ( glyph_sid >= 65000L ) + { FT_ERROR(( "cff_charset_load: invalid SID range\n" )); error = CFF_Err_Invalid_File_Format; goto Exit; } /* try to rescue some of the SIDs if `nleft' is too large */ - if ( nleft > 65000L - 1L || glyph_sid >= 65000L - nleft ) { + if ( nleft > 65000L - 1L || glyph_sid >= 65000L - nleft ) + { FT_ERROR(( "cff_charset_load: invalid SID range trimmed\n" )); nleft = ( FT_UInt )( 65000L - 1L - glyph_sid ); } @@ -1361,9 +1398,8 @@ if ( error ) goto Exit; - font->num_local_subrs = font->local_subrs_index.count; error = cff_index_get_pointers( &font->local_subrs_index, - &font->local_subrs ); + &font->local_subrs, NULL ); if ( error ) goto Exit; } @@ -1409,9 +1445,11 @@ FT_Memory memory = stream->memory; FT_ULong base_offset; CFF_FontRecDict dict; + CFF_IndexRec string_index; FT_ZERO( font ); + FT_ZERO( &string_index ); font->stream = stream; font->memory = memory; @@ -1438,15 +1476,20 @@ /* read the name, top dict, string and global subrs index */ if ( FT_SET_ERROR( cff_index_init( &font->name_index, - stream, 0 ) ) || + stream, 0 ) ) || FT_SET_ERROR( cff_index_init( &font->font_dict_index, - stream, 0 ) ) || - FT_SET_ERROR( cff_index_init( &font->string_index, - stream, 0 ) ) || + stream, 0 ) ) || + FT_SET_ERROR( cff_index_init( &string_index, + stream, 1 ) ) || FT_SET_ERROR( cff_index_init( &font->global_subrs_index, - stream, 1 ) ) ) + stream, 1 ) ) || + FT_SET_ERROR( cff_index_get_pointers( &string_index, + &font->strings, + &font->string_pool ) ) ) goto Exit; + font->num_strings = string_index.count; + /* well, we don't really forget the `disabled' fonts... */ font->num_faces = font->name_index.count; if ( face_index >= (FT_Int)font->num_faces ) @@ -1542,12 +1585,10 @@ goto Exit; } - /* explicit the global subrs */ - font->num_global_subrs = font->global_subrs_index.count; - font->num_glyphs = font->charstrings_index.count; + font->num_glyphs = font->charstrings_index.count; error = cff_index_get_pointers( &font->global_subrs_index, - &font->global_subrs ) ; + &font->global_subrs, NULL ); if ( error ) goto Exit; @@ -1579,9 +1620,11 @@ /* get the font name (/CIDFontName for CID-keyed fonts, */ /* /FontName otherwise) */ - font->font_name = cff_index_get_name( &font->name_index, face_index ); + font->font_name = cff_index_get_name( font, face_index ); Exit: + cff_index_done( &string_index ); + return error; } @@ -1594,7 +1637,6 @@ cff_index_done( &font->global_subrs_index ); - cff_index_done( &font->string_index ); cff_index_done( &font->font_dict_index ); cff_index_done( &font->name_index ); cff_index_done( &font->charstrings_index ); @@ -1617,21 +1659,12 @@ CFF_Done_FD_Select( &font->fd_select, font->stream ); - if (font->font_info != NULL) - { - FT_FREE( font->font_info->version ); - FT_FREE( font->font_info->notice ); - FT_FREE( font->font_info->full_name ); - FT_FREE( font->font_info->family_name ); - FT_FREE( font->font_info->weight ); - FT_FREE( font->font_info ); - } - - FT_FREE( font->registry ); - FT_FREE( font->ordering ); + FT_FREE( font->font_info ); - FT_FREE( font->global_subrs ); FT_FREE( font->font_name ); + FT_FREE( font->global_subrs ); + FT_FREE( font->strings ); + FT_FREE( font->string_pool ); } diff --git a/src/cff/cffload.h b/src/cff/cffload.h index 2b313ac..c755de9 100644 --- a/src/cff/cffload.h +++ b/src/cff/cffload.h @@ -4,7 +4,7 @@ /* */ /* OpenType & CFF data/program tables loader (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2007, 2008 by */ +/* Copyright 1996-2001, 2002, 2003, 2007, 2008, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -22,7 +22,6 @@ #include #include "cfftypes.h" -#include FT_SERVICE_POSTSCRIPT_CMAPS_H FT_BEGIN_HEADER @@ -32,13 +31,12 @@ FT_BEGIN_HEADER FT_LOCAL( FT_String* ) - cff_index_get_name( CFF_Index idx, - FT_UInt element ); + cff_index_get_string( CFF_Font font, + FT_UInt element ); FT_LOCAL( FT_String* ) - cff_index_get_sid_string( CFF_Index idx, - FT_UInt sid, - FT_Service_PsCMaps psnames ); + cff_index_get_sid_string( CFF_Font font, + FT_UInt sid ); FT_LOCAL( FT_Error ) @@ -51,6 +49,10 @@ FT_BEGIN_HEADER cff_index_forget_element( CFF_Index idx, FT_Byte** pbytes ); + FT_LOCAL( FT_String* ) + cff_index_get_name( CFF_Font font, + FT_UInt element ); + FT_LOCAL( FT_UInt ) cff_charset_cid_to_gindex( CFF_Charset charset, diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c index bd56c4b..f8b07c3 100644 --- a/src/cff/cffobjs.c +++ b/src/cff/cffobjs.c @@ -4,7 +4,8 @@ /* */ /* OpenType objects manager (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -24,8 +25,6 @@ #include FT_TRUETYPE_IDS_H #include FT_TRUETYPE_TAGS_H #include FT_INTERNAL_SFNT_H -#include FT_SERVICE_POSTSCRIPT_CMAPS_H -#include FT_INTERNAL_POSTSCRIPT_HINTS_H #include "cffobjs.h" #include "cffload.h" #include "cffcmap.h" @@ -58,7 +57,7 @@ { CFF_Face face = (CFF_Face)size->root.face; CFF_Font font = (CFF_Font)face->extra.data; - PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; + PSHinter_Service pshinter = font->pshinter; FT_Module module; @@ -349,7 +348,7 @@ { CFF_Face face = (CFF_Face)slot->face; CFF_Font font = (CFF_Font)face->extra.data; - PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; + PSHinter_Service pshinter = font->pshinter; if ( pshinter ) @@ -395,6 +394,41 @@ } + /* Strip all subset prefixes of the form `ABCDEF+'. Usually, there */ + /* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold' */ + /* have been seen in the wild. */ + + static void + remove_subset_prefix( FT_String* name ) + { + FT_Int32 idx = 0; + FT_Int32 length = strlen( name ) + 1; + FT_Bool continue_search = 1; + + + while ( continue_search ) + { + if ( length >= 7 && name[6] == '+' ) + { + for ( idx = 0; idx < 6; idx++ ) + { + /* ASCII uppercase letters */ + if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) ) + continue_search = 0; + } + + if ( continue_search ) + { + for ( idx = 7; idx < length; idx++ ) + name[idx - 7] = name[idx]; + } + } + else + continue_search = 0; + } + } + + FT_LOCAL_DEF( FT_Error ) cff_face_init( FT_Stream stream, FT_Face cffface, /* CFF_Face */ @@ -412,14 +446,6 @@ FT_Library library = cffface->driver->root.library; -#if 0 - FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt, SFNT ); - FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_NAMES ); - FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER ); - - if ( !sfnt ) - goto Bad_Format; -#else sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); if ( !sfnt ) @@ -429,7 +455,6 @@ pshinter = (PSHinter_Service)FT_Get_Module_Interface( library, "pshinter" ); -#endif /* create input stream from resource */ if ( FT_STREAM_SEEK( 0 ) ) @@ -514,7 +539,7 @@ goto Exit; cff->pshinter = pshinter; - cff->psnames = (void*)psnames; + cff->psnames = psnames; cffface->face_index = face_index; @@ -678,24 +703,22 @@ (FT_Short)( dict->underline_thickness >> 16 ); /* retrieve font family & style name */ - cffface->family_name = cff_index_get_name( &cff->name_index, - face_index ); - + cffface->family_name = cff_index_get_name( cff, face_index ); if ( cffface->family_name ) { - char* full = cff_index_get_sid_string( &cff->string_index, - dict->full_name, - psnames ); + char* full = cff_index_get_sid_string( cff, + dict->full_name ); char* fullp = full; char* family = cffface->family_name; - char* family_name = 0; + char* family_name = NULL; + remove_subset_prefix( cffface->family_name ); + if ( dict->family_name ) { - family_name = cff_index_get_sid_string( &cff->string_index, - dict->family_name, - psnames); + family_name = cff_index_get_sid_string( cff, + dict->family_name ); if ( family_name ) family = family_name; } @@ -738,23 +761,18 @@ } break; } - - if ( family_name ) - FT_FREE( family_name ); - FT_FREE( full ); } } else { char *cid_font_name = - cff_index_get_sid_string( &cff->string_index, - dict->cid_font_name, - psnames ); + cff_index_get_sid_string( cff, + dict->cid_font_name ); /* do we have a `/FontName' for a CID-keyed font? */ if ( cid_font_name ) - cffface->family_name = cid_font_name; + cffface->family_name = cff_strcpy( memory, cid_font_name ); } if ( style_name ) @@ -797,16 +815,14 @@ flags |= FT_STYLE_FLAG_ITALIC; { - char *weight = cff_index_get_sid_string( &cff->string_index, - dict->weight, - psnames ); + char *weight = cff_index_get_sid_string( cff, + dict->weight ); if ( weight ) if ( !ft_strcmp( weight, "Bold" ) || !ft_strcmp( weight, "Black" ) ) flags |= FT_STYLE_FLAG_BOLD; - FT_FREE( weight ); } /* double check */ @@ -849,13 +865,14 @@ { cmap = cffface->charmaps[nn]; - /* Windows Unicode (3,1)? */ - if ( cmap->platform_id == 3 && cmap->encoding_id == 1 ) + /* Windows Unicode? */ + if ( cmap->platform_id == TT_PLATFORM_MICROSOFT && + cmap->encoding_id == TT_MS_ID_UNICODE_CS ) goto Skip_Unicode; - /* Deprecated Unicode platform id? */ - if ( cmap->platform_id == 0 ) - goto Skip_Unicode; /* Standard Unicode (deprecated) */ + /* Apple Unicode platform id? */ + if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE ) + goto Skip_Unicode; /* Apple Unicode */ } /* since CID-keyed fonts don't contain glyph names, we can't */ @@ -863,28 +880,51 @@ if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) goto Exit; +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "cff_face_init: no Unicode cmap is found, " + "and too many subtables (%d) to add synthesized cmap\n", + nn )); + goto Exit; + } +#endif + /* we didn't find a Unicode charmap -- synthesize one */ cmaprec.face = cffface; - cmaprec.platform_id = 3; - cmaprec.encoding_id = 1; + cmaprec.platform_id = TT_PLATFORM_MICROSOFT; + cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; cmaprec.encoding = FT_ENCODING_UNICODE; nn = (FT_UInt)cffface->num_charmaps; - FT_CMap_New( &FT_CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, &cmaprec, NULL ); + error = FT_CMap_New( &FT_CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, + &cmaprec, NULL ); + if ( error && FT_Err_No_Unicode_Glyph_Name != error ) + goto Exit; + error = FT_Err_Ok; /* if no Unicode charmap was previously selected, select this one */ if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) cffface->charmap = cffface->charmaps[nn]; Skip_Unicode: +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( nn > FT_MAX_CHARMAP_CACHEABLE ) + { + FT_ERROR(( "cff_face_init: Unicode cmap is found, " + "but too many preceding subtables (%d) to access\n", + nn - 1 )); + goto Exit; + } +#endif if ( encoding->count > 0 ) { FT_CMap_Class clazz; cmaprec.face = cffface; - cmaprec.platform_id = 7; /* Adobe platform id */ + cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */ if ( encoding->offset == 0 ) { @@ -905,7 +945,7 @@ clazz = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET; } - FT_CMap_New( clazz, NULL, &cmaprec, NULL ); + error = FT_CMap_New( clazz, NULL, &cmaprec, NULL ); } } } diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c index 01266a1..0d11a72 100644 --- a/src/cff/cffparse.c +++ b/src/cff/cffparse.c @@ -4,7 +4,7 @@ /* */ /* CFF token stream parser (body) */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -137,26 +137,23 @@ FT_UInt nib; FT_UInt phase; - FT_Long result, number, rest, exponent; + FT_Long result, number, exponent; FT_Int sign = 0, exponent_sign = 0; FT_Long exponent_add, integer_length, fraction_length; if ( scaling ) - *scaling = 0; + *scaling = 0; result = 0; number = 0; - rest = 0; exponent = 0; exponent_add = 0; integer_length = 0; fraction_length = 0; - FT_UNUSED( rest ); - /* First of all, read the integer part. */ phase = 4; @@ -332,11 +329,19 @@ goto Exit; /* Remove non-significant digits. */ - if ( integer_length < 0 ) { + if ( integer_length < 0 ) + { number /= power_tens[-integer_length]; fraction_length += integer_length; } + /* this can only happen if exponent was non-zero */ + if ( fraction_length == 10 ) + { + number /= 10; + fraction_length -= 1; + } + /* Convert into 16.16 format. */ if ( fraction_length > 0 ) { @@ -702,7 +707,7 @@ clazz[i].count_offset = 0; *output_class = clazz; - return FT_Err_Ok; + return CFF_Err_Ok; } diff --git a/src/cff/cffpic.c b/src/cff/cffpic.c index 568956d..5d01bd4 100644 --- a/src/cff/cffpic.c +++ b/src/cff/cffpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for cff module. */ /* */ -/* Copyright 2009 by */ +/* Copyright 2009, 2010 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -59,18 +59,20 @@ } } + FT_Error - cff_driver_class_pic_init( FT_Library library ) + cff_driver_class_pic_init( FT_Library library ) { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - CffModulePIC* container; - FT_Memory memory = library->memory; + FT_PIC_Container* pic_container = &library->pic_container; + FT_Error error = CFF_Err_Ok; + CffModulePIC* container; + FT_Memory memory = library->memory; + /* allocate pointer, clear and set global container pointer */ if ( FT_ALLOC ( container, sizeof ( *container ) ) ) return error; - FT_MEM_SET( container, 0, sizeof(*container) ); + FT_MEM_SET( container, 0, sizeof ( *container ) ); pic_container->cff = container; /* initialize pointer table - this is how the module usually expects this data */ diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h index df92e9a..d405357 100644 --- a/src/cff/cfftypes.h +++ b/src/cff/cfftypes.h @@ -5,7 +5,7 @@ /* Basic OpenType/CFF type definitions and interface (specification */ /* only). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008 by */ +/* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -24,6 +24,9 @@ #include #include FT_FREETYPE_H #include FT_TYPE1_TABLES_H +#include FT_INTERNAL_SERVICE_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H FT_BEGIN_HEADER @@ -204,8 +207,7 @@ FT_BEGIN_HEADER CFF_PrivateRec private_dict; CFF_IndexRec local_subrs_index; - FT_UInt num_local_subrs; - FT_Byte** local_subrs; + FT_Byte** local_subrs; /* array of pointers into Local Subrs INDEX data */ } CFF_SubFontRec, *CFF_SubFont; @@ -229,7 +231,6 @@ FT_BEGIN_HEADER CFF_IndexRec name_index; CFF_IndexRec top_dict_index; - CFF_IndexRec string_index; CFF_IndexRec global_subrs_index; CFF_EncodingRec encoding; @@ -241,9 +242,15 @@ FT_BEGIN_HEADER CFF_IndexRec local_subrs_index; FT_String* font_name; - FT_UInt num_global_subrs; + + /* array of pointers into Global Subrs INDEX data */ FT_Byte** global_subrs; + /* array of pointers into String INDEX data stored at string_pool */ + FT_UInt num_strings; + FT_Byte** strings; + FT_Byte* string_pool; + CFF_SubFontRec top_font; FT_UInt num_subfonts; CFF_SubFont subfonts[CFF_MAX_CID_FONTS]; @@ -251,10 +258,10 @@ FT_BEGIN_HEADER CFF_FDSelectRec fd_select; /* interface to PostScript hinter */ - void* pshinter; + PSHinter_Service pshinter; /* interface to Postscript Names service */ - void* psnames; + FT_Service_PsCMaps psnames; /* since version 2.3.0 */ PS_FontInfoRec* font_info; /* font info dictionary */ diff --git a/src/psaux/afmparse.c b/src/psaux/afmparse.c index 91a17e2..d7de373 100644 --- a/src/psaux/afmparse.c +++ b/src/psaux/afmparse.c @@ -4,7 +4,7 @@ /* */ /* AFM parser (body). */ /* */ -/* Copyright 2006, 2007, 2008, 2009 by */ +/* Copyright 2006, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -527,7 +527,7 @@ FT_Byte* base, FT_Byte* limit ) { - AFM_Stream stream; + AFM_Stream stream = NULL; FT_Error error; diff --git a/src/psaux/afmparse.h b/src/psaux/afmparse.h index de2a530..35d9604 100644 --- a/src/psaux/afmparse.h +++ b/src/psaux/afmparse.h @@ -56,7 +56,8 @@ FT_BEGIN_HEADER typedef struct AFM_ValueRec_ { enum AFM_ValueType_ type; - union { + union + { char* s; FT_Fixed f; FT_Int i; diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c index fe8398a..45c7419 100644 --- a/src/psaux/psobjs.c +++ b/src/psaux/psobjs.c @@ -4,7 +4,8 @@ /* */ /* Auxiliary functions for PostScript fonts (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -1588,6 +1589,13 @@ FT_Error error; + /* this might happen in invalid fonts */ + if ( !outline ) + { + FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" )); + return PSaux_Err_Invalid_File_Format; + } + if ( !builder->load_points ) { outline->n_contours++; @@ -1621,7 +1629,7 @@ if ( builder->parse_state == T1_Parse_Have_Path ) error = PSaux_Err_Ok; - else if ( builder->parse_state == T1_Parse_Have_Moveto ) + else { builder->parse_state = T1_Parse_Have_Path; error = t1_builder_add_contour( builder ); diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c index 31554ff..babf3ba 100644 --- a/src/psaux/t1decode.c +++ b/src/psaux/t1decode.c @@ -777,6 +777,8 @@ } /* the two `results' are popped by the following setcurrentpoint */ + top[0] = x; + top[1] = y; known_othersubr_result_cnt = 2; break; @@ -1480,8 +1482,12 @@ goto Syntax_Error; } else + ... #endif - decoder->flex_state = 0; + + x = top[0]; + y = top[1]; + decoder->flex_state = 0; break; case op_unknown15: diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c index 417dcee..4b08785 100644 --- a/src/pshinter/pshalgo.c +++ b/src/pshinter/pshalgo.c @@ -4,7 +4,8 @@ /* */ /* PostScript hinting algorithm (body). */ /* */ -/* Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 */ +/* by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ @@ -1690,7 +1691,10 @@ /* process secondary hints to `selected' points */ if ( num_masks > 1 && glyph->num_points > 0 ) { - first = mask->end_point; + /* the `endchar' op can reduce the number of points */ + first = mask->end_point > glyph->num_points + ? glyph->num_points + : mask->end_point; mask++; for ( ; num_masks > 1; num_masks--, mask++ ) { @@ -1698,7 +1702,9 @@ FT_Int count; - next = mask->end_point; + next = mask->end_point > glyph->num_points + ? glyph->num_points + : mask->end_point; count = next - first; if ( count > 0 ) { diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c index 8a69aa1..31231ad 100644 --- a/src/pshinter/pshglob.c +++ b/src/pshinter/pshglob.c @@ -5,7 +5,7 @@ /* PostScript hinter global hinting management (body). */ /* Inspired by the new auto-hinter module. */ /* */ -/* Copyright 2001, 2002, 2003, 2004, 2006 by */ +/* Copyright 2001, 2002, 2003, 2004, 2006, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ @@ -624,7 +624,7 @@ T1_Private* priv, PSH_Globals *aglobals ) { - PSH_Globals globals; + PSH_Globals globals = NULL; FT_Error error; diff --git a/src/pshinter/pshpic.c b/src/pshinter/pshpic.c index 51a0879..5efb422 100644 --- a/src/pshinter/pshpic.c +++ b/src/pshinter/pshpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for pshinter module. */ /* */ -/* Copyright 2009 by */ +/* Copyright 2009, 2010 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -38,18 +38,20 @@ } } + FT_Error - pshinter_module_class_pic_init( FT_Library library ) + pshinter_module_class_pic_init( FT_Library library ) { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - PSHinterPIC* container; - FT_Memory memory = library->memory; + FT_PIC_Container* pic_container = &library->pic_container; + FT_Error error = PSH_Err_Ok; + PSHinterPIC* container; + FT_Memory memory = library->memory; + /* allocate pointer, clear and set global container pointer */ if ( FT_ALLOC ( container, sizeof ( *container ) ) ) return error; - FT_MEM_SET( container, 0, sizeof(*container) ); + FT_MEM_SET( container, 0, sizeof ( *container ) ); pic_container->pshinter = container; /* add call to initialization function when you add new scripts */ diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c index 00b363f..7528696 100644 --- a/src/psnames/psmodule.c +++ b/src/psnames/psmodule.c @@ -366,11 +366,13 @@ if ( count == 0 ) { + /* No unicode chars here! */ FT_FREE( table->maps ); if ( !error ) - error = PSnames_Err_Invalid_Argument; /* No unicode chars here! */ + error = PSnames_Err_No_Unicode_Glyph_Name; } - else { + else + { /* Reallocate if the number of used entries is much smaller. */ if ( count < num_glyphs / 2 ) { diff --git a/src/psnames/pspic.c b/src/psnames/pspic.c index ed7dadd..b9075d5 100644 --- a/src/psnames/pspic.c +++ b/src/psnames/pspic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for psnames module. */ /* */ -/* Copyright 2009 by */ +/* Copyright 2009, 2010 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -44,13 +44,15 @@ } } + FT_Error - psnames_module_class_pic_init( FT_Library library ) + psnames_module_class_pic_init( FT_Library library ) { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - PSModulePIC* container; - FT_Memory memory = library->memory; + FT_PIC_Container* pic_container = &library->pic_container; + FT_Error error = PSnames_Err_Ok; + PSModulePIC* container; + FT_Memory memory = library->memory; + /* allocate pointer, clear and set global container pointer */ if ( FT_ALLOC ( container, sizeof ( *container ) ) ) diff --git a/src/raster/ftmisc.h b/src/raster/ftmisc.h index f04b540..7773924 100644 --- a/src/raster/ftmisc.h +++ b/src/raster/ftmisc.h @@ -5,7 +5,7 @@ /* Miscellaneous macros for stand-alone rasterizer (specification */ /* only). */ /* */ -/* Copyright 2005, 2009 by */ +/* Copyright 2005, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ @@ -27,6 +27,7 @@ #ifndef __FTMISC_H__ #define __FTMISC_H__ + /* memset */ #include FT_CONFIG_STANDARD_LIBRARY_H @@ -35,6 +36,7 @@ #define FT_LOCAL_DEF( x ) static x + /* from include/freetype2/fttypes.h */ typedef unsigned char FT_Byte; @@ -77,12 +79,22 @@ } FT_MemoryRec; + /* from src/ftcalc.c */ -#include +#if ( defined _WIN32 || defined _WIN64 ) + + typedef __int64 FT_Int64; + +#else + +#include "inttypes.h" typedef int64_t FT_Int64; +#endif + + static FT_Long FT_MulDiv( FT_Long a, FT_Long b, diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c index 23ad592..ce6fdfe 100644 --- a/src/raster/ftraster.c +++ b/src/raster/ftraster.c @@ -4,7 +4,7 @@ /* */ /* The FreeType glyph rasterizer (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -1122,13 +1122,13 @@ if ( Dx > 0 ) { - Ix = ( ras.precision * Dx ) / Dy; + Ix = SMulDiv( ras.precision, Dx, Dy); Rx = ( ras.precision * Dx ) % Dy; Dx = 1; } else { - Ix = -( ( ras.precision * -Dx ) / Dy ); + Ix = SMulDiv( ras.precision, -Dx, Dy) * -1; Rx = ( ras.precision * -Dx ) % Dy; Dx = -1; } @@ -1931,18 +1931,21 @@ y1 = SCALED( point[-2].y ); x2 = SCALED( point[-1].x ); y2 = SCALED( point[-1].y ); - x3 = SCALED( point[ 0].x ); - y3 = SCALED( point[ 0].y ); if ( flipped ) { SWAP_( x1, y1 ); SWAP_( x2, y2 ); - SWAP_( x3, y3 ); } if ( point <= limit ) { + x3 = SCALED( point[0].x ); + y3 = SCALED( point[0].y ); + + if ( flipped ) + SWAP_( x3, y3 ); + if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) ) goto Fail; continue; @@ -2495,7 +2498,7 @@ PByte p; - p = bits - e1*ras.target.pitch; + p = bits - e1 * ras.target.pitch; if ( ras.target.pitch > 0 ) p += ( ras.target.rows - 1 ) * ras.target.pitch; @@ -3400,7 +3403,7 @@ } -#else /* _STANDALONE_ */ +#else /* !_STANDALONE_ */ static int @@ -3408,7 +3411,7 @@ PRaster *araster ) { FT_Error error; - PRaster raster; + PRaster raster = NULL; *araster = 0; @@ -3432,7 +3435,7 @@ } -#endif /* _STANDALONE_ */ +#endif /* !_STANDALONE_ */ static void @@ -3447,9 +3450,8 @@ PWorker worker = (PWorker)pool_base; - raster->buffer = pool_base + ( (sizeof ( *worker ) + 7 ) & ~7 ); - raster->buffer_size = ( ( pool_base + pool_size ) - - (char*)raster->buffer ) / sizeof ( Long ); + raster->buffer = pool_base + ( ( sizeof ( *worker ) + 7 ) & ~7 ); + raster->buffer_size = pool_base + pool_size - (char*)raster->buffer; raster->worker = worker; } else diff --git a/src/raster/rastpic.c b/src/raster/rastpic.c index 3c26487..e31c549 100644 --- a/src/raster/rastpic.c +++ b/src/raster/rastpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for raster module. */ /* */ -/* Copyright 2009 by */ +/* Copyright 2009, 2010 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -43,16 +43,17 @@ FT_Error - ft_raster1_renderer_class_pic_init( FT_Library library ) + ft_raster1_renderer_class_pic_init( FT_Library library ) { FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - RasterPIC* container; - FT_Memory memory = library->memory; + FT_Error error = Raster_Err_Ok; + RasterPIC* container; + FT_Memory memory = library->memory; + /* since this function also serve raster5 renderer, it implements reference counting */ - if(pic_container->raster) + if ( pic_container->raster ) { ((RasterPIC*)pic_container->raster)->ref_count++; return error; diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index 1097efb..b74679b 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ /* */ /* High-level SFNT driver interface (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -362,7 +362,7 @@ *acharset_registry = registry.u.atom; } else - error = FT_Err_Invalid_Argument; + error = SFNT_Err_Invalid_Argument; } } @@ -436,7 +436,7 @@ FT_UNUSED( face_index ); FT_UNUSED( header ); - return FT_Err_Unimplemented_Feature; + return SFNT_Err_Unimplemented_Feature; } @@ -449,7 +449,7 @@ FT_UNUSED( stream ); FT_UNUSED( header ); - return FT_Err_Unimplemented_Feature; + return SFNT_Err_Unimplemented_Feature; } @@ -460,7 +460,7 @@ FT_UNUSED( face ); FT_UNUSED( stream ); - return FT_Err_Unimplemented_Feature; + return SFNT_Err_Unimplemented_Feature; } @@ -513,7 +513,7 @@ * is only there for some rogue clients which would want to call it * directly (which doesn't make much sense). */ - return FT_Err_Unimplemented_Feature; + return SFNT_Err_Unimplemented_Feature; } @@ -534,7 +534,7 @@ FT_UNUSED( cmap ); FT_UNUSED( input ); - return FT_Err_Unimplemented_Feature; + return SFNT_Err_Unimplemented_Feature; } @@ -545,7 +545,7 @@ FT_UNUSED( face ); FT_UNUSED( cmap ); - return 0; + return SFNT_Err_Ok; } #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ diff --git a/src/sfnt/sfntpic.c b/src/sfnt/sfntpic.c index fd3cf4e..53aca17 100644 --- a/src/sfnt/sfntpic.c +++ b/src/sfnt/sfntpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for sfnt module. */ /* */ -/* Copyright 2009 by */ +/* Copyright 2009, 2010 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -60,15 +60,16 @@ FT_Error sfnt_module_class_pic_init( FT_Library library ) { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - sfntModulePIC* container; - FT_Memory memory = library->memory; + FT_PIC_Container* pic_container = &library->pic_container; + FT_Error error = SFNT_Err_Ok; + sfntModulePIC* container; + FT_Memory memory = library->memory; + /* allocate pointer, clear and set global container pointer */ if ( FT_ALLOC ( container, sizeof ( *container ) ) ) return error; - FT_MEM_SET( container, 0, sizeof(*container) ); + FT_MEM_SET( container, 0, sizeof ( *container ) ); pic_container->sfnt = container; /* initialize pointer table - this is how the module usually expects this data */ diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index b74b1a9..6e35e2d 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -4,7 +4,7 @@ /* */ /* SFNT object management (base). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -50,9 +50,9 @@ tt_name_entry_ascii_from_utf16( TT_NameEntry entry, FT_Memory memory ) { - FT_String* string; + FT_String* string = NULL; FT_UInt len, code, n; - FT_Byte* read = (FT_Byte*)entry->string; + FT_Byte* read = (FT_Byte*)entry->string; FT_Error error; @@ -81,9 +81,9 @@ tt_name_entry_ascii_from_other( TT_NameEntry entry, FT_Memory memory ) { - FT_String* string; + FT_String* string = NULL; FT_UInt len, code, n; - FT_Byte* read = (FT_Byte*)entry->string; + FT_Byte* read = (FT_Byte*)entry->string; FT_Error error; @@ -160,7 +160,7 @@ /* According to the OpenType 1.3 specification, only Microsoft or */ /* Apple platform IDs might be used in the `name' table. The */ /* `Unicode' platform is reserved for the `cmap' table, and the */ - /* `Iso' one is deprecated. */ + /* `ISO' one is deprecated. */ /* */ /* However, the Apple TrueType specification doesn't say the same */ /* thing and goes to suggest that all Unicode `name' table entries */ diff --git a/src/sfnt/ttbdf.c b/src/sfnt/ttbdf.c index 206cece..18845c3 100644 --- a/src/sfnt/ttbdf.c +++ b/src/sfnt/ttbdf.c @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded BDF properties (body). */ /* */ -/* Copyright 2005, 2006 by */ +/* Copyright 2005, 2006, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -74,7 +74,7 @@ length < 8 || FT_FRAME_EXTRACT( length, bdf->table ) ) { - error = FT_Err_Invalid_Table; + error = SFNT_Err_Invalid_Table; goto Exit; } @@ -131,7 +131,7 @@ BadTable: FT_FRAME_RELEASE( bdf->table ); FT_ZERO( bdf ); - error = FT_Err_Invalid_Table; + error = SFNT_Err_Invalid_Table; goto Exit; } @@ -143,7 +143,7 @@ { TT_BDF bdf = &face->bdf; FT_Size size = FT_FACE(face)->size; - FT_Error error = 0; + FT_Error error = SFNT_Err_Ok; FT_Byte* p; FT_UInt count; FT_Byte* strike; @@ -163,7 +163,7 @@ p = bdf->table + 8; strike = p + 4 * count; - error = FT_Err_Invalid_Argument; + error = SFNT_Err_Invalid_Argument; if ( size == NULL || property_name == NULL ) goto Exit; @@ -215,7 +215,7 @@ { aprop->type = BDF_PROPERTY_TYPE_ATOM; aprop->u.atom = (const char*)bdf->strings + value; - error = 0; + error = SFNT_Err_Ok; goto Exit; } break; @@ -223,13 +223,13 @@ case 0x02: aprop->type = BDF_PROPERTY_TYPE_INTEGER; aprop->u.integer = (FT_Int32)value; - error = 0; + error = SFNT_Err_Ok; goto Exit; case 0x03: aprop->type = BDF_PROPERTY_TYPE_CARDINAL; aprop->u.cardinal = value; - error = 0; + error = SFNT_Err_Ok; goto Exit; default: diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c index b283f6d..544750a 100644 --- a/src/sfnt/ttcmap.c +++ b/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ /* */ /* TrueType character mapping table (cmap) support (body). */ /* */ -/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -2689,7 +2689,7 @@ FT_Memory memory ) { FT_UInt32 old_max = cmap->max_results; - FT_Error error = 0; + FT_Error error = SFNT_Err_Ok; if ( num_results > cmap->max_results ) @@ -2787,7 +2787,8 @@ } /* and the non-default table (these glyphs are specified here) */ - if ( nondefOff != 0 ) { + if ( nondefOff != 0 ) + { FT_Byte* ndp = table + nondefOff; FT_ULong numMappings = TT_NEXT_ULONG( ndp ); FT_ULong i, lastUni = 0; @@ -3375,7 +3376,7 @@ clazz[i] = NULL; *output_class = clazz; - return FT_Err_Ok; + return SFNT_Err_Ok; } #endif /*FT_CONFIG_OPTION_PIC*/ @@ -3391,11 +3392,12 @@ FT_Byte* limit = table + face->cmap_size; FT_UInt volatile num_cmaps; FT_Byte* volatile p = table; - FT_Library library = FT_FACE_LIBRARY(face); - FT_UNUSED(library); + FT_Library library = FT_FACE_LIBRARY( face ); + + FT_UNUSED( library ); - if ( p + 4 > limit ) + if ( !p || p + 4 > limit ) return SFNT_Err_Invalid_Table; /* only recognize format 0 */ @@ -3409,6 +3411,12 @@ } num_cmaps = TT_NEXT_USHORT( p ); +#ifdef FT_MAX_CHARMAP_CACHEABLE + if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE ) + FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables(%d) " + "subtable#%d and later are loaded but cannot be searched\n", + num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 )); +#endif for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) { diff --git a/src/sfnt/ttkern.c b/src/sfnt/ttkern.c index c154080..4688898 100644 --- a/src/sfnt/ttkern.c +++ b/src/sfnt/ttkern.c @@ -5,7 +5,7 @@ /* Load the basic TrueType kerning table. This doesn't handle */ /* kerning data within the GPOS table at the moment. */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -115,7 +115,7 @@ num_pairs = FT_NEXT_USHORT( p ); p += 6; - if ( ( p_next - p ) / 6 < (int)num_pairs ) /* handle broken count */ + if ( ( p_next - p ) < 6 * (int)num_pairs ) /* handle broken count */ num_pairs = (FT_UInt)( ( p_next - p ) / 6 ); avail |= mask; @@ -220,7 +220,7 @@ num_pairs = FT_NEXT_USHORT( p ); p += 6; - if ( ( next - p ) / 6 < (int)num_pairs ) /* handle broken count */ + if ( ( next - p ) < 6 * (int)num_pairs ) /* handle broken count */ num_pairs = (FT_UInt)( ( next - p ) / 6 ); switch ( coverage >> 8 ) diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c index 3ad33bd..1c174af 100644 --- a/src/sfnt/ttload.c +++ b/src/sfnt/ttload.c @@ -5,7 +5,8 @@ /* Load the basic TrueType tables, i.e., tables that can be either in */ /* TTF or OTF fonts (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -77,7 +78,8 @@ { /* For compatibility with Windows, we consider */ /* zero-length tables the same as missing tables. */ - if ( entry->Tag == tag ) { + if ( entry->Tag == tag ) + { if ( entry->Length != 0 ) { FT_TRACE4(( "found table.\n" )); @@ -693,6 +695,15 @@ maxProfile->maxTwilightPoints = 0xFFFFU - 4; } + + /* we arbitrarily limit recursion to avoid stack exhaustion */ + if ( maxProfile->maxComponentDepth > 100 ) + { + FT_TRACE0(( "tt_face_load_maxp:" + " abnormally large component depth (%d) set to 100\n", + maxProfile->maxComponentDepth )); + maxProfile->maxComponentDepth = 100; + } } FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs )); diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c index 833bb2a..faa8f88 100644 --- a/src/sfnt/ttsbit.c +++ b/src/sfnt/ttsbit.c @@ -4,7 +4,8 @@ /* */ /* TrueType and OpenType embedded bitmap support (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -417,7 +418,7 @@ tt_face_load_eblc( TT_Face face, FT_Stream stream ) { - FT_Error error = 0; + FT_Error error = SFNT_Err_Ok; FT_Memory memory = stream->memory; FT_Fixed version; FT_ULong num_strikes; diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c index 846e454..0b94143 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -4,7 +4,7 @@ /* */ /* A new `perfect' anti-aliasing renderer (body). */ /* */ -/* Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -103,10 +103,12 @@ #include #endif +#include #include #include #include #define FT_UINT_MAX UINT_MAX +#define FT_INT_MAX INT_MAX #define ft_memset memset @@ -114,6 +116,8 @@ #define ft_longjmp longjmp #define ft_jmp_buf jmp_buf +typedef ptrdiff_t FT_PtrDist; + #define ErrRaster_Invalid_Mode -2 #define ErrRaster_Invalid_Outline -1 @@ -1007,56 +1011,53 @@ const FT_Vector* control2, const FT_Vector* to ) { - TPos dx, dy, da, db; int top, level; int* levels; FT_Vector* arc; + int mid_x = ( DOWNSCALE( ras.x ) + to->x + + 3 * (control1->x + control2->x ) ) / 8; + int mid_y = ( DOWNSCALE( ras.y ) + to->y + + 3 * (control1->y + control2->y ) ) / 8; + TPos dx = DOWNSCALE( ras.x ) + to->x - ( mid_x << 1 ); + TPos dy = DOWNSCALE( ras.y ) + to->y - ( mid_y << 1 ); - dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 ); if ( dx < 0 ) dx = -dx; - dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 ); if ( dy < 0 ) dy = -dy; if ( dx < dy ) dx = dy; - da = dx; - - dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x ); - if ( dx < 0 ) - dx = -dx; - dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y ); - if ( dy < 0 ) - dy = -dy; - if ( dx < dy ) - dx = dy; - db = dx; level = 1; - da = da / ras.cubic_level; - db = db / ras.conic_level; - while ( da > 0 || db > 0 ) + dx /= ras.cubic_level; + while ( dx > 0 ) { - da >>= 2; - db >>= 3; + dx >>= 2; level++; } if ( level <= 1 ) { - TPos to_x, to_y, mid_x, mid_y; + TPos to_x, to_y; to_x = UPSCALE( to->x ); to_y = UPSCALE( to->y ); + + /* Recalculation of midpoint is needed only if */ + /* UPSCALE and DOWNSCALE have any effect. */ + +#if ( PIXEL_BITS != 6 ) mid_x = ( ras.x + to_x + 3 * UPSCALE( control1->x + control2->x ) ) / 8; mid_y = ( ras.y + to_y + 3 * UPSCALE( control1->y + control2->y ) ) / 8; +#endif gray_render_line( RAS_VAR_ mid_x, mid_y ); gray_render_line( RAS_VAR_ to_x, to_y ); + return; } @@ -1104,7 +1105,7 @@ Draw: { - TPos to_x, to_y, mid_x, mid_y; + TPos to_x, to_y; to_x = arc[0].x; @@ -1189,7 +1190,7 @@ /* first of all, compute the scanline offset */ p = (unsigned char*)map->buffer - y * map->pitch; if ( map->pitch >= 0 ) - p += ( map->rows - 1 ) * map->pitch; + p += (unsigned)( ( map->rows - 1 ) * map->pitch ); for ( ; count > 0; count--, spans++ ) { @@ -2003,14 +2004,14 @@ FT_UNUSED( raster ); } -#else /* _STANDALONE_ */ +#else /* !_STANDALONE_ */ static int gray_raster_new( FT_Memory memory, FT_Raster* araster ) { FT_Error error; - PRaster raster; + PRaster raster = NULL; *araster = 0; @@ -2033,7 +2034,7 @@ FT_FREE( raster ); } -#endif /* _STANDALONE_ */ +#endif /* !_STANDALONE_ */ static void diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c index eed6353..7d16b94 100644 --- a/src/smooth/ftsmooth.c +++ b/src/smooth/ftsmooth.c @@ -4,7 +4,7 @@ /* */ /* Anti-aliasing renderer interface (body). */ /* */ -/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009 by */ +/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -200,7 +200,7 @@ /* Required check is ( pitch * height < FT_ULONG_MAX ), */ /* but we care realistic cases only. Always pitch <= width. */ - if ( width > 0xFFFFU || height > 0xFFFFU ) + if ( width > 0x7FFFU || height > 0x7FFFU ) { FT_ERROR(( "ft_smooth_render_generic: glyph too large: %d x %d\n", width, height )); diff --git a/src/smooth/ftspic.c b/src/smooth/ftspic.c index aa547fc..7adaab1 100644 --- a/src/smooth/ftspic.c +++ b/src/smooth/ftspic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for smooth module. */ /* */ -/* Copyright 2009 by */ +/* Copyright 2009, 2010 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -43,12 +43,13 @@ FT_Error - ft_smooth_renderer_class_pic_init( FT_Library library ) + ft_smooth_renderer_class_pic_init( FT_Library library ) { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - SmoothPIC* container; - FT_Memory memory = library->memory; + FT_PIC_Container* pic_container = &library->pic_container; + FT_Error error = Smooth_Err_Ok; + SmoothPIC* container; + FT_Memory memory = library->memory; + /* since this function also serve smooth_lcd and smooth_lcdv renderers, it implements reference counting */ diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index 57ea0ba..1b496c0 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -161,8 +161,31 @@ &top_bearing, &advance_height ); + loader->left_bearing = left_bearing; + loader->advance = advance_width; + loader->top_bearing = top_bearing; + loader->vadvance = advance_height; + + if ( !loader->linear_def ) + { + loader->linear_def = 1; + loader->linear = advance_width; + } + } + + #ifdef FT_CONFIG_OPTION_INCREMENTAL + static void + tt_get_metrics_incr_overrides( TT_Loader loader, + FT_UInt glyph_index ) + { + TT_Face face = (TT_Face)loader->face; + + FT_Short left_bearing = 0, top_bearing = 0; + FT_UShort advance_width = 0, advance_height = 0; + + /* If this is an incrementally loaded font check whether there are */ /* overriding metrics for this glyph. */ if ( face->root.internal->incremental_interface && @@ -172,9 +195,9 @@ FT_Error error; - metrics.bearing_x = left_bearing; + metrics.bearing_x = loader->left_bearing; metrics.bearing_y = 0; - metrics.advance = advance_width; + metrics.advance = loader->advance; metrics.advance_v = 0; error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( @@ -190,8 +213,8 @@ /* GWW: Do I do the same for vertical metrics? */ metrics.bearing_x = 0; - metrics.bearing_y = top_bearing; - metrics.advance = advance_height; + metrics.bearing_y = loader->top_bearing; + metrics.advance = loader->vadvance; error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( face->root.internal->incremental_interface->object, @@ -204,24 +227,24 @@ #endif /* 0 */ + loader->left_bearing = left_bearing; + loader->advance = advance_width; + loader->top_bearing = top_bearing; + loader->vadvance = advance_height; + + if ( !loader->linear_def ) + { + loader->linear_def = 1; + loader->linear = advance_width; + } } Exit: + return; + } #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - loader->left_bearing = left_bearing; - loader->advance = advance_width; - loader->top_bearing = top_bearing; - loader->vadvance = advance_height; - - if ( !loader->linear_def ) - { - loader->linear_def = 1; - loader->linear = advance_width; - } - } - /*************************************************************************/ /* */ @@ -271,7 +294,7 @@ FT_UNUSED( glyph_index ); - FT_TRACE5(( "Glyph %ld\n", glyph_index )); + FT_TRACE4(( "Glyph %ld\n", glyph_index )); /* the following line sets the `error' variable through macros! */ if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) ) @@ -367,7 +390,7 @@ if ( cont[0] <= prev_cont ) { /* unordered contours: this is invalid */ - error = FT_Err_Invalid_Table; + error = TT_Err_Invalid_Table; goto Fail; } prev_cont = cont[0]; @@ -1118,7 +1141,8 @@ { FT_Stream stream = loader->stream; - FT_UShort n_ins; + FT_UShort n_ins, max_ins; + FT_ULong tmp; /* TT_Load_Composite_Glyph only gives us the offset of instructions */ @@ -1130,12 +1154,27 @@ FT_TRACE5(( " Instructions size = %d\n", n_ins )); /* check it */ - if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions ) + max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions; + if ( n_ins > max_ins ) { - FT_TRACE0(( "TT_Process_Composite_Glyph: too many instructions (%d)\n", - n_ins )); + /* acroread ignores this field, so we only do a rough safety check */ + if ( (FT_Int)n_ins > loader->byte_len ) + { + FT_TRACE1(( "TT_Process_Composite_Glyph: " + "too many instructions (%d) for glyph with length %d\n", + n_ins, loader->byte_len )); + return TT_Err_Too_Many_Hints; + } - return TT_Err_Too_Many_Hints; + tmp = loader->exec->glyphSize; + error = Update_Max( loader->exec->memory, + &tmp, + sizeof ( FT_Byte ), + (void*)&loader->exec->glyphIns, + n_ins ); + loader->exec->glyphSize = (FT_UShort)tmp; + if ( error ) + return error; } else if ( n_ins == 0 ) return TT_Err_Ok; @@ -1316,8 +1355,14 @@ if ( header_only ) goto Exit; + /* must initialize points before (possibly) overriding */ + /* glyph metrics from the incremental interface */ TT_LOADER_SET_PP( loader ); +#ifdef FT_CONFIG_OPTION_INCREMENTAL + tt_get_metrics_incr_overrides( loader, glyph_index ); +#endif + #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT if ( ((TT_Face)(loader->face))->doblend ) @@ -1353,8 +1398,14 @@ goto Exit; } + /* must initialize points before (possibly) overriding */ + /* glyph metrics from the incremental interface */ TT_LOADER_SET_PP( loader ); +#ifdef FT_CONFIG_OPTION_INCREMENTAL + tt_get_metrics_incr_overrides( loader, glyph_index ); +#endif + /***********************************************************************/ /***********************************************************************/ /***********************************************************************/ @@ -1481,6 +1532,7 @@ FT_UInt num_base_subgs = gloader->base.num_subglyphs; FT_Stream old_stream = loader->stream; + FT_Int old_byte_len = loader->byte_len; FT_GlyphLoader_Add( gloader ); @@ -1535,7 +1587,8 @@ num_base_points ); } - loader->stream = old_stream; + loader->stream = old_stream; + loader->byte_len = old_byte_len; /* process the glyph */ loader->ins_pos = ins_pos; @@ -2031,9 +2084,11 @@ glyph->outline = loader.gloader->base.outline; glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; - /* In case bit 1 of the `flags' field in the `head' table isn't */ - /* set, translate array so that (0,0) is the glyph's origin. */ - if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x ) + /* Translate array so that (0,0) is the glyph's origin. Note */ + /* that this behaviour is independent on the value of bit 1 of */ + /* the `flags' field in the `head' table -- at least major */ + /* applications like Acroread indicate that. */ + if ( loader.pp1.x ) FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 ); } diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index ef25aaf..653d9d5 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ /* */ /* TrueType GX Font Variation loader */ /* */ -/* Copyright 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */ /* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -210,12 +210,12 @@ ft_var_readpackeddeltas( FT_Stream stream, FT_Offset delta_cnt ) { - FT_Short *deltas; + FT_Short *deltas = NULL; FT_UInt runcnt; FT_Offset i; FT_UInt j; FT_Memory memory = stream->memory; - FT_Error error = TT_Err_Ok; + FT_Error error = TT_Err_Ok; FT_UNUSED( error ); @@ -682,7 +682,11 @@ if ( fvar_head.version != (FT_Long)0x00010000L || fvar_head.countSizePairs != 2 || fvar_head.axisSize != 20 || + /* axisCount limit implied by 16-bit instanceSize */ + fvar_head.axisCount > 0x3FFE || fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount || + /* instanceCount limit implied by limited range of name IDs */ + fvar_head.instanceCount > 0x7EFF || fvar_head.offsetToData + fvar_head.axisCount * 20U + fvar_head.instanceCount * fvar_head.instanceSize > table_len ) { @@ -693,7 +697,7 @@ if ( FT_NEW( face->blend ) ) goto Exit; - /* XXX: TODO - check for overflows */ + /* cannot overflow 32-bit arithmetic because of limits above */ face->blend->mmvar_len = sizeof ( FT_MM_Var ) + fvar_head.axisCount * sizeof ( FT_Var_Axis ) + diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index 13aa9a2..d22e94f 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -4,8 +4,9 @@ /* */ /* TrueType bytecode interpreter (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ -/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */ +/* 2010 */ +/* by David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ @@ -223,9 +224,10 @@ /*************************************************************************/ /* */ - /* A simple bounds-checking macro. */ + /* Two simple bounds-checking macros. */ /* */ -#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) ) +#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) ) +#define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) ) #undef SUCCESS #define SUCCESS 0 @@ -508,7 +510,7 @@ /* */ /* FreeType error code. 0 means success. */ /* */ - static FT_Error + FT_LOCAL_DEF( FT_Error ) Update_Max( FT_Memory memory, FT_ULong* size, FT_Long multiplier, @@ -1111,6 +1113,287 @@ }; +#ifdef FT_DEBUG_LEVEL_TRACE + + static + const char* const opcode_name[256] = + { + "SVTCA y", + "SVTCA x", + "SPvTCA y", + "SPvTCA x", + "SFvTCA y", + "SFvTCA x", + "SPvTL ||", + "SPvTL +", + "SFvTL ||", + "SFvTL +", + "SPvFS", + "SFvFS", + "GPV", + "GFV", + "SFvTPv", + "ISECT", + + "SRP0", + "SRP1", + "SRP2", + "SZP0", + "SZP1", + "SZP2", + "SZPS", + "SLOOP", + "RTG", + "RTHG", + "SMD", + "ELSE", + "JMPR", + "SCvTCi", + "SSwCi", + "SSW", + + "DUP", + "POP", + "CLEAR", + "SWAP", + "DEPTH", + "CINDEX", + "MINDEX", + "AlignPTS", + "INS_$28", + "UTP", + "LOOPCALL", + "CALL", + "FDEF", + "ENDF", + "MDAP[0]", + "MDAP[1]", + + "IUP[0]", + "IUP[1]", + "SHP[0]", + "SHP[1]", + "SHC[0]", + "SHC[1]", + "SHZ[0]", + "SHZ[1]", + "SHPIX", + "IP", + "MSIRP[0]", + "MSIRP[1]", + "AlignRP", + "RTDG", + "MIAP[0]", + "MIAP[1]", + + "NPushB", + "NPushW", + "WS", + "RS", + "WCvtP", + "RCvt", + "GC[0]", + "GC[1]", + "SCFS", + "MD[0]", + "MD[1]", + "MPPEM", + "MPS", + "FlipON", + "FlipOFF", + "DEBUG", + + "LT", + "LTEQ", + "GT", + "GTEQ", + "EQ", + "NEQ", + "ODD", + "EVEN", + "IF", + "EIF", + "AND", + "OR", + "NOT", + "DeltaP1", + "SDB", + "SDS", + + "ADD", + "SUB", + "DIV", + "MUL", + "ABS", + "NEG", + "FLOOR", + "CEILING", + "ROUND[0]", + "ROUND[1]", + "ROUND[2]", + "ROUND[3]", + "NROUND[0]", + "NROUND[1]", + "NROUND[2]", + "NROUND[3]", + + "WCvtF", + "DeltaP2", + "DeltaP3", + "DeltaCn[0]", + "DeltaCn[1]", + "DeltaCn[2]", + "SROUND", + "S45Round", + "JROT", + "JROF", + "ROFF", + "INS_$7B", + "RUTG", + "RDTG", + "SANGW", + "AA", + + "FlipPT", + "FlipRgON", + "FlipRgOFF", + "INS_$83", + "INS_$84", + "ScanCTRL", + "SDVPTL[0]", + "SDVPTL[1]", + "GetINFO", + "IDEF", + "ROLL", + "MAX", + "MIN", + "ScanTYPE", + "InstCTRL", + "INS_$8F", + + "INS_$90", + "INS_$91", + "INS_$92", + "INS_$93", + "INS_$94", + "INS_$95", + "INS_$96", + "INS_$97", + "INS_$98", + "INS_$99", + "INS_$9A", + "INS_$9B", + "INS_$9C", + "INS_$9D", + "INS_$9E", + "INS_$9F", + + "INS_$A0", + "INS_$A1", + "INS_$A2", + "INS_$A3", + "INS_$A4", + "INS_$A5", + "INS_$A6", + "INS_$A7", + "INS_$A8", + "INS_$A9", + "INS_$AA", + "INS_$AB", + "INS_$AC", + "INS_$AD", + "INS_$AE", + "INS_$AF", + + "PushB[0]", + "PushB[1]", + "PushB[2]", + "PushB[3]", + "PushB[4]", + "PushB[5]", + "PushB[6]", + "PushB[7]", + "PushW[0]", + "PushW[1]", + "PushW[2]", + "PushW[3]", + "PushW[4]", + "PushW[5]", + "PushW[6]", + "PushW[7]", + + "MDRP[00]", + "MDRP[01]", + "MDRP[02]", + "MDRP[03]", + "MDRP[04]", + "MDRP[05]", + "MDRP[06]", + "MDRP[07]", + "MDRP[08]", + "MDRP[09]", + "MDRP[10]", + "MDRP[11]", + "MDRP[12]", + "MDRP[13]", + "MDRP[14]", + "MDRP[15]", + + "MDRP[16]", + "MDRP[17]", + "MDRP[18]", + "MDRP[19]", + "MDRP[20]", + "MDRP[21]", + "MDRP[22]", + "MDRP[23]", + "MDRP[24]", + "MDRP[25]", + "MDRP[26]", + "MDRP[27]", + "MDRP[28]", + "MDRP[29]", + "MDRP[30]", + "MDRP[31]", + + "MIRP[00]", + "MIRP[01]", + "MIRP[02]", + "MIRP[03]", + "MIRP[04]", + "MIRP[05]", + "MIRP[06]", + "MIRP[07]", + "MIRP[08]", + "MIRP[09]", + "MIRP[10]", + "MIRP[11]", + "MIRP[12]", + "MIRP[13]", + "MIRP[14]", + "MIRP[15]", + + "MIRP[16]", + "MIRP[17]", + "MIRP[18]", + "MIRP[19]", + "MIRP[20]", + "MIRP[21]", + "MIRP[22]", + "MIRP[23]", + "MIRP[24]", + "MIRP[25]", + "MIRP[26]", + "MIRP[27]", + "MIRP[28]", + "MIRP[29]", + "MIRP[30]", + "MIRP[31]" + }; + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + static const FT_Char opcode_length[256] = { @@ -1727,7 +2010,8 @@ if ( distance && val < 0 ) val = 0; } - else { + else + { val = distance - compensation; if ( val > 0 ) val = 0; @@ -2892,24 +3176,30 @@ } -#define DO_JROT \ - if ( args[1] != 0 ) \ - { \ - CUR.IP += args[0]; \ - CUR.step_ins = FALSE; \ +#define DO_JROT \ + if ( args[1] != 0 ) \ + { \ + CUR.IP += args[0]; \ + if ( CUR.IP < 0 ) \ + CUR.error = TT_Err_Bad_Argument; \ + CUR.step_ins = FALSE; \ } -#define DO_JMPR \ - CUR.IP += args[0]; \ +#define DO_JMPR \ + CUR.IP += args[0]; \ + if ( CUR.IP < 0 ) \ + CUR.error = TT_Err_Bad_Argument; \ CUR.step_ins = FALSE; -#define DO_JROF \ - if ( args[1] == 0 ) \ - { \ - CUR.IP += args[0]; \ - CUR.step_ins = FALSE; \ +#define DO_JROF \ + if ( args[1] == 0 ) \ + { \ + CUR.IP += args[0]; \ + if ( CUR.IP < 0 ) \ + CUR.error = TT_Err_Bad_Argument; \ + CUR.step_ins = FALSE; \ } @@ -2992,39 +3282,39 @@ args[0] = FT_PIX_CEIL( args[0] ); -#define DO_RS \ - { \ - FT_ULong I = (FT_ULong)args[0]; \ - \ - \ - if ( BOUNDS( I, CUR.storeSize ) ) \ - { \ - if ( CUR.pedantic_hinting ) \ - { \ - ARRAY_BOUND_ERROR; \ - } \ - else \ - args[0] = 0; \ - } \ - else \ - args[0] = CUR.storage[I]; \ +#define DO_RS \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDSL( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + else \ + args[0] = 0; \ + } \ + else \ + args[0] = CUR.storage[I]; \ } -#define DO_WS \ - { \ - FT_ULong I = (FT_ULong)args[0]; \ - \ - \ - if ( BOUNDS( I, CUR.storeSize ) ) \ - { \ - if ( CUR.pedantic_hinting ) \ - { \ - ARRAY_BOUND_ERROR; \ - } \ - } \ - else \ - CUR.storage[I] = args[1]; \ +#define DO_WS \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDSL( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR.storage[I] = args[1]; \ } @@ -3033,7 +3323,7 @@ FT_ULong I = (FT_ULong)args[0]; \ \ \ - if ( BOUNDS( I, CUR.cvtSize ) ) \ + if ( BOUNDSL( I, CUR.cvtSize ) ) \ { \ if ( CUR.pedantic_hinting ) \ { \ @@ -3052,7 +3342,7 @@ FT_ULong I = (FT_ULong)args[0]; \ \ \ - if ( BOUNDS( I, CUR.cvtSize ) ) \ + if ( BOUNDSL( I, CUR.cvtSize ) ) \ { \ if ( CUR.pedantic_hinting ) \ { \ @@ -3069,7 +3359,7 @@ FT_ULong I = (FT_ULong)args[0]; \ \ \ - if ( BOUNDS( I, CUR.cvtSize ) ) \ + if ( BOUNDSL( I, CUR.cvtSize ) ) \ { \ if ( CUR.pedantic_hinting ) \ { \ @@ -4390,7 +4680,7 @@ /* first of all, check the index */ F = args[0]; - if ( BOUNDS( F, CUR.maxFunc + 1 ) ) + if ( BOUNDSL( F, CUR.maxFunc + 1 ) ) goto Fail; /* Except for some old Apple fonts, all functions in a TrueType */ @@ -4466,7 +4756,7 @@ /* first of all, check the index */ F = args[1]; - if ( BOUNDS( F, CUR.maxFunc + 1 ) ) + if ( BOUNDSL( F, CUR.maxFunc + 1 ) ) goto Fail; /* Except for some old Apple fonts, all functions in a TrueType */ @@ -4569,7 +4859,7 @@ } def->opc = (FT_Byte)args[0]; - def->start = CUR.IP+1; + def->start = CUR.IP + 1; def->range = CUR.curRange; def->active = TRUE; @@ -4741,7 +5031,7 @@ L = (FT_ULong)args[0]; - if ( BOUNDS( L, CUR.zp2.n_points ) ) + if ( BOUNDSL( L, CUR.zp2.n_points ) ) { if ( CUR.pedantic_hinting ) { @@ -4825,8 +5115,8 @@ K = (FT_UShort)args[1]; L = (FT_UShort)args[0]; - if( BOUNDS( L, CUR.zp0.n_points ) || - BOUNDS( K, CUR.zp1.n_points ) ) + if ( BOUNDS( L, CUR.zp0.n_points ) || + BOUNDS( K, CUR.zp1.n_points ) ) { if ( CUR.pedantic_hinting ) { @@ -5480,12 +5770,12 @@ static void Ins_SHZ( INS_ARG ) { - TT_GlyphZoneRec zp; - FT_UShort refp; - FT_F26Dot6 dx, - dy; + TT_GlyphZoneRec zp; + FT_UShort refp; + FT_F26Dot6 dx, + dy; - FT_UShort last_point, i; + FT_UShort last_point, i; if ( BOUNDS( args[0], 2 ) ) @@ -5687,8 +5977,8 @@ cvtEntry = (FT_ULong)args[1]; point = (FT_UShort)args[0]; - if ( BOUNDS( point, CUR.zp0.n_points ) || - BOUNDS( cvtEntry, CUR.cvtSize ) ) + if ( BOUNDS( point, CUR.zp0.n_points ) || + BOUNDSL( cvtEntry, CUR.cvtSize ) ) { if ( CUR.pedantic_hinting ) CUR.error = TT_Err_Invalid_Reference; @@ -5880,7 +6170,7 @@ /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ if ( BOUNDS( point, CUR.zp1.n_points ) || - BOUNDS( cvtEntry, CUR.cvtSize + 1 ) || + BOUNDSL( cvtEntry, CUR.cvtSize + 1 ) || BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) @@ -6131,8 +6421,8 @@ p1 = (FT_UShort)args[0]; p2 = (FT_UShort)args[1]; - if ( BOUNDS( args[0], CUR.zp1.n_points ) || - BOUNDS( args[1], CUR.zp0.n_points ) ) + if ( BOUNDS( p1, CUR.zp1.n_points ) || + BOUNDS( p2, CUR.zp0.n_points ) ) { if ( CUR.pedantic_hinting ) CUR.error = TT_Err_Invalid_Reference; @@ -6466,8 +6756,8 @@ end_point = CUR.pts.contours[contour] - CUR.pts.first_point; first_point = point; - if ( CUR.pts.n_points <= end_point ) - end_point = CUR.pts.n_points; + if ( BOUNDS ( end_point, CUR.pts.n_points ) ) + end_point = CUR.pts.n_points - 1; while ( point <= end_point && ( CUR.pts.tags[point] & mask ) == 0 ) point++; @@ -6661,7 +6951,7 @@ A = (FT_ULong)CUR.stack[CUR.args + 1]; B = CUR.stack[CUR.args]; - if ( BOUNDS( A, CUR.cvtSize ) ) + if ( BOUNDSL( A, CUR.cvtSize ) ) { if ( CUR.pedantic_hinting ) { @@ -6771,7 +7061,7 @@ call = CUR.callStack + CUR.callTop++; call->Caller_Range = CUR.curRange; - call->Caller_IP = CUR.IP+1; + call->Caller_IP = CUR.IP + 1; call->Cur_Count = 1; call->Cur_Restart = def->start; @@ -7140,6 +7430,10 @@ { CUR.opcode = CUR.code[CUR.IP]; + FT_TRACE7(( " " )); + FT_TRACE7(( opcode_name[CUR.opcode] )); + FT_TRACE7(( "\n" )); + if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 ) { if ( CUR.IP + 1 > CUR.codeSize ) diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h index 07a8972..c480dfa 100644 --- a/src/truetype/ttinterp.h +++ b/src/truetype/ttinterp.h @@ -4,7 +4,7 @@ /* */ /* TrueType bytecode interpreter (specification). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -150,7 +150,7 @@ FT_BEGIN_HEADER FT_Bool step_ins; /* true if the interpreter must */ /* increment IP after ins. exec */ - FT_Long cvtSize; + FT_ULong cvtSize; FT_Long* cvt; FT_UInt glyphSize; /* glyph instructions buffer size */ @@ -239,6 +239,14 @@ FT_BEGIN_HEADER FT_Int range ); + FT_LOCAL( FT_Error ) + Update_Max( FT_Memory memory, + FT_ULong* size, + FT_Long multiplier, + void* _pbuff, + FT_ULong new_max ); + + /*************************************************************************/ /* */ /* */ diff --git a/src/truetype/ttpic.c b/src/truetype/ttpic.c index 27ec4a1..5d72574 100644 --- a/src/truetype/ttpic.c +++ b/src/truetype/ttpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for truetype module. */ /* */ -/* Copyright 2009 by */ +/* Copyright 2009, 2010 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -45,13 +45,15 @@ } } + FT_Error - tt_driver_class_pic_init( FT_Library library ) + tt_driver_class_pic_init( FT_Library library ) { - FT_PIC_Container* pic_container = &library->pic_container; - FT_Error error = FT_Err_Ok; - TTModulePIC* container; - FT_Memory memory = library->memory; + FT_PIC_Container* pic_container = &library->pic_container; + FT_Error error = TT_Err_Ok; + TTModulePIC* container; + FT_Memory memory = library->memory; + /* allocate pointer, clear and set global container pointer */ if ( FT_ALLOC ( container, sizeof ( *container ) ) ) -- cgit v1.2.3