code:
/***************************************************************************/
/*                                                                         */
/*  afloader.c                                                             */
/*                                                                         */
/*    Auto-fitter glyph loading routines (body).                           */
/*                                                                         */
/*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by                  */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  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 "afloader.h"
#include "afhints.h"
#include "afglobal.h"
#include "aferrors.h"

  FT_LOCAL_DEF( FT_Error )
  af_loader_init( AF_Loader  loader,
                  FT_Memory  memory )
  {
    FT_ZERO( loader );

    af_glyph_hints_init( &loader->hints, memory );
#ifdef AF_DEBUG
    _af_debug_hints = &loader->hints;
#endif
    return FT_GlyphLoader_New( memory, &loader->gloader );
  }

  FT_LOCAL_DEF( FT_Error )
  af_loader_reset( AF_Loader  loader,
                   FT_Face    face )
  {
    FT_Error  error = AF_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 );
      if ( !error )
      {
        face->autohint.data =
          (FT_Pointer)loader->globals;
        face->autohint.finalizer =
          (FT_Generic_Finalizer)af_face_globals_free;
      }
    }

    return error;
  }

  FT_LOCAL_DEF( void )
  af_loader_done( AF_Loader  loader )
  {
    af_glyph_hints_done( &loader->hints );

    loader->face    = NULL;
    loader->globals = NULL;

#ifdef AF_DEBUG
    _af_debug_hints = NULL;
#endif
    FT_GlyphLoader_Done( loader->gloader );
    loader->gloader = NULL;
  }

  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_Error          error;
    FT_Face           face     = loader->face;
    FT_GlyphLoader    gloader  = loader->gloader;
    AF_ScriptMetrics  metrics  = loader->metrics;
    AF_GlyphHints     hints    = &loader->hints;
    FT_GlyphSlot      slot     = face->glyph;
    FT_Slot_Internal  internal = slot->internal;

    error = FT_Load_Glyph( face, glyph_index, load_flags );
    if ( error )
      goto Exit;

    loader->transformed = internal->glyph_transformed;
    if ( loader->transformed )
    {
      FT_Matrix  inverse;

      loader->trans_matrix = internal->glyph_matrix;
      loader->trans_delta  = internal->glyph_delta;

      inverse = loader->trans_matrix;
      FT_Matrix_Invert( &inverse );
      FT_Vector_Transform( &loader->trans_delta, &inverse );
    }

    /* set linear metrics */
    slot->linearHoriAdvance = slot->metrics.horiAdvance;
    slot->linearVertAdvance = slot->metrics.vertAdvance;

    switch ( slot->format )
    {
    case FT_GLYPH_FORMAT_OUTLINE:
      /* translate the loaded glyph when an internal transform is needed */
      if ( loader->transformed )
        FT_Outline_Translate( &slot->outline,
                              loader->trans_delta.x,
                              loader->trans_delta.y );

      /* copy the outline points in the loader's current               */
      /* extra points which is 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;
      loader->pp1.y = hints->y_delta;
      loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
                                 hints->x_scale ) + hints->x_delta;
      loader->pp2.y = hints->y_delta;

      /* be sure to check for spacing glyphs */
      if ( slot->outline.n_points == 0 )
        goto Hint_Metrics;

      /* now load the slot image into the auto-outline and run the */
      /* automatic hinting process                                 */
      if ( metrics->clazz->script_hints_apply )
        metrics->clazz->script_hints_apply( hints,
                                            &gloader->current.outline,
                                            metrics );

      /* we now need to hint 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;
        FT_Pos        pp1x_uh, pp2x_uh;
        AF_AxisHints  axis  = &hints->axis[AF_DIMENSION_HORZ];
        AF_Edge       edge1 = axis->edges;         /* leftmost edge  */
        AF_Edge       edge2 = edge1 +
                              axis->num_edges - 1; /* rightmost edge */

        if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
        {
          old_rsb = loader->pp2.x - edge2->opos;
          old_lsb = edge1->opos;
          new_lsb = edge1->pos;

          /* remember unhinted values to later account */
          /* for rounding errors                       */

          pp1x_uh = new_lsb    - old_lsb;
          pp2x_uh = edge2->pos + old_rsb;

          /* prefer too much space over too little space */
          /* for very small sizes                        */

          if ( old_lsb < 24 )
            pp1x_uh -= 8;

          if ( old_rsb < 24 )
            pp2x_uh += 8;

          loader->pp1.x = FT_PIX_ROUND( pp1x_uh );
          loader->pp2.x = FT_PIX_ROUND( pp2x_uh );

          if ( loader->pp1.x >= new_lsb && old_lsb > 0 )
            loader->pp1.x -= 64;

          if ( loader->pp2.x <= edge2->pos && old_rsb > 0 )
            loader->pp2.x += 64;

          slot->lsb_delta = loader->pp1.x - pp1x_uh;
          slot->rsb_delta = loader->pp2.x - pp2x_uh;
        }
        else
        {
          FT_Pos  pp1x = loader->pp1.x;
          FT_Pos  pp2x = loader->pp2.x;

          loader->pp1.x = FT_PIX_ROUND( pp1x );
          loader->pp2.x = FT_PIX_ROUND( pp2x );

          slot->lsb_delta = loader->pp1.x - pp1x;
          slot->rsb_delta = loader->pp2.x - pp2x;
        }
      }
      else
      {
        FT_Pos  pp1x = loader->pp1.x;
        FT_Pos  pp2x = loader->pp2.x;

        loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
        loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );

        slot->lsb_delta = loader->pp1.x - pp1x;
        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 transform 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 = AF_Err_Invalid_Composite;
              goto Exit;
            }

            l += num_base_points;

            /* for now, only use the current point coordinates;    */
            /* we may consider another approach in the near future */
            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:
      /* we don't support other formats (yet?) */
      error = AF_Err_Unimplemented_Feature;
    }

  Hint_Metrics:
    if ( depth == 0 )
    {
      FT_BBox    bbox;
      FT_Vector  vvector;

      vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX;
      vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY;
      vvector.x = FT_MulFix( vvector.x, metrics->scaler.x_scale );
      vvector.y = FT_MulFix( vvector.y, metrics->scaler.y_scale );

      /* transform the hinted outline if needed */
      if ( loader->transformed )
      {
        FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
        FT_Vector_Transform( &vvector, &loader->trans_matrix );
      }
#if 1
      /* we must translate our final outline by -pp1.x and compute */
      /* the new metrics                                           */
      if ( loader->pp1.x )
        FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
#endif
      FT_Outline_Get_CBox( &gloader->base.outline, &bbox );

      bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
      bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
      bbox.xMax = FT_PIX_CEIL(  bbox.xMax );
      bbox.yMax = FT_PIX_CEIL(  bbox.yMax );

      slot->metrics.width        = bbox.xMax - bbox.xMin;
      slot->metrics.height       = bbox.yMax - bbox.yMin;
      slot->metrics.horiBearingX = bbox.xMin;
      slot->metrics.horiBearingY = bbox.yMax;

      slot->metrics.vertBearingX = FT_PIX_FLOOR( bbox.xMin + vvector.x );
      slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y );

      /* for mono-width fonts (like Andale, Courier, etc.) we need */
      /* to keep the original rounded advance width; ditto for     */
      /* digits if all have the same advance width                 */
#if 0
      if ( !FT_IS_FIXED_WIDTH( slot->face ) )
        slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
      else
        slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
                                               x_scale );
#else
      if ( FT_IS_FIXED_WIDTH( slot->face )                              ||
           ( af_face_globals_is_digit( loader->globals, glyph_index ) &&
             metrics->digits_have_same_width                          ) )
      {
        slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
                                               metrics->scaler.x_scale );

        /* Set delta values to 0.  Otherwise code that uses them is */
        /* going to ruin the fixed advance width.                   */
        slot->lsb_delta = 0;
        slot->rsb_delta = 0;
      }
      else
      {
        /* non-spacing glyphs must stay as-is */
        if ( slot->metrics.horiAdvance )
          slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
      }
