(root)/
freetype-2.13.2/
src/
sdf/
ftsdfcommon.c
       1  /****************************************************************************
       2   *
       3   * ftsdfcommon.c
       4   *
       5   *   Auxiliary data for Signed Distance Field support (body).
       6   *
       7   * Copyright (C) 2020-2023 by
       8   * David Turner, Robert Wilhelm, and Werner Lemberg.
       9   *
      10   * Written by Anuj Verma.
      11   *
      12   * This file is part of the FreeType project, and may only be used,
      13   * modified, and distributed under the terms of the FreeType project
      14   * license, LICENSE.TXT.  By continuing to use, modify, or distribute
      15   * this file you indicate that you have read the license and
      16   * understand and accept it fully.
      17   *
      18   */
      19  
      20  
      21  #include "ftsdf.h"
      22  #include "ftsdfcommon.h"
      23  
      24  
      25    /**************************************************************************
      26     *
      27     * common functions
      28     *
      29     */
      30  
      31    /*
      32     * Original algorithm:
      33     *
      34     *   https://github.com/chmike/fpsqrt
      35     *
      36     * Use this to compute the square root of a 16.16 fixed-point number.
      37     */
      38    FT_LOCAL_DEF( FT_16D16 )
      39    square_root( FT_16D16  val )
      40    {
      41      FT_ULong  t, q, b, r;
      42  
      43  
      44      r = (FT_ULong)val;
      45      b = 0x40000000L;
      46      q = 0;
      47  
      48      while ( b > 0x40L )
      49      {
      50        t = q + b;
      51  
      52        if ( r >= t )
      53        {
      54          r -= t;
      55          q  = t + b;
      56        }
      57  
      58        r <<= 1;
      59        b >>= 1;
      60      }
      61  
      62      q >>= 8;
      63  
      64      return (FT_16D16)q;
      65    }
      66  
      67  
      68    /**************************************************************************
      69     *
      70     * format and sign manipulating functions
      71     *
      72     */
      73  
      74    /*
      75     * Convert 16.16 fixed-point values to the desired output format.
      76     * In this case we reduce 16.16 fixed-point values to normalized
      77     * 8-bit values.
      78     *
      79     * The `max_value` in the parameter is the maximum value in the
      80     * distance field map and is equal to the spread.  We normalize
      81     * the distances using this value instead of computing the maximum
      82     * value for the entire bitmap.
      83     *
      84     * You can use this function to map the 16.16 signed values to any
      85     * format required.  Do note that the output buffer is 8-bit, so only
      86     * use an 8-bit format for `FT_SDFFormat`, or increase the buffer size in
      87     * `ftsdfrend.c`.
      88     */
      89    FT_LOCAL_DEF( FT_SDFFormat )
      90    map_fixed_to_sdf( FT_16D16  dist,
      91                      FT_16D16  max_value )
      92    {
      93      FT_SDFFormat  out;
      94      FT_16D16      udist;
      95  
      96  
      97      /* normalize the distance values */
      98      dist = FT_DivFix( dist, max_value );
      99  
     100      udist = dist < 0 ? -dist : dist;
     101  
     102      /* Reduce the distance values to 8 bits.                   */
     103      /*                                                         */
     104      /* Since +1/-1 in 16.16 takes the 16th bit, we right-shift */
     105      /* the number by 9 to make it fit into the 7-bit range.    */
     106      /*                                                         */
     107      /* One bit is reserved for the sign.                       */
     108      udist >>= 9;
     109  
     110      /* Since `char` can only store a maximum positive value    */
     111      /* of 127 we need to make sure it does not wrap around and */
     112      /* give a negative value.                                  */
     113      if ( dist > 0 && udist > 127 )
     114        udist = 127;
     115      if ( dist < 0 && udist > 128 )
     116        udist = 128;
     117  
     118      /* Output the data; negative values are from [0, 127] and positive    */
     119      /* from [128, 255].  One important thing is that negative values      */
     120      /* are inverted here, that means [0, 128] maps to [-128, 0] linearly. */
     121      /* More on that in `freetype.h` near the documentation of             */
     122      /* `FT_RENDER_MODE_SDF`.                                              */
     123      out = dist < 0 ? 128 - (FT_SDFFormat)udist
     124                     : (FT_SDFFormat)udist + 128;
     125  
     126      return out;
     127    }
     128  
     129  
     130    /*
     131     * Invert the signed distance packed into the corresponding format.
     132     * So if the values are negative they will become positive in the
     133     * chosen format.
     134     *
     135     * [Note]: This function should only be used after converting the
     136     *         16.16 signed distance values to `FT_SDFFormat`.  If that
     137     *         conversion has not been done, then simply invert the sign
     138     *         and use the above function to pack the values.
     139     */
     140    FT_LOCAL_DEF( FT_SDFFormat )
     141    invert_sign( FT_SDFFormat  dist )
     142    {
     143      return 255 - dist;
     144    }
     145  
     146  
     147  /* END */