freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Git][freetype/freetype][download-test-fonts] 5 commits: Update 'dlg' su


From: David Turner (@david.freetype)
Subject: [Git][freetype/freetype][download-test-fonts] 5 commits: Update 'dlg' subproject.
Date: Mon, 12 Jul 2021 07:34:48 +0000

David Turner pushed to branch download-test-fonts at FreeType / FreeType

Commits:

28 changed files:

Changes:

  • ChangeLog
    1
    +2021-07-12  David Turner  <david@freetype.org>
    
    2
    +
    
    3
    +	Replaces download-test-fonts.sh with download-test-fonts.py which
    
    4
    +	does the same work, and also avoids downloading anything if the
    
    5
    +	files are already installed with the right content.
    
    6
    +
    
    7
    +	Now uses the first 8 byte of each file's sha256 hash for the digest.
    
    8
    +
    
    9
    +	* tests/scripts/download-test-fonts.sh: Removed
    
    10
    +	* tests/scripts/download-test-fonts.py: New script
    
    11
    +	* tests/README.md: Updated
    
    12
    +
    
    13
    +2021-07-12  David Turner  <david@freetype.org>
    
    14
    +
    
    15
    +	Remove obsolete AF_Angle type and related sources.
    
    16
    +
    
    17
    +	Move the af_sort_xxx() functions from afangles.c to afhints.c in
    
    18
    +	order to get rid of the obsolete angle-related types, macros and
    
    19
    +	function definitions.
    
    20
    +
    
    21
    +	* src/autofit/*: Remove code.
    
    22
    +
    
    23
    +2021-07-12  David Turner  <david@freetype.org>
    
    24
    +
    
    25
    +	Remove experimental auto-hinting 'warp' mode.
    
    26
    +
    
    27
    +	This feature was always experimental, and probably nevery worked
    
    28
    +	properly. This patch completely removes it from the source code,
    
    29
    +	except for a documentation block describing it for historical
    
    30
    +	purpose.
    
    31
    +
    
    32
    +	* devel/ftoption.h: Remove AF_CONFIG_OPTION_USE_WARPER.
    
    33
    +	* include/freetype/config/ftoption.h: Remove AF_CONFIG_OPTION_USE_WARPER.
    
    34
    +	* include/freetype/ftdriver.h: Document 'warping' property as obsolete.
    
    35
    +	* src/autofit/*: Remove any warp mode related code.
    
    36
    +
    
    37
    +2021-07-12  David Turner  <david@freetype.org>
    
    38
    +
    
    39
    +	Remove experimental "Latin2" writing system (FT_OPTION_AUTOFIT2)
    
    40
    +
    
    41
    +	This code has always been experimental and was never compiled anyway
    
    42
    +	(FT_OPTION_AUTOFIT2 does not appear in ftoption.h or even any of our
    
    43
    +	build files).
    
    44
    +
    
    45
    +	* include/freetype/internal/fttrace.h: Remove 'FT_TRACE_DEF( aflatin2 )'.
    
    46
    +	* src/autofit/aflatin2.[hc]: Removed.
    
    47
    +	* src/autofit/afloader.c: Remove undocumented hook to activate Latin2 system.
    
    48
    +	* src/autofit/afstyles.h: Remove ltn2_dflt style definition.
    
    49
    +	* src/autofit/afwrtsys.h: Remove LATIN2 writing system definition.
    
    50
    +	* src/autofit/autofit.c: Updated.
    
    51
    +
    
    1 52
     2021-07-05  Werner Lemberg  <wl@gnu.org>
    
    2 53
     
    
    3 54
     	* src/base/ftlcdfil.c (FT_Library_SetLcdGeometry): Fix argument.
    

  • devel/ftoption.h
    ... ... @@ -907,24 +907,6 @@ FT_BEGIN_HEADER
    907 907
     #endif
    
    908 908
     
    
    909 909
     
    
    910
    -  /**************************************************************************
    
    911
    -   *
    
    912
    -   * Compile 'autofit' module with warp hinting.  The idea of the warping
    
    913
    -   * code is to slightly scale and shift a glyph within a single dimension so
    
    914
    -   * that as much of its segments are aligned (more or less) on the grid.  To
    
    915
    -   * find out the optimal scaling and shifting value, various parameter
    
    916
    -   * combinations are tried and scored.
    
    917
    -   *
    
    918
    -   * You can switch warping on and off with the `warping` property of the
    
    919
    -   * auto-hinter (see file `ftdriver.h` for more information; by default it
    
    920
    -   * is switched off).
    
    921
    -   *
    
    922
    -   * This experimental option is not active if the rendering mode is
    
    923
    -   * `FT_RENDER_MODE_LIGHT`.
    
    924
    -   */
    
    925
    -#define AF_CONFIG_OPTION_USE_WARPER
    
    926
    -
    
    927
    -
    
    928 910
       /**************************************************************************
    
    929 911
        *
    
    930 912
        * Use TrueType-like size metrics for 'light' auto-hinting.
    

  • include/freetype/config/ftoption.h
    ... ... @@ -909,24 +909,6 @@ FT_BEGIN_HEADER
    909 909
     #endif
    
    910 910
     
    
    911 911
     
    
    912
    -  /**************************************************************************
    
    913
    -   *
    
    914
    -   * Compile 'autofit' module with warp hinting.  The idea of the warping
    
    915
    -   * code is to slightly scale and shift a glyph within a single dimension so
    
    916
    -   * that as much of its segments are aligned (more or less) on the grid.  To
    
    917
    -   * find out the optimal scaling and shifting value, various parameter
    
    918
    -   * combinations are tried and scored.
    
    919
    -   *
    
    920
    -   * You can switch warping on and off with the `warping` property of the
    
    921
    -   * auto-hinter (see file `ftdriver.h` for more information; by default it
    
    922
    -   * is switched off).
    
    923
    -   *
    
    924
    -   * This experimental option is not active if the rendering mode is
    
    925
    -   * `FT_RENDER_MODE_LIGHT`.
    
    926
    -   */
    
    927
    -#define AF_CONFIG_OPTION_USE_WARPER
    
    928
    -
    
    929
    -
    
    930 912
       /**************************************************************************
    
    931 913
        *
    
    932 914
        * Use TrueType-like size metrics for 'light' auto-hinting.
    

  • include/freetype/ftdriver.h
    ... ... @@ -1162,11 +1162,11 @@ FT_BEGIN_HEADER
    1162 1162
        *   warping
    
    1163 1163
        *
    
    1164 1164
        * @description:
    
    1165
    -   *   **Experimental only**
    
    1165
    +   *   **Obsolete**
    
    1166 1166
        *
    
    1167
    -   *   If FreeType gets compiled with option `AF_CONFIG_OPTION_USE_WARPER` to
    
    1168
    -   *   activate the warp hinting code in the auto-hinter, this property
    
    1169
    -   *   switches warping on and off.
    
    1167
    +   *   This property was always experimental and probably never worked
    
    1168
    +   *   correctly. It was entirely removed from the FreeType 2 sources.
    
    1169
    +   *   This entry is only here for historical reference.
    
    1170 1170
        *
    
    1171 1171
        *   Warping only works in 'normal' auto-hinting mode replacing it.  The
    
    1172 1172
        *   idea of the code is to slightly scale and shift a glyph along the
    
    ... ... @@ -1175,36 +1175,6 @@ FT_BEGIN_HEADER
    1175 1175
        *   out a glyph's optimal scaling and shifting value, various parameter
    
    1176 1176
        *   combinations are tried and scored.
    
    1177 1177
        *
    
    1178
    -   *   By default, warping is off.
    
    1179
    -   *
    
    1180
    -   * @note:
    
    1181
    -   *   This property can be used with @FT_Property_Get also.
    
    1182
    -   *
    
    1183
    -   *   This property can be set via the `FREETYPE_PROPERTIES` environment
    
    1184
    -   *   variable (using values 1 and 0 for 'on' and 'off', respectively).
    
    1185
    -   *
    
    1186
    -   *   The warping code can also change advance widths.  Have a look at the
    
    1187
    -   *   `lsb_delta` and `rsb_delta` fields in the @FT_GlyphSlotRec structure
    
    1188
    -   *   for details on improving inter-glyph distances while rendering.
    
    1189
    -   *
    
    1190
    -   *   Since warping is a global property of the auto-hinter it is best to
    
    1191
    -   *   change its value before rendering any face.  Otherwise, you should
    
    1192
    -   *   reload all faces that get auto-hinted in 'normal' hinting mode.
    
    1193
    -   *
    
    1194
    -   * @example:
    
    1195
    -   *   This example shows how to switch on warping (omitting the error
    
    1196
    -   *   handling).
    
    1197
    -   *
    
    1198
    -   *   ```
    
    1199
    -   *     FT_Library  library;
    
    1200
    -   *     FT_Bool     warping = 1;
    
    1201
    -   *
    
    1202
    -   *
    
    1203
    -   *     FT_Init_FreeType( &library );
    
    1204
    -   *
    
    1205
    -   *     FT_Property_Set( library, "autofitter", "warping", &warping );
    
    1206
    -   *   ```
    
    1207
    -   *
    
    1208 1178
        * @since:
    
    1209 1179
        *   2.6
    
    1210 1180
        *
    

  • include/freetype/internal/fttrace.h
    ... ... @@ -159,7 +159,6 @@ FT_TRACE_DEF( afglobal )
    159 159
     FT_TRACE_DEF( afhints )
    
    160 160
     FT_TRACE_DEF( afmodule )
    
    161 161
     FT_TRACE_DEF( aflatin )
    
    162
    -FT_TRACE_DEF( aflatin2 )
    
    163 162
     FT_TRACE_DEF( afshaper )
    
    164 163
     FT_TRACE_DEF( afwarp )
    
    165 164
     
    

  • src/autofit/afangles.c deleted
    1
    -/****************************************************************************
    
    2
    - *
    
    3
    - * afangles.c
    
    4
    - *
    
    5
    - *   Routines used to compute vector angles with limited accuracy
    
    6
    - *   and very high speed.  It also contains sorting routines (body).
    
    7
    - *
    
    8
    - * Copyright (C) 2003-2021 by
    
    9
    - * David Turner, Robert Wilhelm, and Werner Lemberg.
    
    10
    - *
    
    11
    - * This file is part of the FreeType project, and may only be used,
    
    12
    - * modified, and distributed under the terms of the FreeType project
    
    13
    - * license, LICENSE.TXT.  By continuing to use, modify, or distribute
    
    14
    - * this file you indicate that you have read the license and
    
    15
    - * understand and accept it fully.
    
    16
    - *
    
    17
    - */
    
    18
    -
    
    19
    -
    
    20
    -#include "aftypes.h"
    
    21
    -
    
    22
    -
    
    23
    -  /*
    
    24
    -   * We are not using `af_angle_atan' anymore, but we keep the source
    
    25
    -   * code below just in case...
    
    26
    -   */
    
    27
    -
    
    28
    -
    
    29
    -#if 0
    
    30
    -
    
    31
    -
    
    32
    -  /*
    
    33
    -   * The trick here is to realize that we don't need a very accurate angle
    
    34
    -   * approximation.  We are going to use the result of `af_angle_atan' to
    
    35
    -   * only compare the sign of angle differences, or check whether its
    
    36
    -   * magnitude is very small.
    
    37
    -   *
    
    38
    -   * The approximation
    
    39
    -   *
    
    40
    -   *   dy * PI / (|dx|+|dy|)
    
    41
    -   *
    
    42
    -   * should be enough, and much faster to compute.
    
    43
    -   */
    
    44
    -  FT_LOCAL_DEF( AF_Angle )
    
    45
    -  af_angle_atan( FT_Fixed  dx,
    
    46
    -                 FT_Fixed  dy )
    
    47
    -  {
    
    48
    -    AF_Angle  angle;
    
    49
    -    FT_Fixed  ax = dx;
    
    50
    -    FT_Fixed  ay = dy;
    
    51
    -
    
    52
    -
    
    53
    -    if ( ax < 0 )
    
    54
    -      ax = -ax;
    
    55
    -    if ( ay < 0 )
    
    56
    -      ay = -ay;
    
    57
    -
    
    58
    -    ax += ay;
    
    59
    -
    
    60
    -    if ( ax == 0 )
    
    61
    -      angle = 0;
    
    62
    -    else
    
    63
    -    {
    
    64
    -      angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay );
    
    65
    -      if ( dx < 0 )
    
    66
    -      {
    
    67
    -        if ( angle >= 0 )
    
    68
    -          angle = AF_ANGLE_PI - angle;
    
    69
    -        else
    
    70
    -          angle = -AF_ANGLE_PI - angle;
    
    71
    -      }
    
    72
    -    }
    
    73
    -
    
    74
    -    return angle;
    
    75
    -  }
    
    76
    -
    
    77
    -
    
    78
    -#elif 0
    
    79
    -
    
    80
    -
    
    81
    -  /* the following table has been automatically generated with */
    
    82
    -  /* the `mather.py' Python script                             */
    
    83
    -
    
    84
    -#define AF_ATAN_BITS  8
    
    85
    -
    
    86
    -  static const FT_Byte  af_arctan[1L << AF_ATAN_BITS] =
    
    87
    -  {
    
    88
    -     0,  0,  1,  1,  1,  2,  2,  2,
    
    89
    -     3,  3,  3,  3,  4,  4,  4,  5,
    
    90
    -     5,  5,  6,  6,  6,  7,  7,  7,
    
    91
    -     8,  8,  8,  9,  9,  9, 10, 10,
    
    92
    -    10, 10, 11, 11, 11, 12, 12, 12,
    
    93
    -    13, 13, 13, 14, 14, 14, 14, 15,
    
    94
    -    15, 15, 16, 16, 16, 17, 17, 17,
    
    95
    -    18, 18, 18, 18, 19, 19, 19, 20,
    
    96
    -    20, 20, 21, 21, 21, 21, 22, 22,
    
    97
    -    22, 23, 23, 23, 24, 24, 24, 24,
    
    98
    -    25, 25, 25, 26, 26, 26, 26, 27,
    
    99
    -    27, 27, 28, 28, 28, 28, 29, 29,
    
    100
    -    29, 30, 30, 30, 30, 31, 31, 31,
    
    101
    -    31, 32, 32, 32, 33, 33, 33, 33,
    
    102
    -    34, 34, 34, 34, 35, 35, 35, 35,
    
    103
    -    36, 36, 36, 36, 37, 37, 37, 38,
    
    104
    -    38, 38, 38, 39, 39, 39, 39, 40,
    
    105
    -    40, 40, 40, 41, 41, 41, 41, 42,
    
    106
    -    42, 42, 42, 42, 43, 43, 43, 43,
    
    107
    -    44, 44, 44, 44, 45, 45, 45, 45,
    
    108
    -    46, 46, 46, 46, 46, 47, 47, 47,
    
    109
    -    47, 48, 48, 48, 48, 48, 49, 49,
    
    110
    -    49, 49, 50, 50, 50, 50, 50, 51,
    
    111
    -    51, 51, 51, 51, 52, 52, 52, 52,
    
    112
    -    52, 53, 53, 53, 53, 53, 54, 54,
    
    113
    -    54, 54, 54, 55, 55, 55, 55, 55,
    
    114
    -    56, 56, 56, 56, 56, 57, 57, 57,
    
    115
    -    57, 57, 57, 58, 58, 58, 58, 58,
    
    116
    -    59, 59, 59, 59, 59, 59, 60, 60,
    
    117
    -    60, 60, 60, 61, 61, 61, 61, 61,
    
    118
    -    61, 62, 62, 62, 62, 62, 62, 63,
    
    119
    -    63, 63, 63, 63, 63, 64, 64, 64
    
    120
    -  };
    
    121
    -
    
    122
    -
    
    123
    -  FT_LOCAL_DEF( AF_Angle )
    
    124
    -  af_angle_atan( FT_Fixed  dx,
    
    125
    -                 FT_Fixed  dy )
    
    126
    -  {
    
    127
    -    AF_Angle  angle;
    
    128
    -
    
    129
    -
    
    130
    -    /* check trivial cases */
    
    131
    -    if ( dy == 0 )
    
    132
    -    {
    
    133
    -      angle = 0;
    
    134
    -      if ( dx < 0 )
    
    135
    -        angle = AF_ANGLE_PI;
    
    136
    -      return angle;
    
    137
    -    }
    
    138
    -    else if ( dx == 0 )
    
    139
    -    {
    
    140
    -      angle = AF_ANGLE_PI2;
    
    141
    -      if ( dy < 0 )
    
    142
    -        angle = -AF_ANGLE_PI2;
    
    143
    -      return angle;
    
    144
    -    }
    
    145
    -
    
    146
    -    angle = 0;
    
    147
    -    if ( dx < 0 )
    
    148
    -    {
    
    149
    -      dx = -dx;
    
    150
    -      dy = -dy;
    
    151
    -      angle = AF_ANGLE_PI;
    
    152
    -    }
    
    153
    -
    
    154
    -    if ( dy < 0 )
    
    155
    -    {
    
    156
    -      FT_Pos  tmp;
    
    157
    -
    
    158
    -
    
    159
    -      tmp = dx;
    
    160
    -      dx  = -dy;
    
    161
    -      dy  = tmp;
    
    162
    -      angle -= AF_ANGLE_PI2;
    
    163
    -    }
    
    164
    -
    
    165
    -    if ( dx == 0 && dy == 0 )
    
    166
    -      return 0;
    
    167
    -
    
    168
    -    if ( dx == dy )
    
    169
    -      angle += AF_ANGLE_PI4;
    
    170
    -    else if ( dx > dy )
    
    171
    -      angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];
    
    172
    -    else
    
    173
    -      angle += AF_ANGLE_PI2 -
    
    174
    -               af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];
    
    175
    -
    
    176
    -    if ( angle > AF_ANGLE_PI )
    
    177
    -      angle -= AF_ANGLE_2PI;
    
    178
    -
    
    179
    -    return angle;
    
    180
    -  }
    
    181
    -
    
    182
    -
    
    183
    -#endif /* 0 */
    
    184
    -
    
    185
    -
    
    186
    -  FT_LOCAL_DEF( void )
    
    187
    -  af_sort_pos( FT_UInt  count,
    
    188
    -               FT_Pos*  table )
    
    189
    -  {
    
    190
    -    FT_UInt  i, j;
    
    191
    -    FT_Pos   swap;
    
    192
    -
    
    193
    -
    
    194
    -    for ( i = 1; i < count; i++ )
    
    195
    -    {
    
    196
    -      for ( j = i; j > 0; j-- )
    
    197
    -      {
    
    198
    -        if ( table[j] >= table[j - 1] )
    
    199
    -          break;
    
    200
    -
    
    201
    -        swap         = table[j];
    
    202
    -        table[j]     = table[j - 1];
    
    203
    -        table[j - 1] = swap;
    
    204
    -      }
    
    205
    -    }
    
    206
    -  }
    
    207
    -
    
    208
    -
    
    209
    -  FT_LOCAL_DEF( void )
    
    210
    -  af_sort_and_quantize_widths( FT_UInt*  count,
    
    211
    -                               AF_Width  table,
    
    212
    -                               FT_Pos    threshold )
    
    213
    -  {
    
    214
    -    FT_UInt      i, j;
    
    215
    -    FT_UInt      cur_idx;
    
    216
    -    FT_Pos       cur_val;
    
    217
    -    FT_Pos       sum;
    
    218
    -    AF_WidthRec  swap;
    
    219
    -
    
    220
    -
    
    221
    -    if ( *count == 1 )
    
    222
    -      return;
    
    223
    -
    
    224
    -    /* sort */
    
    225
    -    for ( i = 1; i < *count; i++ )
    
    226
    -    {
    
    227
    -      for ( j = i; j > 0; j-- )
    
    228
    -      {
    
    229
    -        if ( table[j].org >= table[j - 1].org )
    
    230
    -          break;
    
    231
    -
    
    232
    -        swap         = table[j];
    
    233
    -        table[j]     = table[j - 1];
    
    234
    -        table[j - 1] = swap;
    
    235
    -      }
    
    236
    -    }
    
    237
    -
    
    238
    -    cur_idx = 0;
    
    239
    -    cur_val = table[cur_idx].org;
    
    240
    -
    
    241
    -    /* compute and use mean values for clusters not larger than  */
    
    242
    -    /* `threshold'; this is very primitive and might not yield   */
    
    243
    -    /* the best result, but normally, using reference character  */
    
    244
    -    /* `o', `*count' is 2, so the code below is fully sufficient */
    
    245
    -    for ( i = 1; i < *count; i++ )
    
    246
    -    {
    
    247
    -      if ( table[i].org - cur_val > threshold ||
    
    248
    -           i == *count - 1                    )
    
    249
    -      {
    
    250
    -        sum = 0;
    
    251
    -
    
    252
    -        /* fix loop for end of array */
    
    253
    -        if ( table[i].org - cur_val <= threshold &&
    
    254
    -             i == *count - 1                     )
    
    255
    -          i++;
    
    256
    -
    
    257
    -        for ( j = cur_idx; j < i; j++ )
    
    258
    -        {
    
    259
    -          sum         += table[j].org;
    
    260
    -          table[j].org = 0;
    
    261
    -        }
    
    262
    -        table[cur_idx].org = sum / (FT_Pos)j;
    
    263
    -
    
    264
    -        if ( i < *count - 1 )
    
    265
    -        {
    
    266
    -          cur_idx = i + 1;
    
    267
    -          cur_val = table[cur_idx].org;
    
    268
    -        }
    
    269
    -      }
    
    270
    -    }
    
    271
    -
    
    272
    -    cur_idx = 1;
    
    273
    -
    
    274
    -    /* compress array to remove zero values */
    
    275
    -    for ( i = 1; i < *count; i++ )
    
    276
    -    {
    
    277
    -      if ( table[i].org )
    
    278
    -        table[cur_idx++] = table[i];
    
    279
    -    }
    
    280
    -
    
    281
    -    *count = cur_idx;
    
    282
    -  }
    
    283
    -
    
    284
    -
    
    285
    -/* END */

  • src/autofit/afangles.h deleted
    1
    -/*
    
    2
    - * afangles.h
    
    3
    - *
    
    4
    - * This is a dummy file, used to please the build system.  It is never
    
    5
    - * included by the auto-fitter sources.
    
    6
    - *
    
    7
    - */

  • src/autofit/afcjk.c
    ... ... @@ -37,11 +37,6 @@
    37 37
     #include "aferrors.h"
    
    38 38
     
    
    39 39
     
    
    40
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    41
    -#include "afwarp.h"
    
    42
    -#endif
    
    43
    -
    
    44
    -
    
    45 40
       /**************************************************************************
    
    46 41
        *
    
    47 42
        * The macro FT_COMPONENT is used in trace mode.  It is an implicit
    
    ... ... @@ -1400,11 +1395,6 @@
    1400 1395
         /* compute flags depending on render mode, etc. */
    
    1401 1396
         mode = metrics->root.scaler.render_mode;
    
    1402 1397
     
    
    1403
    -#if 0 /* AF_CONFIG_OPTION_USE_WARPER */
    
    1404
    -    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
    
    1405
    -      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
    
    1406
    -#endif
    
    1407
    -
    
    1408 1398
         scaler_flags = hints->scaler_flags;
    
    1409 1399
         other_flags  = 0;
    
    1410 1400
     
    
    ... ... @@ -1433,12 +1423,6 @@
    1433 1423
     
    
    1434 1424
         scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE;
    
    1435 1425
     
    
    1436
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    1437
    -    /* get (global) warper flag */
    
    1438
    -    if ( !metrics->root.globals->module->warping )
    
    1439
    -      scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
    
    1440
    -#endif
    
    1441
    -
    
    1442 1426
         hints->scaler_flags = scaler_flags;
    
    1443 1427
         hints->other_flags  = other_flags;
    
    1444 1428
     
    
    ... ... @@ -2321,25 +2305,6 @@
    2321 2305
           if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
    
    2322 2306
                ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
    
    2323 2307
           {
    
    2324
    -
    
    2325
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    2326
    -        if ( dim == AF_DIMENSION_HORZ                                  &&
    
    2327
    -             metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
    
    2328
    -             AF_HINTS_DO_WARP( hints )                                 )
    
    2329
    -        {
    
    2330
    -          AF_WarperRec  warper;
    
    2331
    -          FT_Fixed      scale;
    
    2332
    -          FT_Pos        delta;
    
    2333
    -
    
    2334
    -
    
    2335
    -          af_warper_compute( &warper, hints, (AF_Dimension)dim,
    
    2336
    -                             &scale, &delta );
    
    2337
    -          af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
    
    2338
    -                                    scale, delta );
    
    2339
    -          continue;
    
    2340
    -        }
    
    2341
    -#endif /* AF_CONFIG_OPTION_USE_WARPER */
    
    2342
    -
    
    2343 2308
             af_cjk_hint_edges( hints, (AF_Dimension)dim );
    
    2344 2309
             af_cjk_align_edge_points( hints, (AF_Dimension)dim );
    
    2345 2310
             af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
    

  • src/autofit/afhints.c
    ... ... @@ -32,6 +32,104 @@
    32 32
     #define FT_COMPONENT  afhints
    
    33 33
     
    
    34 34
     
    
    35
    +  FT_LOCAL_DEF( void )
    
    36
    +  af_sort_pos( FT_UInt  count,
    
    37
    +               FT_Pos*  table )
    
    38
    +  {
    
    39
    +    FT_UInt  i, j;
    
    40
    +    FT_Pos   swap;
    
    41
    +
    
    42
    +
    
    43
    +    for ( i = 1; i < count; i++ )
    
    44
    +    {
    
    45
    +      for ( j = i; j > 0; j-- )
    
    46
    +      {
    
    47
    +        if ( table[j] >= table[j - 1] )
    
    48
    +          break;
    
    49
    +
    
    50
    +        swap         = table[j];
    
    51
    +        table[j]     = table[j - 1];
    
    52
    +        table[j - 1] = swap;
    
    53
    +      }
    
    54
    +    }
    
    55
    +  }
    
    56
    +
    
    57
    +
    
    58
    +  FT_LOCAL_DEF( void )
    
    59
    +  af_sort_and_quantize_widths( FT_UInt*  count,
    
    60
    +                               AF_Width  table,
    
    61
    +                               FT_Pos    threshold )
    
    62
    +  {
    
    63
    +    FT_UInt      i, j;
    
    64
    +    FT_UInt      cur_idx;
    
    65
    +    FT_Pos       cur_val;
    
    66
    +    FT_Pos       sum;
    
    67
    +    AF_WidthRec  swap;
    
    68
    +
    
    69
    +
    
    70
    +    if ( *count == 1 )
    
    71
    +      return;
    
    72
    +
    
    73
    +    /* sort */
    
    74
    +    for ( i = 1; i < *count; i++ )
    
    75
    +    {
    
    76
    +      for ( j = i; j > 0; j-- )
    
    77
    +      {
    
    78
    +        if ( table[j].org >= table[j - 1].org )
    
    79
    +          break;
    
    80
    +
    
    81
    +        swap         = table[j];
    
    82
    +        table[j]     = table[j - 1];
    
    83
    +        table[j - 1] = swap;
    
    84
    +      }
    
    85
    +    }
    
    86
    +
    
    87
    +    cur_idx = 0;
    
    88
    +    cur_val = table[cur_idx].org;
    
    89
    +
    
    90
    +    /* compute and use mean values for clusters not larger than  */
    
    91
    +    /* `threshold'; this is very primitive and might not yield   */
    
    92
    +    /* the best result, but normally, using reference character  */
    
    93
    +    /* `o', `*count' is 2, so the code below is fully sufficient */
    
    94
    +    for ( i = 1; i < *count; i++ )
    
    95
    +    {
    
    96
    +      if ( table[i].org - cur_val > threshold ||
    
    97
    +           i == *count - 1                    )
    
    98
    +      {
    
    99
    +        sum = 0;
    
    100
    +
    
    101
    +        /* fix loop for end of array */
    
    102
    +        if ( table[i].org - cur_val <= threshold &&
    
    103
    +             i == *count - 1                     )
    
    104
    +          i++;
    
    105
    +
    
    106
    +        for ( j = cur_idx; j < i; j++ )
    
    107
    +        {
    
    108
    +          sum         += table[j].org;
    
    109
    +          table[j].org = 0;
    
    110
    +        }
    
    111
    +        table[cur_idx].org = sum / (FT_Pos)j;
    
    112
    +
    
    113
    +        if ( i < *count - 1 )
    
    114
    +        {
    
    115
    +          cur_idx = i + 1;
    
    116
    +          cur_val = table[cur_idx].org;
    
    117
    +        }
    
    118
    +      }
    
    119
    +    }
    
    120
    +
    
    121
    +    cur_idx = 1;
    
    122
    +
    
    123
    +    /* compress array to remove zero values */
    
    124
    +    for ( i = 1; i < *count; i++ )
    
    125
    +    {
    
    126
    +      if ( table[i].org )
    
    127
    +        table[cur_idx++] = table[i];
    
    128
    +    }
    
    129
    +
    
    130
    +    *count = cur_idx;
    
    131
    +  }
    
    132
    +
    
    35 133
       /* Get new segment for given axis. */
    
    36 134
     
    
    37 135
       FT_LOCAL_DEF( FT_Error )
    
    ... ... @@ -1688,33 +1786,4 @@
    1688 1786
       }
    
    1689 1787
     
    
    1690 1788
     
    
    1691
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    1692
    -
    
    1693
    -  /* Apply (small) warp scale and warp delta for given dimension. */
    
    1694
    -
    
    1695
    -  FT_LOCAL_DEF( void )
    
    1696
    -  af_glyph_hints_scale_dim( AF_GlyphHints  hints,
    
    1697
    -                            AF_Dimension   dim,
    
    1698
    -                            FT_Fixed       scale,
    
    1699
    -                            FT_Pos         delta )
    
    1700
    -  {
    
    1701
    -    AF_Point  points       = hints->points;
    
    1702
    -    AF_Point  points_limit = points + hints->num_points;
    
    1703
    -    AF_Point  point;
    
    1704
    -
    
    1705
    -
    
    1706
    -    if ( dim == AF_DIMENSION_HORZ )
    
    1707
    -    {
    
    1708
    -      for ( point = points; point < points_limit; point++ )
    
    1709
    -        point->x = FT_MulFix( point->fx, scale ) + delta;
    
    1710
    -    }
    
    1711
    -    else
    
    1712
    -    {
    
    1713
    -      for ( point = points; point < points_limit; point++ )
    
    1714
    -        point->y = FT_MulFix( point->fy, scale ) + delta;
    
    1715
    -    }
    
    1716
    -  }
    
    1717
    -
    
    1718
    -#endif /* AF_CONFIG_OPTION_USE_WARPER */
    
    1719
    -
    
    1720 1789
     /* END */

  • src/autofit/afhints.h
    ... ... @@ -408,10 +408,6 @@ FT_BEGIN_HEADER
    408 408
     #define AF_HINTS_DO_ADVANCE( h )                                \
    
    409 409
               !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
    
    410 410
     
    
    411
    -#define AF_HINTS_DO_WARP( h )                                  \
    
    412
    -          !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_WARPER )
    
    413
    -
    
    414
    -
    
    415 411
     
    
    416 412
       FT_LOCAL( AF_Direction )
    
    417 413
       af_direction_compute( FT_Pos  dx,
    
    ... ... @@ -459,14 +455,6 @@ FT_BEGIN_HEADER
    459 455
       af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
    
    460 456
                                         AF_Dimension   dim );
    
    461 457
     
    
    462
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    463
    -  FT_LOCAL( void )
    
    464
    -  af_glyph_hints_scale_dim( AF_GlyphHints  hints,
    
    465
    -                            AF_Dimension   dim,
    
    466
    -                            FT_Fixed       scale,
    
    467
    -                            FT_Pos         delta );
    
    468
    -#endif
    
    469
    -
    
    470 458
       FT_LOCAL( void )
    
    471 459
       af_glyph_hints_done( AF_GlyphHints  hints );
    
    472 460
     
    

  • src/autofit/afindic.c
    ... ... @@ -27,11 +27,6 @@
    27 27
     #include "aferrors.h"
    
    28 28
     
    
    29 29
     
    
    30
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    31
    -#include "afwarp.h"
    
    32
    -#endif
    
    33
    -
    
    34
    -
    
    35 30
       static FT_Error
    
    36 31
       af_indic_metrics_init( AF_CJKMetrics  metrics,
    
    37 32
                              FT_Face        face )
    

  • src/autofit/aflatin.c
    ... ... @@ -24,11 +24,6 @@
    24 24
     #include "aferrors.h"
    
    25 25
     
    
    26 26
     
    
    27
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    28
    -#include "afwarp.h"
    
    29
    -#endif
    
    30
    -
    
    31
    -
    
    32 27
       /**************************************************************************
    
    33 28
        *
    
    34 29
        * The macro FT_COMPONENT is used in trace mode.  It is an implicit
    
    ... ... @@ -2636,11 +2631,6 @@
    2636 2631
         /* compute flags depending on render mode, etc. */
    
    2637 2632
         mode = metrics->root.scaler.render_mode;
    
    2638 2633
     
    
    2639
    -#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
    
    2640
    -    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
    
    2641
    -      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
    
    2642
    -#endif
    
    2643
    -
    
    2644 2634
         scaler_flags = hints->scaler_flags;
    
    2645 2635
         other_flags  = 0;
    
    2646 2636
     
    
    ... ... @@ -2678,12 +2668,6 @@
    2678 2668
              ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0          )
    
    2679 2669
           scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
    
    2680 2670
     
    
    2681
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    2682
    -    /* get (global) warper flag */
    
    2683
    -    if ( !metrics->root.globals->module->warping )
    
    2684
    -      scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
    
    2685
    -#endif
    
    2686
    -
    
    2687 2671
         hints->scaler_flags = scaler_flags;
    
    2688 2672
         hints->other_flags  = other_flags;
    
    2689 2673
     
    
    ... ... @@ -3600,24 +3584,6 @@
    3600 3584
         /* grid-fit the outline */
    
    3601 3585
         for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
    
    3602 3586
         {
    
    3603
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    3604
    -      if ( dim == AF_DIMENSION_HORZ                                  &&
    
    3605
    -           metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
    
    3606
    -           AF_HINTS_DO_WARP( hints )                                 )
    
    3607
    -      {
    
    3608
    -        AF_WarperRec  warper;
    
    3609
    -        FT_Fixed      scale;
    
    3610
    -        FT_Pos        delta;
    
    3611
    -
    
    3612
    -
    
    3613
    -        af_warper_compute( &warper, hints, (AF_Dimension)dim,
    
    3614
    -                           &scale, &delta );
    
    3615
    -        af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
    
    3616
    -                                  scale, delta );
    
    3617
    -        continue;
    
    3618
    -      }
    
    3619
    -#endif /* AF_CONFIG_OPTION_USE_WARPER */
    
    3620
    -
    
    3621 3587
           if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
    
    3622 3588
                ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
    
    3623 3589
           {
    

  • src/autofit/aflatin2.c deleted
    1
    -/* ATTENTION: This file doesn't compile.  It is only here as a reference */
    
    2
    -/*            of an alternative latin hinting algorithm that was always  */
    
    3
    -/*            marked as experimental.                                    */
    
    4
    -
    
    5
    -
    
    6
    -/****************************************************************************
    
    7
    - *
    
    8
    - * aflatin2.c
    
    9
    - *
    
    10
    - *   Auto-fitter hinting routines for latin writing system (body).
    
    11
    - *
    
    12
    - * Copyright (C) 2003-2021 by
    
    13
    - * David Turner, Robert Wilhelm, and Werner Lemberg.
    
    14
    - *
    
    15
    - * This file is part of the FreeType project, and may only be used,
    
    16
    - * modified, and distributed under the terms of the FreeType project
    
    17
    - * license, LICENSE.TXT.  By continuing to use, modify, or distribute
    
    18
    - * this file you indicate that you have read the license and
    
    19
    - * understand and accept it fully.
    
    20
    - *
    
    21
    - */
    
    22
    -
    
    23
    -
    
    24
    -#include <freetype/ftadvanc.h>
    
    25
    -
    
    26
    -
    
    27
    -#ifdef FT_OPTION_AUTOFIT2
    
    28
    -
    
    29
    -#include "afglobal.h"
    
    30
    -#include "aflatin.h"
    
    31
    -#include "aflatin2.h"
    
    32
    -#include "aferrors.h"
    
    33
    -
    
    34
    -
    
    35
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    36
    -#include "afwarp.h"
    
    37
    -#endif
    
    38
    -
    
    39
    -
    
    40
    -  /**************************************************************************
    
    41
    -   *
    
    42
    -   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
    
    43
    -   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
    
    44
    -   * messages during execution.
    
    45
    -   */
    
    46
    -#undef  FT_COMPONENT
    
    47
    -#define FT_COMPONENT  aflatin2
    
    48
    -
    
    49
    -
    
    50
    -  FT_LOCAL_DEF( FT_Error )
    
    51
    -  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
    
    52
    -                                    AF_Dimension   dim );
    
    53
    -
    
    54
    -  FT_LOCAL_DEF( void )
    
    55
    -  af_latin2_hints_link_segments( AF_GlyphHints  hints,
    
    56
    -                                 AF_Dimension   dim );
    
    57
    -
    
    58
    -  /*************************************************************************/
    
    59
    -  /*************************************************************************/
    
    60
    -  /*****                                                               *****/
    
    61
    -  /*****            L A T I N   G L O B A L   M E T R I C S            *****/
    
    62
    -  /*****                                                               *****/
    
    63
    -  /*************************************************************************/
    
    64
    -  /*************************************************************************/
    
    65
    -
    
    66
    -  FT_LOCAL_DEF( void )
    
    67
    -  af_latin2_metrics_init_widths( AF_LatinMetrics  metrics,
    
    68
    -                                 FT_Face          face )
    
    69
    -  {
    
    70
    -    /* scan the array of segments in each direction */
    
    71
    -    AF_GlyphHintsRec  hints[1];
    
    72
    -
    
    73
    -
    
    74
    -    af_glyph_hints_init( hints, face->memory );
    
    75
    -
    
    76
    -    metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
    
    77
    -    metrics->axis[AF_DIMENSION_VERT].width_count = 0;
    
    78
    -
    
    79
    -    {
    
    80
    -      FT_Error             error;
    
    81
    -      FT_UInt              glyph_index;
    
    82
    -      int                  dim;
    
    83
    -      AF_LatinMetricsRec   dummy[1];
    
    84
    -      AF_Scaler            scaler = &dummy->root.scaler;
    
    85
    -
    
    86
    -
    
    87
    -      glyph_index = FT_Get_Char_Index(
    
    88
    -                      face,
    
    89
    -                      metrics->root.style_class->standard_char );
    
    90
    -      if ( glyph_index == 0 )
    
    91
    -        goto Exit;
    
    92
    -
    
    93
    -      error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
    
    94
    -      if ( error || face->glyph->outline.n_points <= 0 )
    
    95
    -        goto Exit;
    
    96
    -
    
    97
    -      FT_ZERO( dummy );
    
    98
    -
    
    99
    -      dummy->units_per_em = metrics->units_per_em;
    
    100
    -      scaler->x_scale     = scaler->y_scale = 0x10000L;
    
    101
    -      scaler->x_delta     = scaler->y_delta = 0;
    
    102
    -      scaler->face        = face;
    
    103
    -      scaler->render_mode = FT_RENDER_MODE_NORMAL;
    
    104
    -      scaler->flags       = 0;
    
    105
    -
    
    106
    -      af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy );
    
    107
    -
    
    108
    -      error = af_glyph_hints_reload( hints, &face->glyph->outline );
    
    109
    -      if ( error )
    
    110
    -        goto Exit;
    
    111
    -
    
    112
    -      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
    
    113
    -      {
    
    114
    -        AF_LatinAxis  axis    = &metrics->axis[dim];
    
    115
    -        AF_AxisHints  axhints = &hints->axis[dim];
    
    116
    -        AF_Segment    seg, limit, link;
    
    117
    -        FT_UInt       num_widths = 0;
    
    118
    -
    
    119
    -
    
    120
    -        error = af_latin2_hints_compute_segments( hints,
    
    121
    -                                                 (AF_Dimension)dim );
    
    122
    -        if ( error )
    
    123
    -          goto Exit;
    
    124
    -
    
    125
    -        af_latin2_hints_link_segments( hints,
    
    126
    -                                      (AF_Dimension)dim );
    
    127
    -
    
    128
    -        seg   = axhints->segments;
    
    129
    -        limit = seg + axhints->num_segments;
    
    130
    -
    
    131
    -        for ( ; seg < limit; seg++ )
    
    132
    -        {
    
    133
    -          link = seg->link;
    
    134
    -
    
    135
    -          /* we only consider stem segments there! */
    
    136
    -          if ( link && link->link == seg && link > seg )
    
    137
    -          {
    
    138
    -            FT_Pos  dist;
    
    139
    -
    
    140
    -
    
    141
    -            dist = seg->pos - link->pos;
    
    142
    -            if ( dist < 0 )
    
    143
    -              dist = -dist;
    
    144
    -
    
    145
    -            if ( num_widths < AF_LATIN_MAX_WIDTHS )
    
    146
    -              axis->widths[num_widths++].org = dist;
    
    147
    -          }
    
    148
    -        }
    
    149
    -
    
    150
    -        af_sort_widths( num_widths, axis->widths );
    
    151
    -        axis->width_count = num_widths;
    
    152
    -      }
    
    153
    -
    
    154
    -  Exit:
    
    155
    -      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
    
    156
    -      {
    
    157
    -        AF_LatinAxis  axis = &metrics->axis[dim];
    
    158
    -        FT_Pos        stdw;
    
    159
    -
    
    160
    -
    
    161
    -        stdw = ( axis->width_count > 0 )
    
    162
    -                 ? axis->widths[0].org
    
    163
    -                 : AF_LATIN_CONSTANT( metrics, 50 );
    
    164
    -
    
    165
    -        /* let's try 20% of the smallest width */
    
    166
    -        axis->edge_distance_threshold = stdw / 5;
    
    167
    -        axis->standard_width          = stdw;
    
    168
    -        axis->extra_light             = 0;
    
    169
    -      }
    
    170
    -    }
    
    171
    -
    
    172
    -    af_glyph_hints_done( hints );
    
    173
    -  }
    
    174
    -
    
    175
    -
    
    176
    -
    
    177
    -#define AF_LATIN_MAX_TEST_CHARACTERS  12
    
    178
    -
    
    179
    -
    
    180
    -  static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES]
    
    181
    -                                        [AF_LATIN_MAX_TEST_CHARACTERS+1] =
    
    182
    -  {
    
    183
    -    "THEZOCQS",
    
    184
    -    "HEZLOCUS",
    
    185
    -    "fijkdbh",
    
    186
    -    "xzroesc",
    
    187
    -    "xzroesc",
    
    188
    -    "pqgjy"
    
    189
    -  };
    
    190
    -
    
    191
    -
    
    192
    -  static void
    
    193
    -  af_latin2_metrics_init_blues( AF_LatinMetrics  metrics,
    
    194
    -                                FT_Face          face )
    
    195
    -  {
    
    196
    -    FT_Pos        flats [AF_LATIN_MAX_TEST_CHARACTERS];
    
    197
    -    FT_Pos        rounds[AF_LATIN_MAX_TEST_CHARACTERS];
    
    198
    -    FT_Int        num_flats;
    
    199
    -    FT_Int        num_rounds;
    
    200
    -    FT_Int        bb;
    
    201
    -    AF_LatinBlue  blue;
    
    202
    -    FT_Error      error;
    
    203
    -    AF_LatinAxis  axis  = &metrics->axis[AF_DIMENSION_VERT];
    
    204
    -    FT_GlyphSlot  glyph = face->glyph;
    
    205
    -
    
    206
    -
    
    207
    -    /* we compute the blues simply by loading each character from the     */
    
    208
    -    /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
    
    209
    -    /* bottom-most points (depending on `AF_IS_TOP_BLUE')                 */
    
    210
    -
    
    211
    -    FT_TRACE5(( "blue zones computation\n" ));
    
    212
    -    FT_TRACE5(( "======================\n" ));
    
    213
    -    FT_TRACE5(( "\n" ));
    
    214
    -
    
    215
    -    for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
    
    216
    -    {
    
    217
    -      const char*  p     = af_latin2_blue_chars[bb];
    
    218
    -      const char*  limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
    
    219
    -      FT_Pos*      blue_ref;
    
    220
    -      FT_Pos*      blue_shoot;
    
    221
    -
    
    222
    -
    
    223
    -      FT_TRACE5(( "blue zone %d:\n", bb ));
    
    224
    -
    
    225
    -      num_flats  = 0;
    
    226
    -      num_rounds = 0;
    
    227
    -
    
    228
    -      for ( ; p < limit && *p; p++ )
    
    229
    -      {
    
    230
    -        FT_UInt     glyph_index;
    
    231
    -        FT_Int      best_point, best_y, best_first, best_last;
    
    232
    -        FT_Vector*  points;
    
    233
    -        FT_Bool     round;
    
    234
    -
    
    235
    -
    
    236
    -        /* load the character in the face -- skip unknown or empty ones */
    
    237
    -        glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
    
    238
    -        if ( glyph_index == 0 )
    
    239
    -          continue;
    
    240
    -
    
    241
    -        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
    
    242
    -        if ( error || glyph->outline.n_points <= 0 )
    
    243
    -          continue;
    
    244
    -
    
    245
    -        /* now compute min or max point indices and coordinates */
    
    246
    -        points      = glyph->outline.points;
    
    247
    -        best_point  = -1;
    
    248
    -        best_y      = 0;  /* make compiler happy */
    
    249
    -        best_first  = 0;  /* ditto */
    
    250
    -        best_last   = 0;  /* ditto */
    
    251
    -
    
    252
    -        {
    
    253
    -          FT_Int  nn;
    
    254
    -          FT_Int  first = 0;
    
    255
    -          FT_Int  last  = -1;
    
    256
    -
    
    257
    -
    
    258
    -          for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
    
    259
    -          {
    
    260
    -            FT_Int  old_best_point = best_point;
    
    261
    -            FT_Int  pp;
    
    262
    -
    
    263
    -
    
    264
    -            last = glyph->outline.contours[nn];
    
    265
    -
    
    266
    -            /* Avoid single-point contours since they are never rasterized. */
    
    267
    -            /* In some fonts, they correspond to mark attachment points     */
    
    268
    -            /* which are way outside of the glyph's real outline.           */
    
    269
    -            if ( last <= first )
    
    270
    -                continue;
    
    271
    -
    
    272
    -            if ( AF_LATIN_IS_TOP_BLUE( bb ) )
    
    273
    -            {
    
    274
    -              for ( pp = first; pp <= last; pp++ )
    
    275
    -                if ( best_point < 0 || points[pp].y > best_y )
    
    276
    -                {
    
    277
    -                  best_point = pp;
    
    278
    -                  best_y     = points[pp].y;
    
    279
    -                }
    
    280
    -            }
    
    281
    -            else
    
    282
    -            {
    
    283
    -              for ( pp = first; pp <= last; pp++ )
    
    284
    -                if ( best_point < 0 || points[pp].y < best_y )
    
    285
    -                {
    
    286
    -                  best_point = pp;
    
    287
    -                  best_y     = points[pp].y;
    
    288
    -                }
    
    289
    -            }
    
    290
    -
    
    291
    -            if ( best_point != old_best_point )
    
    292
    -            {
    
    293
    -              best_first = first;
    
    294
    -              best_last  = last;
    
    295
    -            }
    
    296
    -          }
    
    297
    -          FT_TRACE5(( "  %c  %d", *p, best_y ));
    
    298
    -        }
    
    299
    -
    
    300
    -        /* now check whether the point belongs to a straight or round   */
    
    301
    -        /* segment; we first need to find in which contour the extremum */
    
    302
    -        /* lies, then inspect its previous and next points              */
    
    303
    -        if ( best_point >= 0 )
    
    304
    -        {
    
    305
    -          FT_Pos  best_x = points[best_point].x;
    
    306
    -          FT_Int  start, end, prev, next;
    
    307
    -          FT_Pos  dist;
    
    308
    -
    
    309
    -
    
    310
    -          /* now look for the previous and next points that are not on the */
    
    311
    -          /* same Y coordinate.  Threshold the `closeness'...              */
    
    312
    -          start = end = best_point;
    
    313
    -
    
    314
    -          do
    
    315
    -          {
    
    316
    -            prev = start - 1;
    
    317
    -            if ( prev < best_first )
    
    318
    -              prev = best_last;
    
    319
    -
    
    320
    -            dist = FT_ABS( points[prev].y - best_y );
    
    321
    -            /* accept a small distance or a small angle (both values are */
    
    322
    -            /* heuristic; value 20 corresponds to approx. 2.9 degrees)   */
    
    323
    -            if ( dist > 5 )
    
    324
    -              if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
    
    325
    -                break;
    
    326
    -
    
    327
    -            start = prev;
    
    328
    -
    
    329
    -          } while ( start != best_point );
    
    330
    -
    
    331
    -          do
    
    332
    -          {
    
    333
    -            next = end + 1;
    
    334
    -            if ( next > best_last )
    
    335
    -              next = best_first;
    
    336
    -
    
    337
    -            dist = FT_ABS( points[next].y - best_y );
    
    338
    -            if ( dist > 5 )
    
    339
    -              if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
    
    340
    -                break;
    
    341
    -
    
    342
    -            end = next;
    
    343
    -
    
    344
    -          } while ( end != best_point );
    
    345
    -
    
    346
    -          /* now, set the `round' flag depending on the segment's kind */
    
    347
    -          round = FT_BOOL(
    
    348
    -            FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
    
    349
    -            FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
    
    350
    -
    
    351
    -          FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
    
    352
    -        }
    
    353
    -
    
    354
    -        if ( round )
    
    355
    -          rounds[num_rounds++] = best_y;
    
    356
    -        else
    
    357
    -          flats[num_flats++]   = best_y;
    
    358
    -      }
    
    359
    -
    
    360
    -      if ( num_flats == 0 && num_rounds == 0 )
    
    361
    -      {
    
    362
    -        /*
    
    363
    -         * we couldn't find a single glyph to compute this blue zone,
    
    364
    -         * we will simply ignore it then
    
    365
    -         */
    
    366
    -        FT_TRACE5(( "  empty\n" ));
    
    367
    -        continue;
    
    368
    -      }
    
    369
    -
    
    370
    -      /* we have computed the contents of the `rounds' and `flats' tables, */
    
    371
    -      /* now determine the reference and overshoot position of the blue -- */
    
    372
    -      /* we simply take the median value after a simple sort               */
    
    373
    -      af_sort_pos( num_rounds, rounds );
    
    374
    -      af_sort_pos( num_flats,  flats );
    
    375
    -
    
    376
    -      blue       = & axis->blues[axis->blue_count];
    
    377
    -      blue_ref   = & blue->ref.org;
    
    378
    -      blue_shoot = & blue->shoot.org;
    
    379
    -
    
    380
    -      axis->blue_count++;
    
    381
    -
    
    382
    -      if ( num_flats == 0 )
    
    383
    -      {
    
    384
    -        *blue_ref   =
    
    385
    -        *blue_shoot = rounds[num_rounds / 2];
    
    386
    -      }
    
    387
    -      else if ( num_rounds == 0 )
    
    388
    -      {
    
    389
    -        *blue_ref   =
    
    390
    -        *blue_shoot = flats[num_flats / 2];
    
    391
    -      }
    
    392
    -      else
    
    393
    -      {
    
    394
    -        *blue_ref   = flats[num_flats / 2];
    
    395
    -        *blue_shoot = rounds[num_rounds / 2];
    
    396
    -      }
    
    397
    -
    
    398
    -      /* there are sometimes problems: if the overshoot position of top     */
    
    399
    -      /* zones is under its reference position, or the opposite for bottom  */
    
    400
    -      /* zones.  We must thus check everything there and correct the errors */
    
    401
    -      if ( *blue_shoot != *blue_ref )
    
    402
    -      {
    
    403
    -        FT_Pos   ref      = *blue_ref;
    
    404
    -        FT_Pos   shoot    = *blue_shoot;
    
    405
    -        FT_Bool  over_ref = FT_BOOL( shoot > ref );
    
    406
    -
    
    407
    -
    
    408
    -        if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
    
    409
    -        {
    
    410
    -          *blue_ref   =
    
    411
    -          *blue_shoot = ( shoot + ref ) / 2;
    
    412
    -
    
    413
    -          FT_TRACE5(( "  [overshoot smaller than reference,"
    
    414
    -                      " taking mean value]\n" ));
    
    415
    -        }
    
    416
    -      }
    
    417
    -
    
    418
    -      blue->flags = 0;
    
    419
    -      if ( AF_LATIN_IS_TOP_BLUE( bb ) )
    
    420
    -        blue->flags |= AF_LATIN_BLUE_TOP;
    
    421
    -
    
    422
    -      /*
    
    423
    -       * The following flag is used later to adjust the y and x scales
    
    424
    -       * in order to optimize the pixel grid alignment of the top of small
    
    425
    -       * letters.
    
    426
    -       */
    
    427
    -      if ( AF_LATIN_IS_X_HEIGHT_BLUE( bb ) )
    
    428
    -        blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
    
    429
    -
    
    430
    -      FT_TRACE5(( "    -> reference = %ld\n", *blue_ref ));
    
    431
    -      FT_TRACE5(( "       overshoot = %ld\n", *blue_shoot ));
    
    432
    -    }
    
    433
    -
    
    434
    -    return;
    
    435
    -  }
    
    436
    -
    
    437
    -
    
    438
    -  FT_LOCAL_DEF( void )
    
    439
    -  af_latin2_metrics_check_digits( AF_LatinMetrics  metrics,
    
    440
    -                                  FT_Face          face )
    
    441
    -  {
    
    442
    -    FT_UInt   i;
    
    443
    -    FT_Bool   started = 0, same_width = 1;
    
    444
    -    FT_Fixed  advance, old_advance = 0;
    
    445
    -
    
    446
    -
    
    447
    -    /* check whether all ASCII digits have the same advance width; */
    
    448
    -    /* digit `0' is 0x30 in all supported charmaps                 */
    
    449
    -    for ( i = 0x30; i <= 0x39; i++ )
    
    450
    -    {
    
    451
    -      FT_UInt  glyph_index;
    
    452
    -
    
    453
    -
    
    454
    -      glyph_index = FT_Get_Char_Index( face, i );
    
    455
    -      if ( glyph_index == 0 )
    
    456
    -        continue;
    
    457
    -
    
    458
    -      if ( FT_Get_Advance( face, glyph_index,
    
    459
    -                           FT_LOAD_NO_SCALE         |
    
    460
    -                           FT_LOAD_NO_HINTING       |
    
    461
    -                           FT_LOAD_IGNORE_TRANSFORM,
    
    462
    -                           &advance ) )
    
    463
    -        continue;
    
    464
    -
    
    465
    -      if ( started )
    
    466
    -      {
    
    467
    -        if ( advance != old_advance )
    
    468
    -        {
    
    469
    -          same_width = 0;
    
    470
    -          break;
    
    471
    -        }
    
    472
    -      }
    
    473
    -      else
    
    474
    -      {
    
    475
    -        old_advance = advance;
    
    476
    -        started     = 1;
    
    477
    -      }
    
    478
    -    }
    
    479
    -
    
    480
    -    metrics->root.digits_have_same_width = same_width;
    
    481
    -  }
    
    482
    -
    
    483
    -
    
    484
    -  FT_LOCAL_DEF( FT_Error )
    
    485
    -  af_latin2_metrics_init( AF_LatinMetrics  metrics,
    
    486
    -                          FT_Face          face )
    
    487
    -  {
    
    488
    -    FT_Error    error  = FT_Err_Ok;
    
    489
    -    FT_CharMap  oldmap = face->charmap;
    
    490
    -    FT_UInt     ee;
    
    491
    -
    
    492
    -    static const FT_Encoding  latin_encodings[] =
    
    493
    -    {
    
    494
    -      FT_ENCODING_UNICODE,
    
    495
    -      FT_ENCODING_APPLE_ROMAN,
    
    496
    -      FT_ENCODING_ADOBE_STANDARD,
    
    497
    -      FT_ENCODING_ADOBE_LATIN_1,
    
    498
    -      FT_ENCODING_NONE  /* end of list */
    
    499
    -    };
    
    500
    -
    
    501
    -
    
    502
    -    metrics->units_per_em = face->units_per_EM;
    
    503
    -
    
    504
    -    /* do we have a latin charmap in there? */
    
    505
    -    for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
    
    506
    -    {
    
    507
    -      error = FT_Select_Charmap( face, latin_encodings[ee] );
    
    508
    -      if ( !error )
    
    509
    -        break;
    
    510
    -    }
    
    511
    -
    
    512
    -    if ( !error )
    
    513
    -    {
    
    514
    -      af_latin2_metrics_init_widths( metrics, face );
    
    515
    -      af_latin2_metrics_init_blues( metrics, face );
    
    516
    -      af_latin2_metrics_check_digits( metrics, face );
    
    517
    -    }
    
    518
    -
    
    519
    -    FT_Set_Charmap( face, oldmap );
    
    520
    -    return FT_Err_Ok;
    
    521
    -  }
    
    522
    -
    
    523
    -
    
    524
    -  static void
    
    525
    -  af_latin2_metrics_scale_dim( AF_LatinMetrics  metrics,
    
    526
    -                               AF_Scaler        scaler,
    
    527
    -                               AF_Dimension     dim )
    
    528
    -  {
    
    529
    -    FT_Fixed      scale;
    
    530
    -    FT_Pos        delta;
    
    531
    -    AF_LatinAxis  axis;
    
    532
    -    FT_UInt       nn;
    
    533
    -
    
    534
    -
    
    535
    -    if ( dim == AF_DIMENSION_HORZ )
    
    536
    -    {
    
    537
    -      scale = scaler->x_scale;
    
    538
    -      delta = scaler->x_delta;
    
    539
    -    }
    
    540
    -    else
    
    541
    -    {
    
    542
    -      scale = scaler->y_scale;
    
    543
    -      delta = scaler->y_delta;
    
    544
    -    }
    
    545
    -
    
    546
    -    axis = &metrics->axis[dim];
    
    547
    -
    
    548
    -    if ( axis->org_scale == scale && axis->org_delta == delta )
    
    549
    -      return;
    
    550
    -
    
    551
    -    axis->org_scale = scale;
    
    552
    -    axis->org_delta = delta;
    
    553
    -
    
    554
    -    /*
    
    555
    -     * correct Y scale to optimize the alignment of the top of small
    
    556
    -     * letters to the pixel grid
    
    557
    -     */
    
    558
    -    if ( dim == AF_DIMENSION_VERT )
    
    559
    -    {
    
    560
    -      AF_LatinAxis  vaxis = &metrics->axis[AF_DIMENSION_VERT];
    
    561
    -      AF_LatinBlue  blue = NULL;
    
    562
    -
    
    563
    -
    
    564
    -      for ( nn = 0; nn < vaxis->blue_count; nn++ )
    
    565
    -      {
    
    566
    -        if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
    
    567
    -        {
    
    568
    -          blue = &vaxis->blues[nn];
    
    569
    -          break;
    
    570
    -        }
    
    571
    -      }
    
    572
    -
    
    573
    -      if ( blue )
    
    574
    -      {
    
    575
    -        FT_Pos   scaled;
    
    576
    -        FT_Pos   threshold;
    
    577
    -        FT_Pos   fitted;
    
    578
    -        FT_UInt  limit;
    
    579
    -        FT_UInt  ppem;
    
    580
    -
    
    581
    -
    
    582
    -        scaled    = FT_MulFix( blue->shoot.org, scaler->y_scale );
    
    583
    -        ppem      = metrics->root.scaler.face->size->metrics.x_ppem;
    
    584
    -        limit     = metrics->root.globals->increase_x_height;
    
    585
    -        threshold = 40;
    
    586
    -
    
    587
    -        /* if the `increase-x-height' property is active, */
    
    588
    -        /* we round up much more often                    */
    
    589
    -        if ( limit                                 &&
    
    590
    -             ppem <= limit                         &&
    
    591
    -             ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN )
    
    592
    -          threshold = 52;
    
    593
    -
    
    594
    -        fitted = ( scaled + threshold ) & ~63;
    
    595
    -
    
    596
    -#if 1
    
    597
    -        if ( scaled != fitted )
    
    598
    -        {
    
    599
    -          scale = FT_MulDiv( scale, fitted, scaled );
    
    600
    -          FT_TRACE5(( "== scaled x-top = %.2g"
    
    601
    -                      "  fitted = %.2g, scaling = %.4g\n",
    
    602
    -                      scaled / 64.0, fitted / 64.0,
    
    603
    -                      ( fitted * 1.0 ) / scaled ));
    
    604
    -        }
    
    605
    -#endif
    
    606
    -      }
    
    607
    -    }
    
    608
    -
    
    609
    -    axis->scale = scale;
    
    610
    -    axis->delta = delta;
    
    611
    -
    
    612
    -    if ( dim == AF_DIMENSION_HORZ )
    
    613
    -    {
    
    614
    -      metrics->root.scaler.x_scale = scale;
    
    615
    -      metrics->root.scaler.x_delta = delta;
    
    616
    -    }
    
    617
    -    else
    
    618
    -    {
    
    619
    -      metrics->root.scaler.y_scale = scale;
    
    620
    -      metrics->root.scaler.y_delta = delta;
    
    621
    -    }
    
    622
    -
    
    623
    -    /* scale the standard widths */
    
    624
    -    for ( nn = 0; nn < axis->width_count; nn++ )
    
    625
    -    {
    
    626
    -      AF_Width  width = axis->widths + nn;
    
    627
    -
    
    628
    -
    
    629
    -      width->cur = FT_MulFix( width->org, scale );
    
    630
    -      width->fit = width->cur;
    
    631
    -    }
    
    632
    -
    
    633
    -    /* an extra-light axis corresponds to a standard width that is */
    
    634
    -    /* smaller than 5/8 pixels                                     */
    
    635
    -    axis->extra_light =
    
    636
    -      FT_BOOL( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
    
    637
    -
    
    638
    -    if ( dim == AF_DIMENSION_VERT )
    
    639
    -    {
    
    640
    -      /* scale the blue zones */
    
    641
    -      for ( nn = 0; nn < axis->blue_count; nn++ )
    
    642
    -      {
    
    643
    -        AF_LatinBlue  blue = &axis->blues[nn];
    
    644
    -        FT_Pos        dist;
    
    645
    -
    
    646
    -
    
    647
    -        blue->ref.cur   = FT_MulFix( blue->ref.org, scale ) + delta;
    
    648
    -        blue->ref.fit   = blue->ref.cur;
    
    649
    -        blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
    
    650
    -        blue->shoot.fit = blue->shoot.cur;
    
    651
    -        blue->flags    &= ~AF_LATIN_BLUE_ACTIVE;
    
    652
    -
    
    653
    -        /* a blue zone is only active if it is less than 3/4 pixels tall */
    
    654
    -        dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
    
    655
    -        if ( dist <= 48 && dist >= -48 )
    
    656
    -        {
    
    657
    -          FT_Pos  delta1, delta2;
    
    658
    -
    
    659
    -          delta1 = blue->shoot.org - blue->ref.org;
    
    660
    -          delta2 = delta1;
    
    661
    -          if ( delta1 < 0 )
    
    662
    -            delta2 = -delta2;
    
    663
    -
    
    664
    -          delta2 = FT_MulFix( delta2, scale );
    
    665
    -
    
    666
    -          if ( delta2 < 32 )
    
    667
    -            delta2 = 0;
    
    668
    -          else if ( delta2 < 64 )
    
    669
    -            delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
    
    670
    -          else
    
    671
    -            delta2 = FT_PIX_ROUND( delta2 );
    
    672
    -
    
    673
    -          if ( delta1 < 0 )
    
    674
    -            delta2 = -delta2;
    
    675
    -
    
    676
    -          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
    
    677
    -          blue->shoot.fit = blue->ref.fit + delta2;
    
    678
    -
    
    679
    -          FT_TRACE5(( ">> activating blue zone %d:"
    
    680
    -                      "  ref.cur=%.2g ref.fit=%.2g"
    
    681
    -                      "  shoot.cur=%.2g shoot.fit=%.2g\n",
    
    682
    -                      nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0,
    
    683
    -                      blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
    
    684
    -
    
    685
    -          blue->flags |= AF_LATIN_BLUE_ACTIVE;
    
    686
    -        }
    
    687
    -      }
    
    688
    -    }
    
    689
    -  }
    
    690
    -
    
    691
    -
    
    692
    -  FT_LOCAL_DEF( void )
    
    693
    -  af_latin2_metrics_scale( AF_LatinMetrics  metrics,
    
    694
    -                           AF_Scaler        scaler )
    
    695
    -  {
    
    696
    -    metrics->root.scaler.render_mode = scaler->render_mode;
    
    697
    -    metrics->root.scaler.face        = scaler->face;
    
    698
    -    metrics->root.scaler.flags       = scaler->flags;
    
    699
    -
    
    700
    -    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
    
    701
    -    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
    
    702
    -  }
    
    703
    -
    
    704
    -
    
    705
    -  /* Extract standard_width from writing system/script specific */
    
    706
    -  /* metrics class.                                             */
    
    707
    -
    
    708
    -  FT_LOCAL_DEF( void )
    
    709
    -  af_latin2_get_standard_widths( AF_LatinMetrics  metrics,
    
    710
    -                                 FT_Pos*          stdHW,
    
    711
    -                                 FT_Pos*          stdVW )
    
    712
    -  {
    
    713
    -    if ( stdHW )
    
    714
    -      *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
    
    715
    -
    
    716
    -    if ( stdVW )
    
    717
    -      *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
    
    718
    -  }
    
    719
    -
    
    720
    -
    
    721
    -  /*************************************************************************/
    
    722
    -  /*************************************************************************/
    
    723
    -  /*****                                                               *****/
    
    724
    -  /*****           L A T I N   G L Y P H   A N A L Y S I S             *****/
    
    725
    -  /*****                                                               *****/
    
    726
    -  /*************************************************************************/
    
    727
    -  /*************************************************************************/
    
    728
    -
    
    729
    -#define  SORT_SEGMENTS
    
    730
    -
    
    731
    -  FT_LOCAL_DEF( FT_Error )
    
    732
    -  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
    
    733
    -                                    AF_Dimension   dim )
    
    734
    -  {
    
    735
    -    AF_AxisHints  axis          = &hints->axis[dim];
    
    736
    -    FT_Memory     memory        = hints->memory;
    
    737
    -    FT_Error      error         = FT_Err_Ok;
    
    738
    -    AF_Segment    segment       = NULL;
    
    739
    -    AF_SegmentRec seg0;
    
    740
    -    AF_Point*     contour       = hints->contours;
    
    741
    -    AF_Point*     contour_limit = contour + hints->num_contours;
    
    742
    -    AF_Direction  major_dir, segment_dir;
    
    743
    -
    
    744
    -
    
    745
    -    FT_ZERO( &seg0 );
    
    746
    -    seg0.score = 32000;
    
    747
    -    seg0.flags = AF_EDGE_NORMAL;
    
    748
    -
    
    749
    -    major_dir   = (AF_Direction)FT_ABS( axis->major_dir );
    
    750
    -    segment_dir = major_dir;
    
    751
    -
    
    752
    -    axis->num_segments = 0;
    
    753
    -
    
    754
    -    /* set up (u,v) in each point */
    
    755
    -    if ( dim == AF_DIMENSION_HORZ )
    
    756
    -    {
    
    757
    -      AF_Point  point = hints->points;
    
    758
    -      AF_Point  limit = point + hints->num_points;
    
    759
    -
    
    760
    -
    
    761
    -      for ( ; point < limit; point++ )
    
    762
    -      {
    
    763
    -        point->u = point->fx;
    
    764
    -        point->v = point->fy;
    
    765
    -      }
    
    766
    -    }
    
    767
    -    else
    
    768
    -    {
    
    769
    -      AF_Point  point = hints->points;
    
    770
    -      AF_Point  limit = point + hints->num_points;
    
    771
    -
    
    772
    -
    
    773
    -      for ( ; point < limit; point++ )
    
    774
    -      {
    
    775
    -        point->u = point->fy;
    
    776
    -        point->v = point->fx;
    
    777
    -      }
    
    778
    -    }
    
    779
    -
    
    780
    -    /* do each contour separately */
    
    781
    -    for ( ; contour < contour_limit; contour++ )
    
    782
    -    {
    
    783
    -      AF_Point  point   =  contour[0];
    
    784
    -      AF_Point  start   =  point;
    
    785
    -      AF_Point  last    =  point->prev;
    
    786
    -
    
    787
    -
    
    788
    -      if ( point == last )  /* skip singletons -- just in case */
    
    789
    -        continue;
    
    790
    -
    
    791
    -      /* already on an edge ?, backtrack to find its start */
    
    792
    -      if ( FT_ABS( point->in_dir ) == major_dir )
    
    793
    -      {
    
    794
    -        point = point->prev;
    
    795
    -
    
    796
    -        while ( point->in_dir == start->in_dir )
    
    797
    -          point = point->prev;
    
    798
    -      }
    
    799
    -      else  /* otherwise, find first segment start, if any */
    
    800
    -      {
    
    801
    -        while ( FT_ABS( point->out_dir ) != major_dir )
    
    802
    -        {
    
    803
    -          point = point->next;
    
    804
    -
    
    805
    -          if ( point == start )
    
    806
    -            goto NextContour;
    
    807
    -        }
    
    808
    -      }
    
    809
    -
    
    810
    -      start = point;
    
    811
    -
    
    812
    -      for  (;;)
    
    813
    -      {
    
    814
    -        AF_Point  first;
    
    815
    -        FT_Pos    min_u, min_v, max_u, max_v;
    
    816
    -
    
    817
    -        /* we're at the start of a new segment */
    
    818
    -        FT_ASSERT( FT_ABS( point->out_dir ) == major_dir &&
    
    819
    -                           point->in_dir != point->out_dir );
    
    820
    -        first = point;
    
    821
    -
    
    822
    -        min_u = max_u = point->u;
    
    823
    -        min_v = max_v = point->v;
    
    824
    -
    
    825
    -        point = point->next;
    
    826
    -
    
    827
    -        while ( point->out_dir == first->out_dir )
    
    828
    -        {
    
    829
    -          point = point->next;
    
    830
    -
    
    831
    -          if ( point->u < min_u )
    
    832
    -            min_u = point->u;
    
    833
    -
    
    834
    -          if ( point->u > max_u )
    
    835
    -            max_u = point->u;
    
    836
    -        }
    
    837
    -
    
    838
    -        if ( point->v < min_v )
    
    839
    -          min_v = point->v;
    
    840
    -
    
    841
    -        if ( point->v > max_v )
    
    842
    -          max_v = point->v;
    
    843
    -
    
    844
    -        /* record new segment */
    
    845
    -        error = af_axis_hints_new_segment( axis, memory, &segment );
    
    846
    -        if ( error )
    
    847
    -          goto Exit;
    
    848
    -
    
    849
    -        segment[0]         = seg0;
    
    850
    -        segment->dir       = first->out_dir;
    
    851
    -        segment->first     = first;
    
    852
    -        segment->last      = point;
    
    853
    -        segment->pos       = (FT_Short)( ( min_u + max_u ) >> 1 );
    
    854
    -        segment->min_coord = (FT_Short) min_v;
    
    855
    -        segment->max_coord = (FT_Short) max_v;
    
    856
    -        segment->height    = (FT_Short)( max_v - min_v );
    
    857
    -
    
    858
    -        /* a segment is round if it doesn't have successive */
    
    859
    -        /* on-curve points.                                 */
    
    860
    -        {
    
    861
    -          AF_Point  pt   = first;
    
    862
    -          AF_Point  last = point;
    
    863
    -          FT_UInt   f0   = pt->flags & AF_FLAG_CONTROL;
    
    864
    -          FT_UInt   f1;
    
    865
    -
    
    866
    -
    
    867
    -          segment->flags &= ~AF_EDGE_ROUND;
    
    868
    -
    
    869
    -          for ( ; pt != last; f0 = f1 )
    
    870
    -          {
    
    871
    -            pt = pt->next;
    
    872
    -            f1 = pt->flags & AF_FLAG_CONTROL;
    
    873
    -
    
    874
    -            if ( !f0 && !f1 )
    
    875
    -              break;
    
    876
    -
    
    877
    -            if ( pt == last )
    
    878
    -              segment->flags |= AF_EDGE_ROUND;
    
    879
    -          }
    
    880
    -        }
    
    881
    -
    
    882
    -       /* this can happen in the case of a degenerate contour
    
    883
    -        * e.g. a 2-point vertical contour
    
    884
    -        */
    
    885
    -        if ( point == start )
    
    886
    -          break;
    
    887
    -
    
    888
    -        /* jump to the start of the next segment, if any */
    
    889
    -        while ( FT_ABS( point->out_dir ) != major_dir )
    
    890
    -        {
    
    891
    -          point = point->next;
    
    892
    -
    
    893
    -          if ( point == start )
    
    894
    -            goto NextContour;
    
    895
    -        }
    
    896
    -      }
    
    897
    -
    
    898
    -    NextContour:
    
    899
    -      ;
    
    900
    -    } /* contours */
    
    901
    -
    
    902
    -    /* now slightly increase the height of segments when this makes */
    
    903
    -    /* sense -- this is used to better detect and ignore serifs     */
    
    904
    -    {
    
    905
    -      AF_Segment  segments     = axis->segments;
    
    906
    -      AF_Segment  segments_end = segments + axis->num_segments;
    
    907
    -
    
    908
    -
    
    909
    -      for ( segment = segments; segment < segments_end; segment++ )
    
    910
    -      {
    
    911
    -        AF_Point  first   = segment->first;
    
    912
    -        AF_Point  last    = segment->last;
    
    913
    -        AF_Point  p;
    
    914
    -        FT_Pos    first_v = first->v;
    
    915
    -        FT_Pos    last_v  = last->v;
    
    916
    -
    
    917
    -
    
    918
    -        if ( first_v < last_v )
    
    919
    -        {
    
    920
    -          p = first->prev;
    
    921
    -          if ( p->v < first_v )
    
    922
    -            segment->height = (FT_Short)( segment->height +
    
    923
    -                                          ( ( first_v - p->v ) >> 1 ) );
    
    924
    -
    
    925
    -          p = last->next;
    
    926
    -          if ( p->v > last_v )
    
    927
    -            segment->height = (FT_Short)( segment->height +
    
    928
    -                                          ( ( p->v - last_v ) >> 1 ) );
    
    929
    -        }
    
    930
    -        else
    
    931
    -        {
    
    932
    -          p = first->prev;
    
    933
    -          if ( p->v > first_v )
    
    934
    -            segment->height = (FT_Short)( segment->height +
    
    935
    -                                          ( ( p->v - first_v ) >> 1 ) );
    
    936
    -
    
    937
    -          p = last->next;
    
    938
    -          if ( p->v < last_v )
    
    939
    -            segment->height = (FT_Short)( segment->height +
    
    940
    -                                          ( ( last_v - p->v ) >> 1 ) );
    
    941
    -        }
    
    942
    -      }
    
    943
    -    }
    
    944
    -
    
    945
    -#ifdef AF_SORT_SEGMENTS
    
    946
    -   /* place all segments with a negative direction to the start
    
    947
    -    * of the array, used to speed up segment linking later...
    
    948
    -    */
    
    949
    -    {
    
    950
    -      AF_Segment  segments = axis->segments;
    
    951
    -      FT_UInt     count    = axis->num_segments;
    
    952
    -      FT_UInt     ii, jj;
    
    953
    -
    
    954
    -      for ( ii = 0; ii < count; ii++ )
    
    955
    -      {
    
    956
    -        if ( segments[ii].dir > 0 )
    
    957
    -        {
    
    958
    -          for ( jj = ii + 1; jj < count; jj++ )
    
    959
    -          {
    
    960
    -            if ( segments[jj].dir < 0 )
    
    961
    -            {
    
    962
    -              AF_SegmentRec  tmp;
    
    963
    -
    
    964
    -
    
    965
    -              tmp          = segments[ii];
    
    966
    -              segments[ii] = segments[jj];
    
    967
    -              segments[jj] = tmp;
    
    968
    -
    
    969
    -              break;
    
    970
    -            }
    
    971
    -          }
    
    972
    -
    
    973
    -          if ( jj == count )
    
    974
    -            break;
    
    975
    -        }
    
    976
    -      }
    
    977
    -      axis->mid_segments = ii;
    
    978
    -    }
    
    979
    -#endif
    
    980
    -
    
    981
    -  Exit:
    
    982
    -    return error;
    
    983
    -  }
    
    984
    -
    
    985
    -
    
    986
    -  FT_LOCAL_DEF( void )
    
    987
    -  af_latin2_hints_link_segments( AF_GlyphHints  hints,
    
    988
    -                                 AF_Dimension   dim )
    
    989
    -  {
    
    990
    -    AF_AxisHints  axis          = &hints->axis[dim];
    
    991
    -    AF_Segment    segments      = axis->segments;
    
    992
    -    AF_Segment    segment_limit = segments + axis->num_segments;
    
    993
    -#ifdef AF_SORT_SEGMENTS
    
    994
    -    AF_Segment    segment_mid   = segments + axis->mid_segments;
    
    995
    -#endif
    
    996
    -    FT_Pos        len_threshold, len_score;
    
    997
    -    AF_Segment    seg1, seg2;
    
    998
    -
    
    999
    -
    
    1000
    -    len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
    
    1001
    -    if ( len_threshold == 0 )
    
    1002
    -      len_threshold = 1;
    
    1003
    -
    
    1004
    -    len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
    
    1005
    -
    
    1006
    -#ifdef AF_SORT_SEGMENTS
    
    1007
    -    for ( seg1 = segments; seg1 < segment_mid; seg1++ )
    
    1008
    -    {
    
    1009
    -      if ( seg1->dir != axis->major_dir )
    
    1010
    -        continue;
    
    1011
    -
    
    1012
    -      for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
    
    1013
    -#else
    
    1014
    -    /* now compare each segment to the others */
    
    1015
    -    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
    
    1016
    -    {
    
    1017
    -      if ( seg1->dir != axis->major_dir )
    
    1018
    -        continue;
    
    1019
    -
    
    1020
    -      for ( seg2 = segments; seg2 < segment_limit; seg2++ )
    
    1021
    -        if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
    
    1022
    -#endif
    
    1023
    -        {
    
    1024
    -          FT_Pos  pos1 = seg1->pos;
    
    1025
    -          FT_Pos  pos2 = seg2->pos;
    
    1026
    -          FT_Pos  dist = pos2 - pos1;
    
    1027
    -
    
    1028
    -
    
    1029
    -          if ( dist < 0 )
    
    1030
    -            continue;
    
    1031
    -
    
    1032
    -          {
    
    1033
    -            FT_Pos  min = seg1->min_coord;
    
    1034
    -            FT_Pos  max = seg1->max_coord;
    
    1035
    -            FT_Pos  len, score;
    
    1036
    -
    
    1037
    -
    
    1038
    -            if ( min < seg2->min_coord )
    
    1039
    -              min = seg2->min_coord;
    
    1040
    -
    
    1041
    -            if ( max > seg2->max_coord )
    
    1042
    -              max = seg2->max_coord;
    
    1043
    -
    
    1044
    -            len = max - min;
    
    1045
    -            if ( len >= len_threshold )
    
    1046
    -            {
    
    1047
    -              score = dist + len_score / len;
    
    1048
    -              if ( score < seg1->score )
    
    1049
    -              {
    
    1050
    -                seg1->score = score;
    
    1051
    -                seg1->link  = seg2;
    
    1052
    -              }
    
    1053
    -
    
    1054
    -              if ( score < seg2->score )
    
    1055
    -              {
    
    1056
    -                seg2->score = score;
    
    1057
    -                seg2->link  = seg1;
    
    1058
    -              }
    
    1059
    -            }
    
    1060
    -          }
    
    1061
    -        }
    
    1062
    -    }
    
    1063
    -#if 0
    
    1064
    -    }
    
    1065
    -#endif
    
    1066
    -
    
    1067
    -    /* now, compute the `serif' segments */
    
    1068
    -    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
    
    1069
    -    {
    
    1070
    -      seg2 = seg1->link;
    
    1071
    -
    
    1072
    -      if ( seg2 )
    
    1073
    -      {
    
    1074
    -        if ( seg2->link != seg1 )
    
    1075
    -        {
    
    1076
    -          seg1->link  = NULL;
    
    1077
    -          seg1->serif = seg2->link;
    
    1078
    -        }
    
    1079
    -      }
    
    1080
    -    }
    
    1081
    -  }
    
    1082
    -
    
    1083
    -
    
    1084
    -  FT_LOCAL_DEF( FT_Error )
    
    1085
    -  af_latin2_hints_compute_edges( AF_GlyphHints  hints,
    
    1086
    -                                 AF_Dimension   dim )
    
    1087
    -  {
    
    1088
    -    AF_AxisHints  axis   = &hints->axis[dim];
    
    1089
    -    FT_Error      error  = FT_Err_Ok;
    
    1090
    -    FT_Memory     memory = hints->memory;
    
    1091
    -    AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
    
    1092
    -
    
    1093
    -    AF_Segment    segments      = axis->segments;
    
    1094
    -    AF_Segment    segment_limit = segments + axis->num_segments;
    
    1095
    -    AF_Segment    seg;
    
    1096
    -
    
    1097
    -    AF_Direction  up_dir;
    
    1098
    -    FT_Fixed      scale;
    
    1099
    -    FT_Pos        edge_distance_threshold;
    
    1100
    -    FT_Pos        segment_length_threshold;
    
    1101
    -
    
    1102
    -
    
    1103
    -    axis->num_edges = 0;
    
    1104
    -
    
    1105
    -    scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
    
    1106
    -                                         : hints->y_scale;
    
    1107
    -
    
    1108
    -    up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
    
    1109
    -                                          : AF_DIR_RIGHT;
    
    1110
    -
    
    1111
    -    /*
    
    1112
    -     * We want to ignore very small (mostly serif) segments, we do that
    
    1113
    -     * by ignoring those that whose length is less than a given fraction
    
    1114
    -     * of the standard width. If there is no standard width, we ignore
    
    1115
    -     * those that are less than a given size in pixels
    
    1116
    -     *
    
    1117
    -     * also, unlink serif segments that are linked to segments farther
    
    1118
    -     * than 50% of the standard width
    
    1119
    -     */
    
    1120
    -    if ( dim == AF_DIMENSION_HORZ )
    
    1121
    -    {
    
    1122
    -      if ( laxis->width_count > 0 )
    
    1123
    -        segment_length_threshold = ( laxis->standard_width * 10 ) >> 4;
    
    1124
    -      else
    
    1125
    -        segment_length_threshold = FT_DivFix( 64, hints->y_scale );
    
    1126
    -    }
    
    1127
    -    else
    
    1128
    -      segment_length_threshold = 0;
    
    1129
    -
    
    1130
    -    /**********************************************************************
    
    1131
    -     *
    
    1132
    -     * We will begin by generating a sorted table of edges for the
    
    1133
    -     * current direction.  To do so, we simply scan each segment and try
    
    1134
    -     * to find an edge in our table that corresponds to its position.
    
    1135
    -     *
    
    1136
    -     * If no edge is found, we create and insert a new edge in the
    
    1137
    -     * sorted table.  Otherwise, we simply add the segment to the edge's
    
    1138
    -     * list which will be processed in the second step to compute the
    
    1139
    -     * edge's properties.
    
    1140
    -     *
    
    1141
    -     * Note that the edges table is sorted along the segment/edge
    
    1142
    -     * position.
    
    1143
    -     *
    
    1144
    -     */
    
    1145
    -
    
    1146
    -    edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
    
    1147
    -                                         scale );
    
    1148
    -    if ( edge_distance_threshold > 64 / 4 )
    
    1149
    -      edge_distance_threshold = 64 / 4;
    
    1150
    -
    
    1151
    -    edge_distance_threshold = FT_DivFix( edge_distance_threshold,
    
    1152
    -                                         scale );
    
    1153
    -
    
    1154
    -    for ( seg = segments; seg < segment_limit; seg++ )
    
    1155
    -    {
    
    1156
    -      AF_Edge  found = NULL;
    
    1157
    -      FT_Int   ee;
    
    1158
    -
    
    1159
    -
    
    1160
    -      if ( seg->height < segment_length_threshold )
    
    1161
    -        continue;
    
    1162
    -
    
    1163
    -      /* A special case for serif edges: If they are smaller than */
    
    1164
    -      /* 1.5 pixels we ignore them.                               */
    
    1165
    -      if ( seg->serif )
    
    1166
    -      {
    
    1167
    -        FT_Pos  dist = seg->serif->pos - seg->pos;
    
    1168
    -
    
    1169
    -
    
    1170
    -        if ( dist < 0 )
    
    1171
    -          dist = -dist;
    
    1172
    -
    
    1173
    -        if ( dist >= laxis->standard_width >> 1 )
    
    1174
    -        {
    
    1175
    -          /* unlink this serif, it is too distant from its reference stem */
    
    1176
    -          seg->serif = NULL;
    
    1177
    -        }
    
    1178
    -        else if ( 2*seg->height < 3 * segment_length_threshold )
    
    1179
    -          continue;
    
    1180
    -      }
    
    1181
    -
    
    1182
    -      /* look for an edge corresponding to the segment */
    
    1183
    -      for ( ee = 0; ee < axis->num_edges; ee++ )
    
    1184
    -      {
    
    1185
    -        AF_Edge  edge = axis->edges + ee;
    
    1186
    -        FT_Pos   dist;
    
    1187
    -
    
    1188
    -
    
    1189
    -        dist = seg->pos - edge->fpos;
    
    1190
    -        if ( dist < 0 )
    
    1191
    -          dist = -dist;
    
    1192
    -
    
    1193
    -        if ( dist < edge_distance_threshold && edge->dir == seg->dir )
    
    1194
    -        {
    
    1195
    -          found = edge;
    
    1196
    -          break;
    
    1197
    -        }
    
    1198
    -      }
    
    1199
    -
    
    1200
    -      if ( !found )
    
    1201
    -      {
    
    1202
    -        AF_Edge   edge;
    
    1203
    -
    
    1204
    -
    
    1205
    -        /* insert a new edge in the list and */
    
    1206
    -        /* sort according to the position    */
    
    1207
    -        error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, 0,
    
    1208
    -                                        memory, &edge );
    
    1209
    -        if ( error )
    
    1210
    -          goto Exit;
    
    1211
    -
    
    1212
    -        /* add the segment to the new edge's list */
    
    1213
    -        FT_ZERO( edge );
    
    1214
    -
    
    1215
    -        edge->first    = seg;
    
    1216
    -        edge->last     = seg;
    
    1217
    -        edge->dir      = seg->dir;
    
    1218
    -        edge->fpos     = seg->pos;
    
    1219
    -        edge->opos     = FT_MulFix( seg->pos, scale );
    
    1220
    -        edge->pos      = edge->opos;
    
    1221
    -        seg->edge_next = seg;
    
    1222
    -      }
    
    1223
    -      else
    
    1224
    -      {
    
    1225
    -        /* if an edge was found, simply add the segment to the edge's */
    
    1226
    -        /* list                                                       */
    
    1227
    -        seg->edge_next         = found->first;
    
    1228
    -        found->last->edge_next = seg;
    
    1229
    -        found->last            = seg;
    
    1230
    -      }
    
    1231
    -    }
    
    1232
    -
    
    1233
    -
    
    1234
    -    /**********************************************************************
    
    1235
    -     *
    
    1236
    -     * Good, we will now compute each edge's properties according to
    
    1237
    -     * segments found on its position.  Basically, these are:
    
    1238
    -     *
    
    1239
    -     * - edge's main direction
    
    1240
    -     * - stem edge, serif edge or both (which defaults to stem then)
    
    1241
    -     * - rounded edge, straight or both (which defaults to straight)
    
    1242
    -     * - link for edge
    
    1243
    -     *
    
    1244
    -     */
    
    1245
    -
    
    1246
    -    /* first of all, set the `edge' field in each segment -- this is */
    
    1247
    -    /* required in order to compute edge links                       */
    
    1248
    -
    
    1249
    -    /*
    
    1250
    -     * Note that removing this loop and setting the `edge' field of each
    
    1251
    -     * segment directly in the code above slows down execution speed for
    
    1252
    -     * some reasons on platforms like the Sun.
    
    1253
    -     */
    
    1254
    -    {
    
    1255
    -      AF_Edge  edges      = axis->edges;
    
    1256
    -      AF_Edge  edge_limit = edges + axis->num_edges;
    
    1257
    -      AF_Edge  edge;
    
    1258
    -
    
    1259
    -
    
    1260
    -      for ( edge = edges; edge < edge_limit; edge++ )
    
    1261
    -      {
    
    1262
    -        seg = edge->first;
    
    1263
    -        if ( seg )
    
    1264
    -          do
    
    1265
    -          {
    
    1266
    -            seg->edge = edge;
    
    1267
    -            seg       = seg->edge_next;
    
    1268
    -
    
    1269
    -          } while ( seg != edge->first );
    
    1270
    -      }
    
    1271
    -
    
    1272
    -      /* now, compute each edge properties */
    
    1273
    -      for ( edge = edges; edge < edge_limit; edge++ )
    
    1274
    -      {
    
    1275
    -        FT_Int  is_round    = 0;  /* does it contain round segments?    */
    
    1276
    -        FT_Int  is_straight = 0;  /* does it contain straight segments? */
    
    1277
    -#if 0
    
    1278
    -        FT_Pos  ups         = 0;  /* number of upwards segments         */
    
    1279
    -        FT_Pos  downs       = 0;  /* number of downwards segments       */
    
    1280
    -#endif
    
    1281
    -
    
    1282
    -
    
    1283
    -        seg = edge->first;
    
    1284
    -
    
    1285
    -        do
    
    1286
    -        {
    
    1287
    -          FT_Bool  is_serif;
    
    1288
    -
    
    1289
    -
    
    1290
    -          /* check for roundness of segment */
    
    1291
    -          if ( seg->flags & AF_EDGE_ROUND )
    
    1292
    -            is_round++;
    
    1293
    -          else
    
    1294
    -            is_straight++;
    
    1295
    -
    
    1296
    -#if 0
    
    1297
    -          /* check for segment direction */
    
    1298
    -          if ( seg->dir == up_dir )
    
    1299
    -            ups   += seg->max_coord-seg->min_coord;
    
    1300
    -          else
    
    1301
    -            downs += seg->max_coord-seg->min_coord;
    
    1302
    -#endif
    
    1303
    -
    
    1304
    -          /* check for links -- if seg->serif is set, then seg->link must */
    
    1305
    -          /* be ignored                                                   */
    
    1306
    -          is_serif = FT_BOOL( seg->serif               &&
    
    1307
    -                              seg->serif->edge         &&
    
    1308
    -                              seg->serif->edge != edge );
    
    1309
    -
    
    1310
    -          if ( ( seg->link && seg->link->edge ) || is_serif )
    
    1311
    -          {
    
    1312
    -            AF_Edge     edge2;
    
    1313
    -            AF_Segment  seg2;
    
    1314
    -
    
    1315
    -
    
    1316
    -            edge2 = edge->link;
    
    1317
    -            seg2  = seg->link;
    
    1318
    -
    
    1319
    -            if ( is_serif )
    
    1320
    -            {
    
    1321
    -              seg2  = seg->serif;
    
    1322
    -              edge2 = edge->serif;
    
    1323
    -            }
    
    1324
    -
    
    1325
    -            if ( edge2 )
    
    1326
    -            {
    
    1327
    -              FT_Pos  edge_delta;
    
    1328
    -              FT_Pos  seg_delta;
    
    1329
    -
    
    1330
    -
    
    1331
    -              edge_delta = edge->fpos - edge2->fpos;
    
    1332
    -              if ( edge_delta < 0 )
    
    1333
    -                edge_delta = -edge_delta;
    
    1334
    -
    
    1335
    -              seg_delta = seg->pos - seg2->pos;
    
    1336
    -              if ( seg_delta < 0 )
    
    1337
    -                seg_delta = -seg_delta;
    
    1338
    -
    
    1339
    -              if ( seg_delta < edge_delta )
    
    1340
    -                edge2 = seg2->edge;
    
    1341
    -            }
    
    1342
    -            else
    
    1343
    -              edge2 = seg2->edge;
    
    1344
    -
    
    1345
    -            if ( is_serif )
    
    1346
    -            {
    
    1347
    -              edge->serif   = edge2;
    
    1348
    -              edge2->flags |= AF_EDGE_SERIF;
    
    1349
    -            }
    
    1350
    -            else
    
    1351
    -              edge->link  = edge2;
    
    1352
    -          }
    
    1353
    -
    
    1354
    -          seg = seg->edge_next;
    
    1355
    -
    
    1356
    -        } while ( seg != edge->first );
    
    1357
    -
    
    1358
    -        /* set the round/straight flags */
    
    1359
    -        edge->flags = AF_EDGE_NORMAL;
    
    1360
    -
    
    1361
    -        if ( is_round > 0 && is_round >= is_straight )
    
    1362
    -          edge->flags |= AF_EDGE_ROUND;
    
    1363
    -
    
    1364
    -#if 0
    
    1365
    -        /* set the edge's main direction */
    
    1366
    -        edge->dir = AF_DIR_NONE;
    
    1367
    -
    
    1368
    -        if ( ups > downs )
    
    1369
    -          edge->dir = (FT_Char)up_dir;
    
    1370
    -
    
    1371
    -        else if ( ups < downs )
    
    1372
    -          edge->dir = (FT_Char)-up_dir;
    
    1373
    -
    
    1374
    -        else if ( ups == downs )
    
    1375
    -          edge->dir = 0;  /* both up and down! */
    
    1376
    -#endif
    
    1377
    -
    
    1378
    -        /* gets rid of serifs if link is set                */
    
    1379
    -        /* XXX: This gets rid of many unpleasant artefacts! */
    
    1380
    -        /*      Example: the `c' in cour.pfa at size 13     */
    
    1381
    -
    
    1382
    -        if ( edge->serif && edge->link )
    
    1383
    -          edge->serif = NULL;
    
    1384
    -      }
    
    1385
    -    }
    
    1386
    -
    
    1387
    -  Exit:
    
    1388
    -    return error;
    
    1389
    -  }
    
    1390
    -
    
    1391
    -
    
    1392
    -  FT_LOCAL_DEF( FT_Error )
    
    1393
    -  af_latin2_hints_detect_features( AF_GlyphHints  hints,
    
    1394
    -                                   AF_Dimension   dim )
    
    1395
    -  {
    
    1396
    -    FT_Error  error;
    
    1397
    -
    
    1398
    -
    
    1399
    -    error = af_latin2_hints_compute_segments( hints, dim );
    
    1400
    -    if ( !error )
    
    1401
    -    {
    
    1402
    -      af_latin2_hints_link_segments( hints, dim );
    
    1403
    -
    
    1404
    -      error = af_latin2_hints_compute_edges( hints, dim );
    
    1405
    -    }
    
    1406
    -    return error;
    
    1407
    -  }
    
    1408
    -
    
    1409
    -
    
    1410
    -  static void
    
    1411
    -  af_latin2_hints_compute_blue_edges( AF_GlyphHints    hints,
    
    1412
    -                                      AF_LatinMetrics  metrics )
    
    1413
    -  {
    
    1414
    -    AF_AxisHints  axis       = &hints->axis[AF_DIMENSION_VERT];
    
    1415
    -    AF_Edge       edge       = axis->edges;
    
    1416
    -    AF_Edge       edge_limit = edge + axis->num_edges;
    
    1417
    -    AF_LatinAxis  latin      = &metrics->axis[AF_DIMENSION_VERT];
    
    1418
    -    FT_Fixed      scale      = latin->scale;
    
    1419
    -    FT_Pos        best_dist0;  /* initial threshold */
    
    1420
    -
    
    1421
    -
    
    1422
    -    /* compute the initial threshold as a fraction of the EM size */
    
    1423
    -    best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
    
    1424
    -
    
    1425
    -    if ( best_dist0 > 64 / 2 )
    
    1426
    -      best_dist0 = 64 / 2;
    
    1427
    -
    
    1428
    -    /* compute which blue zones are active, i.e. have their scaled */
    
    1429
    -    /* size < 3/4 pixels                                           */
    
    1430
    -
    
    1431
    -    /* for each horizontal edge search the blue zone which is closest */
    
    1432
    -    for ( ; edge < edge_limit; edge++ )
    
    1433
    -    {
    
    1434
    -      FT_Int    bb;
    
    1435
    -      AF_Width  best_blue = NULL;
    
    1436
    -      FT_Pos    best_dist = best_dist0;
    
    1437
    -
    
    1438
    -      for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
    
    1439
    -      {
    
    1440
    -        AF_LatinBlue  blue = latin->blues + bb;
    
    1441
    -        FT_Bool       is_top_blue, is_major_dir;
    
    1442
    -
    
    1443
    -
    
    1444
    -        /* skip inactive blue zones (i.e., those that are too small) */
    
    1445
    -        if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
    
    1446
    -          continue;
    
    1447
    -
    
    1448
    -        /* if it is a top zone, check for right edges -- if it is a bottom */
    
    1449
    -        /* zone, check for left edges                                      */
    
    1450
    -        /*                                                                 */
    
    1451
    -        /* of course, that's for TrueType                                  */
    
    1452
    -        is_top_blue  = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
    
    1453
    -        is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
    
    1454
    -
    
    1455
    -        /* if it is a top zone, the edge must be against the major    */
    
    1456
    -        /* direction; if it is a bottom zone, it must be in the major */
    
    1457
    -        /* direction                                                  */
    
    1458
    -        if ( is_top_blue ^ is_major_dir )
    
    1459
    -        {
    
    1460
    -          FT_Pos     dist;
    
    1461
    -          AF_Width   compare;
    
    1462
    -
    
    1463
    -
    
    1464
    -          /* if it's a rounded edge, compare it to the overshoot position */
    
    1465
    -          /* if it's a flat edge, compare it to the reference position    */
    
    1466
    -          if ( edge->flags & AF_EDGE_ROUND )
    
    1467
    -            compare = &blue->shoot;
    
    1468
    -          else
    
    1469
    -            compare = &blue->ref;
    
    1470
    -
    
    1471
    -          dist = edge->fpos - compare->org;
    
    1472
    -          if ( dist < 0 )
    
    1473
    -            dist = -dist;
    
    1474
    -
    
    1475
    -          dist = FT_MulFix( dist, scale );
    
    1476
    -          if ( dist < best_dist )
    
    1477
    -          {
    
    1478
    -            best_dist = dist;
    
    1479
    -            best_blue = compare;
    
    1480
    -          }
    
    1481
    -
    
    1482
    -#if 0
    
    1483
    -          /* now, compare it to the overshoot position if the edge is     */
    
    1484
    -          /* rounded, and if the edge is over the reference position of a */
    
    1485
    -          /* top zone, or under the reference position of a bottom zone   */
    
    1486
    -          if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
    
    1487
    -          {
    
    1488
    -            FT_Bool  is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
    
    1489
    -
    
    1490
    -
    
    1491
    -            if ( is_top_blue ^ is_under_ref )
    
    1492
    -            {
    
    1493
    -              blue = latin->blues + bb;
    
    1494
    -              dist = edge->fpos - blue->shoot.org;
    
    1495
    -              if ( dist < 0 )
    
    1496
    -                dist = -dist;
    
    1497
    -
    
    1498
    -              dist = FT_MulFix( dist, scale );
    
    1499
    -              if ( dist < best_dist )
    
    1500
    -              {
    
    1501
    -                best_dist = dist;
    
    1502
    -                best_blue = & blue->shoot;
    
    1503
    -              }
    
    1504
    -            }
    
    1505
    -          }
    
    1506
    -#endif
    
    1507
    -        }
    
    1508
    -      }
    
    1509
    -
    
    1510
    -      if ( best_blue )
    
    1511
    -        edge->blue_edge = best_blue;
    
    1512
    -    }
    
    1513
    -  }
    
    1514
    -
    
    1515
    -
    
    1516
    -  static FT_Error
    
    1517
    -  af_latin2_hints_init( AF_GlyphHints    hints,
    
    1518
    -                        AF_LatinMetrics  metrics )
    
    1519
    -  {
    
    1520
    -    FT_Render_Mode  mode;
    
    1521
    -    FT_UInt32       scaler_flags, other_flags;
    
    1522
    -    FT_Face         face = metrics->root.scaler.face;
    
    1523
    -
    
    1524
    -
    
    1525
    -    af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
    
    1526
    -
    
    1527
    -    /*
    
    1528
    -     * correct x_scale and y_scale if needed, since they may have
    
    1529
    -     * been modified `af_latin2_metrics_scale_dim' above
    
    1530
    -     */
    
    1531
    -    hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
    
    1532
    -    hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
    
    1533
    -    hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
    
    1534
    -    hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
    
    1535
    -
    
    1536
    -    /* compute flags depending on render mode, etc. */
    
    1537
    -    mode = metrics->root.scaler.render_mode;
    
    1538
    -
    
    1539
    -#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
    
    1540
    -    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
    
    1541
    -      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
    
    1542
    -#endif
    
    1543
    -
    
    1544
    -    scaler_flags = hints->scaler_flags;
    
    1545
    -    other_flags  = 0;
    
    1546
    -
    
    1547
    -    /*
    
    1548
    -     * We snap the width of vertical stems for the monochrome and
    
    1549
    -     * horizontal LCD rendering targets only.
    
    1550
    -     */
    
    1551
    -    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
    
    1552
    -      other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
    
    1553
    -
    
    1554
    -    /*
    
    1555
    -     * We snap the width of horizontal stems for the monochrome and
    
    1556
    -     * vertical LCD rendering targets only.
    
    1557
    -     */
    
    1558
    -    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
    
    1559
    -      other_flags |= AF_LATIN_HINTS_VERT_SNAP;
    
    1560
    -
    
    1561
    -    /*
    
    1562
    -     * We adjust stems to full pixels unless in `light' or `lcd' mode.
    
    1563
    -     */
    
    1564
    -    if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD )
    
    1565
    -      other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
    
    1566
    -
    
    1567
    -    if ( mode == FT_RENDER_MODE_MONO )
    
    1568
    -      other_flags |= AF_LATIN_HINTS_MONO;
    
    1569
    -
    
    1570
    -    /*
    
    1571
    -     * In `light' or `lcd' mode we disable horizontal hinting completely.
    
    1572
    -     * We also do it if the face is italic.
    
    1573
    -     */
    
    1574
    -    if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD ||
    
    1575
    -         ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0          )
    
    1576
    -      scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
    
    1577
    -
    
    1578
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    1579
    -    /* get (global) warper flag */
    
    1580
    -    if ( !metrics->root.globals->module->warping )
    
    1581
    -      scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
    
    1582
    -#endif
    
    1583
    -
    
    1584
    -    hints->scaler_flags = scaler_flags;
    
    1585
    -    hints->other_flags  = other_flags;
    
    1586
    -
    
    1587
    -    return 0;
    
    1588
    -  }
    
    1589
    -
    
    1590
    -
    
    1591
    -  /*************************************************************************/
    
    1592
    -  /*************************************************************************/
    
    1593
    -  /*****                                                               *****/
    
    1594
    -  /*****        L A T I N   G L Y P H   G R I D - F I T T I N G        *****/
    
    1595
    -  /*****                                                               *****/
    
    1596
    -  /*************************************************************************/
    
    1597
    -  /*************************************************************************/
    
    1598
    -
    
    1599
    -  /* snap a given width in scaled coordinates to one of the */
    
    1600
    -  /* current standard widths                                */
    
    1601
    -
    
    1602
    -  static FT_Pos
    
    1603
    -  af_latin2_snap_width( AF_Width  widths,
    
    1604
    -                        FT_UInt   count,
    
    1605
    -                        FT_Pos    width )
    
    1606
    -  {
    
    1607
    -    FT_UInt  n;
    
    1608
    -    FT_Pos   best      = 64 + 32 + 2;
    
    1609
    -    FT_Pos   reference = width;
    
    1610
    -    FT_Pos   scaled;
    
    1611
    -
    
    1612
    -
    
    1613
    -    for ( n = 0; n < count; n++ )
    
    1614
    -    {
    
    1615
    -      FT_Pos  w;
    
    1616
    -      FT_Pos  dist;
    
    1617
    -
    
    1618
    -
    
    1619
    -      w = widths[n].cur;
    
    1620
    -      dist = width - w;
    
    1621
    -      if ( dist < 0 )
    
    1622
    -        dist = -dist;
    
    1623
    -      if ( dist < best )
    
    1624
    -      {
    
    1625
    -        best      = dist;
    
    1626
    -        reference = w;
    
    1627
    -      }
    
    1628
    -    }
    
    1629
    -
    
    1630
    -    scaled = FT_PIX_ROUND( reference );
    
    1631
    -
    
    1632
    -    if ( width >= reference )
    
    1633
    -    {
    
    1634
    -      if ( width < scaled + 48 )
    
    1635
    -        width = reference;
    
    1636
    -    }
    
    1637
    -    else
    
    1638
    -    {
    
    1639
    -      if ( width > scaled - 48 )
    
    1640
    -        width = reference;
    
    1641
    -    }
    
    1642
    -
    
    1643
    -    return width;
    
    1644
    -  }
    
    1645
    -
    
    1646
    -
    
    1647
    -  /* compute the snapped width of a given stem */
    
    1648
    -
    
    1649
    -  static FT_Pos
    
    1650
    -  af_latin2_compute_stem_width( AF_GlyphHints  hints,
    
    1651
    -                                AF_Dimension   dim,
    
    1652
    -                                FT_Pos         width,
    
    1653
    -                                FT_UInt        base_flags,
    
    1654
    -                                FT_UInt        stem_flags )
    
    1655
    -  {
    
    1656
    -    AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
    
    1657
    -    AF_LatinAxis     axis     = & metrics->axis[dim];
    
    1658
    -    FT_Pos           dist     = width;
    
    1659
    -    FT_Int           sign     = 0;
    
    1660
    -    FT_Int           vertical = ( dim == AF_DIMENSION_VERT );
    
    1661
    -
    
    1662
    -    FT_UNUSED( base_flags );
    
    1663
    -
    
    1664
    -
    
    1665
    -    if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
    
    1666
    -          axis->extra_light                      )
    
    1667
    -      return width;
    
    1668
    -
    
    1669
    -    if ( dist < 0 )
    
    1670
    -    {
    
    1671
    -      dist = -width;
    
    1672
    -      sign = 1;
    
    1673
    -    }
    
    1674
    -
    
    1675
    -    if ( (  vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
    
    1676
    -         ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
    
    1677
    -    {
    
    1678
    -      /* smooth hinting process: very lightly quantize the stem width */
    
    1679
    -
    
    1680
    -      /* leave the widths of serifs alone */
    
    1681
    -
    
    1682
    -      if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
    
    1683
    -        goto Done_Width;
    
    1684
    -
    
    1685
    -#if 0
    
    1686
    -      else if ( ( base_flags & AF_EDGE_ROUND ) )
    
    1687
    -      {
    
    1688
    -        if ( dist < 80 )
    
    1689
    -          dist = 64;
    
    1690
    -      }
    
    1691
    -      else if ( dist < 56 )
    
    1692
    -        dist = 56;
    
    1693
    -#endif
    
    1694
    -      if ( axis->width_count > 0 )
    
    1695
    -      {
    
    1696
    -        FT_Pos  delta;
    
    1697
    -
    
    1698
    -
    
    1699
    -        /* compare to standard width */
    
    1700
    -        if ( axis->width_count > 0 )
    
    1701
    -        {
    
    1702
    -          delta = dist - axis->widths[0].cur;
    
    1703
    -
    
    1704
    -          if ( delta < 0 )
    
    1705
    -            delta = -delta;
    
    1706
    -
    
    1707
    -          if ( delta < 40 )
    
    1708
    -          {
    
    1709
    -            dist = axis->widths[0].cur;
    
    1710
    -            if ( dist < 48 )
    
    1711
    -              dist = 48;
    
    1712
    -
    
    1713
    -            goto Done_Width;
    
    1714
    -          }
    
    1715
    -        }
    
    1716
    -
    
    1717
    -        if ( dist < 3 * 64 )
    
    1718
    -        {
    
    1719
    -          delta  = dist & 63;
    
    1720
    -          dist  &= -64;
    
    1721
    -
    
    1722
    -          if ( delta < 10 )
    
    1723
    -            dist += delta;
    
    1724
    -
    
    1725
    -          else if ( delta < 32 )
    
    1726
    -            dist += 10;
    
    1727
    -
    
    1728
    -          else if ( delta < 54 )
    
    1729
    -            dist += 54;
    
    1730
    -
    
    1731
    -          else
    
    1732
    -            dist += delta;
    
    1733
    -        }
    
    1734
    -        else
    
    1735
    -          dist = ( dist + 32 ) & ~63;
    
    1736
    -      }
    
    1737
    -    }
    
    1738
    -    else
    
    1739
    -    {
    
    1740
    -      /* strong hinting process: snap the stem width to integer pixels */
    
    1741
    -      FT_Pos  org_dist = dist;
    
    1742
    -
    
    1743
    -
    
    1744
    -      dist = af_latin2_snap_width( axis->widths, axis->width_count, dist );
    
    1745
    -
    
    1746
    -      if ( vertical )
    
    1747
    -      {
    
    1748
    -        /* in the case of vertical hinting, always round */
    
    1749
    -        /* the stem heights to integer pixels            */
    
    1750
    -
    
    1751
    -        if ( dist >= 64 )
    
    1752
    -          dist = ( dist + 16 ) & ~63;
    
    1753
    -        else
    
    1754
    -          dist = 64;
    
    1755
    -      }
    
    1756
    -      else
    
    1757
    -      {
    
    1758
    -        if ( AF_LATIN_HINTS_DO_MONO( hints ) )
    
    1759
    -        {
    
    1760
    -          /* monochrome horizontal hinting: snap widths to integer pixels */
    
    1761
    -          /* with a different threshold                                   */
    
    1762
    -
    
    1763
    -          if ( dist < 64 )
    
    1764
    -            dist = 64;
    
    1765
    -          else
    
    1766
    -            dist = ( dist + 32 ) & ~63;
    
    1767
    -        }
    
    1768
    -        else
    
    1769
    -        {
    
    1770
    -          /* for horizontal anti-aliased hinting, we adopt a more subtle */
    
    1771
    -          /* approach: we strengthen small stems, round stems whose size */
    
    1772
    -          /* is between 1 and 2 pixels to an integer, otherwise nothing  */
    
    1773
    -
    
    1774
    -          if ( dist < 48 )
    
    1775
    -            dist = ( dist + 64 ) >> 1;
    
    1776
    -
    
    1777
    -          else if ( dist < 128 )
    
    1778
    -          {
    
    1779
    -            /* We only round to an integer width if the corresponding */
    
    1780
    -            /* distortion is less than 1/4 pixel.  Otherwise this     */
    
    1781
    -            /* makes everything worse since the diagonals, which are  */
    
    1782
    -            /* not hinted, appear a lot bolder or thinner than the    */
    
    1783
    -            /* vertical stems.                                        */
    
    1784
    -
    
    1785
    -            FT_Int  delta;
    
    1786
    -
    
    1787
    -
    
    1788
    -            dist = ( dist + 22 ) & ~63;
    
    1789
    -            delta = dist - org_dist;
    
    1790
    -            if ( delta < 0 )
    
    1791
    -              delta = -delta;
    
    1792
    -
    
    1793
    -            if ( delta >= 16 )
    
    1794
    -            {
    
    1795
    -              dist = org_dist;
    
    1796
    -              if ( dist < 48 )
    
    1797
    -                dist = ( dist + 64 ) >> 1;
    
    1798
    -            }
    
    1799
    -          }
    
    1800
    -          else
    
    1801
    -            /* round otherwise to prevent color fringes in LCD mode */
    
    1802
    -            dist = ( dist + 32 ) & ~63;
    
    1803
    -        }
    
    1804
    -      }
    
    1805
    -    }
    
    1806
    -
    
    1807
    -  Done_Width:
    
    1808
    -    if ( sign )
    
    1809
    -      dist = -dist;
    
    1810
    -
    
    1811
    -    return dist;
    
    1812
    -  }
    
    1813
    -
    
    1814
    -
    
    1815
    -  /* align one stem edge relative to the previous stem edge */
    
    1816
    -
    
    1817
    -  static void
    
    1818
    -  af_latin2_align_linked_edge( AF_GlyphHints  hints,
    
    1819
    -                               AF_Dimension   dim,
    
    1820
    -                               AF_Edge        base_edge,
    
    1821
    -                               AF_Edge        stem_edge )
    
    1822
    -  {
    
    1823
    -    FT_Pos  dist = stem_edge->opos - base_edge->opos;
    
    1824
    -
    
    1825
    -    FT_Pos  fitted_width = af_latin2_compute_stem_width( hints, dim, dist,
    
    1826
    -                                                         base_edge->flags,
    
    1827
    -                                                         stem_edge->flags );
    
    1828
    -
    
    1829
    -
    
    1830
    -    stem_edge->pos = base_edge->pos + fitted_width;
    
    1831
    -
    
    1832
    -    FT_TRACE5(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
    
    1833
    -                "dist was %.2f, now %.2f\n",
    
    1834
    -                stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
    
    1835
    -                stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
    
    1836
    -  }
    
    1837
    -
    
    1838
    -
    
    1839
    -  static void
    
    1840
    -  af_latin2_align_serif_edge( AF_GlyphHints  hints,
    
    1841
    -                              AF_Edge        base,
    
    1842
    -                              AF_Edge        serif )
    
    1843
    -  {
    
    1844
    -    FT_UNUSED( hints );
    
    1845
    -
    
    1846
    -    serif->pos = base->pos + ( serif->opos - base->opos );
    
    1847
    -  }
    
    1848
    -
    
    1849
    -
    
    1850
    -  /*************************************************************************/
    
    1851
    -  /*************************************************************************/
    
    1852
    -  /*************************************************************************/
    
    1853
    -  /****                                                                 ****/
    
    1854
    -  /****                    E D G E   H I N T I N G                      ****/
    
    1855
    -  /****                                                                 ****/
    
    1856
    -  /*************************************************************************/
    
    1857
    -  /*************************************************************************/
    
    1858
    -  /*************************************************************************/
    
    1859
    -
    
    1860
    -
    
    1861
    -  static void
    
    1862
    -  af_latin2_hint_edges( AF_GlyphHints  hints,
    
    1863
    -                        AF_Dimension   dim )
    
    1864
    -  {
    
    1865
    -    AF_AxisHints  axis       = &hints->axis[dim];
    
    1866
    -    AF_Edge       edges      = axis->edges;
    
    1867
    -    AF_Edge       edge_limit = edges + axis->num_edges;
    
    1868
    -    AF_Edge       edge;
    
    1869
    -    AF_Edge       anchor     = NULL;
    
    1870
    -    FT_Int        has_serifs = 0;
    
    1871
    -    FT_Pos        anchor_drift = 0;
    
    1872
    -
    
    1873
    -
    
    1874
    -
    
    1875
    -    FT_TRACE5(( "==== hinting %s edges =====\n",
    
    1876
    -                dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
    
    1877
    -
    
    1878
    -    /* we begin by aligning all stems relative to the blue zone */
    
    1879
    -    /* if needed -- that's only for horizontal edges            */
    
    1880
    -
    
    1881
    -    if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
    
    1882
    -    {
    
    1883
    -      for ( edge = edges; edge < edge_limit; edge++ )
    
    1884
    -      {
    
    1885
    -        AF_Width  blue;
    
    1886
    -        AF_Edge   edge1, edge2;
    
    1887
    -
    
    1888
    -
    
    1889
    -        if ( edge->flags & AF_EDGE_DONE )
    
    1890
    -          continue;
    
    1891
    -
    
    1892
    -        blue  = edge->blue_edge;
    
    1893
    -        edge1 = NULL;
    
    1894
    -        edge2 = edge->link;
    
    1895
    -
    
    1896
    -        if ( blue )
    
    1897
    -        {
    
    1898
    -          edge1 = edge;
    
    1899
    -        }
    
    1900
    -        else if ( edge2 && edge2->blue_edge )
    
    1901
    -        {
    
    1902
    -          blue  = edge2->blue_edge;
    
    1903
    -          edge1 = edge2;
    
    1904
    -          edge2 = edge;
    
    1905
    -        }
    
    1906
    -
    
    1907
    -        if ( !edge1 )
    
    1908
    -          continue;
    
    1909
    -
    
    1910
    -        FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
    
    1911
    -                    "was (%.2f)\n",
    
    1912
    -                    edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
    
    1913
    -                    edge1->pos / 64.0 ));
    
    1914
    -
    
    1915
    -        edge1->pos    = blue->fit;
    
    1916
    -        edge1->flags |= AF_EDGE_DONE;
    
    1917
    -
    
    1918
    -        if ( edge2 && !edge2->blue_edge )
    
    1919
    -        {
    
    1920
    -          af_latin2_align_linked_edge( hints, dim, edge1, edge2 );
    
    1921
    -          edge2->flags |= AF_EDGE_DONE;
    
    1922
    -        }
    
    1923
    -
    
    1924
    -        if ( !anchor )
    
    1925
    -        {
    
    1926
    -          anchor = edge;
    
    1927
    -
    
    1928
    -          anchor_drift = ( anchor->pos - anchor->opos );
    
    1929
    -          if ( edge2 )
    
    1930
    -            anchor_drift = ( anchor_drift +
    
    1931
    -                             ( edge2->pos - edge2->opos ) ) >> 1;
    
    1932
    -        }
    
    1933
    -      }
    
    1934
    -    }
    
    1935
    -
    
    1936
    -    /* now we will align all stem edges, trying to maintain the */
    
    1937
    -    /* relative order of stems in the glyph                     */
    
    1938
    -    for ( edge = edges; edge < edge_limit; edge++ )
    
    1939
    -    {
    
    1940
    -      AF_Edge  edge2;
    
    1941
    -
    
    1942
    -
    
    1943
    -      if ( edge->flags & AF_EDGE_DONE )
    
    1944
    -        continue;
    
    1945
    -
    
    1946
    -      /* skip all non-stem edges */
    
    1947
    -      edge2 = edge->link;
    
    1948
    -      if ( !edge2 )
    
    1949
    -      {
    
    1950
    -        has_serifs++;
    
    1951
    -        continue;
    
    1952
    -      }
    
    1953
    -
    
    1954
    -      /* now align the stem */
    
    1955
    -
    
    1956
    -      /* this should not happen, but it's better to be safe */
    
    1957
    -      if ( edge2->blue_edge )
    
    1958
    -      {
    
    1959
    -        FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
    
    1960
    -
    
    1961
    -        af_latin2_align_linked_edge( hints, dim, edge2, edge );
    
    1962
    -        edge->flags |= AF_EDGE_DONE;
    
    1963
    -        continue;
    
    1964
    -      }
    
    1965
    -
    
    1966
    -      if ( !anchor )
    
    1967
    -      {
    
    1968
    -        FT_Pos  org_len, org_center, cur_len;
    
    1969
    -        FT_Pos  cur_pos1, error1, error2, u_off, d_off;
    
    1970
    -
    
    1971
    -
    
    1972
    -        org_len = edge2->opos - edge->opos;
    
    1973
    -        cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
    
    1974
    -                                                edge->flags,
    
    1975
    -                                                edge2->flags );
    
    1976
    -        if ( cur_len <= 64 )
    
    1977
    -          u_off = d_off = 32;
    
    1978
    -        else
    
    1979
    -        {
    
    1980
    -          u_off = 38;
    
    1981
    -          d_off = 26;
    
    1982
    -        }
    
    1983
    -
    
    1984
    -        if ( cur_len < 96 )
    
    1985
    -        {
    
    1986
    -          org_center = edge->opos + ( org_len >> 1 );
    
    1987
    -
    
    1988
    -          cur_pos1   = FT_PIX_ROUND( org_center );
    
    1989
    -
    
    1990
    -          error1 = org_center - ( cur_pos1 - u_off );
    
    1991
    -          if ( error1 < 0 )
    
    1992
    -            error1 = -error1;
    
    1993
    -
    
    1994
    -          error2 = org_center - ( cur_pos1 + d_off );
    
    1995
    -          if ( error2 < 0 )
    
    1996
    -            error2 = -error2;
    
    1997
    -
    
    1998
    -          if ( error1 < error2 )
    
    1999
    -            cur_pos1 -= u_off;
    
    2000
    -          else
    
    2001
    -            cur_pos1 += d_off;
    
    2002
    -
    
    2003
    -          edge->pos  = cur_pos1 - cur_len / 2;
    
    2004
    -          edge2->pos = edge->pos + cur_len;
    
    2005
    -        }
    
    2006
    -        else
    
    2007
    -          edge->pos = FT_PIX_ROUND( edge->opos );
    
    2008
    -
    
    2009
    -        FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
    
    2010
    -                    " snapped to (%.2f) (%.2f)\n",
    
    2011
    -                    edge-edges, edge->opos / 64.0,
    
    2012
    -                    edge2-edges, edge2->opos / 64.0,
    
    2013
    -                    edge->pos / 64.0, edge2->pos / 64.0 ));
    
    2014
    -        anchor = edge;
    
    2015
    -
    
    2016
    -        edge->flags |= AF_EDGE_DONE;
    
    2017
    -
    
    2018
    -        af_latin2_align_linked_edge( hints, dim, edge, edge2 );
    
    2019
    -
    
    2020
    -        edge2->flags |= AF_EDGE_DONE;
    
    2021
    -
    
    2022
    -        anchor_drift = ( ( anchor->pos - anchor->opos ) +
    
    2023
    -                         ( edge2->pos - edge2->opos ) ) >> 1;
    
    2024
    -
    
    2025
    -        FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
    
    2026
    -      }
    
    2027
    -      else
    
    2028
    -      {
    
    2029
    -        FT_Pos   org_pos, org_len, org_center, cur_center, cur_len;
    
    2030
    -        FT_Pos   org_left, org_right;
    
    2031
    -
    
    2032
    -
    
    2033
    -        org_pos    = edge->opos + anchor_drift;
    
    2034
    -        org_len    = edge2->opos - edge->opos;
    
    2035
    -        org_center = org_pos + ( org_len >> 1 );
    
    2036
    -
    
    2037
    -        cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
    
    2038
    -                                                edge->flags,
    
    2039
    -                                                edge2->flags );
    
    2040
    -
    
    2041
    -        org_left  = org_pos + ( ( org_len - cur_len ) >> 1 );
    
    2042
    -        org_right = org_pos + ( ( org_len + cur_len ) >> 1 );
    
    2043
    -
    
    2044
    -        FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
    
    2045
    -                    org_left / 64.0, org_right / 64.0 ));
    
    2046
    -        cur_center = org_center;
    
    2047
    -
    
    2048
    -        if ( edge2->flags & AF_EDGE_DONE )
    
    2049
    -        {
    
    2050
    -          FT_TRACE5(( "\n" ));
    
    2051
    -          edge->pos = edge2->pos - cur_len;
    
    2052
    -        }
    
    2053
    -        else
    
    2054
    -        {
    
    2055
    -         /* we want to compare several displacement, and choose
    
    2056
    -          * the one that increases fitness while minimizing
    
    2057
    -          * distortion as well
    
    2058
    -          */
    
    2059
    -          FT_Pos   displacements[6], scores[6], org, fit, delta;
    
    2060
    -          FT_UInt  count = 0;
    
    2061
    -
    
    2062
    -          /* note: don't even try to fit tiny stems */
    
    2063
    -          if ( cur_len < 32 )
    
    2064
    -          {
    
    2065
    -            FT_TRACE5(( "tiny stem\n" ));
    
    2066
    -            goto AlignStem;
    
    2067
    -          }
    
    2068
    -
    
    2069
    -          /* if the span is within a single pixel, don't touch it */
    
    2070
    -          if ( FT_PIX_FLOOR( org_left ) == FT_PIX_CEIL( org_right ) )
    
    2071
    -          {
    
    2072
    -            FT_TRACE5(( "single pixel stem\n" ));
    
    2073
    -            goto AlignStem;
    
    2074
    -          }
    
    2075
    -
    
    2076
    -          if ( cur_len <= 96 )
    
    2077
    -          {
    
    2078
    -           /* we want to avoid the absolute worst case which is
    
    2079
    -            * when the left and right edges of the span each represent
    
    2080
    -            * about 50% of the gray. we'd better want to change this
    
    2081
    -            * to 25/75%, since this is much more pleasant to the eye with
    
    2082
    -            * very acceptable distortion
    
    2083
    -            */
    
    2084
    -            FT_Pos  frac_left  = org_left  & 63;
    
    2085
    -            FT_Pos  frac_right = org_right & 63;
    
    2086
    -
    
    2087
    -            if ( frac_left  >= 22 && frac_left  <= 42 &&
    
    2088
    -                 frac_right >= 22 && frac_right <= 42 )
    
    2089
    -            {
    
    2090
    -              org = frac_left;
    
    2091
    -              fit = ( org <= 32 ) ? 16 : 48;
    
    2092
    -              delta = FT_ABS( fit - org );
    
    2093
    -              displacements[count] = fit - org;
    
    2094
    -              scores[count++]      = delta;
    
    2095
    -              FT_TRACE5(( "dispA=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
    
    2096
    -
    
    2097
    -              org = frac_right;
    
    2098
    -              fit = ( org <= 32 ) ? 16 : 48;
    
    2099
    -              delta = FT_ABS( fit - org );
    
    2100
    -              displacements[count] = fit - org;
    
    2101
    -              scores[count++]     = delta;
    
    2102
    -              FT_TRACE5(( "dispB=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
    
    2103
    -            }
    
    2104
    -          }
    
    2105
    -
    
    2106
    -          /* snapping the left edge to the grid */
    
    2107
    -          org   = org_left;
    
    2108
    -          fit   = FT_PIX_ROUND( org );
    
    2109
    -          delta = FT_ABS( fit - org );
    
    2110
    -          displacements[count] = fit - org;
    
    2111
    -          scores[count++]      = delta;
    
    2112
    -          FT_TRACE5(( "dispC=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
    
    2113
    -
    
    2114
    -          /* snapping the right edge to the grid */
    
    2115
    -          org   = org_right;
    
    2116
    -          fit   = FT_PIX_ROUND( org );
    
    2117
    -          delta = FT_ABS( fit - org );
    
    2118
    -          displacements[count] = fit - org;
    
    2119
    -          scores[count++]      = delta;
    
    2120
    -          FT_TRACE5(( "dispD=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
    
    2121
    -
    
    2122
    -          /* now find the best displacement */
    
    2123
    -          {
    
    2124
    -            FT_Pos  best_score = scores[0];
    
    2125
    -            FT_Pos  best_disp  = displacements[0];
    
    2126
    -            FT_UInt nn;
    
    2127
    -
    
    2128
    -            for ( nn = 1; nn < count; nn++ )
    
    2129
    -            {
    
    2130
    -              if ( scores[nn] < best_score )
    
    2131
    -              {
    
    2132
    -                best_score = scores[nn];
    
    2133
    -                best_disp  = displacements[nn];
    
    2134
    -              }
    
    2135
    -            }
    
    2136
    -
    
    2137
    -            cur_center = org_center + best_disp;
    
    2138
    -          }
    
    2139
    -          FT_TRACE5(( "\n" ));
    
    2140
    -        }
    
    2141
    -
    
    2142
    -      AlignStem:
    
    2143
    -        edge->pos  = cur_center - ( cur_len >> 1 );
    
    2144
    -        edge2->pos = edge->pos + cur_len;
    
    2145
    -
    
    2146
    -        FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
    
    2147
    -                    " snapped to (%.2f) and (%.2f),"
    
    2148
    -                    " org_len=%.2f cur_len=%.2f\n",
    
    2149
    -                    edge-edges, edge->opos / 64.0,
    
    2150
    -                    edge2-edges, edge2->opos / 64.0,
    
    2151
    -                    edge->pos / 64.0, edge2->pos / 64.0,
    
    2152
    -                    org_len / 64.0, cur_len / 64.0 ));
    
    2153
    -
    
    2154
    -        edge->flags  |= AF_EDGE_DONE;
    
    2155
    -        edge2->flags |= AF_EDGE_DONE;
    
    2156
    -
    
    2157
    -        if ( edge > edges && edge->pos < edge[-1].pos )
    
    2158
    -        {
    
    2159
    -          FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
    
    2160
    -                      edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
    
    2161
    -          edge->pos = edge[-1].pos;
    
    2162
    -        }
    
    2163
    -      }
    
    2164
    -    }
    
    2165
    -
    
    2166
    -    /* make sure that lowercase m's maintain their symmetry */
    
    2167
    -
    
    2168
    -    /* In general, lowercase m's have six vertical edges if they are sans */
    
    2169
    -    /* serif, or twelve if they are with serifs.  This implementation is  */
    
    2170
    -    /* based on that assumption, and seems to work very well with most    */
    
    2171
    -    /* faces.  However, if for a certain face this assumption is not      */
    
    2172
    -    /* true, the m is just rendered like before.  In addition, any stem   */
    
    2173
    -    /* correction will only be applied to symmetrical glyphs (even if the */
    
    2174
    -    /* glyph is not an m), so the potential for unwanted distortion is    */
    
    2175
    -    /* relatively low.                                                    */
    
    2176
    -
    
    2177
    -    /* We don't handle horizontal edges since we can't easily assure that */
    
    2178
    -    /* the third (lowest) stem aligns with the base line; it might end up */
    
    2179
    -    /* one pixel higher or lower.                                         */
    
    2180
    -
    
    2181
    -#if 0
    
    2182
    -    {
    
    2183
    -      FT_Int  n_edges = edge_limit - edges;
    
    2184
    -
    
    2185
    -
    
    2186
    -      if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
    
    2187
    -      {
    
    2188
    -        AF_Edge  edge1, edge2, edge3;
    
    2189
    -        FT_Pos   dist1, dist2, span, delta;
    
    2190
    -
    
    2191
    -
    
    2192
    -        if ( n_edges == 6 )
    
    2193
    -        {
    
    2194
    -          edge1 = edges;
    
    2195
    -          edge2 = edges + 2;
    
    2196
    -          edge3 = edges + 4;
    
    2197
    -        }
    
    2198
    -        else
    
    2199
    -        {
    
    2200
    -          edge1 = edges + 1;
    
    2201
    -          edge2 = edges + 5;
    
    2202
    -          edge3 = edges + 9;
    
    2203
    -        }
    
    2204
    -
    
    2205
    -        dist1 = edge2->opos - edge1->opos;
    
    2206
    -        dist2 = edge3->opos - edge2->opos;
    
    2207
    -
    
    2208
    -        span = dist1 - dist2;
    
    2209
    -        if ( span < 0 )
    
    2210
    -          span = -span;
    
    2211
    -
    
    2212
    -        if ( span < 8 )
    
    2213
    -        {
    
    2214
    -          delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
    
    2215
    -          edge3->pos -= delta;
    
    2216
    -          if ( edge3->link )
    
    2217
    -            edge3->link->pos -= delta;
    
    2218
    -
    
    2219
    -          /* move the serifs along with the stem */
    
    2220
    -          if ( n_edges == 12 )
    
    2221
    -          {
    
    2222
    -            ( edges + 8 )->pos -= delta;
    
    2223
    -            ( edges + 11 )->pos -= delta;
    
    2224
    -          }
    
    2225
    -
    
    2226
    -          edge3->flags |= AF_EDGE_DONE;
    
    2227
    -          if ( edge3->link )
    
    2228
    -            edge3->link->flags |= AF_EDGE_DONE;
    
    2229
    -        }
    
    2230
    -      }
    
    2231
    -    }
    
    2232
    -#endif
    
    2233
    -
    
    2234
    -    if ( has_serifs || !anchor )
    
    2235
    -    {
    
    2236
    -      /*
    
    2237
    -       * now hint the remaining edges (serifs and single) in order
    
    2238
    -       * to complete our processing
    
    2239
    -       */
    
    2240
    -      for ( edge = edges; edge < edge_limit; edge++ )
    
    2241
    -      {
    
    2242
    -        FT_Pos  delta;
    
    2243
    -
    
    2244
    -
    
    2245
    -        if ( edge->flags & AF_EDGE_DONE )
    
    2246
    -          continue;
    
    2247
    -
    
    2248
    -        delta = 1000;
    
    2249
    -
    
    2250
    -        if ( edge->serif )
    
    2251
    -        {
    
    2252
    -          delta = edge->serif->opos - edge->opos;
    
    2253
    -          if ( delta < 0 )
    
    2254
    -            delta = -delta;
    
    2255
    -        }
    
    2256
    -
    
    2257
    -        if ( delta < 64 + 16 )
    
    2258
    -        {
    
    2259
    -          af_latin2_align_serif_edge( hints, edge->serif, edge );
    
    2260
    -          FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
    
    2261
    -                      " aligned to (%.2f)\n",
    
    2262
    -                      edge-edges, edge->opos / 64.0,
    
    2263
    -                      edge->serif - edges, edge->serif->opos / 64.0,
    
    2264
    -                      edge->pos / 64.0 ));
    
    2265
    -        }
    
    2266
    -        else if ( !anchor )
    
    2267
    -        {
    
    2268
    -          FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)"
    
    2269
    -                      " snapped to (%.2f)\n",
    
    2270
    -                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
    
    2271
    -          edge->pos = FT_PIX_ROUND( edge->opos );
    
    2272
    -          anchor    = edge;
    
    2273
    -        }
    
    2274
    -        else
    
    2275
    -        {
    
    2276
    -          AF_Edge  before, after;
    
    2277
    -
    
    2278
    -
    
    2279
    -          for ( before = edge - 1; before >= edges; before-- )
    
    2280
    -            if ( before->flags & AF_EDGE_DONE )
    
    2281
    -              break;
    
    2282
    -
    
    2283
    -          for ( after = edge + 1; after < edge_limit; after++ )
    
    2284
    -            if ( after->flags & AF_EDGE_DONE )
    
    2285
    -              break;
    
    2286
    -
    
    2287
    -          if ( before >= edges && before < edge   &&
    
    2288
    -               after < edge_limit && after > edge )
    
    2289
    -          {
    
    2290
    -            if ( after->opos == before->opos )
    
    2291
    -              edge->pos = before->pos;
    
    2292
    -            else
    
    2293
    -              edge->pos = before->pos +
    
    2294
    -                          FT_MulDiv( edge->opos - before->opos,
    
    2295
    -                                     after->pos - before->pos,
    
    2296
    -                                     after->opos - before->opos );
    
    2297
    -            FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
    
    2298
    -                        " from %d (opos=%.2f)\n",
    
    2299
    -                        edge-edges, edge->opos / 64.0, edge->pos / 64.0,
    
    2300
    -                        before - edges, before->opos / 64.0 ));
    
    2301
    -          }
    
    2302
    -          else
    
    2303
    -          {
    
    2304
    -            edge->pos = anchor->pos +
    
    2305
    -                        ( ( edge->opos - anchor->opos + 16 ) & ~31 );
    
    2306
    -
    
    2307
    -            FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)"
    
    2308
    -                        " snapped to (%.2f)\n",
    
    2309
    -                        edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
    
    2310
    -          }
    
    2311
    -        }
    
    2312
    -
    
    2313
    -        edge->flags |= AF_EDGE_DONE;
    
    2314
    -
    
    2315
    -        if ( edge > edges && edge->pos < edge[-1].pos )
    
    2316
    -          edge->pos = edge[-1].pos;
    
    2317
    -
    
    2318
    -        if ( edge + 1 < edge_limit        &&
    
    2319
    -             edge[1].flags & AF_EDGE_DONE &&
    
    2320
    -             edge->pos > edge[1].pos      )
    
    2321
    -          edge->pos = edge[1].pos;
    
    2322
    -      }
    
    2323
    -    }
    
    2324
    -  }
    
    2325
    -
    
    2326
    -
    
    2327
    -  static FT_Error
    
    2328
    -  af_latin2_hints_apply( FT_UInt          glyph_index,
    
    2329
    -                         AF_GlyphHints    hints,
    
    2330
    -                         FT_Outline*      outline,
    
    2331
    -                         AF_LatinMetrics  metrics )
    
    2332
    -  {
    
    2333
    -    FT_Error  error;
    
    2334
    -    int       dim;
    
    2335
    -
    
    2336
    -    FT_UNUSED( glyph_index );
    
    2337
    -
    
    2338
    -
    
    2339
    -    error = af_glyph_hints_reload( hints, outline );
    
    2340
    -    if ( error )
    
    2341
    -      goto Exit;
    
    2342
    -
    
    2343
    -    /* analyze glyph outline */
    
    2344
    -    if ( AF_HINTS_DO_HORIZONTAL( hints ) )
    
    2345
    -    {
    
    2346
    -      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ );
    
    2347
    -      if ( error )
    
    2348
    -        goto Exit;
    
    2349
    -    }
    
    2350
    -
    
    2351
    -    if ( AF_HINTS_DO_VERTICAL( hints ) )
    
    2352
    -    {
    
    2353
    -      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT );
    
    2354
    -      if ( error )
    
    2355
    -        goto Exit;
    
    2356
    -
    
    2357
    -      af_latin2_hints_compute_blue_edges( hints, metrics );
    
    2358
    -    }
    
    2359
    -
    
    2360
    -    /* grid-fit the outline */
    
    2361
    -    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
    
    2362
    -    {
    
    2363
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    2364
    -      if ( dim == AF_DIMENSION_HORZ                                  &&
    
    2365
    -           metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
    
    2366
    -           AF_HINTS_DO_WARP( hints )                                 )
    
    2367
    -      {
    
    2368
    -        AF_WarperRec  warper;
    
    2369
    -        FT_Fixed      scale;
    
    2370
    -        FT_Pos        delta;
    
    2371
    -
    
    2372
    -
    
    2373
    -        af_warper_compute( &warper, hints, dim, &scale, &delta );
    
    2374
    -        af_glyph_hints_scale_dim( hints, dim, scale, delta );
    
    2375
    -        continue;
    
    2376
    -      }
    
    2377
    -#endif /* AF_CONFIG_OPTION_USE_WARPER */
    
    2378
    -
    
    2379
    -      if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
    
    2380
    -           ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
    
    2381
    -      {
    
    2382
    -        af_latin2_hint_edges( hints, (AF_Dimension)dim );
    
    2383
    -        af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
    
    2384
    -        af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
    
    2385
    -        af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
    
    2386
    -      }
    
    2387
    -    }
    
    2388
    -    af_glyph_hints_save( hints, outline );
    
    2389
    -
    
    2390
    -  Exit:
    
    2391
    -    return error;
    
    2392
    -  }
    
    2393
    -
    
    2394
    -
    
    2395
    -  /*************************************************************************/
    
    2396
    -  /*************************************************************************/
    
    2397
    -  /*****                                                               *****/
    
    2398
    -  /*****              L A T I N   S C R I P T   C L A S S              *****/
    
    2399
    -  /*****                                                               *****/
    
    2400
    -  /*************************************************************************/
    
    2401
    -  /*************************************************************************/
    
    2402
    -
    
    2403
    -
    
    2404
    -  AF_DEFINE_WRITING_SYSTEM_CLASS(
    
    2405
    -    af_latin2_writing_system_class,
    
    2406
    -
    
    2407
    -    AF_WRITING_SYSTEM_LATIN2,
    
    2408
    -
    
    2409
    -    sizeof ( AF_LatinMetricsRec ),
    
    2410
    -
    
    2411
    -    (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init,        /* style_metrics_init    */
    
    2412
    -    (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale,       /* style_metrics_scale   */
    
    2413
    -    (AF_WritingSystem_DoneMetricsFunc) NULL,                          /* style_metrics_done    */
    
    2414
    -    (AF_WritingSystem_GetStdWidthsFunc)af_latin2_get_standard_widths, /* style_metrics_getstdw */
    
    2415
    -
    
    2416
    -    (AF_WritingSystem_InitHintsFunc)   af_latin2_hints_init,          /* style_hints_init      */
    
    2417
    -    (AF_WritingSystem_ApplyHintsFunc)  af_latin2_hints_apply          /* style_hints_apply     */
    
    2418
    -  )
    
    2419
    -
    
    2420
    -#else /* !FT_OPTION_AUTOFIT2 */
    
    2421
    -
    
    2422
    -  /* ANSI C doesn't like empty source files */
    
    2423
    -  typedef int  _af_latin2_dummy;
    
    2424
    -
    
    2425
    -#endif /* !FT_OPTION_AUTOFIT2 */
    
    2426
    -
    
    2427
    -
    
    2428
    -/* END */

  • src/autofit/aflatin2.h deleted
    1
    -/* ATTENTION: This file doesn't compile.  It is only here as a reference */
    
    2
    -/*            of an alternative latin hinting algorithm that was always  */
    
    3
    -/*            marked as experimental.                                    */
    
    4
    -
    
    5
    -
    
    6
    -/****************************************************************************
    
    7
    - *
    
    8
    - * aflatin2.h
    
    9
    - *
    
    10
    - *   Auto-fitter hinting routines for latin writing system
    
    11
    - *   (specification).
    
    12
    - *
    
    13
    - * Copyright (C) 2003-2021 by
    
    14
    - * David Turner, Robert Wilhelm, and Werner Lemberg.
    
    15
    - *
    
    16
    - * This file is part of the FreeType project, and may only be used,
    
    17
    - * modified, and distributed under the terms of the FreeType project
    
    18
    - * license, LICENSE.TXT.  By continuing to use, modify, or distribute
    
    19
    - * this file you indicate that you have read the license and
    
    20
    - * understand and accept it fully.
    
    21
    - *
    
    22
    - */
    
    23
    -
    
    24
    -
    
    25
    -#ifndef AFLATIN2_H_
    
    26
    -#define AFLATIN2_H_
    
    27
    -
    
    28
    -#include "afhints.h"
    
    29
    -
    
    30
    -
    
    31
    -FT_BEGIN_HEADER
    
    32
    -
    
    33
    -
    
    34
    -  /* the `latin' writing system */
    
    35
    -
    
    36
    -  AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin2_writing_system_class )
    
    37
    -
    
    38
    -
    
    39
    -/* */
    
    40
    -
    
    41
    -FT_END_HEADER
    
    42
    -
    
    43
    -#endif /* AFLATIN_H_ */
    
    44
    -
    
    45
    -
    
    46
    -/* END */

  • src/autofit/afloader.c
    ... ... @@ -297,12 +297,6 @@
    297 297
         if ( error )
    
    298 298
           goto Exit;
    
    299 299
     
    
    300
    -#ifdef FT_OPTION_AUTOFIT2
    
    301
    -    /* XXX: undocumented hook to activate the latin2 writing system. */
    
    302
    -    if ( load_flags & ( 1UL << 20 ) )
    
    303
    -      style_options = AF_STYLE_LTN2_DFLT;
    
    304
    -#endif
    
    305
    -
    
    306 300
         /*
    
    307 301
          * Glyphs (really code points) are assigned to scripts.  Script
    
    308 302
          * analysis is done lazily: For each glyph that passes through here,
    

  • src/autofit/afmodule.c
    ... ... @@ -190,35 +190,6 @@
    190 190
     
    
    191 191
           return error;
    
    192 192
         }
    
    193
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    194
    -    else if ( !ft_strcmp( property_name, "warping" ) )
    
    195
    -    {
    
    196
    -#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
    
    197
    -      if ( value_is_string )
    
    198
    -      {
    
    199
    -        const char*  s = (const char*)value;
    
    200
    -        long         w = ft_strtol( s, NULL, 10 );
    
    201
    -
    
    202
    -
    
    203
    -        if ( w == 0 )
    
    204
    -          module->warping = 0;
    
    205
    -        else if ( w == 1 )
    
    206
    -          module->warping = 1;
    
    207
    -        else
    
    208
    -          return FT_THROW( Invalid_Argument );
    
    209
    -      }
    
    210
    -      else
    
    211
    -#endif
    
    212
    -      {
    
    213
    -        FT_Bool*  warping = (FT_Bool*)value;
    
    214
    -
    
    215
    -
    
    216
    -        module->warping = *warping;
    
    217
    -      }
    
    218
    -
    
    219
    -      return error;
    
    220
    -    }
    
    221
    -#endif /* AF_CONFIG_OPTION_USE_WARPER */
    
    222 193
         else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
    
    223 194
         {
    
    224 195
           FT_Int*  darken_params;
    
    ... ... @@ -322,9 +293,6 @@
    322 293
         AF_Module  module         = (AF_Module)ft_module;
    
    323 294
         FT_UInt    fallback_style = module->fallback_style;
    
    324 295
         FT_UInt    default_script = module->default_script;
    
    325
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    326
    -    FT_Bool    warping        = module->warping;
    
    327
    -#endif
    
    328 296
     
    
    329 297
     
    
    330 298
         if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
    
    ... ... @@ -371,17 +339,6 @@
    371 339
     
    
    372 340
           return error;
    
    373 341
         }
    
    374
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    375
    -    else if ( !ft_strcmp( property_name, "warping" ) )
    
    376
    -    {
    
    377
    -      FT_Bool*  val = (FT_Bool*)value;
    
    378
    -
    
    379
    -
    
    380
    -      *val = warping;
    
    381
    -
    
    382
    -      return error;
    
    383
    -    }
    
    384
    -#endif /* AF_CONFIG_OPTION_USE_WARPER */
    
    385 342
         else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
    
    386 343
         {
    
    387 344
           FT_Int*  darken_params = module->darken_params;
    
    ... ... @@ -447,9 +404,6 @@
    447 404
     
    
    448 405
         module->fallback_style    = AF_STYLE_FALLBACK;
    
    449 406
         module->default_script    = AF_SCRIPT_DEFAULT;
    
    450
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    451
    -    module->warping           = 0;
    
    452
    -#endif
    
    453 407
         module->no_stem_darkening = TRUE;
    
    454 408
     
    
    455 409
         module->darken_params[0]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
    

  • src/autofit/afmodule.h
    ... ... @@ -37,9 +37,6 @@ FT_BEGIN_HEADER
    37 37
     
    
    38 38
         FT_UInt       fallback_style;
    
    39 39
         FT_UInt       default_script;
    
    40
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    41
    -    FT_Bool       warping;
    
    42
    -#endif
    
    43 40
         FT_Bool       no_stem_darkening;
    
    44 41
         FT_Int        darken_params[8];
    
    45 42
     
    

  • src/autofit/afstyles.h
    ... ... @@ -299,15 +299,6 @@
    299 299
              AF_BLUE_STRINGSET_LATP,
    
    300 300
              AF_COVERAGE_DEFAULT )
    
    301 301
     
    
    302
    -#ifdef FT_OPTION_AUTOFIT2
    
    303
    -  STYLE( ltn2_dflt, LTN2_DFLT,
    
    304
    -         "Latin 2 default style",
    
    305
    -         AF_WRITING_SYSTEM_LATIN2,
    
    306
    -         AF_SCRIPT_LATN,
    
    307
    -         AF_BLUE_STRINGSET_LATN,
    
    308
    -         AF_COVERAGE_DEFAULT )
    
    309
    -#endif
    
    310
    -
    
    311 302
       STYLE( lisu_dflt, LISU_DFLT,
    
    312 303
              "Lisu default style",
    
    313 304
              AF_WRITING_SYSTEM_LATIN,
    

  • src/autofit/aftypes.h
    ... ... @@ -92,63 +92,6 @@ extern void* _af_debug_hints;
    92 92
                                    FT_Pos    threshold );
    
    93 93
     
    
    94 94
     
    
    95
    -  /*************************************************************************/
    
    96
    -  /*************************************************************************/
    
    97
    -  /*****                                                               *****/
    
    98
    -  /*****                   A N G L E   T Y P E S                       *****/
    
    99
    -  /*****                                                               *****/
    
    100
    -  /*************************************************************************/
    
    101
    -  /*************************************************************************/
    
    102
    -
    
    103
    -  /*
    
    104
    -   * The auto-fitter doesn't need a very high angular accuracy;
    
    105
    -   * this allows us to speed up some computations considerably with a
    
    106
    -   * light Cordic algorithm (see afangles.c).
    
    107
    -   */
    
    108
    -
    
    109
    -  typedef FT_Int  AF_Angle;
    
    110
    -
    
    111
    -
    
    112
    -#define AF_ANGLE_PI   256
    
    113
    -#define AF_ANGLE_2PI  ( AF_ANGLE_PI * 2 )
    
    114
    -#define AF_ANGLE_PI2  ( AF_ANGLE_PI / 2 )
    
    115
    -#define AF_ANGLE_PI4  ( AF_ANGLE_PI / 4 )
    
    116
    -
    
    117
    -
    
    118
    -#if 0
    
    119
    -  /*
    
    120
    -   * compute the angle of a given 2-D vector
    
    121
    -   */
    
    122
    -  FT_LOCAL( AF_Angle )
    
    123
    -  af_angle_atan( FT_Pos  dx,
    
    124
    -                 FT_Pos  dy );
    
    125
    -
    
    126
    -
    
    127
    -  /*
    
    128
    -   * compute `angle2 - angle1'; the result is always within
    
    129
    -   * the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
    
    130
    -   */
    
    131
    -  FT_LOCAL( AF_Angle )
    
    132
    -  af_angle_diff( AF_Angle  angle1,
    
    133
    -                 AF_Angle  angle2 );
    
    134
    -#endif /* 0 */
    
    135
    -
    
    136
    -
    
    137
    -#define AF_ANGLE_DIFF( result, angle1, angle2 ) \
    
    138
    -  FT_BEGIN_STMNT                                \
    
    139
    -    AF_Angle  _delta = (angle2) - (angle1);     \
    
    140
    -                                                \
    
    141
    -                                                \
    
    142
    -    while ( _delta <= -AF_ANGLE_PI )            \
    
    143
    -      _delta += AF_ANGLE_2PI;                   \
    
    144
    -                                                \
    
    145
    -    while ( _delta > AF_ANGLE_PI )              \
    
    146
    -      _delta -= AF_ANGLE_2PI;                   \
    
    147
    -                                                \
    
    148
    -    result = _delta;                            \
    
    149
    -  FT_END_STMNT
    
    150
    -
    
    151
    -
    
    152 95
       /*
    
    153 96
        * opaque handle to glyph-specific hints -- see `afhints.h' for more
    
    154 97
        * details
    
    ... ... @@ -172,7 +115,6 @@ extern void* _af_debug_hints;
    172 115
     #define AF_SCALER_FLAG_NO_HORIZONTAL  1U /* disable horizontal hinting */
    
    173 116
     #define AF_SCALER_FLAG_NO_VERTICAL    2U /* disable vertical hinting   */
    
    174 117
     #define AF_SCALER_FLAG_NO_ADVANCE     4U /* disable advance hinting    */
    
    175
    -#define AF_SCALER_FLAG_NO_WARPER      8U /* disable warper             */
    
    176 118
     
    
    177 119
     
    
    178 120
       typedef struct  AF_ScalerRec_
    

  • src/autofit/afwarp.c deleted
    1
    -/****************************************************************************
    
    2
    - *
    
    3
    - * afwarp.c
    
    4
    - *
    
    5
    - *   Auto-fitter warping algorithm (body).
    
    6
    - *
    
    7
    - * Copyright (C) 2006-2021 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
    -  /*
    
    20
    -   * The idea of the warping code is to slightly scale and shift a glyph
    
    21
    -   * within a single dimension so that as much of its segments are aligned
    
    22
    -   * (more or less) on the grid.  To find out the optimal scaling and
    
    23
    -   * shifting value, various parameter combinations are tried and scored.
    
    24
    -   */
    
    25
    -
    
    26
    -#include "afwarp.h"
    
    27
    -
    
    28
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    29
    -
    
    30
    -  /**************************************************************************
    
    31
    -   *
    
    32
    -   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
    
    33
    -   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
    
    34
    -   * messages during execution.
    
    35
    -   */
    
    36
    -#undef  FT_COMPONENT
    
    37
    -#define FT_COMPONENT  afwarp
    
    38
    -
    
    39
    -
    
    40
    -  /* The weights cover the range 0/64 - 63/64 of a pixel.  Obviously, */
    
    41
    -  /* values around a half pixel (which means exactly between two grid */
    
    42
    -  /* lines) gets the worst weight.                                    */
    
    43
    -#if 1
    
    44
    -  static const AF_WarpScore
    
    45
    -  af_warper_weights[64] =
    
    46
    -  {
    
    47
    -    35, 32, 30, 25, 20, 15, 12, 10,  5,  1,  0,  0,  0,  0,  0,  0,
    
    48
    -     0,  0,  0,  0,  0,  0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30,
    
    49
    -
    
    50
    -   -30,-30,-20,-20,-10,-10, -8, -5, -2, -1,  0,  0,  0,  0,  0,  0,
    
    51
    -     0,  0,  0,  0,  0,  0,  0,  1,  5, 10, 12, 15, 20, 25, 30, 32,
    
    52
    -  };
    
    53
    -#else
    
    54
    -  static const AF_WarpScore
    
    55
    -  af_warper_weights[64] =
    
    56
    -  {
    
    57
    -    30, 20, 10,  5,  4,  4,  3,  2,  1,  0,  0,  0,  0,  0,  0,  0,
    
    58
    -     0,  0,  0,  0,  0,  0,  0, -1, -2, -2, -5, -5,-10,-10,-15,-20,
    
    59
    -
    
    60
    -   -20,-15,-15,-10,-10, -5, -5, -2, -2, -1,  0,  0,  0,  0,  0,  0,
    
    61
    -     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  4,  5, 10, 20,
    
    62
    -  };
    
    63
    -#endif
    
    64
    -
    
    65
    -
    
    66
    -  /* Score segments for a given `scale' and `delta' in the range */
    
    67
    -  /* `xx1' to `xx2', and store the best result in `warper'.  If  */
    
    68
    -  /* the new best score is equal to the old one, prefer the      */
    
    69
    -  /* value with a smaller distortion (around `base_distort').    */
    
    70
    -
    
    71
    -  static void
    
    72
    -  af_warper_compute_line_best( AF_Warper     warper,
    
    73
    -                               FT_Fixed      scale,
    
    74
    -                               FT_Pos        delta,
    
    75
    -                               FT_Pos        xx1,
    
    76
    -                               FT_Pos        xx2,
    
    77
    -                               AF_WarpScore  base_distort,
    
    78
    -                               AF_Segment    segments,
    
    79
    -                               FT_Int        num_segments )
    
    80
    -  {
    
    81
    -    FT_Int        idx_min, idx_max, idx0;
    
    82
    -    FT_Int        nn;
    
    83
    -    AF_WarpScore  scores[65];
    
    84
    -
    
    85
    -
    
    86
    -    for ( nn = 0; nn < 65; nn++ )
    
    87
    -      scores[nn] = 0;
    
    88
    -
    
    89
    -    idx0 = xx1 - warper->t1;
    
    90
    -
    
    91
    -    /* compute minimum and maximum indices */
    
    92
    -    {
    
    93
    -      FT_Pos  xx1min = warper->x1min;
    
    94
    -      FT_Pos  xx1max = warper->x1max;
    
    95
    -      FT_Pos  w      = xx2 - xx1;
    
    96
    -
    
    97
    -
    
    98
    -      if ( xx1min + w < warper->x2min )
    
    99
    -        xx1min = warper->x2min - w;
    
    100
    -
    
    101
    -      if ( xx1max + w > warper->x2max )
    
    102
    -        xx1max = warper->x2max - w;
    
    103
    -
    
    104
    -      idx_min = xx1min - warper->t1;
    
    105
    -      idx_max = xx1max - warper->t1;
    
    106
    -
    
    107
    -      if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
    
    108
    -      {
    
    109
    -        FT_TRACE5(( "invalid indices:\n" ));
    
    110
    -        FT_TRACE5(( "  min=%d max=%d, xx1=%ld xx2=%ld,\n",
    
    111
    -                    idx_min, idx_max, xx1, xx2 ));
    
    112
    -        FT_TRACE5(( "  x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
    
    113
    -                    warper->x1min, warper->x1max,
    
    114
    -                    warper->x2min, warper->x2max ));
    
    115
    -        return;
    
    116
    -      }
    
    117
    -    }
    
    118
    -
    
    119
    -    for ( nn = 0; nn < num_segments; nn++ )
    
    120
    -    {
    
    121
    -      FT_Pos  len = segments[nn].max_coord - segments[nn].min_coord;
    
    122
    -      FT_Pos  y0  = FT_MulFix( segments[nn].pos, scale ) + delta;
    
    123
    -      FT_Pos  y   = y0 + ( idx_min - idx0 );
    
    124
    -      FT_Int  idx;
    
    125
    -
    
    126
    -
    
    127
    -      /* score the length of the segments for the given range */
    
    128
    -      for ( idx = idx_min; idx <= idx_max; idx++, y++ )
    
    129
    -        scores[idx] += af_warper_weights[y & 63] * len;
    
    130
    -    }
    
    131
    -
    
    132
    -    /* find best score */
    
    133
    -    {
    
    134
    -      FT_Int  idx;
    
    135
    -
    
    136
    -
    
    137
    -      for ( idx = idx_min; idx <= idx_max; idx++ )
    
    138
    -      {
    
    139
    -        AF_WarpScore  score = scores[idx];
    
    140
    -        AF_WarpScore  distort = base_distort + ( idx - idx0 );
    
    141
    -
    
    142
    -
    
    143
    -        if ( score > warper->best_score         ||
    
    144
    -             ( score == warper->best_score    &&
    
    145
    -               distort < warper->best_distort ) )
    
    146
    -        {
    
    147
    -          warper->best_score   = score;
    
    148
    -          warper->best_distort = distort;
    
    149
    -          warper->best_scale   = scale;
    
    150
    -          warper->best_delta   = delta + ( idx - idx0 );
    
    151
    -        }
    
    152
    -      }
    
    153
    -    }
    
    154
    -  }
    
    155
    -
    
    156
    -
    
    157
    -  /* Compute optimal scaling and delta values for a given glyph and */
    
    158
    -  /* dimension.                                                     */
    
    159
    -
    
    160
    -  FT_LOCAL_DEF( void )
    
    161
    -  af_warper_compute( AF_Warper      warper,
    
    162
    -                     AF_GlyphHints  hints,
    
    163
    -                     AF_Dimension   dim,
    
    164
    -                     FT_Fixed      *a_scale,
    
    165
    -                     FT_Pos        *a_delta )
    
    166
    -  {
    
    167
    -    AF_AxisHints  axis;
    
    168
    -    AF_Point      points;
    
    169
    -
    
    170
    -    FT_Fixed      org_scale;
    
    171
    -    FT_Pos        org_delta;
    
    172
    -
    
    173
    -    FT_Int        nn, num_points, num_segments;
    
    174
    -    FT_Int        X1, X2;
    
    175
    -    FT_Int        w;
    
    176
    -
    
    177
    -    AF_WarpScore  base_distort;
    
    178
    -    AF_Segment    segments;
    
    179
    -
    
    180
    -
    
    181
    -    /* get original scaling transformation */
    
    182
    -    if ( dim == AF_DIMENSION_VERT )
    
    183
    -    {
    
    184
    -      org_scale = hints->y_scale;
    
    185
    -      org_delta = hints->y_delta;
    
    186
    -    }
    
    187
    -    else
    
    188
    -    {
    
    189
    -      org_scale = hints->x_scale;
    
    190
    -      org_delta = hints->x_delta;
    
    191
    -    }
    
    192
    -
    
    193
    -    warper->best_scale   = org_scale;
    
    194
    -    warper->best_delta   = org_delta;
    
    195
    -    warper->best_score   = FT_INT_MIN;
    
    196
    -    warper->best_distort = 0;
    
    197
    -
    
    198
    -    axis         = &hints->axis[dim];
    
    199
    -    segments     = axis->segments;
    
    200
    -    num_segments = axis->num_segments;
    
    201
    -    points       = hints->points;
    
    202
    -    num_points   = hints->num_points;
    
    203
    -
    
    204
    -    *a_scale = org_scale;
    
    205
    -    *a_delta = org_delta;
    
    206
    -
    
    207
    -    /* get X1 and X2, minimum and maximum in original coordinates */
    
    208
    -    if ( num_segments < 1 )
    
    209
    -      return;
    
    210
    -
    
    211
    -#if 1
    
    212
    -    X1 = X2 = points[0].fx;
    
    213
    -    for ( nn = 1; nn < num_points; nn++ )
    
    214
    -    {
    
    215
    -      FT_Int  X = points[nn].fx;
    
    216
    -
    
    217
    -
    
    218
    -      if ( X < X1 )
    
    219
    -        X1 = X;
    
    220
    -      if ( X > X2 )
    
    221
    -        X2 = X;
    
    222
    -    }
    
    223
    -#else
    
    224
    -    X1 = X2 = segments[0].pos;
    
    225
    -    for ( nn = 1; nn < num_segments; nn++ )
    
    226
    -    {
    
    227
    -      FT_Int  X = segments[nn].pos;
    
    228
    -
    
    229
    -
    
    230
    -      if ( X < X1 )
    
    231
    -        X1 = X;
    
    232
    -      if ( X > X2 )
    
    233
    -        X2 = X;
    
    234
    -    }
    
    235
    -#endif
    
    236
    -
    
    237
    -    if ( X1 >= X2 )
    
    238
    -      return;
    
    239
    -
    
    240
    -    warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;
    
    241
    -    warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;
    
    242
    -
    
    243
    -    warper->t1 = AF_WARPER_FLOOR( warper->x1 );
    
    244
    -    warper->t2 = AF_WARPER_CEIL( warper->x2 );
    
    245
    -
    
    246
    -    /* examine a half pixel wide range around the maximum coordinates */
    
    247
    -    warper->x1min = warper->x1 & ~31;
    
    248
    -    warper->x1max = warper->x1min + 32;
    
    249
    -    warper->x2min = warper->x2 & ~31;
    
    250
    -    warper->x2max = warper->x2min + 32;
    
    251
    -
    
    252
    -    if ( warper->x1max > warper->x2 )
    
    253
    -      warper->x1max = warper->x2;
    
    254
    -
    
    255
    -    if ( warper->x2min < warper->x1 )
    
    256
    -      warper->x2min = warper->x1;
    
    257
    -
    
    258
    -    warper->w0 = warper->x2 - warper->x1;
    
    259
    -
    
    260
    -    if ( warper->w0 <= 64 )
    
    261
    -    {
    
    262
    -      warper->x1max = warper->x1;
    
    263
    -      warper->x2min = warper->x2;
    
    264
    -    }
    
    265
    -
    
    266
    -    /* examine (at most) a pixel wide range around the natural width */
    
    267
    -    warper->wmin = warper->x2min - warper->x1max;
    
    268
    -    warper->wmax = warper->x2max - warper->x1min;
    
    269
    -
    
    270
    -#if 1
    
    271
    -    /* some heuristics to reduce the number of widths to be examined */
    
    272
    -    {
    
    273
    -      int  margin = 16;
    
    274
    -
    
    275
    -
    
    276
    -      if ( warper->w0 <= 128 )
    
    277
    -      {
    
    278
    -         margin = 8;
    
    279
    -         if ( warper->w0 <= 96 )
    
    280
    -           margin = 4;
    
    281
    -      }
    
    282
    -
    
    283
    -      if ( warper->wmin < warper->w0 - margin )
    
    284
    -        warper->wmin = warper->w0 - margin;
    
    285
    -
    
    286
    -      if ( warper->wmax > warper->w0 + margin )
    
    287
    -        warper->wmax = warper->w0 + margin;
    
    288
    -    }
    
    289
    -
    
    290
    -    if ( warper->wmin < warper->w0 * 3 / 4 )
    
    291
    -      warper->wmin = warper->w0 * 3 / 4;
    
    292
    -
    
    293
    -    if ( warper->wmax > warper->w0 * 5 / 4 )
    
    294
    -      warper->wmax = warper->w0 * 5 / 4;
    
    295
    -#else
    
    296
    -    /* no scaling, just translation */
    
    297
    -    warper->wmin = warper->wmax = warper->w0;
    
    298
    -#endif
    
    299
    -
    
    300
    -    for ( w = warper->wmin; w <= warper->wmax; w++ )
    
    301
    -    {
    
    302
    -      FT_Fixed  new_scale;
    
    303
    -      FT_Pos    new_delta;
    
    304
    -      FT_Pos    xx1, xx2;
    
    305
    -
    
    306
    -
    
    307
    -      /* compute min and max positions for given width,       */
    
    308
    -      /* assuring that they stay within the coordinate ranges */
    
    309
    -      xx1 = warper->x1;
    
    310
    -      xx2 = warper->x2;
    
    311
    -      if ( w >= warper->w0 )
    
    312
    -      {
    
    313
    -        xx1 -= w - warper->w0;
    
    314
    -        if ( xx1 < warper->x1min )
    
    315
    -        {
    
    316
    -          xx2 += warper->x1min - xx1;
    
    317
    -          xx1  = warper->x1min;
    
    318
    -        }
    
    319
    -      }
    
    320
    -      else
    
    321
    -      {
    
    322
    -        xx1 -= w - warper->w0;
    
    323
    -        if ( xx1 > warper->x1max )
    
    324
    -        {
    
    325
    -          xx2 -= xx1 - warper->x1max;
    
    326
    -          xx1  = warper->x1max;
    
    327
    -        }
    
    328
    -      }
    
    329
    -
    
    330
    -      if ( xx1 < warper->x1 )
    
    331
    -        base_distort = warper->x1 - xx1;
    
    332
    -      else
    
    333
    -        base_distort = xx1 - warper->x1;
    
    334
    -
    
    335
    -      if ( xx2 < warper->x2 )
    
    336
    -        base_distort += warper->x2 - xx2;
    
    337
    -      else
    
    338
    -        base_distort += xx2 - warper->x2;
    
    339
    -
    
    340
    -      /* give base distortion a greater weight while scoring */
    
    341
    -      base_distort *= 10;
    
    342
    -
    
    343
    -      new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
    
    344
    -      new_delta = xx1 - FT_MulFix( X1, new_scale );
    
    345
    -
    
    346
    -      af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,
    
    347
    -                                   base_distort,
    
    348
    -                                   segments, num_segments );
    
    349
    -    }
    
    350
    -
    
    351
    -    {
    
    352
    -      FT_Fixed  best_scale = warper->best_scale;
    
    353
    -      FT_Pos    best_delta = warper->best_delta;
    
    354
    -
    
    355
    -
    
    356
    -      hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale )
    
    357
    -                          + best_delta;
    
    358
    -      hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale )
    
    359
    -                          + best_delta;
    
    360
    -
    
    361
    -      *a_scale = best_scale;
    
    362
    -      *a_delta = best_delta;
    
    363
    -    }
    
    364
    -  }
    
    365
    -
    
    366
    -#else /* !AF_CONFIG_OPTION_USE_WARPER */
    
    367
    -
    
    368
    -  /* ANSI C doesn't like empty source files */
    
    369
    -  typedef int  _af_warp_dummy;
    
    370
    -
    
    371
    -#endif /* !AF_CONFIG_OPTION_USE_WARPER */
    
    372
    -
    
    373
    -/* END */

  • src/autofit/afwarp.h deleted
    1
    -/****************************************************************************
    
    2
    - *
    
    3
    - * afwarp.h
    
    4
    - *
    
    5
    - *   Auto-fitter warping algorithm (specification).
    
    6
    - *
    
    7
    - * Copyright (C) 2006-2021 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 AFWARP_H_
    
    20
    -#define AFWARP_H_
    
    21
    -
    
    22
    -#include "afhints.h"
    
    23
    -
    
    24
    -FT_BEGIN_HEADER
    
    25
    -
    
    26
    -#define AF_WARPER_SCALE
    
    27
    -
    
    28
    -#define AF_WARPER_FLOOR( x )  ( (x) & ~FT_TYPEOF( x )63 )
    
    29
    -#define AF_WARPER_CEIL( x )   AF_WARPER_FLOOR( (x) + 63 )
    
    30
    -
    
    31
    -
    
    32
    -  typedef FT_Int32  AF_WarpScore;
    
    33
    -
    
    34
    -  typedef struct  AF_WarperRec_
    
    35
    -  {
    
    36
    -    FT_Pos        x1, x2;
    
    37
    -    FT_Pos        t1, t2;
    
    38
    -    FT_Pos        x1min, x1max;
    
    39
    -    FT_Pos        x2min, x2max;
    
    40
    -    FT_Pos        w0, wmin, wmax;
    
    41
    -
    
    42
    -    FT_Fixed      best_scale;
    
    43
    -    FT_Pos        best_delta;
    
    44
    -    AF_WarpScore  best_score;
    
    45
    -    AF_WarpScore  best_distort;
    
    46
    -
    
    47
    -  } AF_WarperRec, *AF_Warper;
    
    48
    -
    
    49
    -
    
    50
    -#ifdef AF_CONFIG_OPTION_USE_WARPER
    
    51
    -  FT_LOCAL( void )
    
    52
    -  af_warper_compute( AF_Warper      warper,
    
    53
    -                     AF_GlyphHints  hints,
    
    54
    -                     AF_Dimension   dim,
    
    55
    -                     FT_Fixed      *a_scale,
    
    56
    -                     FT_Pos        *a_delta );
    
    57
    -#endif
    
    58
    -
    
    59
    -
    
    60
    -FT_END_HEADER
    
    61
    -
    
    62
    -
    
    63
    -#endif /* AFWARP_H_ */
    
    64
    -
    
    65
    -
    
    66
    -/* END */

  • src/autofit/afwrtsys.h
    ... ... @@ -26,9 +26,6 @@
    26 26
     #include "aflatin.h"
    
    27 27
     #include "afcjk.h"
    
    28 28
     #include "afindic.h"
    
    29
    -#ifdef FT_OPTION_AUTOFIT2
    
    30
    -#include "aflatin2.h"
    
    31
    -#endif
    
    32 29
     
    
    33 30
     #endif /* AFWRTSYS_H_ */
    
    34 31
     
    
    ... ... @@ -44,9 +41,5 @@
    44 41
       WRITING_SYSTEM( latin,  LATIN  )
    
    45 42
       WRITING_SYSTEM( cjk,    CJK    )
    
    46 43
       WRITING_SYSTEM( indic,  INDIC  )
    
    47
    -#ifdef FT_OPTION_AUTOFIT2
    
    48
    -  WRITING_SYSTEM( latin2, LATIN2 )
    
    49
    -#endif
    
    50
    -
    
    51 44
     
    
    52 45
     /* END */

  • src/autofit/autofit.c
    ... ... @@ -18,7 +18,6 @@
    18 18
     
    
    19 19
     #define FT_MAKE_OPTION_SINGLE_OBJECT
    
    20 20
     
    
    21
    -#include "afangles.c"
    
    22 21
     #include "afblue.c"
    
    23 22
     #include "afcjk.c"
    
    24 23
     #include "afdummy.c"
    
    ... ... @@ -26,12 +25,10 @@
    26 25
     #include "afhints.c"
    
    27 26
     #include "afindic.c"
    
    28 27
     #include "aflatin.c"
    
    29
    -#include "aflatin2.c"
    
    30 28
     #include "afloader.c"
    
    31 29
     #include "afmodule.c"
    
    32 30
     #include "afranges.c"
    
    33 31
     #include "afshaper.c"
    
    34
    -#include "afwarp.c"
    
    35 32
     
    
    36 33
     
    
    37 34
     /* END */

  • src/autofit/rules.mk
    ... ... @@ -28,8 +28,7 @@ AUTOF_COMPILE := $(CC) $(ANSIFLAGS) \
    28 28
     
    
    29 29
     # AUTOF driver sources (i.e., C files)
    
    30 30
     #
    
    31
    -AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
    
    32
    -                 $(AUTOF_DIR)/afblue.c   \
    
    31
    +AUTOF_DRV_SRC := $(AUTOF_DIR)/afblue.c   \
    
    33 32
                      $(AUTOF_DIR)/afcjk.c    \
    
    34 33
                      $(AUTOF_DIR)/afdummy.c  \
    
    35 34
                      $(AUTOF_DIR)/afglobal.c \
    
    ... ... @@ -40,7 +39,6 @@ AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
    40 39
                      $(AUTOF_DIR)/afmodule.c \
    
    41 40
                      $(AUTOF_DIR)/afranges.c \
    
    42 41
                      $(AUTOF_DIR)/afshaper.c \
    
    43
    -                 $(AUTOF_DIR)/afwarp.c
    
    44 42
     
    
    45 43
     # AUTOF driver headers
    
    46 44
     #
    

  • subprojects/dlg
    1
    -Subproject commit 6e83f637efd10b736350496c565c24a86a98b07b
    1
    +Subproject commit 0cc0d3eaed28483fc8036d90ac18878ebd83ed87

  • tests/README.md
    ... ... @@ -4,7 +4,7 @@
    4 4
     
    
    5 5
     ### Download test fonts
    
    6 6
     
    
    7
    -Run the `tests/scripts/download-fonts.sh` script, which will
    
    7
    +Run the `tests/scripts/download-fonts.py` script, which will
    
    8 8
     download test fonts to the `tests/data/` directory first.
    
    9 9
     
    
    10 10
     ### Build the test programs
    

  • tests/scripts/download-test-fonts.py
    1
    +#!/usr/bin/env python3
    
    2
    +
    
    3
    +"""Download test fonts used by the FreeType regression test programs.
    
    4
    +These will be copied to $FREETYPE/tests/data/ by default.
    
    5
    +"""
    
    6
    +
    
    7
    +import argparse
    
    8
    +import collections
    
    9
    +import hashlib
    
    10
    +import io
    
    11
    +import os
    
    12
    +import requests
    
    13
    +import sys
    
    14
    +import zipfile
    
    15
    +
    
    16
    +from typing import Callable, List, Optional, Tuple
    
    17
    +
    
    18
    +# The list of download items describing the font files to install.
    
    19
    +# Each download item is a dictionary with one of the following schemas:
    
    20
    +#
    
    21
    +# - File item:
    
    22
    +#
    
    23
    +#      file_url
    
    24
    +#        Type: URL string.
    
    25
    +#        Required: Yes.
    
    26
    +#        Description: URL to download the file from.
    
    27
    +#
    
    28
    +#      install_name
    
    29
    +#        Type: file name string
    
    30
    +#        Required: No
    
    31
    +#        Description: Installation name for the font file, only provided if it
    
    32
    +#          must be different from the original URL's basename.
    
    33
    +#
    
    34
    +#      hex_digest
    
    35
    +#        Type: hexadecimal string
    
    36
    +#        Required: No
    
    37
    +#        Description: Digest of the input font file.
    
    38
    +#
    
    39
    +# - Zip items:
    
    40
    +#
    
    41
    +#   These items correspond to one or more font files that are embedded in a
    
    42
    +#   remote zip archive. Each entry has the following fields:
    
    43
    +#
    
    44
    +#      zip_url
    
    45
    +#        Type: URL string.
    
    46
    +#        Required: Yes.
    
    47
    +#        Description: URL to download the zip archive from.
    
    48
    +#
    
    49
    +#      zip_files
    
    50
    +#        Type: List of file entries (see below)
    
    51
    +#        Required: Yes
    
    52
    +#        Description: A list of entries describing a single font file to be
    
    53
    +#          extracted from the archive
    
    54
    +#
    
    55
    +# Apart from that, some schemas are used for dictionaries used inside download
    
    56
    +# items:
    
    57
    +#
    
    58
    +# - File entries:
    
    59
    +#
    
    60
    +#   These are dictionaries describing a single font file to extract from an archive.
    
    61
    +#
    
    62
    +#      filename
    
    63
    +#        Type: file path string
    
    64
    +#        Required: Yes
    
    65
    +#        Description: Path of source file, relative to the archive's top-level directory.
    
    66
    +#
    
    67
    +#      install_name
    
    68
    +#        Type: file name string
    
    69
    +#        Required: No
    
    70
    +#        Description: Installation name for the font file, only provided if it must be
    
    71
    +#          different from the original filename value.
    
    72
    +#
    
    73
    +#      hex_digest
    
    74
    +#        Type: hexadecimal string
    
    75
    +#        Required: No
    
    76
    +#        Description: Digest of the input source file
    
    77
    +#
    
    78
    +_DOWNLOAD_ITEMS = [
    
    79
    +    {
    
    80
    +        "zip_url": "https://github.com/python-pillow/Pillow/files/6622147/As.I.Lay.Dying.zip",
    
    81
    +        "zip_files": [
    
    82
    +            {
    
    83
    +                "filename": "As I Lay Dying.ttf",
    
    84
    +                "install_name": "As.I.Lay.Dying.ttf",
    
    85
    +                "hex_digest": "ef146bbc2673b387",
    
    86
    +            },
    
    87
    +        ],
    
    88
    +    },
    
    89
    +]
    
    90
    +
    
    91
    +
    
    92
    +def digest_data(data: bytes):
    
    93
    +    """Compute the digest of a given input byte string, which are the first 8 bytes of its sha256 hash."""
    
    94
    +    m = hashlib.sha256()
    
    95
    +    m.update(data)
    
    96
    +    return m.digest()[:8]
    
    97
    +
    
    98
    +
    
    99
    +def check_existing(path: str, hex_digest: str):
    
    100
    +    """Return True if |path| exists and matches |hex_digest|."""
    
    101
    +    if not os.path.exists(path) or hex_digest is None:
    
    102
    +        return False
    
    103
    +
    
    104
    +    with open(path, "rb") as f:
    
    105
    +        existing_content = f.read()
    
    106
    +
    
    107
    +    return bytes.fromhex(hex_digest) == digest_data(existing_content)
    
    108
    +
    
    109
    +
    
    110
    +def install_file(content: bytes, dest_path: str):
    
    111
    +    """Write a byte string to a given destination file.
    
    112
    +
    
    113
    +    Args:
    
    114
    +      content: Input data, as a byte string
    
    115
    +      dest_path: Installation path
    
    116
    +    """
    
    117
    +    parent_path = os.path.dirname(dest_path)
    
    118
    +    if not os.path.exists(parent_path):
    
    119
    +        os.makedirs(parent_path)
    
    120
    +
    
    121
    +    with open(dest_path, "wb") as f:
    
    122
    +        f.write(content)
    
    123
    +
    
    124
    +
    
    125
    +def download_file(url: str, expected_digest: Optional[bytes] = None):
    
    126
    +    """Download a file from a given URL.
    
    127
    +
    
    128
    +    Args:
    
    129
    +      url: Input URL
    
    130
    +      expected_digest: Optional digest of the file
    
    131
    +        as a byte string
    
    132
    +    Returns:
    
    133
    +      URL content as binary string.
    
    134
    +    """
    
    135
    +    r = requests.get(url, allow_redirects=True)
    
    136
    +    content = r.content
    
    137
    +    if expected_digest is not None:
    
    138
    +        digest = digest_data(r.content)
    
    139
    +        if digest != expected_digest:
    
    140
    +            raise ValueError(
    
    141
    +                "%s has invalid digest %s (expected %s)"
    
    142
    +                % (url, digest.hex(), expected_digest.hex())
    
    143
    +            )
    
    144
    +
    
    145
    +    return content
    
    146
    +
    
    147
    +
    
    148
    +def extract_file_from_zip_archive(
    
    149
    +    archive: zipfile.ZipFile,
    
    150
    +    archive_name: str,
    
    151
    +    filepath: str,
    
    152
    +    expected_digest: Optional[bytes] = None,
    
    153
    +):
    
    154
    +    """Extract a file from a given zipfile.ZipFile archive.
    
    155
    +
    
    156
    +    Args:
    
    157
    +      archive: Input ZipFile objec.
    
    158
    +      archive_name: Archive name or URL, only used to generate a human-readable error
    
    159
    +        message.
    
    160
    +      filepath: Input filepath in archive.
    
    161
    +      expected_digest: Optional digest for the file.
    
    162
    +    Returns:
    
    163
    +      A new File instance corresponding to the extract file.
    
    164
    +    Raises:
    
    165
    +      ValueError if expected_digest is not None and does not match the extracted file.
    
    166
    +    """
    
    167
    +    file = archive.open(filepath)
    
    168
    +    if expected_digest is not None:
    
    169
    +        digest = digest_data(archive.open(filepath).read())
    
    170
    +        if digest != expected_digest:
    
    171
    +            raise ValueError(
    
    172
    +                "%s in zip archive at %s has invalid digest %s (expected %s)"
    
    173
    +                % (filepath, archive_name, digest.hex(), expected_digest.hex())
    
    174
    +            )
    
    175
    +    return file.read()
    
    176
    +
    
    177
    +
    
    178
    +def _get_and_install_file(
    
    179
    +    install_path: str,
    
    180
    +    hex_digest: Optional[str],
    
    181
    +    force_download: bool,
    
    182
    +    get_content: Callable[[], bytes],
    
    183
    +) -> bool:
    
    184
    +    if not force_download and hex_digest is not None and os.path.exists(install_path):
    
    185
    +        with open(install_path, "rb") as f:
    
    186
    +            content: bytes = f.read()
    
    187
    +        if bytes.fromhex(hex_digest) == digest_data(content):
    
    188
    +            return False
    
    189
    +
    
    190
    +    content = get_content()
    
    191
    +    install_file(content, install_path)
    
    192
    +    return True
    
    193
    +
    
    194
    +
    
    195
    +def download_and_install_item(
    
    196
    +    item: dict, install_dir: str, force_download: bool
    
    197
    +) -> List[Tuple[str, bool]]:
    
    198
    +    """Download and install one item.
    
    199
    +
    
    200
    +    Args:
    
    201
    +      item: Download item as a dictionary, see above for schema.
    
    202
    +      install_dir: Installation directory.
    
    203
    +      force_download: Set to True to force download and installation, even if
    
    204
    +        the font file is already installed with the right content.
    
    205
    +
    
    206
    +    Returns:
    
    207
    +      A list of (install_name, status) tuples, where 'install_name' is the file's
    
    208
    +      installation name under 'install_dir', and 'status' is a boolean that is True
    
    209
    +      to indicate that the file was downloaded and installed, or False to indicate that
    
    210
    +      the file is already installed with the right content.
    
    211
    +    """
    
    212
    +    if "file_url" in item:
    
    213
    +        file_url = item["file_url"]
    
    214
    +        install_name = item.get("install_name", os.path.basename(file_url))
    
    215
    +        install_path = os.path.join(install_dir, install_name)
    
    216
    +        hex_digest = item.get("hex_digest")
    
    217
    +
    
    218
    +        def get_content():
    
    219
    +            return download_file(file_url, hex_digest)
    
    220
    +
    
    221
    +        status = _get_and_install_file(
    
    222
    +            install_path, hex_digest, force_download, get_content
    
    223
    +        )
    
    224
    +        return [(install_name, status)]
    
    225
    +
    
    226
    +    if "zip_url" in item:
    
    227
    +        # One or more files from a zip archive.
    
    228
    +        archive_url = item["zip_url"]
    
    229
    +        archive = zipfile.ZipFile(io.BytesIO(download_file(archive_url)))
    
    230
    +
    
    231
    +        result = []
    
    232
    +        for f in item["zip_files"]:
    
    233
    +            filename = f["filename"]
    
    234
    +            install_name = f.get("install_name", filename)
    
    235
    +            hex_digest = f.get("hex_digest")
    
    236
    +
    
    237
    +            def get_content():
    
    238
    +                return extract_file_from_zip_archive(
    
    239
    +                    archive,
    
    240
    +                    archive_url,
    
    241
    +                    filename,
    
    242
    +                    bytes.fromhex(hex_digest) if hex_digest else None,
    
    243
    +                )
    
    244
    +
    
    245
    +            status = _get_and_install_file(
    
    246
    +                os.path.join(install_dir, install_name),
    
    247
    +                hex_digest,
    
    248
    +                force_download,
    
    249
    +                get_content,
    
    250
    +            )
    
    251
    +            result.append((install_name, status))
    
    252
    +
    
    253
    +        return result
    
    254
    +
    
    255
    +    else:
    
    256
    +        raise ValueError("Unknown download item schema: %s" % item)
    
    257
    +
    
    258
    +
    
    259
    +def main():
    
    260
    +    parser = argparse.ArgumentParser(description=__doc__)
    
    261
    +
    
    262
    +    # Assume this script is under tests/scripts/ and tests/data/
    
    263
    +    # is the default installation directory.
    
    264
    +    install_dir = os.path.normpath(
    
    265
    +        os.path.join(os.path.dirname(__file__), "..", "data")
    
    266
    +    )
    
    267
    +
    
    268
    +    parser.add_argument(
    
    269
    +        "--force",
    
    270
    +        action="store_true",
    
    271
    +        default=False,
    
    272
    +        help="Force download and installation of font files",
    
    273
    +    )
    
    274
    +
    
    275
    +    parser.add_argument(
    
    276
    +        "--install-dir",
    
    277
    +        default=install_dir,
    
    278
    +        help="Specify installation directory [%s]" % install_dir,
    
    279
    +    )
    
    280
    +
    
    281
    +    args = parser.parse_args()
    
    282
    +
    
    283
    +    for item in _DOWNLOAD_ITEMS:
    
    284
    +        for install_name, status in download_and_install_item(
    
    285
    +            item, args.install_dir, args.force
    
    286
    +        ):
    
    287
    +            print("%s %s" % (install_name, "INSTALLED" if status else "UP-TO-DATE"))
    
    288
    +
    
    289
    +    return 0
    
    290
    +
    
    291
    +
    
    292
    +if __name__ == "__main__":
    
    293
    +    sys.exit(main())

  • tests/scripts/download-test-fonts.sh deleted
    1
    -#!/usr/bin/bash
    
    2
    -# Download test fonts used by the FreeType regression test programs.
    
    3
    -# These will be copied to $FREETYPE/tests/data/
    
    4
    -# Each font file contains an 8-hexchar prefix corresponding to its md5sum
    
    5
    -
    
    6
    -set -e
    
    7
    -
    
    8
    -export LANG=C
    
    9
    -export LC_ALL=C
    
    10
    -
    
    11
    -PROGDIR=$(dirname "$0")
    
    12
    -PROGNAME=$(basename "$0")
    
    13
    -
    
    14
    -# Download a file from a given URL
    
    15
    -#
    
    16
    -# $1: URL
    
    17
    -# $2: Destination directory
    
    18
    -# $3: If not empty, destination file name. Default is to take
    
    19
    -# the URL's basename.
    
    20
    -#
    
    21
    -download_file () {
    
    22
    -  local URL=$1
    
    23
    -  local DST_DIR=$2
    
    24
    -  local DST_FILE=$3
    
    25
    -  if [[ -z "$DST_FILE" ]]; then
    
    26
    -    DST_FILE=$(basename "$URL")
    
    27
    -  fi
    
    28
    -  echo "URL: $URL"
    
    29
    -  wget -q -O "$DST_DIR/$DST_FILE" "$URL"
    
    30
    -}
    
    31
    -
    
    32
    -# $1: URL
    
    33
    -# $2: Destination directory
    
    34
    -# $3+: Optional file list, otherwise the full archive is extracted to $2
    
    35
    -download_and_extract_zip () {
    
    36
    -  local URL=$1
    
    37
    -  local DST_DIR=$2
    
    38
    -  shift
    
    39
    -  shift
    
    40
    -  TEMP_DST_DIR=$(mktemp -d)
    
    41
    -  TEMP_DST_NAME="a.zip"
    
    42
    -  download_file "$URL" "$TEMP_DST_DIR" "$TEMP_DST_NAME"
    
    43
    -  unzip -qo "$TEMP_DST_DIR/$TEMP_DST_NAME" -d "$DST_DIR" "$@"
    
    44
    -  rm -rf "$TEMP_DST_DIR"
    
    45
    -}
    
    46
    -
    
    47
    -# $1: File path
    
    48
    -# $2: Expected md5sum
    
    49
    -md5sum_check () {
    
    50
    -  local FILE=$1
    
    51
    -  local EXPECTED=$2
    
    52
    -  local HASH=$(md5sum "$FILE" | cut -d" " -f1)
    
    53
    -  if [[ "$EXPECTED" != "$HASH" ]]; then
    
    54
    -    echo "$FILE: Invalid md5sum $HASH expected $EXPECTED"
    
    55
    -    return 1
    
    56
    -  fi
    
    57
    -}
    
    58
    -
    
    59
    -INSTALL_DIR=$(cd $PROGDIR/.. && pwd)/data
    
    60
    -
    
    61
    -mkdir -p "$INSTALL_DIR"
    
    62
    -
    
    63
    -# See https://gitlab.freedesktop.org/freetype/freetype/-/issues/1063
    
    64
    -download_and_extract_zip "https://github.com/python-pillow/Pillow/files/6622147/As.I.Lay.Dying.zip" "$INSTALL_DIR"
    
    65
    -mv "$INSTALL_DIR/As I Lay Dying.ttf" "$INSTALL_DIR/As.I.Lay.Dying.ttf"
    
    66
    -md5sum_check "$INSTALL_DIR/As.I.Lay.Dying.ttf" e153d60e66199660f7cfe99ef4705ad7


  • reply via email to

    [Prev in Thread] Current Thread [Next in Thread]