#endif

      slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
                                              metrics->scaler.y_scale );

      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;

      slot->outline = internal->loader->base.outline;
      slot->format  = FT_GLYPH_FORMAT_OUTLINE;
    }

#ifdef DEBUG_HINTER
    af_debug_hinter = hinter;
#endif

  Exit:
    return error;
  }

  FT_LOCAL_DEF( FT_Error )
  af_loader_load_glyph( AF_Loader  loader,
                        FT_Face    face,
                        FT_UInt    gindex,
                        FT_UInt32  load_flags )
  {
    FT_Error      error;
    FT_Size       size = face->size;
    AF_ScalerRec  scaler;

    if ( !size )
      return AF_Err_Invalid_Argument;

    FT_ZERO( &scaler );

    scaler.face    = face;
    scaler.x_scale = size->metrics.x_scale;
    scaler.x_delta = 0;  /* XXX: TODO: add support for sub-pixel hinting */
    scaler.y_scale = size->metrics.y_scale;
    scaler.y_delta = 0;  /* XXX: TODO: add support for sub-pixel hinting */

    scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
    scaler.flags       = 0;  /* XXX: fix this */

    error = af_loader_reset( loader, face );
    if ( !error )
    {
      AF_ScriptMetrics  metrics;
      FT_UInt           options = 0;

#ifdef FT_OPTION_AUTOFIT2
      /* XXX: undocumented hook to activate the latin2 hinter */
      if ( load_flags & ( 1UL << 20 ) )
        options = 2;
#endif

      error = af_face_globals_get_metrics( loader->globals, gindex,
                                           options, &metrics );
      if ( !error )
      {
        loader->metrics = metrics;

        if ( metrics->clazz->script_metrics_scale )
          metrics->clazz->script_metrics_scale( metrics, &scaler );
        else
          metrics->scaler = scaler;

        load_flags |=  FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
        load_flags &= ~FT_LOAD_RENDER;

        if ( metrics->clazz->script_hints_init )
        {
          error = metrics->clazz->script_hints_init( &loader->hints,
                                                     metrics );
          if ( error )
            goto Exit;
        }

        error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
      }
    }
  Exit:
    return error;
  }

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  afloader.h                                                             */
/*                                                                         */
/*    Auto-fitter glyph loading routines (specification).                  */
/*                                                                         */
/*  Copyright 2003, 2004, 2005 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.                                        */
/*                                                                         */
/***************************************************************************/

#ifndef __AF_LOADER_H__
#define __AF_LOADER_H__

#include "afhints.h"
#include "afglobal.h"

FT_BEGIN_HEADER

  typedef struct AF_LoaderRec_
  {
    FT_Face           face;           /* current face */
    AF_FaceGlobals    globals;        /* current face globals */
    FT_GlyphLoader    gloader;        /* glyph loader */
    AF_GlyphHintsRec  hints;
    AF_ScriptMetrics  metrics;
    FT_Bool           transformed;
    FT_Matrix         trans_matrix;
    FT_Vector         trans_delta;
    FT_Vector         pp1;
    FT_Vector         pp2;
    /* we don't handle vertical phantom points */

  } AF_LoaderRec, *AF_Loader;

  FT_LOCAL( FT_Error )
  af_loader_init( AF_Loader  loader,
                  FT_Memory  memory );

  FT_LOCAL( FT_Error )
  af_loader_reset( AF_Loader  loader,
                   FT_Face    face );

  FT_LOCAL( void )
  af_loader_done( AF_Loader  loader );

  FT_LOCAL( FT_Error )
  af_loader_load_glyph( AF_Loader  loader,
                        FT_Face    face,
                        FT_UInt    gindex,
                        FT_UInt32  load_flags );

/* */

FT_END_HEADER

#endif /* __AF_LOADER_H__ */

/* END */

license: mit


code:
/***************************************************************************/
/*                                                                         */
/*  afmodule.c                                                             */
/*                                                                         */
/*    Auto-fitter module implementation (body).                            */
/*                                                                         */
/*  Copyright 2003, 2004, 2005, 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.                                        */
/*                                                                         */
/***************************************************************************/

#include "afmodule.h"
#include "afloader.h"
#include "afpic.h"

#ifdef AF_DEBUG
  int    _af_debug;
  int    _af_debug_disable_horz_hints;
  int    _af_debug_disable_vert_hints;
  int    _af_debug_disable_blue_hints;
  void*  _af_debug_hints;
#endif

#include FT_INTERNAL_OBJECTS_H

  typedef struct  FT_AutofitterRec_
  {
    FT_ModuleRec  root;
    AF_LoaderRec  loader[1];

  } FT_AutofitterRec, *FT_Autofitter;

  FT_CALLBACK_DEF( FT_Error )
  af_autofitter_init( FT_Autofitter  module )
  {
    return af_loader_init( module->loader, module->root.library->memory );
  }

  FT_CALLBACK_DEF( void )
  af_autofitter_done( FT_Autofitter  module )
  {
    af_loader_done( module->loader );
  }

  FT_CALLBACK_DEF( FT_Error )
  af_autofitter_load_glyph( FT_Autofitter  module,
                            FT_GlyphSlot   slot,
                            FT_Size        size,
                            FT_UInt        glyph_index,
                            FT_Int32       load_flags )
  {
    FT_UNUSED( size );

    return af_loader_load_glyph( module->loader, slot->face,
                                 glyph_index, load_flags );
  }

  FT_DEFINE_AUTOHINTER_SERVICE(af_autofitter_service,
    NULL,
    NULL,
    NULL,
    (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph
  )

  FT_DEFINE_MODULE(autofit_module_class,

    FT_MODULE_HINTER,
    sizeof ( FT_AutofitterRec ),

    "autofitter",
    0x10000L,   /* version 1.0 of the autofitter  */
    0x20000L,   /* requires FreeType 2.0 or above */

    (const void*)&AF_AF_AUTOFITTER_SERVICE_GET,

    (FT_Module_Constructor)af_autofitter_init,
    (FT_Module_Destructor) af_autofitter_done,
    (FT_Module_Requester)  NULL
  )

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  afmodule.h                                                             */
/*                                                                         */
/*    Auto-fitter module implementation (specification).                   */
/*                                                                         */
/*  Copyright 2003, 2004, 2005 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.                                        */
/*                                                                         */
/***************************************************************************/

#ifndef __AFMODULE_H__
#define __AFMODULE_H__

#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H
#include FT_MODULE_H

FT_BEGIN_HEADER

FT_DECLARE_MODULE(autofit_module_class)

FT_END_HEADER

#endif /* __AFMODULE_H__ */

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  afpic.c                                                                */
/*                                                                         */
/*    The FreeType position independent code services for autofit module.  */
/*                                                                         */
/*  Copyright 2009, 2010 by                                                */
/*  Oran Agra and Mickey Gabel.                                            */
/*                                                                         */
/*  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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "afpic.h"

#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*);

  /* forward declaration of PIC init functions from script classes */
#include "aflatin.h"
#include "aflatin2.h"
#include "afcjk.h"
#include "afdummy.h"
#include "afindic.h"

  void
  autofit_module_class_pic_free( FT_Library library )
  {
    FT_PIC_Container* pic_container = &library->pic_container;
    FT_Memory memory = library->memory;
    if ( pic_container->autofit )
    {
      FT_FREE( pic_container->autofit );
      pic_container->autofit = NULL;
    }
  }

  FT_Error
  autofit_module_class_pic_init( FT_Library  library )
  {
    FT_PIC_Container*  pic_container = &library->pic_container;
    FT_UInt            ss;
    FT_Error           error         = AF_Err_Ok;
    AFModulePIC*       container;
    FT_Memory          memory        = library->memory;

    /* allocate pointer, clear and set global container pointer */
    if ( FT_ALLOC ( container, sizeof ( *container ) ) )
      return error;
    FT_MEM_SET( container, 0, sizeof ( *container ) );
    pic_container->autofit = container;

    /* 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[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++]);
#ifdef FT_OPTION_AUTOFIT2
    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_autofitter_service(library, &container->af_autofitter_service);

/*Exit:*/
    if(error)
      autofit_module_class_pic_free(library);
    return error;
  }

#endif /* FT_CONFIG_OPTION_PIC */

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  afpic.h                                                                */
/*                                                                         */
/*    The FreeType position independent code services for autofit module.  */
/*                                                                         */
/*  Copyright 2009 by                                                      */
/*  Oran Agra and Mickey Gabel.                                            */
/*                                                                         */
/*  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.                                        */
/*                                                                         */
/***************************************************************************/

#ifndef __AFPIC_H__
#define __AFPIC_H__

FT_BEGIN_HEADER

#include FT_INTERNAL_PIC_H

#ifndef FT_CONFIG_OPTION_PIC

#define AF_SCRIPT_CLASSES_GET         af_script_classes
#define AF_AF_AUTOFITTER_SERVICE_GET  af_autofitter_service

#else /* FT_CONFIG_OPTION_PIC */

#include "aftypes.h"

/* increase these when you add new scripts, and update autofit_module_class_pic_init */
#ifdef FT_OPTION_AUTOFIT2
  #define AF_SCRIPT_CLASSES_COUNT     6
#else
  #define AF_SCRIPT_CLASSES_COUNT     5
#endif
#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;
  } 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)

