/****************************************************************************
 *
 * aftypes.h
 *
 *   Auto-fitter types (specification only).
 *
 * Copyright (C) 2003-2020 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
   * writing systems and scripts in order to apply specific rules.
   *
   * The code has also been compartmentalized into several entities that
   * should make algorithmic experimentation easier than with the old
   * code.
   *
   *************************************************************************/


#ifndef AFTYPES_H_
#define AFTYPES_H_


#include <freetype/freetype.h>
#include <freetype/ftoutln.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>

#include "afblue.h"

#ifdef FT_DEBUG_AUTOFIT
#include FT_CONFIG_STANDARD_LIBRARY_H
#endif


FT_BEGIN_HEADER

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

#ifdef FT_DEBUG_AUTOFIT

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;

#endif /* FT_DEBUG_AUTOFIT */


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                 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 subpixels */
    FT_Pos  fit;  /* current/fitted position/width in device subpixels */

  } AF_WidthRec, *AF_Width;


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

  FT_LOCAL( void )
  af_sort_and_quantize_widths( FT_UInt*  count,
                               AF_Width  widths,
                               FT_Pos    threshold );


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                   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);     \
                                                \
                                                \
    while ( _delta <= -AF_ANGLE_PI )            \
      _delta += AF_ANGLE_2PI;                   \
                                                \
    while ( _delta > AF_ANGLE_PI )              \
      _delta -= AF_ANGLE_2PI;                   \
                                                \
    result = _delta;                            \
  FT_END_STMNT


  /*
   * opaque handle to glyph-specific hints -- see `afhints.h' for more
   * details
   */
  typedef struct AF_GlyphHintsRec_*  AF_GlyphHints;


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

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

#define AF_SCALER_FLAG_NO_HORIZONTAL  1U /* disable horizontal hinting */
#define AF_SCALER_FLAG_NO_VERTICAL    2U /* disable vertical hinting   */
#define AF_SCALER_FLAG_NO_ADVANCE     4U /* disable advance hinting    */
#define AF_SCALER_FLAG_NO_WARPER      8U /* disable warper             */


  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 )


  typedef struct AF_StyleMetricsRec_*  AF_StyleMetrics;

  /*
   * This function parses an FT_Face to compute global metrics for
   * a specific style.
   */
  typedef FT_Error
  (*AF_WritingSystem_InitMetricsFunc)( AF_StyleMetrics  metrics,
                                       FT_Face          face );

  typedef void
  (*AF_WritingSystem_ScaleMetricsFunc)( AF_StyleMetrics  metrics,
                                        AF_Scaler        scaler );

  typedef void
  (*AF_WritingSystem_DoneMetricsFunc)( AF_StyleMetrics  metrics );

  typedef void
  (*AF_WritingSystem_GetStdWidthsFunc)( AF_StyleMetrics  metrics,
                                        FT_Pos*          stdHW,
                                        FT_Pos*          stdVW );


  typedef FT_Error
  (*AF_WritingSystem_InitHintsFunc)( AF_GlyphHints    hints,
                                     AF_StyleMetrics  metrics );

  typedef FT_Error
  (*AF_WritingSystem_ApplyHintsFunc)( FT_UInt          glyph_index,
                                      AF_GlyphHints    hints,
                                      FT_Outline*      outline,
                                      AF_StyleMetrics  metrics );


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                W R I T I N G   S Y S T E M S                  *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*
   * For the auto-hinter, a writing system consists of multiple scripts that
   * can be handled similarly *in a typographical way*; the relationship is
   * not based on history.  For example, both the Greek and the unrelated
   * Armenian scripts share the same features like ascender, descender,
   * x-height, etc.  Essentially, a writing system is covered by a
   * submodule of the auto-fitter; it contains
   *
   * - a specific global analyzer that computes global metrics specific to
   *   the script (based on script-specific characters to identify ascender
   *   height, x-height, etc.),
   *
   * - a specific glyph analyzer that computes segments and edges for each
   *   glyph covered by the script,
   *
   * - a specific grid-fitting algorithm that distorts the scaled glyph
   *   outline according to the results of the glyph analyzer.
   */

