/***************************************************************************/

/*                                                                         */

/*  pshalgo.h                                                              */

/*                                                                         */

/*    PostScript hinting algorithm (specification).                        */

/*                                                                         */

/*  Copyright 2001, 2002, 2003, 2008 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 __PSHALGO_H__

#define __PSHALGO_H__





#include "pshrec.h"

#include "pshglob.h"

#include FT_TRIGONOMETRY_H





FT_BEGIN_HEADER





  /* handle to Hint structure */

  typedef struct PSH_HintRec_*  PSH_Hint;



  /* hint bit-flags */

  typedef enum  PSH_Hint_Flags_

  {

    PSH_HINT_GHOST  = PS_HINT_FLAG_GHOST,

    PSH_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM,

    PSH_HINT_ACTIVE = 4,

    PSH_HINT_FITTED = 8



  } PSH_Hint_Flags;





#define psh_hint_is_active( x )  ( ( (x)->flags & PSH_HINT_ACTIVE ) != 0 )

#define psh_hint_is_ghost( x )   ( ( (x)->flags & PSH_HINT_GHOST  ) != 0 )

#define psh_hint_is_fitted( x )  ( ( (x)->flags & PSH_HINT_FITTED ) != 0 )



#define psh_hint_activate( x )    (x)->flags |=  PSH_HINT_ACTIVE

#define psh_hint_deactivate( x )  (x)->flags &= ~PSH_HINT_ACTIVE

#define psh_hint_set_fitted( x )  (x)->flags |=  PSH_HINT_FITTED



  /* hint structure */

  typedef struct  PSH_HintRec_

  {

    FT_Int    org_pos;

    FT_Int    org_len;

    FT_Pos    cur_pos;

    FT_Pos    cur_len;

    FT_UInt   flags;

    PSH_Hint  parent;

    FT_Int    order;



  } PSH_HintRec;





  /* this is an interpolation zone used for strong points;  */

  /* weak points are interpolated according to their strong */

  /* neighbours                                             */

  typedef struct  PSH_ZoneRec_

  {

    FT_Fixed  scale;

    FT_Fixed  delta;

    FT_Pos    min;

    FT_Pos    max;



  } PSH_ZoneRec, *PSH_Zone;





  typedef struct  PSH_Hint_TableRec_

  {

    FT_UInt        max_hints;

    FT_UInt        num_hints;

    PSH_Hint       hints;

    PSH_Hint*      sort;

    PSH_Hint*      sort_global;

    FT_UInt        num_zones;

    PSH_ZoneRec*   zones;

    PSH_Zone       zone;

    PS_Mask_Table  hint_masks;

    PS_Mask_Table  counter_masks;



  } PSH_Hint_TableRec, *PSH_Hint_Table;





  typedef struct PSH_PointRec_*    PSH_Point;

  typedef struct PSH_ContourRec_*  PSH_Contour;



  enum

  {

    PSH_DIR_NONE  =  4,

    PSH_DIR_UP    = -1,

    PSH_DIR_DOWN  =  1,

    PSH_DIR_LEFT  = -2,

    PSH_DIR_RIGHT =  2

  };



#define PSH_DIR_HORIZONTAL  2

#define PSH_DIR_VERTICAL    1



#define PSH_DIR_COMPARE( d1, d2 )   ( (d1) == (d2) || (d1) == -(d2) )

#define PSH_DIR_IS_HORIZONTAL( d )  PSH_DIR_COMPARE( d, PSH_DIR_HORIZONTAL )

#define PSH_DIR_IS_VERTICAL( d )    PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL )





 /* the following bit-flags are computed once by the glyph */

 /* analyzer, for both dimensions                          */

  enum

  {

    PSH_POINT_OFF    = 1,   /* point is off the curve */

    PSH_POINT_SMOOTH = 2,   /* point is smooth        */

    PSH_POINT_INFLEX = 4    /* point is inflection    */

  };



#define psh_point_is_smooth( p )  ( (p)->flags & PSH_POINT_SMOOTH )

#define psh_point_is_off( p )     ( (p)->flags & PSH_POINT_OFF    )

#define psh_point_is_inflex( p )  ( (p)->flags & PSH_POINT_INFLEX )



#define psh_point_set_smooth( p )  (p)->flags |= PSH_POINT_SMOOTH

#define psh_point_set_off( p )     (p)->flags |= PSH_POINT_OFF