#endif /* FT_CONFIG_OPTION_PIC */

 /* */

FT_END_HEADER

#endif /* __AFPIC_H__ */

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  aftypes.h                                                              */
/*                                                                         */
/*    Auto-fitter types (specification only).                              */
/*                                                                         */
/*  Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 by                  */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  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.                                        */
/*                                                                         */
/***************************************************************************/

  /*************************************************************************
   *
   *  The auto-fitter is a complete rewrite of the old auto-hinter.
   *  Its main feature is the ability to differentiate between different
   *  scripts in order to apply language-specific rules.
   *
   *  The code has also been compartmentized into several entities that
   *  should make algorithmic experimentation easier than with the old
   *  code.
   *
   *  Finally, we get rid of the Catharon license, since this code is
   *  released under the FreeType one.
   *
   *************************************************************************/

#ifndef __AFTYPES_H__
#define __AFTYPES_H__

#include <ft2build.h>

#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H

FT_BEGIN_HEADER

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                    D E B U G G I N G                          *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

#define xxAF_USE_WARPER  /* only define to use warp hinting */
#define xxAF_DEBUG

#ifdef AF_DEBUG

#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 */

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                 U T I L I T Y   S T U F F                     *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  typedef struct  AF_WidthRec_
  {
    FT_Pos  org;  /* original position/width in font units              */
    FT_Pos  cur;  /* current/scaled position/width in device sub-pixels */
    FT_Pos  fit;  /* current/fitted position/width in device sub-pixels */

  } AF_WidthRec, *AF_Width;

  FT_LOCAL( void )
  af_sort_pos( FT_UInt  count,
               FT_Pos*  table );

  FT_LOCAL( void )
  af_sort_widths( FT_UInt   count,
                  AF_Width  widths );

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                   A N G L E   T Y P E S                       *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*
   *  The auto-fitter doesn't need a very high angular accuracy;
   *  this allows us to speed up some computations considerably with a
   *  light Cordic algorithm (see afangles.c).
   */

  typedef FT_Int  AF_Angle;

#define AF_ANGLE_PI   256
#define AF_ANGLE_2PI  ( AF_ANGLE_PI * 2 )
#define AF_ANGLE_PI2  ( AF_ANGLE_PI / 2 )
#define AF_ANGLE_PI4  ( AF_ANGLE_PI / 4 )

#if 0
  /*
   *  compute the angle of a given 2-D vector
   */
  FT_LOCAL( AF_Angle )
  af_angle_atan( FT_Pos  dx,
                 FT_Pos  dy );

  /*
   *  compute `angle2 - angle1'; the result is always within
   *  the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
   */
  FT_LOCAL( AF_Angle )
  af_angle_diff( AF_Angle  angle1,
                 AF_Angle  angle2 );
#endif /* 0 */

#define AF_ANGLE_DIFF( result, angle1, angle2 ) \
  FT_BEGIN_STMNT                                \
    AF_Angle  _delta = (angle2) - (angle1);     \
                                                \
                                                \
    _delta %= AF_ANGLE_2PI;                     \
    if ( _delta < 0 )                           \
      _delta += AF_ANGLE_2PI;                   \
                                                \
    if ( _delta > AF_ANGLE_PI )                 \
      _delta -= AF_ANGLE_2PI;                   \
                                                \
    result = _delta;                            \
  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;

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                       S C A L E R S                           *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*
   *  A scaler models the target pixel device that will receive the
   *  auto-hinted glyph image.
   */

  typedef enum  AF_ScalerFlags_
  {
    AF_SCALER_FLAG_NO_HORIZONTAL = 1,  /* disable horizontal hinting */
    AF_SCALER_FLAG_NO_VERTICAL   = 2,  /* disable vertical hinting   */
    AF_SCALER_FLAG_NO_ADVANCE    = 4   /* disable advance hinting    */

  } AF_ScalerFlags;

  typedef struct  AF_ScalerRec_
  {
    FT_Face         face;        /* source font face                        */
    FT_Fixed        x_scale;     /* from font units to 1/64th device pixels */
    FT_Fixed        y_scale;     /* from font units to 1/64th device pixels */
    FT_Pos          x_delta;     /* in 1/64th device pixels                 */
    FT_Pos          y_delta;     /* in 1/64th device pixels                 */
    FT_Render_Mode  render_mode; /* monochrome, anti-aliased, LCD, etc.     */
    FT_UInt32       flags;       /* additional control flags, see above     */

  } AF_ScalerRec, *AF_Scaler;

#define AF_SCALER_EQUAL_SCALES( a, b )      \
          ( (a)->x_scale == (b)->x_scale && \
            (a)->y_scale == (b)->y_scale && \
            (a)->x_delta == (b)->x_delta && \
            (a)->y_delta == (b)->y_delta )

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                       S C R I P T S                           *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*
   *  The list of know scripts.  Each different script corresponds to the
   *  following information:
   *
   *   - A set of Unicode ranges to test whether the face supports the
   *     script.
   *
   *   - A specific global analyzer that will compute global metrics
   *     specific to the script.
   *
   *   - A specific glyph analyzer that will compute segments and
   *     edges for each glyph covered by the script.
   *
   *   - A specific grid-fitting algorithm that will distort the
   *     scaled glyph outline according to the results of the glyph
   *     analyzer.
   *
   *  Note that a given analyzer and/or grid-fitting algorithm can be
   *  used by more than one script.
   */

  typedef enum  AF_Script_
  {
    AF_SCRIPT_NONE  = 0,
    AF_SCRIPT_LATIN = 1,
    AF_SCRIPT_CJK   = 2,
    AF_SCRIPT_INDIC = 3,
#ifdef FT_OPTION_AUTOFIT2
    AF_SCRIPT_LATIN2,
#endif

    /* add new scripts here.  Don't forget to update the list in */
    /* `afglobal.c'.                                             */

    AF_SCRIPT_MAX   /* do not remove */

  } AF_Script;

  typedef struct AF_ScriptClassRec_ const*  AF_ScriptClass;

  typedef struct  AF_ScriptMetricsRec_
  {
    AF_ScriptClass  clazz;
    AF_ScalerRec    scaler;
    FT_Bool         digits_have_same_width;

  } AF_ScriptMetricsRec, *AF_ScriptMetrics;

  /*  This function parses an FT_Face to compute global metrics for
   *  a specific script.
   */
  typedef FT_Error
  (*AF_Script_InitMetricsFunc)( AF_ScriptMetrics  metrics,
                                FT_Face           face );

  typedef void
  (*AF_Script_ScaleMetricsFunc)( AF_ScriptMetrics  metrics,
                                 AF_Scaler         scaler );

  typedef void
  (*AF_Script_DoneMetricsFunc)( AF_ScriptMetrics  metrics );

  typedef FT_Error
  (*AF_Script_InitHintsFunc)( AF_GlyphHints     hints,
                              AF_ScriptMetrics  metrics );

  typedef void
  (*AF_Script_ApplyHintsFunc)( AF_GlyphHints     hints,
                               FT_Outline*       outline,
                               AF_ScriptMetrics  metrics );

  typedef struct  AF_Script_UniRangeRec_
  {
    FT_UInt32  first;
    FT_UInt32  last;

  } AF_Script_UniRangeRec;

