godot/thirdparty/freetype/src/pshinter/pshalgo.c

/****************************************************************************
 *
 * pshalgo.c
 *
 *   PostScript hinting algorithm (body).
 *
 * Copyright (C) 2001-2023 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 <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftcalc.h>
#include "pshalgo.h"

#include "pshnterr.h"


#undef  FT_COMPONENT
#define FT_COMPONENT


#ifdef DEBUG_HINTER
  PSH_Hint_Table  ps_debug_hint_table = NULL;
  PSH_HintFunc    ps_debug_hint_func  = NULL;
  PSH_Glyph       ps_debug_glyph      = NULL;
#endif


#define COMPUTE_INFLEXS
                          /* and similar glyphs                        */


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                  BASIC HINTS RECORDINGS                       *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /* return true if two stem hints overlap */
  static FT_Int
  psh_hint_overlap( PSH_Hint  hint1,
                    PSH_Hint  hint2 )
  {}


  /* destroy hints table */
  static void
  psh_hint_table_done( PSH_Hint_Table  table,
                       FT_Memory       memory )
  {}


  /* deactivate all hints in a table */
  static void
  psh_hint_table_deactivate( PSH_Hint_Table  table )
  {}


  /* internal function to record a new hint */
  static void
  psh_hint_table_record( PSH_Hint_Table  table,
                         FT_UInt         idx )
  {}


  static void
  psh_hint_table_record_mask( PSH_Hint_Table  table,
                              PS_Mask         hint_mask )
  {}


  /* create hints table */
  static FT_Error
  psh_hint_table_init( PSH_Hint_Table  table,
                       PS_Hint_Table   hints,
                       PS_Mask_Table   hint_masks,
                       PS_Mask_Table   counter_masks,
                       FT_Memory       memory )
  {}


  static void
  psh_hint_table_activate_mask( PSH_Hint_Table  table,
                                PS_Mask         hint_mask )
  {}


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****               HINTS GRID-FITTING AND OPTIMIZATION             *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

#if 1
  static FT_Pos
  psh_dimension_quantize_len( PSH_Dimension  dim,
                              FT_Pos         len,
                              FT_Bool        do_snapping )
  {}
#endif /* 0 */


#ifdef DEBUG_HINTER

  static void
  ps_simple_scale( PSH_Hint_Table  table,
                   FT_Fixed        scale,
                   FT_Fixed        delta,
                   FT_Int          dimension )
  {
    FT_UInt  count;


    for ( count = 0; count < table->max_hints; count++ )
    {
      PSH_Hint  hint = table->hints + count;


      hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
      hint->cur_len = FT_MulFix( hint->org_len, scale );

      if ( ps_debug_hint_func )
        ps_debug_hint_func( hint, dimension );
    }
  }

#endif /* DEBUG_HINTER */


  static FT_Fixed
  psh_hint_snap_stem_side_delta( FT_Fixed  pos,
                                 FT_Fixed  len )
  {}


  static void
  psh_hint_align( PSH_Hint     hint,
                  PSH_Globals  globals,
                  FT_Int       dimension,
                  PSH_Glyph    glyph )
  {}


