aboutsummaryrefslogtreecommitdiff
path: root/freetype/src
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2011-07-18 10:51:09 +0200
committermarha <marha@users.sourceforge.net>2011-07-18 10:51:09 +0200
commit3c0d2312573b81e3067bea610a58b1940c075e05 (patch)
tree3f025a27d813374f225957801226aa8ee829a33a /freetype/src
parentba033884541714680fd7552ab9d6c8817650f7d8 (diff)
parent88101146f2ec7d53ffb793e365f05097ffd35fd3 (diff)
downloadvcxsrv-3c0d2312573b81e3067bea610a58b1940c075e05.tar.gz
vcxsrv-3c0d2312573b81e3067bea610a58b1940c075e05.tar.bz2
vcxsrv-3c0d2312573b81e3067bea610a58b1940c075e05.zip
Merge remote-tracking branch 'origin/released'
Conflicts: X11/Xfuncproto.h.in X11/configure.ac X11/keysymdef.h freetype/include/freetype/internal/pcftypes.h freetype/src/cache/ftcbasic.c freetype/src/cache/ftccmap.c mesalib/src/glsl/ir.h mesalib/src/glsl/link_functions.cpp mesalib/src/mesa/main/dlist.c mesalib/src/mesa/program/prog_optimize.c mesalib/src/mesa/state_tracker/st_program.c pthreads/Makefile
Diffstat (limited to 'freetype/src')
-rw-r--r--freetype/src/autofit/afangles.c4
-rw-r--r--freetype/src/autofit/afcjk.c835
-rw-r--r--freetype/src/autofit/afcjk.h104
-rw-r--r--freetype/src/autofit/afdummy.c9
-rw-r--r--freetype/src/autofit/afdummy.h4
-rw-r--r--freetype/src/autofit/afglobal.c14
-rw-r--r--freetype/src/autofit/afglobal.h8
-rw-r--r--freetype/src/autofit/afhints.c241
-rw-r--r--freetype/src/autofit/afhints.h217
-rw-r--r--freetype/src/autofit/afindic.c55
-rw-r--r--freetype/src/autofit/aflatin.c479
-rw-r--r--freetype/src/autofit/aflatin.h25
-rw-r--r--freetype/src/autofit/aflatin2.c227
-rw-r--r--freetype/src/autofit/afloader.c32
-rw-r--r--freetype/src/autofit/afloader.h8
-rw-r--r--freetype/src/autofit/afmodule.c17
-rw-r--r--freetype/src/autofit/afpic.c46
-rw-r--r--freetype/src/autofit/afpic.h27
-rw-r--r--freetype/src/autofit/aftypes.h129
-rw-r--r--freetype/src/autofit/afwarp.c62
-rw-r--r--freetype/src/autofit/autofit.c4
-rw-r--r--freetype/src/autofit/rules.mk7
-rw-r--r--freetype/src/base/ftbitmap.c2
-rw-r--r--freetype/src/base/ftobjs.c35
-rw-r--r--freetype/src/base/ftrfork.c8
-rw-r--r--freetype/src/base/ftstream.c72
-rw-r--r--freetype/src/base/ftstroke.c5
-rw-r--r--freetype/src/bdf/README4
-rw-r--r--freetype/src/bzip2/Jamfile19
-rw-r--r--freetype/src/bzip2/ftbzip2.c510
-rw-r--r--freetype/src/bzip2/rules.mk63
-rw-r--r--freetype/src/cache/ftcbasic.c8
-rw-r--r--freetype/src/cache/ftccache.c103
-rw-r--r--freetype/src/cache/ftccache.h66
-rw-r--r--freetype/src/cache/ftccback.h8
-rw-r--r--freetype/src/cache/ftccmap.c14
-rw-r--r--freetype/src/cache/ftcglyph.c18
-rw-r--r--freetype/src/cache/ftcglyph.h12
-rw-r--r--freetype/src/cache/ftcmanag.h2
-rw-r--r--freetype/src/cache/ftcmru.c12
-rw-r--r--freetype/src/cache/ftcsbits.c25
-rw-r--r--freetype/src/cache/ftcsbits.h9
-rw-r--r--freetype/src/cff/cffdrivr.c2
-rw-r--r--freetype/src/cff/cffgload.c19
-rw-r--r--freetype/src/cff/cffload.c4
-rw-r--r--freetype/src/cff/cffobjs.c60
-rw-r--r--freetype/src/cff/cfftypes.h5
-rw-r--r--freetype/src/cff/rules.mk15
-rw-r--r--freetype/src/gxvalid/gxvcommn.c45
-rw-r--r--freetype/src/gxvalid/gxvcommn.h16
-rw-r--r--freetype/src/gxvalid/gxvfeat.c25
-rw-r--r--freetype/src/gxvalid/gxvjust.c107
-rw-r--r--freetype/src/gxvalid/gxvkern.c66
-rw-r--r--freetype/src/gxvalid/gxvmort.c23
-rw-r--r--freetype/src/gxvalid/gxvmort0.c16
-rw-r--r--freetype/src/gxvalid/gxvmort1.c27
-rw-r--r--freetype/src/gxvalid/gxvmort2.c37
-rw-r--r--freetype/src/gxvalid/gxvmort5.c9
-rw-r--r--freetype/src/gxvalid/gxvmorx.c15
-rw-r--r--freetype/src/gxvalid/gxvmorx0.c8
-rw-r--r--freetype/src/gxvalid/gxvmorx1.c7
-rw-r--r--freetype/src/gxvalid/gxvmorx2.c40
-rw-r--r--freetype/src/gxvalid/gxvmorx5.c8
-rw-r--r--freetype/src/gxvalid/gxvprop.c30
-rw-r--r--freetype/src/gxvalid/gxvtrak.c19
-rw-r--r--freetype/src/gzip/ftgzip.c8
-rw-r--r--freetype/src/lzw/ftlzw.c2
-rw-r--r--freetype/src/pcf/README26
-rw-r--r--freetype/src/pcf/pcf.h6
-rw-r--r--freetype/src/pcf/pcfdrivr.c44
-rw-r--r--freetype/src/pcf/pcfread.c10
-rw-r--r--freetype/src/pfr/pfrload.c2
-rw-r--r--freetype/src/psaux/psobjs.c13
-rw-r--r--freetype/src/pshinter/rules.mk7
-rw-r--r--freetype/src/psnames/rules.mk9
-rw-r--r--freetype/src/raster/ftraster.c42
-rw-r--r--freetype/src/raster/ftrend1.c8
-rw-r--r--freetype/src/raster/rules.mk5
-rw-r--r--freetype/src/sfnt/rules.mk5
-rw-r--r--freetype/src/sfnt/sfdriver.c19
-rw-r--r--freetype/src/sfnt/sfobjs.c17
-rw-r--r--freetype/src/sfnt/ttload.c2
-rw-r--r--freetype/src/sfnt/ttmtx.c4
-rw-r--r--freetype/src/sfnt/ttsbit.c2
-rw-r--r--freetype/src/smooth/ftgrays.c15
-rw-r--r--freetype/src/smooth/ftsmooth.c9
-rw-r--r--freetype/src/smooth/rules.mk5
-rw-r--r--freetype/src/tools/glnames.py7
-rw-r--r--freetype/src/truetype/rules.mk11
-rw-r--r--freetype/src/truetype/ttdriver.c9
-rw-r--r--freetype/src/truetype/ttgload.c53
-rw-r--r--freetype/src/truetype/ttgload.h4
-rw-r--r--freetype/src/truetype/ttgxvar.c6
-rw-r--r--freetype/src/truetype/ttinterp.c210
-rw-r--r--freetype/src/truetype/ttobjs.c131
-rw-r--r--freetype/src/truetype/ttobjs.h11
-rw-r--r--freetype/src/truetype/ttpload.c13
-rw-r--r--freetype/src/type1/t1load.c2
98 files changed, 3718 insertions, 1151 deletions
diff --git a/freetype/src/autofit/afangles.c b/freetype/src/autofit/afangles.c
index e2360d157..790af1779 100644
--- a/freetype/src/autofit/afangles.c
+++ b/freetype/src/autofit/afangles.c
@@ -5,7 +5,7 @@
/* Routines used to compute vector angles with limited accuracy */
/* and very high speed. It also contains sorting routines (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006 by */
+/* Copyright 2003-2006, 2011 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 @@
return 1 - 2 * ( delta < 0 );
}
-#endif
+#endif /* 0 */
/*
diff --git a/freetype/src/autofit/afcjk.c b/freetype/src/autofit/afcjk.c
index f3b1067ed..0acef9c85 100644
--- a/freetype/src/autofit/afcjk.c
+++ b/freetype/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for CJK script (body). */
/* */
-/* Copyright 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 2006-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,22 +22,38 @@
*
*/
+#include <ft2build.h>
+#include FT_ADVANCES_H
+#include FT_INTERNAL_DEBUG_H
+
#include "aftypes.h"
#include "aflatin.h"
#ifdef AF_CONFIG_OPTION_CJK
+#undef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+
#include "afcjk.h"
#include "aferrors.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
/*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_afcjk
+
+
+ /*************************************************************************/
/*************************************************************************/
/***** *****/
/***** C J K G L O B A L M E T R I C S *****/
@@ -45,24 +61,504 @@
/*************************************************************************/
/*************************************************************************/
+
+ /* Basically the Latin version with AF_CJKMetrics */
+ /* to replace AF_LatinMetrics. */
+
+ FT_LOCAL_DEF( void )
+ af_cjk_metrics_init_widths( AF_CJKMetrics metrics,
+ FT_Face face,
+ FT_ULong charcode )
+ {
+ /* scan the array of segments in each direction */
+ AF_GlyphHintsRec hints[1];
+
+
+ af_glyph_hints_init( hints, face->memory );
+
+ metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
+ metrics->axis[AF_DIMENSION_VERT].width_count = 0;
+
+ {
+ FT_Error error;
+ FT_UInt glyph_index;
+ int dim;
+ AF_CJKMetricsRec dummy[1];
+ AF_Scaler scaler = &dummy->root.scaler;
+
+
+ glyph_index = FT_Get_Char_Index( face, charcode );
+ if ( glyph_index == 0 )
+ goto Exit;
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || face->glyph->outline.n_points <= 0 )
+ goto Exit;
+
+ FT_ZERO( dummy );
+
+ dummy->units_per_em = metrics->units_per_em;
+
+ scaler->x_scale = 0x10000L;
+ scaler->y_scale = 0x10000L;
+ scaler->x_delta = 0;
+ scaler->y_delta = 0;
+
+ scaler->face = face;
+ scaler->render_mode = FT_RENDER_MODE_NORMAL;
+ scaler->flags = 0;
+
+ af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy );
+
+ error = af_glyph_hints_reload( hints, &face->glyph->outline );
+ if ( error )
+ goto Exit;
+
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_CJKAxis axis = &metrics->axis[dim];
+ AF_AxisHints axhints = &hints->axis[dim];
+ AF_Segment seg, limit, link;
+ FT_UInt num_widths = 0;
+
+
+ error = af_latin_hints_compute_segments( hints, (AF_Dimension)dim );
+ if ( error )
+ goto Exit;
+
+ af_latin_hints_link_segments( hints, (AF_Dimension)dim );
+
+ seg = axhints->segments;
+ limit = seg + axhints->num_segments;
+
+ for ( ; seg < limit; seg++ )
+ {
+ link = seg->link;
+
+ /* we only consider stem segments there! */
+ if ( link && link->link == seg && link > seg )
+ {
+ FT_Pos dist;
+
+
+ dist = seg->pos - link->pos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( num_widths < AF_CJK_MAX_WIDTHS )
+ axis->widths[num_widths++].org = dist;
+ }
+ }
+
+ af_sort_widths( num_widths, axis->widths );
+ axis->width_count = num_widths;
+ }
+
+ Exit:
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_CJKAxis axis = &metrics->axis[dim];
+ FT_Pos stdw;
+
+
+ stdw = ( axis->width_count > 0 ) ? axis->widths[0].org
+ : AF_LATIN_CONSTANT( metrics, 50 );
+
+ /* let's try 20% of the smallest width */
+ axis->edge_distance_threshold = stdw / 5;
+ axis->standard_width = stdw;
+ axis->extra_light = 0;
+ }
+ }
+
+ af_glyph_hints_done( hints );
+ }
+
+
+#define AF_CJK_MAX_TEST_CHARACTERS 32
+
+
+ /* Each blue zone has two types of fill and unfill, this is, */
+ /* filling the entire glyph square or not. */
+
+ enum
+ {
+ AF_CJK_BLUE_TYPE_FILL,
+ AF_CJK_BLUE_TYPE_UNFILL,
+ AF_CJK_BLUE_TYPE_MAX
+ };
+
+
+ /* Put some common and representative Han Ideographs characters here. */
+ static const FT_ULong af_cjk_hani_blue_chars[AF_CJK_BLUE_MAX]
+ [AF_CJK_BLUE_TYPE_MAX]
+ [AF_CJK_MAX_TEST_CHARACTERS] =
+ {
+ {
+ {
+ 0x4ED6, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
+ 0x5BF9, 0x5C0D, 0x5C31, 0x5E2D, 0x6211, 0x65F6, 0x6642, 0x6703,
+ 0x6765, 0x70BA, 0x80FD, 0x8230, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
+ 0x9F4A /* top fill */
+ },
+ {
+ 0x519B, 0x540C, 0x5DF2, 0x613F, 0x65E2, 0x661F, 0x662F, 0x666F,
+ 0x6C11, 0x7167, 0x73B0, 0x73FE, 0x7406, 0x7528, 0x7F6E, 0x8981,
+ 0x8ECD, 0x90A3, 0x914D, 0x91CC, 0x958B, 0x96F7, 0x9732, 0x9762,
+ 0x987E /* top unfill */
+ }
+ },
+ {
+ {
+ 0x4E2A, 0x4E3A, 0x4EBA, 0x4ED6, 0x4EE5, 0x4EEC, 0x4F60, 0x4F86,
+ 0x500B, 0x5011, 0x5230, 0x548C, 0x5927, 0x5BF9, 0x5C0D, 0x5C31,
+ 0x6211, 0x65F6, 0x6642, 0x6709, 0x6765, 0x70BA, 0x8981, 0x8AAA,
+ 0x8BF4 /* bottom fill */
+ },
+ {
+ 0x4E3B, 0x4E9B, 0x56E0, 0x5B83, 0x60F3, 0x610F, 0x7406, 0x751F,
+ 0x7576, 0x770B, 0x7740, 0x7F6E, 0x8005, 0x81EA, 0x8457, 0x88E1,
+ 0x8FC7, 0x8FD8, 0x8FDB, 0x9032, 0x904E, 0x9053, 0x9084, 0x91CC,
+ 0x9762 /* bottom unfill */
+ }
+ },
+#ifndef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
+ { {0x0000}, {0x0000} },
+ { {0x0000}, {0x0000} }
+#else
+ {
+ {
+ 0x4E9B, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730,
+ 0x5979, 0x5C06, 0x5C07, 0x5C31, 0x5E74, 0x5F97, 0x60C5, 0x6700,
+ 0x6837, 0x6A23, 0x7406, 0x80FD, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019,
+ 0x901A /* left fill */
+ },
+ {
+ 0x5373, 0x5417, 0x5427, 0x542C, 0x5462, 0x54C1, 0x54CD, 0x55CE,
+ 0x5E08, 0x5E2B, 0x6536, 0x65AD, 0x65B7, 0x660E, 0x773C, 0x9593,
+ 0x95F4, 0x9645, 0x9648, 0x9650, 0x9664, 0x9673, 0x968F, 0x969B,
+ 0x96A8 /* left unfill */
+ }
+ },
+ {
+ {
+ 0x4E8B, 0x524D, 0x5B78, 0x5C06, 0x5C07, 0x60C5, 0x60F3, 0x6216,
+ 0x653F, 0x65AF, 0x65B0, 0x6837, 0x6A23, 0x6C11, 0x6C92, 0x6CA1,
+ 0x7136, 0x7279, 0x73B0, 0x73FE, 0x7403, 0x7B2C, 0x7D93, 0x8C01,
+ 0x8D77 /* right fill */
+ },
+ {
+ 0x4F8B, 0x5225, 0x522B, 0x5236, 0x52A8, 0x52D5, 0x5417, 0x55CE,
+ 0x589E, 0x6307, 0x660E, 0x671D, 0x671F, 0x6784, 0x7269, 0x786E,
+ 0x79CD, 0x8ABF, 0x8C03, 0x8CBB, 0x8D39, 0x90A3, 0x90FD, 0x9593,
+ 0x95F4 /* right unfill */
+ }
+ }
+#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
+ };
+
+
+ /* Calculate blue zones for all the CJK_BLUE_XXX's. */
+
+ static void
+ af_cjk_metrics_init_blues( AF_CJKMetrics metrics,
+ FT_Face face,
+ const FT_ULong blue_chars
+ [AF_CJK_BLUE_MAX]
+ [AF_CJK_BLUE_TYPE_MAX]
+ [AF_CJK_MAX_TEST_CHARACTERS] )
+ {
+ FT_Pos fills[AF_CJK_MAX_TEST_CHARACTERS];
+ FT_Pos flats[AF_CJK_MAX_TEST_CHARACTERS];
+
+ FT_Int num_fills;
+ FT_Int num_flats;
+
+ FT_Int bb;
+ AF_CJKBlue blue;
+ FT_Error error;
+ AF_CJKAxis axis;
+ FT_GlyphSlot glyph = face->glyph;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ FT_String* cjk_blue_name[AF_CJK_BLUE_MAX] = {
+ (FT_String*)"top",
+ (FT_String*)"bottom",
+ (FT_String*)"left",
+ (FT_String*)"right"
+ };
+ FT_String* cjk_blue_type_name[AF_CJK_BLUE_TYPE_MAX] = {
+ (FT_String*)"filled",
+ (FT_String*)"unfilled"
+ };
+#endif
+
+
+ /* We compute the blues simply by loading each character from the */
+ /* `blue_chars[blues]' string, then computing its extreme points */
+ /* (depending blue zone type etc.). */
+
+ FT_TRACE5(( "cjk blue zones computation\n" ));
+ FT_TRACE5(( "------------------------------------------------\n" ));
+
+ for ( bb = 0; bb < AF_CJK_BLUE_MAX; bb++ )
+ {
+ FT_Int fill_type;
+ FT_Pos* blue_ref;
+ FT_Pos* blue_shoot;
+
+
+ num_fills = 0;
+ num_flats = 0;
+
+ for ( fill_type = 0; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++ )
+ {
+ const FT_ULong* p = blue_chars[bb][fill_type];
+ const FT_ULong* limit = p + AF_CJK_MAX_TEST_CHARACTERS;
+ FT_Bool fill = FT_BOOL(
+ fill_type == AF_CJK_BLUE_TYPE_FILL );
+
+
+ FT_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb],
+ cjk_blue_type_name[fill_type] ));
+
+
+ for ( ; p < limit && *p; p++ )
+ {
+ FT_UInt glyph_index;
+ FT_Pos best_pos; /* same as points.y */
+ FT_Int best_point;
+ FT_Vector* points;
+
+
+ FT_TRACE5(( " U+%lX...", *p ));
+
+ /* load the character in the face -- skip unknown or empty ones */
+ glyph_index = FT_Get_Char_Index( face, *p );
+ if ( glyph_index == 0 )
+ {
+ FT_TRACE5(( "unavailable\n" ));
+ continue;
+ }
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || glyph->outline.n_points <= 0 )
+ {
+ FT_TRACE5(( "no outline\n" ));
+ continue;
+ }
+
+ /* now compute min or max point indices and coordinates */
+ points = glyph->outline.points;
+ best_point = -1;
+ best_pos = 0; /* make compiler happy */
+
+ {
+ FT_Int nn;
+ FT_Int first = 0;
+ FT_Int last = -1;
+
+
+ for ( nn = 0;
+ nn < glyph->outline.n_contours;
+ first = last + 1, nn++ )
+ {
+ FT_Int pp;
+
+
+ last = glyph->outline.contours[nn];
+
+ /* Avoid single-point contours since they are never */
+ /* rasterized. In some fonts, they correspond to mark */
+ /* attachment points which are way outside of the glyph's */
+ /* real outline. */
+ if ( last <= first )
+ continue;
+
+ switch ( bb )
+ {
+ case AF_CJK_BLUE_TOP:
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y > best_pos )
+ {
+ best_point = pp;
+ best_pos = points[pp].y;
+ }
+ break;
+
+ case AF_CJK_BLUE_BOTTOM:
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y < best_pos )
+ {
+ best_point = pp;
+ best_pos = points[pp].y;
+ }
+ break;
+
+ case AF_CJK_BLUE_LEFT:
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].x < best_pos )
+ {
+ best_point = pp;
+ best_pos = points[pp].x;
+ }
+ break;
+
+ case AF_CJK_BLUE_RIGHT:
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].x > best_pos )
+ {
+ best_point = pp;
+ best_pos = points[pp].x;
+ }
+ break;
+
+ default:
+ ;
+ }
+ }
+ FT_TRACE5(( "best_pos=%5ld\n", best_pos ));
+ }
+
+ if ( fill )
+ fills[num_fills++] = best_pos;
+ else
+ flats[num_flats++] = best_pos;
+ }
+ }
+
+ if ( num_flats == 0 && num_fills == 0 )
+ {
+ /*
+ * we couldn't find a single glyph to compute this blue zone,
+ * we will simply ignore it then
+ */
+ FT_TRACE5(( "empty\n" ));
+ continue;
+ }
+
+ /* we have computed the contents of the `fill' and `flats' tables, */
+ /* now determine the reference position of the blue -- */
+ /* we simply take the median value after a simple sort */
+ af_sort_pos( num_flats, flats );
+ af_sort_pos( num_fills, fills );
+
+ if ( AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_BOTTOM == bb )
+ axis = &metrics->axis[AF_DIMENSION_VERT];
+ else
+ axis = &metrics->axis[AF_DIMENSION_HORZ];
+
+ blue = & axis->blues[axis->blue_count];
+ blue_ref = & blue->ref.org;
+ blue_shoot = & blue->shoot.org;
+
+ axis->blue_count++;
+ if ( num_flats == 0 )
+ {
+ *blue_ref = fills[num_fills / 2];
+ *blue_shoot = fills[num_fills / 2];
+ }
+ else if ( num_fills == 0 )
+ {
+ *blue_ref = flats[num_flats / 2];
+ *blue_shoot = flats[num_flats / 2];
+ }
+ else
+ {
+ *blue_ref = fills[num_fills / 2];
+ *blue_shoot = flats[num_flats / 2];
+ }
+
+ /* make sure blue_ref >= blue_shoot for top/right or */
+ /* vice versa for bottom/left */
+ if ( *blue_shoot != *blue_ref )
+ {
+ FT_Pos ref = *blue_ref;
+ FT_Pos shoot = *blue_shoot;
+ FT_Bool under_ref = FT_BOOL( shoot < ref );
+
+
+ if ( (AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_RIGHT == bb) ^ under_ref )
+ *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+ }
+
+ blue->flags = 0;
+ if ( AF_CJK_BLUE_TOP == bb )
+ blue->flags |= AF_CJK_BLUE_IS_TOP;
+ else if ( AF_CJK_BLUE_RIGHT == bb )
+ blue->flags |= AF_CJK_BLUE_IS_RIGHT;
+
+ FT_TRACE5(( "-- cjk %s bluezone ref = %ld shoot = %ld\n",
+ cjk_blue_name[bb], *blue_ref, *blue_shoot ));
+ }
+
+ return;
+ }
+
+
+ /* Basically the Latin version with type AF_CJKMetrics for metrics. */
+ FT_LOCAL_DEF( void )
+ af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
+ FT_Face face )
+ {
+ FT_UInt i;
+ FT_Bool started = 0, same_width = 1;
+ FT_Fixed advance, old_advance = 0;
+
+
+ /* check whether all ASCII digits have the same advance width; */
+ /* digit `0' is 0x30 in all supported charmaps */
+ for ( i = 0x30; i <= 0x39; i++ )
+ {
+ FT_UInt glyph_index;
+
+
+ glyph_index = FT_Get_Char_Index( face, i );
+ if ( glyph_index == 0 )
+ continue;
+
+ if ( FT_Get_Advance( face, glyph_index,
+ FT_LOAD_NO_SCALE |
+ FT_LOAD_NO_HINTING |
+ FT_LOAD_IGNORE_TRANSFORM,
+ &advance ) )
+ continue;
+
+ if ( started )
+ {
+ if ( advance != old_advance )
+ {
+ same_width = 0;
+ break;
+ }
+ }
+ else
+ {
+ old_advance = advance;
+ started = 1;
+ }
+ }
+
+ metrics->root.digits_have_same_width = same_width;
+ }
+
+
FT_LOCAL_DEF( FT_Error )
- af_cjk_metrics_init( AF_LatinMetrics metrics,
- FT_Face face )
+ af_cjk_metrics_init( AF_CJKMetrics metrics,
+ FT_Face face )
{
FT_CharMap oldmap = face->charmap;
metrics->units_per_em = face->units_per_EM;
- /* TODO are there blues? */
-
if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
face->charmap = NULL;
else
{
- /* latin's version would suffice */
- af_latin_metrics_init_widths( metrics, face, 0x7530 );
- af_latin_metrics_check_digits( metrics, face );
+ af_cjk_metrics_init_widths( metrics, face, 0x7530 );
+ af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars );
+ af_cjk_metrics_check_digits( metrics, face );
}
FT_Set_Charmap( face, oldmap );
@@ -72,31 +568,100 @@
static void
- af_cjk_metrics_scale_dim( AF_LatinMetrics metrics,
- AF_Scaler scaler,
- AF_Dimension dim )
+ af_cjk_metrics_scale_dim( AF_CJKMetrics metrics,
+ AF_Scaler scaler,
+ AF_Dimension dim )
{
- AF_LatinAxis axis;
+ FT_Fixed scale;
+ FT_Pos delta;
+ AF_CJKAxis axis;
+ FT_UInt nn;
axis = &metrics->axis[dim];
if ( dim == AF_DIMENSION_HORZ )
{
- axis->scale = scaler->x_scale;
- axis->delta = scaler->x_delta;
+ scale = scaler->x_scale;
+ delta = scaler->x_delta;
}
else
{
- axis->scale = scaler->y_scale;
- axis->delta = scaler->y_delta;
+ scale = scaler->y_scale;
+ delta = scaler->y_delta;
+ }
+
+ if ( axis->org_scale == scale && axis->org_delta == delta )
+ return;
+
+ axis->org_scale = scale;
+ axis->org_delta = delta;
+
+ axis->scale = scale;
+ axis->delta = delta;
+
+ /* scale the blue zones */
+ for ( nn = 0; nn < axis->blue_count; nn++ )
+ {
+ AF_CJKBlue blue = &axis->blues[nn];
+ FT_Pos dist;
+
+
+ blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
+ blue->ref.fit = blue->ref.cur;
+ blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
+ blue->shoot.fit = blue->shoot.cur;
+ blue->flags &= ~AF_CJK_BLUE_ACTIVE;
+
+ /* a blue zone is only active if it is less than 3/4 pixels tall */
+ dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
+ if ( dist <= 48 && dist >= -48 )
+ {
+ FT_Pos delta1, delta2;
+
+
+ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
+
+ /* shoot is under shoot for cjk */
+ delta1 = FT_DivFix( blue->ref.fit, scale ) - blue->shoot.org;
+ delta2 = delta1;
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ delta2 = FT_MulFix( delta2, scale );
+
+ FT_TRACE5(( "delta: %d", delta1 ));
+ if ( delta2 < 32 )
+ delta2 = 0;
+#if 0
+ else if ( delta2 < 64 )
+ delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
+#endif
+ else
+ delta2 = FT_PIX_ROUND( delta2 );
+ FT_TRACE5(( "/%d\n", delta2 ));
+
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ blue->shoot.fit = blue->ref.fit - delta2;
+
+ FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]: "
+ "ref: cur=%.2f fit=%.2f shoot: cur=%.2f fit=%.2f\n",
+ ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
+ nn, blue->ref.org, blue->shoot.org,
+ blue->ref.cur / 64.0, blue->ref.fit / 64.0,
+ blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
+
+ blue->flags |= AF_CJK_BLUE_ACTIVE;
+ }
}
}
FT_LOCAL_DEF( void )
- af_cjk_metrics_scale( AF_LatinMetrics metrics,
- AF_Scaler scaler )
+ af_cjk_metrics_scale( AF_CJKMetrics metrics,
+ AF_Scaler scaler )
{
metrics->root.scaler = *scaler;
@@ -329,7 +894,7 @@
AF_AxisHints axis = &hints->axis[dim];
FT_Error error = AF_Err_Ok;
FT_Memory memory = hints->memory;
- AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
+ AF_CJKAxis laxis = &((AF_CJKMetrics)hints->metrics)->axis[dim];
AF_Segment segments = axis->segments;
AF_Segment segment_limit = segments + axis->num_segments;
@@ -601,9 +1166,96 @@
}
+ FT_LOCAL_DEF( void )
+ af_cjk_hints_compute_blue_edges( AF_GlyphHints hints,
+ AF_CJKMetrics metrics,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Edge edge = axis->edges;
+ AF_Edge edge_limit = edge + axis->num_edges;
+ AF_CJKAxis cjk = &metrics->axis[dim];
+ FT_Fixed scale = cjk->scale;
+ FT_Pos best_dist0; /* initial threshold */
+
+
+ /* compute the initial threshold as a fraction of the EM size */
+ best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
+
+ if ( best_dist0 > 64 / 2 ) /* maximum 1/2 pixel */
+ best_dist0 = 64 / 2;
+
+ /* compute which blue zones are active, i.e. have their scaled */
+ /* size < 3/4 pixels */
+
+ /* If the distant between an edge and a blue zone is shorter than */
+ /* best_dist0, set the blue zone for the edge. Then search for */
+ /* the blue zone with the smallest best_dist to the edge. */
+
+ for ( ; edge < edge_limit; edge++ )
+ {
+ FT_UInt bb;
+ AF_Width best_blue = NULL;
+ FT_Pos best_dist = best_dist0;
+
+
+ for ( bb = 0; bb < cjk->blue_count; bb++ )
+ {
+ AF_CJKBlue blue = cjk->blues + bb;
+ FT_Bool is_top_right_blue, is_major_dir;
+
+
+ /* skip inactive blue zones (i.e., those that are too small) */
+ if ( !( blue->flags & AF_CJK_BLUE_ACTIVE ) )
+ continue;
+
+ /* if it is a top zone, check for right edges -- if it is a bottom */
+ /* zone, check for left edges */
+ /* */
+ /* of course, that's for TrueType */
+ is_top_right_blue =
+ FT_BOOL( ( ( blue->flags & AF_CJK_BLUE_IS_TOP ) != 0 ) ||
+ ( ( blue->flags & AF_CJK_BLUE_IS_RIGHT ) != 0 ) );
+ is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
+
+ /* if it is a top zone, the edge must be against the major */
+ /* direction; if it is a bottom zone, it must be in the major */
+ /* direction */
+ if ( is_top_right_blue ^ is_major_dir )
+ {
+ FT_Pos dist;
+ AF_Width compare;
+
+
+ /* Compare the edge to the closest blue zone type */
+ if ( FT_ABS( edge->fpos - blue->ref.org ) >
+ FT_ABS( edge->fpos - blue->shoot.org ) )
+ compare = &blue->shoot;
+ else
+ compare = &blue->ref;
+
+ dist = edge->fpos - compare->org;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = compare;
+ }
+ }
+ }
+
+ if ( best_blue )
+ edge->blue_edge = best_blue;
+ }
+ }
+
+
FT_LOCAL_DEF( FT_Error )
- af_cjk_hints_init( AF_GlyphHints hints,
- AF_LatinMetrics metrics )
+ af_cjk_hints_init( AF_GlyphHints hints,
+ AF_CJKMetrics metrics )
{
FT_Render_Mode mode;
FT_UInt32 scaler_flags, other_flags;
@@ -623,7 +1275,7 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
#endif
@@ -728,11 +1380,11 @@
AF_Edge_Flags base_flags,
AF_Edge_Flags stem_flags )
{
- AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
- AF_LatinAxis axis = & metrics->axis[dim];
- FT_Pos dist = width;
- FT_Int sign = 0;
- FT_Int vertical = ( dim == AF_DIMENSION_VERT );
+ AF_CJKMetrics metrics = (AF_CJKMetrics) hints->metrics;
+ AF_CJKAxis axis = & metrics->axis[dim];
+ FT_Pos dist = width;
+ FT_Int sign = 0;
+ FT_Bool vertical = FT_BOOL( dim == AF_DIMENSION_VERT );
FT_UNUSED( base_flags );
FT_UNUSED( stem_flags );
@@ -1025,7 +1677,61 @@
AF_Edge anchor = 0;
FT_Pos delta = 0;
FT_Int skipped = 0;
+ FT_Bool has_last_stem = FALSE;
+ FT_Pos last_stem_pos = 0;
+
+ /* we begin by aligning all stems relative to the blue zone */
+ FT_TRACE5(( "==== cjk hinting %s edges =====\n",
+ dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
+
+ if ( AF_HINTS_DO_BLUES( hints ) )
+ {
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Width blue;
+ AF_Edge edge1, edge2;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ blue = edge->blue_edge;
+ edge1 = NULL;
+ edge2 = edge->link;
+
+ if ( blue )
+ {
+ edge1 = edge;
+ }
+ else if ( edge2 && edge2->blue_edge )
+ {
+ blue = edge2->blue_edge;
+ edge1 = edge2;
+ edge2 = edge;
+ }
+
+ if ( !edge1 )
+ continue;
+
+ FT_TRACE5(( "CJKBLUE: edge %d @%d (opos=%.2f) snapped to (%.2f), "
+ "was (%.2f)\n",
+ edge1-edges, edge1->fpos, edge1->opos / 64.0, blue->fit / 64.0,
+ edge1->pos / 64.0 ));
+
+ edge1->pos = blue->fit;
+ edge1->flags |= AF_EDGE_DONE;
+
+ if ( edge2 && !edge2->blue_edge )
+ {
+ af_cjk_align_linked_edge( hints, dim, edge1, edge2 );
+ edge2->flags |= AF_EDGE_DONE;
+ }
+
+ if ( !anchor )
+ anchor = edge;
+ }
+ }
/* now we align all stem edges. */
for ( edge = edges; edge < edge_limit; edge++ )
@@ -1044,12 +1750,43 @@
continue;
}
+ /* Some CJK characters have so many stems that
+ * the hinter is likely to merge two adjacent ones.
+ * To solve this problem, if either edge of a stem
+ * is too close to the previous one, we avoid
+ * aligning the two edges, but rather interpolate
+ * their locations at the end of this function in
+ * order to preserve the space between the stems.
+ */
+ if ( has_last_stem &&
+ ( edge->pos < last_stem_pos + 64 ||
+ edge2->pos < last_stem_pos + 64 ) )
+ {
+ skipped++;
+ continue;
+ }
+
/* now align the stem */
+ /* this should not happen, but it's better to be safe */
+ if ( edge2->blue_edge )
+ {
+ FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
+
+ af_cjk_align_linked_edge( hints, dim, edge2, edge );
+ edge->flags |= AF_EDGE_DONE;
+ continue;
+ }
if ( edge2 < edge )
{
af_cjk_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE;
+ /* We rarely reaches here it seems;
+ * usually the two edges belonging
+ * to one stem are marked as DONE together
+ */
+ has_last_stem = TRUE;
+ last_stem_pos = edge->pos;
continue;
}
@@ -1142,6 +1879,8 @@
anchor = edge;
edge->flags |= AF_EDGE_DONE;
edge2->flags |= AF_EDGE_DONE;
+ has_last_stem = TRUE;
+ last_stem_pos = edge2->pos;
}
/* make sure that lowercase m's maintain their symmetry */
@@ -1361,9 +2100,9 @@
FT_LOCAL_DEF( FT_Error )
- af_cjk_hints_apply( AF_GlyphHints hints,
- FT_Outline* outline,
- AF_LatinMetrics metrics )
+ af_cjk_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_CJKMetrics metrics )
{
FT_Error error;
int dim;
@@ -1381,6 +2120,8 @@
error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ );
if ( error )
goto Exit;
+
+ af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_HORZ );
}
if ( AF_HINTS_DO_VERTICAL( hints ) )
@@ -1388,6 +2129,8 @@
error = af_cjk_hints_detect_features( hints, AF_DIMENSION_VERT );
if ( error )
goto Exit;
+
+ af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_VERT );
}
/* grid-fit the outline */
@@ -1397,7 +2140,7 @@
( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
{
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( dim == AF_DIMENSION_HORZ &&
metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL )
{
@@ -1406,11 +2149,13 @@
FT_Pos delta;
- af_warper_compute( &warper, hints, dim, &scale, &delta );
- af_glyph_hints_scale_dim( hints, dim, scale, delta );
+ af_warper_compute( &warper, hints, (AF_Dimension)dim,
+ &scale, &delta );
+ af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
+ scale, delta );
continue;
}
-#endif /* AF_USE_WARPER */
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
af_cjk_hint_edges( hints, (AF_Dimension)dim );
af_cjk_align_edge_points( hints, (AF_Dimension)dim );
@@ -1441,18 +2186,19 @@
/*************************************************************************/
+ /* this corresponds to Unicode 6.0 */
+
static const AF_Script_UniRangeRec af_cjk_uniranges[] =
{
-#if 0
- AF_UNIRANGE_REC( 0x0100UL, 0xFFFFUL ), /* why this? */
-#endif
AF_UNIRANGE_REC( 0x2E80UL, 0x2EFFUL ), /* CJK Radicals Supplement */
AF_UNIRANGE_REC( 0x2F00UL, 0x2FDFUL ), /* Kangxi Radicals */
+ AF_UNIRANGE_REC( 0x2FF0UL, 0x2FFFUL ), /* Ideographic Description Characters */
AF_UNIRANGE_REC( 0x3000UL, 0x303FUL ), /* CJK Symbols and Punctuation */
AF_UNIRANGE_REC( 0x3040UL, 0x309FUL ), /* Hiragana */
AF_UNIRANGE_REC( 0x30A0UL, 0x30FFUL ), /* Katakana */
AF_UNIRANGE_REC( 0x3100UL, 0x312FUL ), /* Bopomofo */
AF_UNIRANGE_REC( 0x3130UL, 0x318FUL ), /* Hangul Compatibility Jamo */
+ AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ), /* Kanbun */
AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended */
AF_UNIRANGE_REC( 0x31C0UL, 0x31EFUL ), /* CJK Strokes */
AF_UNIRANGE_REC( 0x31F0UL, 0x31FFUL ), /* Katakana Phonetic Extensions */
@@ -1461,10 +2207,19 @@
AF_UNIRANGE_REC( 0x3400UL, 0x4DBFUL ), /* CJK Unified Ideographs Extension A */
AF_UNIRANGE_REC( 0x4DC0UL, 0x4DFFUL ), /* Yijing Hexagram Symbols */
AF_UNIRANGE_REC( 0x4E00UL, 0x9FFFUL ), /* CJK Unified Ideographs */
+ AF_UNIRANGE_REC( 0xA960UL, 0xA97FUL ), /* Hangul Jamo Extended-A */
+ AF_UNIRANGE_REC( 0xAC00UL, 0xD7AFUL ), /* Hangul Syllables */
+ AF_UNIRANGE_REC( 0xD7B0UL, 0xD7FFUL ), /* Hangul Jamo Extended-B */
AF_UNIRANGE_REC( 0xF900UL, 0xFAFFUL ), /* CJK Compatibility Ideographs */
+ AF_UNIRANGE_REC( 0xFE10UL, 0xFE1FUL ), /* Vertical forms */
AF_UNIRANGE_REC( 0xFE30UL, 0xFE4FUL ), /* CJK Compatibility Forms */
AF_UNIRANGE_REC( 0xFF00UL, 0xFFEFUL ), /* Halfwidth and Fullwidth Forms */
+ AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ), /* Kana Supplement */
+ AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ), /* Tai Xuan Hing Symbols */
+ AF_UNIRANGE_REC( 0x1F200UL, 0x1F2FFUL ), /* Enclosed Ideographic Supplement */
AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ), /* CJK Unified Ideographs Extension B */
+ AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ), /* CJK Unified Ideographs Extension C */
+ AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ), /* CJK Unified Ideographs Extension D */
AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ), /* CJK Compatibility Ideographs Supplement */
AF_UNIRANGE_REC( 0UL, 0UL )
};
@@ -1474,7 +2229,7 @@
AF_SCRIPT_CJK,
af_cjk_uniranges,
- sizeof( AF_LatinMetricsRec ),
+ sizeof( AF_CJKMetricsRec ),
(AF_Script_InitMetricsFunc) af_cjk_metrics_init,
(AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale,
@@ -1496,7 +2251,7 @@
AF_SCRIPT_CJK,
af_cjk_uniranges,
- sizeof( AF_LatinMetricsRec ),
+ sizeof( AF_CJKMetricsRec ),
(AF_Script_InitMetricsFunc) NULL,
(AF_Script_ScaleMetricsFunc)NULL,
diff --git a/freetype/src/autofit/afcjk.h b/freetype/src/autofit/afcjk.h
index 0b20d4ae3..8416c0d02 100644
--- a/freetype/src/autofit/afcjk.h
+++ b/freetype/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for CJK script (specification). */
/* */
-/* Copyright 2006, 2007 by */
+/* Copyright 2006, 2007, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,6 +20,7 @@
#define __AFCJK_H__
#include "afhints.h"
+#include "aflatin.h"
FT_BEGIN_HEADER
@@ -29,23 +30,106 @@ FT_BEGIN_HEADER
AF_DECLARE_SCRIPT_CLASS(af_cjk_script_class)
+ /* CJK (global) metrics management */
+
+ /*
+ * CJK glyphs tend to fill the square. So we have both vertical and
+ * horizontal blue zones. But some glyphs have flat bounding strokes that
+ * leave some space between neighbour glyphs.
+ */
+ enum
+ {
+ AF_CJK_BLUE_TOP,
+ AF_CJK_BLUE_BOTTOM,
+ AF_CJK_BLUE_LEFT,
+ AF_CJK_BLUE_RIGHT,
+
+ AF_CJK_BLUE_MAX
+ };
+
+
+#define AF_CJK_MAX_WIDTHS 16
+#define AF_CJK_MAX_BLUES AF_CJK_BLUE_MAX
+
+
+ enum
+ {
+ AF_CJK_BLUE_ACTIVE = 1 << 0,
+ AF_CJK_BLUE_IS_TOP = 1 << 1,
+ AF_CJK_BLUE_IS_RIGHT = 1 << 2,
+ AF_CJK_BLUE_ADJUSTMENT = 1 << 3, /* used for scale adjustment */
+ /* optimization */
+ AF_CJK_BLUE_FLAG_MAX
+ };
+
+
+ typedef struct AF_CJKBlueRec_
+ {
+ AF_WidthRec ref;
+ AF_WidthRec shoot; /* undershoot */
+ FT_UInt flags;
+
+ } AF_CJKBlueRec, *AF_CJKBlue;
+
+
+ typedef struct AF_CJKAxisRec_
+ {
+ FT_Fixed scale;
+ FT_Pos delta;
+
+ FT_UInt width_count;
+ AF_WidthRec widths[AF_CJK_MAX_WIDTHS];
+ FT_Pos edge_distance_threshold;
+ FT_Pos standard_width;
+ FT_Bool extra_light;
+
+ /* used for horizontal metrics too for CJK */
+ FT_Bool control_overshoot;
+ FT_UInt blue_count;
+ AF_CJKBlueRec blues[AF_CJK_BLUE_MAX];
+
+ FT_Fixed org_scale;
+ FT_Pos org_delta;
+
+ } AF_CJKAxisRec, *AF_CJKAxis;
+
+
+ typedef struct AF_CJKMetricsRec_
+ {
+ AF_ScriptMetricsRec root;
+ FT_UInt units_per_em;
+ AF_CJKAxisRec axis[AF_DIMENSION_MAX];
+
+ } AF_CJKMetricsRec, *AF_CJKMetrics;
+
FT_LOCAL( FT_Error )
- af_cjk_metrics_init( AF_LatinMetrics metrics,
- FT_Face face );
+ af_cjk_metrics_init( AF_CJKMetrics metrics,
+ FT_Face face );
FT_LOCAL( void )
- af_cjk_metrics_scale( AF_LatinMetrics metrics,
- AF_Scaler scaler );
+ af_cjk_metrics_scale( AF_CJKMetrics metrics,
+ AF_Scaler scaler );
FT_LOCAL( FT_Error )
- af_cjk_hints_init( AF_GlyphHints hints,
- AF_LatinMetrics metrics );
+ af_cjk_hints_init( AF_GlyphHints hints,
+ AF_CJKMetrics metrics );
FT_LOCAL( FT_Error )
- af_cjk_hints_apply( AF_GlyphHints hints,
- FT_Outline* outline,
- AF_LatinMetrics metrics );
+ af_cjk_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_CJKMetrics metrics );
+
+ /* Shared. called from afindic.c */
+ FT_LOCAL( void )
+ af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
+ FT_Face face );
+
+ FT_LOCAL( void )
+ af_cjk_metrics_init_widths( AF_CJKMetrics metrics,
+ FT_Face face,
+ FT_ULong charcode );
+
/* */
diff --git a/freetype/src/autofit/afdummy.c b/freetype/src/autofit/afdummy.c
index 42b2fcb21..c71265131 100644
--- a/freetype/src/autofit/afdummy.c
+++ b/freetype/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
/* Auto-fitter dummy routines to be used if no hinting should be */
/* performed (body). */
/* */
-/* Copyright 2003, 2004, 2005 by */
+/* Copyright 2003-2005, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,6 +19,7 @@
#include "afdummy.h"
#include "afhints.h"
+#include "aferrors.h"
static FT_Error
@@ -27,7 +28,7 @@
{
af_glyph_hints_rescale( hints,
metrics );
- return 0;
+ return AF_Err_Ok;
}
@@ -38,11 +39,11 @@
FT_UNUSED( hints );
FT_UNUSED( outline );
- return 0;
+ return AF_Err_Ok;
}
- AF_DEFINE_SCRIPT_CLASS(af_dummy_script_class,
+ AF_DEFINE_SCRIPT_CLASS( af_dummy_script_class,
AF_SCRIPT_NONE,
NULL,
diff --git a/freetype/src/autofit/afdummy.h b/freetype/src/autofit/afdummy.h
index b69ef437f..95d8f8cf1 100644
--- a/freetype/src/autofit/afdummy.h
+++ b/freetype/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
/* Auto-fitter dummy routines to be used if no hinting should be */
/* performed (specification). */
/* */
-/* Copyright 2003, 2004, 2005 by */
+/* Copyright 2003-2005, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -29,7 +29,7 @@ FT_BEGIN_HEADER
* be performed. This is the default for non-latin glyphs!
*/
- AF_DECLARE_SCRIPT_CLASS(af_dummy_script_class)
+ AF_DECLARE_SCRIPT_CLASS( af_dummy_script_class )
/* */
diff --git a/freetype/src/autofit/afglobal.c b/freetype/src/autofit/afglobal.c
index 178c884cd..3c5f02ec6 100644
--- a/freetype/src/autofit/afglobal.c
+++ b/freetype/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, 2010 by */
+/* Copyright 2003-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -31,8 +31,8 @@
#ifndef FT_CONFIG_OPTION_PIC
-/* when updating this table, don't forget to update
- AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
+ /* when updating this table, don't forget to update */
+ /* AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
/* populate this list when you add new scripts */
static AF_ScriptClass const af_script_classes[] =
@@ -47,7 +47,7 @@
NULL /* do not remove */
};
-#endif /* FT_CONFIG_OPTION_PIC */
+#endif /* !FT_CONFIG_OPTION_PIC */
/* index of default script in `af_script_classes' */
#define AF_SCRIPT_LIST_DEFAULT 2
@@ -85,7 +85,7 @@
FT_UInt ss, i;
- /* the value 255 means `uncovered glyph' */
+ /* the value AF_SCRIPT_LIST_NONE means `uncovered glyph' */
FT_MEM_SET( globals->glyph_scripts,
AF_SCRIPT_LIST_NONE,
globals->glyph_count );
@@ -126,9 +126,7 @@
if ( gindex != 0 &&
gindex < (FT_ULong)globals->glyph_count &&
gscripts[gindex] == AF_SCRIPT_LIST_NONE )
- {
gscripts[gindex] = (FT_Byte)ss;
- }
for (;;)
{
@@ -139,9 +137,7 @@
if ( gindex < (FT_ULong)globals->glyph_count &&
gscripts[gindex] == AF_SCRIPT_LIST_NONE )
- {
gscripts[gindex] = (FT_Byte)ss;
- }
}
}
}
diff --git a/freetype/src/autofit/afglobal.h b/freetype/src/autofit/afglobal.h
index 2a68e1960..cc6860b26 100644
--- a/freetype/src/autofit/afglobal.h
+++ b/freetype/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
/* Auto-fitter routines to compute global hinting values */
/* (specification). */
/* */
-/* Copyright 2003, 2004, 2005, 2007, 2009 by */
+/* Copyright 2003-2005, 2007, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,8 +17,8 @@
/***************************************************************************/
-#ifndef __AF_GLOBAL_H__
-#define __AF_GLOBAL_H__
+#ifndef __AFGLOBAL_H__
+#define __AFGLOBAL_H__
#include "aftypes.h"
@@ -65,7 +65,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __AF_GLOBALS_H__ */
+#endif /* __AFGLOBAL_H__ */
/* END */
diff --git a/freetype/src/autofit/afhints.c b/freetype/src/autofit/afhints.c
index f899af0f4..25864c52f 100644
--- a/freetype/src/autofit/afhints.c
+++ b/freetype/src/autofit/afhints.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/* Copyright 2003-2007, 2009-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -21,6 +21,8 @@
#include <freetype/internal/ftcalc.h>
+ /* Get new segment for given axis. */
+
FT_LOCAL_DEF( FT_Error )
af_axis_hints_new_segment( AF_AxisHints axis,
FT_Memory memory,
@@ -61,6 +63,8 @@
}
+ /* Get new edge for given axis, direction, and position. */
+
FT_LOCAL( FT_Error )
af_axis_hints_new_edge( AF_AxisHints axis,
FT_Int fpos,
@@ -125,7 +129,7 @@
}
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
#include FT_CONFIG_STANDARD_LIBRARY_H
@@ -160,6 +164,9 @@
#define AF_INDEX_NUM( ptr, base ) ( (ptr) ? ( (ptr) - (base) ) : -1 )
+#ifdef __cplusplus
+ extern "C" {
+#endif
void
af_glyph_hints_dump_points( AF_GlyphHints hints )
{
@@ -169,20 +176,20 @@
printf( "Table of points:\n" );
- printf( " [ index | xorg | yorg | xscale | yscale "
- "| xfit | yfit | flags ]\n" );
+ printf( " [ index | xorg | yorg | xscale | yscale"
+ " | xfit | yfit | flags ]\n" );
for ( point = points; point < limit; point++ )
{
- printf( " [ %5d | %5d | %5d | %-5.2f | %-5.2f "
- "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
+ printf( " [ %5d | %5d | %5d | %6.2f | %6.2f"
+ " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
point - points,
point->fx,
point->fy,
- point->ox/64.0,
- point->oy/64.0,
- point->x/64.0,
- point->y/64.0,
+ point->ox / 64.0,
+ point->oy / 64.0,
+ point->x / 64.0,
+ point->y / 64.0,
( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
( point->flags & AF_FLAG_INFLECTION ) ? 'i' : ' ',
( point->flags & AF_FLAG_EXTREMA_X ) ? '<' : ' ',
@@ -192,6 +199,9 @@
}
printf( "\n" );
}
+#ifdef __cplusplus
+ }
+#endif
static const char*
@@ -222,7 +232,11 @@
}
- /* A function to dump the array of linked segments. */
+ /* Dump the array of linked segments. */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
void
af_glyph_hints_dump_segments( AF_GlyphHints hints )
{
@@ -240,11 +254,11 @@
printf ( "Table of %s segments:\n",
dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link | serif |"
- " height | extra | flags ]\n" );
+ " height | extra | flags ]\n" );
for ( seg = segments; seg < limit; seg++ )
{
- printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
+ printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %6d | %5d | %11s ]\n",
seg - segments,
dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
: (int)seg->first->oy / 64.0,
@@ -253,13 +267,84 @@
AF_INDEX_NUM( seg->serif, segments ),
seg->height,
seg->height - ( seg->max_coord - seg->min_coord ),
- af_edge_flags_to_string( seg->flags ) );
+ af_edge_flags_to_string( (AF_Edge_Flags)seg->flags ) );
}
printf( "\n" );
}
}
+#ifdef __cplusplus
+ }
+#endif
+
+
+ /* Fetch number of segments. */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+ FT_Error
+ af_glyph_hints_get_num_segments( AF_GlyphHints hints,
+ FT_Int dimension,
+ FT_Int* num_segments )
+ {
+ AF_Dimension dim;
+ AF_AxisHints axis;
+
+
+ dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
+
+ axis = &hints->axis[dim];
+ *num_segments = axis->num_segments;
+
+ return AF_Err_Ok;
+ }
+#ifdef __cplusplus
+ }
+#endif
+
+
+ /* Fetch offset of segments into user supplied offset array. */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+ FT_Error
+ af_glyph_hints_get_segment_offset( AF_GlyphHints hints,
+ FT_Int dimension,
+ FT_Int idx,
+ FT_Pos* offset )
+ {
+ AF_Dimension dim;
+ AF_AxisHints axis;
+ AF_Segment seg;
+
+
+ if ( !offset )
+ return AF_Err_Invalid_Argument;
+
+ dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
+
+ axis = &hints->axis[dim];
+
+ if ( idx < 0 || idx >= axis->num_segments )
+ return AF_Err_Invalid_Argument;
+
+ seg = &axis->segments[idx];
+ *offset = (dim == AF_DIMENSION_HORZ) ? seg->first->ox
+ : seg->first->oy;
+
+ return AF_Err_Ok;
+ }
+#ifdef __cplusplus
+ }
+#endif
+
+ /* Dump the array of linked edges. */
+#ifdef __cplusplus
+ extern "C" {
+#endif
void
af_glyph_hints_dump_edges( AF_GlyphHints hints )
{
@@ -276,17 +361,17 @@
/*
* note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
- * since they have constant a X coordinate.
+ * since they have a constant X coordinate.
*/
printf ( "Table of %s edges:\n",
dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
printf ( " [ index | pos | dir | link |"
- " serif | blue | opos | pos | flags ]\n" );
+ " serif | blue | opos | pos | flags ]\n" );
for ( edge = edges; edge < limit; edge++ )
{
printf ( " [ %5d | %5.2g | %5s | %4d |"
- " %5d | %c | %5.2f | %5.2f | %s ]\n",
+ " %5d | %c | %5.2f | %5.2f | %11s ]\n",
edge - edges,
(int)edge->opos / 64.0,
af_dir_str( (AF_Direction)edge->dir ),
@@ -295,16 +380,23 @@
edge->blue_edge ? 'y' : 'n',
edge->opos / 64.0,
edge->pos / 64.0,
- af_edge_flags_to_string( edge->flags ) );
+ af_edge_flags_to_string( (AF_Edge_Flags)edge->flags ) );
}
printf( "\n" );
}
}
+#ifdef __cplusplus
+ }
+#endif
-#else /* !AF_DEBUG */
+#else /* !FT_DEBUG_AUTOFIT */
/* these empty stubs are only used to link the `ftgrid' test program */
- /* when debugging is disabled */
+ /* if debugging is disabled */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
void
af_glyph_hints_dump_points( AF_GlyphHints hints )
@@ -320,16 +412,49 @@
}
+ FT_Error
+ af_glyph_hints_get_num_segments( AF_GlyphHints hints,
+ FT_Int dimension,
+ FT_Int* num_segments )
+ {
+ FT_UNUSED( hints );
+ FT_UNUSED( dimension );
+ FT_UNUSED( num_segments );
+
+ return 0;
+ }
+
+
+ FT_Error
+ af_glyph_hints_get_segment_offset( AF_GlyphHints hints,
+ FT_Int dimension,
+ FT_Int idx,
+ FT_Pos* offset )
+ {
+ FT_UNUSED( hints );
+ FT_UNUSED( dimension );
+ FT_UNUSED( idx );
+ FT_UNUSED( offset );
+
+ return 0;
+ }
+
+
void
af_glyph_hints_dump_edges( AF_GlyphHints hints )
{
FT_UNUSED( hints );
}
-#endif /* !AF_DEBUG */
+#ifdef __cplusplus
+ }
+#endif
+#endif /* !FT_DEBUG_AUTOFIT */
+
+
+ /* Compute the direction value of a given vector. */
- /* compute the direction value of a given vector */
FT_LOCAL_DEF( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy )
@@ -369,6 +494,8 @@
}
}
+ /* return no direction if arm lengths differ too much */
+ /* (value 14 is heuristic) */
ss *= 14;
if ( FT_ABS( ll ) <= FT_ABS( ss ) )
dir = AF_DIR_NONE;
@@ -397,7 +524,7 @@
/*
* note that we don't need to free the segment and edge
- * buffers, since they are really within the hints->points array
+ * buffers since they are really within the hints->points array
*/
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
@@ -408,8 +535,8 @@
axis->max_segments = 0;
FT_FREE( axis->segments );
- axis->num_edges = 0;
- axis->max_edges = 0;
+ axis->num_edges = 0;
+ axis->max_edges = 0;
FT_FREE( axis->edges );
}
@@ -426,6 +553,8 @@
}
+ /* Reset metrics. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_ScriptMetrics metrics )
@@ -435,6 +564,9 @@
}
+ /* Recompute all AF_Point in AF_GlyphHints from the definitions */
+ /* in a source outline. */
+
FT_LOCAL_DEF( FT_Error )
af_glyph_hints_reload( AF_GlyphHints hints,
FT_Outline* outline )
@@ -457,12 +589,12 @@
hints->axis[1].num_segments = 0;
hints->axis[1].num_edges = 0;
- /* first of all, reallocate the contours array when necessary */
+ /* first of all, reallocate the contours array if necessary */
new_max = (FT_UInt)outline->n_contours;
old_max = hints->max_contours;
if ( new_max > old_max )
{
- new_max = ( new_max + 3 ) & ~3;
+ new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
goto Exit;
@@ -479,7 +611,7 @@
old_max = hints->max_points;
if ( new_max > old_max )
{
- new_max = ( new_max + 2 + 7 ) & ~7;
+ new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
goto Exit;
@@ -545,7 +677,7 @@
point->flags = AF_FLAG_CUBIC;
break;
default:
- point->flags = 0;
+ point->flags = AF_FLAG_NONE;
}
point->prev = prev;
@@ -563,7 +695,7 @@
}
}
- /* set-up the contours array */
+ /* set up the contours array */
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
@@ -611,6 +743,8 @@
in_dir = af_direction_compute( out_x, out_y );
point->out_dir = (FT_Char)in_dir;
+ /* check for weak points */
+
if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
{
Is_Weak_Point:
@@ -639,6 +773,8 @@
}
+ /* Store the hinted outline in an FT_Outline structure. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_save( AF_GlyphHints hints,
FT_Outline* outline )
@@ -671,6 +807,9 @@
****************************************************************/
+ /* Align all points of an edge to the same coordinate value, */
+ /* either horizontally or vertically. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_align_edge_points( AF_GlyphHints hints,
AF_Dimension dim )
@@ -704,7 +843,6 @@
break;
point = point->next;
-
}
}
}
@@ -744,8 +882,8 @@
****************************************************************/
- /* hint the strong points -- this is equivalent to the TrueType `IP' */
- /* hinting instruction */
+ /* Hint the strong points -- this is equivalent to the TrueType `IP' */
+ /* hinting instruction. */
FT_LOCAL_DEF( void )
af_glyph_hints_align_strong_points( AF_GlyphHints hints,
@@ -827,11 +965,12 @@
max = edge_limit - edges;
#if 1
- /* for small edge counts, a linear search is better */
+ /* for a small number of edges, a linear search is better */
if ( max <= 8 )
{
FT_PtrDist nn;
+
for ( nn = 0; nn < max; nn++ )
if ( edges[nn].fpos >= u )
break;
@@ -863,6 +1002,7 @@
}
}
+ /* point is not on an edge */
{
AF_Edge before = edges + min - 1;
AF_Edge after = edges + min + 0;
@@ -898,6 +1038,10 @@
****************************************************************/
+ /* Shift the original coordinates of all points between `p1' and */
+ /* `p2' to get hinted coordinates, using the same difference as */
+ /* given by `ref'. */
+
static void
af_iup_shift( AF_Point p1,
AF_Point p2,
@@ -906,6 +1050,7 @@
AF_Point p;
FT_Pos delta = ref->u - ref->v;
+
if ( delta == 0 )
return;
@@ -917,6 +1062,13 @@
}
+ /* Interpolate the original coordinates of all points between `p1' and */
+ /* `p2' to get hinted coordinates, using `ref1' and `ref2' as the */
+ /* reference points. The `u' and `v' members are the current and */
+ /* original coordinate values, respectively. */
+ /* */
+ /* Details can be found in the TrueType bytecode specification. */
+
static void
af_iup_interp( AF_Point p1,
AF_Point p2,
@@ -985,6 +1137,9 @@
}
+ /* Hint the weak points -- this is equivalent to the TrueType `IUP' */
+ /* hinting instruction. */
+
FT_LOCAL_DEF( void )
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim )
@@ -1050,17 +1205,18 @@
for (;;)
{
- FT_ASSERT( point <= end_point &&
+ FT_ASSERT( point <= end_point &&
( point->flags & touch_flag ) != 0 );
- /* skip any touched neighbhours */
- while ( point < end_point && ( point[1].flags & touch_flag ) != 0 )
+ /* skip any touched neighbours */
+ while ( point < end_point &&
+ ( point[1].flags & touch_flag ) != 0 )
point++;
last_touched = point;
/* find the next touched point, if any */
- point ++;
+ point++;
for (;;)
{
if ( point > end_point )
@@ -1080,9 +1236,8 @@
EndContour:
/* special case: only one point was touched */
if ( last_touched == first_touched )
- {
af_iup_shift( first_point, end_point, first_touched );
- }
+
else /* interpolate the last part */
{
if ( last_touched < end_point )
@@ -1112,7 +1267,9 @@
}
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+
+ /* Apply (small) warp scale and warp delta for given dimension. */
FT_LOCAL_DEF( void )
af_glyph_hints_scale_dim( AF_GlyphHints hints,
@@ -1137,6 +1294,6 @@
}
}
-#endif /* AF_USE_WARPER */
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
/* END */
diff --git a/freetype/src/autofit/afhints.h b/freetype/src/autofit/afhints.h
index 10e673b3f..1c52e0de7 100644
--- a/freetype/src/autofit/afhints.h
+++ b/freetype/src/autofit/afhints.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines (specification). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
+/* Copyright 2003-2008, 2010-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -25,10 +25,10 @@
FT_BEGIN_HEADER
- /*
- * The definition of outline glyph hints. These are shared by all
- * script analysis routines (until now).
- */
+ /*
+ * The definition of outline glyph hints. These are shared by all
+ * script analysis routines (until now).
+ */
typedef enum AF_Dimension_
{
@@ -55,6 +55,151 @@ FT_BEGIN_HEADER
} AF_Direction;
+ /*
+ * The following explanations are mostly taken from the article
+ *
+ * Real-Time Grid Fitting of Typographic Outlines
+ *
+ * by David Turner and Werner Lemberg
+ *
+ * http://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
+ *
+ *
+ * Segments
+ *
+ * `af_{cjk,latin,...}_hints_compute_segments' are the functions to
+ * find segments in an outline. A segment is a series of consecutive
+ * points that are approximately aligned along a coordinate axis. The
+ * analysis to do so is specific to a script.
+ *
+ * A segment must have at least two points, except in the case of
+ * `fake' segments that are generated to hint metrics appropriately,
+ * and which consist of a single point.
+ *
+ *
+ * Edges
+ *
+ * As soon as segments are defined, the auto-hinter groups them into
+ * edges. An edge corresponds to a single position on the main
+ * dimension that collects one or more segments (allowing for a small
+ * threshold).
+ *
+ * The auto-hinter first tries to grid fit edges, then to align
+ * segments on the edges unless it detects that they form a serif.
+ *
+ * `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
+ * edges; they are specific to a script.
+ *
+ *
+ * A H
+ * | |
+ * | |
+ * | |
+ * | |
+ * C | | F
+ * +------<-----+ +-----<------+
+ * | B G |
+ * | |
+ * | |
+ * +--------------->------------------+
+ * D E
+ *
+ *
+ * Stems
+ *
+ * Segments need to be `linked' to other ones in order to detect stems.
+ * A stem is made of two segments that face each other in opposite
+ * directions and that are sufficiently close to each other. Using
+ * vocabulary from the TrueType specification, stem segments form a
+ * `black distance'.
+ *
+ * In the above ASCII drawing, the horizontal segments are BC, DE, and
+ * FG; the vertical segments are AB, CD, EF, and GH.
+ *
+ * Each segment has at most one `best' candidate to form a black
+ * distance, or no candidate at all. Notice that two distinct segments
+ * can have the same candidate, which frequently means a serif.
+ *
+ * A stem is recognized by the following condition:
+ *
+ * best segment_1 = segment_2 && best segment_2 = segment_1
+ *
+ * The best candidate is stored in field `link' in structure
+ * `AF_Segment'.
+ *
+ * Stems are detected by `af_{cjk,latin,...}_hint_edges'.
+ *
+ * In the above ASCII drawing, the best candidate for both AB and CD is
+ * GH, while the best candidate for GH is AB. Similarly, the best
+ * candidate for EF and GH is AB, while the best candidate for AB is
+ * GH.
+ *
+ *
+ * Serifs
+ *
+ * On the opposite, a serif has
+ *
+ * best segment_1 = segment_2 && best segment_2 != segment_1
+ *
+ * where segment_1 corresponds to the serif segment (CD and EF in the
+ * above ASCII drawing).
+ *
+ * The best candidate is stored in field `serif' in structure
+ * `AF_Segment' (and `link' is set to NULL).
+ *
+ * Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
+ *
+ *
+ * Touched points
+ *
+ * A point is called `touched' if it has been processed somehow by the
+ * auto-hinter. It basically means that it shouldn't be moved again
+ * (or moved only under certain constraints to preserve the already
+ * applied processing).
+ *
+ *
+ * Flat and round segments
+ *
+ * Segments are `round' or `flat', depending on the series of points
+ * that define them. A segment is round if the next and previous point
+ * of an extremum (which can be either a single point or sequence of
+ * points) are both conic or cubic control points. Otherwise, a
+ * segment with an extremum is flat.
+ *
+ *
+ * Strong Points
+ *
+ * Experience has shown that points which are not part of an edge need
+ * to be interpolated linearly between their two closest edges, even if
+ * these are not part of the contour of those particular points.
+ * Typical candidates for this are
+ *
+ * - angle points (i.e., points where the `in' and `out' direction
+ * differ greatly)
+ *
+ * - inflection points (i.e., where the `in' and `out' angles are the
+ * same, but the curvature changes sign)
+ *
+ * `af_glyph_hints_align_strong_points' is the function which takes
+ * care of such situations; it is equivalent to the TrueType `IP'
+ * hinting instruction.
+ *
+ *
+ * Weak Points
+ *
+ * Other points in the outline must be interpolated using the
+ * coordinates of their previous and next unfitted contour neighbours.
+ * These are called `weak points' and are touched by the function
+ * `af_glyph_hints_align_weak_points', equivalent to the TrueType `IUP'
+ * hinting instruction. Typical candidates are control points and
+ * points on the contour without a major direction.
+ *
+ * The major effect is to reduce possible distortion caused by
+ * alignment of edges and strong points, thus weak points are processed
+ * after strong points.
+ */
+
+
/* point hint flags */
typedef enum AF_Flags_
{
@@ -137,9 +282,8 @@ FT_BEGIN_HEADER
FT_Pos score; /* used during stem matching */
FT_Pos len; /* used during stem matching */
- AF_Point first; /* first point in edge segment */
- AF_Point last; /* last point in edge segment */
- AF_Point* contour; /* ptr to first point of segment's contour */
+ AF_Point first; /* first point in edge segment */
+ AF_Point last; /* last point in edge segment */
} AF_SegmentRec;
@@ -155,32 +299,31 @@ FT_BEGIN_HEADER
FT_Fixed scale; /* used to speed up interpolation between edges */
AF_Width blue_edge; /* non-NULL if this is a blue edge */
- AF_Edge link;
- AF_Edge serif;
- FT_Short num_linked;
-
- FT_Int score;
+ AF_Edge link; /* link edge */
+ AF_Edge serif; /* primary edge for serifs */
+ FT_Short num_linked; /* number of linked edges */
+ FT_Int score; /* used during stem matching */
- AF_Segment first;
- AF_Segment last;
+ AF_Segment first; /* first segment in edge */
+ AF_Segment last; /* last segment in edge */
} AF_EdgeRec;
typedef struct AF_AxisHintsRec_
{
- FT_Int num_segments;
- FT_Int max_segments;
- AF_Segment segments;
+ FT_Int num_segments; /* number of used segments */
+ FT_Int max_segments; /* number of allocated segments */
+ AF_Segment segments; /* segments array */
#ifdef AF_SORT_SEGMENTS
FT_Int mid_segments;
#endif
- FT_Int num_edges;
- FT_Int max_edges;
- AF_Edge edges;
+ FT_Int num_edges; /* number of used edges */
+ FT_Int max_edges; /* number of allocated edges */
+ AF_Edge edges; /* edges array */
- AF_Direction major_dir;
+ AF_Direction major_dir; /* either vertical or horizontal */
} AF_AxisHintsRec, *AF_AxisHints;
@@ -195,15 +338,13 @@ FT_BEGIN_HEADER
FT_Fixed y_scale;
FT_Pos y_delta;
- FT_Pos edge_distance_threshold;
+ FT_Int max_points; /* number of allocated points */
+ FT_Int num_points; /* number of used points */
+ AF_Point points; /* points array */
- FT_Int max_points;
- FT_Int num_points;
- AF_Point points;
-
- FT_Int max_contours;
- FT_Int num_contours;
- AF_Point* contours;
+ FT_Int max_contours; /* number of allocated contours */
+ FT_Int num_contours; /* number of used contours */
+ AF_Point* contours; /* contours array */
AF_AxisHintsRec axis[AF_DIMENSION_MAX];
@@ -214,7 +355,7 @@ FT_BEGIN_HEADER
FT_Pos xmin_delta; /* used for warping */
FT_Pos xmax_delta;
-
+
} AF_GlyphHintsRec;
@@ -222,7 +363,7 @@ FT_BEGIN_HEADER
#define AF_HINTS_TEST_OTHER( h, f ) ( (h)->other_flags & (f) )
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
#define AF_HINTS_DO_HORIZONTAL( h ) \
( !_af_debug_disable_horz_hints && \
@@ -237,7 +378,7 @@ FT_BEGIN_HEADER
#define AF_HINTS_DO_BLUES( h ) ( !_af_debug_disable_blue_hints )
-#else /* !AF_DEBUG */
+#else /* !FT_DEBUG_AUTOFIT */
#define AF_HINTS_DO_HORIZONTAL( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL )
@@ -250,7 +391,7 @@ FT_BEGIN_HEADER
#define AF_HINTS_DO_BLUES( h ) 1
-#endif /* !AF_DEBUG */
+#endif /* !FT_DEBUG_AUTOFIT */
FT_LOCAL( AF_Direction )
@@ -274,12 +415,6 @@ FT_BEGIN_HEADER
af_glyph_hints_init( AF_GlyphHints hints,
FT_Memory memory );
-
-
- /*
- * recompute all AF_Point in a AF_GlyphHints from the definitions
- * in a source outline
- */
FT_LOCAL( void )
af_glyph_hints_rescale( AF_GlyphHints hints,
AF_ScriptMetrics metrics );
@@ -304,7 +439,7 @@ FT_BEGIN_HEADER
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim );
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
FT_LOCAL( void )
af_glyph_hints_scale_dim( AF_GlyphHints hints,
AF_Dimension dim,
diff --git a/freetype/src/autofit/afindic.c b/freetype/src/autofit/afindic.c
index 1d9e9eafb..c232cff78 100644
--- a/freetype/src/autofit/afindic.c
+++ b/freetype/src/autofit/afindic.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for Indic scripts (body). */
/* */
-/* Copyright 2007 by */
+/* Copyright 2007, 2011 by */
/* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -27,23 +27,42 @@
#include "afcjk.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
static FT_Error
- af_indic_metrics_init( AF_LatinMetrics metrics,
- FT_Face face )
+ af_indic_metrics_init( AF_CJKMetrics metrics,
+ FT_Face face )
{
- /* use CJK routines */
- return af_cjk_metrics_init( metrics, face );
+ /* skip blue zone init in CJK routines */
+ FT_CharMap oldmap = face->charmap;
+
+
+ metrics->units_per_em = face->units_per_EM;
+
+ if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
+ face->charmap = NULL;
+ else
+ {
+ af_cjk_metrics_init_widths( metrics, face, 0x7530 );
+#if 0
+ /* either need indic specific blue_chars[] or just skip blue zones */
+ af_cjk_metrics_init_blues( metrics, face, af_cjk_blue_chars );
+#endif
+ af_cjk_metrics_check_digits( metrics, face );
+ }
+
+ FT_Set_Charmap( face, oldmap );
+
+ return AF_Err_Ok;
}
static void
- af_indic_metrics_scale( AF_LatinMetrics metrics,
- AF_Scaler scaler )
+ af_indic_metrics_scale( AF_CJKMetrics metrics,
+ AF_Scaler scaler )
{
/* use CJK routines */
af_cjk_metrics_scale( metrics, scaler );
@@ -51,8 +70,8 @@
static FT_Error
- af_indic_hints_init( AF_GlyphHints hints,
- AF_LatinMetrics metrics )
+ af_indic_hints_init( AF_GlyphHints hints,
+ AF_CJKMetrics metrics )
{
/* use CJK routines */
return af_cjk_hints_init( hints, metrics );
@@ -60,9 +79,9 @@
static FT_Error
- af_indic_hints_apply( AF_GlyphHints hints,
- FT_Outline* outline,
- AF_LatinMetrics metrics)
+ af_indic_hints_apply( AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_CJKMetrics metrics )
{
/* use CJK routines */
return af_cjk_hints_apply( hints, outline, metrics );
@@ -84,6 +103,12 @@
AF_UNIRANGE_REC( 0x0100UL, 0xFFFFUL ), /* why this? */
#endif
AF_UNIRANGE_REC( 0x0900UL, 0x0DFFUL), /* Indic Range */
+ AF_UNIRANGE_REC( 0x0F00UL, 0x0FFFUL), /* Tibetan */
+ AF_UNIRANGE_REC( 0x1900UL, 0x194FUL), /* Limbu */
+ AF_UNIRANGE_REC( 0x1B80UL, 0x1BBFUL), /* Sundanese */
+ AF_UNIRANGE_REC( 0x1C80UL, 0x1CDFUL), /* Meetei Mayak */
+ AF_UNIRANGE_REC( 0xA800UL, 0xA82FUL), /* Syloti Nagri */
+ AF_UNIRANGE_REC( 0x11800UL, 0x118DFUL), /* Sharada */
AF_UNIRANGE_REC( 0UL, 0UL)
};
@@ -92,7 +117,7 @@
AF_SCRIPT_INDIC,
af_indic_uniranges,
- sizeof( AF_LatinMetricsRec ),
+ sizeof( AF_CJKMetricsRec ),
(AF_Script_InitMetricsFunc) af_indic_metrics_init,
(AF_Script_ScaleMetricsFunc)af_indic_metrics_scale,
@@ -114,7 +139,7 @@
AF_SCRIPT_INDIC,
af_indic_uniranges,
- sizeof( AF_LatinMetricsRec ),
+ sizeof( AF_CJKMetricsRec ),
(AF_Script_InitMetricsFunc) NULL,
(AF_Script_ScaleMetricsFunc)NULL,
diff --git a/freetype/src/autofit/aflatin.c b/freetype/src/autofit/aflatin.c
index 63491e310..54fcf7f0a 100644
--- a/freetype/src/autofit/aflatin.c
+++ b/freetype/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for latin script (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 2003-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,17 +18,28 @@
#include <ft2build.h>
#include FT_ADVANCES_H
+#include FT_INTERNAL_DEBUG_H
#include "aflatin.h"
#include "aferrors.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
/*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_aflatin
+
+
+ /*************************************************************************/
/*************************************************************************/
/***** *****/
/***** L A T I N G L O B A L M E T R I C S *****/
@@ -36,6 +47,10 @@
/*************************************************************************/
/*************************************************************************/
+
+ /* Find segments and links, compute all stem widths, and initialize */
+ /* standard width and height for the glyph with given charcode. */
+
FT_LOCAL_DEF( void )
af_latin_metrics_init_widths( AF_LatinMetrics metrics,
FT_Face face,
@@ -69,8 +84,12 @@
FT_ZERO( dummy );
dummy->units_per_em = metrics->units_per_em;
- scaler->x_scale = scaler->y_scale = 0x10000L;
- scaler->x_delta = scaler->y_delta = 0;
+
+ scaler->x_scale = 0x10000L;
+ scaler->y_scale = 0x10000L;
+ scaler->x_delta = 0;
+ scaler->y_delta = 0;
+
scaler->face = face;
scaler->render_mode = FT_RENDER_MODE_NORMAL;
scaler->flags = 0;
@@ -115,7 +134,7 @@
dist = -dist;
if ( num_widths < AF_LATIN_MAX_WIDTHS )
- axis->widths[ num_widths++ ].org = dist;
+ axis->widths[num_widths++].org = dist;
}
}
@@ -161,6 +180,9 @@
};
+ /* Find all blue zones. Flat segments give the reference points, */
+ /* round segments the overshoot positions. */
+
static void
af_latin_metrics_init_blues( AF_LatinMetrics metrics,
FT_Face face )
@@ -177,11 +199,11 @@
/* we compute the blues simply by loading each character from the */
- /* 'af_latin_blue_chars[blues]' string, then compute its top-most or */
+ /* `af_latin_blue_chars[blues]' string, then finding its top-most or */
/* bottom-most points (depending on `AF_IS_TOP_BLUE') */
- AF_LOG(( "blue zones computation\n" ));
- AF_LOG(( "------------------------------------------------\n" ));
+ FT_TRACE5(( "blue zones computation\n" ));
+ FT_TRACE5(( "------------------------------------------------\n" ));
for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
{
@@ -191,7 +213,7 @@
FT_Pos* blue_shoot;
- AF_LOG(( "blue %3d: ", bb ));
+ FT_TRACE5(( "blue %3d: ", bb ));
num_flats = 0;
num_rounds = 0;
@@ -199,13 +221,13 @@
for ( ; p < limit && *p; p++ )
{
FT_UInt glyph_index;
- FT_Pos best_y; /* same as points.y */
+ FT_Pos best_y; /* same as points.y */
FT_Int best_point, best_first, best_last;
FT_Vector* points;
FT_Bool round = 0;
- AF_LOG(( "'%c'", *p ));
+ FT_TRACE5(( "'%c'", *p ));
/* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
@@ -229,7 +251,9 @@
FT_Int last = -1;
- for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
+ for ( nn = 0;
+ nn < glyph->outline.n_contours;
+ first = last + 1, nn++ )
{
FT_Int old_best_point = best_point;
FT_Int pp;
@@ -241,7 +265,7 @@
/* In some fonts, they correspond to mark attachment points */
/* which are way outside of the glyph's real outline. */
if ( last <= first )
- continue;
+ continue;
if ( AF_LATIN_IS_TOP_BLUE( bb ) )
{
@@ -268,7 +292,7 @@
best_last = last;
}
}
- AF_LOG(( "%5d", best_y ));
+ FT_TRACE5(( "%5d", best_y ));
}
/* now check whether the point belongs to a straight or round */
@@ -311,12 +335,12 @@
} while ( next != best_point );
- /* now, set the `round' flag depending on the segment's kind */
+ /* now set the `round' flag depending on the segment's kind */
round = FT_BOOL(
FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||
FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );
- AF_LOG(( "%c ", round ? 'r' : 'f' ));
+ FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
}
if ( round )
@@ -325,7 +349,7 @@
flats[num_flats++] = best_y;
}
- AF_LOG(( "\n" ));
+ FT_TRACE5(( "\n" ));
if ( num_flats == 0 && num_rounds == 0 )
{
@@ -333,7 +357,7 @@
* we couldn't find a single glyph to compute this blue zone,
* we will simply ignore it then
*/
- AF_LOG(( "empty\n" ));
+ FT_TRACE5(( "empty\n" ));
continue;
}
@@ -343,9 +367,9 @@
af_sort_pos( num_rounds, rounds );
af_sort_pos( num_flats, flats );
- blue = & axis->blues[axis->blue_count];
- blue_ref = & blue->ref.org;
- blue_shoot = & blue->shoot.org;
+ blue = &axis->blues[axis->blue_count];
+ blue_ref = &blue->ref.org;
+ blue_shoot = &blue->shoot.org;
axis->blue_count++;
@@ -376,7 +400,8 @@
if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
- *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+ *blue_ref =
+ *blue_shoot = ( shoot + ref ) / 2;
}
blue->flags = 0;
@@ -391,13 +416,17 @@
if ( bb == AF_LATIN_BLUE_SMALL_TOP )
blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
- AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+ FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
}
+ FT_TRACE5(( "\n" ));
+
return;
}
+ /* Check whether all ASCII digits have the same advance width. */
+
FT_LOCAL_DEF( void )
af_latin_metrics_check_digits( AF_LatinMetrics metrics,
FT_Face face )
@@ -407,8 +436,7 @@
FT_Fixed advance, old_advance = 0;
- /* check whether all ASCII digits have the same advance width; */
- /* digit `0' is 0x30 in all supported charmaps */
+ /* digit `0' is 0x30 in all supported charmaps */
for ( i = 0x30; i <= 0x39; i++ )
{
FT_UInt glyph_index;
@@ -444,6 +472,8 @@
}
+ /* Initialize global metrics. */
+
FT_LOCAL_DEF( FT_Error )
af_latin_metrics_init( AF_LatinMetrics metrics,
FT_Face face )
@@ -458,6 +488,7 @@
FT_ENCODING_APPLE_ROMAN,
FT_ENCODING_ADOBE_STANDARD,
FT_ENCODING_ADOBE_LATIN_1,
+
FT_ENCODING_NONE /* end of list */
};
@@ -485,6 +516,9 @@
}
+ /* Adjust scaling value, then scale and shift widths */
+ /* and blue zones (if applicable) for given dimension. */
+
static void
af_latin_metrics_scale_dim( AF_LatinMetrics metrics,
AF_Scaler scaler,
@@ -550,9 +584,7 @@
else
#endif
if ( dim == AF_DIMENSION_VERT )
- {
scale = FT_MulDiv( scale, fitted, scaled );
- }
}
}
}
@@ -571,7 +603,7 @@
metrics->root.scaler.y_delta = delta;
}
- /* scale the standard widths */
+ /* scale the widths */
for ( nn = 0; nn < axis->width_count; nn++ )
{
AF_Width width = axis->widths + nn;
@@ -582,7 +614,7 @@
}
/* an extra-light axis corresponds to a standard width that is */
- /* smaller than 0.75 pixels */
+ /* smaller than 5/8 pixels */
axis->extra_light =
(FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
@@ -605,9 +637,17 @@
dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
if ( dist <= 48 && dist >= -48 )
{
- FT_Pos delta1, delta2;
+#if 0
+ FT_Pos delta1;
+#endif
+ FT_Pos delta2;
+
+
+ /* use discrete values for blue zone widths */
+#if 0
+ /* generic, original code */
delta1 = blue->shoot.org - blue->ref.org;
delta2 = delta1;
if ( delta1 < 0 )
@@ -628,6 +668,28 @@
blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
blue->shoot.fit = blue->ref.fit + delta2;
+#else
+
+ /* simplified version due to abs(dist) <= 48 */
+ delta2 = dist;
+ if ( dist < 0 )
+ delta2 = -delta2;
+
+ if ( delta2 < 32 )
+ delta2 = 0;
+ else if ( delta < 48 )
+ delta2 = 32;
+ else
+ delta2 = 64;
+
+ if ( dist < 0 )
+ delta2 = -delta2;
+
+ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
+ blue->shoot.fit = blue->ref.fit - delta2;
+
+#endif
+
blue->flags |= AF_LATIN_BLUE_ACTIVE;
}
}
@@ -635,6 +697,8 @@
}
+ /* Scale global values in both directions. */
+
FT_LOCAL_DEF( void )
af_latin_metrics_scale( AF_LatinMetrics metrics,
AF_Scaler scaler )
@@ -655,18 +719,21 @@
/*************************************************************************/
/*************************************************************************/
+
+ /* Walk over all contours and compute its segments. */
+
FT_LOCAL_DEF( FT_Error )
af_latin_hints_compute_segments( AF_GlyphHints hints,
AF_Dimension dim )
{
- AF_AxisHints axis = &hints->axis[dim];
- FT_Memory memory = hints->memory;
- FT_Error error = AF_Err_Ok;
- AF_Segment segment = NULL;
- AF_SegmentRec seg0;
- AF_Point* contour = hints->contours;
- AF_Point* contour_limit = contour + hints->num_contours;
- AF_Direction major_dir, segment_dir;
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Memory memory = hints->memory;
+ FT_Error error = AF_Err_Ok;
+ AF_Segment segment = NULL;
+ AF_SegmentRec seg0;
+ AF_Point* contour = hints->contours;
+ AF_Point* contour_limit = contour + hints->num_contours;
+ AF_Direction major_dir, segment_dir;
FT_ZERO( &seg0 );
@@ -762,7 +829,7 @@
/* a segment is round if either its first or last point */
/* is a control point */
if ( ( segment->first->flags | point->flags ) &
- AF_FLAG_CONTROL )
+ AF_FLAG_CONTROL )
segment->flags |= AF_EDGE_ROUND;
/* compute segment size */
@@ -808,7 +875,6 @@
min_pos = max_pos = point->u;
segment->first = point;
segment->last = point;
- segment->contour = contour;
on_edge = 1;
}
@@ -874,6 +940,8 @@
}
+ /* Link segments to form stems and serifs. */
+
FT_LOCAL_DEF( void )
af_latin_hints_link_segments( AF_GlyphHints hints,
AF_Dimension dim )
@@ -899,51 +967,56 @@
if ( seg1->dir != axis->major_dir || seg1->first == seg1->last )
continue;
+ /* search for stems having opposite directions, */
+ /* with seg1 to the `left' of seg2 */
for ( seg2 = segments; seg2 < segment_limit; seg2++ )
- if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
- {
- FT_Pos pos1 = seg1->pos;
- FT_Pos pos2 = seg2->pos;
- FT_Pos dist = pos2 - pos1;
+ {
+ FT_Pos pos1 = seg1->pos;
+ FT_Pos pos2 = seg2->pos;
- if ( dist < 0 )
- dist = -dist;
+ if ( seg1->dir + seg2->dir == 0 && pos2 > pos1 )
+ {
+ /* compute distance between the two segments */
+ FT_Pos dist = pos2 - pos1;
+ FT_Pos min = seg1->min_coord;
+ FT_Pos max = seg1->max_coord;
+ FT_Pos len, score;
- {
- FT_Pos min = seg1->min_coord;
- FT_Pos max = seg1->max_coord;
- FT_Pos len, score;
+ if ( min < seg2->min_coord )
+ min = seg2->min_coord;
- if ( min < seg2->min_coord )
- min = seg2->min_coord;
+ if ( max > seg2->max_coord )
+ max = seg2->max_coord;
- if ( max > seg2->max_coord )
- max = seg2->max_coord;
+ /* compute maximum coordinate difference of the two segments */
+ len = max - min;
+ if ( len >= len_threshold )
+ {
+ /* small coordinate differences cause a higher score, and */
+ /* segments with a greater distance cause a higher score also */
+ score = dist + len_score / len;
- len = max - min;
- if ( len >= len_threshold )
+ /* and we search for the smallest score */
+ /* of the sum of the two values */
+ if ( score < seg1->score )
{
- score = dist + len_score / len;
-
- if ( score < seg1->score )
- {
- seg1->score = score;
- seg1->link = seg2;
- }
+ seg1->score = score;
+ seg1->link = seg2;
+ }
- if ( score < seg2->score )
- {
- seg2->score = score;
- seg2->link = seg1;
- }
+ if ( score < seg2->score )
+ {
+ seg2->score = score;
+ seg2->link = seg1;
}
}
}
+ }
}
- /* now, compute the `serif' segments */
+ /* now compute the `serif' segments, cf. explanations in `afhints.h' */
for ( seg1 = segments; seg1 < segment_limit; seg1++ )
{
seg2 = seg1->link;
@@ -960,6 +1033,8 @@
}
+ /* Link segments to edges, using feature analysis for selection. */
+
FT_LOCAL_DEF( FT_Error )
af_latin_hints_compute_edges( AF_GlyphHints hints,
AF_Dimension dim )
@@ -973,7 +1048,9 @@
AF_Segment segment_limit = segments + axis->num_segments;
AF_Segment seg;
+#if 0
AF_Direction up_dir;
+#endif
FT_Fixed scale;
FT_Pos edge_distance_threshold;
FT_Pos segment_length_threshold;
@@ -984,11 +1061,13 @@
scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
: hints->y_scale;
+#if 0
up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
: AF_DIR_RIGHT;
+#endif
/*
- * We ignore all segments that are less than 1 pixels in length,
+ * We ignore all segments that are less than 1 pixel in length
* to avoid many problems with serif fonts. We compute the
* corresponding threshold in font units.
*/
@@ -999,20 +1078,21 @@
/*********************************************************************/
/* */
- /* We will begin by generating a sorted table of edges for the */
- /* current direction. To do so, we simply scan each segment and try */
- /* to find an edge in our table that corresponds to its position. */
+ /* We begin by generating a sorted table of edges for the current */
+ /* direction. To do so, we simply scan each segment and try to find */
+ /* an edge in our table that corresponds to its position. */
/* */
/* If no edge is found, we create and insert a new edge in the */
/* sorted table. Otherwise, we simply add the segment to the edge's */
- /* list which will be processed in the second step to compute the */
+ /* list which gets processed in the second step to compute the */
/* edge's properties. */
/* */
- /* Note that the edges table is sorted along the segment/edge */
+ /* Note that the table of edges is sorted along the segment/edge */
/* position. */
/* */
/*********************************************************************/
+ /* assure that edge distance threshold is at most 0.25px */
edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
scale );
if ( edge_distance_threshold > 64 / 4 )
@@ -1023,7 +1103,7 @@
for ( seg = segments; seg < segment_limit; seg++ )
{
- AF_Edge found = 0;
+ AF_Edge found = NULL;
FT_Int ee;
@@ -1072,9 +1152,10 @@
edge->first = seg;
edge->last = seg;
- edge->fpos = seg->pos;
edge->dir = seg->dir;
- edge->opos = edge->pos = FT_MulFix( seg->pos, scale );
+ edge->fpos = seg->pos;
+ edge->opos = FT_MulFix( seg->pos, scale );
+ edge->pos = edge->opos;
seg->edge_next = seg;
}
else
@@ -1091,9 +1172,9 @@
/*********************************************************************/
/* */
/* Good, we will now compute each edge's properties according to */
- /* segments found on its position. Basically, these are: */
+ /* the segments found on its position. Basically, these are */
/* */
- /* - edge's main direction */
+ /* - the edge's main direction */
/* - stem edge, serif edge or both (which defaults to stem then) */
/* - rounded edge, straight or both (which defaults to straight) */
/* - link for edge */
@@ -1126,13 +1207,15 @@
} while ( seg != edge->first );
}
- /* now, compute each edge properties */
+ /* now compute each edge properties */
for ( edge = edges; edge < edge_limit; edge++ )
{
FT_Int is_round = 0; /* does it contain round segments? */
FT_Int is_straight = 0; /* does it contain straight segments? */
+#if 0
FT_Pos ups = 0; /* number of upwards segments */
FT_Pos downs = 0; /* number of downwards segments */
+#endif
seg = edge->first;
@@ -1148,11 +1231,13 @@
else
is_straight++;
+#if 0
/* check for segment direction */
if ( seg->dir == up_dir )
- ups += seg->max_coord-seg->min_coord;
+ ups += seg->max_coord - seg->min_coord;
else
- downs += seg->max_coord-seg->min_coord;
+ downs += seg->max_coord - seg->min_coord;
+#endif
/* check for links -- if seg->serif is set, then seg->link must */
/* be ignored */
@@ -1228,7 +1313,7 @@
edge->dir = 0; /* both up and down! */
#endif
- /* gets rid of serifs if link is set */
+ /* get rid of serifs if link is set */
/* XXX: This gets rid of many unpleasant artefacts! */
/* Example: the `c' in cour.pfa at size 13 */
@@ -1242,6 +1327,8 @@
}
+ /* Detect segments and edges for given dimension. */
+
FT_LOCAL_DEF( FT_Error )
af_latin_hints_detect_features( AF_GlyphHints hints,
AF_Dimension dim )
@@ -1256,18 +1343,21 @@
error = af_latin_hints_compute_edges( hints, dim );
}
+
return error;
}
+ /* Compute all edges which lie within blue zones. */
+
FT_LOCAL_DEF( void )
af_latin_hints_compute_blue_edges( AF_GlyphHints hints,
AF_LatinMetrics metrics )
{
- AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ];
+ AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT];
AF_Edge edge = axis->edges;
AF_Edge edge_limit = edge + axis->num_edges;
- AF_LatinAxis latin = &metrics->axis[ AF_DIMENSION_VERT ];
+ AF_LatinAxis latin = &metrics->axis[AF_DIMENSION_VERT];
FT_Fixed scale = latin->scale;
@@ -1283,8 +1373,10 @@
/* compute the initial threshold as a fraction of the EM size */
+ /* (the value 40 is heuristic) */
best_dist = FT_MulFix( metrics->units_per_em / 40, scale );
+ /* assure a minimum distance of 0.5px */
if ( best_dist > 64 / 2 )
best_dist = 64 / 2;
@@ -1294,7 +1386,7 @@
FT_Bool is_top_blue, is_major_dir;
- /* skip inactive blue zones (i.e., those that are too small) */
+ /* skip inactive blue zones (i.e., those that are too large) */
if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
continue;
@@ -1322,12 +1414,13 @@
if ( dist < best_dist )
{
best_dist = dist;
- best_blue = & blue->ref;
+ best_blue = &blue->ref;
}
- /* now, compare it to the overshoot position if the edge is */
- /* rounded, and if the edge is over the reference position of a */
- /* top zone, or under the reference position of a bottom zone */
+ /* now compare it to the overshoot position and check whether */
+ /* the edge is rounded, and whether the edge is over the */
+ /* reference position of a top zone, or under the reference */
+ /* position of a bottom zone */
if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
{
FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
@@ -1335,7 +1428,6 @@
if ( is_top_blue ^ is_under_ref )
{
- blue = latin->blues + bb;
dist = edge->fpos - blue->shoot.org;
if ( dist < 0 )
dist = -dist;
@@ -1344,7 +1436,7 @@
if ( dist < best_dist )
{
best_dist = dist;
- best_blue = & blue->shoot;
+ best_blue = &blue->shoot;
}
}
}
@@ -1357,6 +1449,8 @@
}
+ /* Initalize hinting engine. */
+
static FT_Error
af_latin_hints_init( AF_GlyphHints hints,
AF_LatinMetrics metrics )
@@ -1370,7 +1464,7 @@
/*
* correct x_scale and y_scale if needed, since they may have
- * been modified `af_latin_metrics_scale_dim' above
+ * been modified by `af_latin_metrics_scale_dim' above
*/
hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
@@ -1380,7 +1474,7 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
-#if 0 /* #ifdef AF_USE_WARPER */
+#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
{
metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
@@ -1417,14 +1511,14 @@
* In `light' hinting mode we disable horizontal hinting completely.
* We also do it if the face is italic.
*/
- if ( mode == FT_RENDER_MODE_LIGHT ||
- (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )
+ if ( mode == FT_RENDER_MODE_LIGHT ||
+ ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
- return 0;
+ return AF_Err_Ok;
}
@@ -1436,8 +1530,8 @@
/*************************************************************************/
/*************************************************************************/
- /* snap a given width in scaled coordinates to one of the */
- /* current standard widths */
+ /* Snap a given width in scaled coordinates to one of the */
+ /* current standard widths. */
static FT_Pos
af_latin_snap_width( AF_Width widths,
@@ -1484,7 +1578,9 @@
}
- /* compute the snapped width of a given stem */
+ /* Compute the snapped width of a given stem, ignoring very thin ones. */
+ /* There is a lot of voodoo in this function; changing the hard-coded */
+ /* parameters influence the whole hinting process. */
static FT_Pos
af_latin_compute_stem_width( AF_GlyphHints hints,
@@ -1501,7 +1597,7 @@
if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
- axis->extra_light )
+ axis->extra_light )
return width;
if ( dist < 0 )
@@ -1516,11 +1612,12 @@
/* smooth hinting process: very lightly quantize the stem width */
/* leave the widths of serifs alone */
-
- if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
+ if ( ( stem_flags & AF_EDGE_SERIF ) &&
+ vertical &&
+ ( dist < 3 * 64 ) )
goto Done_Width;
- else if ( ( base_flags & AF_EDGE_ROUND ) )
+ else if ( base_flags & AF_EDGE_ROUND )
{
if ( dist < 80 )
dist = 64;
@@ -1572,6 +1669,7 @@
else
{
/* strong hinting process: snap the stem width to integer pixels */
+
FT_Pos org_dist = dist;
@@ -1646,7 +1744,7 @@
}
- /* align one stem edge relative to the previous stem edge */
+ /* Align one stem edge relative to the previous stem edge. */
static void
af_latin_align_linked_edge( AF_GlyphHints hints,
@@ -1664,13 +1762,16 @@
stem_edge->pos = base_edge->pos + fitted_width;
- AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
- "dist was %.2f, now %.2f\n",
- stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
- stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+ FT_TRACE5(( " LINK: edge %d (opos=%.2f) linked to (%.2f),"
+ " dist was %.2f, now %.2f\n",
+ stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
+ stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
}
+ /* Shift the coordinates of the `serif' edge by the same amount */
+ /* as the corresponding `base' edge has been moved already. */
+
static void
af_latin_align_serif_edge( AF_GlyphHints hints,
AF_Edge base,
@@ -1678,7 +1779,7 @@
{
FT_UNUSED( hints );
- serif->pos = base->pos + (serif->opos - base->opos);
+ serif->pos = base->pos + ( serif->opos - base->opos );
}
@@ -1693,6 +1794,8 @@
/*************************************************************************/
+ /* The main grid-fitting routine. */
+
FT_LOCAL_DEF( void )
af_latin_hint_edges( AF_GlyphHints hints,
AF_Dimension dim )
@@ -1702,10 +1805,13 @@
AF_Edge edge_limit = edges + axis->num_edges;
FT_PtrDist n_edges;
AF_Edge edge;
- AF_Edge anchor = 0;
+ AF_Edge anchor = NULL;
FT_Int has_serifs = 0;
+ FT_TRACE5(("%s edge hinting\n", dim == AF_DIMENSION_VERT ? "horizontal"
+ : "vertical"));
+
/* we begin by aligning all stems relative to the blue zone */
/* if needed -- that's only for horizontal edges */
@@ -1714,7 +1820,7 @@
for ( edge = edges; edge < edge_limit; edge++ )
{
AF_Width blue;
- AF_Edge edge1, edge2;
+ AF_Edge edge1, edge2; /* these edges form the stem to check */
if ( edge->flags & AF_EDGE_DONE )
@@ -1725,9 +1831,9 @@
edge2 = edge->link;
if ( blue )
- {
edge1 = edge;
- }
+
+ /* flip edges if the other stem is aligned to a blue zone */
else if ( edge2 && edge2->blue_edge )
{
blue = edge2->blue_edge;
@@ -1738,10 +1844,10 @@
if ( !edge1 )
continue;
- AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
- "was (%.2f)\n",
- edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
- edge1->pos / 64.0 ));
+ FT_TRACE5(( " BLUE: edge %d (opos=%.2f) snapped to (%.2f),"
+ " was (%.2f)\n",
+ edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0,
+ edge1->pos / 64.0 ));
edge1->pos = blue->fit;
edge1->flags |= AF_EDGE_DONE;
@@ -1757,8 +1863,8 @@
}
}
- /* now we will align all stem edges, trying to maintain the */
- /* relative order of stems in the glyph */
+ /* now we align all other stem edges, trying to maintain the */
+ /* relative order of stems in the glyph */
for ( edge = edges; edge < edge_limit; edge++ )
{
AF_Edge edge2;
@@ -1780,7 +1886,7 @@
/* this should not happen, but it's better to be safe */
if ( edge2->blue_edge )
{
- AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
+ FT_TRACE5(( " ASSERTION FAILED for edge %d\n", edge2-edges ));
af_latin_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE;
@@ -1789,6 +1895,8 @@
if ( !anchor )
{
+ /* if we reach this if clause, no stem has been aligned yet */
+
FT_Pos org_len, org_center, cur_len;
FT_Pos cur_pos1, error1, error2, u_off, d_off;
@@ -1798,10 +1906,19 @@
hints, dim, org_len,
(AF_Edge_Flags)edge->flags,
(AF_Edge_Flags)edge2->flags );
+
+ /* some voodoo to specially round edges for small stem widths; */
+ /* the idea is to align the center of a stem, then shifting */
+ /* the stem edges to suitable positions */
if ( cur_len <= 64 )
- u_off = d_off = 32;
+ {
+ /* width <= 1px */
+ u_off = 32;
+ d_off = 32;
+ }
else
{
+ /* 1px < width < 1.5px */
u_off = 38;
d_off = 26;
}
@@ -1809,7 +1926,6 @@
if ( cur_len < 96 )
{
org_center = edge->opos + ( org_len >> 1 );
-
cur_pos1 = FT_PIX_ROUND( org_center );
error1 = org_center - ( cur_pos1 - u_off );
@@ -1831,11 +1947,11 @@
else
edge->pos = FT_PIX_ROUND( edge->opos );
- AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
- "snapped to (%.2f) (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0 ));
+ FT_TRACE5(( " ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
+ " snapped to (%.2f) (%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge2 - edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
anchor = edge;
edge->flags |= AF_EDGE_DONE;
@@ -1853,12 +1969,18 @@
org_center = org_pos + ( org_len >> 1 );
cur_len = af_latin_compute_stem_width(
- hints, dim, org_len,
- (AF_Edge_Flags)edge->flags,
- (AF_Edge_Flags)edge2->flags );
+ hints, dim, org_len,
+ (AF_Edge_Flags)edge->flags,
+ (AF_Edge_Flags)edge2->flags );
if ( edge2->flags & AF_EDGE_DONE )
+ {
+ FT_TRACE5(( " ADJUST: edge %d (pos=%.2f) moved to %.2f\n",
+ edge - edges, edge->pos / 64.0,
+ ( edge2->pos - cur_len ) / 64.0 ));
+
edge->pos = edge2->pos - cur_len;
+ }
else if ( cur_len < 96 )
{
@@ -1868,7 +1990,10 @@
cur_pos1 = FT_PIX_ROUND( org_center );
if (cur_len <= 64 )
- u_off = d_off = 32;
+ {
+ u_off = 32;
+ d_off = 32;
+ }
else
{
u_off = 38;
@@ -1891,11 +2016,11 @@
edge->pos = cur_pos1 - cur_len / 2;
edge2->pos = cur_pos1 + cur_len / 2;
- AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
- "snapped to (%.2f) and (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0 ));
+ FT_TRACE5(( " STEM: %d (opos=%.2f) to %d (opos=%.2f)"
+ " snapped to (%.2f) and (%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge2 - edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
}
else
{
@@ -1908,24 +2033,24 @@
(AF_Edge_Flags)edge->flags,
(AF_Edge_Flags)edge2->flags );
- cur_pos1 = FT_PIX_ROUND( org_pos );
- delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center;
+ cur_pos1 = FT_PIX_ROUND( org_pos );
+ delta1 = cur_pos1 + ( cur_len >> 1 ) - org_center;
if ( delta1 < 0 )
delta1 = -delta1;
- cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
- delta2 = cur_pos2 + ( cur_len >> 1 ) - org_center;
+ cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len;
+ delta2 = cur_pos2 + ( cur_len >> 1 ) - org_center;
if ( delta2 < 0 )
delta2 = -delta2;
edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;
edge2->pos = edge->pos + cur_len;
- AF_LOG(( "STEM: %d (opos=%.2f) to %d (opos=%.2f) "
- "snapped to (%.2f) and (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0 ));
+ FT_TRACE5(( " STEM: %d (opos=%.2f) to %d (opos=%.2f)"
+ " snapped to (%.2f) and (%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge2 - edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
}
edge->flags |= AF_EDGE_DONE;
@@ -1933,8 +2058,8 @@
if ( edge > edges && edge->pos < edge[-1].pos )
{
- AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
- edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+ FT_TRACE5(( " BOUND: %d (pos=%.2f) to (%.2f)\n",
+ edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
edge->pos = edge[-1].pos;
}
}
@@ -2028,18 +2153,19 @@
if ( delta < 64 + 16 )
{
af_latin_align_serif_edge( hints, edge->serif, edge );
- AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
- "aligned to (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge->serif - edges, edge->serif->opos / 64.0,
- edge->pos / 64.0 ));
+ FT_TRACE5(( " SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
+ " aligned to (%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge->serif - edges, edge->serif->opos / 64.0,
+ edge->pos / 64.0 ));
}
else if ( !anchor )
{
- AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
edge->pos = FT_PIX_ROUND( edge->opos );
anchor = edge;
+ FT_TRACE5(( " SERIF_ANCHOR: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
}
else
{
@@ -2064,18 +2190,21 @@
FT_MulDiv( edge->opos - before->opos,
after->pos - before->pos,
after->opos - before->opos );
- AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) "
- "from %d (opos=%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge->pos / 64.0, before - edges,
- before->opos / 64.0 ));
+
+ FT_TRACE5(( " SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
+ " from %d (opos=%.2f)\n",
+ edge - edges, edge->opos / 64.0,
+ edge->pos / 64.0,
+ before - edges, before->opos / 64.0 ));
}
else
{
edge->pos = anchor->pos +
( ( edge->opos - anchor->opos + 16 ) & ~31 );
- AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+
+ FT_TRACE5(( " SERIF_LINK2: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge - edges, edge->opos / 64.0, edge->pos / 64.0 ));
}
}
@@ -2090,9 +2219,13 @@
edge->pos = edge[1].pos;
}
}
+
+ FT_TRACE5(( "\n" ));
}
+ /* Apply the complete hinting algorithm to a latin glyph. */
+
static FT_Error
af_latin_hints_apply( AF_GlyphHints hints,
FT_Outline* outline,
@@ -2107,9 +2240,9 @@
goto Exit;
/* analyze glyph outline */
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
- AF_HINTS_DO_HORIZONTAL( hints ) )
+ AF_HINTS_DO_HORIZONTAL( hints ) )
#else
if ( AF_HINTS_DO_HORIZONTAL( hints ) )
#endif
@@ -2131,17 +2264,19 @@
/* grid-fit the outline */
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
-#ifdef AF_USE_WARPER
- if ( ( dim == AF_DIMENSION_HORZ &&
- metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT )
{
AF_WarperRec warper;
FT_Fixed scale;
FT_Pos delta;
- af_warper_compute( &warper, hints, dim, &scale, &delta );
- af_glyph_hints_scale_dim( hints, dim, scale, delta );
+ af_warper_compute( &warper, hints, (AF_Dimension)dim,
+ &scale, &delta );
+ af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
+ scale, delta );
continue;
}
#endif
@@ -2206,7 +2341,7 @@
};
- AF_DEFINE_SCRIPT_CLASS(af_latin_script_class,
+ AF_DEFINE_SCRIPT_CLASS(af_latin_script_class,
AF_SCRIPT_LATIN,
af_latin_uniranges,
diff --git a/freetype/src/autofit/aflatin.h b/freetype/src/autofit/aflatin.h
index 660b10c83..c5c2d13f8 100644
--- a/freetype/src/autofit/aflatin.h
+++ b/freetype/src/autofit/aflatin.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter hinting routines for latin script (specification). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2009 by */
+/* Copyright 2003-2007, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -30,8 +30,8 @@ FT_BEGIN_HEADER
AF_DECLARE_SCRIPT_CLASS(af_latin_script_class)
-/* constants are given with units_per_em == 2048 in mind */
-#define AF_LATIN_CONSTANT( metrics, c ) \
+ /* constants are given with units_per_em == 2048 in mind */
+#define AF_LATIN_CONSTANT( metrics, c ) \
( ( (c) * (FT_Long)( (AF_LatinMetrics)(metrics) )->units_per_em ) / 2048 )
@@ -76,10 +76,10 @@ FT_BEGIN_HEADER
enum
{
- AF_LATIN_BLUE_ACTIVE = 1 << 0,
- AF_LATIN_BLUE_TOP = 1 << 1,
- AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */
- /* optimization */
+ AF_LATIN_BLUE_ACTIVE = 1 << 0, /* set if zone height is <= 3/4px */
+ AF_LATIN_BLUE_TOP = 1 << 1, /* result of AF_LATIN_IS_TOP_BLUE */
+ AF_LATIN_BLUE_ADJUSTMENT = 1 << 2, /* used for scale adjustment */
+ /* optimization */
AF_LATIN_BLUE_FLAG_MAX
};
@@ -98,14 +98,13 @@ FT_BEGIN_HEADER
FT_Fixed scale;
FT_Pos delta;
- FT_UInt width_count;
- AF_WidthRec widths[AF_LATIN_MAX_WIDTHS];
- FT_Pos edge_distance_threshold;
- FT_Pos standard_width;
- FT_Bool extra_light;
+ FT_UInt width_count; /* number of used widths */
+ AF_WidthRec widths[AF_LATIN_MAX_WIDTHS]; /* widths array */
+ FT_Pos edge_distance_threshold; /* used for creating edges */
+ FT_Pos standard_width; /* the default stem thickness */
+ FT_Bool extra_light; /* is standard width very light? */
/* ignored for horizontal metrics */
- FT_Bool control_overshoot;
FT_UInt blue_count;
AF_LatinBlueRec blues[AF_LATIN_BLUE_MAX];
diff --git a/freetype/src/autofit/aflatin2.c b/freetype/src/autofit/aflatin2.c
index 6546475a1..23558b879 100644
--- a/freetype/src/autofit/aflatin2.c
+++ b/freetype/src/autofit/aflatin2.c
@@ -1,10 +1,10 @@
/***************************************************************************/
/* */
-/* aflatin.c */
+/* aflatin2.c */
/* */
/* Auto-fitter hinting routines for latin script (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 2003-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,13 +23,24 @@
#include "aferrors.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.h"
#endif
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_aflatin2
+
+
FT_LOCAL_DEF( FT_Error )
af_latin2_hints_compute_segments( AF_GlyphHints hints,
- AF_Dimension dim );
+ AF_Dimension dim );
FT_LOCAL_DEF( void )
af_latin2_hints_link_segments( AF_GlyphHints hints,
@@ -45,8 +56,8 @@
FT_LOCAL_DEF( void )
af_latin2_metrics_init_widths( AF_LatinMetrics metrics,
- FT_Face face,
- FT_ULong charcode )
+ FT_Face face,
+ FT_ULong charcode )
{
/* scan the array of segments in each direction */
AF_GlyphHintsRec hints[1];
@@ -156,7 +167,8 @@
#define AF_LATIN_MAX_TEST_CHARACTERS 12
- static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES][AF_LATIN_MAX_TEST_CHARACTERS+1] =
+ static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES]
+ [AF_LATIN_MAX_TEST_CHARACTERS+1] =
{
"THEZOCQS",
"HEZLOCUS",
@@ -169,7 +181,7 @@
static void
af_latin2_metrics_init_blues( AF_LatinMetrics metrics,
- FT_Face face )
+ FT_Face face )
{
FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS];
FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS];
@@ -182,12 +194,12 @@
FT_GlyphSlot glyph = face->glyph;
- /* we compute the blues simply by loading each character from the */
+ /* we compute the blues simply by loading each character from the */
/* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
- /* bottom-most points (depending on `AF_IS_TOP_BLUE') */
+ /* bottom-most points (depending on `AF_IS_TOP_BLUE') */
- AF_LOG(( "blue zones computation\n" ));
- AF_LOG(( "------------------------------------------------\n" ));
+ FT_TRACE5(( "blue zones computation\n" ));
+ FT_TRACE5(( "------------------------------------------------\n" ));
for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
{
@@ -197,7 +209,7 @@
FT_Pos* blue_shoot;
- AF_LOG(( "blue %3d: ", bb ));
+ FT_TRACE5(( "blue %3d: ", bb ));
num_flats = 0;
num_rounds = 0;
@@ -210,7 +222,7 @@
FT_Bool round;
- AF_LOG(( "'%c'", *p ));
+ FT_TRACE5(( "'%c'", *p ));
/* load the character in the face -- skip unknown or empty ones */
glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
@@ -273,7 +285,7 @@
best_last = last;
}
}
- AF_LOG(( "%5d", best_y ));
+ FT_TRACE5(( "%5d", best_y ));
}
/* now check whether the point belongs to a straight or round */
@@ -321,7 +333,7 @@
FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
- AF_LOG(( "%c ", round ? 'r' : 'f' ));
+ FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
}
if ( round )
@@ -330,7 +342,7 @@
flats[num_flats++] = best_y;
}
- AF_LOG(( "\n" ));
+ FT_TRACE5(( "\n" ));
if ( num_flats == 0 && num_rounds == 0 )
{
@@ -338,7 +350,7 @@
* we couldn't find a single glyph to compute this blue zone,
* we will simply ignore it then
*/
- AF_LOG(( "empty\n" ));
+ FT_TRACE5(( "empty\n" ));
continue;
}
@@ -396,7 +408,7 @@
if ( bb == AF_LATIN_BLUE_SMALL_TOP )
blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
- AF_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+ FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
}
return;
@@ -451,7 +463,7 @@
FT_LOCAL_DEF( FT_Error )
af_latin2_metrics_init( AF_LatinMetrics metrics,
- FT_Face face )
+ FT_Face face )
{
FT_Error error = AF_Err_Ok;
FT_CharMap oldmap = face->charmap;
@@ -492,8 +504,8 @@
static void
af_latin2_metrics_scale_dim( AF_LatinMetrics metrics,
- AF_Scaler scaler,
- AF_Dimension dim )
+ AF_Scaler scaler,
+ AF_Dimension dim )
{
FT_Fixed scale;
FT_Pos delta;
@@ -548,7 +560,10 @@
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 ));
+ FT_TRACE5(( "== scaled x-top = %.2g"
+ " fitted = %.2g, scaling = %.4g\n",
+ scaled / 64.0, fitted / 64.0,
+ ( fitted * 1.0 ) / scaled ));
}
#endif
}
@@ -579,7 +594,7 @@
}
/* an extra-light axis corresponds to a standard width that is */
- /* smaller than 0.75 pixels */
+ /* smaller than 5/8 pixels */
axis->extra_light =
(FT_Bool)( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
@@ -624,9 +639,11 @@
blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
blue->shoot.fit = blue->ref.fit + delta2;
- AF_LOG(( ">> activating blue zone %d: ref.cur=%.2g ref.fit=%.2g shoot.cur=%.2g shoot.fit=%.2g\n",
- nn, blue->ref.cur/64.0, blue->ref.fit/64.0,
- blue->shoot.cur/64.0, blue->shoot.fit/64.0 ));
+ FT_TRACE5(( ">> activating blue zone %d:"
+ " ref.cur=%.2g ref.fit=%.2g"
+ " shoot.cur=%.2g shoot.fit=%.2g\n",
+ nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0,
+ blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
blue->flags |= AF_LATIN_BLUE_ACTIVE;
}
@@ -637,7 +654,7 @@
FT_LOCAL_DEF( void )
af_latin2_metrics_scale( AF_LatinMetrics metrics,
- AF_Scaler scaler )
+ AF_Scaler scaler )
{
metrics->root.scaler.render_mode = scaler->render_mode;
metrics->root.scaler.face = scaler->face;
@@ -659,7 +676,7 @@
FT_LOCAL_DEF( FT_Error )
af_latin2_hints_compute_segments( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
FT_Memory memory = hints->memory;
@@ -779,7 +796,6 @@
segment->dir = first->out_dir;
segment->first = first;
segment->last = point;
- segment->contour = contour;
segment->pos = (FT_Short)(( min_u + max_u ) >> 1);
segment->min_coord = (FT_Short) min_v;
segment->max_coord = (FT_Short) max_v;
@@ -917,7 +933,7 @@
FT_LOCAL_DEF( void )
af_latin2_hints_link_segments( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
AF_Segment segments = axis->segments;
@@ -1017,7 +1033,7 @@
FT_LOCAL_DEF( FT_Error )
af_latin2_hints_compute_edges( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
FT_Error error = AF_Err_Ok;
@@ -1137,7 +1153,8 @@
/* insert a new edge in the list and */
/* sort according to the position */
- error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, memory, &edge );
+ error = af_axis_hints_new_edge( axis, seg->pos, seg->dir,
+ memory, &edge );
if ( error )
goto Exit;
@@ -1205,8 +1222,10 @@
{
FT_Int is_round = 0; /* does it contain round segments? */
FT_Int is_straight = 0; /* does it contain straight segments? */
+#if 0
FT_Pos ups = 0; /* number of upwards segments */
FT_Pos downs = 0; /* number of downwards segments */
+#endif
seg = edge->first;
@@ -1222,11 +1241,13 @@
else
is_straight++;
+#if 0
/* check for segment direction */
if ( seg->dir == up_dir )
ups += seg->max_coord-seg->min_coord;
else
downs += seg->max_coord-seg->min_coord;
+#endif
/* check for links -- if seg->serif is set, then seg->link must */
/* be ignored */
@@ -1318,7 +1339,7 @@
FT_LOCAL_DEF( FT_Error )
af_latin2_hints_detect_features( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
FT_Error error;
@@ -1336,7 +1357,7 @@
FT_LOCAL_DEF( void )
af_latin2_hints_compute_blue_edges( AF_GlyphHints hints,
- AF_LatinMetrics metrics )
+ AF_LatinMetrics metrics )
{
AF_AxisHints axis = &hints->axis[ AF_DIMENSION_VERT ];
AF_Edge edge = axis->edges;
@@ -1442,7 +1463,7 @@
static FT_Error
af_latin2_hints_init( AF_GlyphHints hints,
- AF_LatinMetrics metrics )
+ AF_LatinMetrics metrics )
{
FT_Render_Mode mode;
FT_UInt32 scaler_flags, other_flags;
@@ -1463,7 +1484,7 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
-#if 0 /* #ifdef AF_USE_WARPER */
+#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
{
metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
@@ -1524,8 +1545,8 @@
static FT_Pos
af_latin2_snap_width( AF_Width widths,
- FT_Int count,
- FT_Pos width )
+ FT_Int count,
+ FT_Pos width )
{
int n;
FT_Pos best = 64 + 32 + 2;
@@ -1571,10 +1592,10 @@
static FT_Pos
af_latin2_compute_stem_width( AF_GlyphHints hints,
- AF_Dimension dim,
- FT_Pos width,
- AF_Edge_Flags base_flags,
- AF_Edge_Flags stem_flags )
+ AF_Dimension dim,
+ FT_Pos width,
+ AF_Edge_Flags base_flags,
+ AF_Edge_Flags stem_flags )
{
AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
AF_LatinAxis axis = & metrics->axis[dim];
@@ -1739,9 +1760,9 @@
static void
af_latin2_align_linked_edge( AF_GlyphHints hints,
- AF_Dimension dim,
- AF_Edge base_edge,
- AF_Edge stem_edge )
+ AF_Dimension dim,
+ AF_Edge base_edge,
+ AF_Edge stem_edge )
{
FT_Pos dist = stem_edge->opos - base_edge->opos;
@@ -1753,17 +1774,17 @@
stem_edge->pos = base_edge->pos + fitted_width;
- AF_LOG(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
- "dist was %.2f, now %.2f\n",
- stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
- stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+ FT_TRACE5(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
+ "dist was %.2f, now %.2f\n",
+ stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
+ stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
}
static void
af_latin2_align_serif_edge( AF_GlyphHints hints,
- AF_Edge base,
- AF_Edge serif )
+ AF_Edge base,
+ AF_Edge serif )
{
FT_UNUSED( hints );
@@ -1784,7 +1805,7 @@
FT_LOCAL_DEF( void )
af_latin2_hint_edges( AF_GlyphHints hints,
- AF_Dimension dim )
+ AF_Dimension dim )
{
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edges = axis->edges;
@@ -1796,7 +1817,8 @@
- AF_LOG(( "==== hinting %s edges =====\n", dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
+ FT_TRACE5(( "==== hinting %s edges =====\n",
+ dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
/* we begin by aligning all stems relative to the blue zone */
/* if needed -- that's only for horizontal edges */
@@ -1830,10 +1852,10 @@
if ( !edge1 )
continue;
- AF_LOG(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
- "was (%.2f)\n",
- edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
- edge1->pos / 64.0 ));
+ FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
+ "was (%.2f)\n",
+ edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
+ edge1->pos / 64.0 ));
edge1->pos = blue->fit;
edge1->flags |= AF_EDGE_DONE;
@@ -1878,7 +1900,7 @@
/* this should not happen, but it's better to be safe */
if ( edge2->blue_edge )
{
- AF_LOG(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
+ FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
af_latin2_align_linked_edge( hints, dim, edge2, edge );
edge->flags |= AF_EDGE_DONE;
@@ -1929,11 +1951,11 @@
else
edge->pos = FT_PIX_ROUND( edge->opos );
- AF_LOG(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f) "
- "snapped to (%.2f) (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0 ));
+ FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
+ " snapped to (%.2f) (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
anchor = edge;
edge->flags |= AF_EDGE_DONE;
@@ -1945,7 +1967,7 @@
anchor_drift = ( (anchor->pos - anchor->opos) +
(edge2->pos - edge2->opos)) >> 1;
- AF_LOG(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
+ FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
}
else
{
@@ -1965,12 +1987,13 @@
org_left = org_pos + ((org_len - cur_len) >> 1);
org_right = org_pos + ((org_len + cur_len) >> 1);
- AF_LOG(( "ALIGN: left=%.2f right=%.2f ", org_left/64.0, org_right/64.0 ));
+ FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
+ org_left / 64.0, org_right / 64.0 ));
cur_center = org_center;
if ( edge2->flags & AF_EDGE_DONE )
{
- AF_LOG(( "\n" ));
+ FT_TRACE5(( "\n" ));
edge->pos = edge2->pos - cur_len;
}
else
@@ -1985,14 +2008,14 @@
/* note: don't even try to fit tiny stems */
if ( cur_len < 32 )
{
- AF_LOG(( "tiny stem\n" ));
+ FT_TRACE5(( "tiny stem\n" ));
goto AlignStem;
}
/* if the span is within a single pixel, don't touch it */
if ( FT_PIX_FLOOR(org_left) == FT_PIX_CEIL(org_right) )
{
- AF_LOG(( "single pixel stem\n" ));
+ FT_TRACE5(( "single pixel stem\n" ));
goto AlignStem;
}
@@ -2015,14 +2038,14 @@
delta = FT_ABS(fit - org);
displacements[count] = fit - org;
scores[count++] = delta;
- AF_LOG(( "dispA=%.2f (%d) ", (fit - org)/64.0, delta ));
+ FT_TRACE5(( "dispA=%.2f (%d) ", (fit - org) / 64.0, delta ));
org = frac_right;
fit = (org <= 32) ? 16 : 48;
delta = FT_ABS(fit - org);
displacements[count] = fit - org;
scores[count++] = delta;
- AF_LOG(( "dispB=%.2f (%d) ", (fit - org)/64.0, delta ));
+ FT_TRACE5(( "dispB=%.2f (%d) ", (fit - org) / 64.0, delta ));
}
}
@@ -2032,7 +2055,7 @@
delta = FT_ABS(fit - org);
displacements[count] = fit - org;
scores[count++] = delta;
- AF_LOG(( "dispC=%.2f (%d) ", (fit - org)/64.0, delta ));
+ FT_TRACE5(( "dispC=%.2f (%d) ", (fit - org) / 64.0, delta ));
/* snapping the right edge to the grid */
org = org_right;
@@ -2040,7 +2063,7 @@
delta = FT_ABS(fit - org);
displacements[count] = fit - org;
scores[count++] = delta;
- AF_LOG(( "dispD=%.2f (%d) ", (fit - org)/64.0, delta ));
+ FT_TRACE5(( "dispD=%.2f (%d) ", (fit - org) / 64.0, delta ));
/* now find the best displacement */
{
@@ -2059,27 +2082,28 @@
cur_center = org_center + best_disp;
}
- AF_LOG(( "\n" ));
+ FT_TRACE5(( "\n" ));
}
AlignStem:
edge->pos = cur_center - (cur_len >> 1);
edge2->pos = edge->pos + cur_len;
- AF_LOG(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f) "
- "snapped to (%.2f) and (%.2f), org_len = %.2f cur_len=%.2f\n",
- edge-edges, edge->opos / 64.0,
- edge2-edges, edge2->opos / 64.0,
- edge->pos / 64.0, edge2->pos / 64.0,
- org_len / 64.0, cur_len / 64.0 ));
+ FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
+ " snapped to (%.2f) and (%.2f),"
+ " org_len=%.2f cur_len=%.2f\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0,
+ org_len / 64.0, cur_len / 64.0 ));
edge->flags |= AF_EDGE_DONE;
edge2->flags |= AF_EDGE_DONE;
if ( edge > edges && edge->pos < edge[-1].pos )
{
- AF_LOG(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
- edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+ FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
+ edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
edge->pos = edge[-1].pos;
}
}
@@ -2179,16 +2203,17 @@
if ( delta < 64 + 16 )
{
af_latin2_align_serif_edge( hints, edge->serif, edge );
- AF_LOG(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f) "
- "aligned to (%.2f)\n",
- edge-edges, edge->opos / 64.0,
- edge->serif - edges, edge->serif->opos / 64.0,
- edge->pos / 64.0 ));
+ FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
+ " aligned to (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge->serif - edges, edge->serif->opos / 64.0,
+ edge->pos / 64.0 ));
}
else if ( !anchor )
{
- AF_LOG(( "SERIF_ANCHOR: edge %d (opos=%.2f) snapped to (%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
edge->pos = FT_PIX_ROUND( edge->opos );
anchor = edge;
}
@@ -2215,15 +2240,19 @@
FT_MulDiv( edge->opos - before->opos,
after->pos - before->pos,
after->opos - before->opos );
- AF_LOG(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f) from %d (opos=%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0, before - edges, before->opos / 64.0 ));
+ FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
+ " from %d (opos=%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0,
+ before - edges, before->opos / 64.0 ));
}
else
{
- edge->pos = anchor->pos + (( edge->opos - anchor->opos + 16) & ~31);
+ edge->pos = anchor->pos +
+ ( ( edge->opos - anchor->opos + 16 ) & ~31 );
- AF_LOG(( "SERIF_LINK2: edge %d (opos=%.2f) snapped to (%.2f)\n",
- edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
}
}
@@ -2243,8 +2272,8 @@
static FT_Error
af_latin2_hints_apply( AF_GlyphHints hints,
- FT_Outline* outline,
- AF_LatinMetrics metrics )
+ FT_Outline* outline,
+ AF_LatinMetrics metrics )
{
FT_Error error;
int dim;
@@ -2255,7 +2284,7 @@
goto Exit;
/* analyze glyph outline */
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ||
AF_HINTS_DO_HORIZONTAL( hints ) )
#else
@@ -2279,7 +2308,7 @@
/* grid-fit the outline */
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
if ( ( dim == AF_DIMENSION_HORZ &&
metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT ) )
{
@@ -2321,7 +2350,7 @@
static const AF_Script_UniRangeRec af_latin2_uniranges[] =
{
- AF_UNIRANGE_REC( 32UL, 127UL ), /* XXX: TODO: Add new Unicode ranges here! */
+ AF_UNIRANGE_REC( 32UL, 127UL ), /* TODO: Add new Unicode ranges here! */
AF_UNIRANGE_REC( 160UL, 255UL ),
AF_UNIRANGE_REC( 0UL, 0UL )
};
diff --git a/freetype/src/autofit/afloader.c b/freetype/src/autofit/afloader.c
index 6dd9f2a31..966a0df73 100644
--- a/freetype/src/autofit/afloader.c
+++ b/freetype/src/autofit/afloader.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter glyph loading routines (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 2003-2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,6 +22,8 @@
#include "aferrors.h"
+ /* Initialize glyph loader. */
+
FT_LOCAL_DEF( FT_Error )
af_loader_init( AF_Loader loader,
FT_Memory memory )
@@ -29,13 +31,15 @@
FT_ZERO( loader );
af_glyph_hints_init( &loader->hints, memory );
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
_af_debug_hints = &loader->hints;
#endif
return FT_GlyphLoader_New( memory, &loader->gloader );
}
+ /* Reset glyph loader and compute globals if necessary. */
+
FT_LOCAL_DEF( FT_Error )
af_loader_reset( AF_Loader loader,
FT_Face face )
@@ -64,6 +68,8 @@
}
+ /* Finalize glyph loader. */
+
FT_LOCAL_DEF( void )
af_loader_done( AF_Loader loader )
{
@@ -72,7 +78,7 @@
loader->face = NULL;
loader->globals = NULL;
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
_af_debug_hints = NULL;
#endif
FT_GlyphLoader_Done( loader->gloader );
@@ -80,6 +86,10 @@
}
+ /* Load a single glyph component. This routine calls itself */
+ /* recursively, if necessary, and does the main work of */
+ /* `af_loader_load_glyph.' */
+
static FT_Error
af_loader_load_g( AF_Loader loader,
AF_Scaler scaler,
@@ -169,8 +179,8 @@
&gloader->current.outline,
metrics );
- /* we now need to hint the metrics according to the change in */
- /* width/positioning that occurred during the hinting process */
+ /* we now need to adjust the metrics according to the change in */
+ /* width/positioning that occurred during the hinting process */
if ( scaler->render_mode != FT_RENDER_MODE_LIGHT )
{
FT_Pos old_rsb, old_lsb, new_lsb;
@@ -265,7 +275,7 @@
gloader->current.num_subglyphs = num_subglyphs;
num_base_subgs = gloader->base.num_subglyphs;
- /* now, read each subglyph independently */
+ /* now read each subglyph independently */
for ( nn = 0; nn < num_subglyphs; nn++ )
{
FT_Vector pp1, pp2;
@@ -305,7 +315,7 @@
num_points = gloader->base.outline.n_points;
num_new_points = num_points - num_base_points;
- /* now perform the transform required for this subglyph */
+ /* now perform the transformation required for this subglyph */
if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
FT_SUBGLYPH_FLAG_XY_SCALE |
@@ -444,7 +454,7 @@
#endif
slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
- metrics->scaler.y_scale );
+ metrics->scaler.y_scale );
slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
@@ -459,15 +469,13 @@
slot->format = FT_GLYPH_FORMAT_OUTLINE;
}
-#ifdef DEBUG_HINTER
- af_debug_hinter = hinter;
-#endif
-
Exit:
return error;
}
+ /* Load a glyph. */
+
FT_LOCAL_DEF( FT_Error )
af_loader_load_glyph( AF_Loader loader,
FT_Face face,
diff --git a/freetype/src/autofit/afloader.h b/freetype/src/autofit/afloader.h
index fa67c10ff..3f91e1a22 100644
--- a/freetype/src/autofit/afloader.h
+++ b/freetype/src/autofit/afloader.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter glyph loading routines (specification). */
/* */
-/* Copyright 2003, 2004, 2005 by */
+/* Copyright 2003-2005, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,8 +16,8 @@
/***************************************************************************/
-#ifndef __AF_LOADER_H__
-#define __AF_LOADER_H__
+#ifndef __AFLOADER_H__
+#define __AFLOADER_H__
#include "afhints.h"
#include "afglobal.h"
@@ -67,7 +67,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __AF_LOADER_H__ */
+#endif /* __AFLOADER_H__ */
/* END */
diff --git a/freetype/src/autofit/afmodule.c b/freetype/src/autofit/afmodule.c
index fc75df7ed..683106121 100644
--- a/freetype/src/autofit/afmodule.c
+++ b/freetype/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module implementation (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006 by */
+/* Copyright 2003-2006, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,8 +20,7 @@
#include "afloader.h"
#include "afpic.h"
-#ifdef AF_DEBUG
- int _af_debug;
+#ifdef FT_DEBUG_AUTOFIT
int _af_debug_disable_horz_hints;
int _af_debug_disable_vert_hints;
int _af_debug_disable_blue_hints;
@@ -67,14 +66,15 @@
}
- FT_DEFINE_AUTOHINTER_SERVICE(af_autofitter_service,
+ FT_DEFINE_AUTOHINTER_SERVICE(
+ af_autofitter_service,
NULL,
NULL,
NULL,
- (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph
- )
+ (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph )
- FT_DEFINE_MODULE(autofit_module_class,
+ FT_DEFINE_MODULE(
+ autofit_module_class,
FT_MODULE_HINTER,
sizeof ( FT_AutofitterRec ),
@@ -87,8 +87,7 @@
(FT_Module_Constructor)af_autofitter_init,
(FT_Module_Destructor) af_autofitter_done,
- (FT_Module_Requester) NULL
- )
+ (FT_Module_Requester) NULL )
/* END */
diff --git a/freetype/src/autofit/afpic.c b/freetype/src/autofit/afpic.c
index 897dbe35d..3fb8e51c4 100644
--- a/freetype/src/autofit/afpic.c
+++ b/freetype/src/autofit/afpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for autofit module. */
/* */
-/* Copyright 2009, 2010 by */
+/* Copyright 2009, 2010, 2011 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,7 +24,8 @@
#ifdef FT_CONFIG_OPTION_PIC
/* forward declaration of PIC init functions from afmodule.c */
- void FT_Init_Class_af_autofitter_service( FT_Library, FT_AutoHinter_ServiceRec*);
+ void FT_Init_Class_af_autofitter_service( FT_Library,
+ FT_AutoHinter_ServiceRec* );
/* forward declaration of PIC init functions from script classes */
#include "aflatin.h"
@@ -34,10 +35,12 @@
#include "afindic.h"
void
- autofit_module_class_pic_free( FT_Library library )
+ autofit_module_class_pic_free( FT_Library library )
{
- FT_PIC_Container* pic_container = &library->pic_container;
- FT_Memory memory = library->memory;
+ FT_PIC_Container* pic_container = &library->pic_container;
+ FT_Memory memory = library->memory;
+
+
if ( pic_container->autofit )
{
FT_FREE( pic_container->autofit );
@@ -62,28 +65,37 @@
FT_MEM_SET( container, 0, sizeof ( *container ) );
pic_container->autofit = container;
- /* initialize pointer table - this is how the module usually expects this data */
+ /* initialize pointer table - */
+ /* this is how the module usually expects this data */
for ( ss = 0 ; ss < AF_SCRIPT_CLASSES_REC_COUNT ; ss++ )
{
- container->af_script_classes[ss] = &container->af_script_classes_rec[ss];
+ container->af_script_classes[ss] =
+ &container->af_script_classes_rec[ss];
}
- container->af_script_classes[AF_SCRIPT_CLASSES_COUNT-1] = NULL;
+ container->af_script_classes[AF_SCRIPT_CLASSES_COUNT - 1] = NULL;
/* add call to initialization function when you add new scripts */
ss = 0;
- FT_Init_Class_af_dummy_script_class(&container->af_script_classes_rec[ss++]);
+ FT_Init_Class_af_dummy_script_class(
+ &container->af_script_classes_rec[ss++] );
#ifdef FT_OPTION_AUTOFIT2
- FT_Init_Class_af_latin2_script_class(&container->af_script_classes_rec[ss++]);
+ FT_Init_Class_af_latin2_script_class(
+ &container->af_script_classes_rec[ss++] );
#endif
- FT_Init_Class_af_latin_script_class(&container->af_script_classes_rec[ss++]);
- FT_Init_Class_af_cjk_script_class(&container->af_script_classes_rec[ss++]);
- FT_Init_Class_af_indic_script_class(&container->af_script_classes_rec[ss++]);
+ FT_Init_Class_af_latin_script_class(
+ &container->af_script_classes_rec[ss++] );
+ FT_Init_Class_af_cjk_script_class(
+ &container->af_script_classes_rec[ss++] );
+ FT_Init_Class_af_indic_script_class(
+ &container->af_script_classes_rec[ss++] );
+
+ FT_Init_Class_af_autofitter_service(
+ library, &container->af_autofitter_service );
- FT_Init_Class_af_autofitter_service(library, &container->af_autofitter_service);
+/* Exit: */
-/*Exit:*/
- if(error)
- autofit_module_class_pic_free(library);
+ if ( error )
+ autofit_module_class_pic_free( library );
return error;
}
diff --git a/freetype/src/autofit/afpic.h b/freetype/src/autofit/afpic.h
index 8c41b011c..e4cd7a05d 100644
--- a/freetype/src/autofit/afpic.h
+++ b/freetype/src/autofit/afpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for autofit module. */
/* */
-/* Copyright 2009 by */
+/* Copyright 2009, 2011 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -33,24 +33,29 @@ FT_BEGIN_HEADER
#include "aftypes.h"
-/* increase these when you add new scripts, and update autofit_module_class_pic_init */
+ /* increase these when you add new scripts, */
+ /* and update autofit_module_class_pic_init */
#ifdef FT_OPTION_AUTOFIT2
- #define AF_SCRIPT_CLASSES_COUNT 6
+#define AF_SCRIPT_CLASSES_COUNT 6
#else
- #define AF_SCRIPT_CLASSES_COUNT 5
+#define AF_SCRIPT_CLASSES_COUNT 5
#endif
-#define AF_SCRIPT_CLASSES_REC_COUNT (AF_SCRIPT_CLASSES_COUNT-1)
+#define AF_SCRIPT_CLASSES_REC_COUNT ( AF_SCRIPT_CLASSES_COUNT - 1 )
typedef struct AFModulePIC_
{
- AF_ScriptClass af_script_classes[AF_SCRIPT_CLASSES_COUNT];
- AF_ScriptClassRec af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
- FT_AutoHinter_ServiceRec af_autofitter_service;
+ AF_ScriptClass af_script_classes[AF_SCRIPT_CLASSES_COUNT];
+ AF_ScriptClassRec af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
+ FT_AutoHinter_ServiceRec af_autofitter_service;
+
} AFModulePIC;
-#define GET_PIC(lib) ((AFModulePIC*)((lib)->pic_container.autofit))
-#define AF_SCRIPT_CLASSES_GET (GET_PIC(FT_FACE_LIBRARY(globals->face))->af_script_classes)
-#define AF_AF_AUTOFITTER_SERVICE_GET (GET_PIC(library)->af_autofitter_service)
+#define GET_PIC( lib ) \
+ ( (AFModulePIC*)((lib)->pic_container.autofit) )
+#define AF_SCRIPT_CLASSES_GET \
+ ( GET_PIC( FT_FACE_LIBRARY(globals->face) )->af_script_classes )
+#define AF_AF_AUTOFITTER_SERVICE_GET \
+ ( GET_PIC( library )->af_autofitter_service )
#endif /* FT_CONFIG_OPTION_PIC */
diff --git a/freetype/src/autofit/aftypes.h b/freetype/src/autofit/aftypes.h
index cc1bfe890..a31bf5225 100644
--- a/freetype/src/autofit/aftypes.h
+++ b/freetype/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter types (specification only). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 2003-2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -53,26 +53,16 @@ FT_BEGIN_HEADER
/*************************************************************************/
/*************************************************************************/
-#define xxAF_USE_WARPER /* only define to use warp hinting */
-#define xxAF_DEBUG
-
-#ifdef AF_DEBUG
+#ifdef FT_DEBUG_AUTOFIT
#include FT_CONFIG_STANDARD_LIBRARY_H
-#define AF_LOG( x ) do { if ( _af_debug ) printf x; } while ( 0 )
-
-extern int _af_debug;
extern int _af_debug_disable_horz_hints;
extern int _af_debug_disable_vert_hints;
extern int _af_debug_disable_blue_hints;
extern void* _af_debug_hints;
-#else /* !AF_DEBUG */
-
-#define AF_LOG( x ) do { } while ( 0 ) /* nothing */
-
-#endif /* !AF_DEBUG */
+#endif /* FT_DEBUG_AUTOFIT */
/*************************************************************************/
@@ -159,36 +149,11 @@ extern void* _af_debug_hints;
FT_END_STMNT
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** O U T L I N E S *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
/* opaque handle to glyph-specific hints -- see `afhints.h' for more
* details
*/
typedef struct AF_GlyphHintsRec_* AF_GlyphHints;
- /* This structure is used to model an input glyph outline to
- * the auto-hinter. The latter will set the `hints' field
- * depending on the glyph's script.
- */
- typedef struct AF_OutlineRec_
- {
- FT_Face face;
- FT_Outline outline;
- FT_UInt outline_resolution;
-
- FT_Int advance;
- FT_UInt metrics_resolution;
-
- AF_GlyphHints hints;
-
- } AF_OutlineRec;
-
/*************************************************************************/
/*************************************************************************/
@@ -241,7 +206,7 @@ extern void* _af_debug_hints;
/*************************************************************************/
/*
- * The list of know scripts. Each different script corresponds to the
+ * The list of known scripts. Each different script corresponds to the
* following information:
*
* - A set of Unicode ranges to test whether the face supports the
@@ -342,55 +307,57 @@ extern void* _af_debug_hints;
} AF_ScriptClassRec;
-/* Declare and define vtables for classes */
+
+ /* Declare and define vtables for classes */
#ifndef FT_CONFIG_OPTION_PIC
-#define AF_DECLARE_SCRIPT_CLASS(script_class) \
- FT_CALLBACK_TABLE const AF_ScriptClassRec \
+#define AF_DECLARE_SCRIPT_CLASS( script_class ) \
+ FT_CALLBACK_TABLE const AF_ScriptClassRec \
script_class;
-#define AF_DEFINE_SCRIPT_CLASS(script_class, script_, ranges, m_size, \
- m_init, m_scale, m_done, h_init, h_apply) \
- FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec \
- script_class = \
- { \
- script_, \
- ranges, \
- \
- m_size, \
- \
- m_init, \
- m_scale, \
- m_done, \
- \
- h_init, \
- h_apply \
+#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, m_size, \
+ m_init, m_scale, m_done, h_init, h_apply ) \
+ FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec \
+ script_class = \
+ { \
+ script_, \
+ ranges, \
+ \
+ m_size, \
+ \
+ m_init, \
+ m_scale, \
+ m_done, \
+ \
+ h_init, \
+ h_apply \
};
-#else
-
-#define AF_DECLARE_SCRIPT_CLASS(script_class) \
- FT_LOCAL(void) \
- FT_Init_Class_##script_class(AF_ScriptClassRec* ac);
-
-#define AF_DEFINE_SCRIPT_CLASS(script_class, script_, ranges, m_size, \
- m_init, m_scale, m_done, h_init, h_apply) \
- FT_LOCAL_DEF(void) \
- FT_Init_Class_##script_class(AF_ScriptClassRec* ac) \
- { \
- ac->script = script_; \
- ac->script_uni_ranges = ranges; \
- \
- ac->script_metrics_size = m_size; \
- \
- ac->script_metrics_init = m_init; \
- ac->script_metrics_scale = m_scale; \
- ac->script_metrics_done = m_done; \
- \
- ac->script_hints_init = h_init; \
- ac->script_hints_apply = h_apply; \
+#else /* FT_CONFIG_OPTION_PIC */
+
+#define AF_DECLARE_SCRIPT_CLASS( script_class ) \
+ FT_LOCAL( void ) \
+ FT_Init_Class_##script_class( AF_ScriptClassRec* ac );
+
+#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, m_size, \
+ m_init, m_scale, m_done, h_init, h_apply ) \
+ FT_LOCAL_DEF( void ) \
+ FT_Init_Class_##script_class( AF_ScriptClassRec* ac ) \
+ { \
+ ac->script = script_; \
+ ac->script_uni_ranges = ranges; \
+ \
+ ac->script_metrics_size = m_size; \
+ \
+ ac->script_metrics_init = m_init; \
+ ac->script_metrics_scale = m_scale; \
+ ac->script_metrics_done = m_done; \
+ \
+ ac->script_hints_init = h_init; \
+ ac->script_hints_apply = h_apply; \
}
-#endif
+
+#endif /* FT_CONFIG_OPTION_PIC */
/* */
diff --git a/freetype/src/autofit/afwarp.c b/freetype/src/autofit/afwarp.c
index f5bb9b18a..d0d4850bd 100644
--- a/freetype/src/autofit/afwarp.c
+++ b/freetype/src/autofit/afwarp.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter warping algorithm (body). */
/* */
-/* Copyright 2006, 2007 by */
+/* Copyright 2006, 2007, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,10 +16,30 @@
/***************************************************************************/
+ /*
+ * The idea of the warping code is to slightly scale and shift a glyph
+ * within a single dimension so that as much of its segments are aligned
+ * (more or less) on the grid. To find out the optimal scaling and
+ * shifting value, various parameter combinations are tried and scored.
+ */
+
#include "afwarp.h"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_afwarp
+
+ /* The weights cover the range 0/64 - 63/64 of a pixel. Obviously, */
+ /* values around a half pixel (which means exactly between two grid */
+ /* lines) gets the worst weight. */
#if 1
static const AF_WarpScore
af_warper_weights[64] =
@@ -43,6 +63,11 @@
#endif
+ /* Score segments for a given `scale' and `delta' in the range */
+ /* `xx1' to `xx2', and store the best result in `warper'. If */
+ /* the new best score is equal to the old one, prefer the */
+ /* value with a smaller distortion (around `base_distort'). */
+
static void
af_warper_compute_line_best( AF_Warper warper,
FT_Fixed scale,
@@ -82,12 +107,12 @@
if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
{
- AF_LOG(( "invalid indices:\n"
- " min=%d max=%d, xx1=%ld xx2=%ld,\n"
- " x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
- idx_min, idx_max, xx1, xx2,
- warper->x1min, warper->x1max,
- warper->x2min, warper->x2max ));
+ FT_TRACE5(( "invalid indices:\n"
+ " min=%d max=%d, xx1=%ld xx2=%ld,\n"
+ " x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
+ idx_min, idx_max, xx1, xx2,
+ warper->x1min, warper->x1max,
+ warper->x2min, warper->x2max ));
return;
}
}
@@ -100,6 +125,7 @@
FT_Int idx;
+ /* score the length of the segments for the given range */
for ( idx = idx_min; idx <= idx_max; idx++, y++ )
scores[idx] += af_warper_weights[y & 63] * len;
}
@@ -115,9 +141,9 @@
AF_WarpScore distort = base_distort + ( idx - idx0 );
- if ( score > warper->best_score ||
+ if ( score > warper->best_score ||
( score == warper->best_score &&
- distort < warper->best_distort ) )
+ distort < warper->best_distort ) )
{
warper->best_score = score;
warper->best_distort = distort;
@@ -129,6 +155,9 @@
}
+ /* Compute optimal scaling and delta values for a given glyph and */
+ /* dimension. */
+
FT_LOCAL_DEF( void )
af_warper_compute( AF_Warper warper,
AF_GlyphHints hints,
@@ -215,6 +244,7 @@
warper->t1 = AF_WARPER_FLOOR( warper->x1 );
warper->t2 = AF_WARPER_CEIL( warper->x2 );
+ /* examine a half pixel wide range around the maximum coordinates */
warper->x1min = warper->x1 & ~31;
warper->x1max = warper->x1min + 32;
warper->x2min = warper->x2 & ~31;
@@ -234,10 +264,12 @@
warper->x2min = warper->x2;
}
+ /* examine (at most) a pixel wide range around the natural width */
warper->wmin = warper->x2min - warper->x1max;
warper->wmax = warper->x2max - warper->x1min;
#if 1
+ /* some heuristics to reduce the number of widths to be examined */
{
int margin = 16;
@@ -273,6 +305,8 @@
FT_Pos xx1, xx2;
+ /* compute min and max positions for given width, */
+ /* assuring that they stay within the coordinate ranges */
xx1 = warper->x1;
xx2 = warper->x2;
if ( w >= warper->w0 )
@@ -304,6 +338,7 @@
else
base_distort += xx2 - warper->x2;
+ /* give base distortion a greater weight while scoring */
base_distort *= 10;
new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
@@ -329,10 +364,11 @@
}
}
-#else /* !AF_USE_WARPER */
+#else /* !AF_CONFIG_OPTION_USE_WARPER */
-char af_warper_dummy = 0; /* make compiler happy */
+ /* ANSI C doesn't like empty source files */
+ typedef int _af_warp_dummy;
-#endif /* !AF_USE_WARPER */
+#endif /* !AF_CONFIG_OPTION_USE_WARPER */
/* END */
diff --git a/freetype/src/autofit/autofit.c b/freetype/src/autofit/autofit.c
index 83b613e79..3883a0a70 100644
--- a/freetype/src/autofit/autofit.c
+++ b/freetype/src/autofit/autofit.c
@@ -4,7 +4,7 @@
/* */
/* Auto-fitter module (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007 by */
+/* Copyright 2003-2007, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -34,7 +34,7 @@
#include "afloader.c"
#include "afmodule.c"
-#ifdef AF_USE_WARPER
+#ifdef AF_CONFIG_OPTION_USE_WARPER
#include "afwarp.c"
#endif
diff --git a/freetype/src/autofit/rules.mk b/freetype/src/autofit/rules.mk
index 017489d9e..b76bb79ab 100644
--- a/freetype/src/autofit/rules.mk
+++ b/freetype/src/autofit/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2003, 2004, 2005, 2006, 2007 by
+# Copyright 2003, 2004, 2005, 2006, 2007, 2011 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -34,13 +34,14 @@ AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
$(AUTOF_DIR)/aflatin.c \
$(AUTOF_DIR)/afloader.c \
$(AUTOF_DIR)/afmodule.c \
+ $(AUTOF_DIR)/afpic.c \
$(AUTOF_DIR)/afwarp.c
# AUTOF driver headers
#
AUTOF_DRV_H := $(AUTOF_DRV_SRC:%c=%h) \
- $(AUTOF_DIR)/aftypes.h \
- $(AUTOF_DIR)/aferrors.h
+ $(AUTOF_DIR)/aferrors.h \
+ $(AUTOF_DIR)/aftypes.h
# AUTOF driver object(s)
diff --git a/freetype/src/base/ftbitmap.c b/freetype/src/base/ftbitmap.c
index 95f7f93ee..b700b28f2 100644
--- a/freetype/src/base/ftbitmap.c
+++ b/freetype/src/base/ftbitmap.c
@@ -105,7 +105,7 @@
int new_pitch;
FT_UInt bpp;
FT_Int i, width, height;
- unsigned char* buffer;
+ unsigned char* buffer = NULL;
width = bitmap->width;
diff --git a/freetype/src/base/ftobjs.c b/freetype/src/base/ftobjs.c
index ed403a3cf..e83062468 100644
--- a/freetype/src/base/ftobjs.c
+++ b/freetype/src/base/ftobjs.c
@@ -4,8 +4,7 @@
/* */
/* The FreeType private base classes (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -131,7 +130,7 @@
{
FT_Error error;
FT_Memory memory;
- FT_Stream stream;
+ FT_Stream stream = NULL;
*astream = 0;
@@ -375,7 +374,7 @@
FT_Driver driver;
FT_Driver_Class clazz;
FT_Memory memory;
- FT_GlyphSlot slot;
+ FT_GlyphSlot slot = NULL;
if ( !face || !face->driver )
@@ -561,6 +560,7 @@
FT_Library library;
FT_Bool autohint = FALSE;
FT_Module hinter;
+ TT_Face ttface = (TT_Face)face;
if ( !face || !face->size || !face->glyph )
@@ -601,7 +601,8 @@
* - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
* have a native font hinter.
*
- * - Otherwise, auto-hint for LIGHT hinting mode.
+ * - Otherwise, auto-hint for LIGHT hinting mode or if there isn't
+ * any hinting bytecode in the TrueType/OpenType font.
*
* - Exception: The font is `tricky' and requires the native hinter to
* load properly.
@@ -626,8 +627,13 @@
FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
- if ( mode == FT_RENDER_MODE_LIGHT ||
- face->internal->ignore_unpatented_hinter )
+ /* the check for `num_locations' assures that we actually */
+ /* test for instructions in a TTF and not in a CFF-based OTF */
+ if ( mode == FT_RENDER_MODE_LIGHT ||
+ face->internal->ignore_unpatented_hinter ||
+ ( FT_IS_SFNT( face ) &&
+ ttface->num_locations &&
+ ttface->max_profile.maxSizeOfInstructions == 0 ) )
autohint = TRUE;
}
}
@@ -1283,7 +1289,7 @@
{
FT_Error error;
FT_Memory memory;
- FT_Stream stream;
+ FT_Stream stream = NULL;
if ( !library )
@@ -1458,7 +1464,7 @@
FT_ULong offset, length;
FT_Long pos;
FT_Bool is_sfnt_cid;
- FT_Byte* sfnt_ps;
+ FT_Byte* sfnt_ps = NULL;
FT_UNUSED( num_params );
FT_UNUSED( params );
@@ -1525,7 +1531,7 @@
{
FT_Error error = FT_Err_Cannot_Open_Resource;
FT_Memory memory = library->memory;
- FT_Byte* pfb_data;
+ FT_Byte* pfb_data = NULL;
int i, type, flags;
FT_Long len;
FT_Long pfb_len, pfb_pos, pfb_lenpos;
@@ -1667,7 +1673,7 @@
FT_Face *aface )
{
FT_Memory memory = library->memory;
- FT_Byte* sfnt_data;
+ FT_Byte* sfnt_data = NULL;
FT_Error error;
FT_Long flag_offset;
FT_Long rlen;
@@ -1869,7 +1875,7 @@
" is already checked and"
" no font is found\n", i ));
continue;
- }
+ }
if ( errors[i] )
{
@@ -3148,7 +3154,7 @@
FT_Error error = FT_Err_Ok;
FT_Face face;
FT_Memory memory;
- FT_CMap cmap;
+ FT_CMap cmap = NULL;
if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
@@ -3887,6 +3893,7 @@
error = set_mode( renderer, parameters->tag, parameters->data );
if ( error )
break;
+ parameters++;
}
}
@@ -4150,7 +4157,7 @@
FT_Renderer renderer = FT_RENDERER( module );
- if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
+ if ( renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
renderer->raster )
renderer->clazz->raster_class->raster_done( renderer->raster );
}
diff --git a/freetype/src/base/ftrfork.c b/freetype/src/base/ftrfork.c
index 4bb405e38..c94cdd86d 100644
--- a/freetype/src/base/ftrfork.c
+++ b/freetype/src/base/ftrfork.c
@@ -159,8 +159,8 @@
FT_Long tag_internal, rpos;
FT_Memory memory = library->memory;
FT_Long temp;
- FT_Long *offsets_internal;
- FT_RFork_Ref *ref;
+ FT_Long *offsets_internal = NULL;
+ FT_RFork_Ref *ref = NULL;
error = FT_Stream_Seek( stream, map_offset );
@@ -527,7 +527,7 @@
Only meaningful on systems with hfs+ drivers (or Macs).
*/
FT_Error error;
- char* newpath;
+ char* newpath = NULL;
FT_Memory memory;
FT_Long base_file_len = ft_strlen( base_file_name );
@@ -563,7 +563,7 @@
Only meaningful on systems with Mac OS X (> 10.1).
*/
FT_Error error;
- char* newpath;
+ char* newpath = NULL;
FT_Memory memory;
FT_Long base_file_len = ft_strlen( base_file_name );
diff --git a/freetype/src/base/ftstream.c b/freetype/src/base/ftstream.c
index c36cadd79..c04af6724 100644
--- a/freetype/src/base/ftstream.c
+++ b/freetype/src/base/ftstream.c
@@ -4,7 +4,7 @@
/* */
/* I/O stream support (body). */
/* */
-/* Copyright 2000-2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010 by */
+/* Copyright 2000-2002, 2004-2006, 2008-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -354,8 +354,8 @@
}
- FT_BASE_DEF( FT_Short )
- FT_Stream_GetShort( FT_Stream stream )
+ FT_BASE_DEF( FT_UShort )
+ FT_Stream_GetUShort( FT_Stream stream )
{
FT_Byte* p;
FT_Short result;
@@ -366,15 +366,15 @@
result = 0;
p = stream->cursor;
if ( p + 1 < stream->limit )
- result = FT_NEXT_SHORT( p );
+ result = FT_NEXT_USHORT( p );
stream->cursor = p;
return result;
}
- FT_BASE_DEF( FT_Short )
- FT_Stream_GetShortLE( FT_Stream stream )
+ FT_BASE_DEF( FT_UShort )
+ FT_Stream_GetUShortLE( FT_Stream stream )
{
FT_Byte* p;
FT_Short result;
@@ -385,15 +385,15 @@
result = 0;
p = stream->cursor;
if ( p + 1 < stream->limit )
- result = FT_NEXT_SHORT_LE( p );
+ result = FT_NEXT_USHORT_LE( p );
stream->cursor = p;
return result;
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_GetOffset( FT_Stream stream )
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_GetUOffset( FT_Stream stream )
{
FT_Byte* p;
FT_Long result;
@@ -404,14 +404,14 @@
result = 0;
p = stream->cursor;
if ( p + 2 < stream->limit )
- result = FT_NEXT_OFF3( p );
+ result = FT_NEXT_UOFF3( p );
stream->cursor = p;
return result;
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_GetLong( FT_Stream stream )
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_GetULong( FT_Stream stream )
{
FT_Byte* p;
FT_Long result;
@@ -422,14 +422,14 @@
result = 0;
p = stream->cursor;
if ( p + 3 < stream->limit )
- result = FT_NEXT_LONG( p );
+ result = FT_NEXT_ULONG( p );
stream->cursor = p;
return result;
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_GetLongLE( FT_Stream stream )
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_GetULongLE( FT_Stream stream )
{
FT_Byte* p;
FT_Long result;
@@ -440,7 +440,7 @@
result = 0;
p = stream->cursor;
if ( p + 3 < stream->limit )
- result = FT_NEXT_LONG_LE( p );
+ result = FT_NEXT_ULONG_LE( p );
stream->cursor = p;
return result;
}
@@ -483,8 +483,8 @@
}
- FT_BASE_DEF( FT_Short )
- FT_Stream_ReadShort( FT_Stream stream,
+ FT_BASE_DEF( FT_UShort )
+ FT_Stream_ReadUShort( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[2];
@@ -511,7 +511,7 @@
}
if ( p )
- result = FT_NEXT_SHORT( p );
+ result = FT_NEXT_USHORT( p );
}
else
goto Fail;
@@ -522,7 +522,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadShort:"
+ FT_ERROR(( "FT_Stream_ReadUShort:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
@@ -530,8 +530,8 @@
}
- FT_BASE_DEF( FT_Short )
- FT_Stream_ReadShortLE( FT_Stream stream,
+ FT_BASE_DEF( FT_UShort )
+ FT_Stream_ReadUShortLE( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[2];
@@ -558,7 +558,7 @@
}
if ( p )
- result = FT_NEXT_SHORT_LE( p );
+ result = FT_NEXT_USHORT_LE( p );
}
else
goto Fail;
@@ -569,7 +569,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadShortLE:"
+ FT_ERROR(( "FT_Stream_ReadUShortLE:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
@@ -577,8 +577,8 @@
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_ReadOffset( FT_Stream stream,
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_ReadUOffset( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[3];
@@ -605,7 +605,7 @@
}
if ( p )
- result = FT_NEXT_OFF3( p );
+ result = FT_NEXT_UOFF3( p );
}
else
goto Fail;
@@ -616,7 +616,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadOffset:"
+ FT_ERROR(( "FT_Stream_ReadUOffset:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
@@ -624,8 +624,8 @@
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_ReadLong( FT_Stream stream,
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_ReadULong( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[4];
@@ -652,7 +652,7 @@
}
if ( p )
- result = FT_NEXT_LONG( p );
+ result = FT_NEXT_ULONG( p );
}
else
goto Fail;
@@ -663,7 +663,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadLong:"
+ FT_ERROR(( "FT_Stream_ReadULong:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
@@ -671,8 +671,8 @@
}
- FT_BASE_DEF( FT_Long )
- FT_Stream_ReadLongLE( FT_Stream stream,
+ FT_BASE_DEF( FT_ULong )
+ FT_Stream_ReadULongLE( FT_Stream stream,
FT_Error* error )
{
FT_Byte reads[4];
@@ -699,7 +699,7 @@
}
if ( p )
- result = FT_NEXT_LONG_LE( p );
+ result = FT_NEXT_ULONG_LE( p );
}
else
goto Fail;
@@ -710,7 +710,7 @@
Fail:
*error = FT_Err_Invalid_Stream_Operation;
- FT_ERROR(( "FT_Stream_ReadLongLE:"
+ FT_ERROR(( "FT_Stream_ReadULongLE:"
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
stream->pos, stream->size ));
diff --git a/freetype/src/base/ftstroke.c b/freetype/src/base/ftstroke.c
index 20c1d03fc..1f7c96fa9 100644
--- a/freetype/src/base/ftstroke.c
+++ b/freetype/src/base/ftstroke.c
@@ -4,7 +4,7 @@
/* */
/* FreeType path stroker (body). */
/* */
-/* Copyright 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010 by */
+/* Copyright 2002-2006, 2008-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -704,7 +704,6 @@
FT_Fixed miter_limit;
FT_Fixed radius;
- FT_Bool valid;
FT_StrokeBorderRec borders[2];
FT_Library library;
@@ -719,7 +718,7 @@
{
FT_Error error;
FT_Memory memory;
- FT_Stroker stroker;
+ FT_Stroker stroker = NULL;
if ( !library )
diff --git a/freetype/src/bdf/README b/freetype/src/bdf/README
index e3f2ae386..b761aba2b 100644
--- a/freetype/src/bdf/README
+++ b/freetype/src/bdf/README
@@ -13,7 +13,7 @@ This code implements a BDF driver for the FreeType library, following the
Adobe Specification V 2.2. The specification of the BDF font format is
available from Adobe's web site:
- http://partners.adobe.com/asn/developer/PDFS/TN/5005.BDF_Spec.pdf
+ http://partners.adobe.com/public/developer/en/font/5005.BDF_Spec.pdf
Many good bitmap fonts in bdf format come with XFree86 (www.XFree86.org).
They do not define vertical metrics, because the X Consortium BDF
@@ -119,7 +119,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*** Portions of the driver (that is, bdflib.c and bdf.h):
Copyright 2000 Computing Research Labs, New Mexico State University
-Copyright 2001-2002 Francesco Zappa Nardelli
+Copyright 2001-2002, 2011 Francesco Zappa Nardelli
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/freetype/src/bzip2/Jamfile b/freetype/src/bzip2/Jamfile
new file mode 100644
index 000000000..3da986dce
--- /dev/null
+++ b/freetype/src/bzip2/Jamfile
@@ -0,0 +1,19 @@
+# FreeType 2 src/bzip2 Jamfile
+#
+# Copyright 2010 by
+# Joel Klinghed
+#
+# Based on src/lzw/Jamfile, Copyright 2004, 2006 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 license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+SubDir FT2_TOP $(FT2_SRC_DIR) bzip2 ;
+
+Library $(FT2_LIB) : ftbzip2.c ;
+
+# end of src/bzip2 Jamfile
diff --git a/freetype/src/bzip2/ftbzip2.c b/freetype/src/bzip2/ftbzip2.c
new file mode 100644
index 000000000..e443dc85e
--- /dev/null
+++ b/freetype/src/bzip2/ftbzip2.c
@@ -0,0 +1,510 @@
+/***************************************************************************/
+/* */
+/* ftbzip2.c */
+/* */
+/* FreeType support for .bz2 compressed files. */
+/* */
+/* This optional component relies on libbz2. It should mainly be used to */
+/* parse compressed PCF fonts, as found with many X11 server */
+/* distributions. */
+/* */
+/* Copyright 2010 by */
+/* Joel Klinghed. */
+/* */
+/* Based on src/gzip/ftgzip.c, Copyright 2002 - 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 */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_BZIP2_H
+#include FT_CONFIG_STANDARD_LIBRARY_H
+
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX Bzip2_Err_
+#define FT_ERR_BASE FT_Mod_Err_Bzip2
+
+#include FT_ERRORS_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_BZIP2
+
+#ifdef FT_CONFIG_OPTION_PIC
+#error "bzip2 code does not support PIC yet"
+#endif
+
+#define BZ_NO_STDIO /* Do not need FILE */
+#include <bzlib.h>
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** B Z I P 2 M E M O R Y M A N A G E M E N T *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+ /* it is better to use FreeType memory routines instead of raw
+ 'malloc/free' */
+
+ typedef void *(* alloc_func)(void*, int, int);
+ typedef void (* free_func)(void*, void*);
+
+ static void*
+ ft_bzip2_alloc( FT_Memory memory,
+ int items,
+ int size )
+ {
+ FT_ULong sz = (FT_ULong)size * items;
+ FT_Error error;
+ FT_Pointer p = NULL;
+
+
+ (void)FT_ALLOC( p, sz );
+ return p;
+ }
+
+
+ static void
+ ft_bzip2_free( FT_Memory memory,
+ void* address )
+ {
+ FT_MEM_FREE( address );
+ }
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** B Z I P 2 F I L E D E S C R I P T O R *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+#define FT_BZIP2_BUFFER_SIZE 4096
+
+ typedef struct FT_BZip2FileRec_
+ {
+ FT_Stream source; /* parent/source stream */
+ FT_Stream stream; /* embedding stream */
+ FT_Memory memory; /* memory allocator */
+ bz_stream bzstream; /* bzlib input stream */
+
+ FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */
+
+ FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */
+ FT_ULong pos; /* position in output */
+ FT_Byte* cursor;
+ FT_Byte* limit;
+
+ } FT_BZip2FileRec, *FT_BZip2File;
+
+
+ /* check and skip .bz2 header - we don't support `transparent' compression */
+ static FT_Error
+ ft_bzip2_check_header( FT_Stream stream )
+ {
+ FT_Error error = Bzip2_Err_Ok;
+ FT_Byte head[4];
+
+
+ if ( FT_STREAM_SEEK( 0 ) ||
+ FT_STREAM_READ( head, 4 ) )
+ goto Exit;
+
+ /* head[0] && head[1] are the magic numbers; */
+ /* head[2] is the version, and head[3] the blocksize */
+ if ( head[0] != 0x42 ||
+ head[1] != 0x5a ||
+ head[2] != 0x68 ) /* only support bzip2 (huffman) */
+ {
+ error = Bzip2_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ ft_bzip2_file_init( FT_BZip2File zip,
+ FT_Stream stream,
+ FT_Stream source )
+ {
+ bz_stream* bzstream = &zip->bzstream;
+ FT_Error error = Bzip2_Err_Ok;
+
+
+ zip->stream = stream;
+ zip->source = source;
+ zip->memory = stream->memory;
+
+ zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+
+ /* check .bz2 header */
+ {
+ stream = source;
+
+ error = ft_bzip2_check_header( stream );
+ if ( error )
+ goto Exit;
+
+ if ( FT_STREAM_SEEK( 0 ) )
+ goto Exit;
+ }
+
+ /* initialize bzlib */
+ bzstream->bzalloc = (alloc_func)ft_bzip2_alloc;
+ bzstream->bzfree = (free_func) ft_bzip2_free;
+ bzstream->opaque = zip->memory;
+
+ bzstream->avail_in = 0;
+ bzstream->next_in = (char*)zip->buffer;
+
+ if ( BZ2_bzDecompressInit( bzstream, 0, 0 ) != BZ_OK ||
+ bzstream->next_in == NULL )
+ error = Bzip2_Err_Invalid_File_Format;
+
+ Exit:
+ return error;
+ }
+
+
+ static void
+ ft_bzip2_file_done( FT_BZip2File zip )
+ {
+ bz_stream* bzstream = &zip->bzstream;
+
+
+ BZ2_bzDecompressEnd( bzstream );
+
+ /* clear the rest */
+ bzstream->bzalloc = NULL;
+ bzstream->bzfree = NULL;
+ bzstream->opaque = NULL;
+ bzstream->next_in = NULL;
+ bzstream->next_out = NULL;
+ bzstream->avail_in = 0;
+ bzstream->avail_out = 0;
+
+ zip->memory = NULL;
+ zip->source = NULL;
+ zip->stream = NULL;
+ }
+
+
+ static FT_Error
+ ft_bzip2_file_reset( FT_BZip2File zip )
+ {
+ FT_Stream stream = zip->source;
+ FT_Error error;
+
+
+ if ( !FT_STREAM_SEEK( 0 ) )
+ {
+ bz_stream* bzstream = &zip->bzstream;
+
+
+ BZ2_bzDecompressEnd( bzstream );
+
+ bzstream->avail_in = 0;
+ bzstream->next_in = (char*)zip->input;
+ bzstream->avail_out = 0;
+ bzstream->next_out = (char*)zip->buffer;
+
+ zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
+ zip->cursor = zip->limit;
+ zip->pos = 0;
+
+ BZ2_bzDecompressInit( bzstream, 0, 0 );
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ ft_bzip2_file_fill_input( FT_BZip2File zip )
+ {
+ bz_stream* bzstream = &zip->bzstream;
+ FT_Stream stream = zip->source;
+ FT_ULong size;
+
+
+ if ( stream->read )
+ {
+ size = stream->read( stream, stream->pos, zip->input,
+ FT_BZIP2_BUFFER_SIZE );
+ if ( size == 0 )
+ return Bzip2_Err_Invalid_Stream_Operation;
+ }
+ else
+ {
+ size = stream->size - stream->pos;
+ if ( size > FT_BZIP2_BUFFER_SIZE )
+ size = FT_BZIP2_BUFFER_SIZE;
+
+ if ( size == 0 )
+ return Bzip2_Err_Invalid_Stream_Operation;
+
+ FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
+ }
+ stream->pos += size;
+
+ bzstream->next_in = (char*)zip->input;
+ bzstream->avail_in = size;
+
+ return Bzip2_Err_Ok;
+ }
+
+
+ static FT_Error
+ ft_bzip2_file_fill_output( FT_BZip2File zip )
+ {
+ bz_stream* bzstream = &zip->bzstream;
+ FT_Error error = Bzip2_Err_Ok;
+
+
+ zip->cursor = zip->buffer;
+ bzstream->next_out = (char*)zip->cursor;
+ bzstream->avail_out = FT_BZIP2_BUFFER_SIZE;
+
+ while ( bzstream->avail_out > 0 )
+ {
+ int err;
+
+
+ if ( bzstream->avail_in == 0 )
+ {
+ error = ft_bzip2_file_fill_input( zip );
+ if ( error )
+ break;
+ }
+
+ err = BZ2_bzDecompress( bzstream );
+
+ if ( err == BZ_STREAM_END )
+ {
+ zip->limit = (FT_Byte*)bzstream->next_out;
+ if ( zip->limit == zip->cursor )
+ error = Bzip2_Err_Invalid_Stream_Operation;
+ break;
+ }
+ else if ( err != BZ_OK )
+ {
+ error = Bzip2_Err_Invalid_Stream_Operation;
+ break;
+ }
+ }
+
+ return error;
+ }
+
+
+ /* fill output buffer; `count' must be <= FT_BZIP2_BUFFER_SIZE */
+ static FT_Error
+ ft_bzip2_file_skip_output( FT_BZip2File zip,
+ FT_ULong count )
+ {
+ FT_Error error = Bzip2_Err_Ok;
+ FT_ULong delta;
+
+
+ for (;;)
+ {
+ delta = (FT_ULong)( zip->limit - zip->cursor );
+ if ( delta >= count )
+ delta = count;
+
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ if ( count == 0 )
+ break;
+
+ error = ft_bzip2_file_fill_output( zip );
+ if ( error )
+ break;
+ }
+
+ return error;
+ }
+
+
+ static FT_ULong
+ ft_bzip2_file_io( FT_BZip2File zip,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_ULong result = 0;
+ FT_Error error;
+
+
+ /* Reset inflate stream if we're seeking backwards. */
+ /* Yes, that is not too efficient, but it saves memory :-) */
+ if ( pos < zip->pos )
+ {
+ error = ft_bzip2_file_reset( zip );
+ if ( error )
+ goto Exit;
+ }
+
+ /* skip unwanted bytes */
+ if ( pos > zip->pos )
+ {
+ error = ft_bzip2_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( count == 0 )
+ goto Exit;
+
+ /* now read the data */
+ for (;;)
+ {
+ FT_ULong delta;
+
+
+ delta = (FT_ULong)( zip->limit - zip->cursor );
+ if ( delta >= count )
+ delta = count;
+
+ FT_MEM_COPY( buffer, zip->cursor, delta );
+ buffer += delta;
+ result += delta;
+ zip->cursor += delta;
+ zip->pos += delta;
+
+ count -= delta;
+ if ( count == 0 )
+ break;
+
+ error = ft_bzip2_file_fill_output( zip );
+ if ( error )
+ break;
+ }
+
+ Exit:
+ return result;
+ }
+
+
+/***************************************************************************/
+/***************************************************************************/
+/***** *****/
+/***** B Z E M B E D D I N G S T R E A M *****/
+/***** *****/
+/***************************************************************************/
+/***************************************************************************/
+
+ static void
+ ft_bzip2_stream_close( FT_Stream stream )
+ {
+ FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
+ FT_Memory memory = stream->memory;
+
+
+ if ( zip )
+ {
+ /* finalize bzip file descriptor */
+ ft_bzip2_file_done( zip );
+
+ FT_FREE( zip );
+
+ stream->descriptor.pointer = NULL;
+ }
+ }
+
+
+ static FT_ULong
+ ft_bzip2_stream_io( FT_Stream stream,
+ FT_ULong pos,
+ FT_Byte* buffer,
+ FT_ULong count )
+ {
+ FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
+
+
+ return ft_bzip2_file_io( zip, pos, buffer, count );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stream_OpenBzip2( FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_Error error;
+ FT_Memory memory = source->memory;
+ FT_BZip2File zip = NULL;
+
+
+ /*
+ * check the header right now; this prevents allocating unnecessary
+ * objects when we don't need them
+ */
+ error = ft_bzip2_check_header( source );
+ if ( error )
+ goto Exit;
+
+ FT_ZERO( stream );
+ stream->memory = memory;
+
+ if ( !FT_QNEW( zip ) )
+ {
+ error = ft_bzip2_file_init( zip, stream, source );
+ if ( error )
+ {
+ FT_FREE( zip );
+ goto Exit;
+ }
+
+ stream->descriptor.pointer = zip;
+ }
+
+ stream->size = 0x7FFFFFFFL; /* don't know the real size! */
+ stream->pos = 0;
+ stream->base = 0;
+ stream->read = ft_bzip2_stream_io;
+ stream->close = ft_bzip2_stream_close;
+
+ Exit:
+ return error;
+ }
+
+#else /* !FT_CONFIG_OPTION_USE_BZIP2 */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Stream_OpenBzip2( FT_Stream stream,
+ FT_Stream source )
+ {
+ FT_UNUSED( stream );
+ FT_UNUSED( source );
+
+ return Bzip2_Err_Unimplemented_Feature;
+ }
+
+#endif /* !FT_CONFIG_OPTION_USE_BZIP2 */
+
+
+/* END */
diff --git a/freetype/src/bzip2/rules.mk b/freetype/src/bzip2/rules.mk
new file mode 100644
index 000000000..0ff2628b4
--- /dev/null
+++ b/freetype/src/bzip2/rules.mk
@@ -0,0 +1,63 @@
+#
+# FreeType 2 BZIP2 support configuration rules
+#
+
+# Copyright 2010 by
+# Joel Klinghed.
+#
+# Based on src/lzw/rules.mk, Copyright 2004-2006 by
+# Albert Chin-A-Young.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# BZIP2 driver directory
+#
+BZIP2_DIR := $(SRC_DIR)/bzip2
+
+
+# compilation flags for the driver
+#
+BZIP2_COMPILE := $(FT_COMPILE)
+
+
+# BZIP2 support sources (i.e., C files)
+#
+BZIP2_DRV_SRC := $(BZIP2_DIR)/ftbzip2.c
+
+# BZIP2 driver object(s)
+#
+# BZIP2_DRV_OBJ_M is used during `multi' builds
+# BZIP2_DRV_OBJ_S is used during `single' builds
+#
+BZIP2_DRV_OBJ_M := $(OBJ_DIR)/ftbzip2.$O
+BZIP2_DRV_OBJ_S := $(OBJ_DIR)/ftbzip2.$O
+
+# BZIP2 support source file for single build
+#
+BZIP2_DRV_SRC_S := $(BZIP2_DIR)/ftbzip2.c
+
+
+# BZIP2 support - single object
+#
+$(BZIP2_DRV_OBJ_S): $(BZIP2_DRV_SRC_S) $(BZIP2_DRV_SRC) $(FREETYPE_H) $(BZIP2_DRV_H)
+ $(BZIP2_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(BZIP2_DRV_SRC_S))
+
+
+# BZIP2 support - multiple objects
+#
+$(OBJ_DIR)/%.$O: $(BZIP2_DIR)/%.c $(FREETYPE_H) $(BZIP2_DRV_H)
+ $(BZIP2_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(BZIP2_DRV_OBJ_S)
+DRV_OBJS_M += $(BZIP2_DRV_OBJ_M)
+
+
+# EOF
diff --git a/freetype/src/cache/ftcbasic.c b/freetype/src/cache/ftcbasic.c
index 7c2ecb5c1..3749cd753 100644
--- a/freetype/src/cache/ftcbasic.c
+++ b/freetype/src/cache/ftcbasic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType basic cache interface (body). */
/* */
-/* Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/* Copyright 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,6 +17,7 @@
#include <ft2build.h>
+#include <freetype/internal/objects.h>
#include <freetype/internal/ftdebug.h>
#include FT_CACHE_H
#include "ftcglyph.h"
@@ -237,7 +238,8 @@
FT_CALLBACK_DEF( FT_Bool )
ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode,
FT_Pointer ftcface_id,
- FTC_Cache cache )
+ FTC_Cache cache,
+ FT_Bool* list_changed )
{
FTC_GNode gnode = (FTC_GNode)ftcgnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
@@ -245,6 +247,8 @@
FT_Bool result;
+ if ( list_changed )
+ *list_changed = FALSE;
result = FT_BOOL( family->attrs.scaler.face_id == face_id );
if ( result )
{
diff --git a/freetype/src/cache/ftccache.c b/freetype/src/cache/ftccache.c
index c503f4955..3af33a2e3 100644
--- a/freetype/src/cache/ftccache.c
+++ b/freetype/src/cache/ftccache.c
@@ -4,7 +4,8 @@
/* */
/* The FreeType internal cache interface (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, */
+/* 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -32,7 +33,7 @@
#define FTC_HASH_MIN_LOAD 1
#define FTC_HASH_SUB_LOAD ( FTC_HASH_MAX_LOAD - FTC_HASH_MIN_LOAD )
-/* this one _must_ be a power of 2! */
+ /* this one _must_ be a power of 2! */
#define FTC_HASH_INITIAL_SIZE 8
@@ -83,6 +84,25 @@
(FTC_MruNode)node );
}
+
+ /* get a top bucket for specified hash from cache,
+ * body for FTC_NODE__TOP_FOR_HASH( cache, hash )
+ */
+ FT_LOCAL_DEF( FTC_Node* )
+ ftc_get_top_node_for_hash( FTC_Cache cache,
+ FT_PtrDist hash )
+ {
+ FTC_Node* pnode;
+ FT_UInt idx;
+
+
+ idx = (FT_UInt)( hash & cache->mask );
+ if ( idx < cache->p )
+ idx = (FT_UInt)( hash & ( 2 * cache->mask + 1 ) );
+ pnode = cache->buckets + idx;
+ return pnode;
+ }
+
#endif /* !FTC_INLINE */
@@ -96,9 +116,9 @@
for (;;)
{
FTC_Node node, *pnode;
- FT_UFast p = cache->p;
- FT_UFast mask = cache->mask;
- FT_UFast count = mask + p + 1; /* number of buckets */
+ FT_UFast p = cache->p;
+ FT_UFast mask = cache->mask;
+ FT_UFast count = mask + p + 1; /* number of buckets */
/* do we need to shrink the buckets array? */
@@ -117,7 +137,8 @@
/* if we can't expand the array, leave immediately */
- if ( FT_RENEW_ARRAY( cache->buckets, (mask+1)*2, (mask+1)*4 ) )
+ if ( FT_RENEW_ARRAY( cache->buckets,
+ ( mask + 1 ) * 2, ( mask + 1 ) * 4 ) )
break;
}
@@ -191,7 +212,9 @@
cache->slack -= FTC_HASH_MAX_LOAD;
cache->p = p;
}
- else /* the hash table is balanced */
+
+ /* otherwise, the hash table is balanced */
+ else
break;
}
}
@@ -202,15 +225,8 @@
ftc_node_hash_unlink( FTC_Node node0,
FTC_Cache cache )
{
- FTC_Node *pnode;
- FT_UInt idx;
-
-
- idx = (FT_UInt)( node0->hash & cache->mask );
- if ( idx < cache->p )
- idx = (FT_UInt)( node0->hash & ( 2 * cache->mask + 1 ) );
+ FTC_Node *pnode = FTC_NODE__TOP_FOR_HASH( cache, node0->hash );
- pnode = cache->buckets + idx;
for (;;)
{
@@ -242,16 +258,9 @@
ftc_node_hash_link( FTC_Node node,
FTC_Cache cache )
{
- FTC_Node *pnode;
- FT_UInt idx;
+ FTC_Node *pnode = FTC_NODE__TOP_FOR_HASH( cache, node->hash );
- idx = (FT_UInt)( node->hash & cache->mask );
- if ( idx < cache->p )
- idx = (FT_UInt)( node->hash & (2 * cache->mask + 1 ) );
-
- pnode = cache->buckets + idx;
-
node->link = *pnode;
*pnode = node;
@@ -413,8 +422,8 @@
FT_PtrDist hash,
FTC_Node node )
{
- node->hash = hash;
- node->cache_index = (FT_UInt16) cache->index;
+ node->hash = hash;
+ node->cache_index = (FT_UInt16)cache->index;
node->ref_count = 0;
ftc_node_hash_link( node, cache );
@@ -456,7 +465,7 @@
{
error = cache->clazz.node_new( &node, query, cache );
}
- FTC_CACHE_TRYLOOP_END();
+ FTC_CACHE_TRYLOOP_END( NULL );
if ( error )
node = NULL;
@@ -481,11 +490,11 @@
FT_Pointer query,
FTC_Node *anode )
{
- FT_UFast idx;
FTC_Node* bucket;
FTC_Node* pnode;
FTC_Node node;
- FT_Error error = FTC_Err_Ok;
+ FT_Error error = FTC_Err_Ok;
+ FT_Bool list_changed = FALSE;
FTC_Node_CompareFunc compare = cache->clazz.node_compare;
@@ -493,24 +502,43 @@
if ( cache == NULL || anode == NULL )
return FTC_Err_Invalid_Argument;
- idx = hash & cache->mask;
- if ( idx < cache->p )
- idx = hash & ( cache->mask * 2 + 1 );
+ /* Go to the `top' node of the list sharing same masked hash */
+ bucket = pnode = FTC_NODE__TOP_FOR_HASH( cache, hash );
- bucket = cache->buckets + idx;
- pnode = bucket;
+ /* Lookup a node with exactly same hash and queried properties. */
+ /* NOTE: _nodcomp() may change the linked list to reduce memory. */
for (;;)
{
node = *pnode;
if ( node == NULL )
goto NewNode;
- if ( node->hash == hash && compare( node, query, cache ) )
+ if ( node->hash == hash &&
+ compare( node, query, cache, &list_changed ) )
break;
pnode = &node->link;
}
+ if ( list_changed )
+ {
+ /* Update bucket by modified linked list */
+ bucket = pnode = FTC_NODE__TOP_FOR_HASH( cache, hash );
+
+ /* Update pnode by modified linked list */
+ while ( *pnode != node )
+ {
+ if ( *pnode == NULL )
+ {
+ FT_ERROR(( "FTC_Cache_Lookup: oops!!! node missing\n" ));
+ goto NewNode;
+ }
+ else
+ pnode = &((*pnode)->link);
+ }
+ }
+
+ /* Reorder the list to move the found node to the `top' */
if ( node != *bucket )
{
*pnode = node->link;
@@ -527,6 +555,7 @@
ftc_node_mru_up( node, manager );
}
*anode = node;
+
return error;
NewNode:
@@ -545,7 +574,7 @@
FTC_Node frees = NULL;
- count = cache->p + cache->mask;
+ count = cache->p + cache->mask + 1;
for ( i = 0; i < count; i++ )
{
FTC_Node* bucket = cache->buckets + i;
@@ -555,12 +584,14 @@
for ( ;; )
{
FTC_Node node = *pnode;
+ FT_Bool list_changed = FALSE;
if ( node == NULL )
break;
- if ( cache->clazz.node_remove_faceid( node, face_id, cache ) )
+ if ( cache->clazz.node_remove_faceid( node, face_id,
+ cache, &list_changed ) )
{
*pnode = node->link;
node->link = frees;
diff --git a/freetype/src/cache/ftccache.h b/freetype/src/cache/ftccache.h
index 10830a9f8..d60984f77 100644
--- a/freetype/src/cache/ftccache.h
+++ b/freetype/src/cache/ftccache.h
@@ -4,7 +4,8 @@
/* */
/* FreeType internal cache interface (specification). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, */
+/* 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -24,7 +25,7 @@
FT_BEGIN_HEADER
-#define _FTC_FACE_ID_HASH( i ) \
+#define _FTC_FACE_ID_HASH( i ) \
((FT_PtrDist)(( (FT_PtrDist)(i) >> 3 ) ^ ( (FT_PtrDist)(i) << 7 )))
/* handle to cache object */
@@ -72,6 +73,19 @@ FT_BEGIN_HEADER
#define FTC_NODE__NEXT( x ) FTC_NODE( (x)->mru.next )
#define FTC_NODE__PREV( x ) FTC_NODE( (x)->mru.prev )
+#ifdef FTC_INLINE
+#define FTC_NODE__TOP_FOR_HASH( cache, hash ) \
+ ( ( cache )->buckets + \
+ ( ( ( ( hash ) & ( cache )->mask ) < ( cache )->p ) \
+ ? ( ( hash ) & ( ( cache )->mask * 2 + 1 ) ) \
+ : ( ( hash ) & ( cache )->mask ) ) )
+#else
+ FT_LOCAL( FTC_Node* )
+ ftc_get_top_node_for_hash( FTC_Cache cache,
+ FT_PtrDist hash );
+#define FTC_NODE__TOP_FOR_HASH( cache, hash ) \
+ ftc_get_top_node_for_hash( ( cache ), ( hash ) )
+#endif
#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
FT_BASE( void )
@@ -102,7 +116,8 @@ FT_BEGIN_HEADER
typedef FT_Bool
(*FTC_Node_CompareFunc)( FTC_Node node,
FT_Pointer key,
- FTC_Cache cache );
+ FTC_Cache cache,
+ FT_Bool* list_changed );
typedef void
@@ -162,7 +177,7 @@ FT_BEGIN_HEADER
FT_LOCAL( void )
FTC_Cache_Done( FTC_Cache cache );
- /* Call this function to lookup the cache. If no corresponding
+ /* Call this function to look up the cache. If no corresponding
* node is found, a new one is automatically created. This function
* is capable of flushing the cache adequately to make room for the
* new cache object.
@@ -184,7 +199,7 @@ FT_BEGIN_HEADER
/* Remove all nodes that relate to a given face_id. This is useful
* when un-installing fonts. Note that if a cache node relates to
- * the face_id, but is locked (i.e., has `ref_count > 0'), the node
+ * the face_id but is locked (i.e., has `ref_count > 0'), the node
* will _not_ be destroyed, but its internal face_id reference will
* be modified.
*
@@ -205,28 +220,49 @@ FT_BEGIN_HEADER
FTC_Cache _cache = FTC_CACHE(cache); \
FT_PtrDist _hash = (FT_PtrDist)(hash); \
FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
- FT_UFast _idx; \
+ FT_Bool _list_changed = FALSE; \
\
\
error = FTC_Err_Ok; \
node = NULL; \
- _idx = _hash & _cache->mask; \
- if ( _idx < _cache->p ) \
- _idx = _hash & ( _cache->mask*2 + 1 ); \
\
- _bucket = _pnode = _cache->buckets + _idx; \
+ /* Go to the `top' node of the list sharing same masked hash */ \
+ _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \
+ \
+ /* Look up a node with identical hash and queried properties. */ \
+ /* NOTE: _nodcomp() may change the linked list to reduce memory. */ \
for (;;) \
{ \
_node = *_pnode; \
if ( _node == NULL ) \
goto _NewNode; \
\
- if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \
+ if ( _node->hash == _hash && \
+ _nodcomp( _node, query, _cache, &_list_changed ) ) \
break; \
\
_pnode = &_node->link; \
} \
\
+ if ( _list_changed ) \
+ { \
+ /* Update _bucket by possibly modified linked list */ \
+ _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \
+ \
+ /* Update _pnode by possibly modified linked list */ \
+ while ( *_pnode != _node ) \
+ { \
+ if ( *_pnode == NULL ) \
+ { \
+ FT_ERROR(( "FTC_CACHE_LOOKUP_CMP: oops!!! node missing\n" )); \
+ goto _NewNode; \
+ } \
+ else \
+ _pnode = &((*_pnode)->link); \
+ } \
+ } \
+ \
+ /* Reorder the list to move the found node to the `top' */ \
if ( _node != *_bucket ) \
{ \
*_pnode = _node->link; \
@@ -234,6 +270,7 @@ FT_BEGIN_HEADER
*_bucket = _node; \
} \
\
+ /* Update MRU list */ \
{ \
FTC_Manager _manager = _cache->manager; \
void* _nl = &_manager->nodes_list; \
@@ -268,7 +305,7 @@ FT_BEGIN_HEADER
* loop to flush the cache repeatedly in case of memory overflows.
*
* It is used when creating a new cache node, or within a lookup
- * that needs to allocate data (e.g., the sbit cache lookup).
+ * that needs to allocate data (e.g. the sbit cache lookup).
*
* Example:
*
@@ -290,11 +327,14 @@ FT_BEGIN_HEADER
FT_UInt _try_done;
-#define FTC_CACHE_TRYLOOP_END() \
+#define FTC_CACHE_TRYLOOP_END( list_changed ) \
if ( !error || error != FTC_Err_Out_Of_Memory ) \
break; \
\
_try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
+ if ( _try_done > 0 && ( list_changed ) ) \
+ *(FT_Bool*)( list_changed ) = TRUE; \
+ \
if ( _try_done == 0 ) \
break; \
\
diff --git a/freetype/src/cache/ftccback.h b/freetype/src/cache/ftccback.h
index 4d0818db2..80ec9ce44 100644
--- a/freetype/src/cache/ftccback.h
+++ b/freetype/src/cache/ftccback.h
@@ -4,7 +4,7 @@
/* */
/* Callback functions of the caching sub-system (specification only). */
/* */
-/* Copyright 2004, 2005, 2006 by */
+/* Copyright 2004, 2005, 2006, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -57,13 +57,15 @@
FT_LOCAL( FT_Bool )
ftc_snode_compare( FTC_Node snode,
FT_Pointer gquery,
- FTC_Cache cache );
+ FTC_Cache cache,
+ FT_Bool* list_changed );
FT_LOCAL( FT_Bool )
ftc_gnode_compare( FTC_Node gnode,
FT_Pointer gquery,
- FTC_Cache cache );
+ FTC_Cache cache,
+ FT_Bool* list_changed );
FT_LOCAL( FT_Error )
diff --git a/freetype/src/cache/ftccmap.c b/freetype/src/cache/ftccmap.c
index 6a3962f08..61c33c23f 100644
--- a/freetype/src/cache/ftccmap.c
+++ b/freetype/src/cache/ftccmap.c
@@ -5,7 +5,7 @@
/* FreeType CharMap cache (body) */
/* */
/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* 2010, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,6 +22,7 @@
#include FT_CACHE_H
#include "ftcmanag.h"
#include <freetype/internal/ftmemory.h>
+#include <freetype/internal/objects.h>
#include <freetype/internal/ftdebug.h>
#include "ftccback.h"
@@ -190,13 +191,16 @@
FT_CALLBACK_DEF( FT_Bool )
ftc_cmap_node_compare( FTC_Node ftcnode,
FT_Pointer ftcquery,
- FTC_Cache cache )
+ FTC_Cache cache,
+ FT_Bool* list_changed )
{
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
FTC_CMapQuery query = (FTC_CMapQuery)ftcquery;
FT_UNUSED( cache );
+ if ( list_changed )
+ *list_changed = FALSE;
if ( node->face_id == query->face_id &&
node->cmap_index == query->cmap_index )
{
@@ -213,12 +217,16 @@
FT_CALLBACK_DEF( FT_Bool )
ftc_cmap_node_remove_faceid( FTC_Node ftcnode,
FT_Pointer ftcface_id,
- FTC_Cache cache )
+ FTC_Cache cache,
+ FT_Bool* list_changed )
{
FTC_CMapNode node = (FTC_CMapNode)ftcnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
FT_UNUSED( cache );
+
+ if ( list_changed )
+ *list_changed = FALSE;
return FT_BOOL( node->face_id == face_id );
}
diff --git a/freetype/src/cache/ftcglyph.c b/freetype/src/cache/ftcglyph.c
index a73e2431e..441e17723 100644
--- a/freetype/src/cache/ftcglyph.c
+++ b/freetype/src/cache/ftcglyph.c
@@ -4,7 +4,7 @@
/* */
/* FreeType Glyph Image (FT_Glyph) cache (body). */
/* */
-/* Copyright 2000-2001, 2003, 2004, 2006, 2009 by */
+/* Copyright 2000-2001, 2003, 2004, 2006, 2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,6 +17,7 @@
#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
#include FT_CACHE_H
#include "ftcglyph.h"
#include FT_ERRORS_H
@@ -64,25 +65,34 @@
FT_LOCAL_DEF( FT_Bool )
ftc_gnode_compare( FTC_Node ftcgnode,
FT_Pointer ftcgquery,
- FTC_Cache cache )
+ FTC_Cache cache,
+ FT_Bool* list_changed )
{
FTC_GNode gnode = (FTC_GNode)ftcgnode;
FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
FT_UNUSED( cache );
+ if ( list_changed )
+ *list_changed = FALSE;
return FT_BOOL( gnode->family == gquery->family &&
gnode->gindex == gquery->gindex );
}
+#ifdef FTC_INLINE
+
FT_LOCAL_DEF( FT_Bool )
FTC_GNode_Compare( FTC_GNode gnode,
- FTC_GQuery gquery )
+ FTC_GQuery gquery,
+ FTC_Cache cache,
+ FT_Bool* list_changed )
{
- return ftc_gnode_compare( FTC_NODE( gnode ), gquery, NULL );
+ return ftc_gnode_compare( FTC_NODE( gnode ), gquery,
+ cache, list_changed );
}
+#endif
/*************************************************************************/
/*************************************************************************/
diff --git a/freetype/src/cache/ftcglyph.h b/freetype/src/cache/ftcglyph.h
index 2bc5624c6..5fed19cb8 100644
--- a/freetype/src/cache/ftcglyph.h
+++ b/freetype/src/cache/ftcglyph.h
@@ -4,7 +4,7 @@
/* */
/* FreeType abstract glyph cache (specification). */
/* */
-/* Copyright 2000-2001, 2003, 2004, 2006, 2007 by */
+/* Copyright 2000-2001, 2003, 2004, 2006, 2007, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -180,12 +180,18 @@ FT_BEGIN_HEADER
FT_UInt gindex, /* glyph index for node */
FTC_Family family );
+#ifdef FTC_INLINE
+
/* returns TRUE iff the query's glyph index correspond to the node; */
/* this assumes that the `family' and `hash' fields of the query are */
/* already correctly set */
FT_LOCAL( FT_Bool )
FTC_GNode_Compare( FTC_GNode gnode,
- FTC_GQuery gquery );
+ FTC_GQuery gquery,
+ FTC_Cache cache,
+ FT_Bool* list_changed );
+
+#endif
/* call this function to clear a node's family -- this is necessary */
/* to implement the `node_remove_faceid' cache method correctly */
@@ -307,7 +313,7 @@ FT_BEGIN_HEADER
FT_BEGIN_STMNT \
\
error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, \
- FTC_GQUERY( query ), node ); \
+ FTC_GQUERY( query ), &node ); \
\
FT_END_STMNT
diff --git a/freetype/src/cache/ftcmanag.h b/freetype/src/cache/ftcmanag.h
index 13f26bb10..d6c85162a 100644
--- a/freetype/src/cache/ftcmanag.h
+++ b/freetype/src/cache/ftcmanag.h
@@ -4,7 +4,7 @@
/* */
/* FreeType Cache Manager (specification). */
/* */
-/* Copyright 2000-2001, 2003, 2004, 2006 by */
+/* Copyright 2000-2001, 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, */
diff --git a/freetype/src/cache/ftcmru.c b/freetype/src/cache/ftcmru.c
index 917448998..57783a618 100644
--- a/freetype/src/cache/ftcmru.c
+++ b/freetype/src/cache/ftcmru.c
@@ -161,7 +161,7 @@
*plist = NULL;
}
else if ( node == first )
- *plist = next;
+ *plist = next;
}
@@ -238,7 +238,7 @@
FTC_MruNode *anode )
{
FT_Error error;
- FTC_MruNode node;
+ FTC_MruNode node = NULL;
FT_Memory memory = list->memory;
@@ -264,14 +264,14 @@
list->clazz.node_done( node, list->data );
}
else if ( FT_ALLOC( node, list->clazz.node_size ) )
- goto Exit;
+ goto Exit;
error = list->clazz.node_init( node, key, list->data );
if ( error )
goto Fail;
- FTC_MruNode_Prepend( &list->nodes, node );
- list->num_nodes++;
+ FTC_MruNode_Prepend( &list->nodes, node );
+ list->num_nodes++;
Exit:
*anode = node;
@@ -316,7 +316,7 @@
if ( list->clazz.node_done )
- list->clazz.node_done( node, list->data );
+ list->clazz.node_done( node, list->data );
FT_FREE( node );
}
diff --git a/freetype/src/cache/ftcsbits.c b/freetype/src/cache/ftcsbits.c
index 0552ca060..1c14de453 100644
--- a/freetype/src/cache/ftcsbits.c
+++ b/freetype/src/cache/ftcsbits.c
@@ -4,7 +4,7 @@
/* */
/* FreeType sbits manager (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 by */
+/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -217,6 +217,7 @@
FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache );
FT_UInt total;
+ FT_UInt node_count;
total = clazz->family_get_count( family, cache->manager );
@@ -239,6 +240,10 @@
FTC_GNode_Init( FTC_GNODE( snode ), start, family );
snode->count = count;
+ for ( node_count = 0; node_count < count; node_count++ )
+ {
+ snode->sbits[node_count].width = 255;
+ }
error = ftc_snode_load( snode,
cache->manager,
@@ -319,7 +324,8 @@
FT_LOCAL_DEF( FT_Bool )
ftc_snode_compare( FTC_Node ftcsnode,
FT_Pointer ftcgquery,
- FTC_Cache cache )
+ FTC_Cache cache,
+ FT_Bool* list_changed )
{
FTC_SNode snode = (FTC_SNode)ftcsnode;
FTC_GQuery gquery = (FTC_GQuery)ftcgquery;
@@ -328,6 +334,8 @@
FT_Bool result;
+ if (list_changed)
+ *list_changed = FALSE;
result = FT_BOOL( gnode->family == gquery->family &&
(FT_UInt)( gindex - gnode->gindex ) < snode->count );
if ( result )
@@ -368,7 +376,7 @@
*
*/
- if ( sbit->buffer == NULL && sbit->width != 255 )
+ if ( sbit->buffer == NULL && sbit->width == 255 )
{
FT_ULong size;
FT_Error error;
@@ -381,7 +389,7 @@
{
error = ftc_snode_load( snode, cache->manager, gindex, &size );
}
- FTC_CACHE_TRYLOOP_END();
+ FTC_CACHE_TRYLOOP_END( list_changed );
ftcsnode->ref_count--; /* unlock the node */
@@ -396,13 +404,18 @@
}
+#ifdef FTC_INLINE
+
FT_LOCAL_DEF( FT_Bool )
FTC_SNode_Compare( FTC_SNode snode,
FTC_GQuery gquery,
- FTC_Cache cache )
+ FTC_Cache cache,
+ FT_Bool* list_changed )
{
- return ftc_snode_compare( FTC_NODE( snode ), gquery, cache );
+ return ftc_snode_compare( FTC_NODE( snode ), gquery,
+ cache, list_changed );
}
+#endif
/* END */
diff --git a/freetype/src/cache/ftcsbits.h b/freetype/src/cache/ftcsbits.h
index 6261745f1..df55dca80 100644
--- a/freetype/src/cache/ftcsbits.h
+++ b/freetype/src/cache/ftcsbits.h
@@ -4,7 +4,7 @@
/* */
/* A small-bitmap cache (specification). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2006 by */
+/* Copyright 2000-2001, 2002, 2003, 2006, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -83,10 +83,15 @@ FT_BEGIN_HEADER
#endif
+#ifdef FTC_INLINE
+
FT_LOCAL( FT_Bool )
FTC_SNode_Compare( FTC_SNode snode,
FTC_GQuery gquery,
- FTC_Cache cache );
+ FTC_Cache cache,
+ FT_Bool* list_changed);
+
+#endif
/* */
diff --git a/freetype/src/cff/cffdrivr.c b/freetype/src/cff/cffdrivr.c
index 1768e2afe..cf098c396 100644
--- a/freetype/src/cff/cffdrivr.c
+++ b/freetype/src/cff/cffdrivr.c
@@ -328,7 +328,7 @@
if ( cff && cff->font_info == NULL )
{
CFF_FontRecDict dict = &cff->top_font.font_dict;
- PS_FontInfoRec *font_info;
+ PS_FontInfoRec *font_info = NULL;
FT_Memory memory = face->root.memory;
diff --git a/freetype/src/cff/cffgload.c b/freetype/src/cff/cffgload.c
index 6dce4f3a1..1478dee54 100644
--- a/freetype/src/cff/cffgload.c
+++ b/freetype/src/cff/cffgload.c
@@ -4,8 +4,7 @@
/* */
/* OpenType Glyph Loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -1159,8 +1158,8 @@
op = cff_op_flex1;
break;
default:
- /* decrement ip for syntax error message */
- ip--;
+ FT_TRACE4(( " unknown op (12, %d)\n", v ));
+ break;
}
}
break;
@@ -1213,11 +1212,12 @@
op = cff_op_hvcurveto;
break;
default:
+ FT_TRACE4(( " unknown op (%d)\n", v ));
break;
}
if ( op == cff_op_unknown )
- goto Syntax_Error;
+ continue;
/* check arguments */
req_args = cff_argument_counts[op];
@@ -1438,9 +1438,14 @@
FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
: " vlineto\n" ));
- if ( num_args < 1 )
+ if ( num_args < 0 )
goto Stack_Underflow;
+ /* there exist subsetted fonts (found in PDFs) */
+ /* which call `hlineto' without arguments */
+ if ( num_args == 0 )
+ break;
+
if ( cff_builder_start_point ( builder, x, y ) ||
check_points( builder, num_args ) )
goto Fail;
@@ -2701,7 +2706,7 @@
glyph_index );
if ( fd_index >= cff->num_subfonts )
- fd_index = cff->num_subfonts - 1;
+ fd_index = (FT_Byte)( 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;
diff --git a/freetype/src/cff/cffload.c b/freetype/src/cff/cffload.c
index 91ac2f06c..447813027 100644
--- a/freetype/src/cff/cffload.c
+++ b/freetype/src/cff/cffload.c
@@ -387,7 +387,7 @@
{
FT_Error error = CFF_Err_Ok;
FT_Memory memory = idx->stream->memory;
- FT_Byte** t;
+ FT_Byte** t = NULL;
FT_Byte* new_bytes = NULL;
@@ -1514,7 +1514,7 @@
if ( dict->cid_registry != 0xFFFFU )
{
CFF_IndexRec fd_index;
- CFF_SubFont sub;
+ CFF_SubFont sub = NULL;
FT_UInt idx;
diff --git a/freetype/src/cff/cffobjs.c b/freetype/src/cff/cffobjs.c
index bc9778c97..d8bcb98dc 100644
--- a/freetype/src/cff/cffobjs.c
+++ b/freetype/src/cff/cffobjs.c
@@ -4,8 +4,7 @@
/* */
/* OpenType objects manager (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -163,7 +162,7 @@
{
CFF_Face face = (CFF_Face)cffsize->face;
CFF_Font font = (CFF_Font)face->extra.data;
- CFF_Internal internal;
+ CFF_Internal internal = NULL;
PS_PrivateRec priv;
FT_Memory memory = cffsize->face->memory;
@@ -422,6 +421,7 @@
{
for ( idx = 7; idx < length; idx++ )
name[idx - 7] = name[idx];
+ length -= 7;
}
}
else
@@ -430,6 +430,51 @@
}
+ /* Remove the style part from the family name (if present). */
+
+ static void
+ remove_style( FT_String* family_name,
+ const FT_String* style_name )
+ {
+ FT_Int32 family_name_length, style_name_length;
+
+
+ family_name_length = strlen( family_name );
+ style_name_length = strlen( style_name );
+
+ if ( family_name_length > style_name_length )
+ {
+ FT_Int idx;
+
+
+ for ( idx = 1; idx <= style_name_length; ++idx )
+ {
+ if ( family_name[family_name_length - idx] !=
+ style_name[style_name_length - idx] )
+ break;
+ }
+
+ if ( idx > style_name_length )
+ {
+ /* family_name ends with style_name; remove it */
+ idx = family_name_length - style_name_length - 1;
+
+ /* also remove special characters */
+ /* between real family name and style */
+ while ( idx > 0 &&
+ ( family_name[idx] == '-' ||
+ family_name[idx] == ' ' ||
+ family_name[idx] == '_' ||
+ family_name[idx] == '+' ) )
+ --idx;
+
+ if ( idx > 0 )
+ family_name[idx + 1] = '\0';
+ }
+ }
+ }
+
+
FT_LOCAL_DEF( FT_Error )
cff_face_init( FT_Stream stream,
FT_Face cffface, /* CFF_Face */
@@ -437,14 +482,14 @@
FT_Int num_params,
FT_Parameter* params )
{
- CFF_Face face = (CFF_Face)cffface;
+ CFF_Face face = (CFF_Face)cffface;
FT_Error error;
SFNT_Service sfnt;
FT_Service_PsCMaps psnames;
PSHinter_Service pshinter;
FT_Bool pure_cff = 1;
FT_Bool sfnt_format = 0;
- FT_Library library = cffface->driver->root.library;
+ FT_Library library = cffface->driver->root.library;
sfnt = (SFNT_Service)FT_Get_Module_Interface(
@@ -524,7 +569,7 @@
/* now load and parse the CFF table in the file */
{
- CFF_Font cff;
+ CFF_Font cff = NULL;
CFF_FontRecDict dict;
FT_Memory memory = cffface->memory;
FT_Int32 flags;
@@ -759,6 +804,9 @@
/* case, the remaining string in `fullp' will be used as */
/* the style name. */
style_name = cff_strcpy( memory, fullp );
+
+ /* remove the style part from the family name (if present) */
+ remove_style( cffface->family_name, style_name );
}
break;
}
diff --git a/freetype/src/cff/cfftypes.h b/freetype/src/cff/cfftypes.h
index 4dc78a51e..eba1b10ec 100644
--- a/freetype/src/cff/cfftypes.h
+++ b/freetype/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, 2010 by */
+/* Copyright 1996-2003, 2006-2008, 2010-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -212,8 +212,7 @@ FT_BEGIN_HEADER
} CFF_SubFontRec, *CFF_SubFont;
- /* maximum number of sub-fonts in a CID-keyed file */
-#define CFF_MAX_CID_FONTS 32
+#define CFF_MAX_CID_FONTS 256
typedef struct CFF_FontRec_
diff --git a/freetype/src/cff/rules.mk b/freetype/src/cff/rules.mk
index 4100c8068..ca7aa5de8 100644
--- a/freetype/src/cff/rules.mk
+++ b/freetype/src/cff/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2000, 2001, 2003 by
+# Copyright 1996-2000, 2001, 2003, 2011 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -23,19 +23,20 @@ CFF_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(CFF_DIR))
# CFF driver sources (i.e., C files)
#
-CFF_DRV_SRC := $(CFF_DIR)/cffobjs.c \
- $(CFF_DIR)/cffload.c \
+CFF_DRV_SRC := $(CFF_DIR)/cffcmap.c \
+ $(CFF_DIR)/cffdrivr.c \
$(CFF_DIR)/cffgload.c \
+ $(CFF_DIR)/cffload.c \
+ $(CFF_DIR)/cffobjs.c \
$(CFF_DIR)/cffparse.c \
- $(CFF_DIR)/cffcmap.c \
- $(CFF_DIR)/cffdrivr.c
+ $(CFF_DIR)/cffpic.c
# CFF driver headers
#
CFF_DRV_H := $(CFF_DRV_SRC:%.c=%.h) \
+ $(CFF_DIR)/cfferrs.h \
$(CFF_DIR)/cfftoken.h \
- $(CFF_DIR)/cfftypes.h \
- $(CFF_DIR)/cfferrs.h
+ $(CFF_DIR)/cfftypes.h
# CFF driver object(s)
diff --git a/freetype/src/gxvalid/gxvcommn.c b/freetype/src/gxvalid/gxvcommn.c
index 211f97201..d3c48d4ea 100644
--- a/freetype/src/gxvalid/gxvcommn.c
+++ b/freetype/src/gxvalid/gxvcommn.c
@@ -304,8 +304,7 @@
binSrchHeader->unitSize, binSrchHeader->nUnits,
searchRange, entrySelector, rangeShift ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
}
@@ -442,8 +441,7 @@
{
GXV_TRACE(( "too short, glyphs %d - %d are missing\n",
i, valid->face->num_glyphs ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
break;
}
@@ -531,8 +529,7 @@
GXV_TRACE(( "reverse ordered segment specification:"
" lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
unit, lastGlyph, unit - 1 , gid ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
if ( lastGlyph < firstGlyph )
@@ -540,8 +537,7 @@
GXV_TRACE(( "reverse ordered range specification at unit %d:",
" lastGlyph %d < firstGlyph %d ",
unit, lastGlyph, firstGlyph ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
if ( valid->root->level == FT_VALIDATE_TIGHT )
continue; /* ftxvalidator silently skips such an entry */
@@ -604,8 +600,7 @@
GXV_TRACE(( "reverse ordered segment specification:"
" lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
unit, lastGlyph, unit - 1 , gid ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
if ( lastGlyph < firstGlyph )
@@ -613,8 +608,7 @@
GXV_TRACE(( "reverse ordered range specification at unit %d:",
" lastGlyph %d < firstGlyph %d ",
unit, lastGlyph, firstGlyph ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
if ( valid->root->level == FT_VALIDATE_TIGHT )
continue; /* ftxvalidator silently skips such an entry */
@@ -705,8 +699,7 @@
{
GXV_TRACE(( "current gid 0x%04x < previous gid 0x%04x\n",
glyph, prev_glyph ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
prev_glyph = glyph;
@@ -834,8 +827,7 @@
{
GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %d < %d\n",
face->num_glyphs, gid ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
return 0;
@@ -1101,8 +1093,7 @@
if ( ( maxEntry + 1 ) * entrySize > *length_p )
{
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_TOO_SHORT;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_TOO_SHORT );
/* ftxvalidator and FontValidator both warn and continue */
maxEntry = (FT_Byte)( *length_p / entrySize - 1 );
@@ -1126,8 +1117,7 @@
{
GXV_TRACE(( " newState offset 0x%04x is out of stateArray\n",
newState ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
continue;
}
@@ -1135,8 +1125,7 @@
{
GXV_TRACE(( " newState offset 0x%04x is not aligned to %d-classes\n",
newState, 1 + maxClassID ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
continue;
}
@@ -1173,8 +1162,7 @@
break;
default:
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_FORMAT;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
goto Exit;
}
@@ -1503,8 +1491,7 @@
{
GXV_TRACE(( " newState index 0x%04x points out of stateArray\n",
newState_idx ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
}
state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) );
@@ -1513,8 +1500,7 @@
FT_TRACE4(( "-> new state = %d (supposed)\n"
"but newState index 0x%04x is not aligned to %d-classes\n",
state, newState_idx, 1 + maxClassID ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
}
switch ( GXV_GLYPHOFFSET_FMT( xstatetable ) )
@@ -1548,8 +1534,7 @@
break;
default:
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_FORMAT;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
goto Exit;
}
diff --git a/freetype/src/gxvalid/gxvcommn.h b/freetype/src/gxvalid/gxvcommn.h
index 316e49309..4d2bb44b4 100644
--- a/freetype/src/gxvalid/gxvcommn.h
+++ b/freetype/src/gxvalid/gxvcommn.h
@@ -51,6 +51,19 @@
FT_BEGIN_HEADER
+ /* some variables are not evaluated or only used in trace */
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+#define GXV_LOAD_TRACE_VARS
+#else
+#undef GXV_LOAD_TRACE_VARS
+#endif
+
+#undef GXV_LOAD_UNUSED_VARS /* debug purpose */
+
+#define IS_PARANOID_VALIDATION ( valid->root->level >= FT_VALIDATE_PARANOID )
+#define GXV_SET_ERR_IF_PARANOID( err ) { if ( IS_PARANOID_VALIDATION ) ( err ); }
+
/*************************************************************************/
/*************************************************************************/
/***** *****/
@@ -234,6 +247,9 @@ FT_BEGIN_HEADER
GXV_Lookup_Fmt4_Transit_Func lookupfmt4_trans;
FT_Bytes lookuptbl_head;
+ FT_UShort min_gid;
+ FT_UShort max_gid;
+
GXV_StateTable_ValidatorRec statetable;
GXV_XStateTable_ValidatorRec xstatetable;
diff --git a/freetype/src/gxvalid/gxvfeat.c b/freetype/src/gxvalid/gxvfeat.c
index 002fec6d6..46792bbf9 100644
--- a/freetype/src/gxvalid/gxvfeat.c
+++ b/freetype/src/gxvalid/gxvfeat.c
@@ -92,8 +92,7 @@
{
GXV_TRACE(( "feature number %d is out of range %d\n",
feature, gxv_feat_registry_length ));
- if ( valid->root->level == FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
goto Exit;
}
@@ -101,8 +100,7 @@
{
GXV_TRACE(( "feature number %d is in defined range but doesn't exist\n",
feature ));
- if ( valid->root->level == FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
goto Exit;
}
@@ -222,9 +220,8 @@
if ( settingTable < reserved_size )
FT_INVALID_OFFSET;
- if ( valid->root->level == FT_VALIDATE_PARANOID &&
- ( featureFlags & GXV_FEAT_MASK_UNUSED ) == 0 )
- FT_INVALID_DATA;
+ if ( ( featureFlags & GXV_FEAT_MASK_UNUSED ) == 0 )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
exclusive = FT_BOOL( featureFlags & GXV_FEAT_MASK_EXCLUSIVE_SETTINGS );
if ( exclusive )
@@ -252,9 +249,8 @@
{
gxv_feat_setting_validate( p, limit, exclusive, valid );
- if ( valid->root->level == FT_VALIDATE_PARANOID &&
- (FT_Int)GXV_FEAT_DATA( setting ) <= last_setting )
- FT_INVALID_FORMAT;
+ if ( (FT_Int)GXV_FEAT_DATA( setting ) <= last_setting )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
last_setting = (FT_Int)GXV_FEAT_DATA( setting );
/* setting + nameIndex */
@@ -312,8 +308,8 @@
featureNameCount = FT_NEXT_USHORT( p );
GXV_TRACE(( " (featureNameCount = %d)\n", featureNameCount ));
- if ( valid->root->level != FT_VALIDATE_PARANOID )
- p += 6; /* skip (none) and (none) */
+ if ( !( IS_PARANOID_VALIDATION ) )
+ p += 6; /* skip (none) and (none) */
else
{
if ( FT_NEXT_USHORT( p ) != 0 )
@@ -329,9 +325,8 @@
{
gxv_feat_name_validate( p, limit, valid );
- if ( valid->root->level == FT_VALIDATE_PARANOID &&
- (FT_Int)GXV_FEAT_DATA( feature ) <= last_feature )
- FT_INVALID_FORMAT;
+ if ( (FT_Int)GXV_FEAT_DATA( feature ) <= last_feature )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_FORMAT );
last_feature = GXV_FEAT_DATA( feature );
p += 2 + 2 + 4 + 2 + 2;
diff --git a/freetype/src/gxvalid/gxvjust.c b/freetype/src/gxvalid/gxvjust.c
index e14f946f2..7816e0b7f 100644
--- a/freetype/src/gxvalid/gxvjust.c
+++ b/freetype/src/gxvalid/gxvjust.c
@@ -65,6 +65,22 @@
#define GXV_JUST_DATA( a ) GXV_TABLE_DATA( just, a )
+ /* GX just table does not define their subset of GID */
+ static void
+ gxv_just_check_max_gid( FT_UShort gid,
+ const FT_String* msg_tag,
+ GXV_Validator valid )
+ {
+ if ( gid < valid->face->num_glyphs )
+ return;
+
+ GXV_TRACE(( "just table includes too large %s"
+ " GID=%d > %d (in maxp)\n",
+ msg_tag, gid, valid->face->num_glyphs ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
+ }
+
+
static void
gxv_just_wdp_entry_validate( FT_Bytes table,
FT_Bytes limit,
@@ -72,24 +88,37 @@
{
FT_Bytes p = table;
FT_ULong justClass;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Fixed beforeGrowLimit;
FT_Fixed beforeShrinkGrowLimit;
FT_Fixed afterGrowLimit;
FT_Fixed afterShrinkGrowLimit;
FT_UShort growFlags;
FT_UShort shrinkFlags;
+#endif
GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 + 4 + 2 + 2 );
justClass = FT_NEXT_ULONG( p );
+#ifndef GXV_LOAD_UNUSED_VARS
+ p += 4 + 4 + 4 + 4 + 2 + 2;
+#else
beforeGrowLimit = FT_NEXT_ULONG( p );
beforeShrinkGrowLimit = FT_NEXT_ULONG( p );
afterGrowLimit = FT_NEXT_ULONG( p );
afterShrinkGrowLimit = FT_NEXT_ULONG( p );
growFlags = FT_NEXT_USHORT( p );
shrinkFlags = FT_NEXT_USHORT( p );
+#endif
- /* TODO: decode flags for human readability */
+ /* According to Apple spec, only 7bits in justClass is used */
+ if ( ( justClass & 0xFFFFFF80 ) != 0 )
+ {
+ GXV_TRACE(( "just table includes non-zero value"
+ " in unused justClass higher bits"
+ " of WidthDeltaPair" ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+ }
valid->subtable_length = p - table;
}
@@ -153,8 +182,9 @@
FT_Fixed lowerLimit;
FT_Fixed upperLimit;
-
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort order;
+#endif
FT_UShort decomposedCount;
FT_UInt i;
@@ -163,9 +193,20 @@
GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
lowerLimit = FT_NEXT_ULONG( p );
upperLimit = FT_NEXT_ULONG( p );
+#ifdef GXV_LOAD_UNUSED_VARS
order = FT_NEXT_USHORT( p );
+#else
+ p += 2;
+#endif
decomposedCount = FT_NEXT_USHORT( p );
+ if ( lowerLimit >= upperLimit )
+ {
+ GXV_TRACE(( "just table includes invalid range spec:"
+ " lowerLimit(%d) > upperLimit(%d)\n" ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+ }
+
for ( i = 0; i < decomposedCount; i++ )
{
FT_UShort glyphs;
@@ -173,6 +214,7 @@
GXV_LIMIT_CHECK( 2 );
glyphs = FT_NEXT_USHORT( p );
+ gxv_just_check_max_gid( glyphs, "type0:glyphs", valid );
}
valid->subtable_length = p - table;
@@ -191,6 +233,8 @@
GXV_LIMIT_CHECK( 2 );
addGlyph = FT_NEXT_USHORT( p );
+ gxv_just_check_max_gid( addGlyph, "type1:addGlyph", valid );
+
valid->subtable_length = p - table;
}
@@ -201,16 +245,27 @@
GXV_Validator valid )
{
FT_Bytes p = table;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Fixed substThreshhold; /* Apple misspelled "Threshhold" */
+#endif
FT_UShort addGlyph;
FT_UShort substGlyph;
GXV_LIMIT_CHECK( 4 + 2 + 2 );
+#ifdef GXV_LOAD_UNUSED_VARS
substThreshhold = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
addGlyph = FT_NEXT_USHORT( p );
substGlyph = FT_NEXT_USHORT( p );
+ if ( addGlyph != 0xFFFF )
+ gxv_just_check_max_gid( addGlyph, "type2:addGlyph", valid );
+
+ gxv_just_check_max_gid( substGlyph, "type2:substGlyph", valid );
+
valid->subtable_length = p - table;
}
@@ -234,6 +289,21 @@
maximumLimit = FT_NEXT_ULONG( p );
valid->subtable_length = p - table;
+
+ if ( variantsAxis != 0x64756374 ) /* 'duct' */
+ GXV_TRACE(( "variantsAxis 0x%08x is non default value",
+ variantsAxis ));
+
+ if ( minimumLimit > noStretchValue )
+ GXV_TRACE(( "type4:minimumLimit 0x%08x > noStretchValue 0x%08x\n",
+ minimumLimit, noStretchValue ));
+ else if ( noStretchValue > maximumLimit )
+ GXV_TRACE(( "type4:noStretchValue 0x%08x > maximumLimit 0x%08x\n",
+ noStretchValue, maximumLimit ));
+ else if ( !IS_PARANOID_VALIDATION )
+ return;
+
+ FT_INVALID_DATA;
}
@@ -251,6 +321,11 @@
flags = FT_NEXT_USHORT( p );
glyph = FT_NEXT_USHORT( p );
+ if ( flags )
+ GXV_TRACE(( "type5: nonzero value 0x%04x in unused flags\n",
+ flags ));
+ gxv_just_check_max_gid( glyph, "type5:glyph", valid );
+
valid->subtable_length = p - table;
}
@@ -274,6 +349,10 @@
actionType = FT_NEXT_USHORT( p );
actionLength = FT_NEXT_ULONG( p );
+ /* actionClass is related with justClass using 7bit only */
+ if ( ( actionClass & 0xFF80 ) != 0 )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+
if ( actionType == 0 )
gxv_just_actSubrecord_type0_validate( p, limit, valid );
else if ( actionType == 1 )
@@ -389,10 +468,13 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
+ /* TODO: validate markClass & currentClass */
FT_UShort setMark;
FT_UShort dontAdvance;
FT_UShort markClass;
FT_UShort currentClass;
+#endif
FT_UNUSED( state );
FT_UNUSED( glyphOffset_p );
@@ -400,13 +482,14 @@
FT_UNUSED( limit );
FT_UNUSED( valid );
-
+#ifndef GXV_LOAD_UNUSED_VARS
+ FT_UNUSED( flags );
+#else
setMark = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
markClass = (FT_UShort)( ( flags >> 7 ) & 0x7F );
currentClass = (FT_UShort)( flags & 0x7F );
-
- /* TODO: validate markClass & currentClass */
+#endif
}
@@ -428,9 +511,15 @@
coverage = FT_NEXT_USHORT( p );
subFeatureFlags = FT_NEXT_ULONG( p );
- GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s)",
- coverage,
- ( 0x4000 & coverage ) == 0 ? "ascending" : "descending" ));
+ GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s) ", coverage ));
+ if ( ( coverage & 0x4000 ) == 0 )
+ GXV_TRACE(( "ascending\n" ));
+ else
+ GXV_TRACE(( "descending\n" ));
+
+ if ( subFeatureFlags )
+ GXV_TRACE(( " justClassTable: nonzero value (0x%08x)"
+ " in unused subFeatureFlags\n", subFeatureFlags ));
valid->statetable.optdata = NULL;
valid->statetable.optdata_load_func = NULL;
@@ -557,7 +646,6 @@
{
FT_Bytes p = table;
FT_Bytes limit = 0;
- FT_Offset table_size;
GXV_ValidatorRec validrec;
GXV_Validator valid = &validrec;
@@ -582,7 +670,6 @@
GXV_INIT;
limit = valid->root->limit;
- table_size = limit - table;
GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 );
version = FT_NEXT_ULONG( p );
diff --git a/freetype/src/gxvalid/gxvkern.c b/freetype/src/gxvalid/gxvkern.c
index 2137db842..0ec978f7b 100644
--- a/freetype/src/gxvalid/gxvkern.c
+++ b/freetype/src/gxvalid/gxvkern.c
@@ -127,7 +127,9 @@
{
FT_UShort gid_left;
FT_UShort gid_right;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Short kernValue;
+#endif
/* left */
@@ -156,7 +158,11 @@
FT_INVALID_DATA;
/* skip the kern value */
+#ifdef GXV_LOAD_UNUSED_VARS
kernValue = FT_NEXT_SHORT( p );
+#else
+ p += 2;
+#endif
}
GXV_EXIT;
@@ -261,18 +267,24 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort push;
FT_UShort dontAdvance;
+#endif
FT_UShort valueOffset;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort kernAction;
FT_UShort kernValue;
+#endif
FT_UNUSED( state );
FT_UNUSED( glyphOffset_p );
+#ifdef GXV_LOAD_UNUSED_VARS
push = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+#endif
valueOffset = (FT_UShort)( flags & 0x3FFF );
{
@@ -288,8 +300,12 @@
limit = table + vt_rec->valueTable + vt_rec->valueTable_length;
GXV_LIMIT_CHECK( 2 + 2 );
+#ifdef GXV_LOAD_UNUSED_VARS
kernAction = FT_NEXT_USHORT( p );
kernValue = FT_NEXT_USHORT( p );
+#else
+ p += 4;
+#endif
}
}
@@ -475,10 +491,12 @@
{
GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n",
valid->face->num_glyphs, glyphCount ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
+ if ( flags != 0 )
+ GXV_TRACE(( "kern subtable fmt3 has nonzero value"
+ " (%d) in unused flag\n", flags ));
/*
* just skip kernValue[kernValueCount]
*/
@@ -545,20 +563,24 @@
GXV_Validator valid )
{
/* new Apple-dialect */
+#ifdef GXV_LOAD_TRACE_VARS
FT_Bool kernVertical;
FT_Bool kernCrossStream;
FT_Bool kernVariation;
+#endif
FT_UNUSED( valid );
/* reserved bits = 0 */
if ( coverage & 0x1FFC )
- return 0;
+ return FALSE;
+#ifdef GXV_LOAD_TRACE_VARS
kernVertical = FT_BOOL( ( coverage >> 15 ) & 1 );
kernCrossStream = FT_BOOL( ( coverage >> 14 ) & 1 );
kernVariation = FT_BOOL( ( coverage >> 13 ) & 1 );
+#endif
*format = (FT_UShort)( coverage & 0x0003 );
@@ -568,7 +590,7 @@
GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
- return 1;
+ return TRUE;
}
@@ -578,20 +600,24 @@
GXV_Validator valid )
{
/* classic Apple-dialect */
+#ifdef GXV_LOAD_TRACE_VARS
FT_Bool horizontal;
FT_Bool cross_stream;
+#endif
/* check expected flags, but don't check if MS-dialect is impossible */
if ( !( coverage & 0xFD00 ) && KERN_ALLOWS_MS( valid ) )
- return 0;
+ return FALSE;
/* reserved bits = 0 */
if ( coverage & 0x02FC )
- return 0;
+ return FALSE;
+#ifdef GXV_LOAD_TRACE_VARS
horizontal = FT_BOOL( ( coverage >> 15 ) & 1 );
cross_stream = FT_BOOL( ( coverage >> 13 ) & 1 );
+#endif
*format = (FT_UShort)( coverage & 0x0003 );
@@ -601,11 +627,11 @@
/* format 1 requires GX State Machine, too new for classic */
if ( *format == 1 )
- return 0;
+ return FALSE;
GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
- return 1;
+ return TRUE;
}
@@ -615,22 +641,26 @@
GXV_Validator valid )
{
/* classic Microsoft-dialect */
+#ifdef GXV_LOAD_TRACE_VARS
FT_Bool horizontal;
FT_Bool minimum;
FT_Bool cross_stream;
FT_Bool override;
+#endif
FT_UNUSED( valid );
/* reserved bits = 0 */
if ( coverage & 0xFDF0 )
- return 0;
+ return FALSE;
+#ifdef GXV_LOAD_TRACE_VARS
horizontal = FT_BOOL( coverage & 1 );
minimum = FT_BOOL( ( coverage >> 1 ) & 1 );
cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 );
override = FT_BOOL( ( coverage >> 3 ) & 1 );
+#endif
*format = (FT_UShort)( ( coverage >> 8 ) & 0x0003 );
@@ -643,7 +673,7 @@
GXV_TRACE((
"kerning values in Microsoft format 2 subtable are ignored\n" ));
- return 1;
+ return TRUE;
}
@@ -714,10 +744,14 @@
GXV_Validator valid )
{
FT_Bytes p = table;
+#ifdef GXV_LOAD_TRACE_VARS
FT_UShort version = 0; /* MS only: subtable version, unused */
+#endif
FT_ULong length; /* MS: 16bit, Apple: 32bit*/
FT_UShort coverage;
+#ifdef GXV_LOAD_TRACE_VARS
FT_UShort tupleIndex = 0; /* Apple only */
+#endif
FT_UShort u16[2];
FT_UShort format = 255; /* subtable format */
@@ -732,23 +766,35 @@
switch ( gxv_kern_coverage_validate( coverage, &format, valid ) )
{
case KERN_DIALECT_MS:
+#ifdef GXV_LOAD_TRACE_VARS
version = u16[0];
+#endif
length = u16[1];
+#ifdef GXV_LOAD_TRACE_VARS
tupleIndex = 0;
+#endif
GXV_TRACE(( "Subtable version = %d\n", version ));
GXV_TRACE(( "Subtable length = %d\n", length ));
break;
case KERN_DIALECT_APPLE:
+#ifdef GXV_LOAD_TRACE_VARS
version = 0;
+#endif
length = ( u16[0] << 16 ) + u16[1];
+#ifdef GXV_LOAD_TRACE_VARS
tupleIndex = 0;
+#endif
GXV_TRACE(( "Subtable length = %d\n", length ));
if ( KERN_IS_NEW( valid ) )
{
GXV_LIMIT_CHECK( 2 );
+#ifdef GXV_LOAD_TRACE_VARS
tupleIndex = FT_NEXT_USHORT( p );
+#else
+ p += 2;
+#endif
GXV_TRACE(( "Subtable tupleIndex = %d\n", tupleIndex ));
}
break;
diff --git a/freetype/src/gxvalid/gxvmort.c b/freetype/src/gxvalid/gxvmort.c
index 0aa066339..465462a05 100644
--- a/freetype/src/gxvalid/gxvmort.c
+++ b/freetype/src/gxvalid/gxvmort.c
@@ -47,16 +47,14 @@
GXV_TRACE(( "featureType %d is out of registered range, "
"setting %d is unchecked\n",
f->featureType, f->featureSetting ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
else if ( !gxv_feat_registry[f->featureType].existence )
{
GXV_TRACE(( "featureType %d is within registered area "
"but undefined, setting %d is unchecked\n",
f->featureType, f->featureSetting ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
else
{
@@ -74,8 +72,7 @@
if ( f->featureSetting > nSettings_max )
{
GXV_TRACE(( "out of defined range %d", nSettings_max ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
GXV_TRACE(( "\n" ));
}
@@ -176,7 +173,9 @@
{
FT_UShort length;
FT_UShort coverage;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_ULong subFeatureFlags;
+#endif
FT_UInt type;
FT_UInt rest;
@@ -184,7 +183,11 @@
GXV_LIMIT_CHECK( 2 + 2 + 4 );
length = FT_NEXT_USHORT( p );
coverage = FT_NEXT_USHORT( p );
+#ifdef GXV_LOAD_UNUSED_VARS
subFeatureFlags = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
i + 1, nSubtables, length ));
@@ -204,6 +207,7 @@
func( p, p + rest, valid );
p += rest;
+ /* TODO: validate subFeatureFlags */
}
valid->subtable_length = p - table;
@@ -218,7 +222,9 @@
GXV_Validator valid )
{
FT_Bytes p = table;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_ULong defaultFlags;
+#endif
FT_ULong chainLength;
FT_UShort nFeatureFlags;
FT_UShort nSubtables;
@@ -227,7 +233,11 @@
GXV_NAME_ENTER( "mort chain header" );
GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
+#ifdef GXV_LOAD_UNUSED_VARS
defaultFlags = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
chainLength = FT_NEXT_ULONG( p );
nFeatureFlags = FT_NEXT_USHORT( p );
nSubtables = FT_NEXT_USHORT( p );
@@ -238,6 +248,7 @@
gxv_mort_subtables_validate( p, table + chainLength, nSubtables, valid );
valid->subtable_length = chainLength;
+ /* TODO: validate defaultFlags */
GXV_EXIT;
}
diff --git a/freetype/src/gxvalid/gxvmort0.c b/freetype/src/gxvalid/gxvmort0.c
index 0453062f6..b136ceda2 100644
--- a/freetype/src/gxvalid/gxvmort0.c
+++ b/freetype/src/gxvalid/gxvmort0.c
@@ -98,10 +98,24 @@
GXV_TRACE(( " %02d", verb ));
GXV_TRACE(( " %s\n", GXV_Mort_IndicScript_Msg[verb] ));
+ if ( markFirst > 0 && markLast > 0 )
+ {
+ GXV_TRACE(( " [odd] a glyph is marked as the first and last"
+ " in Indic rearrangement\n" ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+ }
+
+ if ( markFirst > 0 && dontAdvance > 0 )
+ {
+ GXV_TRACE(( " [odd] the first glyph is marked as dontAdvance"
+ " in Indic rearrangement\n" ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
+ }
+
if ( 0 < reserved )
{
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
else
GXV_TRACE(( "\n" ));
diff --git a/freetype/src/gxvalid/gxvmort1.c b/freetype/src/gxvalid/gxvmort1.c
index 696d85032..1c17a5d92 100644
--- a/freetype/src/gxvalid/gxvmort1.c
+++ b/freetype/src/gxvalid/gxvmort1.c
@@ -106,8 +106,6 @@
{
FT_UShort substTable;
FT_UShort substTable_limit;
- FT_UShort min_gid;
- FT_UShort max_gid;
FT_UNUSED( tag );
FT_UNUSED( state );
@@ -121,9 +119,10 @@
((GXV_mort_subtable_type1_StateOptRec *)
(valid->statetable.optdata))->substitutionTable_length );
- min_gid = (FT_UShort)( ( substTable - wordOffset * 2 ) / 2 );
- max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 );
- max_gid = (FT_UShort)( FT_MAX( max_gid, valid->face->num_glyphs ) );
+ valid->min_gid = (FT_UShort)( ( substTable - wordOffset * 2 ) / 2 );
+ valid->max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 );
+ valid->max_gid = (FT_UShort)( FT_MAX( valid->max_gid,
+ valid->face->num_glyphs ) );
/* XXX: check range? */
@@ -140,8 +139,10 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort setMark;
FT_UShort dontAdvance;
+#endif
FT_UShort reserved;
FT_Short markOffset;
FT_Short currentOffset;
@@ -150,8 +151,10 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_UNUSED_VARS
setMark = (FT_UShort)( flags >> 15 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+#endif
reserved = (FT_Short)( flags & 0x3FFF );
markOffset = (FT_Short)( glyphOffset_p->ul >> 16 );
@@ -160,8 +163,7 @@
if ( 0 < reserved )
{
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
gxv_mort_subtable_type1_offset_to_subst_validate( markOffset,
@@ -200,13 +202,12 @@
if ( dst_gid >= 0xFFFFU )
continue;
- if ( dst_gid > valid->face->num_glyphs )
+ if ( dst_gid < valid->min_gid || valid->max_gid < dst_gid )
{
- GXV_TRACE(( "substTable include too large gid[%d]=%d >"
- " max defined gid #%d\n",
- i, dst_gid, valid->face->num_glyphs ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_GLYPH_ID;
+ GXV_TRACE(( "substTable include a strange gid[%d]=%d >"
+ " out of define range (%d..%d)\n",
+ i, dst_gid, valid->min_gid, valid->max_gid ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
}
diff --git a/freetype/src/gxvalid/gxvmort2.c b/freetype/src/gxvalid/gxvmort2.c
index 6f77cf39c..9e08fb792 100644
--- a/freetype/src/gxvalid/gxvmort2.c
+++ b/freetype/src/gxvalid/gxvmort2.c
@@ -155,8 +155,7 @@
ligActionOffset, lat_base - p ));
/* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
}
else if ( lat_limit < p )
{
@@ -164,23 +163,46 @@
ligActionOffset, p - lat_limit ));
/* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_OFFSET;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
}
else
{
/* validate entry in ligActionTable */
FT_ULong lig_action;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort last;
FT_UShort store;
+#endif
FT_ULong offset;
lig_action = FT_NEXT_ULONG( p );
+#ifdef GXV_LOAD_UNUSED_VARS
last = (FT_UShort)( ( lig_action >> 31 ) & 1 );
store = (FT_UShort)( ( lig_action >> 30 ) & 1 );
+#endif
+ /* Apple spec defines this offset as a word offset */
offset = lig_action & 0x3FFFFFFFUL;
+ if ( offset * 2 < optdata->ligatureTable )
+ {
+ GXV_TRACE(( "too short offset 0x%08x:"
+ " 2 x offset < ligatureTable (%d byte rewind)\n",
+ offset, optdata->ligatureTable - offset * 2 ));
+
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
+ } else if ( offset * 2 >
+ optdata->ligatureTable + optdata->ligatureTable_length )
+ {
+ GXV_TRACE(( "too long offset 0x%08x:"
+ " 2 x offset > ligatureTable + ligatureTable_length"
+ " (%d byte overrun)\n",
+ offset,
+ optdata->ligatureTable + optdata->ligatureTable_length
+ - offset * 2 ));
+
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
+ }
}
}
@@ -194,8 +216,10 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort setComponent;
FT_UShort dontAdvance;
+#endif
FT_UShort offset;
FT_UNUSED( state );
@@ -203,8 +227,10 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_UNUSED_VARS
setComponent = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+#endif
offset = (FT_UShort)( flags & 0x3FFFU );
@@ -237,6 +263,9 @@
GXV_LIMIT_CHECK( 2 );
lig_gid = FT_NEXT_USHORT( p );
+
+ if ( valid->face->num_glyphs < lig_gid )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
}
GXV_EXIT;
diff --git a/freetype/src/gxvalid/gxvmort5.c b/freetype/src/gxvalid/gxvmort5.c
index ec0bcb634..32cfb0363 100644
--- a/freetype/src/gxvalid/gxvmort5.c
+++ b/freetype/src/gxvalid/gxvmort5.c
@@ -121,6 +121,9 @@
offset < optdata->entryTable + *(optdata->entryTable_length_p) )
GXV_TRACE(( " offset runs into EntryTable" ));
+#ifndef GXV_LOAD_TRACE_VARS
+ GXV_LIMIT_CHECK( count * 2 );
+#else
while ( p < table + offset + ( count * 2 ) )
{
FT_UShort insert_glyphID;
@@ -130,8 +133,8 @@
insert_glyphID = FT_NEXT_USHORT( p );
GXV_TRACE(( " 0x%04x", insert_glyphID ));
}
-
GXV_TRACE(( "\n" ));
+#endif
}
@@ -144,12 +147,14 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Bool setMark;
FT_Bool dontAdvance;
FT_Bool currentIsKashidaLike;
FT_Bool markedIsKashidaLike;
FT_Bool currentInsertBefore;
FT_Bool markedInsertBefore;
+#endif
FT_Byte currentInsertCount;
FT_Byte markedInsertCount;
FT_UShort currentInsertList;
@@ -158,12 +163,14 @@
FT_UNUSED( state );
+#ifdef GXV_LOAD_UNUSED_VARS
setMark = FT_BOOL( ( flags >> 15 ) & 1 );
dontAdvance = FT_BOOL( ( flags >> 14 ) & 1 );
currentIsKashidaLike = FT_BOOL( ( flags >> 13 ) & 1 );
markedIsKashidaLike = FT_BOOL( ( flags >> 12 ) & 1 );
currentInsertBefore = FT_BOOL( ( flags >> 11 ) & 1 );
markedInsertBefore = FT_BOOL( ( flags >> 10 ) & 1 );
+#endif
currentInsertCount = (FT_Byte)( ( flags >> 5 ) & 0x1F );
markedInsertCount = (FT_Byte)( flags & 0x001F );
diff --git a/freetype/src/gxvalid/gxvmorx.c b/freetype/src/gxvalid/gxvmorx.c
index f8ba5b985..4b1dd0050 100644
--- a/freetype/src/gxvalid/gxvmorx.c
+++ b/freetype/src/gxvalid/gxvmorx.c
@@ -68,7 +68,9 @@
{
FT_ULong length;
FT_ULong coverage;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_ULong subFeatureFlags;
+#endif
FT_ULong type;
FT_ULong rest;
@@ -76,7 +78,11 @@
GXV_LIMIT_CHECK( 4 + 4 + 4 );
length = FT_NEXT_ULONG( p );
coverage = FT_NEXT_ULONG( p );
+#ifdef GXV_LOAD_UNUSED_VARS
subFeatureFlags = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
i + 1, nSubtables, length ));
@@ -97,6 +103,7 @@
func( p, p + rest, valid );
+ /* TODO: subFeatureFlags should be unique in a table? */
p += rest;
}
@@ -112,7 +119,9 @@
GXV_Validator valid )
{
FT_Bytes p = table;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_ULong defaultFlags;
+#endif
FT_ULong chainLength;
FT_ULong nFeatureFlags;
FT_ULong nSubtables;
@@ -121,7 +130,11 @@
GXV_NAME_ENTER( "morx chain header" );
GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
+#ifdef GXV_LOAD_UNUSED_VARS
defaultFlags = FT_NEXT_ULONG( p );
+#else
+ p += 4;
+#endif
chainLength = FT_NEXT_ULONG( p );
nFeatureFlags = FT_NEXT_ULONG( p );
nSubtables = FT_NEXT_ULONG( p );
@@ -138,6 +151,8 @@
valid->subtable_length = chainLength;
+ /* TODO: defaultFlags should be compared with the flags in tables */
+
GXV_EXIT;
}
diff --git a/freetype/src/gxvalid/gxvmorx0.c b/freetype/src/gxvalid/gxvmorx0.c
index 0159c5aef..6a736c177 100644
--- a/freetype/src/gxvalid/gxvmorx0.c
+++ b/freetype/src/gxvalid/gxvmorx0.c
@@ -47,11 +47,15 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort markFirst;
FT_UShort dontAdvance;
FT_UShort markLast;
+#endif
FT_UShort reserved;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort verb;
+#endif
FT_UNUSED( state );
FT_UNUSED( glyphOffset_p );
@@ -59,12 +63,16 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_UNUSED_VARS
markFirst = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
markLast = (FT_UShort)( ( flags >> 13 ) & 1 );
+#endif
reserved = (FT_UShort)( flags & 0x1FF0 );
+#ifdef GXV_LOAD_UNUSED_VARS
verb = (FT_UShort)( flags & 0x000F );
+#endif
if ( 0 < reserved )
{
diff --git a/freetype/src/gxvalid/gxvmorx1.c b/freetype/src/gxvalid/gxvmorx1.c
index e1c162fa0..ce0009a16 100644
--- a/freetype/src/gxvalid/gxvmorx1.c
+++ b/freetype/src/gxvalid/gxvmorx1.c
@@ -108,8 +108,10 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_TRACE_VARS
FT_UShort setMark;
FT_UShort dontAdvance;
+#endif
FT_UShort reserved;
FT_Short markIndex;
FT_Short currentIndex;
@@ -122,8 +124,10 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_TRACE_VARS
setMark = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
+#endif
reserved = (FT_UShort)( flags & 0x3FFF );
@@ -136,8 +140,7 @@
if ( 0 < reserved )
{
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
- if ( valid->root->level >= FT_VALIDATE_PARANOID )
- FT_INVALID_DATA;
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
}
GXV_TRACE(( "markIndex = %d, currentIndex = %d\n",
diff --git a/freetype/src/gxvalid/gxvmorx2.c b/freetype/src/gxvalid/gxvmorx2.c
index b4bb3353f..bc18c6b8a 100644
--- a/freetype/src/gxvalid/gxvmorx2.c
+++ b/freetype/src/gxvalid/gxvmorx2.c
@@ -168,16 +168,50 @@
{
/* validate entry in ligActionTable */
FT_ULong lig_action;
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort last;
FT_UShort store;
+#endif
FT_ULong offset;
lig_action = FT_NEXT_ULONG( p );
+#ifdef GXV_LOAD_UNUSED_VARS
last = (FT_UShort)( ( lig_action >> 31 ) & 1 );
store = (FT_UShort)( ( lig_action >> 30 ) & 1 );
+#endif
offset = lig_action & 0x3FFFFFFFUL;
+
+ /* this offset is 30-bit signed value to add to GID */
+ /* it is different from the location offset in mort */
+ if ( ( offset & 0x3FFF0000UL ) == 0x3FFF0000UL )
+ {
+ if ( offset + valid->face->num_glyphs > 0x40000000UL )
+ return;
+
+ GXV_TRACE(( "ligature action table includes"
+ " too negative offset moving all GID"
+ " below defined range: 0x%04x\n",
+ offset & 0xFFFFU ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
+ }
+ else if ( ( offset & 0x3FFF0000UL ) == 0x0000000UL )
+ {
+ if ( offset + valid->face->num_glyphs < 0 )
+ return;
+
+ GXV_TRACE(( "ligature action table includes"
+ " too large offset moving all GID"
+ " over defined range: 0x%04x\n",
+ offset & 0xFFFFU ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
+ }
+
+ GXV_TRACE(( "ligature action table includes"
+ " invalid offset to add to 16-bit GID:"
+ " 0x%08x\n", offset ));
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
}
}
@@ -191,9 +225,11 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_UShort setComponent;
FT_UShort dontAdvance;
FT_UShort performAction;
+#endif
FT_UShort reserved;
FT_UShort ligActionIndex;
@@ -201,9 +237,11 @@
FT_UNUSED( limit );
+#ifdef GXV_LOAD_UNUSED_VARS
setComponent = (FT_UShort)( ( flags >> 15 ) & 1 );
dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
performAction = (FT_UShort)( ( flags >> 13 ) & 1 );
+#endif
reserved = (FT_UShort)( flags & 0x1FFF );
ligActionIndex = glyphOffset_p->u;
@@ -241,6 +279,8 @@
GXV_LIMIT_CHECK( 2 );
lig_gid = FT_NEXT_USHORT( p );
+ if ( lig_gid < valid->face->num_glyphs )
+ GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
}
}
diff --git a/freetype/src/gxvalid/gxvmorx5.c b/freetype/src/gxvalid/gxvmorx5.c
index 5e3a16437..d8cf70079 100644
--- a/freetype/src/gxvalid/gxvmorx5.c
+++ b/freetype/src/gxvalid/gxvmorx5.c
@@ -118,6 +118,9 @@
FT_Bytes p = table + table_index * 2;
+#ifndef GXV_LOAD_TRACE_VARS
+ GXV_LIMIT_CHECK( count * 2 );
+#else
while ( p < table + count * 2 + table_index * 2 )
{
FT_UShort insert_glyphID;
@@ -129,6 +132,7 @@
}
GXV_TRACE(( "\n" ));
+#endif
}
@@ -141,12 +145,14 @@
FT_Bytes limit,
GXV_Validator valid )
{
+#ifdef GXV_LOAD_UNUSED_VARS
FT_Bool setMark;
FT_Bool dontAdvance;
FT_Bool currentIsKashidaLike;
FT_Bool markedIsKashidaLike;
FT_Bool currentInsertBefore;
FT_Bool markedInsertBefore;
+#endif
FT_Byte currentInsertCount;
FT_Byte markedInsertCount;
FT_Byte currentInsertList;
@@ -155,12 +161,14 @@
FT_UNUSED( state );
+#ifdef GXV_LOAD_UNUSED_VARS
setMark = FT_BOOL( ( flags >> 15 ) & 1 );
dontAdvance = FT_BOOL( ( flags >> 14 ) & 1 );
currentIsKashidaLike = FT_BOOL( ( flags >> 13 ) & 1 );
markedIsKashidaLike = FT_BOOL( ( flags >> 12 ) & 1 );
currentInsertBefore = FT_BOOL( ( flags >> 11 ) & 1 );
markedInsertBefore = FT_BOOL( ( flags >> 10 ) & 1 );
+#endif
currentInsertCount = (FT_Byte)( ( flags >> 5 ) & 0x1F );
markedInsertCount = (FT_Byte)( flags & 0x001F );
diff --git a/freetype/src/gxvalid/gxvprop.c b/freetype/src/gxvalid/gxvprop.c
index 66c3ab740..54777271a 100644
--- a/freetype/src/gxvalid/gxvprop.c
+++ b/freetype/src/gxvalid/gxvprop.c
@@ -96,7 +96,10 @@
if ( glyph->advance.x != (FT_Pos)0 ||
glyph->advance.y != (FT_Pos)0 )
+ {
+ GXV_TRACE(( " found non-zero advance in zero-advance glyph\n" ));
FT_INVALID_DATA;
+ }
GXV_EXIT;
}
@@ -119,7 +122,10 @@
offset = (FT_UShort)( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET );
if ( offset == 0 )
- FT_INVALID_DATA;
+ {
+ GXV_TRACE(( " found zero offset to property\n" ));
+ FT_INVALID_OFFSET;
+ }
complement = (char)( offset >> 8 );
if ( complement & 0x08 )
@@ -131,7 +137,10 @@
/* The gid for complement must be greater than 0 */
if ( glyph <= complement )
+ {
+ GXV_TRACE(( " found non-positive glyph complement\n" ));
FT_INVALID_DATA;
+ }
}
else
{
@@ -150,18 +159,27 @@
if ( property & GXV_PROP_ATTACHING_TO_RIGHT )
{
if ( GXV_PROP_DATA( version ) == 0x00010000UL )
+ {
+ GXV_TRACE(( " found older version (1.0) in new version table\n" ));
FT_INVALID_DATA;
+ }
}
if ( property & GXV_PROP_RESERVED )
+ {
+ GXV_TRACE(( " found non-zero bits in reserved bits\n" ));
FT_INVALID_DATA;
+ }
if ( ( property & GXV_PROP_DIRECTIONALITY_CLASS ) > 11 )
{
/* TODO: Too restricted. Use the validation level. */
if ( GXV_PROP_DATA( version ) == 0x00010000UL ||
GXV_PROP_DATA( version ) == 0x00020000UL )
+ {
+ GXV_TRACE(( " found too old version in directionality class\n" ));
FT_INVALID_DATA;
+ }
}
}
@@ -264,16 +282,26 @@
format = FT_NEXT_USHORT( p );
defaultProp = FT_NEXT_USHORT( p );
+ GXV_TRACE(( " version 0x%08x\n", version ));
+ GXV_TRACE(( " format 0x%04x\n", format ));
+ GXV_TRACE(( " defaultProp 0x%04x\n", defaultProp ));
+
/* only versions 1.0, 2.0, 3.0 are defined (1996) */
if ( version != 0x00010000UL &&
version != 0x00020000UL &&
version != 0x00030000UL )
+ {
+ GXV_TRACE(( " found unknown version\n" ));
FT_INVALID_FORMAT;
+ }
/* only formats 0x0000, 0x0001 are defined (1996) */
if ( format > 1 )
+ {
+ GXV_TRACE(( " found unknown format\n" ));
FT_INVALID_FORMAT;
+ }
gxv_prop_property_validate( defaultProp, 0, valid );
diff --git a/freetype/src/gxvalid/gxvtrak.c b/freetype/src/gxvalid/gxvtrak.c
index df3fd15c0..11fbd7ccf 100644
--- a/freetype/src/gxvalid/gxvtrak.c
+++ b/freetype/src/gxvalid/gxvtrak.c
@@ -97,10 +97,10 @@
{
FT_Bytes p = table;
- FT_Fixed track;
+ FT_Fixed track, t;
FT_UShort nameIndex;
FT_UShort offset;
- FT_UShort i;
+ FT_UShort i, j;
GXV_NAME_ENTER( "trackTable" );
@@ -108,9 +108,11 @@
GXV_TRAK_DATA( trackValueOffset_min ) = 0xFFFFU;
GXV_TRAK_DATA( trackValueOffset_max ) = 0x0000;
+ GXV_LIMIT_CHECK( nTracks * ( 4 + 2 + 2 ) );
+
for ( i = 0; i < nTracks; i ++ )
{
- GXV_LIMIT_CHECK( 4 + 2 + 2 );
+ p = table + i * ( 4 + 2 + 2 );
track = FT_NEXT_LONG( p );
nameIndex = FT_NEXT_USHORT( p );
offset = FT_NEXT_USHORT( p );
@@ -121,6 +123,15 @@
GXV_TRAK_DATA( trackValueOffset_max ) = offset;
gxv_sfntName_validate( nameIndex, 256, 32767, valid );
+
+ for ( j = i; j < nTracks; j ++ )
+ {
+ p = table + j * ( 4 + 2 + 2 );
+ t = FT_NEXT_LONG( p );
+ if ( t == track )
+ GXV_TRACE(( "duplicated entries found for track value 0x%x\n",
+ track ));
+ }
}
valid->subtable_length = p - table;
@@ -198,7 +209,6 @@
{
FT_Bytes p = table;
FT_Bytes limit = 0;
- FT_Offset table_size;
GXV_ValidatorRec validrec;
GXV_Validator valid = &validrec;
@@ -220,7 +230,6 @@
valid->face = face;
limit = valid->root->limit;
- table_size = limit - table;
FT_TRACE3(( "validating `trak' table\n" ));
GXV_INIT;
diff --git a/freetype/src/gzip/ftgzip.c b/freetype/src/gzip/ftgzip.c
index ef97f2725..14a852a8b 100644
--- a/freetype/src/gzip/ftgzip.c
+++ b/freetype/src/gzip/ftgzip.c
@@ -8,7 +8,7 @@
/* parse compressed PCF fonts, as found with many X11 server */
/* distributions. */
/* */
-/* Copyright 2002, 2003, 2004, 2005, 2006, 2009, 2010 by */
+/* Copyright 2002-2006, 2009-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -571,7 +571,7 @@
old_pos = stream->pos;
if ( !FT_Stream_Seek( stream, stream->size - 4 ) )
{
- result = (FT_ULong)FT_Stream_ReadLong( stream, &error );
+ result = FT_Stream_ReadULong( stream, &error );
if ( error )
result = 0;
@@ -588,7 +588,7 @@
{
FT_Error error;
FT_Memory memory = source->memory;
- FT_GZipFile zip;
+ FT_GZipFile zip = NULL;
/*
@@ -628,7 +628,7 @@
if ( zip_size != 0 && zip_size < 40 * 1024 )
{
- FT_Byte* zip_buff;
+ FT_Byte* zip_buff = NULL;
if ( !FT_ALLOC( zip_buff, zip_size ) )
diff --git a/freetype/src/lzw/ftlzw.c b/freetype/src/lzw/ftlzw.c
index 8a030c386..6522c3454 100644
--- a/freetype/src/lzw/ftlzw.c
+++ b/freetype/src/lzw/ftlzw.c
@@ -349,7 +349,7 @@
{
FT_Error error;
FT_Memory memory = source->memory;
- FT_LZWFile zip;
+ FT_LZWFile zip = NULL;
/*
diff --git a/freetype/src/pcf/README b/freetype/src/pcf/README
index cc1480b2d..8858d68ca 100644
--- a/freetype/src/pcf/README
+++ b/freetype/src/pcf/README
@@ -31,29 +31,11 @@ on linux/alpha.
Encodings
*********
-The variety of encodings that accompanies pcf fonts appears to encompass the
-small set defined in freetype.h. On the other hand, each pcf font defines
-two properties that specify encoding and registry.
+Use `FT_Get_BDF_Charset_ID' to access the encoding and registry.
-I decided to make these two properties directly accessible, leaving to the
-client application the work of interpreting them. For instance:
-
- #include "pcftypes.h" /* include/freetype/internal/pcftypes.h */
-
- FT_Face face;
- PCF_Public_Face pcfface;
-
- FT_New_Face( library,..., &face );
-
- pcfface = (PCF_Public_Face)face;
-
- if ((pcfface->charset_registry == "ISO10646") &&
- (pcfface->charset_encoding) == "1")) [..]
-
-Thus the driver always export `ft_encoding_none' as
-face->charmap.encoding. FT_Get_Char_Index() behavior is unmodified, that
-is, it converts the ULong value given as argument into the corresponding
-glyph number.
+The driver always exports `ft_encoding_none' as face->charmap.encoding.
+FT_Get_Char_Index() behavior is unmodified, that is, it converts the ULong
+value given as argument into the corresponding glyph number.
Known problems
diff --git a/freetype/src/pcf/pcf.h b/freetype/src/pcf/pcf.h
index 12e845eac..78549020b 100644
--- a/freetype/src/pcf/pcf.h
+++ b/freetype/src/pcf/pcf.h
@@ -2,7 +2,7 @@
FreeType font driver for pcf fonts
- Copyright (C) 2000, 2001, 2002, 2003, 2006 by
+ Copyright (C) 2000, 2001, 2002, 2003, 2006, 2010 by
Francesco Zappa Nardelli
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -136,8 +136,8 @@ FT_BEGIN_HEADER
{
FT_FaceRec root;
- FT_StreamRec gzip_stream;
- FT_Stream gzip_source;
+ FT_StreamRec comp_stream;
+ FT_Stream comp_source;
char* charset_encoding;
char* charset_registry;
diff --git a/freetype/src/pcf/pcfdrivr.c b/freetype/src/pcf/pcfdrivr.c
index 14c507e07..30acc7fb1 100644
--- a/freetype/src/pcf/pcfdrivr.c
+++ b/freetype/src/pcf/pcfdrivr.c
@@ -2,7 +2,8 @@
FreeType font driver for pcf files
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009,
+ 2010 by
Francesco Zappa Nardelli
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -32,6 +33,7 @@ THE SOFTWARE.
#include <freetype/internal/ftobjs.h>
#include FT_GZIP_H
#include FT_LZW_H
+#include FT_BZIP2_H
#include FT_ERRORS_H
#include FT_BDF_H
#include FT_TRUETYPE_IDS_H
@@ -248,11 +250,11 @@ THE SOFTWARE.
FT_TRACE4(( "PCF_Face_Done: done face\n" ));
- /* close gzip/LZW stream if any */
- if ( pcfface->stream == &face->gzip_stream )
+ /* close compressed stream if any */
+ if ( pcfface->stream == &face->comp_stream )
{
- FT_Stream_Close( &face->gzip_stream );
- pcfface->stream = face->gzip_source;
+ FT_Stream_Close( &face->comp_stream );
+ pcfface->stream = face->comp_source;
}
}
@@ -277,8 +279,9 @@ THE SOFTWARE.
{
PCF_Face_Done( pcfface );
-#if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \
- defined( FT_CONFIG_OPTION_USE_LZW )
+#if defined( FT_CONFIG_OPTION_USE_ZLIB ) || \
+ defined( FT_CONFIG_OPTION_USE_LZW ) || \
+ defined( FT_CONFIG_OPTION_USE_BZIP2 )
#ifdef FT_CONFIG_OPTION_USE_ZLIB
{
@@ -286,7 +289,7 @@ THE SOFTWARE.
/* this didn't work, try gzip support! */
- error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream );
+ error2 = FT_Stream_OpenGzip( &face->comp_stream, stream );
if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature )
goto Fail;
@@ -301,7 +304,7 @@ THE SOFTWARE.
/* this didn't work, try LZW support! */
- error3 = FT_Stream_OpenLZW( &face->gzip_stream, stream );
+ error3 = FT_Stream_OpenLZW( &face->comp_stream, stream );
if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature )
goto Fail;
@@ -309,11 +312,26 @@ THE SOFTWARE.
}
#endif /* FT_CONFIG_OPTION_USE_LZW */
+#ifdef FT_CONFIG_OPTION_USE_BZIP2
+ if ( error )
+ {
+ FT_Error error4;
+
+
+ /* this didn't work, try Bzip2 support! */
+ error4 = FT_Stream_OpenBzip2( &face->comp_stream, stream );
+ if ( FT_ERROR_BASE( error4 ) == FT_Err_Unimplemented_Feature )
+ goto Fail;
+
+ error = error4;
+ }
+#endif /* FT_CONFIG_OPTION_USE_BZIP2 */
+
if ( error )
goto Fail;
- face->gzip_source = stream;
- pcfface->stream = &face->gzip_stream;
+ face->comp_source = stream;
+ pcfface->stream = &face->comp_stream;
stream = pcfface->stream;
@@ -321,7 +339,9 @@ THE SOFTWARE.
if ( error )
goto Fail;
-#else /* !(FT_CONFIG_OPTION_USE_ZLIB || FT_CONFIG_OPTION_USE_LZW) */
+#else /* !(FT_CONFIG_OPTION_USE_ZLIB ||
+ FT_CONFIG_OPTION_USE_LZW ||
+ FT_CONFIG_OPTION_USE_BZIP2) */
goto Fail;
diff --git a/freetype/src/pcf/pcfread.c b/freetype/src/pcf/pcfread.c
index 596445e86..e08da6e72 100644
--- a/freetype/src/pcf/pcfread.c
+++ b/freetype/src/pcf/pcfread.c
@@ -399,7 +399,7 @@ THE SOFTWARE.
PCF_Face face )
{
PCF_ParseProperty props = 0;
- PCF_Property properties;
+ PCF_Property properties = NULL;
FT_ULong nprops, i;
FT_ULong format, size;
FT_Error error;
@@ -663,9 +663,9 @@ THE SOFTWARE.
pcf_get_bitmaps( FT_Stream stream,
PCF_Face face )
{
- FT_Error error = PCF_Err_Ok;
- FT_Memory memory = FT_FACE(face)->memory;
- FT_Long* offsets;
+ FT_Error error = PCF_Err_Ok;
+ FT_Memory memory = FT_FACE(face)->memory;
+ FT_Long* offsets = NULL;
FT_Long bitmapSizes[GLYPHPADOPTIONS];
FT_ULong format, size;
FT_ULong nbitmaps, i, sizebitmaps = 0;
@@ -772,7 +772,7 @@ THE SOFTWARE.
int firstRow, lastRow;
int nencoding, encodingOffset;
int i, j;
- PCF_Encoding tmpEncoding, encoding = 0;
+ PCF_Encoding tmpEncoding = NULL, encoding = 0;
error = pcf_seek_to_table_type( stream,
diff --git a/freetype/src/pfr/pfrload.c b/freetype/src/pfr/pfrload.c
index e9186e22c..2f5b4cb58 100644
--- a/freetype/src/pfr/pfrload.c
+++ b/freetype/src/pfr/pfrload.c
@@ -476,7 +476,7 @@
PFR_PhyFont phy_font )
{
FT_UInt count, num_vert, num_horz;
- FT_Int* snaps;
+ FT_Int* snaps = NULL;
FT_Error error = PFR_Err_Ok;
FT_Memory memory = phy_font->memory;
diff --git a/freetype/src/psaux/psobjs.c b/freetype/src/psaux/psobjs.c
index 8994e64e3..892d9821b 100644
--- a/freetype/src/psaux/psobjs.c
+++ b/freetype/src/psaux/psobjs.c
@@ -4,8 +4,7 @@
/* */
/* Auxiliary functions for PostScript fonts (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -186,13 +185,13 @@
/* grow the base block if needed */
if ( table->cursor + length > table->capacity )
{
- FT_Error error;
- FT_Offset new_size = table->capacity;
- FT_Long in_offset;
+ FT_Error error;
+ FT_Offset new_size = table->capacity;
+ FT_PtrDist in_offset;
- in_offset = (FT_Long)((FT_Byte*)object - table->block);
- if ( (FT_ULong)in_offset >= table->capacity )
+ in_offset = (FT_Byte*)object - table->block;
+ if ( in_offset < 0 || (FT_Offset)in_offset >= table->capacity )
in_offset = -1;
while ( new_size < table->cursor + length )
diff --git a/freetype/src/pshinter/rules.mk b/freetype/src/pshinter/rules.mk
index 57773394a..888ece105 100644
--- a/freetype/src/pshinter/rules.mk
+++ b/freetype/src/pshinter/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 2001, 2003 by
+# Copyright 2001, 2003, 2011 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -25,10 +25,11 @@ PSHINTER_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(PSHINTER_DIR))
# PSHINTER driver sources (i.e., C files)
#
-PSHINTER_DRV_SRC := $(PSHINTER_DIR)/pshrec.c \
+PSHINTER_DRV_SRC := $(PSHINTER_DIR)/pshalgo.c \
$(PSHINTER_DIR)/pshglob.c \
$(PSHINTER_DIR)/pshmod.c \
- $(PSHINTER_DIR)/pshalgo.c
+ $(PSHINTER_DIR)/pshpic.c \
+ $(PSHINTER_DIR)/pshrec.c
# PSHINTER driver headers
diff --git a/freetype/src/psnames/rules.mk b/freetype/src/psnames/rules.mk
index 06bd161e3..4cd39a8cc 100644
--- a/freetype/src/psnames/rules.mk
+++ b/freetype/src/psnames/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2000, 2001, 2003 by
+# Copyright 1996-2000, 2001, 2003, 2011 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -25,14 +25,15 @@ PSNAMES_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(PSNAMES_DIR))
# PSNames driver sources (i.e., C files)
#
-PSNAMES_DRV_SRC := $(PSNAMES_DIR)/psmodule.c
+PSNAMES_DRV_SRC := $(PSNAMES_DIR)/psmodule.c \
+ $(PSNAMES_DIR)/pspic.c
# PSNames driver headers
#
PSNAMES_DRV_H := $(PSNAMES_DRV_SRC:%.c=%.h) \
- $(PSNAMES_DIR)/pstables.h \
- $(PSNAMES_DIR)/psnamerr.h
+ $(PSNAMES_DIR)/psnamerr.h \
+ $(PSNAMES_DIR)/pstables.h
# PSNames driver object(s)
diff --git a/freetype/src/raster/ftraster.c b/freetype/src/raster/ftraster.c
index 0e7b7423c..daae074c8 100644
--- a/freetype/src/raster/ftraster.c
+++ b/freetype/src/raster/ftraster.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType glyph rasterizer (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010 by */
+/* Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -651,11 +651,33 @@
static void
Set_High_Precision( RAS_ARGS Int High )
{
+ /*
+ * `precision_step' is used in `Bezier_Up' to decide when to split a
+ * given y-monotonous Bezier arc that crosses a scanline before
+ * approximating it as a straight segment. The default value of 32 (for
+ * low accuracy) corresponds to
+ *
+ * 32 / 64 == 0.5 pixels ,
+ *
+ * while for the high accuracy case we have
+ *
+ * 256/ (1 << 12) = 0.0625 pixels .
+ *
+ * `precision_jitter' is an epsilon threshold used in
+ * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
+ * decomposition (after all, we are working with approximations only);
+ * it avoids switching on additional pixels which would cause artifacts
+ * otherwise.
+ *
+ * The value of `precision_jitter' has been determined heuristically.
+ *
+ */
+
if ( High )
{
ras.precision_bits = 12;
ras.precision_step = 256;
- ras.precision_jitter = 50;
+ ras.precision_jitter = 30;
}
else
{
@@ -2403,6 +2425,14 @@
return; /* no drop-out control */
}
+ /* undocumented but confirmed: If the drop-out would result in a */
+ /* pixel outside of the bounding box, use the pixel inside of the */
+ /* bounding box instead */
+ if ( pxl < 0 )
+ pxl = e1;
+ else if ( TRUNC( pxl ) >= ras.bWidth )
+ pxl = e2;
+
/* check that the other pixel isn't set */
e1 = pxl == e1 ? e2 : e1;
@@ -2579,6 +2609,14 @@
return; /* no drop-out control */
}
+ /* undocumented but confirmed: If the drop-out would result in a */
+ /* pixel outside of the bounding box, use the pixel inside of the */
+ /* bounding box instead */
+ if ( pxl < 0 )
+ pxl = e1;
+ else if ( TRUNC( pxl ) >= ras.target.rows )
+ pxl = e2;
+
/* check that the other pixel isn't set */
e1 = pxl == e1 ? e2 : e1;
diff --git a/freetype/src/raster/ftrend1.c b/freetype/src/raster/ftrend1.c
index 8ab1e6e3a..2279533fd 100644
--- a/freetype/src/raster/ftrend1.c
+++ b/freetype/src/raster/ftrend1.c
@@ -161,10 +161,18 @@
/* compute the control box, and grid fit it */
FT_Outline_Get_CBox( outline, &cbox );
+ /* undocumented but confirmed: bbox values get rounded */
+#if 1
+ cbox.xMin = FT_PIX_ROUND( cbox.xMin );
+ cbox.yMin = FT_PIX_ROUND( cbox.yMin );
+ cbox.xMax = FT_PIX_ROUND( cbox.xMax );
+ cbox.yMax = FT_PIX_ROUND( cbox.yMax );
+#else
cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
cbox.xMax = FT_PIX_CEIL( cbox.xMax );
cbox.yMax = FT_PIX_CEIL( cbox.yMax );
+#endif
width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
diff --git a/freetype/src/raster/rules.mk b/freetype/src/raster/rules.mk
index 9703b1298..0e0b5e4eb 100644
--- a/freetype/src/raster/rules.mk
+++ b/freetype/src/raster/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2000, 2001, 2003, 2008, 2009 by
+# Copyright 1996-2000, 2001, 2003, 2008, 2009, 2011 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -25,7 +25,8 @@ RASTER_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(RASTER_DIR))
# raster driver sources (i.e., C files)
#
RASTER_DRV_SRC := $(RASTER_DIR)/ftraster.c \
- $(RASTER_DIR)/ftrend1.c
+ $(RASTER_DIR)/ftrend1.c \
+ $(RASTER_DIR)/rastpic.c
# raster driver headers
diff --git a/freetype/src/sfnt/rules.mk b/freetype/src/sfnt/rules.mk
index abda74fca..02cee585d 100644
--- a/freetype/src/sfnt/rules.mk
+++ b/freetype/src/sfnt/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2000, 2002, 2003, 2004, 2005, 2006, 2007, 2009 by
+# Copyright 1996-2000, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2011 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -33,7 +33,8 @@ SFNT_DRV_SRC := $(SFNT_DIR)/ttload.c \
$(SFNT_DIR)/ttkern.c \
$(SFNT_DIR)/ttbdf.c \
$(SFNT_DIR)/sfobjs.c \
- $(SFNT_DIR)/sfdriver.c
+ $(SFNT_DIR)/sfdriver.c \
+ $(SFNT_DIR)/sfntpic.c
# SFNT driver headers
#
diff --git a/freetype/src/sfnt/sfdriver.c b/freetype/src/sfnt/sfdriver.c
index 77736f42c..9d008efd9 100644
--- a/freetype/src/sfnt/sfdriver.c
+++ b/freetype/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
/* */
/* High-level SFNT driver interface (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
+/* Copyright 1996-2007, 2009-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -117,15 +117,20 @@
FT_ULong *offset,
FT_ULong *length )
{
- if ( !tag || !offset || !length )
+ if ( !offset || !length )
return SFNT_Err_Invalid_Argument;
- if ( idx >= face->num_tables )
- return SFNT_Err_Table_Missing;
+ if ( !tag )
+ *length = face->num_tables;
+ else
+ {
+ if ( idx >= face->num_tables )
+ return SFNT_Err_Table_Missing;
- *tag = face->dir_tables[idx].Tag;
- *offset = face->dir_tables[idx].Offset;
- *length = face->dir_tables[idx].Length;
+ *tag = face->dir_tables[idx].Tag;
+ *offset = face->dir_tables[idx].Offset;
+ *length = face->dir_tables[idx].Length;
+ }
return SFNT_Err_Ok;
}
diff --git a/freetype/src/sfnt/sfobjs.c b/freetype/src/sfnt/sfobjs.c
index 449c6b000..10041e4dc 100644
--- a/freetype/src/sfnt/sfobjs.c
+++ b/freetype/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
/* */
/* SFNT object management (base). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
+/* Copyright 1996-2008, 2010-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -356,7 +356,7 @@
FT_FRAME_START( 8 ),
FT_FRAME_LONG( version ),
- FT_FRAME_LONG( count ),
+ FT_FRAME_LONG( count ), /* this is ULong in the specs */
FT_FRAME_END
};
@@ -390,6 +390,17 @@
if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
return error;
+ if ( face->ttc_header.count == 0 )
+ return SFNT_Err_Invalid_Table;
+
+ /* a rough size estimate: let's conservatively assume that there */
+ /* is just a single table info in each subfont header (12 + 16*1 = */
+ /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */
+ /* size of the TTC header plus `28*count' bytes for all subfont */
+ /* headers */
+ if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) )
+ return SFNT_Err_Array_Too_Large;
+
/* now read the offsets of each font in the file */
if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
return error;
@@ -536,7 +547,7 @@
FT_UNUSED( face_index );
/* Check parameters */
-
+
{
FT_Int i;
diff --git a/freetype/src/sfnt/ttload.c b/freetype/src/sfnt/ttload.c
index 65fa0015f..b0cb9fa77 100644
--- a/freetype/src/sfnt/ttload.c
+++ b/freetype/src/sfnt/ttload.c
@@ -1213,7 +1213,7 @@
FT_Memory memory = stream->memory;
FT_UInt j,num_ranges;
- TT_GaspRange gaspranges;
+ TT_GaspRange gaspranges = NULL;
/* the gasp table is optional */
diff --git a/freetype/src/sfnt/ttmtx.c b/freetype/src/sfnt/ttmtx.c
index 3b9f8606b..caa778c89 100644
--- a/freetype/src/sfnt/ttmtx.c
+++ b/freetype/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
/* */
/* Load the metrics tables common to TTF and OTF fonts (body). */
/* */
-/* Copyright 2006, 2007, 2008, 2009 by */
+/* Copyright 2006-2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -163,7 +163,7 @@
{
FT_TRACE0(( "tt_face_load_hmtx:"
" %cmtx has more metrics than glyphs.\n",
- vertical ? "v" : "h" ));
+ vertical ? 'v' : 'h' ));
/* Adobe simply ignores this problem. So we shall do the same. */
#if 0
diff --git a/freetype/src/sfnt/ttsbit.c b/freetype/src/sfnt/ttsbit.c
index efe8809f6..c138e0b2d 100644
--- a/freetype/src/sfnt/ttsbit.c
+++ b/freetype/src/sfnt/ttsbit.c
@@ -1343,7 +1343,7 @@
/* All right, we have a compound format. First of all, read */
/* the array of elements. */
{
- TT_SBit_Component components;
+ TT_SBit_Component components = NULL;
TT_SBit_Component comp;
FT_UShort num_components, count;
diff --git a/freetype/src/smooth/ftgrays.c b/freetype/src/smooth/ftgrays.c
index f0dae7a93..7b54d12f6 100644
--- a/freetype/src/smooth/ftgrays.c
+++ b/freetype/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, 2010 by */
+/* Copyright 2000-2003, 2005-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -890,14 +890,8 @@ typedef ptrdiff_t FT_PtrDist;
if ( dx < dy )
dx = dy;
- if ( dx <= ONE_PIXEL / 4 )
- {
- gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
- return;
- }
-
level = 0;
- while ( dx > ONE_PIXEL / 4 )
+ while ( dx > ONE_PIXEL / 6 )
{
dx >>= 2;
level++;
@@ -907,7 +901,7 @@ typedef ptrdiff_t FT_PtrDist;
levels[0] = level;
top = 0;
- while ( top >= 0 )
+ do
{
level = levels[top];
if ( level > 1 )
@@ -940,9 +934,8 @@ typedef ptrdiff_t FT_PtrDist;
gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
top--;
arc -= 2;
- }
- return;
+ } while ( top >= 0 );
}
diff --git a/freetype/src/smooth/ftsmooth.c b/freetype/src/smooth/ftsmooth.c
index dc0235ad5..ecdbce522 100644
--- a/freetype/src/smooth/ftsmooth.c
+++ b/freetype/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
/* */
/* Anti-aliasing renderer interface (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 by */
+/* Copyright 2000-2006, 2009-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -104,7 +104,10 @@
FT_Error error;
FT_Outline* outline = NULL;
FT_BBox cbox;
- FT_UInt width, height, height_org, width_org, pitch;
+ FT_UInt width, height, pitch;
+#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+ FT_UInt height_org, width_org;
+#endif
FT_Bitmap* bitmap;
FT_Memory memory;
FT_Int hmul = mode == FT_RENDER_MODE_LCD;
@@ -162,8 +165,10 @@
bitmap = &slot->bitmap;
memory = render->root.memory;
+#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
width_org = width;
height_org = height;
+#endif
/* release old bitmap buffer */
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
diff --git a/freetype/src/smooth/rules.mk b/freetype/src/smooth/rules.mk
index 4f27f01db..88d0aa53a 100644
--- a/freetype/src/smooth/rules.mk
+++ b/freetype/src/smooth/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2000, 2001, 2003 by
+# Copyright 1996-2000, 2001, 2003, 2011 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -25,7 +25,8 @@ SMOOTH_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(SMOOTH_DIR))
# smooth driver sources (i.e., C files)
#
SMOOTH_DRV_SRC := $(SMOOTH_DIR)/ftgrays.c \
- $(SMOOTH_DIR)/ftsmooth.c
+ $(SMOOTH_DIR)/ftsmooth.c \
+ $(SMOOTH_DIR)/ftspic.c
# smooth driver headers
diff --git a/freetype/src/tools/glnames.py b/freetype/src/tools/glnames.py
index 55573b22f..cf5114c10 100644
--- a/freetype/src/tools/glnames.py
+++ b/freetype/src/tools/glnames.py
@@ -6,7 +6,7 @@
#
-# Copyright 1996-2000, 2003, 2005, 2007, 2008 by
+# Copyright 1996-2000, 2003, 2005, 2007, 2008, 2011 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -151,7 +151,7 @@ mac_standard_names = \
# The list of standard `SID' glyph names. For the official list,
# see Annex A of document at
#
-# http://partners.adobe.com/asn/developer/pdfs/tn/5176.CFF.pdf.
+# http://partners.adobe.com/public/developer/en/font/5176.CFF.pdf .
#
sid_standard_names = \
[
@@ -415,8 +415,7 @@ t1_expert_encoding = \
# This data has been taken literally from the file `glyphlist.txt',
# version 2.0, 22 Sept 2002. It is available from
#
-# http://partners.adobe.com/asn/developer/typeforum/unicodegn.html
-# http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt
+# http://sourceforge.net/adobe/aglfn/
#
adobe_glyph_list = """\
A;0041
diff --git a/freetype/src/truetype/rules.mk b/freetype/src/truetype/rules.mk
index 74684260e..507ef16b0 100644
--- a/freetype/src/truetype/rules.mk
+++ b/freetype/src/truetype/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright 1996-2000, 2001, 2003, 2004 by
+# Copyright 1996-2000, 2001, 2003, 2004, 2011 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -25,12 +25,13 @@ TT_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(TT_DIR))
# TrueType driver sources (i.e., C files)
#
-TT_DRV_SRC := $(TT_DIR)/ttobjs.c \
- $(TT_DIR)/ttpload.c \
+TT_DRV_SRC := $(TT_DIR)/ttdriver.c \
$(TT_DIR)/ttgload.c \
+ $(TT_DIR)/ttgxvar.c \
$(TT_DIR)/ttinterp.c \
- $(TT_DIR)/ttgxvar.c \
- $(TT_DIR)/ttdriver.c
+ $(TT_DIR)/ttobjs.c \
+ $(TT_DIR)/ttpic.c \
+ $(TT_DIR)/ttpload.c
# TrueType driver headers
#
diff --git a/freetype/src/truetype/ttdriver.c b/freetype/src/truetype/ttdriver.c
index c3a7d53ab..e61f57fab 100644
--- a/freetype/src/truetype/ttdriver.c
+++ b/freetype/src/truetype/ttdriver.c
@@ -4,8 +4,7 @@
/* */
/* TrueType font driver implementation (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 */
-/* 2010 by */
+/* Copyright 1996-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -135,8 +134,6 @@
{
FT_UInt nn;
TT_Face face = (TT_Face) ttface;
- FT_Bool check = FT_BOOL(
- !( flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) );
/* XXX: TODO: check for sbits */
@@ -149,7 +146,7 @@
FT_UShort ah;
- TT_Get_VMetrics( face, start + nn, check, &tsb, &ah );
+ TT_Get_VMetrics( face, start + nn, &tsb, &ah );
advances[nn] = ah;
}
}
@@ -161,7 +158,7 @@
FT_UShort aw;
- TT_Get_HMetrics( face, start + nn, check, &lsb, &aw );
+ TT_Get_HMetrics( face, start + nn, &lsb, &aw );
advances[nn] = aw;
}
}
diff --git a/freetype/src/truetype/ttgload.c b/freetype/src/truetype/ttgload.c
index 5b7474449..cdbe61a8d 100644
--- a/freetype/src/truetype/ttgload.c
+++ b/freetype/src/truetype/ttgload.c
@@ -4,8 +4,7 @@
/* */
/* TrueType Glyph Loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -47,7 +46,7 @@
/*************************************************************************/
/* */
- /* Composite font flags. */
+ /* Composite glyph flags. */
/* */
#define ARGS_ARE_WORDS 0x0001
#define ARGS_ARE_XY_VALUES 0x0002
@@ -66,22 +65,16 @@
/*************************************************************************/
/* */
- /* Returns the horizontal metrics in font units for a given glyph. If */
- /* `check' is true, take care of monospaced fonts by returning the */
- /* advance width maximum. */
+ /* Return the horizontal metrics in font units for a given glyph. */
/* */
FT_LOCAL_DEF( void )
TT_Get_HMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* lsb,
FT_UShort* aw )
{
( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
- if ( check && face->postscript.isFixedPitch )
- *aw = face->horizontal.advance_Width_Max;
-
FT_TRACE5(( " advance width (font units): %d\n", *aw ));
FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));
}
@@ -89,7 +82,7 @@
/*************************************************************************/
/* */
- /* Returns the vertical metrics in font units for a given glyph. */
+ /* Return the vertical metrics in font units for a given glyph. */
/* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
/* table, typoAscender/Descender from the `OS/2' table would be used */
/* instead, and if there were no `OS/2' table, use ascender/descender */
@@ -97,18 +90,12 @@
/* apparently does: It uses the ppem value as the advance height, and */
/* sets the top side bearing to be zero. */
/* */
- /* The monospace `check' is probably not meaningful here, but we leave */
- /* it in for a consistent interface. */
- /* */
FT_LOCAL_DEF( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* tsb,
FT_UShort* ah )
{
- FT_UNUSED( check );
-
if ( face->vertical_info )
( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
@@ -151,13 +138,9 @@
TT_Get_HMetrics( face, glyph_index,
- (FT_Bool)!( loader->load_flags &
- FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&left_bearing,
&advance_width );
TT_Get_VMetrics( face, glyph_index,
- (FT_Bool)!( loader->load_flags &
- FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&top_bearing,
&advance_height );
@@ -1656,23 +1639,7 @@
/* get the device-independent horizontal advance; it is scaled later */
/* by the base layer. */
- {
- FT_Pos advance = loader->linear;
-
-
- /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
- /* correctly support DynaLab fonts, which have an incorrect */
- /* `advance_Width_Max' field! It is used, to my knowledge, */
- /* exclusively in the X-TrueType font server. */
- /* */
- if ( face->postscript.isFixedPitch &&
- ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
- advance = face->horizontal.advance_Width_Max;
-
- /* we need to return the advance in font units in linearHoriAdvance, */
- /* it will be scaled later by the base layer. */
- glyph->linearHoriAdvance = advance;
- }
+ glyph->linearHoriAdvance = loader->linear;
glyph->metrics.horiBearingX = bbox.xMin;
glyph->metrics.horiBearingY = bbox.yMax;
@@ -1869,6 +1836,7 @@
{
TT_Face face;
FT_Stream stream;
+ FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
face = (TT_Face)glyph->face;
@@ -1887,7 +1855,9 @@
if ( !size->cvt_ready )
{
- FT_Error error = tt_size_ready_bytecode( size );
+ FT_Error error = tt_size_ready_bytecode( size, pedantic );
+
+
if ( error )
return error;
}
@@ -1917,7 +1887,7 @@
for ( i = 0; i < size->cvt_size; i++ )
size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
- tt_size_run_prep( size );
+ tt_size_run_prep( size, pedantic );
}
/* see whether the cvt program has disabled hinting */
@@ -2047,9 +2017,6 @@
glyph->linearHoriAdvance = loader.linear;
glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
loader.vadvance;
- if ( face->postscript.isFixedPitch &&
- ( load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
- glyph->linearHoriAdvance = face->horizontal.advance_Width_Max;
}
return TT_Err_Ok;
diff --git a/freetype/src/truetype/ttgload.h b/freetype/src/truetype/ttgload.h
index 958d67d20..05f75882d 100644
--- a/freetype/src/truetype/ttgload.h
+++ b/freetype/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
/* */
/* TrueType Glyph Loader (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 by */
+/* Copyright 1996-2006, 2008, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -37,14 +37,12 @@ FT_BEGIN_HEADER
FT_LOCAL( void )
TT_Get_HMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* lsb,
FT_UShort* aw );
FT_LOCAL( void )
TT_Get_VMetrics( TT_Face face,
FT_UInt idx,
- FT_Bool check,
FT_Short* tsb,
FT_UShort* ah );
diff --git a/freetype/src/truetype/ttgxvar.c b/freetype/src/truetype/ttgxvar.c
index 700eb2acf..4eb125e5e 100644
--- a/freetype/src/truetype/ttgxvar.c
+++ b/freetype/src/truetype/ttgxvar.c
@@ -123,7 +123,7 @@
ft_var_readpackedpoints( FT_Stream stream,
FT_UInt *point_cnt )
{
- FT_UShort *points;
+ FT_UShort *points = NULL;
FT_Int n;
FT_Int runcnt;
FT_Int i;
@@ -622,7 +622,7 @@
FT_Error error = TT_Err_Ok;
FT_ULong fvar_start;
FT_Int i, j;
- FT_MM_Var* mmvar;
+ FT_MM_Var* mmvar = NULL;
FT_Fixed* next_coords;
FT_String* next_name;
FT_Var_Axis* a;
@@ -1325,7 +1325,7 @@
FT_Stream stream = face->root.stream;
FT_Memory memory = stream->memory;
GX_Blend blend = face->blend;
- FT_Vector* delta_xy;
+ FT_Vector* delta_xy = NULL;
FT_Error error;
FT_ULong glyph_start;
diff --git a/freetype/src/truetype/ttinterp.c b/freetype/src/truetype/ttinterp.c
index 2096cac11..b0ff5c622 100644
--- a/freetype/src/truetype/ttinterp.c
+++ b/freetype/src/truetype/ttinterp.c
@@ -4,8 +4,7 @@
/* */
/* TrueType bytecode interpreter (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 */
+/* Copyright 1996-2011 */
/* by David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -986,8 +985,8 @@
/* INS_$83 */ PACK( 0, 0 ),
/* INS_$84 */ PACK( 0, 0 ),
/* ScanCTRL */ PACK( 1, 0 ),
- /* SDVPTL[0] */ PACK( 2, 0 ),
- /* SDVPTL[1] */ PACK( 2, 0 ),
+ /* SDPVTL[0] */ PACK( 2, 0 ),
+ /* SDPVTL[1] */ PACK( 2, 0 ),
/* GetINFO */ PACK( 1, 1 ),
/* IDEF */ PACK( 1, 0 ),
/* ROLL */ PACK( 3, 3 ),
@@ -3167,44 +3166,54 @@
args[0] = CUR.top;
-#define DO_CINDEX \
- { \
- FT_Long L; \
- \
- \
- L = args[0]; \
- \
- if ( L <= 0 || L > CUR.args ) \
- CUR.error = TT_Err_Invalid_Reference; \
- else \
- args[0] = CUR.stack[CUR.args - L]; \
- }
-
-
-#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]; \
- if ( CUR.IP < 0 ) \
- CUR.error = TT_Err_Bad_Argument; \
+#define DO_CINDEX \
+ { \
+ FT_Long L; \
+ \
+ \
+ L = args[0]; \
+ \
+ if ( L <= 0 || L > CUR.args ) \
+ { \
+ if ( CUR.pedantic_hinting ) \
+ CUR.error = TT_Err_Invalid_Reference; \
+ args[0] = 0; \
+ } \
+ else \
+ args[0] = CUR.stack[CUR.args - L]; \
+ }
+
+
+#define DO_JROT \
+ if ( args[1] != 0 ) \
+ { \
+ if ( args[0] == 0 && CUR.args == 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ CUR.IP += args[0]; \
+ if ( CUR.IP < 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ CUR.step_ins = FALSE; \
+ }
+
+
+#define DO_JMPR \
+ if ( args[0] == 0 && CUR.args == 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ 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]; \
- if ( CUR.IP < 0 ) \
- CUR.error = TT_Err_Bad_Argument; \
- CUR.step_ins = FALSE; \
+#define DO_JROF \
+ if ( args[1] == 0 ) \
+ { \
+ if ( args[0] == 0 && CUR.args == 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ CUR.IP += args[0]; \
+ if ( CUR.IP < 0 ) \
+ CUR.error = TT_Err_Bad_Argument; \
+ CUR.step_ins = FALSE; \
}
@@ -4386,17 +4395,19 @@
if ( L <= 0 || L > CUR.args )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
}
+ else
+ {
+ K = CUR.stack[CUR.args - L];
- K = CUR.stack[CUR.args - L];
-
- FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
- &CUR.stack[CUR.args - L + 1],
- ( L - 1 ) );
+ FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ],
+ &CUR.stack[CUR.args - L + 1],
+ ( L - 1 ) );
- CUR.stack[CUR.args - 1] = K;
+ CUR.stack[CUR.args - 1] = K;
+ }
}
@@ -5039,12 +5050,8 @@
if ( BOUNDSL( L, CUR.zp2.n_points ) )
{
if ( CUR.pedantic_hinting )
- {
CUR.error = TT_Err_Invalid_Reference;
- return;
- }
- else
- R = 0;
+ R = 0;
}
else
{
@@ -5124,10 +5131,7 @@
BOUNDS( K, CUR.zp1.n_points ) )
{
if ( CUR.pedantic_hinting )
- {
CUR.error = TT_Err_Invalid_Reference;
- return;
- }
D = 0;
}
else
@@ -5465,8 +5469,9 @@
if ( CUR.top < CUR.GS.loop )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ goto Fail;
}
while ( CUR.GS.loop > 0 )
@@ -5489,6 +5494,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5676,8 +5682,9 @@
if ( CUR.top < CUR.GS.loop )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
}
if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
@@ -5703,6 +5710,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5837,8 +5845,9 @@
if ( CUR.top < CUR.GS.loop + 1 )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
}
#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
@@ -5882,6 +5891,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -5996,7 +6006,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
/* XXX: UNDOCUMENTED! */
@@ -6042,6 +6052,7 @@
CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+ Fail:
CUR.GS.rp0 = point;
CUR.GS.rp1 = point;
}
@@ -6067,7 +6078,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
/* XXX: Is there some undocumented feature while in the */
@@ -6152,6 +6163,7 @@
CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+ Fail:
CUR.GS.rp1 = CUR.GS.rp0;
CUR.GS.rp2 = point;
@@ -6189,7 +6201,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
if ( !cvtEntry )
@@ -6244,8 +6256,22 @@
/* refer to the same zone. */
if ( CUR.GS.gep0 == CUR.GS.gep1 )
- if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
+ {
+ /* XXX: According to Greg Hitchcock, the following wording is */
+ /* the right one: */
+ /* */
+ /* When the absolute difference between the value in */
+ /* the table [CVT] and the measurement directly from */
+ /* the outline is _greater_ than the cut_in value, the */
+ /* outline measurement is used. */
+ /* */
+ /* This is from `instgly.doc'. The description in */
+ /* `ttinst2.doc', version 1.66, is thus incorrect since */
+ /* it implies `>=' instead of `>'. */
+
+ if ( FT_ABS( cvt_dist - org_dist ) > CUR.GS.control_value_cutin )
cvt_dist = org_dist;
+ }
distance = CUR_Func_round(
cvt_dist,
@@ -6274,6 +6300,7 @@
CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+ Fail:
CUR.GS.rp1 = CUR.GS.rp0;
if ( ( CUR.opcode & 16 ) != 0 )
@@ -6304,7 +6331,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
while ( CUR.GS.loop > 0 )
@@ -6332,6 +6359,7 @@
CUR.GS.loop--;
}
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -6473,8 +6501,9 @@
if ( CUR.top < CUR.GS.loop )
{
- CUR.error = TT_Err_Invalid_Reference;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Invalid_Reference;
+ goto Fail;
}
/*
@@ -6488,7 +6517,7 @@
{
if ( CUR.pedantic_hinting )
CUR.error = TT_Err_Invalid_Reference;
- return;
+ goto Fail;
}
if ( twilight )
@@ -6553,6 +6582,8 @@
CUR_Func_move( &CUR.zp2, (FT_UShort)point, new_dist - cur_dist );
}
+
+ Fail:
CUR.GS.loop = 1;
CUR.new_top = CUR.args;
}
@@ -6845,8 +6876,9 @@
if ( CUR.args < n )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ n = CUR.args;
}
CUR.args -= n;
@@ -6862,8 +6894,10 @@
{
if ( CUR.args < 2 )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ CUR.args = 0;
+ goto Fail;
}
CUR.args -= 2;
@@ -6912,6 +6946,7 @@
CUR.error = TT_Err_Invalid_Reference;
}
+ Fail:
CUR.new_top = CUR.args;
}
@@ -6939,8 +6974,9 @@
if ( CUR.args < n )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ n = CUR.args;
}
CUR.args -= n;
@@ -6955,8 +6991,10 @@
{
if ( CUR.args < 2 )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- return;
+ if ( CUR.pedantic_hinting )
+ CUR.error = TT_Err_Too_Few_Arguments;
+ CUR.args = 0;
+ goto Fail;
}
CUR.args -= 2;
@@ -7004,6 +7042,7 @@
}
}
+ Fail:
CUR.new_top = CUR.args;
}
@@ -7465,8 +7504,19 @@
/* One can also interpret it as the index of the last argument. */
if ( CUR.args < 0 )
{
- CUR.error = TT_Err_Too_Few_Arguments;
- goto LErrorLabel_;
+ FT_UShort i;
+
+
+ if ( CUR.pedantic_hinting )
+ {
+ CUR.error = TT_Err_Too_Few_Arguments;
+ goto LErrorLabel_;
+ }
+
+ /* push zeroes onto the stack */
+ for ( i = 0; i < Pop_Push_Count[CUR.opcode] >> 4; i++ )
+ CUR.stack[i] = 0;
+ CUR.args = 0;
}
CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
@@ -7503,7 +7553,7 @@
case 0x04: /* SFvTCA y */
case 0x05: /* SFvTCA x */
{
- FT_Short AA, BB;
+ FT_Short AA, BB;
AA = (FT_Short)( ( opcode & 1 ) << 14 );
diff --git a/freetype/src/truetype/ttobjs.c b/freetype/src/truetype/ttobjs.c
index f09218239..f24c774e2 100644
--- a/freetype/src/truetype/ttobjs.c
+++ b/freetype/src/truetype/ttobjs.c
@@ -4,8 +4,7 @@
/* */
/* Objects manager (body). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
-/* 2010 by */
+/* Copyright 1996-2011 */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -214,16 +213,18 @@
tt_get_sfnt_checksum( TT_Face face,
FT_UShort i )
{
+#if 0 /* if we believe the written value, use following part. */
if ( face->dir_tables[i].CheckSum )
return face->dir_tables[i].CheckSum;
+#endif
- else if ( !face->goto_table )
+ if ( !face->goto_table )
return 0;
- else if ( !face->goto_table( face,
- face->dir_tables[i].Tag,
- face->root.stream,
- NULL ) )
+ if ( face->goto_table( face,
+ face->dir_tables[i].Tag,
+ face->root.stream,
+ NULL ) )
return 0;
return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
@@ -243,7 +244,7 @@
tt_check_trickyness_sfnt_ids( TT_Face face )
{
#define TRICK_SFNT_IDS_PER_FACE 3
-#define TRICK_SFNT_IDS_NUM_FACES 5
+#define TRICK_SFNT_IDS_NUM_FACES 13
static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
[TRICK_SFNT_IDS_PER_FACE] = {
@@ -276,16 +277,61 @@
{ 0xfffbfffc, 0x00000008 }, /* cvt */
{ 0x0a5a0483, 0x00017c39 }, /* fpgm */
{ 0x70020112, 0x00000008 } /* prep */
+ },
+ { /* NEC fadpop7.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x40c92555, 0x000000e5 }, /* fpgm */
+ { 0xa39b58e3, 0x0000117c } /* prep */
+ },
+ { /* NEC fadrei5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x33c41652, 0x000000e5 }, /* fpgm */
+ { 0x26d6c52a, 0x00000f6a } /* prep */
+ },
+ { /* NEC fangot7.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x6db1651d, 0x0000019d }, /* fpgm */
+ { 0x6c6e4b03, 0x00002492 } /* prep */
+ },
+ { /* NEC fangyo5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x40c92555, 0x000000e5 }, /* fpgm */
+ { 0xde51fad0, 0x0000117c } /* prep */
+ },
+ { /* NEC fankyo5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x85e47664, 0x000000e5 }, /* fpgm */
+ { 0xa6c62831, 0x00001caa } /* prep */
+ },
+ { /* NEC fanrgo5.ttf */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x2d891cfd, 0x0000019d }, /* fpgm */
+ { 0xa0604633, 0x00001de8 } /* prep */
+ },
+ { /* NEC fangot5.ttc */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x40aa774c, 0x000001cb }, /* fpgm */
+ { 0x9b5caa96, 0x00001f9a } /* prep */
+ },
+ { /* NEC fanmin3.ttc */
+ { 0x00000000, 0x00000000 }, /* cvt */
+ { 0x0d3de9cb, 0x00000141 }, /* fpgm */
+ { 0xd4127766, 0x00002280 } /* prep */
}
};
- FT_ULong checksum;
- int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
- int i, j, k;
+ FT_ULong checksum;
+ int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
+ FT_Bool has_cvt, has_fpgm, has_prep;
+ FT_UShort i;
+ int j, k;
FT_MEM_SET( num_matched_ids, 0,
sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES );
+ has_cvt = FALSE;
+ has_fpgm = FALSE;
+ has_prep = FALSE;
for ( i = 0; i < face->num_tables; i++ )
{
@@ -295,14 +341,17 @@
{
case TTAG_cvt:
k = TRICK_SFNT_ID_cvt;
+ has_cvt = TRUE;
break;
case TTAG_fpgm:
k = TRICK_SFNT_ID_fpgm;
+ has_fpgm = TRUE;
break;
case TTAG_prep:
k = TRICK_SFNT_ID_prep;
+ has_prep = TRUE;
break;
default:
@@ -323,6 +372,18 @@
}
}
+ for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
+ {
+ if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
+ num_matched_ids[j] ++;
+ if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
+ num_matched_ids[j] ++;
+ if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
+ num_matched_ids[j] ++;
+ if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
+ return TRUE;
+ }
+
return FALSE;
}
@@ -333,14 +394,10 @@
if ( !face )
return FALSE;
- /* First, check the face name. */
- if ( face->family_name )
- {
- if ( tt_check_trickyness_family( face->family_name ) )
- return TRUE;
- else
- return FALSE;
- }
+ /* For first, check the face name for quick check. */
+ if ( face->family_name &&
+ tt_check_trickyness_family( face->family_name ) )
+ return TRUE;
/* Type42 fonts may lack `name' tables, we thus try to identify */
/* tricky fonts by checking the checksums of Type42-persistent */
@@ -570,13 +627,16 @@
/* Run the font program. */
/* */
/* <Input> */
- /* size :: A handle to the size object. */
+ /* size :: A handle to the size object. */
+ /* */
+ /* pedantic :: Set if bytecode execution should be pedantic. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
- tt_size_run_fpgm( TT_Size size )
+ tt_size_run_fpgm( TT_Size size,
+ FT_Bool pedantic )
{
TT_Face face = (TT_Face)size->root.face;
TT_ExecContext exec;
@@ -594,15 +654,17 @@
TT_Load_Context( exec, face, size );
- exec->callTop = 0;
- exec->top = 0;
+ exec->callTop = 0;
+ exec->top = 0;
exec->period = 64;
exec->phase = 0;
exec->threshold = 0;
exec->instruction_trap = FALSE;
- exec->F_dot_P = 0x10000L;
+ exec->F_dot_P = 0x10000L;
+
+ exec->pedantic_hinting = pedantic;
{
FT_Size_Metrics* metrics = &exec->metrics;
@@ -659,13 +721,16 @@
/* Run the control value program. */
/* */
/* <Input> */
- /* size :: A handle to the size object. */
+ /* size :: A handle to the size object. */
+ /* */
+ /* pedantic :: Set if bytecode execution should be pedantic. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
- tt_size_run_prep( TT_Size size )
+ tt_size_run_prep( TT_Size size,
+ FT_Bool pedantic )
{
TT_Face face = (TT_Face)size->root.face;
TT_ExecContext exec;
@@ -688,6 +753,8 @@
exec->instruction_trap = FALSE;
+ exec->pedantic_hinting = pedantic;
+
TT_Set_CodeRange( exec,
tt_coderange_cvt,
face->cvt_program,
@@ -766,7 +833,8 @@
/* Initialize bytecode-related fields in the size object. */
/* We do this only if bytecode interpretation is really needed. */
static FT_Error
- tt_size_init_bytecode( FT_Size ftsize )
+ tt_size_init_bytecode( FT_Size ftsize,
+ FT_Bool pedantic )
{
FT_Error error;
TT_Size size = (TT_Size)ftsize;
@@ -839,7 +907,7 @@
}
/* Fine, now run the font program! */
- error = tt_size_run_fpgm( size );
+ error = tt_size_run_fpgm( size, pedantic );
Exit:
if ( error )
@@ -850,14 +918,15 @@
FT_LOCAL_DEF( FT_Error )
- tt_size_ready_bytecode( TT_Size size )
+ tt_size_ready_bytecode( TT_Size size,
+ FT_Bool pedantic )
{
FT_Error error = TT_Err_Ok;
if ( !size->bytecode_ready )
{
- error = tt_size_init_bytecode( (FT_Size)size );
+ error = tt_size_init_bytecode( (FT_Size)size, pedantic );
if ( error )
goto Exit;
}
@@ -889,7 +958,7 @@
size->GS = tt_default_graphics_state;
- error = tt_size_run_prep( size );
+ error = tt_size_run_prep( size, pedantic );
if ( !error )
size->cvt_ready = 1;
}
diff --git a/freetype/src/truetype/ttobjs.h b/freetype/src/truetype/ttobjs.h
index cbbccfc76..c7b543cc5 100644
--- a/freetype/src/truetype/ttobjs.h
+++ b/freetype/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
/* */
/* Objects manager (specification). */
/* */
-/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/* Copyright 1996-2009, 2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -390,13 +390,16 @@ FT_BEGIN_HEADER
#ifdef TT_USE_BYTECODE_INTERPRETER
FT_LOCAL( FT_Error )
- tt_size_run_fpgm( TT_Size size );
+ tt_size_run_fpgm( TT_Size size,
+ FT_Bool pedantic );
FT_LOCAL( FT_Error )
- tt_size_run_prep( TT_Size size );
+ tt_size_run_prep( TT_Size size,
+ FT_Bool pedantic );
FT_LOCAL( FT_Error )
- tt_size_ready_bytecode( TT_Size size );
+ tt_size_ready_bytecode( TT_Size size,
+ FT_Bool pedantic );
#endif /* TT_USE_BYTECODE_INTERPRETER */
diff --git a/freetype/src/truetype/ttpload.c b/freetype/src/truetype/ttpload.c
index 56d6efe58..00f3ad5fb 100644
--- a/freetype/src/truetype/ttpload.c
+++ b/freetype/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (body). */
/* */
-/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
+/* Copyright 1996-2002, 2004-2011 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -110,15 +110,16 @@
face->num_locations = table_len >> shift;
}
- if ( face->num_locations != (FT_ULong)face->root.num_glyphs )
+ if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
{
FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
- face->num_locations, face->root.num_glyphs ));
+ face->num_locations - 1, face->root.num_glyphs ));
/* we only handle the case where `maxp' gives a larger value */
- if ( face->num_locations < (FT_ULong)face->root.num_glyphs )
+ if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
{
- FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift;
+ FT_Long new_loca_len =
+ ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
TT_Table entry = face->dir_tables;
TT_Table limit = entry + face->num_tables;
@@ -145,7 +146,7 @@
if ( new_loca_len <= dist )
{
- face->num_locations = face->root.num_glyphs;
+ face->num_locations = face->root.num_glyphs + 1;
table_len = new_loca_len;
FT_TRACE2(( "adjusting num_locations to %d\n",
diff --git a/freetype/src/type1/t1load.c b/freetype/src/type1/t1load.c
index 480a3a6b0..6d1ab9fe0 100644
--- a/freetype/src/type1/t1load.c
+++ b/freetype/src/type1/t1load.c
@@ -303,7 +303,7 @@
FT_MM_Var* *master )
{
FT_Memory memory = face->root.memory;
- FT_MM_Var *mmvar;
+ FT_MM_Var *mmvar = NULL;
FT_Multi_Master mmaster;
FT_Error error;
FT_UInt i;