#define AF_UNIRANGE_REC( a, b ) { (FT_UInt32)(a), (FT_UInt32)(b) }

  typedef const AF_Script_UniRangeRec  *AF_Script_UniRange;

  typedef struct  AF_ScriptClassRec_
  {
    AF_Script                   script;
    AF_Script_UniRange          script_uni_ranges; /* last must be { 0, 0 } */

    FT_Offset                   script_metrics_size;
    AF_Script_InitMetricsFunc   script_metrics_init;
    AF_Script_ScaleMetricsFunc  script_metrics_scale;
    AF_Script_DoneMetricsFunc   script_metrics_done;

    AF_Script_InitHintsFunc     script_hints_init;
    AF_Script_ApplyHintsFunc    script_hints_apply;

  } AF_ScriptClassRec;

/* Declare and define vtables for classes */
#ifndef FT_CONFIG_OPTION_PIC

#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                                                                  \
  };

#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;                                     \
  }
#endif

/* */

FT_END_HEADER

#endif /* __AFTYPES_H__ */

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  afwarp.h                                                               */
/*                                                                         */
/*    Auto-fitter warping algorithm (specification).                       */
/*                                                                         */
/*  Copyright 2006, 2007 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.                                        */
/*                                                                         */
/***************************************************************************/

#ifndef __AFWARP_H__
#define __AFWARP_H__

#include "afhints.h"

FT_BEGIN_HEADER

#define AF_WARPER_SCALE

#define AF_WARPER_FLOOR( x )  ( (x) & ~63 )
#define AF_WARPER_CEIL( x )   AF_WARPER_FLOOR( (x) + 63 )

  typedef FT_Int32  AF_WarpScore;

  typedef struct  AF_WarperRec_
  {
    FT_Pos        x1, x2;
    FT_Pos        t1, t2;
    FT_Pos        x1min, x1max;
    FT_Pos        x2min, x2max;
    FT_Pos        w0, wmin, wmax;

    FT_Fixed      best_scale;
    FT_Pos        best_delta;
    AF_WarpScore  best_score;
    AF_WarpScore  best_distort;

  } AF_WarperRec, *AF_Warper;

  FT_LOCAL( void )
  af_warper_compute( AF_Warper      warper,
                     AF_GlyphHints  hints,
                     AF_Dimension   dim,
                     FT_Fixed      *a_scale,
                     FT_Fixed      *a_delta );

FT_END_HEADER

#endif /* __AFWARP_H__ */

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  autofit.c                                                              */
/*                                                                         */
/*    Auto-fitter module (body).                                           */
/*                                                                         */
/*  Copyright 2003, 2004, 2005, 2006, 2007 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.                                        */
/*                                                                         */
/***************************************************************************/

#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <ft2build.h>
#include "afpic.c"
#include "afangles.c"
#include "afglobal.c"
#include "afhints.c"

#include "afdummy.c"
#include "aflatin.c"
#ifdef FT_OPTION_AUTOFIT2
#include "aflatin2.c"
#endif
#include "afcjk.c"
#include "afindic.c"

#include "afloader.c"
#include "afmodule.c"

#ifdef AF_USE_WARPER
#include "afwarp.c"
#endif

/* END */


code:
#
# FreeType 2 auto-fitter module definition
#

# Copyright 2003, 2004, 2005, 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.

FTMODULE_H_COMMANDS += AUTOFIT_MODULE

define AUTOFIT_MODULE
$(OPEN_DRIVER) FT_Module_Class, autofit_module_class $(CLOSE_DRIVER)
$(ECHO_DRIVER)autofit   $(ECHO_DRIVER_DESC)automatic hinting module$(ECHO_DRIVER_DONE)
endef

# EOF


code:
#
# FreeType 2 auto-fitter module configuration rules
#

# Copyright 2003, 2004, 2005, 2006, 2007 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.

# AUTOF driver directory
#
AUTOF_DIR := $(SRC_DIR)/autofit

# compilation flags for the driver
#
AUTOF_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(AUTOF_DIR))

# AUTOF driver sources (i.e., C files)
#
AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
                 $(AUTOF_DIR)/afcjk.c    \
                 $(AUTOF_DIR)/afdummy.c  \
                 $(AUTOF_DIR)/afglobal.c \
                 $(AUTOF_DIR)/afhints.c  \
                 $(AUTOF_DIR)/afindic.c  \
                 $(AUTOF_DIR)/aflatin.c  \
                 $(AUTOF_DIR)/afloader.c \
                 $(AUTOF_DIR)/afmodule.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 driver object(s)
#
#   AUTOF_DRV_OBJ_M is used during `multi' builds.
#   AUTOF_DRV_OBJ_S is used during `single' builds.
#
AUTOF_DRV_OBJ_M := $(AUTOF_DRV_SRC:$(AUTOF_DIR)/%.c=$(OBJ_DIR)/%.$O)
AUTOF_DRV_OBJ_S := $(OBJ_DIR)/autofit.$O

# AUTOF driver source file for single build
#
AUTOF_DRV_SRC_S := $(AUTOF_DIR)/autofit.c

# AUTOF driver - single object
#
$(AUTOF_DRV_OBJ_S): $(AUTOF_DRV_SRC_S) $(AUTOF_DRV_SRC) \
                   $(FREETYPE_H) $(AUTOF_DRV_H)
	$(AUTOF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(AUTOF_DRV_SRC_S))

# AUTOF driver - multiple objects
#
$(OBJ_DIR)/%.$O: $(AUTOF_DIR)/%.c $(FREETYPE_H) $(AUTOF_DRV_H)
	$(AUTOF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)

# update main driver object lists
#
DRV_OBJS_S += $(AUTOF_DRV_OBJ_S)
DRV_OBJS_M += $(AUTOF_DRV_OBJ_M)

# EOF


code:
# FreeType 2 src/base Jamfile
#
# Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, 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) base ;

{
  local  _sources ;

  if $(FT2_MULTI)
  {
    _sources = ftadvanc ftcalc   ftdbgmem ftgloadr
               ftobjs   ftoutln  ftrfork  ftsnames
               ftstream fttrigon ftutil
               basepic  ftpic
               ;
  }
  else
  {
    _sources = ftbase ;
  }

  Library  $(FT2_LIB) : $(_sources).c ;
}

# Add the optional/replaceable files.
#
{
  local  _sources = bbox   bdf    bitmap debug  gasp
                    glyph  gxval  init   lcdfil mm
                    otval  pfr    stroke synth  system
                    type1  winfnt xf86   patent
                    ;

  Library  $(FT2_LIB) : ft$(_sources).c ;
}

