summaryrefslogtreecommitdiff
path: root/Build/source/libs/freetype2/freetype-src/src/autofit
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2021-08-29 06:19:44 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2021-08-29 06:19:44 +0000
commit0de5be92a3a0fe27e8521fc4de67e19b1057842e (patch)
treee93a390fe965486cca19498840cb8d7904252fec /Build/source/libs/freetype2/freetype-src/src/autofit
parent27ce96eea3f1190bd744448cfa149e8d767af95a (diff)
revert freetype to 2.10.4
git-svn-id: svn://tug.org/texlive/trunk@60360 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/freetype2/freetype-src/src/autofit')
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afangles.c285
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afangles.h7
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afblue.c2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afblue.cin2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afblue.dat2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afblue.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afblue.hin2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.c66
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afcover.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.c2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/aferrors.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.c14
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afhints.c132
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afhints.h17
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afindic.c7
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afindic.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.c125
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/aflatin2.c2428
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/aflatin2.h46
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afloader.c39
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afloader.h4
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.c56
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.h5
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afranges.c2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afranges.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afscript.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.c57
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.h2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afstyles.h11
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/aftypes.h60
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afwarp.c373
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afwarp.h66
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/afwrtsys.h9
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/autofit.c5
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/module.mk2
-rw-r--r--Build/source/libs/freetype2/freetype-src/src/autofit/rules.mk6
40 files changed, 3588 insertions, 266 deletions
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afangles.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afangles.c
new file mode 100644
index 00000000000..a2d45eb72c4
--- /dev/null
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afangles.c
@@ -0,0 +1,285 @@
+/****************************************************************************
+ *
+ * afangles.c
+ *
+ * Routines used to compute vector angles with limited accuracy
+ * and very high speed. It also contains sorting routines (body).
+ *
+ * Copyright (C) 2003-2020 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include "aftypes.h"
+
+
+ /*
+ * We are not using `af_angle_atan' anymore, but we keep the source
+ * code below just in case...
+ */
+
+
+#if 0
+
+
+ /*
+ * The trick here is to realize that we don't need a very accurate angle
+ * approximation. We are going to use the result of `af_angle_atan' to
+ * only compare the sign of angle differences, or check whether its
+ * magnitude is very small.
+ *
+ * The approximation
+ *
+ * dy * PI / (|dx|+|dy|)
+ *
+ * should be enough, and much faster to compute.
+ */
+ FT_LOCAL_DEF( AF_Angle )
+ af_angle_atan( FT_Fixed dx,
+ FT_Fixed dy )
+ {
+ AF_Angle angle;
+ FT_Fixed ax = dx;
+ FT_Fixed ay = dy;
+
+
+ if ( ax < 0 )
+ ax = -ax;
+ if ( ay < 0 )
+ ay = -ay;
+
+ ax += ay;
+
+ if ( ax == 0 )
+ angle = 0;
+ else
+ {
+ angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay );
+ if ( dx < 0 )
+ {
+ if ( angle >= 0 )
+ angle = AF_ANGLE_PI - angle;
+ else
+ angle = -AF_ANGLE_PI - angle;
+ }
+ }
+
+ return angle;
+ }
+
+
+#elif 0
+
+
+ /* the following table has been automatically generated with */
+ /* the `mather.py' Python script */
+
+#define AF_ATAN_BITS 8
+
+ static const FT_Byte af_arctan[1L << AF_ATAN_BITS] =
+ {
+ 0, 0, 1, 1, 1, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 5,
+ 5, 5, 6, 6, 6, 7, 7, 7,
+ 8, 8, 8, 9, 9, 9, 10, 10,
+ 10, 10, 11, 11, 11, 12, 12, 12,
+ 13, 13, 13, 14, 14, 14, 14, 15,
+ 15, 15, 16, 16, 16, 17, 17, 17,
+ 18, 18, 18, 18, 19, 19, 19, 20,
+ 20, 20, 21, 21, 21, 21, 22, 22,
+ 22, 23, 23, 23, 24, 24, 24, 24,
+ 25, 25, 25, 26, 26, 26, 26, 27,
+ 27, 27, 28, 28, 28, 28, 29, 29,
+ 29, 30, 30, 30, 30, 31, 31, 31,
+ 31, 32, 32, 32, 33, 33, 33, 33,
+ 34, 34, 34, 34, 35, 35, 35, 35,
+ 36, 36, 36, 36, 37, 37, 37, 38,
+ 38, 38, 38, 39, 39, 39, 39, 40,
+ 40, 40, 40, 41, 41, 41, 41, 42,
+ 42, 42, 42, 42, 43, 43, 43, 43,
+ 44, 44, 44, 44, 45, 45, 45, 45,
+ 46, 46, 46, 46, 46, 47, 47, 47,
+ 47, 48, 48, 48, 48, 48, 49, 49,
+ 49, 49, 50, 50, 50, 50, 50, 51,
+ 51, 51, 51, 51, 52, 52, 52, 52,
+ 52, 53, 53, 53, 53, 53, 54, 54,
+ 54, 54, 54, 55, 55, 55, 55, 55,
+ 56, 56, 56, 56, 56, 57, 57, 57,
+ 57, 57, 57, 58, 58, 58, 58, 58,
+ 59, 59, 59, 59, 59, 59, 60, 60,
+ 60, 60, 60, 61, 61, 61, 61, 61,
+ 61, 62, 62, 62, 62, 62, 62, 63,
+ 63, 63, 63, 63, 63, 64, 64, 64
+ };
+
+
+ FT_LOCAL_DEF( AF_Angle )
+ af_angle_atan( FT_Fixed dx,
+ FT_Fixed dy )
+ {
+ AF_Angle angle;
+
+
+ /* check trivial cases */
+ if ( dy == 0 )
+ {
+ angle = 0;
+ if ( dx < 0 )
+ angle = AF_ANGLE_PI;
+ return angle;
+ }
+ else if ( dx == 0 )
+ {
+ angle = AF_ANGLE_PI2;
+ if ( dy < 0 )
+ angle = -AF_ANGLE_PI2;
+ return angle;
+ }
+
+ angle = 0;
+ if ( dx < 0 )
+ {
+ dx = -dx;
+ dy = -dy;
+ angle = AF_ANGLE_PI;
+ }
+
+ if ( dy < 0 )
+ {
+ FT_Pos tmp;
+
+
+ tmp = dx;
+ dx = -dy;
+ dy = tmp;
+ angle -= AF_ANGLE_PI2;
+ }
+
+ if ( dx == 0 && dy == 0 )
+ return 0;
+
+ if ( dx == dy )
+ angle += AF_ANGLE_PI4;
+ else if ( dx > dy )
+ angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];
+ else
+ angle += AF_ANGLE_PI2 -
+ af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];
+
+ if ( angle > AF_ANGLE_PI )
+ angle -= AF_ANGLE_2PI;
+
+ return angle;
+ }
+
+
+#endif /* 0 */
+
+
+ FT_LOCAL_DEF( void )
+ af_sort_pos( FT_UInt count,
+ FT_Pos* table )
+ {
+ FT_UInt i, j;
+ FT_Pos swap;
+
+
+ for ( i = 1; i < count; i++ )
+ {
+ for ( j = i; j > 0; j-- )
+ {
+ if ( table[j] >= table[j - 1] )
+ break;
+
+ swap = table[j];
+ table[j] = table[j - 1];
+ table[j - 1] = swap;
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_sort_and_quantize_widths( FT_UInt* count,
+ AF_Width table,
+ FT_Pos threshold )
+ {
+ FT_UInt i, j;
+ FT_UInt cur_idx;
+ FT_Pos cur_val;
+ FT_Pos sum;
+ AF_WidthRec swap;
+
+
+ if ( *count == 1 )
+ return;
+
+ /* sort */
+ for ( i = 1; i < *count; i++ )
+ {
+ for ( j = i; j > 0; j-- )
+ {
+ if ( table[j].org >= table[j - 1].org )
+ break;
+
+ swap = table[j];
+ table[j] = table[j - 1];
+ table[j - 1] = swap;
+ }
+ }
+
+ cur_idx = 0;
+ cur_val = table[cur_idx].org;
+
+ /* compute and use mean values for clusters not larger than */
+ /* `threshold'; this is very primitive and might not yield */
+ /* the best result, but normally, using reference character */
+ /* `o', `*count' is 2, so the code below is fully sufficient */
+ for ( i = 1; i < *count; i++ )
+ {
+ if ( table[i].org - cur_val > threshold ||
+ i == *count - 1 )
+ {
+ sum = 0;
+
+ /* fix loop for end of array */
+ if ( table[i].org - cur_val <= threshold &&
+ i == *count - 1 )
+ i++;
+
+ for ( j = cur_idx; j < i; j++ )
+ {
+ sum += table[j].org;
+ table[j].org = 0;
+ }
+ table[cur_idx].org = sum / (FT_Pos)j;
+
+ if ( i < *count - 1 )
+ {
+ cur_idx = i + 1;
+ cur_val = table[cur_idx].org;
+ }
+ }
+ }
+
+ cur_idx = 1;
+
+ /* compress array to remove zero values */
+ for ( i = 1; i < *count; i++ )
+ {
+ if ( table[i].org )
+ table[cur_idx++] = table[i];
+ }
+
+ *count = cur_idx;
+ }
+
+
+/* END */
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afangles.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afangles.h
new file mode 100644
index 00000000000..18d7dae3a6b
--- /dev/null
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afangles.h
@@ -0,0 +1,7 @@
+/*
+ * afangles.h
+ *
+ * This is a dummy file, used to please the build system. It is never
+ * included by the auto-fitter sources.
+ *
+ */
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.c
index c9e8045c183..9ebffdd0997 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.c
@@ -7,7 +7,7 @@
*
* Auto-fitter data for blue strings (body).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.cin b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.cin
index 071e80b031d..c6a697fee00 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.cin
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.cin
@@ -4,7 +4,7 @@
*
* Auto-fitter data for blue strings (body).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.dat b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.dat
index 1aa9b26de9f..b19b8df0f47 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.dat
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.dat
@@ -2,7 +2,7 @@
//
// Auto-fitter data for blue strings.
//
-// Copyright (C) 2013-2021 by
+// Copyright (C) 2013-2020 by
// David Turner, Robert Wilhelm, and Werner Lemberg.
//
// This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.h
index 311c9e3afda..486d663b6c9 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.h
@@ -7,7 +7,7 @@
*
* Auto-fitter data for blue strings (specification).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.hin b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.hin
index 5186914937c..39570270917 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.hin
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afblue.hin
@@ -4,7 +4,7 @@
*
* Auto-fitter data for blue strings (specification).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.c
index 7e46b6b1ef5..3b340cd5eda 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for CJK writing system (body).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -37,6 +37,11 @@
#include "aferrors.h"
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+#include "afwarp.h"
+#endif
+
+
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
@@ -67,11 +72,11 @@
AF_GlyphHintsRec hints[1];
- FT_TRACE5(( "\n" ));
- FT_TRACE5(( "cjk standard widths computation (style `%s')\n",
+ FT_TRACE5(( "\n"
+ "cjk standard widths computation (style `%s')\n"
+ "===================================================\n"
+ "\n",
af_style_names[metrics->root.style_class->style] ));
- FT_TRACE5(( "===================================================\n" ));
- FT_TRACE5(( "\n" ));
af_glyph_hints_init( hints, face->memory );
@@ -309,9 +314,9 @@
/* style's entry in the `af_blue_stringset' array, computing its */
/* extremum points (depending on the string properties) */
- FT_TRACE5(( "cjk blue zones computation\n" ));
- FT_TRACE5(( "==========================\n" ));
- FT_TRACE5(( "\n" ));
+ FT_TRACE5(( "cjk blue zones computation\n"
+ "==========================\n"
+ "\n" ));
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
shaper_buf = af_shaper_buf_create( face );
@@ -550,8 +555,9 @@
if ( AF_CJK_IS_TOP_BLUE( bs ) )
blue->flags |= AF_CJK_BLUE_TOP;
- FT_TRACE5(( " -> reference = %ld\n", *blue_ref ));
- FT_TRACE5(( " overshoot = %ld\n", *blue_shoot ));
+ FT_TRACE5(( " -> reference = %ld\n"
+ " overshoot = %ld\n",
+ *blue_ref, *blue_shoot ));
} /* end for loop */
@@ -737,12 +743,12 @@
blue->shoot.fit = blue->ref.fit - delta2;
- FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n",
+ FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n"
+ " ref: cur=%.2f fit=%.2f\n"
+ " shoot: cur=%.2f fit=%.2f\n",
( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
- nn, blue->ref.org, blue->shoot.org ));
- FT_TRACE5(( " ref: cur=%.2f fit=%.2f\n",
- blue->ref.cur / 64.0, blue->ref.fit / 64.0 ));
- FT_TRACE5(( " shoot: cur=%.2f fit=%.2f\n",
+ nn, blue->ref.org, blue->shoot.org,
+ blue->ref.cur / 64.0, blue->ref.fit / 64.0,
blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
blue->flags |= AF_CJK_BLUE_ACTIVE;
@@ -1395,6 +1401,11 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
+#if 0 /* AF_CONFIG_OPTION_USE_WARPER */
+ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
+ metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
+#endif
+
scaler_flags = hints->scaler_flags;
other_flags = 0;
@@ -1423,6 +1434,12 @@
scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ /* get (global) warper flag */
+ if ( !metrics->root.globals->module->warping )
+ scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
+#endif
+
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
@@ -2305,6 +2322,25 @@
if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
{
+
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
+ AF_HINTS_DO_WARP( hints ) )
+ {
+ AF_WarperRec warper;
+ FT_Fixed scale;
+ FT_Pos delta;
+
+
+ af_warper_compute( &warper, hints, (AF_Dimension)dim,
+ &scale, &delta );
+ af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
+ scale, delta );
+ continue;
+ }
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
+
af_cjk_hint_edges( hints, (AF_Dimension)dim );
af_cjk_align_edge_points( hints, (AF_Dimension)dim );
af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.h
index 58aa298dada..fd0f451aa83 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for CJK writing system (specification).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afcover.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afcover.h
index c7ae1e9a8a2..03085ad07ea 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afcover.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afcover.h
@@ -4,7 +4,7 @@
*
* Auto-fitter coverages (specification only).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.c
index a36b56f7847..77d31df974f 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
* Auto-fitter dummy routines to be used if no hinting should be
* performed (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.h
index b58849fe505..efd799e84b7 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
* Auto-fitter dummy routines to be used if no hinting should be
* performed (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/aferrors.h b/Build/source/libs/freetype2/freetype-src/src/autofit/aferrors.h
index 09bed663951..f90899944b5 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/aferrors.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
*
* Autofitter error codes (specification only).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.c
index aedb74ddd40..d5129423d52 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
*
* Auto-fitter routines to compute global hinting values (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -285,10 +285,10 @@
#ifdef FT_DEBUG_LEVEL_TRACE
- FT_TRACE4(( "\n" ));
- FT_TRACE4(( "style coverage\n" ));
- FT_TRACE4(( "==============\n" ));
- FT_TRACE4(( "\n" ));
+ FT_TRACE4(( "\n"
+ "style coverage\n"
+ "==============\n"
+ "\n" ));
for ( ss = 0; af_style_classes[ss]; ss++ )
{
@@ -478,10 +478,6 @@
{
style = (AF_Style)( globals->glyph_styles[gindex] &
AF_STYLE_UNASSIGNED );
- /* IMPORTANT: Clear the error code, see
- * https://gitlab.freedesktop.org/freetype/freetype/-/issues/1063
- */
- error = 0;
goto Again;
}
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.h
index cd97e716c4e..fecf7af9773 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
* Auto-fitter routines to compute global hinting values
* (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afhints.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afhints.c
index 4bf6d66ddbf..a8e00890ef3 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afhints.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afhints.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -32,104 +32,6 @@
#define FT_COMPONENT afhints
- FT_LOCAL_DEF( void )
- af_sort_pos( FT_UInt count,
- FT_Pos* table )
- {
- FT_UInt i, j;
- FT_Pos swap;
-
-
- for ( i = 1; i < count; i++ )
- {
- for ( j = i; j > 0; j-- )
- {
- if ( table[j] >= table[j - 1] )
- break;
-
- swap = table[j];
- table[j] = table[j - 1];
- table[j - 1] = swap;
- }
- }
- }
-
-
- FT_LOCAL_DEF( void )
- af_sort_and_quantize_widths( FT_UInt* count,
- AF_Width table,
- FT_Pos threshold )
- {
- FT_UInt i, j;
- FT_UInt cur_idx;
- FT_Pos cur_val;
- FT_Pos sum;
- AF_WidthRec swap;
-
-
- if ( *count == 1 )
- return;
-
- /* sort */
- for ( i = 1; i < *count; i++ )
- {
- for ( j = i; j > 0; j-- )
- {
- if ( table[j].org >= table[j - 1].org )
- break;
-
- swap = table[j];
- table[j] = table[j - 1];
- table[j - 1] = swap;
- }
- }
-
- cur_idx = 0;
- cur_val = table[cur_idx].org;
-
- /* compute and use mean values for clusters not larger than */
- /* `threshold'; this is very primitive and might not yield */
- /* the best result, but normally, using reference character */
- /* `o', `*count' is 2, so the code below is fully sufficient */
- for ( i = 1; i < *count; i++ )
- {
- if ( table[i].org - cur_val > threshold ||
- i == *count - 1 )
- {
- sum = 0;
-
- /* fix loop for end of array */
- if ( table[i].org - cur_val <= threshold &&
- i == *count - 1 )
- i++;
-
- for ( j = cur_idx; j < i; j++ )
- {
- sum += table[j].org;
- table[j].org = 0;
- }
- table[cur_idx].org = sum / (FT_Pos)j;
-
- if ( i < *count - 1 )
- {
- cur_idx = i + 1;
- cur_val = table[cur_idx].org;
- }
- }
- }
-
- cur_idx = 1;
-
- /* compress array to remove zero values */
- for ( i = 1; i < *count; i++ )
- {
- if ( table[i].org )
- table[cur_idx++] = table[i];
- }
-
- *count = cur_idx;
- }
-
/* Get new segment for given axis. */
FT_LOCAL_DEF( FT_Error )
@@ -953,6 +855,9 @@
hints->x_delta = x_delta;
hints->y_delta = y_delta;
+ hints->xmin_delta = 0;
+ hints->xmax_delta = 0;
+
points = hints->points;
if ( hints->num_points == 0 )
goto Exit;
@@ -1783,4 +1688,33 @@
}
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+
+ /* Apply (small) warp scale and warp delta for given dimension. */
+
+ FT_LOCAL_DEF( void )
+ af_glyph_hints_scale_dim( AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Fixed scale,
+ FT_Pos delta )
+ {
+ AF_Point points = hints->points;
+ AF_Point points_limit = points + hints->num_points;
+ AF_Point point;
+
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ for ( point = points; point < points_limit; point++ )
+ point->x = FT_MulFix( point->fx, scale ) + delta;
+ }
+ else
+ {
+ for ( point = points; point < points_limit; point++ )
+ point->y = FT_MulFix( point->fy, scale ) + delta;
+ }
+ }
+
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
+
/* END */
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afhints.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afhints.h
index 38d2847d712..6397f098f00 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afhints.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afhints.h
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -362,6 +362,9 @@ FT_BEGIN_HEADER
/* implementations */
AF_StyleMetrics metrics;
+ FT_Pos xmin_delta; /* used for warping */
+ FT_Pos xmax_delta;
+
/* Two arrays to avoid allocation penalty. */
/* The `embedded' structure must be the last element! */
struct
@@ -405,6 +408,10 @@ FT_BEGIN_HEADER
#define AF_HINTS_DO_ADVANCE( h ) \
!AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
+#define AF_HINTS_DO_WARP( h ) \
+ !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_WARPER )
+
+
FT_LOCAL( AF_Direction )
af_direction_compute( FT_Pos dx,
@@ -452,6 +459,14 @@ FT_BEGIN_HEADER
af_glyph_hints_align_weak_points( AF_GlyphHints hints,
AF_Dimension dim );
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ FT_LOCAL( void )
+ af_glyph_hints_scale_dim( AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Fixed scale,
+ FT_Pos delta );
+#endif
+
FT_LOCAL( void )
af_glyph_hints_done( AF_GlyphHints hints );
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afindic.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afindic.c
index 064c300ed7d..bc2837a26dd 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afindic.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afindic.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for Indic writing system (body).
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2020 by
* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
*
* This file is part of the FreeType project, and may only be used,
@@ -27,6 +27,11 @@
#include "aferrors.h"
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+#include "afwarp.h"
+#endif
+
+
static FT_Error
af_indic_metrics_init( AF_CJKMetrics metrics,
FT_Face face )
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afindic.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afindic.h
index 3e467241125..088b88b19da 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afindic.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afindic.h
@@ -5,7 +5,7 @@
* Auto-fitter hinting routines for Indic writing system
* (specification).
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2020 by
* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.c b/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.c
index b8af228a4f6..21ec02ebd2d 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for latin writing system (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -24,6 +24,11 @@
#include "aferrors.h"
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+#include "afwarp.h"
+#endif
+
+
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
@@ -58,11 +63,11 @@
AF_GlyphHintsRec hints[1];
- FT_TRACE5(( "\n" ));
- FT_TRACE5(( "latin standard widths computation (style `%s')\n",
+ FT_TRACE5(( "\n"
+ "latin standard widths computation (style `%s')\n"
+ "=====================================================\n"
+ "\n",
af_style_names[metrics->root.style_class->style] ));
- FT_TRACE5(( "=====================================================\n" ));
- FT_TRACE5(( "\n" ));
af_glyph_hints_init( hints, face->memory );
@@ -345,9 +350,9 @@
/* we walk over the blue character strings as specified in the */
/* style's entry in the `af_blue_stringset' array */
- FT_TRACE5(( "latin blue zones computation\n" ));
- FT_TRACE5(( "============================\n" ));
- FT_TRACE5(( "\n" ));
+ FT_TRACE5(( "latin blue zones computation\n"
+ "============================\n"
+ "\n" ));
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
shaper_buf = af_shaper_buf_create( face );
@@ -971,8 +976,9 @@
if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) )
blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
- FT_TRACE5(( " -> reference = %ld\n", *blue_ref ));
- FT_TRACE5(( " overshoot = %ld\n", *blue_shoot ));
+ FT_TRACE5(( " -> reference = %ld\n"
+ " overshoot = %ld\n",
+ *blue_ref, *blue_shoot ));
} /* end for loop */
@@ -1269,28 +1275,29 @@
if ( dist == 0 )
{
- FT_TRACE5(( "af_latin_metrics_scale_dim:"
- " x height alignment (style `%s'):\n",
- af_style_names[metrics->root.style_class->style] ));
- FT_TRACE5(( " "
- " vertical scaling changed"
- " from %.5f to %.5f (by %ld%%)\n",
- scale / 65536.0,
- new_scale / 65536.0,
- ( fitted - scaled ) * 100 / scaled ));
- FT_TRACE5(( "\n" ));
+ FT_TRACE5((
+ "af_latin_metrics_scale_dim:"
+ " x height alignment (style `%s'):\n"
+ " "
+ " vertical scaling changed from %.5f to %.5f (by %ld%%)\n"
+ "\n",
+ af_style_names[metrics->root.style_class->style],
+ scale / 65536.0,
+ new_scale / 65536.0,
+ ( fitted - scaled ) * 100 / scaled ));
scale = new_scale;
}
#ifdef FT_DEBUG_LEVEL_TRACE
else
{
- FT_TRACE5(( "af_latin_metrics_scale_dim:"
- " x height alignment (style `%s'):\n",
- af_style_names[metrics->root.style_class->style] ));
- FT_TRACE5(( " "
- " excessive vertical scaling abandoned\n" ));
- FT_TRACE5(( "\n" ));
+ FT_TRACE5((
+ "af_latin_metrics_scale_dim:"
+ " x height alignment (style `%s'):\n"
+ " "
+ " excessive vertical scaling abandoned\n"
+ "\n",
+ af_style_names[metrics->root.style_class->style] ));
}
#endif
}
@@ -1339,11 +1346,9 @@
#ifdef FT_DEBUG_LEVEL_TRACE
if ( axis->extra_light )
- {
- FT_TRACE5(( "`%s' style is extra light (at current resolution)\n",
+ FT_TRACE5(( "`%s' style is extra light (at current resolution)\n"
+ "\n",
af_style_names[metrics->root.style_class->style] ));
- FT_TRACE5(( "\n" ));
- }
#endif
if ( dim == AF_DIMENSION_VERT )
@@ -1468,13 +1473,13 @@
AF_LatinBlue blue = &axis->blues[nn];
- FT_TRACE5(( " reference %d: %ld scaled to %.2f%s\n",
+ FT_TRACE5(( " reference %d: %ld scaled to %.2f%s\n"
+ " overshoot %d: %ld scaled to %.2f%s\n",
nn,
blue->ref.org,
blue->ref.fit / 64.0,
( blue->flags & AF_LATIN_BLUE_ACTIVE ) ? ""
- : " (inactive)" ));
- FT_TRACE5(( " overshoot %d: %ld scaled to %.2f%s\n",
+ : " (inactive)",
nn,
blue->shoot.org,
blue->shoot.fit / 64.0,
@@ -1842,31 +1847,6 @@
( FT_ABS( point->out_dir ) == major_dir ||
point == point->prev ) )
{
- /*
- * For efficiency, we restrict the number of segments to 1000,
- * which is a heuristic value: it is very unlikely that a glyph
- * with so many segments can be hinted in a sensible way.
- * Reasons:
- *
- * - The glyph has really 1000 segments; this implies that it has
- * at least 2000 outline points. Assuming 'normal' fonts that
- * have superfluous points optimized away, viewing such a glyph
- * only makes sense at large magnifications where hinting
- * isn't applied anyway.
- *
- * - We have a broken glyph. Hinting doesn't make sense in this
- * case either.
- */
- if ( axis->num_segments > 1000 )
- {
- FT_TRACE0(( "af_latin_hints_compute_segments:"
- " more than 1000 segments in this glyph;\n" ));
- FT_TRACE0(( " "
- " hinting is suppressed\n" ));
- axis->num_segments = 0;
- return FT_Err_Ok;
- }
-
/* this is the start of a new segment! */
segment_dir = (AF_Direction)point->out_dir;
@@ -2631,6 +2611,11 @@
/* compute flags depending on render mode, etc. */
mode = metrics->root.scaler.render_mode;
+#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
+ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
+ metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
+#endif
+
scaler_flags = hints->scaler_flags;
other_flags = 0;
@@ -2668,6 +2653,12 @@
( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ /* get (global) warper flag */
+ if ( !metrics->root.globals->module->warping )
+ scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
+#endif
+
hints->scaler_flags = scaler_flags;
hints->other_flags = other_flags;
@@ -3584,6 +3575,24 @@
/* grid-fit the outline */
for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
{
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
+ AF_HINTS_DO_WARP( hints ) )
+ {
+ AF_WarperRec warper;
+ FT_Fixed scale;
+ FT_Pos delta;
+
+
+ af_warper_compute( &warper, hints, (AF_Dimension)dim,
+ &scale, &delta );
+ af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
+ scale, delta );
+ continue;
+ }
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
+
if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
{
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.h b/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.h
index d6b919ef842..62bc4c8d442 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin.h
@@ -5,7 +5,7 @@
* Auto-fitter hinting routines for latin writing system
* (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin2.c b/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin2.c
new file mode 100644
index 00000000000..902f3982e04
--- /dev/null
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin2.c
@@ -0,0 +1,2428 @@
+/* ATTENTION: This file doesn't compile. It is only here as a reference */
+/* of an alternative latin hinting algorithm that was always */
+/* marked as experimental. */
+
+
+/****************************************************************************
+ *
+ * aflatin2.c
+ *
+ * Auto-fitter hinting routines for latin writing system (body).
+ *
+ * Copyright (C) 2003-2020 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include <freetype/ftadvanc.h>
+
+
+#ifdef FT_OPTION_AUTOFIT2
+
+#include "afglobal.h"
+#include "aflatin.h"
+#include "aflatin2.h"
+#include "aferrors.h"
+
+
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+#include "afwarp.h"
+#endif
+
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
+#undef FT_COMPONENT
+#define FT_COMPONENT aflatin2
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_hints_compute_segments( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+ FT_LOCAL_DEF( void )
+ af_latin2_hints_link_segments( AF_GlyphHints hints,
+ AF_Dimension dim );
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L O B A L M E T R I C S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ FT_LOCAL_DEF( void )
+ af_latin2_metrics_init_widths( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ /* scan the array of segments in each direction */
+ AF_GlyphHintsRec hints[1];
+
+
+ af_glyph_hints_init( hints, face->memory );
+
+ metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
+ metrics->axis[AF_DIMENSION_VERT].width_count = 0;
+
+ {
+ FT_Error error;
+ FT_UInt glyph_index;
+ int dim;
+ AF_LatinMetricsRec dummy[1];
+ AF_Scaler scaler = &dummy->root.scaler;
+
+
+ glyph_index = FT_Get_Char_Index(
+ face,
+ metrics->root.style_class->standard_char );
+ if ( glyph_index == 0 )
+ goto Exit;
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || face->glyph->outline.n_points <= 0 )
+ goto Exit;
+
+ FT_ZERO( dummy );
+
+ dummy->units_per_em = metrics->units_per_em;
+ scaler->x_scale = scaler->y_scale = 0x10000L;
+ scaler->x_delta = scaler->y_delta = 0;
+ scaler->face = face;
+ scaler->render_mode = FT_RENDER_MODE_NORMAL;
+ scaler->flags = 0;
+
+ af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy );
+
+ error = af_glyph_hints_reload( hints, &face->glyph->outline );
+ if ( error )
+ goto Exit;
+
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_LatinAxis axis = &metrics->axis[dim];
+ AF_AxisHints axhints = &hints->axis[dim];
+ AF_Segment seg, limit, link;
+ FT_UInt num_widths = 0;
+
+
+ error = af_latin2_hints_compute_segments( hints,
+ (AF_Dimension)dim );
+ if ( error )
+ goto Exit;
+
+ af_latin2_hints_link_segments( hints,
+ (AF_Dimension)dim );
+
+ seg = axhints->segments;
+ limit = seg + axhints->num_segments;
+
+ for ( ; seg < limit; seg++ )
+ {
+ link = seg->link;
+
+ /* we only consider stem segments there! */
+ if ( link && link->link == seg && link > seg )
+ {
+ FT_Pos dist;
+
+
+ dist = seg->pos - link->pos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( num_widths < AF_LATIN_MAX_WIDTHS )
+ axis->widths[num_widths++].org = dist;
+ }
+ }
+
+ af_sort_widths( num_widths, axis->widths );
+ axis->width_count = num_widths;
+ }
+
+ Exit:
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+ AF_LatinAxis axis = &metrics->axis[dim];
+ FT_Pos stdw;
+
+
+ stdw = ( axis->width_count > 0 )
+ ? axis->widths[0].org
+ : AF_LATIN_CONSTANT( metrics, 50 );
+
+ /* let's try 20% of the smallest width */
+ axis->edge_distance_threshold = stdw / 5;
+ axis->standard_width = stdw;
+ axis->extra_light = 0;
+ }
+ }
+
+ af_glyph_hints_done( hints );
+ }
+
+
+
+#define AF_LATIN_MAX_TEST_CHARACTERS 12
+
+
+ static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES]
+ [AF_LATIN_MAX_TEST_CHARACTERS+1] =
+ {
+ "THEZOCQS",
+ "HEZLOCUS",
+ "fijkdbh",
+ "xzroesc",
+ "xzroesc",
+ "pqgjy"
+ };
+
+
+ static void
+ af_latin2_metrics_init_blues( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ FT_Pos flats [AF_LATIN_MAX_TEST_CHARACTERS];
+ FT_Pos rounds[AF_LATIN_MAX_TEST_CHARACTERS];
+ FT_Int num_flats;
+ FT_Int num_rounds;
+ FT_Int bb;
+ AF_LatinBlue blue;
+ FT_Error error;
+ AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT];
+ FT_GlyphSlot glyph = face->glyph;
+
+
+ /* we compute the blues simply by loading each character from the */
+ /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
+ /* bottom-most points (depending on `AF_IS_TOP_BLUE') */
+
+ FT_TRACE5(( "blue zones computation\n"
+ "======================\n\n" ));
+
+ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
+ {
+ const char* p = af_latin2_blue_chars[bb];
+ const char* limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
+ FT_Pos* blue_ref;
+ FT_Pos* blue_shoot;
+
+
+ FT_TRACE5(( "blue zone %d:\n", bb ));
+
+ num_flats = 0;
+ num_rounds = 0;
+
+ for ( ; p < limit && *p; p++ )
+ {
+ FT_UInt glyph_index;
+ FT_Int best_point, best_y, best_first, best_last;
+ FT_Vector* points;
+ FT_Bool round;
+
+
+ /* load the character in the face -- skip unknown or empty ones */
+ glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
+ if ( glyph_index == 0 )
+ continue;
+
+ error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+ if ( error || glyph->outline.n_points <= 0 )
+ continue;
+
+ /* now compute min or max point indices and coordinates */
+ points = glyph->outline.points;
+ best_point = -1;
+ best_y = 0; /* make compiler happy */
+ best_first = 0; /* ditto */
+ best_last = 0; /* ditto */
+
+ {
+ FT_Int nn;
+ FT_Int first = 0;
+ FT_Int last = -1;
+
+
+ for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
+ {
+ FT_Int old_best_point = best_point;
+ FT_Int pp;
+
+
+ last = glyph->outline.contours[nn];
+
+ /* Avoid single-point contours since they are never rasterized. */
+ /* In some fonts, they correspond to mark attachment points */
+ /* which are way outside of the glyph's real outline. */
+ if ( last <= first )
+ continue;
+
+ if ( AF_LATIN_IS_TOP_BLUE( bb ) )
+ {
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y > best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ }
+ }
+ else
+ {
+ for ( pp = first; pp <= last; pp++ )
+ if ( best_point < 0 || points[pp].y < best_y )
+ {
+ best_point = pp;
+ best_y = points[pp].y;
+ }
+ }
+
+ if ( best_point != old_best_point )
+ {
+ best_first = first;
+ best_last = last;
+ }
+ }
+ FT_TRACE5(( " %c %d", *p, best_y ));
+ }
+
+ /* now check whether the point belongs to a straight or round */
+ /* segment; we first need to find in which contour the extremum */
+ /* lies, then inspect its previous and next points */
+ if ( best_point >= 0 )
+ {
+ FT_Pos best_x = points[best_point].x;
+ FT_Int start, end, prev, next;
+ FT_Pos dist;
+
+
+ /* now look for the previous and next points that are not on the */
+ /* same Y coordinate. Threshold the `closeness'... */
+ start = end = best_point;
+
+ do
+ {
+ prev = start - 1;
+ if ( prev < best_first )
+ prev = best_last;
+
+ dist = FT_ABS( points[prev].y - best_y );
+ /* accept a small distance or a small angle (both values are */
+ /* heuristic; value 20 corresponds to approx. 2.9 degrees) */
+ if ( dist > 5 )
+ if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
+ break;
+
+ start = prev;
+
+ } while ( start != best_point );
+
+ do
+ {
+ next = end + 1;
+ if ( next > best_last )
+ next = best_first;
+
+ dist = FT_ABS( points[next].y - best_y );
+ if ( dist > 5 )
+ if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
+ break;
+
+ end = next;
+
+ } while ( end != best_point );
+
+ /* now, set the `round' flag depending on the segment's kind */
+ round = FT_BOOL(
+ FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
+ FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
+
+ FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
+ }
+
+ if ( round )
+ rounds[num_rounds++] = best_y;
+ else
+ flats[num_flats++] = best_y;
+ }
+
+ if ( num_flats == 0 && num_rounds == 0 )
+ {
+ /*
+ * we couldn't find a single glyph to compute this blue zone,
+ * we will simply ignore it then
+ */
+ FT_TRACE5(( " empty\n" ));
+ continue;
+ }
+
+ /* we have computed the contents of the `rounds' and `flats' tables, */
+ /* now determine the reference and overshoot position of the blue -- */
+ /* we simply take the median value after a simple sort */
+ af_sort_pos( num_rounds, rounds );
+ af_sort_pos( num_flats, flats );
+
+ blue = & axis->blues[axis->blue_count];
+ blue_ref = & blue->ref.org;
+ blue_shoot = & blue->shoot.org;
+
+ axis->blue_count++;
+
+ if ( num_flats == 0 )
+ {
+ *blue_ref =
+ *blue_shoot = rounds[num_rounds / 2];
+ }
+ else if ( num_rounds == 0 )
+ {
+ *blue_ref =
+ *blue_shoot = flats[num_flats / 2];
+ }
+ else
+ {
+ *blue_ref = flats[num_flats / 2];
+ *blue_shoot = rounds[num_rounds / 2];
+ }
+
+ /* there are sometimes problems: if the overshoot position of top */
+ /* zones is under its reference position, or the opposite for bottom */
+ /* zones. We must thus check everything there and correct the errors */
+ if ( *blue_shoot != *blue_ref )
+ {
+ FT_Pos ref = *blue_ref;
+ FT_Pos shoot = *blue_shoot;
+ FT_Bool over_ref = FT_BOOL( shoot > ref );
+
+
+ if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
+ {
+ *blue_ref =
+ *blue_shoot = ( shoot + ref ) / 2;
+
+ FT_TRACE5(( " [overshoot smaller than reference,"
+ " taking mean value]\n" ));
+ }
+ }
+
+ blue->flags = 0;
+ if ( AF_LATIN_IS_TOP_BLUE( bb ) )
+ blue->flags |= AF_LATIN_BLUE_TOP;
+
+ /*
+ * The following flag is used later to adjust the y and x scales
+ * in order to optimize the pixel grid alignment of the top of small
+ * letters.
+ */
+ if ( AF_LATIN_IS_X_HEIGHT_BLUE( bb ) )
+ blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
+
+ FT_TRACE5(( " -> reference = %ld\n"
+ " overshoot = %ld\n",
+ *blue_ref, *blue_shoot ));
+ }
+
+ return;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_latin2_metrics_check_digits( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ FT_UInt i;
+ FT_Bool started = 0, same_width = 1;
+ FT_Fixed advance, old_advance = 0;
+
+
+ /* check whether all ASCII digits have the same advance width; */
+ /* digit `0' is 0x30 in all supported charmaps */
+ for ( i = 0x30; i <= 0x39; i++ )
+ {
+ FT_UInt glyph_index;
+
+
+ glyph_index = FT_Get_Char_Index( face, i );
+ if ( glyph_index == 0 )
+ continue;
+
+ if ( FT_Get_Advance( face, glyph_index,
+ FT_LOAD_NO_SCALE |
+ FT_LOAD_NO_HINTING |
+ FT_LOAD_IGNORE_TRANSFORM,
+ &advance ) )
+ continue;
+
+ if ( started )
+ {
+ if ( advance != old_advance )
+ {
+ same_width = 0;
+ break;
+ }
+ }
+ else
+ {
+ old_advance = advance;
+ started = 1;
+ }
+ }
+
+ metrics->root.digits_have_same_width = same_width;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_metrics_init( AF_LatinMetrics metrics,
+ FT_Face face )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_CharMap oldmap = face->charmap;
+ FT_UInt ee;
+
+ static const FT_Encoding latin_encodings[] =
+ {
+ FT_ENCODING_UNICODE,
+ FT_ENCODING_APPLE_ROMAN,
+ FT_ENCODING_ADOBE_STANDARD,
+ FT_ENCODING_ADOBE_LATIN_1,
+ FT_ENCODING_NONE /* end of list */
+ };
+
+
+ metrics->units_per_em = face->units_per_EM;
+
+ /* do we have a latin charmap in there? */
+ for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
+ {
+ error = FT_Select_Charmap( face, latin_encodings[ee] );
+ if ( !error )
+ break;
+ }
+
+ if ( !error )
+ {
+ af_latin2_metrics_init_widths( metrics, face );
+ af_latin2_metrics_init_blues( metrics, face );
+ af_latin2_metrics_check_digits( metrics, face );
+ }
+
+ FT_Set_Charmap( face, oldmap );
+ return FT_Err_Ok;
+ }
+
+
+ static void
+ af_latin2_metrics_scale_dim( AF_LatinMetrics metrics,
+ AF_Scaler scaler,
+ AF_Dimension dim )
+ {
+ FT_Fixed scale;
+ FT_Pos delta;
+ AF_LatinAxis axis;
+ FT_UInt nn;
+
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ scale = scaler->x_scale;
+ delta = scaler->x_delta;
+ }
+ else
+ {
+ scale = scaler->y_scale;
+ delta = scaler->y_delta;
+ }
+
+ axis = &metrics->axis[dim];
+
+ if ( axis->org_scale == scale && axis->org_delta == delta )
+ return;
+
+ axis->org_scale = scale;
+ axis->org_delta = delta;
+
+ /*
+ * correct Y scale to optimize the alignment of the top of small
+ * letters to the pixel grid
+ */
+ if ( dim == AF_DIMENSION_VERT )
+ {
+ AF_LatinAxis vaxis = &metrics->axis[AF_DIMENSION_VERT];
+ AF_LatinBlue blue = NULL;
+
+
+ for ( nn = 0; nn < vaxis->blue_count; nn++ )
+ {
+ if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
+ {
+ blue = &vaxis->blues[nn];
+ break;
+ }
+ }
+
+ if ( blue )
+ {
+ FT_Pos scaled;
+ FT_Pos threshold;
+ FT_Pos fitted;
+ FT_UInt limit;
+ FT_UInt ppem;
+
+
+ scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
+ ppem = metrics->root.scaler.face->size->metrics.x_ppem;
+ limit = metrics->root.globals->increase_x_height;
+ threshold = 40;
+
+ /* if the `increase-x-height' property is active, */
+ /* we round up much more often */
+ if ( limit &&
+ ppem <= limit &&
+ ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN )
+ threshold = 52;
+
+ fitted = ( scaled + threshold ) & ~63;
+
+#if 1
+ if ( scaled != fitted )
+ {
+ scale = FT_MulDiv( scale, fitted, scaled );
+ FT_TRACE5(( "== scaled x-top = %.2g"
+ " fitted = %.2g, scaling = %.4g\n",
+ scaled / 64.0, fitted / 64.0,
+ ( fitted * 1.0 ) / scaled ));
+ }
+#endif
+ }
+ }
+
+ axis->scale = scale;
+ axis->delta = delta;
+
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ metrics->root.scaler.x_scale = scale;
+ metrics->root.scaler.x_delta = delta;
+ }
+ else
+ {
+ metrics->root.scaler.y_scale = scale;
+ metrics->root.scaler.y_delta = delta;
+ }
+
+ /* scale the standard widths */
+ for ( nn = 0; nn < axis->width_count; nn++ )
+ {
+ AF_Width width = axis->widths + nn;
+
+
+ width->cur = FT_MulFix( width->org, scale );
+ width->fit = width->cur;
+ }
+
+ /* an extra-light axis corresponds to a standard width that is */
+ /* smaller than 5/8 pixels */
+ axis->extra_light =
+ FT_BOOL( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
+
+ if ( dim == AF_DIMENSION_VERT )
+ {
+ /* scale the blue zones */
+ for ( nn = 0; nn < axis->blue_count; nn++ )
+ {
+ AF_LatinBlue blue = &axis->blues[nn];
+ FT_Pos dist;
+
+
+ blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta;
+ blue->ref.fit = blue->ref.cur;
+ blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
+ blue->shoot.fit = blue->shoot.cur;
+ blue->flags &= ~AF_LATIN_BLUE_ACTIVE;
+
+ /* a blue zone is only active if it is less than 3/4 pixels tall */
+ dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
+ if ( dist <= 48 && dist >= -48 )
+ {
+ FT_Pos delta1, delta2;
+
+ delta1 = blue->shoot.org - blue->ref.org;
+ delta2 = delta1;
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ delta2 = FT_MulFix( delta2, scale );
+
+ if ( delta2 < 32 )
+ delta2 = 0;
+ else if ( delta2 < 64 )
+ delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
+ else
+ delta2 = FT_PIX_ROUND( delta2 );
+
+ if ( delta1 < 0 )
+ delta2 = -delta2;
+
+ blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
+ blue->shoot.fit = blue->ref.fit + delta2;
+
+ FT_TRACE5(( ">> activating blue zone %d:"
+ " ref.cur=%.2g ref.fit=%.2g"
+ " shoot.cur=%.2g shoot.fit=%.2g\n",
+ nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0,
+ blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
+
+ blue->flags |= AF_LATIN_BLUE_ACTIVE;
+ }
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_latin2_metrics_scale( AF_LatinMetrics metrics,
+ AF_Scaler scaler )
+ {
+ metrics->root.scaler.render_mode = scaler->render_mode;
+ metrics->root.scaler.face = scaler->face;
+ metrics->root.scaler.flags = scaler->flags;
+
+ af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
+ af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
+ }
+
+
+ /* Extract standard_width from writing system/script specific */
+ /* metrics class. */
+
+ FT_LOCAL_DEF( void )
+ af_latin2_get_standard_widths( AF_LatinMetrics metrics,
+ FT_Pos* stdHW,
+ FT_Pos* stdVW )
+ {
+ if ( stdHW )
+ *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
+
+ if ( stdVW )
+ *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L Y P H A N A L Y S I S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+#define SORT_SEGMENTS
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_hints_compute_segments( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Memory memory = hints->memory;
+ FT_Error error = FT_Err_Ok;
+ AF_Segment segment = NULL;
+ AF_SegmentRec seg0;
+ AF_Point* contour = hints->contours;
+ AF_Point* contour_limit = contour + hints->num_contours;
+ AF_Direction major_dir, segment_dir;
+
+
+ FT_ZERO( &seg0 );
+ seg0.score = 32000;
+ seg0.flags = AF_EDGE_NORMAL;
+
+ major_dir = (AF_Direction)FT_ABS( axis->major_dir );
+ segment_dir = major_dir;
+
+ axis->num_segments = 0;
+
+ /* set up (u,v) in each point */
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ AF_Point point = hints->points;
+ AF_Point limit = point + hints->num_points;
+
+
+ for ( ; point < limit; point++ )
+ {
+ point->u = point->fx;
+ point->v = point->fy;
+ }
+ }
+ else
+ {
+ AF_Point point = hints->points;
+ AF_Point limit = point + hints->num_points;
+
+
+ for ( ; point < limit; point++ )
+ {
+ point->u = point->fy;
+ point->v = point->fx;
+ }
+ }
+
+ /* do each contour separately */
+ for ( ; contour < contour_limit; contour++ )
+ {
+ AF_Point point = contour[0];
+ AF_Point start = point;
+ AF_Point last = point->prev;
+
+
+ if ( point == last ) /* skip singletons -- just in case */
+ continue;
+
+ /* already on an edge ?, backtrack to find its start */
+ if ( FT_ABS( point->in_dir ) == major_dir )
+ {
+ point = point->prev;
+
+ while ( point->in_dir == start->in_dir )
+ point = point->prev;
+ }
+ else /* otherwise, find first segment start, if any */
+ {
+ while ( FT_ABS( point->out_dir ) != major_dir )
+ {
+ point = point->next;
+
+ if ( point == start )
+ goto NextContour;
+ }
+ }
+
+ start = point;
+
+ for (;;)
+ {
+ AF_Point first;
+ FT_Pos min_u, min_v, max_u, max_v;
+
+ /* we're at the start of a new segment */
+ FT_ASSERT( FT_ABS( point->out_dir ) == major_dir &&
+ point->in_dir != point->out_dir );
+ first = point;
+
+ min_u = max_u = point->u;
+ min_v = max_v = point->v;
+
+ point = point->next;
+
+ while ( point->out_dir == first->out_dir )
+ {
+ point = point->next;
+
+ if ( point->u < min_u )
+ min_u = point->u;
+
+ if ( point->u > max_u )
+ max_u = point->u;
+ }
+
+ if ( point->v < min_v )
+ min_v = point->v;
+
+ if ( point->v > max_v )
+ max_v = point->v;
+
+ /* record new segment */
+ error = af_axis_hints_new_segment( axis, memory, &segment );
+ if ( error )
+ goto Exit;
+
+ segment[0] = seg0;
+ segment->dir = first->out_dir;
+ segment->first = first;
+ segment->last = point;
+ segment->pos = (FT_Short)( ( min_u + max_u ) >> 1 );
+ segment->min_coord = (FT_Short) min_v;
+ segment->max_coord = (FT_Short) max_v;
+ segment->height = (FT_Short)( max_v - min_v );
+
+ /* a segment is round if it doesn't have successive */
+ /* on-curve points. */
+ {
+ AF_Point pt = first;
+ AF_Point last = point;
+ FT_UInt f0 = pt->flags & AF_FLAG_CONTROL;
+ FT_UInt f1;
+
+
+ segment->flags &= ~AF_EDGE_ROUND;
+
+ for ( ; pt != last; f0 = f1 )
+ {
+ pt = pt->next;
+ f1 = pt->flags & AF_FLAG_CONTROL;
+
+ if ( !f0 && !f1 )
+ break;
+
+ if ( pt == last )
+ segment->flags |= AF_EDGE_ROUND;
+ }
+ }
+
+ /* this can happen in the case of a degenerate contour
+ * e.g. a 2-point vertical contour
+ */
+ if ( point == start )
+ break;
+
+ /* jump to the start of the next segment, if any */
+ while ( FT_ABS( point->out_dir ) != major_dir )
+ {
+ point = point->next;
+
+ if ( point == start )
+ goto NextContour;
+ }
+ }
+
+ NextContour:
+ ;
+ } /* contours */
+
+ /* now slightly increase the height of segments when this makes */
+ /* sense -- this is used to better detect and ignore serifs */
+ {
+ AF_Segment segments = axis->segments;
+ AF_Segment segments_end = segments + axis->num_segments;
+
+
+ for ( segment = segments; segment < segments_end; segment++ )
+ {
+ AF_Point first = segment->first;
+ AF_Point last = segment->last;
+ AF_Point p;
+ FT_Pos first_v = first->v;
+ FT_Pos last_v = last->v;
+
+
+ if ( first_v < last_v )
+ {
+ p = first->prev;
+ if ( p->v < first_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( first_v - p->v ) >> 1 ) );
+
+ p = last->next;
+ if ( p->v > last_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( p->v - last_v ) >> 1 ) );
+ }
+ else
+ {
+ p = first->prev;
+ if ( p->v > first_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( p->v - first_v ) >> 1 ) );
+
+ p = last->next;
+ if ( p->v < last_v )
+ segment->height = (FT_Short)( segment->height +
+ ( ( last_v - p->v ) >> 1 ) );
+ }
+ }
+ }
+
+#ifdef AF_SORT_SEGMENTS
+ /* place all segments with a negative direction to the start
+ * of the array, used to speed up segment linking later...
+ */
+ {
+ AF_Segment segments = axis->segments;
+ FT_UInt count = axis->num_segments;
+ FT_UInt ii, jj;
+
+ for ( ii = 0; ii < count; ii++ )
+ {
+ if ( segments[ii].dir > 0 )
+ {
+ for ( jj = ii + 1; jj < count; jj++ )
+ {
+ if ( segments[jj].dir < 0 )
+ {
+ AF_SegmentRec tmp;
+
+
+ tmp = segments[ii];
+ segments[ii] = segments[jj];
+ segments[jj] = tmp;
+
+ break;
+ }
+ }
+
+ if ( jj == count )
+ break;
+ }
+ }
+ axis->mid_segments = ii;
+ }
+#endif
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ af_latin2_hints_link_segments( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+#ifdef AF_SORT_SEGMENTS
+ AF_Segment segment_mid = segments + axis->mid_segments;
+#endif
+ FT_Pos len_threshold, len_score;
+ AF_Segment seg1, seg2;
+
+
+ len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
+ if ( len_threshold == 0 )
+ len_threshold = 1;
+
+ len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
+
+#ifdef AF_SORT_SEGMENTS
+ for ( seg1 = segments; seg1 < segment_mid; seg1++ )
+ {
+ if ( seg1->dir != axis->major_dir )
+ continue;
+
+ for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
+#else
+ /* now compare each segment to the others */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+ if ( seg1->dir != axis->major_dir )
+ continue;
+
+ for ( seg2 = segments; seg2 < segment_limit; seg2++ )
+ if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
+#endif
+ {
+ FT_Pos pos1 = seg1->pos;
+ FT_Pos pos2 = seg2->pos;
+ FT_Pos dist = pos2 - pos1;
+
+
+ if ( dist < 0 )
+ continue;
+
+ {
+ FT_Pos min = seg1->min_coord;
+ FT_Pos max = seg1->max_coord;
+ FT_Pos len, score;
+
+
+ if ( min < seg2->min_coord )
+ min = seg2->min_coord;
+
+ if ( max > seg2->max_coord )
+ max = seg2->max_coord;
+
+ len = max - min;
+ if ( len >= len_threshold )
+ {
+ score = dist + len_score / len;
+ if ( score < seg1->score )
+ {
+ seg1->score = score;
+ seg1->link = seg2;
+ }
+
+ if ( score < seg2->score )
+ {
+ seg2->score = score;
+ seg2->link = seg1;
+ }
+ }
+ }
+ }
+ }
+#if 0
+ }
+#endif
+
+ /* now, compute the `serif' segments */
+ for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+ {
+ seg2 = seg1->link;
+
+ if ( seg2 )
+ {
+ if ( seg2->link != seg1 )
+ {
+ seg1->link = NULL;
+ seg1->serif = seg2->link;
+ }
+ }
+ }
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_hints_compute_edges( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory = hints->memory;
+ AF_LatinAxis laxis = &((AF_LatinMetrics)hints->metrics)->axis[dim];
+
+ AF_Segment segments = axis->segments;
+ AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment seg;
+
+ AF_Direction up_dir;
+ FT_Fixed scale;
+ FT_Pos edge_distance_threshold;
+ FT_Pos segment_length_threshold;
+
+
+ axis->num_edges = 0;
+
+ scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
+ : hints->y_scale;
+
+ up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
+ : AF_DIR_RIGHT;
+
+ /*
+ * We want to ignore very small (mostly serif) segments, we do that
+ * by ignoring those that whose length is less than a given fraction
+ * of the standard width. If there is no standard width, we ignore
+ * those that are less than a given size in pixels
+ *
+ * also, unlink serif segments that are linked to segments farther
+ * than 50% of the standard width
+ */
+ if ( dim == AF_DIMENSION_HORZ )
+ {
+ if ( laxis->width_count > 0 )
+ segment_length_threshold = ( laxis->standard_width * 10 ) >> 4;
+ else
+ segment_length_threshold = FT_DivFix( 64, hints->y_scale );
+ }
+ else
+ segment_length_threshold = 0;
+
+ /**********************************************************************
+ *
+ * We will begin by generating a sorted table of edges for the
+ * current direction. To do so, we simply scan each segment and try
+ * to find an edge in our table that corresponds to its position.
+ *
+ * If no edge is found, we create and insert a new edge in the
+ * sorted table. Otherwise, we simply add the segment to the edge's
+ * list which will be processed in the second step to compute the
+ * edge's properties.
+ *
+ * Note that the edges table is sorted along the segment/edge
+ * position.
+ *
+ */
+
+ edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
+ scale );
+ if ( edge_distance_threshold > 64 / 4 )
+ edge_distance_threshold = 64 / 4;
+
+ edge_distance_threshold = FT_DivFix( edge_distance_threshold,
+ scale );
+
+ for ( seg = segments; seg < segment_limit; seg++ )
+ {
+ AF_Edge found = NULL;
+ FT_Int ee;
+
+
+ if ( seg->height < segment_length_threshold )
+ continue;
+
+ /* A special case for serif edges: If they are smaller than */
+ /* 1.5 pixels we ignore them. */
+ if ( seg->serif )
+ {
+ FT_Pos dist = seg->serif->pos - seg->pos;
+
+
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( dist >= laxis->standard_width >> 1 )
+ {
+ /* unlink this serif, it is too distant from its reference stem */
+ seg->serif = NULL;
+ }
+ else if ( 2*seg->height < 3 * segment_length_threshold )
+ continue;
+ }
+
+ /* look for an edge corresponding to the segment */
+ for ( ee = 0; ee < axis->num_edges; ee++ )
+ {
+ AF_Edge edge = axis->edges + ee;
+ FT_Pos dist;
+
+
+ dist = seg->pos - edge->fpos;
+ if ( dist < 0 )
+ dist = -dist;
+
+ if ( dist < edge_distance_threshold && edge->dir == seg->dir )
+ {
+ found = edge;
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ AF_Edge edge;
+
+
+ /* insert a new edge in the list and */
+ /* sort according to the position */
+ error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, 0,
+ memory, &edge );
+ if ( error )
+ goto Exit;
+
+ /* add the segment to the new edge's list */
+ FT_ZERO( edge );
+
+ edge->first = seg;
+ edge->last = seg;
+ edge->dir = seg->dir;
+ edge->fpos = seg->pos;
+ edge->opos = FT_MulFix( seg->pos, scale );
+ edge->pos = edge->opos;
+ seg->edge_next = seg;
+ }
+ else
+ {
+ /* if an edge was found, simply add the segment to the edge's */
+ /* list */
+ seg->edge_next = found->first;
+ found->last->edge_next = seg;
+ found->last = seg;
+ }
+ }
+
+
+ /**********************************************************************
+ *
+ * Good, we will now compute each edge's properties according to
+ * segments found on its position. Basically, these are:
+ *
+ * - edge's main direction
+ * - stem edge, serif edge or both (which defaults to stem then)
+ * - rounded edge, straight or both (which defaults to straight)
+ * - link for edge
+ *
+ */
+
+ /* first of all, set the `edge' field in each segment -- this is */
+ /* required in order to compute edge links */
+
+ /*
+ * Note that removing this loop and setting the `edge' field of each
+ * segment directly in the code above slows down execution speed for
+ * some reasons on platforms like the Sun.
+ */
+ {
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge;
+
+
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ seg = edge->first;
+ if ( seg )
+ do
+ {
+ seg->edge = edge;
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+ }
+
+ /* now, compute each edge properties */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ FT_Int is_round = 0; /* does it contain round segments? */
+ FT_Int is_straight = 0; /* does it contain straight segments? */
+#if 0
+ FT_Pos ups = 0; /* number of upwards segments */
+ FT_Pos downs = 0; /* number of downwards segments */
+#endif
+
+
+ seg = edge->first;
+
+ do
+ {
+ FT_Bool is_serif;
+
+
+ /* check for roundness of segment */
+ if ( seg->flags & AF_EDGE_ROUND )
+ is_round++;
+ else
+ is_straight++;
+
+#if 0
+ /* check for segment direction */
+ if ( seg->dir == up_dir )
+ ups += seg->max_coord-seg->min_coord;
+ else
+ downs += seg->max_coord-seg->min_coord;
+#endif
+
+ /* check for links -- if seg->serif is set, then seg->link must */
+ /* be ignored */
+ is_serif = FT_BOOL( seg->serif &&
+ seg->serif->edge &&
+ seg->serif->edge != edge );
+
+ if ( ( seg->link && seg->link->edge ) || is_serif )
+ {
+ AF_Edge edge2;
+ AF_Segment seg2;
+
+
+ edge2 = edge->link;
+ seg2 = seg->link;
+
+ if ( is_serif )
+ {
+ seg2 = seg->serif;
+ edge2 = edge->serif;
+ }
+
+ if ( edge2 )
+ {
+ FT_Pos edge_delta;
+ FT_Pos seg_delta;
+
+
+ edge_delta = edge->fpos - edge2->fpos;
+ if ( edge_delta < 0 )
+ edge_delta = -edge_delta;
+
+ seg_delta = seg->pos - seg2->pos;
+ if ( seg_delta < 0 )
+ seg_delta = -seg_delta;
+
+ if ( seg_delta < edge_delta )
+ edge2 = seg2->edge;
+ }
+ else
+ edge2 = seg2->edge;
+
+ if ( is_serif )
+ {
+ edge->serif = edge2;
+ edge2->flags |= AF_EDGE_SERIF;
+ }
+ else
+ edge->link = edge2;
+ }
+
+ seg = seg->edge_next;
+
+ } while ( seg != edge->first );
+
+ /* set the round/straight flags */
+ edge->flags = AF_EDGE_NORMAL;
+
+ if ( is_round > 0 && is_round >= is_straight )
+ edge->flags |= AF_EDGE_ROUND;
+
+#if 0
+ /* set the edge's main direction */
+ edge->dir = AF_DIR_NONE;
+
+ if ( ups > downs )
+ edge->dir = (FT_Char)up_dir;
+
+ else if ( ups < downs )
+ edge->dir = (FT_Char)-up_dir;
+
+ else if ( ups == downs )
+ edge->dir = 0; /* both up and down! */
+#endif
+
+ /* gets rid of serifs if link is set */
+ /* XXX: This gets rid of many unpleasant artefacts! */
+ /* Example: the `c' in cour.pfa at size 13 */
+
+ if ( edge->serif && edge->link )
+ edge->serif = NULL;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ af_latin2_hints_detect_features( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ FT_Error error;
+
+
+ error = af_latin2_hints_compute_segments( hints, dim );
+ if ( !error )
+ {
+ af_latin2_hints_link_segments( hints, dim );
+
+ error = af_latin2_hints_compute_edges( hints, dim );
+ }
+ return error;
+ }
+
+
+ static void
+ af_latin2_hints_compute_blue_edges( AF_GlyphHints hints,
+ AF_LatinMetrics metrics )
+ {
+ AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT];
+ AF_Edge edge = axis->edges;
+ AF_Edge edge_limit = edge + axis->num_edges;
+ AF_LatinAxis latin = &metrics->axis[AF_DIMENSION_VERT];
+ FT_Fixed scale = latin->scale;
+ FT_Pos best_dist0; /* initial threshold */
+
+
+ /* compute the initial threshold as a fraction of the EM size */
+ best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
+
+ if ( best_dist0 > 64 / 2 )
+ best_dist0 = 64 / 2;
+
+ /* compute which blue zones are active, i.e. have their scaled */
+ /* size < 3/4 pixels */
+
+ /* for each horizontal edge search the blue zone which is closest */
+ for ( ; edge < edge_limit; edge++ )
+ {
+ FT_Int bb;
+ AF_Width best_blue = NULL;
+ FT_Pos best_dist = best_dist0;
+
+ for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
+ {
+ AF_LatinBlue blue = latin->blues + bb;
+ FT_Bool is_top_blue, is_major_dir;
+
+
+ /* skip inactive blue zones (i.e., those that are too small) */
+ if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
+ continue;
+
+ /* if it is a top zone, check for right edges -- if it is a bottom */
+ /* zone, check for left edges */
+ /* */
+ /* of course, that's for TrueType */
+ is_top_blue = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
+ is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
+
+ /* if it is a top zone, the edge must be against the major */
+ /* direction; if it is a bottom zone, it must be in the major */
+ /* direction */
+ if ( is_top_blue ^ is_major_dir )
+ {
+ FT_Pos dist;
+ AF_Width compare;
+
+
+ /* if it's a rounded edge, compare it to the overshoot position */
+ /* if it's a flat edge, compare it to the reference position */
+ if ( edge->flags & AF_EDGE_ROUND )
+ compare = &blue->shoot;
+ else
+ compare = &blue->ref;
+
+ dist = edge->fpos - compare->org;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = compare;
+ }
+
+#if 0
+ /* now, compare it to the overshoot position if the edge is */
+ /* rounded, and if the edge is over the reference position of a */
+ /* top zone, or under the reference position of a bottom zone */
+ if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
+ {
+ FT_Bool is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
+
+
+ if ( is_top_blue ^ is_under_ref )
+ {
+ blue = latin->blues + bb;
+ dist = edge->fpos - blue->shoot.org;
+ if ( dist < 0 )
+ dist = -dist;
+
+ dist = FT_MulFix( dist, scale );
+ if ( dist < best_dist )
+ {
+ best_dist = dist;
+ best_blue = & blue->shoot;
+ }
+ }
+ }
+#endif
+ }
+ }
+
+ if ( best_blue )
+ edge->blue_edge = best_blue;
+ }
+ }
+
+
+ static FT_Error
+ af_latin2_hints_init( AF_GlyphHints hints,
+ AF_LatinMetrics metrics )
+ {
+ FT_Render_Mode mode;
+ FT_UInt32 scaler_flags, other_flags;
+ FT_Face face = metrics->root.scaler.face;
+
+
+ af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
+
+ /*
+ * correct x_scale and y_scale if needed, since they may have
+ * been modified `af_latin2_metrics_scale_dim' above
+ */
+ hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
+ hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
+ hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
+ hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
+
+ /* compute flags depending on render mode, etc. */
+ mode = metrics->root.scaler.render_mode;
+
+#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
+ if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
+ metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
+#endif
+
+ scaler_flags = hints->scaler_flags;
+ other_flags = 0;
+
+ /*
+ * We snap the width of vertical stems for the monochrome and
+ * horizontal LCD rendering targets only.
+ */
+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
+ other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
+
+ /*
+ * We snap the width of horizontal stems for the monochrome and
+ * vertical LCD rendering targets only.
+ */
+ if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
+ other_flags |= AF_LATIN_HINTS_VERT_SNAP;
+
+ /*
+ * We adjust stems to full pixels unless in `light' or `lcd' mode.
+ */
+ if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD )
+ other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
+
+ if ( mode == FT_RENDER_MODE_MONO )
+ other_flags |= AF_LATIN_HINTS_MONO;
+
+ /*
+ * In `light' or `lcd' mode we disable horizontal hinting completely.
+ * We also do it if the face is italic.
+ */
+ if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD ||
+ ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
+ scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
+
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ /* get (global) warper flag */
+ if ( !metrics->root.globals->module->warping )
+ scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
+#endif
+
+ hints->scaler_flags = scaler_flags;
+ hints->other_flags = other_flags;
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N G L Y P H G R I D - F I T T I N G *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* snap a given width in scaled coordinates to one of the */
+ /* current standard widths */
+
+ static FT_Pos
+ af_latin2_snap_width( AF_Width widths,
+ FT_UInt count,
+ FT_Pos width )
+ {
+ FT_UInt n;
+ FT_Pos best = 64 + 32 + 2;
+ FT_Pos reference = width;
+ FT_Pos scaled;
+
+
+ for ( n = 0; n < count; n++ )
+ {
+ FT_Pos w;
+ FT_Pos dist;
+
+
+ w = widths[n].cur;
+ dist = width - w;
+ if ( dist < 0 )
+ dist = -dist;
+ if ( dist < best )
+ {
+ best = dist;
+ reference = w;
+ }
+ }
+
+ scaled = FT_PIX_ROUND( reference );
+
+ if ( width >= reference )
+ {
+ if ( width < scaled + 48 )
+ width = reference;
+ }
+ else
+ {
+ if ( width > scaled - 48 )
+ width = reference;
+ }
+
+ return width;
+ }
+
+
+ /* compute the snapped width of a given stem */
+
+ static FT_Pos
+ af_latin2_compute_stem_width( AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Pos width,
+ FT_UInt base_flags,
+ FT_UInt stem_flags )
+ {
+ AF_LatinMetrics metrics = (AF_LatinMetrics) hints->metrics;
+ AF_LatinAxis axis = & metrics->axis[dim];
+ FT_Pos dist = width;
+ FT_Int sign = 0;
+ FT_Int vertical = ( dim == AF_DIMENSION_VERT );
+
+ FT_UNUSED( base_flags );
+
+
+ if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
+ axis->extra_light )
+ return width;
+
+ if ( dist < 0 )
+ {
+ dist = -width;
+ sign = 1;
+ }
+
+ if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
+ ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
+ {
+ /* smooth hinting process: very lightly quantize the stem width */
+
+ /* leave the widths of serifs alone */
+
+ if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
+ goto Done_Width;
+
+#if 0
+ else if ( ( base_flags & AF_EDGE_ROUND ) )
+ {
+ if ( dist < 80 )
+ dist = 64;
+ }
+ else if ( dist < 56 )
+ dist = 56;
+#endif
+ if ( axis->width_count > 0 )
+ {
+ FT_Pos delta;
+
+
+ /* compare to standard width */
+ if ( axis->width_count > 0 )
+ {
+ delta = dist - axis->widths[0].cur;
+
+ if ( delta < 0 )
+ delta = -delta;
+
+ if ( delta < 40 )
+ {
+ dist = axis->widths[0].cur;
+ if ( dist < 48 )
+ dist = 48;
+
+ goto Done_Width;
+ }
+ }
+
+ if ( dist < 3 * 64 )
+ {
+ delta = dist & 63;
+ dist &= -64;
+
+ if ( delta < 10 )
+ dist += delta;
+
+ else if ( delta < 32 )
+ dist += 10;
+
+ else if ( delta < 54 )
+ dist += 54;
+
+ else
+ dist += delta;
+ }
+ else
+ dist = ( dist + 32 ) & ~63;
+ }
+ }
+ else
+ {
+ /* strong hinting process: snap the stem width to integer pixels */
+ FT_Pos org_dist = dist;
+
+
+ dist = af_latin2_snap_width( axis->widths, axis->width_count, dist );
+
+ if ( vertical )
+ {
+ /* in the case of vertical hinting, always round */
+ /* the stem heights to integer pixels */
+
+ if ( dist >= 64 )
+ dist = ( dist + 16 ) & ~63;
+ else
+ dist = 64;
+ }
+ else
+ {
+ if ( AF_LATIN_HINTS_DO_MONO( hints ) )
+ {
+ /* monochrome horizontal hinting: snap widths to integer pixels */
+ /* with a different threshold */
+
+ if ( dist < 64 )
+ dist = 64;
+ else
+ dist = ( dist + 32 ) & ~63;
+ }
+ else
+ {
+ /* for horizontal anti-aliased hinting, we adopt a more subtle */
+ /* approach: we strengthen small stems, round stems whose size */
+ /* is between 1 and 2 pixels to an integer, otherwise nothing */
+
+ if ( dist < 48 )
+ dist = ( dist + 64 ) >> 1;
+
+ else if ( dist < 128 )
+ {
+ /* We only round to an integer width if the corresponding */
+ /* distortion is less than 1/4 pixel. Otherwise this */
+ /* makes everything worse since the diagonals, which are */
+ /* not hinted, appear a lot bolder or thinner than the */
+ /* vertical stems. */
+
+ FT_Int delta;
+
+
+ dist = ( dist + 22 ) & ~63;
+ delta = dist - org_dist;
+ if ( delta < 0 )
+ delta = -delta;
+
+ if ( delta >= 16 )
+ {
+ dist = org_dist;
+ if ( dist < 48 )
+ dist = ( dist + 64 ) >> 1;
+ }
+ }
+ else
+ /* round otherwise to prevent color fringes in LCD mode */
+ dist = ( dist + 32 ) & ~63;
+ }
+ }
+ }
+
+ Done_Width:
+ if ( sign )
+ dist = -dist;
+
+ return dist;
+ }
+
+
+ /* align one stem edge relative to the previous stem edge */
+
+ static void
+ af_latin2_align_linked_edge( AF_GlyphHints hints,
+ AF_Dimension dim,
+ AF_Edge base_edge,
+ AF_Edge stem_edge )
+ {
+ FT_Pos dist = stem_edge->opos - base_edge->opos;
+
+ FT_Pos fitted_width = af_latin2_compute_stem_width( hints, dim, dist,
+ base_edge->flags,
+ stem_edge->flags );
+
+
+ stem_edge->pos = base_edge->pos + fitted_width;
+
+ FT_TRACE5(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
+ "dist was %.2f, now %.2f\n",
+ stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
+ stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
+ }
+
+
+ static void
+ af_latin2_align_serif_edge( AF_GlyphHints hints,
+ AF_Edge base,
+ AF_Edge serif )
+ {
+ FT_UNUSED( hints );
+
+ serif->pos = base->pos + ( serif->opos - base->opos );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** E D G E H I N T I N G ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ static void
+ af_latin2_hint_edges( AF_GlyphHints hints,
+ AF_Dimension dim )
+ {
+ AF_AxisHints axis = &hints->axis[dim];
+ AF_Edge edges = axis->edges;
+ AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge;
+ AF_Edge anchor = NULL;
+ FT_Int has_serifs = 0;
+ FT_Pos anchor_drift = 0;
+
+
+
+ FT_TRACE5(( "==== hinting %s edges =====\n",
+ dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
+
+ /* we begin by aligning all stems relative to the blue zone */
+ /* if needed -- that's only for horizontal edges */
+
+ if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
+ {
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Width blue;
+ AF_Edge edge1, edge2;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ blue = edge->blue_edge;
+ edge1 = NULL;
+ edge2 = edge->link;
+
+ if ( blue )
+ {
+ edge1 = edge;
+ }
+ else if ( edge2 && edge2->blue_edge )
+ {
+ blue = edge2->blue_edge;
+ edge1 = edge2;
+ edge2 = edge;
+ }
+
+ if ( !edge1 )
+ continue;
+
+ FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
+ "was (%.2f)\n",
+ edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
+ edge1->pos / 64.0 ));
+
+ edge1->pos = blue->fit;
+ edge1->flags |= AF_EDGE_DONE;
+
+ if ( edge2 && !edge2->blue_edge )
+ {
+ af_latin2_align_linked_edge( hints, dim, edge1, edge2 );
+ edge2->flags |= AF_EDGE_DONE;
+ }
+
+ if ( !anchor )
+ {
+ anchor = edge;
+
+ anchor_drift = ( anchor->pos - anchor->opos );
+ if ( edge2 )
+ anchor_drift = ( anchor_drift +
+ ( edge2->pos - edge2->opos ) ) >> 1;
+ }
+ }
+ }
+
+ /* now we will align all stem edges, trying to maintain the */
+ /* relative order of stems in the glyph */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ AF_Edge edge2;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ /* skip all non-stem edges */
+ edge2 = edge->link;
+ if ( !edge2 )
+ {
+ has_serifs++;
+ continue;
+ }
+
+ /* now align the stem */
+
+ /* this should not happen, but it's better to be safe */
+ if ( edge2->blue_edge )
+ {
+ FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
+
+ af_latin2_align_linked_edge( hints, dim, edge2, edge );
+ edge->flags |= AF_EDGE_DONE;
+ continue;
+ }
+
+ if ( !anchor )
+ {
+ FT_Pos org_len, org_center, cur_len;
+ FT_Pos cur_pos1, error1, error2, u_off, d_off;
+
+
+ org_len = edge2->opos - edge->opos;
+ cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
+ edge->flags,
+ edge2->flags );
+ if ( cur_len <= 64 )
+ u_off = d_off = 32;
+ else
+ {
+ u_off = 38;
+ d_off = 26;
+ }
+
+ if ( cur_len < 96 )
+ {
+ org_center = edge->opos + ( org_len >> 1 );
+
+ cur_pos1 = FT_PIX_ROUND( org_center );
+
+ error1 = org_center - ( cur_pos1 - u_off );
+ if ( error1 < 0 )
+ error1 = -error1;
+
+ error2 = org_center - ( cur_pos1 + d_off );
+ if ( error2 < 0 )
+ error2 = -error2;
+
+ if ( error1 < error2 )
+ cur_pos1 -= u_off;
+ else
+ cur_pos1 += d_off;
+
+ edge->pos = cur_pos1 - cur_len / 2;
+ edge2->pos = edge->pos + cur_len;
+ }
+ else
+ edge->pos = FT_PIX_ROUND( edge->opos );
+
+ FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
+ " snapped to (%.2f) (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0 ));
+ anchor = edge;
+
+ edge->flags |= AF_EDGE_DONE;
+
+ af_latin2_align_linked_edge( hints, dim, edge, edge2 );
+
+ edge2->flags |= AF_EDGE_DONE;
+
+ anchor_drift = ( ( anchor->pos - anchor->opos ) +
+ ( edge2->pos - edge2->opos ) ) >> 1;
+
+ FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
+ }
+ else
+ {
+ FT_Pos org_pos, org_len, org_center, cur_center, cur_len;
+ FT_Pos org_left, org_right;
+
+
+ org_pos = edge->opos + anchor_drift;
+ org_len = edge2->opos - edge->opos;
+ org_center = org_pos + ( org_len >> 1 );
+
+ cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
+ edge->flags,
+ edge2->flags );
+
+ org_left = org_pos + ( ( org_len - cur_len ) >> 1 );
+ org_right = org_pos + ( ( org_len + cur_len ) >> 1 );
+
+ FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
+ org_left / 64.0, org_right / 64.0 ));
+ cur_center = org_center;
+
+ if ( edge2->flags & AF_EDGE_DONE )
+ {
+ FT_TRACE5(( "\n" ));
+ edge->pos = edge2->pos - cur_len;
+ }
+ else
+ {
+ /* we want to compare several displacement, and choose
+ * the one that increases fitness while minimizing
+ * distortion as well
+ */
+ FT_Pos displacements[6], scores[6], org, fit, delta;
+ FT_UInt count = 0;
+
+ /* note: don't even try to fit tiny stems */
+ if ( cur_len < 32 )
+ {
+ FT_TRACE5(( "tiny stem\n" ));
+ goto AlignStem;
+ }
+
+ /* if the span is within a single pixel, don't touch it */
+ if ( FT_PIX_FLOOR( org_left ) == FT_PIX_CEIL( org_right ) )
+ {
+ FT_TRACE5(( "single pixel stem\n" ));
+ goto AlignStem;
+ }
+
+ if ( cur_len <= 96 )
+ {
+ /* we want to avoid the absolute worst case which is
+ * when the left and right edges of the span each represent
+ * about 50% of the gray. we'd better want to change this
+ * to 25/75%, since this is much more pleasant to the eye with
+ * very acceptable distortion
+ */
+ FT_Pos frac_left = org_left & 63;
+ FT_Pos frac_right = org_right & 63;
+
+ if ( frac_left >= 22 && frac_left <= 42 &&
+ frac_right >= 22 && frac_right <= 42 )
+ {
+ org = frac_left;
+ fit = ( org <= 32 ) ? 16 : 48;
+ delta = FT_ABS( fit - org );
+ displacements[count] = fit - org;
+ scores[count++] = delta;
+ FT_TRACE5(( "dispA=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
+
+ org = frac_right;
+ fit = ( org <= 32 ) ? 16 : 48;
+ delta = FT_ABS( fit - org );
+ displacements[count] = fit - org;
+ scores[count++] = delta;
+ FT_TRACE5(( "dispB=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
+ }
+ }
+
+ /* snapping the left edge to the grid */
+ org = org_left;
+ fit = FT_PIX_ROUND( org );
+ delta = FT_ABS( fit - org );
+ displacements[count] = fit - org;
+ scores[count++] = delta;
+ FT_TRACE5(( "dispC=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
+
+ /* snapping the right edge to the grid */
+ org = org_right;
+ fit = FT_PIX_ROUND( org );
+ delta = FT_ABS( fit - org );
+ displacements[count] = fit - org;
+ scores[count++] = delta;
+ FT_TRACE5(( "dispD=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
+
+ /* now find the best displacement */
+ {
+ FT_Pos best_score = scores[0];
+ FT_Pos best_disp = displacements[0];
+ FT_UInt nn;
+
+ for ( nn = 1; nn < count; nn++ )
+ {
+ if ( scores[nn] < best_score )
+ {
+ best_score = scores[nn];
+ best_disp = displacements[nn];
+ }
+ }
+
+ cur_center = org_center + best_disp;
+ }
+ FT_TRACE5(( "\n" ));
+ }
+
+ AlignStem:
+ edge->pos = cur_center - ( cur_len >> 1 );
+ edge2->pos = edge->pos + cur_len;
+
+ FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
+ " snapped to (%.2f) and (%.2f),"
+ " org_len=%.2f cur_len=%.2f\n",
+ edge-edges, edge->opos / 64.0,
+ edge2-edges, edge2->opos / 64.0,
+ edge->pos / 64.0, edge2->pos / 64.0,
+ org_len / 64.0, cur_len / 64.0 ));
+
+ edge->flags |= AF_EDGE_DONE;
+ edge2->flags |= AF_EDGE_DONE;
+
+ if ( edge > edges && edge->pos < edge[-1].pos )
+ {
+ FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
+ edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+ edge->pos = edge[-1].pos;
+ }
+ }
+ }
+
+ /* make sure that lowercase m's maintain their symmetry */
+
+ /* In general, lowercase m's have six vertical edges if they are sans */
+ /* serif, or twelve if they are with serifs. This implementation is */
+ /* based on that assumption, and seems to work very well with most */
+ /* faces. However, if for a certain face this assumption is not */
+ /* true, the m is just rendered like before. In addition, any stem */
+ /* correction will only be applied to symmetrical glyphs (even if the */
+ /* glyph is not an m), so the potential for unwanted distortion is */
+ /* relatively low. */
+
+ /* We don't handle horizontal edges since we can't easily assure that */
+ /* the third (lowest) stem aligns with the base line; it might end up */
+ /* one pixel higher or lower. */
+
+#if 0
+ {
+ FT_Int n_edges = edge_limit - edges;
+
+
+ if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
+ {
+ AF_Edge edge1, edge2, edge3;
+ FT_Pos dist1, dist2, span, delta;
+
+
+ if ( n_edges == 6 )
+ {
+ edge1 = edges;
+ edge2 = edges + 2;
+ edge3 = edges + 4;
+ }
+ else
+ {
+ edge1 = edges + 1;
+ edge2 = edges + 5;
+ edge3 = edges + 9;
+ }
+
+ dist1 = edge2->opos - edge1->opos;
+ dist2 = edge3->opos - edge2->opos;
+
+ span = dist1 - dist2;
+ if ( span < 0 )
+ span = -span;
+
+ if ( span < 8 )
+ {
+ delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
+ edge3->pos -= delta;
+ if ( edge3->link )
+ edge3->link->pos -= delta;
+
+ /* move the serifs along with the stem */
+ if ( n_edges == 12 )
+ {
+ ( edges + 8 )->pos -= delta;
+ ( edges + 11 )->pos -= delta;
+ }
+
+ edge3->flags |= AF_EDGE_DONE;
+ if ( edge3->link )
+ edge3->link->flags |= AF_EDGE_DONE;
+ }
+ }
+ }
+#endif
+
+ if ( has_serifs || !anchor )
+ {
+ /*
+ * now hint the remaining edges (serifs and single) in order
+ * to complete our processing
+ */
+ for ( edge = edges; edge < edge_limit; edge++ )
+ {
+ FT_Pos delta;
+
+
+ if ( edge->flags & AF_EDGE_DONE )
+ continue;
+
+ delta = 1000;
+
+ if ( edge->serif )
+ {
+ delta = edge->serif->opos - edge->opos;
+ if ( delta < 0 )
+ delta = -delta;
+ }
+
+ if ( delta < 64 + 16 )
+ {
+ af_latin2_align_serif_edge( hints, edge->serif, edge );
+ FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
+ " aligned to (%.2f)\n",
+ edge-edges, edge->opos / 64.0,
+ edge->serif - edges, edge->serif->opos / 64.0,
+ edge->pos / 64.0 ));
+ }
+ else if ( !anchor )
+ {
+ FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ edge->pos = FT_PIX_ROUND( edge->opos );
+ anchor = edge;
+ }
+ else
+ {
+ AF_Edge before, after;
+
+
+ for ( before = edge - 1; before >= edges; before-- )
+ if ( before->flags & AF_EDGE_DONE )
+ break;
+
+ for ( after = edge + 1; after < edge_limit; after++ )
+ if ( after->flags & AF_EDGE_DONE )
+ break;
+
+ if ( before >= edges && before < edge &&
+ after < edge_limit && after > edge )
+ {
+ if ( after->opos == before->opos )
+ edge->pos = before->pos;
+ else
+ edge->pos = before->pos +
+ FT_MulDiv( edge->opos - before->opos,
+ after->pos - before->pos,
+ after->opos - before->opos );
+ FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
+ " from %d (opos=%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0,
+ before - edges, before->opos / 64.0 ));
+ }
+ else
+ {
+ edge->pos = anchor->pos +
+ ( ( edge->opos - anchor->opos + 16 ) & ~31 );
+
+ FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)"
+ " snapped to (%.2f)\n",
+ edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
+ }
+ }
+
+ edge->flags |= AF_EDGE_DONE;
+
+ if ( edge > edges && edge->pos < edge[-1].pos )
+ edge->pos = edge[-1].pos;
+
+ if ( edge + 1 < edge_limit &&
+ edge[1].flags & AF_EDGE_DONE &&
+ edge->pos > edge[1].pos )
+ edge->pos = edge[1].pos;
+ }
+ }
+ }
+
+
+ static FT_Error
+ af_latin2_hints_apply( FT_UInt glyph_index,
+ AF_GlyphHints hints,
+ FT_Outline* outline,
+ AF_LatinMetrics metrics )
+ {
+ FT_Error error;
+ int dim;
+
+ FT_UNUSED( glyph_index );
+
+
+ error = af_glyph_hints_reload( hints, outline );
+ if ( error )
+ goto Exit;
+
+ /* analyze glyph outline */
+ if ( AF_HINTS_DO_HORIZONTAL( hints ) )
+ {
+ error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ );
+ if ( error )
+ goto Exit;
+ }
+
+ if ( AF_HINTS_DO_VERTICAL( hints ) )
+ {
+ error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT );
+ if ( error )
+ goto Exit;
+
+ af_latin2_hints_compute_blue_edges( hints, metrics );
+ }
+
+ /* grid-fit the outline */
+ for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
+ {
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ if ( dim == AF_DIMENSION_HORZ &&
+ metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
+ AF_HINTS_DO_WARP( hints ) )
+ {
+ AF_WarperRec warper;
+ FT_Fixed scale;
+ FT_Pos delta;
+
+
+ af_warper_compute( &warper, hints, dim, &scale, &delta );
+ af_glyph_hints_scale_dim( hints, dim, scale, delta );
+ continue;
+ }
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
+
+ if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
+ ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) )
+ {
+ af_latin2_hint_edges( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
+ af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
+ }
+ }
+ af_glyph_hints_save( hints, outline );
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** L A T I N S C R I P T C L A S S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ AF_DEFINE_WRITING_SYSTEM_CLASS(
+ af_latin2_writing_system_class,
+
+ AF_WRITING_SYSTEM_LATIN2,
+
+ sizeof ( AF_LatinMetricsRec ),
+
+ (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init, /* style_metrics_init */
+ (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale, /* style_metrics_scale */
+ (AF_WritingSystem_DoneMetricsFunc) NULL, /* style_metrics_done */
+ (AF_WritingSystem_GetStdWidthsFunc)af_latin2_get_standard_widths, /* style_metrics_getstdw */
+
+ (AF_WritingSystem_InitHintsFunc) af_latin2_hints_init, /* style_hints_init */
+ (AF_WritingSystem_ApplyHintsFunc) af_latin2_hints_apply /* style_hints_apply */
+ )
+
+#else /* !FT_OPTION_AUTOFIT2 */
+
+ /* ANSI C doesn't like empty source files */
+ typedef int _af_latin2_dummy;
+
+#endif /* !FT_OPTION_AUTOFIT2 */
+
+
+/* END */
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin2.h b/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin2.h
new file mode 100644
index 00000000000..c2aebc49acf
--- /dev/null
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/aflatin2.h
@@ -0,0 +1,46 @@
+/* ATTENTION: This file doesn't compile. It is only here as a reference */
+/* of an alternative latin hinting algorithm that was always */
+/* marked as experimental. */
+
+
+/****************************************************************************
+ *
+ * aflatin2.h
+ *
+ * Auto-fitter hinting routines for latin writing system
+ * (specification).
+ *
+ * Copyright (C) 2003-2020 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef AFLATIN2_H_
+#define AFLATIN2_H_
+
+#include "afhints.h"
+
+
+FT_BEGIN_HEADER
+
+
+ /* the `latin' writing system */
+
+ AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin2_writing_system_class )
+
+
+/* */
+
+FT_END_HEADER
+
+#endif /* AFLATIN_H_ */
+
+
+/* END */
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afloader.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afloader.c
index a06d49ad7e5..c35d85c4cfb 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afloader.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afloader.c
@@ -4,7 +4,7 @@
*
* Auto-fitter glyph loading routines (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -105,6 +105,7 @@
globals->stem_darkening_for_ppem;
FT_Fixed em_size = af_intToFixed( face->units_per_EM );
+ FT_Fixed em_ratio = FT_DivFix( af_intToFixed( 1000 ), em_size );
FT_Matrix scale_down_matrix = { 0x10000L, 0, 0, 0x10000L };
@@ -141,11 +142,12 @@
darken_by_font_units_x =
- af_loader_compute_darkening( loader,
- face,
- stdVW ) ;
- darken_x = FT_MulFix( darken_by_font_units_x,
- size_metrics->x_scale );
+ af_intToFixed( af_loader_compute_darkening( loader,
+ face,
+ stdVW ) );
+ darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x,
+ size_metrics->x_scale ),
+ em_ratio );
globals->standard_vertical_width = stdVW;
globals->stem_darkening_for_ppem = size_metrics->x_ppem;
@@ -159,11 +161,12 @@
darken_by_font_units_y =
- af_loader_compute_darkening( loader,
- face,
- stdHW ) ;
- darken_y = FT_MulFix( darken_by_font_units_y,
- size_metrics->y_scale );
+ af_intToFixed( af_loader_compute_darkening( loader,
+ face,
+ stdHW ) );
+ darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y,
+ size_metrics->y_scale ),
+ em_ratio );
globals->standard_horizontal_width = stdHW;
globals->stem_darkening_for_ppem = size_metrics->x_ppem;
@@ -297,6 +300,12 @@
if ( error )
goto Exit;
+#ifdef FT_OPTION_AUTOFIT2
+ /* XXX: undocumented hook to activate the latin2 writing system. */
+ if ( load_flags & ( 1UL << 20 ) )
+ style_options = AF_STYLE_LTN2_DFLT;
+#endif
+
/*
* Glyphs (really code points) are assigned to scripts. Script
* analysis is done lazily: For each glyph that passes through here,
@@ -473,8 +482,8 @@
FT_Pos pp2x = loader->pp2.x;
- loader->pp1.x = FT_PIX_ROUND( pp1x );
- loader->pp2.x = FT_PIX_ROUND( pp2x );
+ loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
+ loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );
slot->lsb_delta = loader->pp1.x - pp1x;
slot->rsb_delta = loader->pp2.x - pp2x;
@@ -585,7 +594,7 @@
*
* XXX: Currently a crude adaption of the original algorithm. Do better?
*/
- FT_LOCAL_DEF( FT_Fixed )
+ FT_LOCAL_DEF( FT_Int32 )
af_loader_compute_darkening( AF_Loader loader,
FT_Face face,
FT_Pos standard_width )
@@ -704,7 +713,7 @@
}
/* Convert darken_amount from per 1000 em to true character space. */
- return FT_DivFix( darken_amount, em_ratio );
+ return af_fixedToInt( FT_DivFix( darken_amount, em_ratio ) );
}
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afloader.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afloader.h
index b4936a8722b..97282371cd4 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afloader.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afloader.h
@@ -4,7 +4,7 @@
*
* Auto-fitter glyph loading routines (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -75,7 +75,7 @@ FT_BEGIN_HEADER
FT_UInt gindex,
FT_Int32 load_flags );
- FT_LOCAL_DEF( FT_Fixed )
+ FT_LOCAL_DEF( FT_Int32 )
af_loader_compute_darkening( AF_Loader loader,
FT_Face face,
FT_Pos standard_width );
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.c
index 76f9b3733b3..e16494460eb 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
*
* Auto-fitter module implementation (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -48,7 +48,7 @@
int _af_debug_disable_blue_hints;
/* we use a global object instead of a local one for debugging */
- static AF_GlyphHintsRec _af_debug_hints_rec[1];
+ AF_GlyphHintsRec _af_debug_hints_rec[1];
void* _af_debug_hints = _af_debug_hints_rec;
#endif
@@ -148,7 +148,7 @@
if ( !af_style_classes[ss] )
{
- FT_TRACE2(( "af_property_set: Invalid value %d for property `%s'\n",
+ FT_TRACE0(( "af_property_set: Invalid value %d for property `%s'\n",
*fallback_script, property_name ));
return FT_THROW( Invalid_Argument );
}
@@ -190,6 +190,35 @@
return error;
}
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ else if ( !ft_strcmp( property_name, "warping" ) )
+ {
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ if ( value_is_string )
+ {
+ const char* s = (const char*)value;
+ long w = ft_strtol( s, NULL, 10 );
+
+
+ if ( w == 0 )
+ module->warping = 0;
+ else if ( w == 1 )
+ module->warping = 1;
+ else
+ return FT_THROW( Invalid_Argument );
+ }
+ else
+#endif
+ {
+ FT_Bool* warping = (FT_Bool*)value;
+
+
+ module->warping = *warping;
+ }
+
+ return error;
+ }
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
FT_Int* darken_params;
@@ -278,7 +307,7 @@
return error;
}
- FT_TRACE2(( "af_property_set: missing property `%s'\n",
+ FT_TRACE0(( "af_property_set: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
@@ -293,6 +322,9 @@
AF_Module module = (AF_Module)ft_module;
FT_UInt fallback_style = module->fallback_style;
FT_UInt default_script = module->default_script;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ FT_Bool warping = module->warping;
+#endif
if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
@@ -339,6 +371,17 @@
return error;
}
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ else if ( !ft_strcmp( property_name, "warping" ) )
+ {
+ FT_Bool* val = (FT_Bool*)value;
+
+
+ *val = warping;
+
+ return error;
+ }
+#endif /* AF_CONFIG_OPTION_USE_WARPER */
else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
FT_Int* darken_params = module->darken_params;
@@ -367,7 +410,7 @@
return error;
}
- FT_TRACE2(( "af_property_get: missing property `%s'\n",
+ FT_TRACE0(( "af_property_get: missing property `%s'\n",
property_name ));
return FT_THROW( Missing_Property );
}
@@ -404,6 +447,9 @@
module->fallback_style = AF_STYLE_FALLBACK;
module->default_script = AF_SCRIPT_DEFAULT;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ module->warping = 0;
+#endif
module->no_stem_darkening = TRUE;
module->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.h
index c5bd4682015..e8fe4a93aad 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
*
* Auto-fitter module implementation (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -37,6 +37,9 @@ FT_BEGIN_HEADER
FT_UInt fallback_style;
FT_UInt default_script;
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ FT_Bool warping;
+#endif
FT_Bool no_stem_darkening;
FT_Int darken_params[8];
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afranges.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afranges.c
index e06f182dd0d..c8ebf5e7849 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afranges.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afranges.c
@@ -4,7 +4,7 @@
*
* Auto-fitter Unicode script ranges (body).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afranges.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afranges.h
index 841d630aab6..c2ffda4b0f9 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afranges.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afranges.h
@@ -4,7 +4,7 @@
*
* Auto-fitter Unicode script ranges (specification).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afscript.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afscript.h
index af78d573e11..4cf9cc19f58 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afscript.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afscript.h
@@ -4,7 +4,7 @@
*
* Auto-fitter scripts (specification only).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.c
index 5d078937e18..bbf7b6b1f9a 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.c
@@ -4,7 +4,7 @@
*
* HarfBuzz interface for accessing OpenType features (body).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -132,24 +132,13 @@
/* Convert a HarfBuzz script tag into the corresponding OpenType */
/* tag or tags -- some Indic scripts like Devanagari have an old */
/* and a new set of features. */
- {
- unsigned int tags_count = 3;
- hb_tag_t tags[3];
-
-
- hb_ot_tags_from_script_and_language( script,
- HB_LANGUAGE_INVALID,
- &tags_count,
- tags,
- NULL,
- NULL );
- script_tags[0] = tags_count > 0 ? tags[0] : HB_TAG_NONE;
- script_tags[1] = tags_count > 1 ? tags[1] : HB_TAG_NONE;
- script_tags[2] = tags_count > 2 ? tags[2] : HB_TAG_NONE;
- }
+ hb_ot_tags_from_script( script,
+ &script_tags[0],
+ &script_tags[1] );
- /* If the second tag is HB_OT_TAG_DEFAULT_SCRIPT, change that to */
- /* HB_TAG_NONE except for the default script. */
+ /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */
+ /* as the second tag. We change that to HB_TAG_NONE except for the */
+ /* default script. */
if ( default_script )
{
if ( script_tags[0] == HB_TAG_NONE )
@@ -168,6 +157,9 @@
/* HarfBuzz maps them to `DFLT', which we don't want to handle here */
if ( script_tags[0] == HB_OT_TAG_DEFAULT_SCRIPT )
goto Exit;
+
+ if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT )
+ script_tags[1] = HB_TAG_NONE;
}
gsub_lookups = hb_set_create();
@@ -181,9 +173,9 @@
if ( hb_set_is_empty( gsub_lookups ) )
goto Exit; /* nothing to do */
- FT_TRACE4(( "GSUB lookups (style `%s'):\n",
+ FT_TRACE4(( "GSUB lookups (style `%s'):\n"
+ " ",
af_style_names[style_class->style] ));
- FT_TRACE4(( " " ));
#ifdef FT_DEBUG_LEVEL_TRACE
count = 0;
@@ -210,13 +202,12 @@
#ifdef FT_DEBUG_LEVEL_TRACE
if ( !count )
FT_TRACE4(( " (none)" ));
- FT_TRACE4(( "\n" ));
- FT_TRACE4(( "\n" ));
+ FT_TRACE4(( "\n\n" ));
#endif
- FT_TRACE4(( "GPOS lookups (style `%s'):\n",
+ FT_TRACE4(( "GPOS lookups (style `%s'):\n"
+ " ",
af_style_names[style_class->style] ));
- FT_TRACE4(( " " ));
gpos_lookups = hb_set_create();
hb_ot_layout_collect_lookups( face,
@@ -251,8 +242,7 @@
#ifdef FT_DEBUG_LEVEL_TRACE
if ( !count )
FT_TRACE4(( " (none)" ));
- FT_TRACE4(( "\n" ));
- FT_TRACE4(( "\n" ));
+ FT_TRACE4(( "\n\n" ));
#endif
/*
@@ -363,10 +353,8 @@
{
#ifdef FT_DEBUG_LEVEL_TRACE
if ( !( count % 10 ) )
- {
- FT_TRACE4(( "\n" ));
- FT_TRACE4(( " " ));
- }
+ FT_TRACE4(( "\n"
+ " " ));
FT_TRACE4(( " %d", idx ));
count++;
@@ -388,12 +376,9 @@
#ifdef FT_DEBUG_LEVEL_TRACE
if ( !count )
- {
- FT_TRACE4(( "\n" ));
- FT_TRACE4(( " (none)" ));
- }
- FT_TRACE4(( "\n" ));
- FT_TRACE4(( "\n" ));
+ FT_TRACE4(( "\n"
+ " (none)" ));
+ FT_TRACE4(( "\n\n" ));
#endif
Exit:
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.h
index cf3f81342ff..138c27b32b6 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afshaper.h
@@ -4,7 +4,7 @@
*
* HarfBuzz interface for accessing OpenType features (specification).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afstyles.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afstyles.h
index 64c808c5812..9113ec451ef 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afstyles.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
*
* Auto-fitter styles (specification only).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -299,6 +299,15 @@
AF_BLUE_STRINGSET_LATP,
AF_COVERAGE_DEFAULT )
+#ifdef FT_OPTION_AUTOFIT2
+ STYLE( ltn2_dflt, LTN2_DFLT,
+ "Latin 2 default style",
+ AF_WRITING_SYSTEM_LATIN2,
+ AF_SCRIPT_LATN,
+ AF_BLUE_STRINGSET_LATN,
+ AF_COVERAGE_DEFAULT )
+#endif
+
STYLE( lisu_dflt, LISU_DFLT,
"Lisu default style",
AF_WRITING_SYSTEM_LATIN,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/aftypes.h b/Build/source/libs/freetype2/freetype-src/src/autofit/aftypes.h
index e76b103ed01..5f040c6b4b9 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/aftypes.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
*
* Auto-fitter types (specification only).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -92,6 +92,63 @@ extern void* _af_debug_hints;
FT_Pos threshold );
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** A N G L E T Y P E S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*
+ * The auto-fitter doesn't need a very high angular accuracy;
+ * this allows us to speed up some computations considerably with a
+ * light Cordic algorithm (see afangles.c).
+ */
+
+ typedef FT_Int AF_Angle;
+
+
+#define AF_ANGLE_PI 256
+#define AF_ANGLE_2PI ( AF_ANGLE_PI * 2 )
+#define AF_ANGLE_PI2 ( AF_ANGLE_PI / 2 )
+#define AF_ANGLE_PI4 ( AF_ANGLE_PI / 4 )
+
+
+#if 0
+ /*
+ * compute the angle of a given 2-D vector
+ */
+ FT_LOCAL( AF_Angle )
+ af_angle_atan( FT_Pos dx,
+ FT_Pos dy );
+
+
+ /*
+ * compute `angle2 - angle1'; the result is always within
+ * the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
+ */
+ FT_LOCAL( AF_Angle )
+ af_angle_diff( AF_Angle angle1,
+ AF_Angle angle2 );
+#endif /* 0 */
+
+
+#define AF_ANGLE_DIFF( result, angle1, angle2 ) \
+ FT_BEGIN_STMNT \
+ AF_Angle _delta = (angle2) - (angle1); \
+ \
+ \
+ while ( _delta <= -AF_ANGLE_PI ) \
+ _delta += AF_ANGLE_2PI; \
+ \
+ while ( _delta > AF_ANGLE_PI ) \
+ _delta -= AF_ANGLE_2PI; \
+ \
+ result = _delta; \
+ FT_END_STMNT
+
+
/*
* opaque handle to glyph-specific hints -- see `afhints.h' for more
* details
@@ -115,6 +172,7 @@ extern void* _af_debug_hints;
#define AF_SCALER_FLAG_NO_HORIZONTAL 1U /* disable horizontal hinting */
#define AF_SCALER_FLAG_NO_VERTICAL 2U /* disable vertical hinting */
#define AF_SCALER_FLAG_NO_ADVANCE 4U /* disable advance hinting */
+#define AF_SCALER_FLAG_NO_WARPER 8U /* disable warper */
typedef struct AF_ScalerRec_
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afwarp.c b/Build/source/libs/freetype2/freetype-src/src/autofit/afwarp.c
new file mode 100644
index 00000000000..808280df5d9
--- /dev/null
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afwarp.c
@@ -0,0 +1,373 @@
+/****************************************************************************
+ *
+ * afwarp.c
+ *
+ * Auto-fitter warping algorithm (body).
+ *
+ * Copyright (C) 2006-2020 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /*
+ * The idea of the warping code is to slightly scale and shift a glyph
+ * within a single dimension so that as much of its segments are aligned
+ * (more or less) on the grid. To find out the optimal scaling and
+ * shifting value, various parameter combinations are tried and scored.
+ */
+
+#include "afwarp.h"
+
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+ * messages during execution.
+ */
+#undef FT_COMPONENT
+#define FT_COMPONENT afwarp
+
+
+ /* The weights cover the range 0/64 - 63/64 of a pixel. Obviously, */
+ /* values around a half pixel (which means exactly between two grid */
+ /* lines) gets the worst weight. */
+#if 1
+ static const AF_WarpScore
+ af_warper_weights[64] =
+ {
+ 35, 32, 30, 25, 20, 15, 12, 10, 5, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30,
+
+ -30,-30,-20,-20,-10,-10, -8, -5, -2, -1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 5, 10, 12, 15, 20, 25, 30, 32,
+ };
+#else
+ static const AF_WarpScore
+ af_warper_weights[64] =
+ {
+ 30, 20, 10, 5, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, -1, -2, -2, -5, -5,-10,-10,-15,-20,
+
+ -20,-15,-15,-10,-10, -5, -5, -2, -2, -1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 5, 10, 20,
+ };
+#endif
+
+
+ /* Score segments for a given `scale' and `delta' in the range */
+ /* `xx1' to `xx2', and store the best result in `warper'. If */
+ /* the new best score is equal to the old one, prefer the */
+ /* value with a smaller distortion (around `base_distort'). */
+
+ static void
+ af_warper_compute_line_best( AF_Warper warper,
+ FT_Fixed scale,
+ FT_Pos delta,
+ FT_Pos xx1,
+ FT_Pos xx2,
+ AF_WarpScore base_distort,
+ AF_Segment segments,
+ FT_Int num_segments )
+ {
+ FT_Int idx_min, idx_max, idx0;
+ FT_Int nn;
+ AF_WarpScore scores[65];
+
+
+ for ( nn = 0; nn < 65; nn++ )
+ scores[nn] = 0;
+
+ idx0 = xx1 - warper->t1;
+
+ /* compute minimum and maximum indices */
+ {
+ FT_Pos xx1min = warper->x1min;
+ FT_Pos xx1max = warper->x1max;
+ FT_Pos w = xx2 - xx1;
+
+
+ if ( xx1min + w < warper->x2min )
+ xx1min = warper->x2min - w;
+
+ if ( xx1max + w > warper->x2max )
+ xx1max = warper->x2max - w;
+
+ idx_min = xx1min - warper->t1;
+ idx_max = xx1max - warper->t1;
+
+ if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
+ {
+ FT_TRACE5(( "invalid indices:\n"
+ " min=%d max=%d, xx1=%ld xx2=%ld,\n"
+ " x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
+ idx_min, idx_max, xx1, xx2,
+ warper->x1min, warper->x1max,
+ warper->x2min, warper->x2max ));
+ return;
+ }
+ }
+
+ for ( nn = 0; nn < num_segments; nn++ )
+ {
+ FT_Pos len = segments[nn].max_coord - segments[nn].min_coord;
+ FT_Pos y0 = FT_MulFix( segments[nn].pos, scale ) + delta;
+ FT_Pos y = y0 + ( idx_min - idx0 );
+ FT_Int idx;
+
+
+ /* score the length of the segments for the given range */
+ for ( idx = idx_min; idx <= idx_max; idx++, y++ )
+ scores[idx] += af_warper_weights[y & 63] * len;
+ }
+
+ /* find best score */
+ {
+ FT_Int idx;
+
+
+ for ( idx = idx_min; idx <= idx_max; idx++ )
+ {
+ AF_WarpScore score = scores[idx];
+ AF_WarpScore distort = base_distort + ( idx - idx0 );
+
+
+ if ( score > warper->best_score ||
+ ( score == warper->best_score &&
+ distort < warper->best_distort ) )
+ {
+ warper->best_score = score;
+ warper->best_distort = distort;
+ warper->best_scale = scale;
+ warper->best_delta = delta + ( idx - idx0 );
+ }
+ }
+ }
+ }
+
+
+ /* Compute optimal scaling and delta values for a given glyph and */
+ /* dimension. */
+
+ FT_LOCAL_DEF( void )
+ af_warper_compute( AF_Warper warper,
+ AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Fixed *a_scale,
+ FT_Pos *a_delta )
+ {
+ AF_AxisHints axis;
+ AF_Point points;
+
+ FT_Fixed org_scale;
+ FT_Pos org_delta;
+
+ FT_Int nn, num_points, num_segments;
+ FT_Int X1, X2;
+ FT_Int w;
+
+ AF_WarpScore base_distort;
+ AF_Segment segments;
+
+
+ /* get original scaling transformation */
+ if ( dim == AF_DIMENSION_VERT )
+ {
+ org_scale = hints->y_scale;
+ org_delta = hints->y_delta;
+ }
+ else
+ {
+ org_scale = hints->x_scale;
+ org_delta = hints->x_delta;
+ }
+
+ warper->best_scale = org_scale;
+ warper->best_delta = org_delta;
+ warper->best_score = FT_INT_MIN;
+ warper->best_distort = 0;
+
+ axis = &hints->axis[dim];
+ segments = axis->segments;
+ num_segments = axis->num_segments;
+ points = hints->points;
+ num_points = hints->num_points;
+
+ *a_scale = org_scale;
+ *a_delta = org_delta;
+
+ /* get X1 and X2, minimum and maximum in original coordinates */
+ if ( num_segments < 1 )
+ return;
+
+#if 1
+ X1 = X2 = points[0].fx;
+ for ( nn = 1; nn < num_points; nn++ )
+ {
+ FT_Int X = points[nn].fx;
+
+
+ if ( X < X1 )
+ X1 = X;
+ if ( X > X2 )
+ X2 = X;
+ }
+#else
+ X1 = X2 = segments[0].pos;
+ for ( nn = 1; nn < num_segments; nn++ )
+ {
+ FT_Int X = segments[nn].pos;
+
+
+ if ( X < X1 )
+ X1 = X;
+ if ( X > X2 )
+ X2 = X;
+ }
+#endif
+
+ if ( X1 >= X2 )
+ return;
+
+ warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;
+ warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;
+
+ warper->t1 = AF_WARPER_FLOOR( warper->x1 );
+ warper->t2 = AF_WARPER_CEIL( warper->x2 );
+
+ /* examine a half pixel wide range around the maximum coordinates */
+ warper->x1min = warper->x1 & ~31;
+ warper->x1max = warper->x1min + 32;
+ warper->x2min = warper->x2 & ~31;
+ warper->x2max = warper->x2min + 32;
+
+ if ( warper->x1max > warper->x2 )
+ warper->x1max = warper->x2;
+
+ if ( warper->x2min < warper->x1 )
+ warper->x2min = warper->x1;
+
+ warper->w0 = warper->x2 - warper->x1;
+
+ if ( warper->w0 <= 64 )
+ {
+ warper->x1max = warper->x1;
+ warper->x2min = warper->x2;
+ }
+
+ /* examine (at most) a pixel wide range around the natural width */
+ warper->wmin = warper->x2min - warper->x1max;
+ warper->wmax = warper->x2max - warper->x1min;
+
+#if 1
+ /* some heuristics to reduce the number of widths to be examined */
+ {
+ int margin = 16;
+
+
+ if ( warper->w0 <= 128 )
+ {
+ margin = 8;
+ if ( warper->w0 <= 96 )
+ margin = 4;
+ }
+
+ if ( warper->wmin < warper->w0 - margin )
+ warper->wmin = warper->w0 - margin;
+
+ if ( warper->wmax > warper->w0 + margin )
+ warper->wmax = warper->w0 + margin;
+ }
+
+ if ( warper->wmin < warper->w0 * 3 / 4 )
+ warper->wmin = warper->w0 * 3 / 4;
+
+ if ( warper->wmax > warper->w0 * 5 / 4 )
+ warper->wmax = warper->w0 * 5 / 4;
+#else
+ /* no scaling, just translation */
+ warper->wmin = warper->wmax = warper->w0;
+#endif
+
+ for ( w = warper->wmin; w <= warper->wmax; w++ )
+ {
+ FT_Fixed new_scale;
+ FT_Pos new_delta;
+ FT_Pos xx1, xx2;
+
+
+ /* compute min and max positions for given width, */
+ /* assuring that they stay within the coordinate ranges */
+ xx1 = warper->x1;
+ xx2 = warper->x2;
+ if ( w >= warper->w0 )
+ {
+ xx1 -= w - warper->w0;
+ if ( xx1 < warper->x1min )
+ {
+ xx2 += warper->x1min - xx1;
+ xx1 = warper->x1min;
+ }
+ }
+ else
+ {
+ xx1 -= w - warper->w0;
+ if ( xx1 > warper->x1max )
+ {
+ xx2 -= xx1 - warper->x1max;
+ xx1 = warper->x1max;
+ }
+ }
+
+ if ( xx1 < warper->x1 )
+ base_distort = warper->x1 - xx1;
+ else
+ base_distort = xx1 - warper->x1;
+
+ if ( xx2 < warper->x2 )
+ base_distort += warper->x2 - xx2;
+ else
+ base_distort += xx2 - warper->x2;
+
+ /* give base distortion a greater weight while scoring */
+ base_distort *= 10;
+
+ new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
+ new_delta = xx1 - FT_MulFix( X1, new_scale );
+
+ af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,
+ base_distort,
+ segments, num_segments );
+ }
+
+ {
+ FT_Fixed best_scale = warper->best_scale;
+ FT_Pos best_delta = warper->best_delta;
+
+
+ hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale )
+ + best_delta;
+ hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale )
+ + best_delta;
+
+ *a_scale = best_scale;
+ *a_delta = best_delta;
+ }
+ }
+
+#else /* !AF_CONFIG_OPTION_USE_WARPER */
+
+ /* ANSI C doesn't like empty source files */
+ typedef int _af_warp_dummy;
+
+#endif /* !AF_CONFIG_OPTION_USE_WARPER */
+
+/* END */
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afwarp.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afwarp.h
new file mode 100644
index 00000000000..cdea23e7dec
--- /dev/null
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afwarp.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+ *
+ * afwarp.h
+ *
+ * Auto-fitter warping algorithm (specification).
+ *
+ * Copyright (C) 2006-2020 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef AFWARP_H_
+#define AFWARP_H_
+
+#include "afhints.h"
+
+FT_BEGIN_HEADER
+
+#define AF_WARPER_SCALE
+
+#define AF_WARPER_FLOOR( x ) ( (x) & ~FT_TYPEOF( x )63 )
+#define AF_WARPER_CEIL( x ) AF_WARPER_FLOOR( (x) + 63 )
+
+
+ typedef FT_Int32 AF_WarpScore;
+
+ typedef struct AF_WarperRec_
+ {
+ FT_Pos x1, x2;
+ FT_Pos t1, t2;
+ FT_Pos x1min, x1max;
+ FT_Pos x2min, x2max;
+ FT_Pos w0, wmin, wmax;
+
+ FT_Fixed best_scale;
+ FT_Pos best_delta;
+ AF_WarpScore best_score;
+ AF_WarpScore best_distort;
+
+ } AF_WarperRec, *AF_Warper;
+
+
+#ifdef AF_CONFIG_OPTION_USE_WARPER
+ FT_LOCAL( void )
+ af_warper_compute( AF_Warper warper,
+ AF_GlyphHints hints,
+ AF_Dimension dim,
+ FT_Fixed *a_scale,
+ FT_Pos *a_delta );
+#endif
+
+
+FT_END_HEADER
+
+
+#endif /* AFWARP_H_ */
+
+
+/* END */
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/afwrtsys.h b/Build/source/libs/freetype2/freetype-src/src/autofit/afwrtsys.h
index 39aa1211263..3990633d2d6 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/afwrtsys.h
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/afwrtsys.h
@@ -4,7 +4,7 @@
*
* Auto-fitter writing systems (specification only).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -26,6 +26,9 @@
#include "aflatin.h"
#include "afcjk.h"
#include "afindic.h"
+#ifdef FT_OPTION_AUTOFIT2
+#include "aflatin2.h"
+#endif
#endif /* AFWRTSYS_H_ */
@@ -41,5 +44,9 @@
WRITING_SYSTEM( latin, LATIN )
WRITING_SYSTEM( cjk, CJK )
WRITING_SYSTEM( indic, INDIC )
+#ifdef FT_OPTION_AUTOFIT2
+ WRITING_SYSTEM( latin2, LATIN2 )
+#endif
+
/* END */
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/autofit.c b/Build/source/libs/freetype2/freetype-src/src/autofit/autofit.c
index 7e692b4de9b..ef5e7f14522 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/autofit.c
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/autofit.c
@@ -4,7 +4,7 @@
*
* Auto-fitter module (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2020 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -18,6 +18,7 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
+#include "afangles.c"
#include "afblue.c"
#include "afcjk.c"
#include "afdummy.c"
@@ -25,10 +26,12 @@
#include "afhints.c"
#include "afindic.c"
#include "aflatin.c"
+#include "aflatin2.c"
#include "afloader.c"
#include "afmodule.c"
#include "afranges.c"
#include "afshaper.c"
+#include "afwarp.c"
/* END */
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/module.mk b/Build/source/libs/freetype2/freetype-src/src/autofit/module.mk
index fab3a6bd623..c32781f478c 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/module.mk
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/module.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2003-2021 by
+# Copyright (C) 2003-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
diff --git a/Build/source/libs/freetype2/freetype-src/src/autofit/rules.mk b/Build/source/libs/freetype2/freetype-src/src/autofit/rules.mk
index 19b3bcadb30..553ddce6b74 100644
--- a/Build/source/libs/freetype2/freetype-src/src/autofit/rules.mk
+++ b/Build/source/libs/freetype2/freetype-src/src/autofit/rules.mk
@@ -3,7 +3,7 @@
#
-# Copyright (C) 2003-2021 by
+# Copyright (C) 2003-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
@@ -28,7 +28,8 @@ AUTOF_COMPILE := $(CC) $(ANSIFLAGS) \
# AUTOF driver sources (i.e., C files)
#
-AUTOF_DRV_SRC := $(AUTOF_DIR)/afblue.c \
+AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
+ $(AUTOF_DIR)/afblue.c \
$(AUTOF_DIR)/afcjk.c \
$(AUTOF_DIR)/afdummy.c \
$(AUTOF_DIR)/afglobal.c \
@@ -39,6 +40,7 @@ AUTOF_DRV_SRC := $(AUTOF_DIR)/afblue.c \
$(AUTOF_DIR)/afmodule.c \
$(AUTOF_DIR)/afranges.c \
$(AUTOF_DIR)/afshaper.c \
+ $(AUTOF_DIR)/afwarp.c
# AUTOF driver headers
#