[Merge] lp:~3v1n0/ubuntu/vivid/freetype/multithread-safe into lp:ubuntu/freetype

Marco Trevisan (Treviño) mail at 3v1n0.net
Mon Jan 26 14:42:12 UTC 2015



Diff comments:

> === modified file 'debian/changelog'
> --- debian/changelog	2014-09-19 17:11:19 +0000
> +++ debian/changelog	2015-01-23 02:45:23 +0000
> @@ -1,3 +1,10 @@
> +freetype (2.5.2-2ubuntu2) UNRELEASED; urgency=medium
> +
> +  * Added patchset to fix multithread violations, LP: #1199571
> +    - debian/patches-freetype/multi-thread-violations.patch
> +
> + -- Marco Trevisan (Treviño) <marco at ubuntu.com>  Fri, 23 Jan 2015 03:23:18 +0100
> +
>  freetype (2.5.2-2ubuntu1) utopic; urgency=medium
>  
>    * Merge from Debian unstable, remaining changes:
> 
> === modified file 'debian/libfreetype6.symbols'
> --- debian/libfreetype6.symbols	2013-12-29 02:56:08 +0000
> +++ debian/libfreetype6.symbols	2015-01-23 02:45:23 +0000
> @@ -311,7 +311,6 @@
>   ft_property_do at Base 2.4.11
>   ft_raccess_guess_table at Base 2.4.9
>   ft_raster1_renderer_class at Base 2.2.1
> - ft_raster5_renderer_class at Base 2.2.1

This looks like a private symbol to me, BTW I guess we can both update the SONAME and re-add this definition.