# Add Macintosh-specific file to the library when necessary.
#
if $(MAC)
{
  Library  $(FT2_LIB) : ftmac.c ;
}
else if $(OS) = MACOSX
{
  if $(FT2_MULTI)
  {
    Library  $(FT2_LIB) : ftmac.c ;
  }
}

# end of src/base Jamfile


code:
/***************************************************************************/
/*                                                                         */
/*  basepic.c                                                              */
/*                                                                         */
/*    The FreeType position independent code services for base.            */
/*                                                                         */
/*  Copyright 2009 by                                                      */
/*  Oran Agra and Mickey Gabel.                                            */
/*                                                                         */
/*  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_FREETYPE_H
#include FT_INTERNAL_OBJECTS_H
#include "basepic.h"

#ifdef FT_CONFIG_OPTION_PIC

  /* forward declaration of PIC init functions from ftglyph.c */
  void FT_Init_Class_ft_outline_glyph_class(FT_Glyph_Class*);
  void FT_Init_Class_ft_bitmap_glyph_class(FT_Glyph_Class*);

  /* forward declaration of PIC init functions from ftinit.c */
  FT_Error ft_create_default_module_classes(FT_Library);
  void ft_destroy_default_module_classes(FT_Library);

  void
  ft_base_pic_free( FT_Library library )
  {
    FT_PIC_Container* pic_container = &library->pic_container;
    FT_Memory    memory = library->memory;
    if ( pic_container->base )
    {
      /* Destroy default module classes (in case FT_Add_Default_Modules was used) */
      ft_destroy_default_module_classes( library );

      FT_FREE( pic_container->base );
      pic_container->base = NULL;
    }
  }

  FT_Error
  ft_base_pic_init( FT_Library library )
  {
    FT_PIC_Container* pic_container = &library->pic_container;
    FT_Error        error = FT_Err_Ok;
    BasePIC*     container;
    FT_Memory    memory = library->memory;

    /* allocate pointer, clear and set global container pointer */
    if ( FT_ALLOC ( container, sizeof ( *container ) ) )
      return error;
    FT_MEM_SET( container, 0, sizeof(*container) );
    pic_container->base = container;

    /* initialize default modules list and pointers */
    error = ft_create_default_module_classes( library );
    if ( error )
      goto Exit;

    /* initialize pointer table - this is how the module usually expects this data */
    FT_Init_Class_ft_outline_glyph_class(&container->ft_outline_glyph_class);
    FT_Init_Class_ft_bitmap_glyph_class(&container->ft_bitmap_glyph_class);

Exit:
    if(error)
      ft_base_pic_free(library);
    return error;
  }

#endif /* FT_CONFIG_OPTION_PIC */

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  basepic.h                                                              */
/*                                                                         */
/*    The FreeType position independent code services for base.            */
/*                                                                         */
/*  Copyright 2009 by                                                      */
/*  Oran Agra and Mickey Gabel.                                            */
/*                                                                         */
/*  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.                                        */
/*                                                                         */
/***************************************************************************/

#ifndef __BASEPIC_H__
#define __BASEPIC_H__

FT_BEGIN_HEADER

#include FT_INTERNAL_PIC_H

#ifndef FT_CONFIG_OPTION_PIC
#define FT_OUTLINE_GLYPH_CLASS_GET &ft_outline_glyph_class
#define FT_BITMAP_GLYPH_CLASS_GET  &ft_bitmap_glyph_class
#define FT_DEFAULT_MODULES_GET     ft_default_modules

#else /* FT_CONFIG_OPTION_PIC */

#include FT_GLYPH_H

  typedef struct BasePIC_
  {
    FT_Module_Class** default_module_classes;
    FT_Glyph_Class ft_outline_glyph_class;
    FT_Glyph_Class ft_bitmap_glyph_class;
  } BasePIC;

#define GET_PIC(lib)                  ((BasePIC*)((lib)->pic_container.base))
#define FT_OUTLINE_GLYPH_CLASS_GET    (&GET_PIC(library)->ft_outline_glyph_class)
#define FT_BITMAP_GLYPH_CLASS_GET     (&GET_PIC(library)->ft_bitmap_glyph_class)
#define FT_DEFAULT_MODULES_GET        (GET_PIC(library)->default_module_classes)

  void
  ft_base_pic_free( FT_Library library );

  FT_Error
  ft_base_pic_init( FT_Library library );

#endif /* FT_CONFIG_OPTION_PIC */
 /* */

FT_END_HEADER

#endif /* __BASEPIC_H__ */

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  ftadvanc.c                                                             */
/*                                                                         */
/*    Quick computation of advance widths (body).                          */
/*                                                                         */
/*  Copyright 2008, 2009 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_ADVANCES_H
#include FT_INTERNAL_OBJECTS_H

  static FT_Error
  _ft_face_scale_advances( FT_Face    face,
                           FT_Fixed*  advances,
                           FT_UInt    count,
                           FT_Int32   flags )
  {
    FT_Fixed  scale;
    FT_UInt   nn;

    if ( flags & FT_LOAD_NO_SCALE )
      return FT_Err_Ok;

    if ( face->size == NULL )
      return FT_Err_Invalid_Size_Handle;

    if ( flags & FT_LOAD_VERTICAL_LAYOUT )
      scale = face->size->metrics.y_scale;
    else
      scale = face->size->metrics.x_scale;

    /* this must be the same scaling as to get linear{Hori,Vert}Advance */
    /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c)        */

    for ( nn = 0; nn < count; nn++ )
      advances[nn] = FT_MulDiv( advances[nn], scale, 64 );

    return FT_Err_Ok;
  }

   /* at the moment, we can perform fast advance retrieval only in */
   /* the following cases:                                         */
   /*                                                              */
   /*  - unscaled load                                             */
   /*  - unhinted load                                             */
   /*  - light-hinted load                                         */

#define LOAD_ADVANCE_FAST_CHECK( flags )                            \
          ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING )    || \
            FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )

  /* documentation is in ftadvanc.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Get_Advance( FT_Face    face,
                  FT_UInt    gindex,
                  FT_Int32   flags,
                  FT_Fixed  *padvance )
  {
    FT_Face_GetAdvancesFunc  func;

    if ( !face )
      return FT_Err_Invalid_Face_Handle;

    if ( gindex >= (FT_UInt)face->num_glyphs )
      return FT_Err_Invalid_Glyph_Index;

    func = face->driver->clazz->get_advances;
    if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
    {
      FT_Error  error;

      error = func( face, gindex, 1, flags, padvance );
      if ( !error )
        return _ft_face_scale_advances( face, padvance, 1, flags );

      if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
        return error;
    }

    return FT_Get_Advances( face, gindex, 1, flags, padvance );
  }

  /* documentation is in ftadvanc.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Get_Advances( FT_Face    face,
                   FT_UInt    start,
                   FT_UInt    count,
                   FT_Int32   flags,
                   FT_Fixed  *padvances )
  {
    FT_Face_GetAdvancesFunc  func;
    FT_UInt                  num, end, nn;
    FT_Error                 error = FT_Err_Ok;

    if ( !face )
      return FT_Err_Invalid_Face_Handle;

    num = (FT_UInt)face->num_glyphs;
    end = start + count;
    if ( start >= num || end < start || end > num )
      return FT_Err_Invalid_Glyph_Index;

    if ( count == 0 )
      return FT_Err_Ok;

    func = face->driver->clazz->get_advances;
    if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
    {
      error = func( face, start, count, flags, padvances );
      if ( !error )
        goto Exit;

      if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
        return error;
    }

    error = FT_Err_Ok;

    if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
      return FT_Err_Unimplemented_Feature;

    flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
    for ( nn = 0; nn < count; nn++ )
    {
      error = FT_Load_Glyph( face, start + nn, flags );
      if ( error )
        break;

      padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
                      ? face->glyph->advance.y
                      : face->glyph->advance.x;
    }

    if ( error )
      return error;

  Exit:
    return _ft_face_scale_advances( face, padvances, count, flags );
  }

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  ftbase.c                                                               */
/*                                                                         */
/*    Single object library component (body only).                         */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by       */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  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>