#if 0  /* not used for now, experimental */

 /*
  * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)
  * of stems
  */
  static void
  psh_hint_align_light( PSH_Hint     hint,
                        PSH_Globals  globals,
                        FT_Int       dimension,
                        PSH_Glyph    glyph )
  {
    PSH_Dimension  dim   = &globals->dimension[dimension];
    FT_Fixed       scale = dim->scale_mult;
    FT_Fixed       delta = dim->scale_delta;


    if ( !psh_hint_is_fitted( hint ) )
    {
      FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
      FT_Pos  len = FT_MulFix( hint->org_len, scale );

      FT_Pos  fit_len;

      PSH_AlignmentRec  align;


      /* ignore stem alignments when requested through the hint flags */
      if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
           ( dimension == 1 && !glyph->do_vert_hints ) )
      {
        hint->cur_pos = pos;
        hint->cur_len = len;

        psh_hint_set_fitted( hint );
        return;
      }

      fit_len = len;

      hint->cur_len = fit_len;

      /* check blue zones for horizontal stems */
      align.align = PSH_BLUE_ALIGN_NONE;
      align.align_bot = align.align_top = 0;

      if ( dimension == 1 )
        psh_blues_snap_stem( &globals->blues,
                             ADD_INT( hint->org_pos, hint->org_len ),
                             hint->org_pos,
                             &align );

      switch ( align.align )
      {
      case PSH_BLUE_ALIGN_TOP:
        /* the top of the stem is aligned against a blue zone */
        hint->cur_pos = align.align_top - fit_len;
        break;

      case PSH_BLUE_ALIGN_BOT:
        /* the bottom of the stem is aligned against a blue zone */
        hint->cur_pos = align.align_bot;
        break;

      case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
        /* both edges of the stem are aligned against blue zones */
        hint->cur_pos = align.align_bot;
        hint->cur_len = align.align_top - align.align_bot;
        break;

      default:
        {
          PSH_Hint  parent = hint->parent;


          if ( parent )
          {
            FT_Pos  par_org_center, par_cur_center;
            FT_Pos  cur_org_center, cur_delta;


            /* ensure that parent is already fitted */
            if ( !psh_hint_is_fitted( parent ) )
              psh_hint_align_light( parent, globals, dimension, glyph );

            par_org_center = parent->org_pos + ( parent->org_len / 2 );
            par_cur_center = parent->cur_pos + ( parent->cur_len / 2 );
            cur_org_center = hint->org_pos   + ( hint->org_len   / 2 );

            cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
            pos       = par_cur_center + cur_delta - ( len >> 1 );
          }

          /* Stems less than one pixel wide are easy -- we want to
           * make them as dark as possible, so they must fall within
           * one pixel.  If the stem is split between two pixels
           * then snap the edge that is nearer to the pixel boundary
           * to the pixel boundary.
           */
          if ( len <= 64 )
          {
            if ( ( pos + len + 63 ) / 64  != pos / 64 + 1 )
              pos += psh_hint_snap_stem_side_delta ( pos, len );
          }

          /* Position stems other to minimize the amount of mid-grays.
           * There are, in general, two positions that do this,
           * illustrated as A) and B) below.
           *
           *   +                   +                   +                   +
           *
           * A)             |--------------------------------|
           * B)   |--------------------------------|
           * C)       |--------------------------------|
           *
           * Position A) (split the excess stem equally) should be better
           * for stems of width N + f where f < 0.5.
           *
           * Position B) (split the deficiency equally) should be better
           * for stems of width N + f where f > 0.5.
           *
           * It turns out though that minimizing the total number of lit
           * pixels is also important, so position C), with one edge
           * aligned with a pixel boundary is actually preferable
           * to A).  There are also more possible positions for C) than
           * for A) or B), so it involves less distortion of the overall
           * character shape.
           */
          else /* len > 64 */
          {
            FT_Fixed  frac_len = len & 63;
            FT_Fixed  center = pos + ( len >> 1 );
            FT_Fixed  delta_a, delta_b;


            if ( ( len / 64 ) & 1 )
            {
              delta_a = FT_PIX_FLOOR( center ) + 32 - center;
              delta_b = FT_PIX_ROUND( center ) - center;
            }
            else
            {
              delta_a = FT_PIX_ROUND( center ) - center;
              delta_b = FT_PIX_FLOOR( center ) + 32 - center;
            }

            /* We choose between B) and C) above based on the amount
             * of fractional stem width; for small amounts, choose
             * C) always, for large amounts, B) always, and inbetween,
             * pick whichever one involves less stem movement.
             */
            if ( frac_len < 32 )
            {
              pos += psh_hint_snap_stem_side_delta ( pos, len );
            }
            else if ( frac_len < 48 )
            {
              FT_Fixed  side_delta = psh_hint_snap_stem_side_delta ( pos,
                                                                     len );

              if ( FT_ABS( side_delta ) < FT_ABS( delta_b ) )
                pos += side_delta;
              else
                pos += delta_b;
            }
            else
            {
              pos += delta_b;
            }
          }

          hint->cur_pos = pos;
        }
      }  /* switch */

      psh_hint_set_fitted( hint );

#ifdef DEBUG_HINTER
      if ( ps_debug_hint_func )
        ps_debug_hint_func( hint, dimension );
#endif
    }
  }