>   ft_service_list_lookup at Base 2.2.1
>   ft_smooth_lcd_renderer_class at Base 2.2.1
>   ft_smooth_lcdv_renderer_class at Base 2.2.1
> 
> === added file 'debian/patches-freetype/multi-thread-violations.patch'
> --- debian/patches-freetype/multi-thread-violations.patch	1970-01-01 00:00:00 +0000
> +++ debian/patches-freetype/multi-thread-violations.patch	2015-01-23 02:45:23 +0000
> @@ -0,0 +1,2098 @@
> +Author: Behdad Esfahbod <behdad at behdad.org>
> +Description: Multithread-safe FreeType
> +Forwarded: http://www.mail-archive.com/freetype-devel@nongnu.org/msg06758.html
> +Bug: https://bugs.freedesktop.org/show_bug.cgi?id=69034
> +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/freetype/+bug/1199571
> +Origin: upstream, https://github.com/behdad/freetype/commits/ftthread
> +Applied-Upstream: 2.5.6, git commits 89bc8d4d, 531d463a, 747ae2c8, 8dc86358,
> + a773c304, 6dfdaf4d, 51634253, 603292d7, b2ba6866, c242fe41, ae6699f8, a4117fbd,
> + c2733656, 6f16b100, 56ddafa0, 48c86628, 4eff854c
> +
> +
> +Index: freetype-2.5.2/devel/ftoption.h
> +===================================================================
> +--- freetype-2.5.2.orig/devel/ftoption.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/devel/ftoption.h	2015-01-23 02:55:34.532290414 +0100
> +@@ -365,10 +365,6 @@
> +   /* The size in bytes of the render pool used by the scan-line converter  */
> +   /* to do all of its work.                                                */
> +   /*                                                                       */
> +-  /* This must be greater than 4KByte if you use FreeType to rasterize     */
> +-  /* glyphs; otherwise, you may set it to zero to avoid unnecessary        */
> +-  /* allocation of the render pool.                                        */
> +-  /*                                                                       */
> + #define FT_RENDER_POOL_SIZE  16384L
> + 
> + 
> +Index: freetype-2.5.2/include/config/ftoption.h
> +===================================================================
> +--- freetype-2.5.2.orig/include/config/ftoption.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/include/config/ftoption.h	2015-01-23 02:55:34.536290423 +0100
> +@@ -365,10 +365,6 @@
> +   /* The size in bytes of the render pool used by the scan-line converter  */
> +   /* to do all of its work.                                                */
> +   /*                                                                       */
> +-  /* This must be greater than 4KByte if you use FreeType to rasterize     */
> +-  /* glyphs; otherwise, you may set it to zero to avoid unnecessary        */
> +-  /* allocation of the render pool.                                        */
> +-  /*                                                                       */
> + #define FT_RENDER_POOL_SIZE  16384L
> + 
> + 
> +Index: freetype-2.5.2/include/freetype.h
> +===================================================================
> +--- freetype-2.5.2.orig/include/freetype.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/include/freetype.h	2015-01-23 02:55:34.536290423 +0100
> +@@ -332,8 +332,11 @@
> +   /*    It also embeds a memory manager (see @FT_Memory), as well as a     */
> +   /*    scan-line converter object (see @FT_Raster).                       */
> +   /*                                                                       */
> +-  /*    In multi-threaded applications, make sure that the same FT_Library */
> +-  /*    object or any of its children doesn't get accessed in parallel.    */
> ++  /*    In multi-threaded applications it is easiest to use one            */
> ++  /*    `FT_Library' object per thread.  In case this is too cumbersome,   */
> ++  /*    a single `FT_Library' object across threads is possible also       */
> ++  /*    (since FreeType version 2.5.6), as long as a mutex lock is used    */
> ++  /*    around @FT_New_Face and @FT_Done_Face.                             */
> +   /*                                                                       */
> +   /* <Note>                                                                */
> +   /*    Library objects are normally created by @FT_Init_FreeType, and     */
> +@@ -401,6 +404,14 @@
> +   /*                                                                       */
> +   /*    Use @FT_Done_Face to destroy it (along with its slot and sizes).   */
> +   /*                                                                       */
> ++  /*    An `FT_Face' object can only be safely used from one thread at a   */
> ++  /*    time.  Similarly, creation and destruction of `FT_Face' with the   */
> ++  /*    same @FT_Library object can only be done from one thread at a      */
> ++  /*    time.  On the other hand, functions like @FT_Load_Glyph and its    */
> ++  /*    siblings are thread-safe and do not need the lock to be held as    */
> ++  /*    long as the same `FT_Face' object is not used from multiple        */
> ++  /*    threads at the same time.                                          */
> ++  /*                                                                       */
> +   /* <Also>                                                                */
> +   /*    See @FT_FaceRec for the publicly accessible fields of a given face */
> +   /*    object.                                                            */
> +@@ -1701,8 +1712,8 @@
> +   /*    use @FT_New_Library instead, followed by a call to                 */
> +   /*    @FT_Add_Default_Modules (or a series of calls to @FT_Add_Module).  */
> +   /*                                                                       */
> +-  /*    For multi-threading applications each thread should have its own   */
> +-  /*    FT_Library object.                                                 */
> ++  /*    See the documentation of @FT_Library and @FT_Face for              */
> ++  /*    multi-threading issues.                                            */
> +   /*                                                                       */
> +   /*    If you need reference-counting (cf. @FT_Reference_Library), use    */
> +   /*    @FT_New_Library and @FT_Done_Library.                              */
> +Index: freetype-2.5.2/include/ftimage.h
> +===================================================================
> +--- freetype-2.5.2.orig/include/ftimage.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/include/ftimage.h	2015-01-23 02:55:34.536290423 +0100
> +@@ -1179,10 +1179,10 @@
> +   /*    FT_Raster_ResetFunc                                                */
> +   /*                                                                       */
> +   /* <Description>                                                         */
> +-  /*    FreeType provides an area of memory called the `render pool',      */
> +-  /*    available to all registered rasters.  This pool can be freely used */
> +-  /*    during a given scan-conversion but is shared by all rasters.  Its  */
> +-  /*    content is thus transient.                                         */
> ++  /*    FreeType used to provide an area of memory called the `render      */
> ++  /*    pool' available to all registered rasters.  This was not thread    */
> ++  /*    safe however and now FreeType never allocates this pool.  NULL     */
> ++  /*    is always passed in as pool_base.                                  */
> +   /*                                                                       */
> +   /*    This function is called each time the render pool changes, or just */
> +   /*    after a new raster object is created.                              */
> +@@ -1195,10 +1195,9 @@
> +   /*    pool_size :: The size in bytes of the render pool.                 */
> +   /*                                                                       */
> +   /* <Note>                                                                */
> +-  /*    Rasters can ignore the render pool and rely on dynamic memory      */
> ++  /*    Rasters should ignore the render pool and rely on dynamic or stack */
> +   /*    allocation if they want to (a handle to the memory allocator is    */
> +-  /*    passed to the raster constructor).  However, this is not           */
> +-  /*    recommended for efficiency purposes.                               */
> ++  /*    passed to the raster constructor).                                 */
> +   /*                                                                       */
> +   typedef void
> +   (*FT_Raster_ResetFunc)( FT_Raster       raster,
> +Index: freetype-2.5.2/include/ftrender.h
> +===================================================================
> +--- freetype-2.5.2.orig/include/ftrender.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/include/ftrender.h	2015-01-23 02:55:34.536290423 +0100
> +@@ -212,13 +212,8 @@
> +   /*                                                                       */
> +   /*    This doesn't change the current renderer for other formats.        */
> +   /*                                                                       */
> +-  /*    Currently, only the B/W renderer, if compiled with                 */
> +-  /*    FT_RASTER_OPTION_ANTI_ALIASING (providing a 5-levels               */
> +-  /*    anti-aliasing mode; this option must be set directly in            */
> +-  /*    `ftraster.c' and is undefined by default) accepts a single tag     */
> +-  /*    `pal5' to set its gray palette as a character string with          */
> +-  /*    5~elements.  Consequently, the third and fourth argument are zero  */
> +-  /*    normally.                                                          */
> ++  /*    Currently, no FreeType renderer module uses `parameters'; you      */
> ++  /*    should thus always pass NULL as the value.                         */
> +   /*                                                                       */
> +   FT_EXPORT( FT_Error )
> +   FT_Set_Renderer( FT_Library     library,
> +Index: freetype-2.5.2/include/internal/ftobjs.h
> +===================================================================
> +--- freetype-2.5.2.orig/include/internal/ftobjs.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/include/internal/ftobjs.h	2015-01-23 02:55:34.540290431 +0100
> +@@ -738,9 +738,8 @@
> +   /*     faces_list   :: The list of faces currently opened by this        */
> +   /*                     driver.                                           */
> +   /*                                                                       */
> +-  /*     glyph_loader :: The glyph loader for all faces managed by this    */
> +-  /*                     driver.  This object isn't defined for unscalable */
> +-  /*                     formats.                                          */
> ++  /*     glyph_loader :: Unused.  Used to be glyph loader for all faces    */
> ++  /*                     managed by this driver.                           */
> +   /*                                                                       */
> +   typedef struct  FT_DriverRec_
> +   {
> +Index: freetype-2.5.2/src/autofit/afhints.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/autofit/afhints.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/autofit/afhints.c	2015-01-23 02:55:34.540290431 +0100
> +@@ -43,7 +43,15 @@
> +     AF_Segment  segment = NULL;
> + 
> + 
> +-    if ( axis->num_segments >= axis->max_segments )
> ++    if ( axis->num_segments < AF_SEGMENTS_EMBEDDED )
> ++    {
> ++      if ( axis->segments == NULL )
> ++      {
> ++        axis->segments     = axis->embedded.segments;
> ++        axis->max_segments = AF_SEGMENTS_EMBEDDED;
> ++      }
> ++    }
> ++    else if ( axis->num_segments >= axis->max_segments )
> +     {
> +       FT_Int  old_max = axis->max_segments;
> +       FT_Int  new_max = old_max;
> +@@ -60,8 +68,18 @@
> +       if ( new_max < old_max || new_max > big_max )
> +         new_max = big_max;
> + 
> +-      if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
> +-        goto Exit;
> ++      if ( axis->segments == axis->embedded.segments )
> ++      {
> ++        if ( FT_NEW_ARRAY( axis->segments, new_max ) )
> ++          goto Exit;
> ++        ft_memcpy( axis->segments, axis->embedded.segments,
> ++                   sizeof ( axis->embedded.segments ) );
> ++      }
> ++      else
> ++      {
> ++        if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
> ++          goto Exit;
> ++      }
> + 
> +       axis->max_segments = new_max;
> +     }
> +@@ -88,7 +106,15 @@
> +     AF_Edge   edges;
> + 
> + 
> +-    if ( axis->num_edges >= axis->max_edges )
> ++    if ( axis->num_edges < AF_EDGES_EMBEDDED )
> ++    {
> ++      if ( axis->edges == NULL )
> ++      {
> ++        axis->edges     = axis->embedded.edges;
> ++        axis->max_edges = AF_EDGES_EMBEDDED;
> ++      }
> ++    }
> ++    else if ( axis->num_edges >= axis->max_edges )
> +     {
> +       FT_Int  old_max = axis->max_edges;
> +       FT_Int  new_max = old_max;
> +@@ -105,8 +131,18 @@
> +       if ( new_max < old_max || new_max > big_max )
> +         new_max = big_max;
> + 
> +-      if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
> +-        goto Exit;
> ++      if ( axis->edges == axis->embedded.edges )
> ++      {
> ++        if ( FT_NEW_ARRAY( axis->edges, new_max ) )
> ++          goto Exit;
> ++        ft_memcpy( axis->edges, axis->embedded.edges,
> ++                   sizeof ( axis->embedded.edges ) );
> ++      }
> ++      else
> ++      {
> ++        if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
> ++          goto Exit;
> ++      }
> + 
> +       axis->max_edges = new_max;
> +     }
> +@@ -485,7 +521,8 @@
> +   af_glyph_hints_init( AF_GlyphHints  hints,
> +                        FT_Memory      memory )
> +   {
> +-    FT_ZERO( hints );
> ++    /* no need to initialize the embedded items */
> ++    FT_MEM_ZERO( hints, sizeof ( *hints ) - sizeof ( hints->embedded ) );
> +     hints->memory = memory;
> +   }
> + 
> +@@ -511,20 +548,24 @@
> + 
> +       axis->num_segments = 0;
> +       axis->max_segments = 0;
> +-      FT_FREE( axis->segments );
> ++      if ( axis->segments != axis->embedded.segments )
> ++        FT_FREE( axis->segments );
> + 
> +       axis->num_edges = 0;
> +       axis->max_edges = 0;
> +-      FT_FREE( axis->edges );
> ++      if ( axis->edges != axis->embedded.edges )
> ++        FT_FREE( axis->edges );
> +     }
> + 
> +-    FT_FREE( hints->contours );
> ++    if ( hints->contours != hints->embedded.contours )
> ++      FT_FREE( hints->contours );
> +     hints->max_contours = 0;
> +     hints->num_contours = 0;
> + 
> +-    FT_FREE( hints->points );
> +-    hints->num_points = 0;
> ++    if ( hints->points != hints->embedded.points )
> ++      FT_FREE( hints->points );
> +     hints->max_points = 0;
> ++    hints->num_points = 0;
> + 
> +     hints->memory = NULL;
> +   }
> +@@ -569,8 +610,14 @@
> +     /* 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 )
> ++
> ++    if ( new_max <= AF_CONTOURS_EMBEDDED )
> ++      hints->contours = hints->embedded.contours;
> ++    else if ( new_max > old_max )
> +     {
> ++      if ( hints->contours == hints->embedded.contours )
> ++        hints->contours = NULL;
> ++
> +       new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
> + 
> +       if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
> +@@ -586,8 +633,14 @@
> +      */
> +     new_max = (FT_UInt)( outline->n_points + 2 );
> +     old_max = hints->max_points;
> +-    if ( new_max > old_max )
> ++
> ++    if ( new_max <= AF_POINTS_EMBEDDED )
> ++      hints->points = hints->embedded.points;
> ++    else if ( new_max > old_max )
> +     {
> ++      if ( hints->points == hints->embedded.points )
> ++        hints->points = NULL;
> ++
> +       new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
> + 
> +       if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
> +Index: freetype-2.5.2/src/autofit/afhints.h
> +===================================================================
> +--- freetype-2.5.2.orig/src/autofit/afhints.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/autofit/afhints.h	2015-01-23 02:55:34.540290431 +0100
> +@@ -322,6 +322,8 @@
> + 
> +   } AF_EdgeRec;
> + 
> ++#define AF_SEGMENTS_EMBEDDED  18   /* number of embedded segments   */
> ++#define AF_EDGES_EMBEDDED     12   /* number of embedded edges      */
> + 
> +   typedef struct  AF_AxisHintsRec_
> +   {
> +@@ -338,9 +340,20 @@
> + 
> +     AF_Direction  major_dir;    /* either vertical or horizontal */
> + 
> ++    /* two arrays to avoid allocation penalty */
> ++    struct
> ++    {
> ++      AF_SegmentRec  segments[AF_SEGMENTS_EMBEDDED];
> ++      AF_EdgeRec     edges[AF_EDGES_EMBEDDED];
> ++    } embedded;
> ++
> ++
> +   } AF_AxisHintsRec, *AF_AxisHints;
> + 
> + 
> ++#define AF_POINTS_EMBEDDED     96   /* number of embedded points   */
> ++#define AF_CONTOURS_EMBEDDED    8   /* number of embedded contours */
> ++
> +   typedef struct  AF_GlyphHintsRec_
> +   {
> +     FT_Memory         memory;
> +@@ -369,6 +382,14 @@
> +     FT_Pos            xmin_delta;    /* used for warping */
> +     FT_Pos            xmax_delta;
> + 
> ++    /* Two arrays to avoid allocation penalty.            */
> ++    /* The `embedded' structure must be the last element! */
> ++    struct
> ++    {
> ++      AF_Point       contours[AF_CONTOURS_EMBEDDED];
> ++      AF_PointRec    points[AF_POINTS_EMBEDDED];
> ++    } embedded;
> ++
> +   } AF_GlyphHintsRec;
> + 
> + 
> +Index: freetype-2.5.2/src/autofit/afloader.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/autofit/afloader.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/autofit/afloader.c	2015-01-23 02:59:34.576788306 +0100
> +@@ -26,38 +26,32 @@
> + 
> +   /* Initialize glyph loader. */
> + 
> +-  FT_LOCAL_DEF( FT_Error )
> +-  af_loader_init( AF_Module  module )
> ++  FT_LOCAL_DEF( void )
> ++  af_loader_init( AF_Loader      loader,
> ++                  AF_GlyphHints  hints )
> +   {
> +-    AF_Loader  loader = module->loader;
> +-    FT_Memory  memory = module->root.library->memory;
> +-
> +-
> +     FT_ZERO( loader );
> + 
> +-    af_glyph_hints_init( &loader->hints, memory );
> ++    loader->hints = hints;
> + #ifdef FT_DEBUG_AUTOFIT
> +-    _af_debug_hints = &loader->hints;
> ++    _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_Module  module,
> ++  af_loader_reset( AF_Loader  loader,
> ++                   AF_Module  module,
> +                    FT_Face    face )
> +   {
> +-    FT_Error   error  = FT_Err_Ok;
> +-    AF_Loader  loader = module->loader;
> ++    FT_Error  error = FT_Err_Ok;
> + 
> + 
> +     loader->face    = face;
> +     loader->globals = (AF_FaceGlobals)face->autohint.data;
> + 
> +-    FT_GlyphLoader_Rewind( loader->gloader );
> +-
> +     if ( loader->globals == NULL )
> +     {
> +       error = af_face_globals_new( face, &loader->globals, module );
> +@@ -77,42 +71,37 @@
> +   /* Finalize glyph loader. */
> + 
> +   FT_LOCAL_DEF( void )
> +-  af_loader_done( AF_Module  module )
> ++  af_loader_done( AF_Loader  loader )
> +   {
> +-    AF_Loader  loader = module->loader;
> +-
> +-
> +-    af_glyph_hints_done( &loader->hints );
> +-
> +     loader->face    = NULL;
> +     loader->globals = NULL;
> ++    loader->hints   = NULL;
> + 
> + #ifdef FT_DEBUG_AUTOFIT
> +     _af_debug_hints = NULL;
> + #endif
> +-    FT_GlyphLoader_Done( loader->gloader );
> +-    loader->gloader = NULL;
> +   }
> + 
> + 
> +-  /* Load a single glyph component.  This routine calls itself */
> +-  /* recursively, if necessary, and does the main work of      */
> +-  /* `af_loader_load_glyph.'                                   */
> ++  /* Do the main work of `af_loader_load_glyph'.  Note that we never   */
> ++  /* have to deal with composite glyphs as those get loaded into       */
> ++  /* FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function. */
> ++  /* In the rare cases where FT_LOAD_NO_RECURSE is set, it implies     */
> ++  /* FT_LOAD_NO_SCALE and as such the auto-hinter is never called.     */
> + 
> +   static FT_Error
> +   af_loader_load_g( AF_Loader  loader,
> +                     AF_Scaler  scaler,
> +                     FT_UInt    glyph_index,
> +-                    FT_Int32   load_flags,
> +-                    FT_UInt    depth )
> ++                    FT_Int32   load_flags )
> +   {
> +     FT_Error          error;
> +     FT_Face           face     = loader->face;
> +-    FT_GlyphLoader    gloader  = loader->gloader;
> +     AF_ScriptMetrics  metrics  = loader->metrics;
> +-    AF_GlyphHints     hints    = &loader->hints;
> ++    AF_GlyphHints     hints    = loader->hints;
> +     FT_GlyphSlot      slot     = face->glyph;
> +     FT_Slot_Internal  internal = slot->internal;
> ++    FT_GlyphLoader    gloader  = internal->loader;
> +     FT_Int32          flags;
> + 
> + 
> +@@ -144,29 +133,6 @@
> +                               loader->trans_delta.x,
> +                               loader->trans_delta.y );
> + 
> +-      /* copy the outline points in the loader's current                */
> +-      /* extra points which are used to keep original glyph coordinates */
> +-      error = FT_GLYPHLOADER_CHECK_POINTS( gloader,
> +-                                           slot->outline.n_points + 4,
> +-                                           slot->outline.n_contours );
> +-      if ( error )
> +-        goto Exit;
> +-
> +-      FT_ARRAY_COPY( gloader->current.outline.points,
> +-                     slot->outline.points,
> +-                     slot->outline.n_points );
> +-
> +-      FT_ARRAY_COPY( gloader->current.outline.contours,
> +-                     slot->outline.contours,
> +-                     slot->outline.n_contours );
> +-
> +-      FT_ARRAY_COPY( gloader->current.outline.tags,
> +-                     slot->outline.tags,
> +-                     slot->outline.n_points );
> +-
> +-      gloader->current.outline.n_points   = slot->outline.n_points;
> +-      gloader->current.outline.n_contours = slot->outline.n_contours;
> +-
> +       /* compute original horizontal phantom points (and ignore */
> +       /* vertical ones)                                         */
> +       loader->pp1.x = hints->x_delta;
> +@@ -192,7 +158,7 @@
> + 
> +         if ( writing_system_class->script_hints_apply )
> +           writing_system_class->script_hints_apply( hints,
> +-                                                    &gloader->current.outline,
> ++                                                    &gloader->base.outline,
> +                                                     metrics );
> +       }
> + 
> +@@ -267,133 +233,6 @@
> +         slot->rsb_delta = loader->pp2.x - pp2x;
> +       }
> + 
> +-      /* good, we simply add the glyph to our loader's base */
> +-      FT_GlyphLoader_Add( gloader );
> +-      break;
> +-
> +-    case FT_GLYPH_FORMAT_COMPOSITE:
> +-      {
> +-        FT_UInt      nn, num_subglyphs = slot->num_subglyphs;
> +-        FT_UInt      num_base_subgs, start_point;
> +-        FT_SubGlyph  subglyph;
> +-
> +-
> +-        start_point = gloader->base.outline.n_points;
> +-
> +-        /* first of all, copy the subglyph descriptors in the glyph loader */
> +-        error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
> +-        if ( error )
> +-          goto Exit;
> +-
> +-        FT_ARRAY_COPY( gloader->current.subglyphs,
> +-                       slot->subglyphs,
> +-                       num_subglyphs );
> +-
> +-        gloader->current.num_subglyphs = num_subglyphs;
> +-        num_base_subgs                 = gloader->base.num_subglyphs;
> +-
> +-        /* now read each subglyph independently */
> +-        for ( nn = 0; nn < num_subglyphs; nn++ )
> +-        {
> +-          FT_Vector  pp1, pp2;
> +-          FT_Pos     x, y;
> +-          FT_UInt    num_points, num_new_points, num_base_points;
> +-
> +-
> +-          /* gloader.current.subglyphs can change during glyph loading due */
> +-          /* to re-allocation -- we must recompute the current subglyph on */
> +-          /* each iteration                                                */
> +-          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
> +-
> +-          pp1 = loader->pp1;
> +-          pp2 = loader->pp2;
> +-
> +-          num_base_points = gloader->base.outline.n_points;
> +-
> +-          error = af_loader_load_g( loader, scaler, subglyph->index,
> +-                                    load_flags, depth + 1 );
> +-          if ( error )
> +-            goto Exit;
> +-
> +-          /* recompute subglyph pointer */
> +-          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
> +-
> +-          if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
> +-          {
> +-            pp1 = loader->pp1;
> +-            pp2 = loader->pp2;
> +-          }
> +-          else
> +-          {
> +-            loader->pp1 = pp1;
> +-            loader->pp2 = pp2;
> +-          }
> +-
> +-          num_points     = gloader->base.outline.n_points;
> +-          num_new_points = num_points - num_base_points;
> +-
> +-          /* now perform the transformation required for this subglyph */
> +-
> +-          if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE    |
> +-                                   FT_SUBGLYPH_FLAG_XY_SCALE |
> +-                                   FT_SUBGLYPH_FLAG_2X2      ) )
> +-          {
> +-            FT_Vector*  cur   = gloader->base.outline.points +
> +-                                num_base_points;
> +-            FT_Vector*  limit = cur + num_new_points;
> +-
> +-
> +-            for ( ; cur < limit; cur++ )
> +-              FT_Vector_Transform( cur, &subglyph->transform );
> +-          }
> +-
> +-          /* apply offset */
> +-
> +-          if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
> +-          {
> +-            FT_Int      k = subglyph->arg1;
> +-            FT_UInt     l = subglyph->arg2;
> +-            FT_Vector*  p1;
> +-            FT_Vector*  p2;
> +-
> +-
> +-            if ( start_point + k >= num_base_points         ||
> +-                               l >= (FT_UInt)num_new_points )
> +-            {
> +-              error = FT_THROW( Invalid_Composite );
> +-              goto Exit;
> +-            }
> +-
> +-            l += num_base_points;
> +-
> +-            /* for now, only use the current point coordinates; */
> +-            /* we eventually may consider another approach      */
> +-            p1 = gloader->base.outline.points + start_point + k;
> +-            p2 = gloader->base.outline.points + start_point + l;
> +-
> +-            x = p1->x - p2->x;
> +-            y = p1->y - p2->y;
> +-          }
> +-          else
> +-          {
> +-            x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
> +-            y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
> +-
> +-            x = FT_PIX_ROUND( x );
> +-            y = FT_PIX_ROUND( y );
> +-          }
> +-
> +-          {
> +-            FT_Outline  dummy = gloader->base.outline;
> +-
> +-
> +-            dummy.points  += num_base_points;
> +-            dummy.n_points = (short)num_new_points;
> +-
> +-            FT_Outline_Translate( &dummy, x, y );
> +-          }
> +-        }
> +-      }
> +       break;
> + 
> +     default:
> +@@ -402,7 +241,6 @@
> +     }
> + 
> +   Hint_Metrics:
> +-    if ( depth == 0 )
> +     {
> +       FT_BBox    bbox;
> +       FT_Vector  vvector;
> +@@ -477,18 +315,14 @@
> +       slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
> +       slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
> + 
> +-      /* now copy outline into glyph slot */
> +-      FT_GlyphLoader_Rewind( internal->loader );
> +-      error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );
> +-      if ( error )
> +-        goto Exit;
> +-
> ++#if 0
> +       /* reassign all outline fields except flags to protect them */
> +       slot->outline.n_contours = internal->loader->base.outline.n_contours;
> +       slot->outline.n_points   = internal->loader->base.outline.n_points;
> +       slot->outline.points     = internal->loader->base.outline.points;
> +       slot->outline.tags       = internal->loader->base.outline.tags;
> +       slot->outline.contours   = internal->loader->base.outline.contours;
> ++#endif
> + 
> +       slot->format  = FT_GLYPH_FORMAT_OUTLINE;
> +     }
> +@@ -501,14 +335,14 @@
> +   /* Load a glyph. */
> + 
> +   FT_LOCAL_DEF( FT_Error )
> +-  af_loader_load_glyph( AF_Module  module,
> ++  af_loader_load_glyph( AF_Loader  loader,
> ++                        AF_Module  module,
> +                         FT_Face    face,
> +                         FT_UInt    gindex,
> +                         FT_Int32   load_flags )
> +   {
> +     FT_Error      error;
> +     FT_Size       size   = face->size;
> +-    AF_Loader     loader = module->loader;
> +     AF_ScalerRec  scaler;
> + 
> + 
> +@@ -526,7 +360,7 @@
> +     scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
> +     scaler.flags       = 0;  /* XXX: fix this */
> + 
> +-    error = af_loader_reset( module, face );
> ++    error = af_loader_reset( loader, module, face );
> +     if ( !error )
> +     {
> +       AF_ScriptMetrics  metrics;
> +@@ -563,13 +397,13 @@
> + 
> +         if ( writing_system_class->script_hints_init )
> +         {
> +-          error = writing_system_class->script_hints_init( &loader->hints,
> ++          error = writing_system_class->script_hints_init( loader->hints,
> +                                                            metrics );
> +           if ( error )
> +             goto Exit;
> +         }
> + 
> +-        error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
> ++        error = af_loader_load_g( loader, &scaler, gindex, load_flags );
> +       }
> +     }
> +   Exit:
> +Index: freetype-2.5.2/src/autofit/afloader.h
> +===================================================================
> +--- freetype-2.5.2.orig/src/autofit/afloader.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/autofit/afloader.h	2015-01-23 02:55:34.540290431 +0100
> +@@ -20,13 +20,12 @@
> + #define __AFLOADER_H__
> + 
> + #include "afhints.h"
> ++#include "afmodule.h"
> + #include "afglobal.h"
> + 
> + 
> + FT_BEGIN_HEADER
> + 
> +-  typedef struct AF_ModuleRec_*  AF_Module;
> +-
> +   /*
> +    *  The autofitter module's (global) data structure to communicate with
> +    *  actual fonts.  If necessary, `local' data like the current face, the
> +@@ -42,8 +41,7 @@
> +     AF_FaceGlobals    globals;
> + 
> +     /* current glyph data */
> +-    FT_GlyphLoader    gloader;
> +-    AF_GlyphHintsRec  hints;
> ++    AF_GlyphHints     hints;
> +     AF_ScriptMetrics  metrics;
> +     FT_Bool           transformed;
> +     FT_Matrix         trans_matrix;
> +@@ -55,21 +53,24 @@
> +   } AF_LoaderRec, *AF_Loader;
> + 
> + 
> +-  FT_LOCAL( FT_Error )
> +-  af_loader_init( AF_Module  module );
> ++  FT_LOCAL( void )
> ++  af_loader_init( AF_Loader      loader,
> ++                  AF_GlyphHints  hints );
> + 
> + 
> +   FT_LOCAL( FT_Error )
> +-  af_loader_reset( AF_Module  module,
> ++  af_loader_reset( AF_Loader  loader,
> ++                   AF_Module  module,
> +                    FT_Face    face );
> + 
> + 
> +   FT_LOCAL( void )
> +-  af_loader_done( AF_Module  module );
> ++  af_loader_done( AF_Loader  loader );
> + 
> + 
> +   FT_LOCAL( FT_Error )
> +-  af_loader_load_glyph( AF_Module  module,
> ++  af_loader_load_glyph( AF_Loader  loader,
> ++                        AF_Module  module,
> +                         FT_Face    face,
> +                         FT_UInt    gindex,
> +                         FT_Int32   load_flags );
> +Index: freetype-2.5.2/src/autofit/afmodule.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/autofit/afmodule.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/autofit/afmodule.c	2015-01-23 02:55:34.544290440 +0100
> +@@ -208,17 +208,14 @@
> + 
> +     module->fallback_script = AF_SCRIPT_FALLBACK;
> + 
> +-    return af_loader_init( module );
> ++    return FT_Err_Ok;
> +   }
> + 
> + 
> +   FT_CALLBACK_DEF( void )
> +   af_autofitter_done( FT_Module  ft_module )      /* AF_Module */
> +   {
> +-    AF_Module  module = (AF_Module)ft_module;
> +-
> +-
> +-    af_loader_done( module );
> ++    FT_UNUSED( ft_module );
> +   }
> + 
> + 
> +@@ -229,10 +226,25 @@
> +                             FT_UInt       glyph_index,
> +                             FT_Int32      load_flags )
> +   {
> ++    FT_Error   error  = FT_Err_Ok;
> ++    FT_Memory  memory = module->root.library->memory;
> ++
> ++    AF_GlyphHintsRec  hints[1];
> ++    AF_LoaderRec      loader[1];
> ++
> +     FT_UNUSED( size );
> + 
> +-    return af_loader_load_glyph( module, slot->face,
> +-                                 glyph_index, load_flags );
> ++
> ++    af_glyph_hints_init( hints, memory );
> ++    af_loader_init( loader, hints );
> ++
> ++    error = af_loader_load_glyph( loader, module, slot->face,
> ++                                  glyph_index, load_flags );
> ++
> ++    af_loader_done( loader );
> ++    af_glyph_hints_done( hints );
> ++
> ++    return error;
> +   }
> + 
> + 
> +Index: freetype-2.5.2/src/autofit/afmodule.h
> +===================================================================
> +--- freetype-2.5.2.orig/src/autofit/afmodule.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/autofit/afmodule.h	2015-01-23 02:55:34.544290440 +0100
> +@@ -23,17 +23,13 @@
> + #include FT_INTERNAL_OBJECTS_H
> + #include FT_MODULE_H
> + 
> +-#include "afloader.h"
> +-
> + 
> + FT_BEGIN_HEADER
> + 
> + 
> +   /*
> +    *  This is the `extended' FT_Module structure which holds the
> +-   *  autofitter's global data.  Right before hinting a glyph, the data
> +-   *  specific to the glyph's face (blue zones, stem widths, etc.) are
> +-   *  loaded into `loader' (see function `af_loader_reset').
> ++   *  autofitter's global data.
> +    */
> + 
> +   typedef struct  AF_ModuleRec_
> +@@ -42,9 +38,7 @@
> + 
> +     FT_UInt       fallback_script;
> + 
> +-    AF_LoaderRec  loader[1];
> +-
> +-  } AF_ModuleRec;
> ++  } AF_ModuleRec, *AF_Module;
> + 
> + 
> + FT_DECLARE_MODULE(autofit_module_class)
> +Index: freetype-2.5.2/src/base/ftobjs.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/base/ftobjs.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/base/ftobjs.c	2015-01-23 02:57:43.332560770 +0100
> +@@ -963,10 +963,6 @@
> +                       (FT_List_Destructor)destroy_face,
> +                       driver->root.memory,
> +                       driver );
> +-
> +-    /* check whether we need to drop the driver's glyph loader */
> +-    if ( FT_DRIVER_USES_OUTLINES( driver ) )
> +-      FT_GlyphLoader_Done( driver->glyph_loader );
> +   }
> + 
> + 
> +@@ -4046,8 +4042,7 @@
> + 
> +     default:
> +       {
> +-        FT_ListNode  node   = 0;
> +-        FT_Bool      update = 0;
> ++        FT_ListNode  node = 0;
> + 
> + 
> +         /* small shortcut for the very common case */
> +@@ -4074,13 +4069,7 @@
> +           /* now, look for another renderer that supports the same */
> +           /* format.                                               */
> +           renderer = FT_Lookup_Renderer( library, slot->format, &node );
> +-          update   = 1;
> +         }
> +-
> +-        /* if we changed the current renderer for the glyph image format */
> +-        /* we need to select it as the next current one                  */
> +-        if ( !error && update && renderer )
> +-          FT_Set_Renderer( library, renderer, 0, 0 );
> +       }
> +     }
> + 
> +@@ -4280,17 +4269,10 @@
> +     /* if the module is a font driver */
> +     if ( FT_MODULE_IS_DRIVER( module ) )
> +     {
> +-      /* allocate glyph loader if needed */
> +       FT_Driver  driver = FT_DRIVER( module );
> + 
> + 
> +       driver->clazz = (FT_Driver_Class)module->clazz;
> +-      if ( FT_DRIVER_USES_OUTLINES( driver ) )
> +-      {
> +-        error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
> +-        if ( error )
> +-          goto Fail;
> +-      }
> +     }
> + 
> +     if ( clazz->module_init )
> +@@ -4307,15 +4289,6 @@
> +     return error;
> + 
> +   Fail:
> +-    if ( FT_MODULE_IS_DRIVER( module ) )
> +-    {
> +-      FT_Driver  driver = FT_DRIVER( module );
> +-
> +-
> +-      if ( FT_DRIVER_USES_OUTLINES( driver ) )
> +-        FT_GlyphLoader_Done( driver->glyph_loader );
> +-    }
> +-
> +     if ( FT_MODULE_IS_RENDERER( module ) )
> +     {
> +       FT_Renderer  renderer = FT_RENDERER( module );
> +@@ -4630,12 +4603,9 @@
> +       goto Fail;
> + #endif
> + 
> +-    /* allocate the render pool */
> +-    library->raster_pool_size = FT_RENDER_POOL_SIZE;
> +-#if FT_RENDER_POOL_SIZE > 0
> +-    if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
> +-      goto Fail;
> +-#endif
> ++    /* we don't use raster_pool anymore. */
> ++    library->raster_pool_size = 0;
> ++    library->raster_pool      = NULL;
> + 
> +     library->version_major = FREETYPE_MAJOR;
> +     library->version_minor = FREETYPE_MINOR;
> +@@ -4648,8 +4618,8 @@
> + 
> +     return FT_Err_Ok;
> + 
> +-  Fail:
> + #ifdef FT_CONFIG_OPTION_PIC
> ++  Fail:
> +     ft_pic_container_destroy( library );
> + #endif
> +     FT_FREE( library );
> +@@ -4784,10 +4754,6 @@
> +     }
> + #endif
> + 
> +-    /* Destroy raster objects */
> +-    FT_FREE( library->raster_pool );
> +-    library->raster_pool_size = 0;
> +-
> + #ifdef FT_CONFIG_OPTION_PIC
> +     /* Destroy pic container contents */
> +     ft_pic_container_destroy( library );
> +Index: freetype-2.5.2/src/base/ftoutln.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/base/ftoutln.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/base/ftoutln.c	2015-01-23 02:55:34.544290440 +0100
> +@@ -606,7 +606,6 @@
> +                      FT_Raster_Params*  params )
> +   {
> +     FT_Error     error;
> +-    FT_Bool      update = FALSE;
> +     FT_Renderer  renderer;
> +     FT_ListNode  node;
> + 
> +@@ -637,14 +636,8 @@
> +       /* format                                                */
> +       renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
> +                                      &node );
> +-      update   = TRUE;
> +     }
> + 
> +-    /* if we changed the current renderer for the glyph image format */
> +-    /* we need to select it as the next current one                  */
> +-    if ( !error && update && renderer )
> +-      FT_Set_Renderer( library, renderer, 0, 0 );
> +-
> +     return error;
> +   }
> + 
> +Index: freetype-2.5.2/src/raster/ftraster.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/raster/ftraster.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/raster/ftraster.c	2015-01-23 02:55:34.548290448 +0100
> +@@ -150,14 +150,6 @@
> +   /* define DEBUG_RASTER if you want to compile a debugging version */
> + /* #define DEBUG_RASTER */
> + 
> +-  /* define FT_RASTER_OPTION_ANTI_ALIASING if you want to support */
> +-  /* 5-levels anti-aliasing                                       */
> +-/* #define FT_RASTER_OPTION_ANTI_ALIASING */
> +-
> +-  /* The size of the two-lines intermediate bitmap used */
> +-  /* for anti-aliasing, in bytes.                       */
> +-#define RASTER_GRAY_LINES  2048
> +-
> + 
> +   /*************************************************************************/
> +   /*************************************************************************/
> +@@ -514,9 +506,6 @@
> + 
> +     Short       traceIncr;          /* sweep's increment in target bitmap  */
> + 
> +-    Short       gray_min_x;         /* current min x during gray rendering */
> +-    Short       gray_max_x;         /* current max x during gray rendering */
> +-
> +     /* dispatch variables */
> + 
> +     Function_Sweep_Init*  Proc_Sweep_Init;
> +@@ -529,45 +518,19 @@
> +     Bool        second_pass;        /* indicates whether a horizontal pass */
> +                                     /* should be performed to control      */
> +                                     /* drop-out accurately when calling    */
> +-                                    /* Render_Glyph.  Note that there is   */
> +-                                    /* no horizontal pass during gray      */
> +-                                    /* rendering.                          */
> ++                                    /* Render_Glyph.                       */
> + 
> +     TPoint      arcs[3 * MaxBezier + 1]; /* The Bezier stack               */
> + 
> +     black_TBand  band_stack[16];    /* band stack used for sub-banding     */
> +     Int          band_top;          /* band stack top                      */
> + 
> +-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
> +-
> +-    Byte*       grays;
> +-
> +-    Byte        gray_lines[RASTER_GRAY_LINES];
> +-                                /* Intermediate table used to render the   */
> +-                                /* graylevels pixmaps.                     */
> +-                                /* gray_lines is a buffer holding two      */
> +-                                /* monochrome scanlines                    */
> +-
> +-    Short       gray_width;     /* width in bytes of one monochrome        */
> +-                                /* intermediate scanline of gray_lines.    */
> +-                                /* Each gray pixel takes 2 bits long there */
> +-
> +-                       /* The gray_lines must hold 2 lines, thus with size */
> +-                       /* in bytes of at least `gray_width*2'.             */
> +-
> +-#endif /* FT_RASTER_ANTI_ALIASING */
> +-
> +   };
> + 
> + 
> +   typedef struct  black_TRaster_
> +   {
> +-    char*          buffer;
> +-    long           buffer_size;
> +     void*          memory;
> +-    black_PWorker  worker;
> +-    Byte           grays[5];
> +-    Short          gray_width;
> + 
> +   } black_TRaster, *black_PRaster;
> + 
> +@@ -583,70 +546,6 @@
> + #endif /* !FT_STATIC_RASTER */
> + 
> + 
> +-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
> +-
> +-  /* A lookup table used to quickly count set bits in four gray 2x2 */
> +-  /* cells.  The values of the table have been produced with the    */
> +-  /* following code:                                                */
> +-  /*                                                                */
> +-  /*   for ( i = 0; i < 256; i++ )                                  */
> +-  /*   {                                                            */
> +-  /*     l = 0;                                                     */
> +-  /*     j = i;                                                     */
> +-  /*                                                                */
> +-  /*     for ( c = 0; c < 4; c++ )                                  */
> +-  /*     {                                                          */
> +-  /*       l <<= 4;                                                 */
> +-  /*                                                                */
> +-  /*       if ( j & 0x80 ) l++;                                     */
> +-  /*       if ( j & 0x40 ) l++;                                     */
> +-  /*                                                                */
> +-  /*       j = ( j << 2 ) & 0xFF;                                   */
> +-  /*     }                                                          */
> +-  /*     printf( "0x%04X", l );                                     */
> +-  /*   }                                                            */
> +-  /*                                                                */
> +-
> +-  static const short  count_table[256] =
> +-  {
> +-    0x0000, 0x0001, 0x0001, 0x0002, 0x0010, 0x0011, 0x0011, 0x0012,
> +-    0x0010, 0x0011, 0x0011, 0x0012, 0x0020, 0x0021, 0x0021, 0x0022,
> +-    0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
> +-    0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
> +-    0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
> +-    0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
> +-    0x0200, 0x0201, 0x0201, 0x0202, 0x0210, 0x0211, 0x0211, 0x0212,
> +-    0x0210, 0x0211, 0x0211, 0x0212, 0x0220, 0x0221, 0x0221, 0x0222,
> +-    0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
> +-    0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
> +-    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
> +-    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
> +-    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
> +-    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
> +-    0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
> +-    0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
> +-    0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
> +-    0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
> +-    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
> +-    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
> +-    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
> +-    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
> +-    0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
> +-    0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
> +-    0x2000, 0x2001, 0x2001, 0x2002, 0x2010, 0x2011, 0x2011, 0x2012,
> +-    0x2010, 0x2011, 0x2011, 0x2012, 0x2020, 0x2021, 0x2021, 0x2022,
> +-    0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
> +-    0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
> +-    0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
> +-    0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
> +-    0x2200, 0x2201, 0x2201, 0x2202, 0x2210, 0x2211, 0x2211, 0x2212,
> +-    0x2210, 0x2211, 0x2211, 0x2212, 0x2220, 0x2221, 0x2221, 0x2222
> +-  };
> +-
> +-#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
> +-
> +-
> +-
> +   /*************************************************************************/
> +   /*************************************************************************/
> +   /**                                                                     **/
> +@@ -2083,7 +1982,8 @@
> +         /* to be drawn.                                                   */
> + 
> +       lastProfile = ras.cProfile;
> +-      if ( ras.cProfile->flags & Flow_Up )
> ++      if ( ras.top != ras.cProfile->offset &&
> ++           ( ras.cProfile->flags & Flow_Up ) )
> +         o = IS_TOP_OVERSHOOT( ras.lastY );
> +       else
> +         o = IS_BOTTOM_OVERSHOOT( ras.lastY );
> +@@ -2268,9 +2168,6 @@
> +     ras.traceOfs  = -*min * pitch;
> +     if ( pitch > 0 )
> +       ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
> +-
> +-    ras.gray_min_x = 0;
> +-    ras.gray_max_x = 0;
> +   }
> + 
> + 
> +@@ -2315,11 +2212,6 @@
> +       f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
> +       f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
> + 
> +-      if ( ras.gray_min_x > c1 )
> +-        ras.gray_min_x = (short)c1;
> +-      if ( ras.gray_max_x < c2 )
> +-        ras.gray_max_x = (short)c2;
> +-
> +       target = ras.bTarget + ras.traceOfs + c1;
> +       c2 -= c1;
> + 
> +@@ -2483,11 +2375,6 @@
> +       c1 = (Short)( e1 >> 3 );
> +       f1 = (Short)( e1 & 7 );
> + 
> +-      if ( ras.gray_min_x > c1 )
> +-        ras.gray_min_x = c1;
> +-      if ( ras.gray_max_x < c1 )
> +-        ras.gray_max_x = c1;
> +-
> +       ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
> +     }
> +   }
> +@@ -2692,249 +2579,6 @@
> +   }
> + 
> + 
> +-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
> +-
> +-
> +-  /*************************************************************************/
> +-  /*                                                                       */
> +-  /*  Vertical Gray Sweep Procedure Set                                    */
> +-  /*                                                                       */
> +-  /*  These two routines are used during the vertical gray-levels sweep    */
> +-  /*  phase by the generic Draw_Sweep() function.                          */
> +-  /*                                                                       */
> +-  /*  NOTES                                                                */
> +-  /*                                                                       */
> +-  /*  - The target pixmap's width *must* be a multiple of 4.               */
> +-  /*                                                                       */
> +-  /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
> +-  /*    span call.                                                         */
> +-  /*                                                                       */
> +-  /*************************************************************************/
> +-
> +-  static void
> +-  Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
> +-                                     Short*  max )
> +-  {
> +-    Long  pitch, byte_len;
> +-
> +-
> +-    *min = *min & -2;
> +-    *max = ( *max + 3 ) & -2;
> +-
> +-    ras.traceOfs  = 0;
> +-    pitch         = ras.target.pitch;
> +-    byte_len      = -pitch;
> +-    ras.traceIncr = (Short)byte_len;
> +-    ras.traceG    = ( *min / 2 ) * byte_len;
> +-
> +-    if ( pitch > 0 )
> +-    {
> +-      ras.traceG += ( ras.target.rows - 1 ) * pitch;
> +-      byte_len    = -byte_len;
> +-    }
> +-
> +-    ras.gray_min_x =  (Short)byte_len;
> +-    ras.gray_max_x = -(Short)byte_len;
> +-  }
> +-
> +-
> +-  static void
> +-  Vertical_Gray_Sweep_Step( RAS_ARG )
> +-  {
> +-    short*  count = (short*)count_table;
> +-    Byte*   grays;
> +-
> +-
> +-    ras.traceOfs += ras.gray_width;
> +-
> +-    if ( ras.traceOfs > ras.gray_width )
> +-    {
> +-      PByte  pix;
> +-
> +-
> +-      pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
> +-      grays = ras.grays;
> +-
> +-      if ( ras.gray_max_x >= 0 )
> +-      {
> +-        Long  last_pixel = ras.target.width - 1;
> +-        Int   last_cell  = last_pixel >> 2;
> +-        Int   last_bit   = last_pixel & 3;
> +-        Bool  over       = 0;
> +-
> +-        Int    c1, c2;
> +-        PByte  bit, bit2;
> +-
> +-
> +-        if ( ras.gray_max_x >= last_cell && last_bit != 3 )
> +-        {
> +-          ras.gray_max_x = last_cell - 1;
> +-          over = 1;
> +-        }
> +-
> +-        if ( ras.gray_min_x < 0 )
> +-          ras.gray_min_x = 0;
> +-
> +-        bit  = ras.bTarget + ras.gray_min_x;
> +-        bit2 = bit + ras.gray_width;
> +-
> +-        c1 = ras.gray_max_x - ras.gray_min_x;
> +-
> +-        while ( c1 >= 0 )
> +-        {
> +-          c2 = count[*bit] + count[*bit2];
> +-
> +-          if ( c2 )
> +-          {
> +-            pix[0] = grays[(c2 >> 12) & 0x000F];
> +-            pix[1] = grays[(c2 >> 8 ) & 0x000F];
> +-            pix[2] = grays[(c2 >> 4 ) & 0x000F];
> +-            pix[3] = grays[ c2        & 0x000F];
> +-
> +-            *bit  = 0;
> +-            *bit2 = 0;
> +-          }
> +-
> +-          bit++;
> +-          bit2++;
> +-          pix += 4;
> +-          c1--;
> +-        }
> +-
> +-        if ( over )
> +-        {
> +-          c2 = count[*bit] + count[*bit2];
> +-          if ( c2 )
> +-          {
> +-            switch ( last_bit )
> +-            {
> +-            case 2:
> +-              pix[2] = grays[(c2 >> 4 ) & 0x000F];
> +-            case 1:
> +-              pix[1] = grays[(c2 >> 8 ) & 0x000F];
> +-            default:
> +-              pix[0] = grays[(c2 >> 12) & 0x000F];
> +-            }
> +-
> +-            *bit  = 0;
> +-            *bit2 = 0;
> +-          }
> +-        }
> +-      }
> +-
> +-      ras.traceOfs = 0;
> +-      ras.traceG  += ras.traceIncr;
> +-
> +-      ras.gray_min_x =  32000;
> +-      ras.gray_max_x = -32000;
> +-    }
> +-  }
> +-
> +-
> +-  static void
> +-  Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
> +-                                       FT_F26Dot6  x1,
> +-                                       FT_F26Dot6  x2,
> +-                                       PProfile    left,
> +-                                       PProfile    right )
> +-  {
> +-    /* nothing, really */
> +-    FT_UNUSED_RASTER;
> +-    FT_UNUSED( y );
> +-    FT_UNUSED( x1 );
> +-    FT_UNUSED( x2 );
> +-    FT_UNUSED( left );
> +-    FT_UNUSED( right );
> +-  }
> +-
> +-
> +-  static void
> +-  Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
> +-                                       FT_F26Dot6  x1,
> +-                                       FT_F26Dot6  x2,
> +-                                       PProfile    left,
> +-                                       PProfile    right )
> +-  {
> +-    Long   e1, e2;
> +-    PByte  pixel;
> +-
> +-
> +-    /* During the horizontal sweep, we only take care of drop-outs */
> +-
> +-    e1 = CEILING( x1 );
> +-    e2 = FLOOR  ( x2 );
> +-
> +-    if ( e1 > e2 )
> +-    {
> +-      Int  dropOutControl = left->flags & 7;
> +-
> +-
> +-      if ( e1 == e2 + ras.precision )
> +-      {
> +-        switch ( dropOutControl )
> +-        {
> +-        case 0: /* simple drop-outs including stubs */
> +-          e1 = e2;
> +-          break;
> +-
> +-        case 4: /* smart drop-outs including stubs */
> +-          e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
> +-          break;
> +-
> +-        case 1: /* simple drop-outs excluding stubs */
> +-        case 5: /* smart drop-outs excluding stubs  */
> +-          /* see Vertical_Sweep_Drop for details */
> +-
> +-          /* rightmost stub test */
> +-          if ( left->next == right && left->height <= 0 )
> +-            return;
> +-
> +-          /* leftmost stub test */
> +-          if ( right->next == left && left->start == y )
> +-            return;
> +-
> +-          if ( dropOutControl == 1 )
> +-            e1 = e2;
> +-          else
> +-            e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
> +-
> +-          break;
> +-
> +-        default: /* modes 2, 3, 6, 7 */
> +-          return;  /* no drop-out control */
> +-        }
> +-      }
> +-      else
> +-        return;
> +-    }
> +-
> +-    if ( e1 >= 0 )
> +-    {
> +-      Byte  color;
> +-
> +-
> +-      if ( x2 - x1 >= ras.precision_half )
> +-        color = ras.grays[2];
> +-      else
> +-        color = ras.grays[1];
> +-
> +-      e1 = TRUNC( e1 ) / 2;
> +-      if ( e1 < ras.target.rows )
> +-      {
> +-        pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
> +-        if ( ras.target.pitch > 0 )
> +-          pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
> +-
> +-        if ( pixel[0] == ras.grays[0] )
> +-          pixel[0] = color;
> +-      }
> +-    }
> +-  }
> +-
> +-
> +-#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
> +-
> +-
> +   /*************************************************************************/
> +   /*                                                                       */
> +   /*  Generic Sweep Drawing routine                                        */
> +@@ -3329,118 +2973,10 @@
> +   }
> + 
> + 
> +-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
> +-
> +-  /*************************************************************************/
> +-  /*                                                                       */
> +-  /* <Function>                                                            */
> +-  /*    Render_Gray_Glyph                                                  */
> +-  /*                                                                       */
> +-  /* <Description>                                                         */
> +-  /*    Render a glyph with grayscaling.  Sub-banding if needed.           */
> +-  /*                                                                       */
> +-  /* <Return>                                                              */
> +-  /*    FreeType error code.  0 means success.                             */
> +-  /*                                                                       */
> +-  FT_LOCAL_DEF( FT_Error )
> +-  Render_Gray_Glyph( RAS_ARG )
> +-  {
> +-    Long      pixel_width;
> +-    FT_Error  error;
> +-
> +-
> +-    Set_High_Precision( RAS_VARS ras.outline.flags &
> +-                                 FT_OUTLINE_HIGH_PRECISION );
> +-    ras.scale_shift = ras.precision_shift + 1;
> +-
> +-    if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
> +-      ras.dropOutControl = 2;
> +-    else
> +-    {
> +-      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
> +-        ras.dropOutControl = 4;
> +-      else
> +-        ras.dropOutControl = 0;
> +-
> +-      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
> +-        ras.dropOutControl += 1;
> +-    }
> +-
> +-    ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
> +-
> +-    /* Vertical Sweep */
> +-
> +-    ras.band_top            = 0;
> +-    ras.band_stack[0].y_min = 0;
> +-    ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
> +-
> +-    ras.bWidth  = ras.gray_width;
> +-    pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
> +-
> +-    if ( ras.bWidth > pixel_width )
> +-      ras.bWidth = pixel_width;
> +-
> +-    ras.bWidth  = ras.bWidth * 8;
> +-    ras.bTarget = (Byte*)ras.gray_lines;
> +-    ras.gTarget = (Byte*)ras.target.buffer;
> +-
> +-    ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
> +-    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
> +-    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
> +-    ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
> +-
> +-    error = Render_Single_Pass( RAS_VARS 0 );
> +-    if ( error )
> +-      return error;
> +-
> +-    /* Horizontal Sweep */
> +-    if ( ras.second_pass && ras.dropOutControl != 2 )
> +-    {
> +-      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
> +-      ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
> +-      ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
> +-      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
> +-
> +-      ras.band_top            = 0;
> +-      ras.band_stack[0].y_min = 0;
> +-      ras.band_stack[0].y_max = ras.target.width * 2 - 1;
> +-
> +-      error = Render_Single_Pass( RAS_VARS 1 );
> +-      if ( error )
> +-        return error;
> +-    }
> +-
> +-    return Raster_Err_None;
> +-  }
> +-
> +-#else /* !FT_RASTER_OPTION_ANTI_ALIASING */
> +-
> +-  FT_LOCAL_DEF( FT_Error )
> +-  Render_Gray_Glyph( RAS_ARG )
> +-  {
> +-    FT_UNUSED_RASTER;
> +-
> +-    return FT_THROW( Unsupported );
> +-  }
> +-
> +-#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
> +-
> +-
> +   static void
> +   ft_black_init( black_PRaster  raster )
> +   {
> +-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
> +-    FT_UInt  n;
> +-
> +-
> +-    /* set default 5-levels gray palette */
> +-    for ( n = 0; n < 5; n++ )
> +-      raster->grays[n] = n * 255 / 4;
> +-
> +-    raster->gray_width = RASTER_GRAY_LINES / 2;
> +-#else
> +     FT_UNUSED( raster );
> +-#endif
> +   }
> + 
> + 
> +@@ -3517,25 +3053,9 @@
> +                   char*          pool_base,
> +                   long           pool_size )
> +   {
> +-    if ( raster )
> +-    {
> +-      if ( pool_base && pool_size >= (long)sizeof ( black_TWorker ) + 2048 )
> +-      {
> +-        black_PWorker  worker = (black_PWorker)pool_base;
> +-
> +-
> +-        raster->buffer      = pool_base + ( ( sizeof ( *worker ) + 7 ) & ~7 );
> +-        raster->buffer_size = (long)( pool_base + pool_size -
> +-                                        (char*)raster->buffer );
> +-        raster->worker      = worker;
> +-      }
> +-      else
> +-      {
> +-        raster->buffer      = NULL;
> +-        raster->buffer_size = 0;
> +-        raster->worker      = NULL;
> +-      }
> +-    }
> ++    FT_UNUSED( raster );
> ++    FT_UNUSED( pool_base );
> ++    FT_UNUSED( pool_size );
> +   }
> + 
> + 
> +@@ -3544,25 +3064,9 @@
> +                      unsigned long  mode,
> +                      const char*    palette )
> +   {
> +-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
> +-
> +-    if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
> +-    {
> +-      /* set 5-levels gray palette */
> +-      raster->grays[0] = palette[0];
> +-      raster->grays[1] = palette[1];
> +-      raster->grays[2] = palette[2];
> +-      raster->grays[3] = palette[3];
> +-      raster->grays[4] = palette[4];
> +-    }
> +-
> +-#else
> +-
> +     FT_UNUSED( raster );
> +     FT_UNUSED( mode );
> +     FT_UNUSED( palette );
> +-
> +-#endif
> +   }
> + 
> + 
> +@@ -3572,10 +3076,13 @@
> +   {
> +     const FT_Outline*  outline    = (const FT_Outline*)params->source;
> +     const FT_Bitmap*   target_map = params->target;
> +-    black_PWorker      worker;
> ++
> ++    black_TWorker  worker[1];
> ++
> ++    Long  buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( Long )];
> + 
> + 
> +-    if ( !raster || !raster->buffer || !raster->buffer_size )
> ++    if ( !raster )
> +       return FT_THROW( Not_Ini );
> + 
> +     if ( !outline )
> +@@ -3592,8 +3099,6 @@
> +            outline->contours[outline->n_contours - 1] + 1 )
> +       return FT_THROW( Invalid );
> + 
> +-    worker = raster->worker;
> +-
> +     /* this version of the raster does not support direct rendering, sorry */
> +     if ( params->flags & FT_RASTER_FLAG_DIRECT )
> +       return FT_THROW( Unsupported );
> +@@ -3611,19 +3116,10 @@
> +     ras.outline = *outline;
> +     ras.target  = *target_map;
> + 
> +-    worker->buff       = (PLong) raster->buffer;
> +-    worker->sizeBuff   = worker->buff +
> +-                           raster->buffer_size / sizeof ( Long );
> +-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
> +-    worker->grays      = raster->grays;
> +-    worker->gray_width = raster->gray_width;
> +-
> +-    FT_MEM_ZERO( worker->gray_lines, worker->gray_width * 2 );
> +-#endif
> ++    worker->buff     = buffer;
> ++    worker->sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
> + 
> +-    return ( params->flags & FT_RASTER_FLAG_AA )
> +-           ? Render_Gray_Glyph( RAS_VAR )
> +-           : Render_Glyph( RAS_VAR );
> ++    return Render_Glyph( RAS_VAR );
> +   }
> + 
> + 
> +Index: freetype-2.5.2/src/raster/ftrend1.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/raster/ftrend1.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/raster/ftrend1.c	2015-01-23 02:55:34.548290448 +0100
> +@@ -120,38 +120,11 @@
> +     }
> + 
> +     /* check rendering mode */
> +-#ifndef FT_CONFIG_OPTION_PIC
> +     if ( mode != FT_RENDER_MODE_MONO )
> +     {
> +       /* raster1 is only capable of producing monochrome bitmaps */
> +-      if ( render->clazz == &ft_raster1_renderer_class )
> +-        return FT_THROW( Cannot_Render_Glyph );
> ++      return FT_THROW( Cannot_Render_Glyph );
> +     }
> +-    else
> +-    {
> +-      /* raster5 is only capable of producing 5-gray-levels bitmaps */
> +-      if ( render->clazz == &ft_raster5_renderer_class )
> +-        return FT_THROW( Cannot_Render_Glyph );
> +-    }
> +-#else /* FT_CONFIG_OPTION_PIC */
> +-    /* When PIC is enabled, we cannot get to the class object      */
> +-    /* so instead we check the final character in the class name   */
> +-    /* ("raster5" or "raster1"). Yes this is a hack.               */
> +-    /* The "correct" thing to do is have different render function */
> +-    /* for each of the classes.                                    */
> +-    if ( mode != FT_RENDER_MODE_MONO )
> +-    {
> +-      /* raster1 is only capable of producing monochrome bitmaps */
> +-      if ( render->clazz->root.module_name[6] == '1' )
> +-        return FT_THROW( Cannot_Render_Glyph );
> +-    }
> +-    else
> +-    {
> +-      /* raster5 is only capable of producing 5-gray-levels bitmaps */
> +-      if ( render->clazz->root.module_name[6] == '5' )
> +-        return FT_THROW( Cannot_Render_Glyph );
> +-    }
> +-#endif /* FT_CONFIG_OPTION_PIC */
> + 
> +     outline = &slot->outline;
> + 
> +@@ -254,37 +227,6 @@
> +       0x10000L,
> +       0x20000L,
> + 
> +-      0,    /* module specific interface */
> +-
> +-      (FT_Module_Constructor)ft_raster1_init,
> +-      (FT_Module_Destructor) 0,
> +-      (FT_Module_Requester)  0
> +-    ,
> +-
> +-    FT_GLYPH_FORMAT_OUTLINE,
> +-
> +-    (FT_Renderer_RenderFunc)   ft_raster1_render,
> +-    (FT_Renderer_TransformFunc)ft_raster1_transform,
> +-    (FT_Renderer_GetCBoxFunc)  ft_raster1_get_cbox,
> +-    (FT_Renderer_SetModeFunc)  ft_raster1_set_mode,
> +-
> +-    (FT_Raster_Funcs*)    &FT_STANDARD_RASTER_GET
> +-  )
> +-
> +-
> +-  /* This renderer is _NOT_ part of the default modules; you will need */
> +-  /* to register it by hand in your application.  It should only be    */
> +-  /* used for backwards-compatibility with FT 1.x anyway.              */
> +-  /*                                                                   */
> +-  FT_DEFINE_RENDERER( ft_raster5_renderer_class,
> +-
> +-      FT_MODULE_RENDERER,
> +-      sizeof ( FT_RendererRec ),
> +-
> +-      "raster5",
> +-      0x10000L,
> +-      0x20000L,
> +-
> +       0,    /* module specific interface */
> + 
> +       (FT_Module_Constructor)ft_raster1_init,
> +Index: freetype-2.5.2/src/smooth/ftgrays.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/smooth/ftgrays.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/smooth/ftgrays.c	2015-01-23 02:55:34.548290448 +0100
> +@@ -461,11 +461,7 @@
> + 
> +   typedef struct gray_TRaster_
> +   {
> +-    void*         buffer;
> +-    long          buffer_size;
> +-    int           band_size;
> +     void*         memory;
> +-    gray_PWorker  worker;
> + 
> +   } gray_TRaster, *gray_PRaster;
> + 
> +@@ -1940,12 +1936,17 @@
> +   gray_raster_render( gray_PRaster             raster,
> +                       const FT_Raster_Params*  params )
> +   {
> +-    const FT_Outline*  outline    = (const FT_Outline*)params->source;
> +-    const FT_Bitmap*   target_map = params->target;
> +-    gray_PWorker       worker;
> ++    const FT_Outline*  outline     = (const FT_Outline*)params->source;
> ++    const FT_Bitmap*   target_map  = params->target;
> + 
> ++    gray_TWorker  worker[1];
> + 
> +-    if ( !raster || !raster->buffer || !raster->buffer_size )
> ++    TCell  buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( TCell )];
> ++    long   buffer_size = sizeof ( buffer );
> ++    int    band_size   = (int)( buffer_size / ( sizeof ( TCell ) * 8 ) );
> ++
> ++
> ++    if ( !raster )
> +       return FT_THROW( Invalid_Argument );
> + 
> +     if ( !outline )
> +@@ -1962,8 +1963,6 @@
> +            outline->contours[outline->n_contours - 1] + 1 )
> +       return FT_THROW( Invalid_Outline );
> + 
> +-    worker = raster->worker;
> +-
> +     /* if direct mode is not set, we must have a target bitmap */
> +     if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
> +     {
> +@@ -2001,13 +2000,14 @@
> +       ras.clip_box.yMax =  32767L;
> +     }
> + 
> +-    gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size );
> ++    gray_init_cells( RAS_VAR_ buffer, buffer_size );
> + 
> +     ras.outline        = *outline;
> +     ras.num_cells      = 0;
> +     ras.invalid        = 1;
> +-    ras.band_size      = raster->band_size;
> ++    ras.band_size      = band_size;
> +     ras.num_gray_spans = 0;
> ++    ras.span_y         = 0;
> + 
> +     if ( params->flags & FT_RASTER_FLAG_DIRECT )
> +     {
> +@@ -2091,34 +2091,9 @@
> +                      char*      pool_base,
> +                      long       pool_size )
> +   {
> +-    gray_PRaster  rast = (gray_PRaster)raster;
> +-
> +-
> +-    if ( raster )
> +-    {
> +-      if ( pool_base && pool_size >= (long)sizeof ( gray_TWorker ) + 2048 )
> +-      {
> +-        gray_PWorker  worker = (gray_PWorker)pool_base;
> +-
> +-
> +-        rast->worker      = worker;
> +-        rast->buffer      = pool_base +
> +-                              ( ( sizeof ( gray_TWorker ) +
> +-                                  sizeof ( TCell ) - 1 )  &
> +-                                ~( sizeof ( TCell ) - 1 ) );
> +-        rast->buffer_size = (long)( ( pool_base + pool_size ) -
> +-                                    (char*)rast->buffer ) &
> +-                                      ~( sizeof ( TCell ) - 1 );
> +-        rast->band_size   = (int)( rast->buffer_size /
> +-                                     ( sizeof ( TCell ) * 8 ) );
> +-      }
> +-      else
> +-      {
> +-        rast->buffer      = NULL;
> +-        rast->buffer_size = 0;
> +-        rast->worker      = NULL;
> +-      }
> +-    }
> ++    FT_UNUSED( raster );
> ++    FT_UNUSED( pool_base );
> ++    FT_UNUSED( pool_size );
> +   }
> + 
> + 
> +Index: freetype-2.5.2/src/truetype/ttgload.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/truetype/ttgload.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/truetype/ttgload.c	2015-01-23 02:55:34.552290457 +0100
> +@@ -802,7 +802,6 @@
> + 
> +     if ( n_ins > 0 )
> +     {
> +-      FT_Bool   debug;
> +       FT_Error  error;
> + 
> +       FT_GlyphLoader  gloader         = loader->gloader;
> +@@ -817,10 +816,7 @@
> +       loader->exec->is_composite = is_composite;
> +       loader->exec->pts          = *zone;
> + 
> +-      debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
> +-                       ((TT_Size)loader->size)->debug             );
> +-
> +-      error = TT_Run_Context( loader->exec, debug );
> ++      error = TT_Run_Context( loader->exec );
> +       if ( error && loader->exec->pedantic_hinting )
> +         return error;
> + 
> +@@ -2116,8 +2112,7 @@
> +       }
> + 
> +       /* query new execution context */
> +-      exec = size->debug ? size->context
> +-                         : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
> ++      exec = size->context;
> +       if ( !exec )
> +         return FT_THROW( Could_Not_Find_Context );
> + 
> +Index: freetype-2.5.2/src/truetype/ttinterp.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/truetype/ttinterp.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/truetype/ttinterp.c	2015-01-23 02:55:34.552290457 +0100
> +@@ -714,12 +714,8 @@
> +   /* <Return>                                                              */
> +   /*    TrueType error code.  0 means success.                             */
> +   /*                                                                       */
> +-  /* <Note>                                                                */
> +-  /*    Only the glyph loader and debugger should call this function.      */
> +-  /*                                                                       */
> +   FT_LOCAL_DEF( FT_Error )
> +-  TT_Run_Context( TT_ExecContext  exec,
> +-                  FT_Bool         debug )
> ++  TT_Run_Context( TT_ExecContext  exec )
> +   {
> +     FT_Error  error;
> + 
> +@@ -754,16 +750,7 @@
> +     exec->top     = 0;
> +     exec->callTop = 0;
> + 
> +-#if 1
> +-    FT_UNUSED( debug );
> +-
> +     return exec->face->interpreter( exec );
> +-#else
> +-    if ( !debug )
> +-      return TT_RunIns( exec );
> +-    else
> +-      return FT_Err_Ok;
> +-#endif
> +   }
> + 
> + 
> +@@ -798,30 +785,23 @@
> +   {
> +     TT_ExecContext  exec;
> +     FT_Memory       memory;
> ++    FT_Error        error;
> + 
> ++    if ( !driver )
> ++      goto Fail;
> + 
> +     memory = driver->root.root.memory;
> +-    exec   = driver->context;
> +-
> +-    if ( !driver->context )
> +-    {
> +-      FT_Error  error;
> +-
> +-
> +-      /* allocate object */
> +-      if ( FT_NEW( exec ) )
> +-        goto Fail;
> +-
> +-      /* initialize it; in case of error this deallocates `exec' too */
> +-      error = Init_Context( exec, memory );
> +-      if ( error )
> +-        goto Fail;
> + 
> +-      /* store it into the driver */
> +-      driver->context = exec;
> +-    }
> ++    /* allocate object */
> ++    if ( FT_NEW( exec ) )
> ++      goto Fail;
> ++
> ++    /* initialize it; in case of error this deallocates `exec' too */
> ++    error = Init_Context( exec, memory );
> ++    if ( error )
> ++      goto Fail;
> + 
> +-    return driver->context;
> ++    return exec;
> + 
> +   Fail:
> +     return NULL;
> +Index: freetype-2.5.2/src/truetype/ttinterp.h
> +===================================================================
> +--- freetype-2.5.2.orig/src/truetype/ttinterp.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/truetype/ttinterp.h	2015-01-23 02:55:34.552290457 +0100
> +@@ -340,6 +340,7 @@
> +   /*                                                                       */
> +   /* <Note>                                                                */
> +   /*    Only the glyph loader and debugger should call this function.      */
> ++  /*    (And right now only the glyph loader uses it.)                     */
> +   /*                                                                       */
> +   FT_EXPORT( TT_ExecContext )
> +   TT_New_Context( TT_Driver  driver );
> +@@ -359,8 +360,7 @@
> +                    TT_Size         ins );
> + 
> +   FT_LOCAL( FT_Error )
> +-  TT_Run_Context( TT_ExecContext  exec,
> +-                  FT_Bool         debug );
> ++  TT_Run_Context( TT_ExecContext  exec );
> + #endif /* TT_USE_BYTECODE_INTERPRETER */
> + 
> + 
> +Index: freetype-2.5.2/src/truetype/ttobjs.c
> +===================================================================
> +--- freetype-2.5.2.orig/src/truetype/ttobjs.c	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/truetype/ttobjs.c	2015-01-23 02:55:34.556290465 +0100
> +@@ -751,14 +751,7 @@
> +     FT_Error        error;
> + 
> + 
> +-    /* debugging instances have their own context */
> +-    if ( size->debug )
> +-      exec = size->context;
> +-    else
> +-      exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
> +-
> +-    if ( !exec )
> +-      return FT_THROW( Could_Not_Find_Context );
> ++    exec = size->context;
> + 
> +     TT_Load_Context( exec, face, size );
> + 
> +@@ -845,14 +838,7 @@
> +     FT_Error        error;
> + 
> + 
> +-    /* debugging instances have their own context */
> +-    if ( size->debug )
> +-      exec = size->context;
> +-    else
> +-      exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
> +-
> +-    if ( !exec )
> +-      return FT_THROW( Could_Not_Find_Context );
> ++    exec = size->context;
> + 
> +     TT_Load_Context( exec, face, size );
> + 
> +@@ -874,12 +860,9 @@
> +     {
> +       error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
> + 
> +-      if ( !error && !size->debug )
> +-      {
> +-        FT_TRACE4(( "Executing `prep' table.\n" ));
> ++      FT_TRACE4(( "Executing `prep' table.\n" ));
> + 
> +-        error = face->interpreter( exec );
> +-      }
> ++      error = face->interpreter( exec );
> +     }
> +     else
> +       error = FT_Err_Ok;
> +@@ -924,12 +907,10 @@
> +     TT_Face    face   = (TT_Face)ftsize->face;
> +     FT_Memory  memory = face->root.memory;
> + 
> +-
> +-    if ( size->debug )
> ++    if ( size->context )
> +     {
> +-      /* the debug context must be deleted by the debugger itself */
> ++      TT_Done_Context( size->context );
> +       size->context = NULL;
> +-      size->debug   = FALSE;
> +     }
> + 
> +     FT_FREE( size->cvt );
> +@@ -977,6 +958,8 @@
> +     size->bytecode_ready = 1;
> +     size->cvt_ready      = 0;
> + 
> ++    size->context = TT_New_Context( (TT_Driver)face->root.driver );
> ++
> +     size->max_function_defs    = maxp->maxFunctionDefs;
> +     size->max_instruction_defs = maxp->maxInstructionDefs;
> + 
> +@@ -1261,10 +1244,6 @@
> + 
> +     TT_Driver  driver = (TT_Driver)ttdriver;
> + 
> +-
> +-    if ( !TT_New_Context( driver ) )
> +-      return FT_THROW( Could_Not_Find_Context );
> +-
> + #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
> +     driver->interpreter_version = TT_INTERPRETER_VERSION_38;
> + #else
> +@@ -1295,20 +1274,7 @@
> +   FT_LOCAL_DEF( void )
> +   tt_driver_done( FT_Module  ttdriver )     /* TT_Driver */
> +   {
> +-#ifdef TT_USE_BYTECODE_INTERPRETER
> +-    TT_Driver  driver = (TT_Driver)ttdriver;
> +-
> +-
> +-    /* destroy the execution context */
> +-    if ( driver->context )
> +-    {
> +-      TT_Done_Context( driver->context );
> +-      driver->context = NULL;
> +-    }
> +-#else
> +     FT_UNUSED( ttdriver );
> +-#endif
> +-
> +   }
> + 
> + 
> +Index: freetype-2.5.2/src/truetype/ttobjs.h
> +===================================================================
> +--- freetype-2.5.2.orig/src/truetype/ttobjs.h	2015-01-23 02:55:34.560290473 +0100
> ++++ freetype-2.5.2/src/truetype/ttobjs.h	2015-01-23 02:55:34.556290465 +0100
> +@@ -324,13 +324,6 @@
> + 
> +     TT_GlyphZoneRec    twilight;     /* The instance's twilight zone    */
> + 
> +-    /* debugging variables */
> +-
> +-    /* When using the debugger, we must keep the */
> +-    /* execution context tied to the instance    */
> +-    /* object rather than asking it on demand.   */
> +-
> +-    FT_Bool            debug;
> +     TT_ExecContext     context;
> + 
> +     FT_Bool            bytecode_ready;
> +@@ -349,7 +342,6 @@
> +   {
> +     FT_DriverRec  root;
> + 
> +-    TT_ExecContext   context;  /* execution context        */
> +     TT_GlyphZoneRec  zone;     /* glyph loader points zone */
> + 
> +     FT_UInt  interpreter_version;
> 
> === modified file 'debian/patches-freetype/series'
> --- debian/patches-freetype/series	2014-09-19 17:10:38 +0000
> +++ debian/patches-freetype/series	2015-01-23 02:45:23 +0000
> @@ -10,3 +10,4 @@
>  0002-Fix-Savannah-bug-42418.patch
>  freetype-config.diff
>  verbose-libtool.patch
> +multi-thread-violations.patch
> 


-- 
https://code.launchpad.net/~3v1n0/ubuntu/vivid/freetype/multithread-safe/+merge/247373
Your team Ubuntu branches is subscribed to branch lp:ubuntu/freetype.



More information about the Ubuntu-reviews mailing list