#define  FT_MAKE_OPTION_SINGLE_OBJECT

#include "ftpic.c"
#include "basepic.c"
#include "ftadvanc.c"
#include "ftcalc.c"
#include "ftdbgmem.c"
#include "ftgloadr.c"
#include "ftobjs.c"
#include "ftoutln.c"
#include "ftrfork.c"
#include "ftsnames.c"
#include "ftstream.c"
#include "fttrigon.c"
#include "ftutil.c"

#if defined( FT_MACINTOSH ) && !defined ( DARWIN_NO_CARBON )
#include "ftmac.c"
#endif

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  ftbase.h                                                               */
/*                                                                         */
/*    The FreeType private functions used in base module (specification).  */
/*                                                                         */
/*  Copyright 2008, 2010 by                                                */
/*  David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.      */
/*                                                                         */
/*  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.                                        */
/*                                                                         */
/***************************************************************************/

#ifndef __FTBASE_H__
#define __FTBASE_H__

#include <ft2build.h>
#include FT_INTERNAL_OBJECTS_H

FT_BEGIN_HEADER

  /* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */
  /* font, and try to load a face specified by the face_index.            */
  FT_LOCAL( FT_Error )
  open_face_PS_from_sfnt_stream( FT_Library     library,
                                 FT_Stream      stream,
                                 FT_Long        face_index,
                                 FT_Int         num_params,
                                 FT_Parameter  *params,
                                 FT_Face       *aface );

  /* Create a new FT_Face given a buffer and a driver name. */
  /* From ftmac.c.                                          */
  FT_LOCAL( FT_Error )
  open_face_from_buffer( FT_Library   library,
                         FT_Byte*     base,
                         FT_ULong     size,
                         FT_Long      face_index,
                         const char*  driver_name,
                         FT_Face     *aface );

#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
  /* Mac OS X/Darwin kernel often changes recommended method to access */
  /* the resource fork and older methods makes the kernel issue the    */
  /* warning of deprecated method.  To calm it down, the methods based */
  /* on Darwin VFS should be grouped and skip the rest methods after   */
  /* the case the resource is opened but found to lack a font in it.   */
  FT_LOCAL( FT_Bool )
  raccess_rule_by_darwin_vfs( FT_UInt  rule_index );
#endif /* FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */

FT_END_HEADER

#endif /* __FTBASE_H__ */

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  ftbbox.c                                                               */
/*                                                                         */
/*    FreeType bbox computation (body).                                    */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2004, 2006, 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.                                        */
/*                                                                         */
/***************************************************************************/

  /*************************************************************************/
  /*                                                                       */
  /* This component has a _single_ role: to compute exact outline bounding */
  /* boxes.                                                                */
  /*                                                                       */
  /*************************************************************************/

#include <ft2build.h>
#include FT_BBOX_H
#include FT_IMAGE_H
#include FT_OUTLINE_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_OBJECTS_H

  typedef struct  TBBox_Rec_
  {
    FT_Vector  last;
    FT_BBox    bbox;

  } TBBox_Rec;

  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    BBox_Move_To                                                       */
  /*                                                                       */
  /* <Description>                                                         */
  /*    This function is used as a `move_to' and `line_to' emitter during  */
  /*    FT_Outline_Decompose().  It simply records the destination point   */
  /*    in `user->last'; no further computations are necessary since we    */
  /*    use the cbox as the starting bbox which must be refined.           */
  /*                                                                       */
  /* <Input>                                                               */
  /*    to   :: A pointer to the destination vector.                       */
  /*                                                                       */
  /* <InOut>                                                               */
  /*    user :: A pointer to the current walk context.                     */
  /*                                                                       */
  /* <Return>                                                              */
  /*    Always 0.  Needed for the interface only.                          */
  /*                                                                       */
  static int
  BBox_Move_To( FT_Vector*  to,
                TBBox_Rec*  user )
  {
    user->last = *to;

    return 0;
  }

#define CHECK_X( p, bbox )  \
          ( p->x < bbox.xMin || p->x > bbox.xMax )

#define CHECK_Y( p, bbox )  \
          ( p->y < bbox.yMin || p->y > bbox.yMax )

  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    BBox_Conic_Check                                                   */
  /*                                                                       */
  /* <Description>                                                         */
  /*    Finds the extrema of a 1-dimensional conic Bezier curve and update */
  /*    a bounding range.  This version uses direct computation, as it     */
  /*    doesn't need square roots.                                         */
  /*                                                                       */
  /* <Input>                                                               */
  /*    y1  :: The start coordinate.                                       */
  /*                                                                       */
  /*    y2  :: The coordinate of the control point.                        */
  /*                                                                       */
  /*    y3  :: The end coordinate.                                         */
  /*                                                                       */
  /* <InOut>                                                               */
  /*    min :: The address of the current minimum.                         */
  /*                                                                       */
  /*    max :: The address of the current maximum.                         */
  /*                                                                       */
  static void
  BBox_Conic_Check( FT_Pos   y1,
                    FT_Pos   y2,
                    FT_Pos   y3,
                    FT_Pos*  min,
                    FT_Pos*  max )
  {
    if ( y1 <= y3 && y2 == y1 )     /* flat arc */
      goto Suite;

    if ( y1 < y3 )
    {
      if ( y2 >= y1 && y2 <= y3 )   /* ascending arc */
        goto Suite;
    }
    else
    {
      if ( y2 >= y3 && y2 <= y1 )   /* descending arc */
      {
        y2 = y1;
        y1 = y3;
        y3 = y2;
        goto Suite;
      }
    }

    y1 = y3 = y1 - FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 );

  Suite:
    if ( y1 < *min ) *min = y1;
    if ( y3 > *max ) *max = y3;
  }

  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    BBox_Conic_To                                                      */
  /*                                                                       */
  /* <Description>                                                         */
  /*    This function is used as a `conic_to' emitter during               */
  /*    FT_Outline_Decompose().  It checks a conic Bezier curve with the   */
  /*    current bounding box, and computes its extrema if necessary to     */
  /*    update it.                                                         */
  /*                                                                       */
  /* <Input>                                                               */
  /*    control :: A pointer to a control point.                           */
  /*                                                                       */
  /*    to      :: A pointer to the destination vector.                    */
  /*                                                                       */
  /* <InOut>                                                               */
  /*    user    :: The address of the current walk context.                */
  /*                                                                       */
  /* <Return>                                                              */
  /*    Always 0.  Needed for the interface only.                          */
  /*                                                                       */
  /* <Note>                                                                */
  /*    In the case of a non-monotonous arc, we compute directly the       */
  /*    extremum coordinates, as it is sufficiently fast.                  */
  /*                                                                       */
  static int
  BBox_Conic_To( FT_Vector*  control,
                 FT_Vector*  to,
                 TBBox_Rec*  user )
  {
    /* we don't need to check `to' since it is always an `on' point, thus */
    /* within the bbox                                                    */

    if ( CHECK_X( control, user->bbox ) )
      BBox_Conic_Check( user->last.x,
                        control->x,
                        to->x,
                        &user->bbox.xMin,
                        &user->bbox.xMax );

    if ( CHECK_Y( control, user->bbox ) )
      BBox_Conic_Check( user->last.y,
                        control->y,
                        to->y,
                        &user->bbox.yMin,
                        &user->bbox.yMax );

    user->last = *to;

    return 0;
  }

  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    BBox_Cubic_Check                                                   */
  /*                                                                       */
  /* <Description>                                                         */
  /*    Finds the extrema of a 1-dimensional cubic Bezier curve and        */
  /*    updates a bounding range.  This version uses splitting because we  */
  /*    don't want to use square roots and extra accuracy.                 */
  /*                                                                       */
  /* <Input>                                                               */
  /*    p1  :: The start coordinate.                                       */
  /*                                                                       */
  /*    p2  :: The coordinate of the first control point.                  */
  /*                                                                       */
  /*    p3  :: The coordinate of the second control point.                 */
  /*                                                                       */
  /*    p4  :: The end coordinate.                                         */
  /*                                                                       */
  /* <InOut>                                                               */
  /*    min :: The address of the current minimum.                         */
  /*                                                                       */
  /*    max :: The address of the current maximum.                         */
  /*                                                                       */

