(root)/
freetype-2.13.2/
src/
autofit/
afhints.h
       1  /****************************************************************************
       2   *
       3   * afhints.h
       4   *
       5   *   Auto-fitter hinting routines (specification).
       6   *
       7   * Copyright (C) 2003-2023 by
       8   * David Turner, Robert Wilhelm, and Werner Lemberg.
       9   *
      10   * This file is part of the FreeType project, and may only be used,
      11   * modified, and distributed under the terms of the FreeType project
      12   * license, LICENSE.TXT.  By continuing to use, modify, or distribute
      13   * this file you indicate that you have read the license and
      14   * understand and accept it fully.
      15   *
      16   */
      17  
      18  
      19  #ifndef AFHINTS_H_
      20  #define AFHINTS_H_
      21  
      22  #include "aftypes.h"
      23  
      24  FT_BEGIN_HEADER
      25  
      26    /*
      27     * The definition of outline glyph hints.  These are shared by all
      28     * writing system analysis routines (until now).
      29     */
      30  
      31    typedef enum  AF_Dimension_
      32    {
      33      AF_DIMENSION_HORZ = 0,  /* x coordinates,                    */
      34                              /* i.e., vertical segments & edges   */
      35      AF_DIMENSION_VERT = 1,  /* y coordinates,                    */
      36                              /* i.e., horizontal segments & edges */
      37  
      38      AF_DIMENSION_MAX  /* do not remove */
      39  
      40    } AF_Dimension;
      41  
      42  
      43    /* hint directions -- the values are computed so that two vectors are */
      44    /* in opposite directions iff `dir1 + dir2 == 0'                      */
      45    typedef enum  AF_Direction_
      46    {
      47      AF_DIR_NONE  =  4,
      48      AF_DIR_RIGHT =  1,
      49      AF_DIR_LEFT  = -1,
      50      AF_DIR_UP    =  2,
      51      AF_DIR_DOWN  = -2
      52  
      53    } AF_Direction;
      54  
      55  
      56    /*
      57     * The following explanations are mostly taken from the article
      58     *
      59     *   Real-Time Grid Fitting of Typographic Outlines
      60     *
      61     * by David Turner and Werner Lemberg
      62     *
      63     *   https://www.tug.org/TUGboat/Articles/tb24-3/lemberg.pdf
      64     *
      65     * with appropriate updates.
      66     *
      67     *
      68     * Segments
      69     *
      70     *   `af_{cjk,latin,...}_hints_compute_segments' are the functions to
      71     *   find segments in an outline.
      72     *
      73     *   A segment is a series of at least two consecutive points that are
      74     *   approximately aligned along a coordinate axis.  The analysis to do
      75     *   so is specific to a writing system.
      76     *
      77     *
      78     * Edges
      79     *
      80     *   `af_{cjk,latin,...}_hints_compute_edges' are the functions to find
      81     *   edges.
      82     *
      83     *   As soon as segments are defined, the auto-hinter groups them into
      84     *   edges.  An edge corresponds to a single position on the main
      85     *   dimension that collects one or more segments (allowing for a small
      86     *   threshold).
      87     *
      88     *   As an example, the `latin' writing system first tries to grid-fit
      89     *   edges, then to align segments on the edges unless it detects that
      90     *   they form a serif.
      91     *
      92     *
      93     *                     A          H
      94     *                      |        |
      95     *                      |        |
      96     *                      |        |
      97     *                      |        |
      98     *        C             |        |             F
      99     *         +------<-----+        +-----<------+
     100     *         |             B      G             |
     101     *         |                                  |
     102     *         |                                  |
     103     *         +--------------->------------------+
     104     *        D                                    E
     105     *
     106     *
     107     * Stems
     108     *
     109     *   Stems are detected by `af_{cjk,latin,...}_hint_edges'.
     110     *
     111     *   Segments need to be `linked' to other ones in order to detect stems.
     112     *   A stem is made of two segments that face each other in opposite
     113     *   directions and that are sufficiently close to each other.  Using
     114     *   vocabulary from the TrueType specification, stem segments form a
     115     *   `black distance'.
     116     *
     117     *   In the above ASCII drawing, the horizontal segments are BC, DE, and
     118     *   FG; the vertical segments are AB, CD, EF, and GH.
     119     *
     120     *   Each segment has at most one `best' candidate to form a black
     121     *   distance, or no candidate at all.  Notice that two distinct segments
     122     *   can have the same candidate, which frequently means a serif.
     123     *
     124     *   A stem is recognized by the following condition:
     125     *
     126     *     best segment_1 = segment_2 && best segment_2 = segment_1
     127     *
     128     *   The best candidate is stored in field `link' in structure
     129     *   `AF_Segment'.
     130     *
     131     *   In the above ASCII drawing, the best candidate for both AB and CD is
     132     *   GH, while the best candidate for GH is AB.  Similarly, the best
     133     *   candidate for EF and GH is AB, while the best candidate for AB is
     134     *   GH.
     135     *
     136     *   The detection and handling of stems is dependent on the writing
     137     *   system.
     138     *
     139     *
     140     * Serifs
     141     *
     142     *   Serifs are detected by `af_{cjk,latin,...}_hint_edges'.
     143     *
     144     *   In comparison to a stem, a serif (as handled by the auto-hinter
     145     *   module that takes care of the `latin' writing system) has
     146     *
     147     *     best segment_1 = segment_2 && best segment_2 != segment_1
     148     *
     149     *   where segment_1 corresponds to the serif segment (CD and EF in the
     150     *   above ASCII drawing).
     151     *
     152     *   The best candidate is stored in field `serif' in structure
     153     *   `AF_Segment' (and `link' is set to NULL).
     154     *
     155     *
     156     * Touched points
     157     *
     158     *   A point is called `touched' if it has been processed somehow by the
     159     *   auto-hinter.  It basically means that it shouldn't be moved again
     160     *   (or moved only under certain constraints to preserve the already
     161     *   applied processing).
     162     *
     163     *
     164     * Flat and round segments
     165     *
     166     *   Segments are `round' or `flat', depending on the series of points
     167     *   that define them.  A segment is round if the next and previous point
     168     *   of an extremum (which can be either a single point or sequence of
     169     *   points) are both conic or cubic control points.  Otherwise, a
     170     *   segment with an extremum is flat.
     171     *
     172     *
     173     * Strong Points
     174     *
     175     *   Experience has shown that points not part of an edge need to be
     176     *   interpolated linearly between their two closest edges, even if these
     177     *   are not part of the contour of those particular points.  Typical
     178     *   candidates for this are
     179     *
     180     *   - angle points (i.e., points where the `in' and `out' direction
     181     *     differ greatly)
     182     *
     183     *   - inflection points (i.e., where the `in' and `out' angles are the
     184     *     same, but the curvature changes sign) [currently, such points
     185     *     aren't handled specially in the auto-hinter]
     186     *
     187     *   `af_glyph_hints_align_strong_points' is the function that takes
     188     *   care of such situations; it is equivalent to the TrueType `IP'
     189     *   hinting instruction.
     190     *
     191     *
     192     * Weak Points
     193     *
     194     *   Other points in the outline must be interpolated using the
     195     *   coordinates of their previous and next unfitted contour neighbours.
     196     *   These are called `weak points' and are touched by the function
     197     *   `af_glyph_hints_align_weak_points', equivalent to the TrueType `IUP'
     198     *   hinting instruction.  Typical candidates are control points and
     199     *   points on the contour without a major direction.
     200     *
     201     *   The major effect is to reduce possible distortion caused by
     202     *   alignment of edges and strong points, thus weak points are processed
     203     *   after strong points.
     204     */
     205  
     206  
     207    /* point hint flags */
     208  #define AF_FLAG_NONE  0
     209  
     210    /* point type flags */
     211  #define AF_FLAG_CONIC    ( 1U << 0 )
     212  #define AF_FLAG_CUBIC    ( 1U << 1 )
     213  #define AF_FLAG_CONTROL  ( AF_FLAG_CONIC | AF_FLAG_CUBIC )
     214  
     215    /* point touch flags */
     216  #define AF_FLAG_TOUCH_X  ( 1U << 2 )
     217  #define AF_FLAG_TOUCH_Y  ( 1U << 3 )
     218  
     219    /* candidates for weak interpolation have this flag set */
     220  #define AF_FLAG_WEAK_INTERPOLATION  ( 1U << 4 )
     221  
     222    /* the distance to the next point is very small */
     223  #define AF_FLAG_NEAR  ( 1U << 5 )
     224  
     225  
     226    /* edge hint flags */
     227  #define AF_EDGE_NORMAL  0
     228  #define AF_EDGE_ROUND    ( 1U << 0 )
     229  #define AF_EDGE_SERIF    ( 1U << 1 )
     230  #define AF_EDGE_DONE     ( 1U << 2 )
     231  #define AF_EDGE_NEUTRAL  ( 1U << 3 ) /* edge aligns to a neutral blue zone */
     232  
     233  
     234    typedef struct AF_PointRec_*    AF_Point;
     235    typedef struct AF_SegmentRec_*  AF_Segment;
     236    typedef struct AF_EdgeRec_*     AF_Edge;
     237  
     238  
     239    typedef struct  AF_PointRec_
     240    {
     241      FT_UShort  flags;    /* point flags used by hinter   */
     242      FT_Char    in_dir;   /* direction of inwards vector  */
     243      FT_Char    out_dir;  /* direction of outwards vector */
     244  
     245      FT_Pos     ox, oy;   /* original, scaled position                   */
     246      FT_Short   fx, fy;   /* original, unscaled position (in font units) */
     247      FT_Pos     x, y;     /* current position                            */
     248      FT_Pos     u, v;     /* current (x,y) or (y,x) depending on context */
     249  
     250      AF_Point   next;     /* next point in contour     */
     251      AF_Point   prev;     /* previous point in contour */
     252  
     253  #ifdef FT_DEBUG_AUTOFIT
     254      /* track `before' and `after' edges for strong points */
     255      AF_Edge    before[2];
     256      AF_Edge    after[2];
     257  #endif
     258  
     259    } AF_PointRec;
     260  
     261  
     262    typedef struct  AF_SegmentRec_
     263    {
     264      FT_Byte     flags;       /* edge/segment flags for this segment */
     265      FT_Char     dir;         /* segment direction                   */
     266      FT_Short    pos;         /* position of segment                 */
     267      FT_Short    delta;       /* deviation from segment position     */
     268      FT_Short    min_coord;   /* minimum coordinate of segment       */
     269      FT_Short    max_coord;   /* maximum coordinate of segment       */
     270      FT_Short    height;      /* the hinted segment height           */
     271  
     272      AF_Edge     edge;        /* the segment's parent edge           */
     273      AF_Segment  edge_next;   /* link to next segment in parent edge */
     274  
     275      AF_Segment  link;        /* (stem) link segment        */
     276      AF_Segment  serif;       /* primary segment for serifs */
     277      FT_Pos      score;       /* used during stem matching  */
     278      FT_Pos      len;         /* used during stem matching  */
     279  
     280      AF_Point    first;       /* first point in edge segment */
     281      AF_Point    last;        /* last point in edge segment  */
     282  
     283    } AF_SegmentRec;
     284  
     285  
     286    typedef struct  AF_EdgeRec_
     287    {
     288      FT_Short    fpos;       /* original, unscaled position (in font units) */
     289      FT_Pos      opos;       /* original, scaled position                   */
     290      FT_Pos      pos;        /* current position                            */
     291  
     292      FT_Byte     flags;      /* edge flags                                   */
     293      FT_Char     dir;        /* edge direction                               */
     294      FT_Fixed    scale;      /* used to speed up interpolation between edges */
     295  
     296      AF_Width    blue_edge;  /* non-NULL if this is a blue edge */
     297      AF_Edge     link;       /* link edge                       */
     298      AF_Edge     serif;      /* primary edge for serifs         */
     299      FT_Int      score;      /* used during stem matching       */
     300  
     301      AF_Segment  first;      /* first segment in edge */
     302      AF_Segment  last;       /* last segment in edge  */
     303  
     304    } AF_EdgeRec;
     305  
     306  #define AF_SEGMENTS_EMBEDDED  18   /* number of embedded segments   */
     307  #define AF_EDGES_EMBEDDED     12   /* number of embedded edges      */
     308  
     309    typedef struct  AF_AxisHintsRec_
     310    {
     311      FT_UInt       num_segments; /* number of used segments      */
     312      FT_UInt       max_segments; /* number of allocated segments */
     313      AF_Segment    segments;     /* segments array               */
     314  
     315      FT_UInt       num_edges;    /* number of used edges      */
     316      FT_UInt       max_edges;    /* number of allocated edges */
     317      AF_Edge       edges;        /* edges array               */
     318  
     319      AF_Direction  major_dir;    /* either vertical or horizontal */
     320  
     321      /* two arrays to avoid allocation penalty */
     322      struct
     323      {
     324        AF_SegmentRec  segments[AF_SEGMENTS_EMBEDDED];
     325        AF_EdgeRec     edges[AF_EDGES_EMBEDDED];
     326      } embedded;
     327  
     328  
     329    } AF_AxisHintsRec, *AF_AxisHints;
     330  
     331  
     332  #define AF_POINTS_EMBEDDED     96   /* number of embedded points   */
     333  #define AF_CONTOURS_EMBEDDED    8   /* number of embedded contours */
     334  
     335    typedef struct  AF_GlyphHintsRec_
     336    {
     337      FT_Memory        memory;
     338  
     339      FT_Fixed         x_scale;
     340      FT_Pos           x_delta;
     341  
     342      FT_Fixed         y_scale;
     343      FT_Pos           y_delta;
     344  
     345      FT_Int           max_points;    /* number of allocated points */
     346      FT_Int           num_points;    /* number of used points      */
     347      AF_Point         points;        /* points array               */
     348  
     349      FT_Int           max_contours;  /* number of allocated contours */
     350      FT_Int           num_contours;  /* number of used contours      */
     351      AF_Point*        contours;      /* contours array               */
     352  
     353      AF_AxisHintsRec  axis[AF_DIMENSION_MAX];
     354  
     355      FT_UInt32        scaler_flags;  /* copy of scaler flags    */
     356      FT_UInt32        other_flags;   /* free for style-specific */
     357                                      /* implementations         */
     358      AF_StyleMetrics  metrics;
     359  
     360      /* Two arrays to avoid allocation penalty.            */
     361      /* The `embedded' structure must be the last element! */
     362      struct
     363      {
     364        AF_Point       contours[AF_CONTOURS_EMBEDDED];
     365        AF_PointRec    points[AF_POINTS_EMBEDDED];
     366      } embedded;
     367  
     368    } AF_GlyphHintsRec;
     369  
     370  
     371  #define AF_HINTS_TEST_SCALER( h, f )  ( (h)->scaler_flags & (f) )
     372  #define AF_HINTS_TEST_OTHER( h, f )   ( (h)->other_flags  & (f) )
     373  
     374  
     375  #ifdef FT_DEBUG_AUTOFIT
     376  
     377  #define AF_HINTS_DO_HORIZONTAL( h )                                     \
     378            ( !af_debug_disable_horz_hints_                            && \
     379              !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL ) )
     380  
     381  #define AF_HINTS_DO_VERTICAL( h )                                     \
     382            ( !af_debug_disable_vert_hints_                          && \
     383              !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL ) )
     384  
     385  #define AF_HINTS_DO_BLUES( h )  ( !af_debug_disable_blue_hints_ )
     386  
     387  #else /* !FT_DEBUG_AUTOFIT */
     388  
     389  #define AF_HINTS_DO_HORIZONTAL( h )                                \
     390            !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_HORIZONTAL )
     391  
     392  #define AF_HINTS_DO_VERTICAL( h )                                \
     393            !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_VERTICAL )
     394  
     395  #define AF_HINTS_DO_BLUES( h )  1
     396  
     397  #endif /* !FT_DEBUG_AUTOFIT */
     398  
     399  
     400  #define AF_HINTS_DO_ADVANCE( h )                                \
     401            !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
     402  
     403  
     404    FT_LOCAL( AF_Direction )
     405    af_direction_compute( FT_Pos  dx,
     406                          FT_Pos  dy );
     407  
     408  
     409    FT_LOCAL( FT_Error )
     410    af_axis_hints_new_segment( AF_AxisHints  axis,
     411                               FT_Memory     memory,
     412                               AF_Segment   *asegment );
     413  
     414    FT_LOCAL( FT_Error)
     415    af_axis_hints_new_edge( AF_AxisHints  axis,
     416                            FT_Int        fpos,
     417                            AF_Direction  dir,
     418                            FT_Bool       top_to_bottom_hinting,
     419                            FT_Memory     memory,
     420                            AF_Edge      *edge );
     421  
     422    FT_LOCAL( void )
     423    af_glyph_hints_init( AF_GlyphHints  hints,
     424                         FT_Memory      memory );
     425  
     426    FT_LOCAL( void )
     427    af_glyph_hints_rescale( AF_GlyphHints    hints,
     428                            AF_StyleMetrics  metrics );
     429  
     430    FT_LOCAL( FT_Error )
     431    af_glyph_hints_reload( AF_GlyphHints  hints,
     432                           FT_Outline*    outline );
     433  
     434    FT_LOCAL( void )
     435    af_glyph_hints_save( AF_GlyphHints  hints,
     436                         FT_Outline*    outline );
     437  
     438    FT_LOCAL( void )
     439    af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
     440                                      AF_Dimension   dim );
     441  
     442    FT_LOCAL( void )
     443    af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
     444                                        AF_Dimension   dim );
     445  
     446    FT_LOCAL( void )
     447    af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
     448                                      AF_Dimension   dim );
     449  
     450    FT_LOCAL( void )
     451    af_glyph_hints_done( AF_GlyphHints  hints );
     452  
     453  /* */
     454  
     455  #define AF_SEGMENT_LEN( seg )          ( (seg)->max_coord - (seg)->min_coord )
     456  
     457  #define AF_SEGMENT_DIST( seg1, seg2 )  ( ( (seg1)->pos > (seg2)->pos )   \
     458                                             ? (seg1)->pos - (seg2)->pos   \
     459                                             : (seg2)->pos - (seg1)->pos )
     460  
     461  
     462  FT_END_HEADER
     463  
     464  #endif /* AFHINTS_H_ */
     465  
     466  
     467  /* END */