#define AFWRTSYS_H_  /* don't load header files */
#undef  WRITING_SYSTEM
#define WRITING_SYSTEM( ws, WS )    \
          AF_WRITING_SYSTEM_ ## WS,

  /* The list of known writing systems. */
  typedef enum  AF_WritingSystem_
  {

#include "afwrtsys.h"

    AF_WRITING_SYSTEM_MAX   /* do not remove */

  } AF_WritingSystem;

#undef  AFWRTSYS_H_


  typedef struct  AF_WritingSystemClassRec_
  {
    AF_WritingSystem  writing_system;

    FT_Offset                          style_metrics_size;
    AF_WritingSystem_InitMetricsFunc   style_metrics_init;
    AF_WritingSystem_ScaleMetricsFunc  style_metrics_scale;
    AF_WritingSystem_DoneMetricsFunc   style_metrics_done;
    AF_WritingSystem_GetStdWidthsFunc  style_metrics_getstdw;

    AF_WritingSystem_InitHintsFunc     style_hints_init;
    AF_WritingSystem_ApplyHintsFunc    style_hints_apply;

  } AF_WritingSystemClassRec;

  typedef const AF_WritingSystemClassRec*  AF_WritingSystemClass;


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

  /*
   * Each script is associated with two sets of Unicode ranges to test
   * whether the font face supports the script, and which non-base
   * characters the script contains.
   *
   * We use four-letter script tags from the OpenType specification,
   * extended by `NONE', which indicates `no script'.
   */

#undef  SCRIPT
#define SCRIPT( s, S, d, h, H, ss ) \
          AF_SCRIPT_ ## S,

  /* The list of known scripts. */
  typedef enum  AF_Script_
  {

#include "afscript.h"

    AF_SCRIPT_MAX   /* do not remove */

  } AF_Script;


  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;

    /* last element in the ranges must be { 0, 0 } */
    AF_Script_UniRange  script_uni_ranges;
    AF_Script_UniRange  script_uni_nonbase_ranges;

    FT_Bool  top_to_bottom_hinting;

    const char*  standard_charstring;      /* for default width and height */

  } AF_ScriptClassRec;

  typedef const AF_ScriptClassRec*  AF_ScriptClass;


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                      C O V E R A G E S                        *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*
   * Usually, a font contains more glyphs than can be addressed by its
   * character map.
   *
   * In the PostScript font world, encoding vectors specific to a given
   * task are used to select such glyphs, and these glyphs can be often
   * recognized by having a suffix in its glyph names.  For example, a
   * superscript glyph `A' might be called `A.sup'.  Unfortunately, this
   * naming scheme is not standardized and thus unusable for us.
   *
   * In the OpenType world, a better solution was invented, namely
   * `features', which cleanly separate a character's input encoding from
   * the corresponding glyph's appearance, and which don't use glyph names
   * at all.  For our purposes, and slightly generalized, an OpenType
   * feature is a name of a mapping that maps character codes to
   * non-standard glyph indices (features get used for other things also).
   * For example, the `sups' feature provides superscript glyphs, thus
   * mapping character codes like `A' or `B' to superscript glyph
   * representation forms.  How this mapping happens is completely
   * uninteresting to us.
   *
   * For the auto-hinter, a `coverage' represents all glyphs of an OpenType
   * feature collected in a set (as listed below) that can be hinted
   * together.  To continue the above example, superscript glyphs must not
   * be hinted together with normal glyphs because the blue zones
   * completely differ.
   *
   * Note that FreeType itself doesn't compute coverages; it only provides
   * the glyphs addressable by the default Unicode character map.  Instead,
   * we use the HarfBuzz library (if available), which has many functions
   * exactly for this purpose.
   *
   * AF_COVERAGE_DEFAULT is special: It should cover everything that isn't
   * listed separately (including the glyphs addressable by the character
   * map).  In case HarfBuzz isn't available, it exactly covers the glyphs
   * addressable by the character map.
   *
   */

#undef  COVERAGE
#define COVERAGE( name, NAME, description, \
                  tag1, tag2, tag3, tag4 ) \
          AF_COVERAGE_ ## NAME,


  typedef enum  AF_Coverage_
  {
#include "afcover.h"

    AF_COVERAGE_DEFAULT

  } AF_Coverage;


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                         S T Y L E S                           *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*
   * The topmost structure for modelling the auto-hinter glyph input data
   * is a `style class', grouping everything together.
   */