#if 0

  static void
  BBox_Cubic_Check( FT_Pos   p1,
                    FT_Pos   p2,
                    FT_Pos   p3,
                    FT_Pos   p4,
                    FT_Pos*  min,
                    FT_Pos*  max )
  {
    FT_Pos  stack[32*3 + 1], *arc;

    arc = stack;

    arc[0] = p1;
    arc[1] = p2;
    arc[2] = p3;
    arc[3] = p4;

    do
    {
      FT_Pos  y1 = arc[0];
      FT_Pos  y2 = arc[1];
      FT_Pos  y3 = arc[2];
      FT_Pos  y4 = arc[3];

      if ( y1 == y4 )
      {
        if ( y1 == y2 && y1 == y3 )                         /* flat */
          goto Test;
      }
      else if ( y1 < y4 )
      {
        if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* ascending */
          goto Test;
      }
      else
      {
        if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* descending */
        {
          y2 = y1;
          y1 = y4;
          y4 = y2;
          goto Test;
        }
      }

      /* unknown direction -- split the arc in two */
      arc[6] = y4;
      arc[1] = y1 = ( y1 + y2 ) / 2;
      arc[5] = y4 = ( y4 + y3 ) / 2;
      y2 = ( y2 + y3 ) / 2;
      arc[2] = y1 = ( y1 + y2 ) / 2;
      arc[4] = y4 = ( y4 + y2 ) / 2;
      arc[3] = ( y1 + y4 ) / 2;

      arc += 3;
      goto Suite;

   Test:
      if ( y1 < *min ) *min = y1;
      if ( y4 > *max ) *max = y4;
      arc -= 3;

    Suite:
      ;
    } while ( arc >= stack );
  }

#else

  static void
  test_cubic_extrema( FT_Pos    y1,
                      FT_Pos    y2,
                      FT_Pos    y3,
                      FT_Pos    y4,
                      FT_Fixed  u,
                      FT_Pos*   min,
                      FT_Pos*   max )
  {
 /* FT_Pos    a = y4 - 3*y3 + 3*y2 - y1; */
    FT_Pos    b = y3 - 2*y2 + y1;
    FT_Pos    c = y2 - y1;
    FT_Pos    d = y1;
    FT_Pos    y;
    FT_Fixed  uu;

    FT_UNUSED ( y4 );

    /* The polynomial is                      */
    /*                                        */
    /*    P(x) = a*x^3 + 3b*x^2 + 3c*x + d  , */
    /*                                        */
    /*   dP/dx = 3a*x^2 + 6b*x + 3c         . */
    /*                                        */
    /* However, we also have                  */
    /*                                        */
    /*   dP/dx(u) = 0                       , */
    /*                                        */
    /* which implies by subtraction that      */
    /*                                        */
    /*   P(u) = b*u^2 + 2c*u + d            . */

    if ( u > 0 && u < 0x10000L )
    {
      uu = FT_MulFix( u, u );
      y  = d + FT_MulFix( c, 2*u ) + FT_MulFix( b, uu );

      if ( y < *min ) *min = y;
      if ( y > *max ) *max = y;
    }
  }

  static void
  BBox_Cubic_Check( FT_Pos   y1,
                    FT_Pos   y2,
                    FT_Pos   y3,
                    FT_Pos   y4,
                    FT_Pos*  min,
                    FT_Pos*  max )
  {
    /* always compare first and last points */
    if      ( y1 < *min )  *min = y1;
    else if ( y1 > *max )  *max = y1;

    if      ( y4 < *min )  *min = y4;
    else if ( y4 > *max )  *max = y4;

    /* now, try to see if there are split points here */
    if ( y1 <= y4 )
    {
      /* flat or ascending arc test */
      if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 )
        return;
    }
    else /* y1 > y4 */
    {
      /* descending arc test */
      if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 )
        return;
    }

    /* There are some split points.  Find them. */
    {
      FT_Pos    a = y4 - 3*y3 + 3*y2 - y1;
      FT_Pos    b = y3 - 2*y2 + y1;
      FT_Pos    c = y2 - y1;
      FT_Pos    d;
      FT_Fixed  t;

      /* We need to solve `ax^2+2bx+c' here, without floating points!      */
      /* The trick is to normalize to a different representation in order  */
      /* to use our 16.16 fixed point routines.                            */
      /*                                                                   */
      /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after normalization. */
      /* These values must fit into a single 16.16 value.                  */
      /*                                                                   */
      /* We normalize a, b, and c to `8.16' fixed float values to ensure   */
      /* that its product is held in a `16.16' value.                      */

      {
        FT_ULong  t1, t2;
        int       shift = 0;

        /* The following computation is based on the fact that for   */
        /* any value `y', if `n' is the position of the most         */
        /* significant bit of `abs(y)' (starting from 0 for the      */
        /* least significant bit), then `y' is in the range          */
        /*                                                           */
        /*   -2^n..2^n-1                                             */
        /*                                                           */
        /* We want to shift `a', `b', and `c' concurrently in order  */
        /* to ensure that they all fit in 8.16 values, which maps    */
        /* to the integer range `-2^23..2^23-1'.                     */
        /*                                                           */
        /* Necessarily, we need to shift `a', `b', and `c' so that   */
        /* the most significant bit of its absolute values is at     */
        /* _most_ at position 23.                                    */
        /*                                                           */
        /* We begin by computing `t1' as the bitwise `OR' of the     */
        /* absolute values of `a', `b', `c'.                         */

        t1  = (FT_ULong)( ( a >= 0 ) ? a : -a );
        t2  = (FT_ULong)( ( b >= 0 ) ? b : -b );
        t1 |= t2;
        t2  = (FT_ULong)( ( c >= 0 ) ? c : -c );
        t1 |= t2;

        /* Now we can be sure that the most significant bit of `t1'  */
        /* is the most significant bit of either `a', `b', or `c',   */
        /* depending on the greatest integer range of the particular */
        /* variable.                                                 */
        /*                                                           */
        /* Next, we compute the `shift', by shifting `t1' as many    */
        /* times as necessary to move its MSB to position 23.  This  */
        /* corresponds to a value of `t1' that is in the range       */
        /* 0x40_0000..0x7F_FFFF.                                     */
        /*                                                           */
        /* Finally, we shift `a', `b', and `c' by the same amount.   */
        /* This ensures that all values are now in the range         */
        /* -2^23..2^23, i.e., they are now expressed as 8.16         */
        /* fixed-float numbers.  This also means that we are using   */
        /* 24 bits of precision to compute the zeros, independently  */
        /* of the range of the original polynomial coefficients.     */
        /*                                                           */
        /* This algorithm should ensure reasonably accurate values   */
        /* for the zeros.  Note that they are only expressed with    */
        /* 16 bits when computing the extrema (the zeros need to     */
        /* be in 0..1 exclusive to be considered part of the arc).   */

        if ( t1 == 0 )  /* all coefficients are 0! */
          return;

        if ( t1 > 0x7FFFFFUL )
        {
          do
          {
            shift++;
            t1 >>= 1;

          } while ( t1 > 0x7FFFFFUL );

          /* this loses some bits of precision, but we use 24 of them */
          /* for the computation anyway                               */
          a >>= shift;
          b >>= shift;
          c >>= shift;
        }
        else if ( t1 < 0x400000UL )
        {
          do
          {
            shift++;
            t1 <<= 1;

          } while ( t1 < 0x400000UL );

          a <<= shift;
          b <<= shift;
          c <<= shift;
        }
      }

      /* handle a == 0 */
      if ( a == 0 )
      {
        if ( b != 0 )
        {
          t = - FT_DivFix( c, b ) / 2;
          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
        }
      }
      else
      {
        /* solve the equation now */
        d = FT_MulFix( b, b ) - FT_MulFix( a, c );
        if ( d < 0 )
          return;

        if ( d == 0 )
        {
          /* there is a single split point at -b/a */
          t = - FT_DivFix( b, a );
          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
        }
        else
        {
          /* there are two solutions; we need to filter them */
          d = FT_SqrtFixed( (FT_Int32)d );
          t = - FT_DivFix( b - d, a );
          test_cubic_extrema( y1, y2, y3, y4, t, min, max );

          t = - FT_DivFix( b + d, a );
          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
        }
      }
    }
  }