#endif /* 0 */


  static void
  psh_hint_table_align_hints( PSH_Hint_Table  table,
                              PSH_Globals     globals,
                              FT_Int          dimension,
                              PSH_Glyph       glyph )
  {}


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                POINTS INTERPOLATION ROUTINES                  *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

#define xxDEBUG_ZONES


#ifdef DEBUG_ZONES

#include FT_CONFIG_STANDARD_LIBRARY_H

  static void
  psh_print_zone( PSH_Zone  zone )
  {
    printf( "zone [scale,delta,min,max] = [%.5f,%.2f,%d,%d]\n",
             zone->scale / 65536.0,
             zone->delta / 64.0,
             zone->min,
             zone->max );
  }

#endif /* DEBUG_ZONES */


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                    HINTER GLYPH MANAGEMENT                    *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

#define psh_corner_is_flat
#define psh_corner_orientation


#ifdef COMPUTE_INFLEXS

  /* compute all inflex points in a given glyph */
  static void
  psh_glyph_compute_inflections( PSH_Glyph  glyph )
  {}

#endif /* COMPUTE_INFLEXS */


  static void
  psh_glyph_done( PSH_Glyph  glyph )
  {}


  static PSH_Dir
  psh_compute_dir( FT_Pos  dx,
                   FT_Pos  dy )
  {}


  /* load outline point coordinates into hinter glyph */
  static void
  psh_glyph_load_points( PSH_Glyph  glyph,
                         FT_Int     dimension )
  {}


  /* save hinted point coordinates back to outline */
  static void
  psh_glyph_save_points( PSH_Glyph  glyph,
                         FT_Int     dimension )
  {}


  static FT_Error
  psh_glyph_init( PSH_Glyph    glyph,
                  FT_Outline*  outline,
                  PS_Hints     ps_hints,
                  PSH_Globals  globals )
  {}


  /* compute all extrema in a glyph for a given dimension */
  static void
  psh_glyph_compute_extrema( PSH_Glyph  glyph )
  {}


  /* the min and max are based on contour orientation and fill rule */
  static void
  psh_hint_table_find_strong_points( PSH_Hint_Table  table,
                                     PSH_Point       point,
                                     FT_UInt         count,
                                     FT_Int          threshold,
                                     PSH_Dir         major_dir )
  {}


  /* the accepted shift for strong points in fractional pixels */
#define PSH_STRONG_THRESHOLD

  /* the maximum shift value in font units tuned to distinguish */
  /* between stems and serifs in URW+ font collection           */
#define PSH_STRONG_THRESHOLD_MAXIMUM


  /* find strong points in a glyph */
  static void
  psh_glyph_find_strong_points( PSH_Glyph  glyph,
                                FT_Int     dimension )
  {}


  /* find points in a glyph which are in a blue zone and have `in' or */
  /* `out' tangents parallel to the horizontal axis                   */
  static void
  psh_glyph_find_blue_points( PSH_Blues  blues,
                              PSH_Glyph  glyph )
  {}


  /* interpolate strong points with the help of hinted coordinates */
  static void
  psh_glyph_interpolate_strong_points( PSH_Glyph  glyph,
                                       FT_Int     dimension )
  {}


#define PSH_MAX_STRONG_INTERNAL

  static void
  psh_glyph_interpolate_normal_points( PSH_Glyph  glyph,
                                       FT_Int     dimension )
  {}


  /* interpolate other points */
  static void
  psh_glyph_interpolate_other_points( PSH_Glyph  glyph,
                                      FT_Int     dimension )
  {}


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                     HIGH-LEVEL INTERFACE                      *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  FT_Error
  ps_hints_apply( PS_Hints        ps_hints,
                  FT_Outline*     outline,
                  PSH_Globals     globals,
                  FT_Render_Mode  hint_mode )
  {}


/* END */