#undef  STYLE
#define STYLE( s, S, d, ws, sc, ss, c ) \
          AF_STYLE_ ## S,

  /* The list of known styles. */
  typedef enum  AF_Style_
  {

#include "afstyles.h"

    AF_STYLE_MAX   /* do not remove */

  } AF_Style;


  typedef struct  AF_StyleClassRec_
  {
    AF_Style  style;

    AF_WritingSystem   writing_system;
    AF_Script          script;
    AF_Blue_Stringset  blue_stringset;
    AF_Coverage        coverage;

  } AF_StyleClassRec;

  typedef const AF_StyleClassRec*  AF_StyleClass;


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                   S T Y L E   M E T R I C S                   *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  typedef struct AF_FaceGlobalsRec_*  AF_FaceGlobals;

  /* This is the main structure that combines everything.  Autofit modules */
  /* specific to writing systems derive their structures from it, for      */
  /* example `AF_LatinMetrics'.                                            */

  typedef struct  AF_StyleMetricsRec_
  {
    AF_StyleClass   style_class;
    AF_ScalerRec    scaler;
    FT_Bool         digits_have_same_width;

    AF_FaceGlobals  globals;    /* to access properties */

  } AF_StyleMetricsRec;


#define AF_HINTING_BOTTOM_TO_TOP  0
#define AF_HINTING_TOP_TO_BOTTOM  1


  /* Declare and define vtables for classes */
#define AF_DECLARE_WRITING_SYSTEM_CLASS( writing_system_class ) \
  FT_CALLBACK_TABLE const AF_WritingSystemClassRec              \
  writing_system_class;

#define AF_DEFINE_WRITING_SYSTEM_CLASS(                  \
          writing_system_class,                          \
          system,                                        \
          m_size,                                        \
          m_init,                                        \
          m_scale,                                       \
          m_done,                                        \
          m_stdw,                                        \
          h_init,                                        \
          h_apply )                                      \
  FT_CALLBACK_TABLE_DEF                                  \
  const AF_WritingSystemClassRec  writing_system_class = \
  {                                                      \
    system,                                              \
                                                         \
    m_size,                                              \
                                                         \
    m_init,                                              \
    m_scale,                                             \
    m_done,                                              \
    m_stdw,                                              \
                                                         \
    h_init,                                              \
    h_apply                                              \
  };


#define AF_DECLARE_SCRIPT_CLASS( script_class ) \
  FT_CALLBACK_TABLE const AF_ScriptClassRec     \
  script_class;

#define AF_DEFINE_SCRIPT_CLASS(           \
          script_class,                   \
          script,                         \
          ranges,                         \
          nonbase_ranges,                 \
          top_to_bottom,                  \
          std_charstring )                \
  FT_CALLBACK_TABLE_DEF                   \
  const AF_ScriptClassRec  script_class = \
  {                                       \
    script,                               \
    ranges,                               \
    nonbase_ranges,                       \
    top_to_bottom,                        \
    std_charstring,                       \
  };


#define AF_DECLARE_STYLE_CLASS( style_class ) \
  FT_CALLBACK_TABLE const AF_StyleClassRec    \
  style_class;

#define AF_DEFINE_STYLE_CLASS(          \
          style_class,                  \
          style,                        \
          writing_system,               \
          script,                       \
          blue_stringset,               \
          coverage )                    \
  FT_CALLBACK_TABLE_DEF                 \
  const AF_StyleClassRec  style_class = \
  {                                     \
    style,                              \
    writing_system,                     \
    script,                             \
    blue_stringset,                     \
    coverage                            \
  };

/* */


FT_END_HEADER

#endif /* AFTYPES_H_ */


/* END */