#endif

  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    BBox_Cubic_To                                                      */
  /*                                                                       */
  /* <Description>                                                         */
  /*    This function is used as a `cubic_to' emitter during               */
  /*    FT_Outline_Decompose().  It checks a cubic Bezier curve with the   */
  /*    current bounding box, and computes its extrema if necessary to     */
  /*    update it.                                                         */
  /*                                                                       */
  /* <Input>                                                               */
  /*    control1 :: A pointer to the first control point.                  */
  /*                                                                       */
  /*    control2 :: A pointer to the second control point.                 */
  /*                                                                       */
  /*    to       :: A pointer to the destination vector.                   */
  /*                                                                       */
  /* <InOut>                                                               */
  /*    user     :: The address of the current walk context.               */
  /*                                                                       */
  /* <Return>                                                              */
  /*    Always 0.  Needed for the interface only.                          */
  /*                                                                       */
  /* <Note>                                                                */
  /*    In the case of a non-monotonous arc, we don't compute directly     */
  /*    extremum coordinates, we subdivide instead.                        */
  /*                                                                       */
  static int
  BBox_Cubic_To( FT_Vector*  control1,
                 FT_Vector*  control2,
                 FT_Vector*  to,
                 TBBox_Rec*  user )
  {
    /* we don't need to check `to' since it is always an `on' point, thus */
    /* within the bbox                                                    */

    if ( CHECK_X( control1, user->bbox ) ||
         CHECK_X( control2, user->bbox ) )
      BBox_Cubic_Check( user->last.x,
                        control1->x,
                        control2->x,
                        to->x,
                        &user->bbox.xMin,
                        &user->bbox.xMax );

    if ( CHECK_Y( control1, user->bbox ) ||
         CHECK_Y( control2, user->bbox ) )
      BBox_Cubic_Check( user->last.y,
                        control1->y,
                        control2->y,
                        to->y,
                        &user->bbox.yMin,
                        &user->bbox.yMax );

    user->last = *to;

    return 0;
  }

FT_DEFINE_OUTLINE_FUNCS(bbox_interface,
    (FT_Outline_MoveTo_Func) BBox_Move_To,
    (FT_Outline_LineTo_Func) BBox_Move_To,
    (FT_Outline_ConicTo_Func)BBox_Conic_To,
    (FT_Outline_CubicTo_Func)BBox_Cubic_To,
    0, 0
  )

  /* documentation is in ftbbox.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Outline_Get_BBox( FT_Outline*  outline,
                       FT_BBox     *abbox )
  {
    FT_BBox     cbox;
    FT_BBox     bbox;
    FT_Vector*  vec;
    FT_UShort   n;

    if ( !abbox )
      return FT_Err_Invalid_Argument;

    if ( !outline )
      return FT_Err_Invalid_Outline;

    /* if outline is empty, return (0,0,0,0) */
    if ( outline->n_points == 0 || outline->n_contours <= 0 )
    {
      abbox->xMin = abbox->xMax = 0;
      abbox->yMin = abbox->yMax = 0;
      return 0;
    }

    /* We compute the control box as well as the bounding box of  */
    /* all `on' points in the outline.  Then, if the two boxes    */
    /* coincide, we exit immediately.                             */

    vec = outline->points;
    bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x;
    bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y;
    vec++;

    for ( n = 1; n < outline->n_points; n++ )
    {
      FT_Pos  x = vec->x;
      FT_Pos  y = vec->y;

      /* update control box */
      if ( x < cbox.xMin ) cbox.xMin = x;
      if ( x > cbox.xMax ) cbox.xMax = x;

      if ( y < cbox.yMin ) cbox.yMin = y;
      if ( y > cbox.yMax ) cbox.yMax = y;

      if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )
      {
        /* update bbox for `on' points only */
        if ( x < bbox.xMin ) bbox.xMin = x;
        if ( x > bbox.xMax ) bbox.xMax = x;

        if ( y < bbox.yMin ) bbox.yMin = y;
        if ( y > bbox.yMax ) bbox.yMax = y;
      }

      vec++;
    }

    /* test two boxes for equality */
    if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax ||
         cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax )
    {
      /* the two boxes are different, now walk over the outline to */
      /* get the Bezier arc extrema.                               */

      FT_Error   error;
      TBBox_Rec  user;

#ifdef FT_CONFIG_OPTION_PIC
      FT_Outline_Funcs bbox_interface;
      Init_Class_bbox_interface(&bbox_interface);
#endif

      user.bbox = bbox;

      error = FT_Outline_Decompose( outline, &bbox_interface, &user );
      if ( error )
        return error;

      *abbox = user.bbox;
    }
    else
      *abbox = bbox;

    return FT_Err_Ok;
  }

/* END */


code:
/***************************************************************************/
/*                                                                         */
/*  ftbdf.c                                                                */
/*                                                                         */
/*    FreeType API for accessing BDF-specific strings (body).              */
/*                                                                         */
/*  Copyright 2002, 2003, 2004 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_OBJECTS_H
#include FT_SERVICE_BDF_H

  /* documentation is in ftbdf.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Get_BDF_Charset_ID( FT_Face       face,
                         const char*  *acharset_encoding,
                         const char*  *acharset_registry )
  {
    FT_Error     error;
    const char*  encoding = NULL;
    const char*  registry = NULL;

    error = FT_Err_Invalid_Argument;

    if ( face )
    {
      FT_Service_BDF  service;

      FT_FACE_FIND_SERVICE( face, service, BDF );

      if ( service && service->get_charset_id )
        error = service->get_charset_id( face, &encoding, &registry );
    }

    if ( acharset_encoding )
      *acharset_encoding = encoding;

    if ( acharset_registry )
      *acharset_registry = registry;

    return error;
  }

  /* documentation is in ftbdf.h */

  FT_EXPORT_DEF( FT_Error )
  FT_Get_BDF_Property( FT_Face           face,
                       const char*       prop_name,
                       BDF_PropertyRec  *aproperty )
  {
    FT_Error  error;

    error = FT_Err_Invalid_Argument;

    aproperty->type = BDF_PROPERTY_TYPE_NONE;

    if ( face )
    {
      FT_Service_BDF  service;

      FT_FACE_FIND_SERVICE( face, service, BDF );

      if ( service && service->get_property )
        error = service->get_property( face, prop_name, aproperty );
    }

    return  error;
  }

/* END */