#define psh_point_set_inflex( p )  (p)->flags |= PSH_POINT_INFLEX



  /* the following bit-flags are re-computed for each dimension */

  enum

  {

    PSH_POINT_STRONG   = 16,   /* point is strong                           */

    PSH_POINT_FITTED   = 32,   /* point is already fitted                   */

    PSH_POINT_EXTREMUM = 64,   /* point is local extremum                   */

    PSH_POINT_POSITIVE = 128,  /* extremum has positive contour flow        */

    PSH_POINT_NEGATIVE = 256,  /* extremum has negative contour flow        */

    PSH_POINT_EDGE_MIN = 512,  /* point is aligned to left/bottom stem edge */

    PSH_POINT_EDGE_MAX = 1024  /* point is aligned to top/right stem edge   */

  };



#define psh_point_is_strong( p )    ( (p)->flags2 & PSH_POINT_STRONG )

#define psh_point_is_fitted( p )    ( (p)->flags2 & PSH_POINT_FITTED )

#define psh_point_is_extremum( p )  ( (p)->flags2 & PSH_POINT_EXTREMUM )

#define psh_point_is_positive( p )  ( (p)->flags2 & PSH_POINT_POSITIVE )

#define psh_point_is_negative( p )  ( (p)->flags2 & PSH_POINT_NEGATIVE )

#define psh_point_is_edge_min( p )  ( (p)->flags2 & PSH_POINT_EDGE_MIN )

#define psh_point_is_edge_max( p )  ( (p)->flags2 & PSH_POINT_EDGE_MAX )



#define psh_point_set_strong( p )    (p)->flags2 |= PSH_POINT_STRONG

#define psh_point_set_fitted( p )    (p)->flags2 |= PSH_POINT_FITTED

#define psh_point_set_extremum( p )  (p)->flags2 |= PSH_POINT_EXTREMUM

#define psh_point_set_positive( p )  (p)->flags2 |= PSH_POINT_POSITIVE

#define psh_point_set_negative( p )  (p)->flags2 |= PSH_POINT_NEGATIVE

#define psh_point_set_edge_min( p )  (p)->flags2 |= PSH_POINT_EDGE_MIN

#define psh_point_set_edge_max( p )  (p)->flags2 |= PSH_POINT_EDGE_MAX





  typedef struct  PSH_PointRec_

  {

    PSH_Point    prev;

    PSH_Point    next;

    PSH_Contour  contour;

    FT_UInt      flags;

    FT_UInt      flags2;

    FT_Char      dir_in;

    FT_Char      dir_out;

    FT_Angle     angle_in;

    FT_Angle     angle_out;

    PSH_Hint     hint;

    FT_Pos       org_u;

    FT_Pos       org_v;

    FT_Pos       cur_u;

#ifdef DEBUG_HINTER

    FT_Pos       org_x;

    FT_Pos       cur_x;

    FT_Pos       org_y;

    FT_Pos       cur_y;

    FT_UInt      flags_x;

    FT_UInt      flags_y;

#endif



  } PSH_PointRec;





#define PSH_POINT_EQUAL_ORG( a, b )  ( (a)->org_u == (b)->org_u && \

                                       (a)->org_v == (b)->org_v )



#define PSH_POINT_ANGLE( a, b )  FT_Atan2( (b)->org_u - (a)->org_u,  \

                                           (b)->org_v - (a)->org_v )



  typedef struct  PSH_ContourRec_

  {

    PSH_Point  start;

    FT_UInt    count;



  } PSH_ContourRec;





  typedef struct  PSH_GlyphRec_

  {

    FT_UInt            num_points;

    FT_UInt            num_contours;



    PSH_Point          points;

    PSH_Contour        contours;



    FT_Memory          memory;

    FT_Outline*        outline;

    PSH_Globals        globals;

    PSH_Hint_TableRec  hint_tables[2];



    FT_Bool            vertical;

    FT_Int             major_dir;

    FT_Int             minor_dir;



    FT_Bool            do_horz_hints;

    FT_Bool            do_vert_hints;

    FT_Bool            do_horz_snapping;

    FT_Bool            do_vert_snapping;

    FT_Bool            do_stem_adjust;



  } PSH_GlyphRec, *PSH_Glyph;





#ifdef DEBUG_HINTER

  extern PSH_Hint_Table  ps_debug_hint_table;



  typedef void

  (*PSH_HintFunc)( PSH_Hint  hint,

                   FT_Bool   vertical );



  extern PSH_HintFunc    ps_debug_hint_func;



  extern PSH_Glyph       ps_debug_glyph;

#endif





  extern FT_Error

  ps_hints_apply( PS_Hints        ps_hints,

                  FT_Outline*     outline,

                  PSH_Globals     globals,

                  FT_Render_Mode  hint_mode );





FT_END_HEADER





#endif /* __PSHALGO_H__ */





/* END */

