shithub: freetype+ttf2subf

Download patch

ref: 0164d934b651949346a27dd160fc3d7ed683312a
parent: f02e1df7ac7bf3e8ef95b6664cb60bc677a311d1
author: Werner Lemberg <[email protected]>
date: Wed Dec 9 15:04:18 EST 2015

[autofit] Introduce subscript top blue zones.

This feature is mainly for Khmer: The idea is to avoid a clash
between the top of subscript glyphs and the bottom of normal
baseline glyphs.

This only works for character clusters mapped to multiple glyphs.

* src/autofit/afblue.dat: Add subscript top blue zone for Khmer.

* src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_SUB_TOP): New
macro.

* src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.

* src/autofit/aflatin.h (AF_LATIN_IS_SUB_TOP_BLUE,
AF_LATIN_BLUE_SUB_TOP): New macros.

* src/autofit/aflatin.c (af_latin_metrics_init_blues): Handle new
blue zone property.
Update tracing messages.
(af_latin_metrics_scale_dim): Handle new blue zone property.
(af_latin_hints_compute_blue_edges): Updated.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,31 @@
 2015-12-09  Werner Lemberg  <[email protected]>
 
+	[autofit] Introduce subscript top blue zones.
+
+	This feature is mainly for Khmer: The idea is to avoid a clash
+	between the top of subscript glyphs and the bottom of normal
+	baseline glyphs.
+
+	This only works for character clusters mapped to multiple glyphs.
+
+	* src/autofit/afblue.dat: Add subscript top blue zone for Khmer.
+
+	* src/autofit/afblue.hin (AF_BLUE_PROPERTY_LATIN_SUB_TOP): New
+	macro.
+
+	* src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+	* src/autofit/aflatin.h (AF_LATIN_IS_SUB_TOP_BLUE,
+	AF_LATIN_BLUE_SUB_TOP): New macros.
+
+	* src/autofit/aflatin.c (af_latin_metrics_init_blues): Handle new
+	blue zone property.
+	Update tracing messages.
+	(af_latin_metrics_scale_dim): Handle new blue zone property.
+	(af_latin_hints_compute_blue_edges): Updated.
+
+2015-12-09  Werner Lemberg  <[email protected]>
+
 	[autofit] Fix tracing message.
 
 	* src/autofit/aflatin.c (af_latin_metrics_scale_dim): Display
--- a/src/autofit/afblue.c
+++ b/src/autofit/afblue.c
@@ -66,6 +66,8 @@
     '\0',
     '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x91', ' ', '\xE1', '\x9E', '\x93', ' ', '\xE1', '\x9E', '\xA7', ' ', '\xE1', '\x9E', '\xA9', ' ', '\xE1', '\x9E', '\xB6',  /* ខ ទ ន ឧ ឩ ា */
     '\0',
+    '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x80', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x82', ' ', '\xE1', '\x9E', '\x80', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x90',  /* ក្ក ក្ខ ក្គ ក្ថ */
+    '\0',
     '\xE1', '\x9E', '\x81', ' ', '\xE1', '\x9E', '\x83', ' ', '\xE1', '\x9E', '\x85', ' ', '\xE1', '\x9E', '\x8B', ' ', '\xE1', '\x9E', '\x94', ' ', '\xE1', '\x9E', '\x98', ' ', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xB2',  /* ខ ឃ ច ឋ ប ម យ ឲ */
     '\0',
     '\xE1', '\x9E', '\x8F', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x9A', ' ', '\xE1', '\x9E', '\x9A', '\xE1', '\x9F', '\x80', ' ', '\xE1', '\x9E', '\xB2', '\xE1', '\x9F', '\x92', '\xE1', '\x9E', '\x99', ' ', '\xE1', '\x9E', '\xA2', '\xE1', '\x9E', '\xBF',  /* ត្រ រៀ ឲ្យ អឿ */
@@ -217,6 +219,7 @@
     { AF_BLUE_STRING_MAX,              0                             },
     { AF_BLUE_STRING_KHMER_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
                                             AF_BLUE_PROPERTY_LATIN_X_HEIGHT   },
+    { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP,   AF_BLUE_PROPERTY_LATIN_SUB_TOP    },
     { AF_BLUE_STRING_KHMER_BOTTOM,          0                                 },
     { AF_BLUE_STRING_KHMER_DESCENDER,       0                                 },
     { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0                                 },
--- a/src/autofit/afblue.dat
+++ b/src/autofit/afblue.dat
@@ -127,6 +127,8 @@
 
   AF_BLUE_STRING_KHMER_TOP
     "ខ ទ ន ឧ ឩ ា"
+  AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP
+    "ក្ក ក្ខ ក្គ ក្ថ"
   AF_BLUE_STRING_KHMER_BOTTOM
     "ខ ឃ ច ឋ ប ម យ ឲ"
   AF_BLUE_STRING_KHMER_DESCENDER
@@ -297,6 +299,21 @@
 //
 //     If not set, take the minimum values.
 //
+//     Mutually exclusive with `LATIN_SUB_TOP'.
+//
+//   LATIN_SUB_TOP
+//     For all glyphs of a character cluster, compute the maximum flat
+//     and round coordinate values of each component, then take the
+//     smallest of the maximum values.  The idea is to get the top of
+//     subscript glyphs, as used in Khmer, for example.  Note that
+//     this mechanism doesn't work for ordinary ligatures.
+//
+//     This flags indicates a secondary blue zone: It gets removed if
+//     there is a non-LATIN_SUB_TOP blue zone at the same coordinate
+//     value (after scaling).
+//
+//     Mutually exclusive with `LATIN_TOP'.
+//
 //   LATIN_NEUTRAL
 //     Ignore round extrema and define the blue zone with flat values only.
 //     Both top and bottom of contours can match.  This is useful for
@@ -401,6 +418,7 @@
   AF_BLUE_STRINGSET_KHMR
     { AF_BLUE_STRING_KHMER_TOP,             AF_BLUE_PROPERTY_LATIN_TOP      |
                                             AF_BLUE_PROPERTY_LATIN_X_HEIGHT   }
+    { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP,   AF_BLUE_PROPERTY_LATIN_SUB_TOP    }
     { AF_BLUE_STRING_KHMER_BOTTOM,          0                                 }
     { AF_BLUE_STRING_KHMER_DESCENDER,       0                                 }
     { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0                                 }
--- a/src/autofit/afblue.h
+++ b/src/autofit/afblue.h
@@ -97,41 +97,42 @@
     AF_BLUE_STRING_HEBREW_BOTTOM = 350,
     AF_BLUE_STRING_HEBREW_DESCENDER = 368,
     AF_BLUE_STRING_KHMER_TOP = 383,
-    AF_BLUE_STRING_KHMER_BOTTOM = 407,
-    AF_BLUE_STRING_KHMER_DESCENDER = 439,
-    AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 473,
-    AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 560,
-    AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 568,
-    AF_BLUE_STRING_LAO_TOP = 576,
-    AF_BLUE_STRING_LAO_BOTTOM = 608,
-    AF_BLUE_STRING_LAO_ASCENDER = 640,
-    AF_BLUE_STRING_LAO_LARGE_ASCENDER = 656,
-    AF_BLUE_STRING_LAO_DESCENDER = 668,
-    AF_BLUE_STRING_LATIN_CAPITAL_TOP = 692,
-    AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 708,
-    AF_BLUE_STRING_LATIN_SMALL_F_TOP = 724,
-    AF_BLUE_STRING_LATIN_SMALL = 738,
-    AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 752,
-    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 762,
-    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 782,
-    AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 802,
-    AF_BLUE_STRING_LATIN_SUBS_SMALL = 822,
-    AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 858,
-    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 878,
-    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 909,
-    AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 938,
-    AF_BLUE_STRING_LATIN_SUPS_SMALL = 964,
-    AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 989,
-    AF_BLUE_STRING_TELUGU_TOP = 1000,
-    AF_BLUE_STRING_TELUGU_BOTTOM = 1028,
-    AF_BLUE_STRING_THAI_TOP = 1056,
-    AF_BLUE_STRING_THAI_BOTTOM = 1080,
-    AF_BLUE_STRING_THAI_ASCENDER = 1108,
-    AF_BLUE_STRING_THAI_LARGE_ASCENDER = 1120,
-    AF_BLUE_STRING_THAI_DESCENDER = 1132,
-    AF_BLUE_STRING_THAI_LARGE_DESCENDER = 1148,
-    AF_BLUE_STRING_THAI_DIGIT_TOP = 1156,
-    af_blue_1_1 = 1167,
+    AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP = 407,
+    AF_BLUE_STRING_KHMER_BOTTOM = 447,
+    AF_BLUE_STRING_KHMER_DESCENDER = 479,
+    AF_BLUE_STRING_KHMER_LARGE_DESCENDER = 513,
+    AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP = 600,
+    AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM = 608,
+    AF_BLUE_STRING_LAO_TOP = 616,
+    AF_BLUE_STRING_LAO_BOTTOM = 648,
+    AF_BLUE_STRING_LAO_ASCENDER = 680,
+    AF_BLUE_STRING_LAO_LARGE_ASCENDER = 696,
+    AF_BLUE_STRING_LAO_DESCENDER = 708,
+    AF_BLUE_STRING_LATIN_CAPITAL_TOP = 732,
+    AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM = 748,
+    AF_BLUE_STRING_LATIN_SMALL_F_TOP = 764,
+    AF_BLUE_STRING_LATIN_SMALL = 778,
+    AF_BLUE_STRING_LATIN_SMALL_DESCENDER = 792,
+    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP = 802,
+    AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM = 822,
+    AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP = 842,
+    AF_BLUE_STRING_LATIN_SUBS_SMALL = 862,
+    AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER = 898,
+    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP = 918,
+    AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM = 949,
+    AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP = 978,
+    AF_BLUE_STRING_LATIN_SUPS_SMALL = 1004,
+    AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER = 1029,
+    AF_BLUE_STRING_TELUGU_TOP = 1040,
+    AF_BLUE_STRING_TELUGU_BOTTOM = 1068,
+    AF_BLUE_STRING_THAI_TOP = 1096,
+    AF_BLUE_STRING_THAI_BOTTOM = 1120,
+    AF_BLUE_STRING_THAI_ASCENDER = 1148,
+    AF_BLUE_STRING_THAI_LARGE_ASCENDER = 1160,
+    AF_BLUE_STRING_THAI_DESCENDER = 1172,
+    AF_BLUE_STRING_THAI_LARGE_DESCENDER = 1188,
+    AF_BLUE_STRING_THAI_DIGIT_TOP = 1196,
+    af_blue_1_1 = 1207,
 #ifdef AF_CONFIG_OPTION_CJK
     AF_BLUE_STRING_CJK_TOP = af_blue_1_1 + 1,
     AF_BLUE_STRING_CJK_BOTTOM = af_blue_1_1 + 203,
@@ -173,9 +174,10 @@
   /* blue string can't be used in more than a single writing system, which */
   /* is a safe bet.                                                        */
 #define AF_BLUE_PROPERTY_LATIN_TOP       ( 1U << 0 )  /* must have value 1 */
-#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1U << 1 )
-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1U << 2 )
-#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_SUB_TOP   ( 1U << 1 )
+#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1U << 2 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1U << 4 )
 
 #define AF_BLUE_PROPERTY_CJK_TOP    ( 1U << 0 )       /* must have value 1 */
 #define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1U << 1 )       /* must have value 2 */
@@ -195,14 +197,14 @@
     AF_BLUE_STRINGSET_GREK = 16,
     AF_BLUE_STRINGSET_HEBR = 23,
     AF_BLUE_STRINGSET_KHMR = 27,
-    AF_BLUE_STRINGSET_KHMS = 32,
-    AF_BLUE_STRINGSET_LAO = 35,
-    AF_BLUE_STRINGSET_LATN = 41,
-    AF_BLUE_STRINGSET_LATB = 48,
-    AF_BLUE_STRINGSET_LATP = 55,
-    AF_BLUE_STRINGSET_TELU = 62,
-    AF_BLUE_STRINGSET_THAI = 65,
-    af_blue_2_1 = 73,
+    AF_BLUE_STRINGSET_KHMS = 33,
+    AF_BLUE_STRINGSET_LAO = 36,
+    AF_BLUE_STRINGSET_LATN = 42,
+    AF_BLUE_STRINGSET_LATB = 49,
+    AF_BLUE_STRINGSET_LATP = 56,
+    AF_BLUE_STRINGSET_TELU = 63,
+    AF_BLUE_STRINGSET_THAI = 66,
+    af_blue_2_1 = 74,
 #ifdef AF_CONFIG_OPTION_CJK
     AF_BLUE_STRINGSET_HANI = af_blue_2_1 + 0,
     af_blue_2_1_1 = af_blue_2_1 + 2,
--- a/src/autofit/afblue.hin
+++ b/src/autofit/afblue.hin
@@ -100,9 +100,10 @@
   /* blue string can't be used in more than a single writing system, which */
   /* is a safe bet.                                                        */
 #define AF_BLUE_PROPERTY_LATIN_TOP       ( 1U << 0 )  /* must have value 1 */
-#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1U << 1 )
-#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1U << 2 )
-#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_SUB_TOP   ( 1U << 1 )
+#define AF_BLUE_PROPERTY_LATIN_NEUTRAL   ( 1U << 2 )
+#define AF_BLUE_PROPERTY_LATIN_X_HEIGHT  ( 1U << 3 )
+#define AF_BLUE_PROPERTY_LATIN_LONG      ( 1U << 4 )
 
 #define AF_BLUE_PROPERTY_CJK_TOP    ( 1U << 0 )       /* must have value 1 */
 #define AF_BLUE_PROPERTY_CJK_HORIZ  ( 1U << 1 )       /* must have value 2 */
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -330,6 +330,11 @@
             FT_TRACE5(( "top" ));
             have_flag = 1;
           }
+          else if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+          {
+            FT_TRACE5(( "sub top" ));
+            have_flag = 1;
+          }
 
           if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
           {
@@ -462,7 +467,8 @@
               if ( last <= first )
                 continue;
 
-              if ( AF_LATIN_IS_TOP_BLUE( bs ) )
+              if ( AF_LATIN_IS_TOP_BLUE( bs )     ||
+                   AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
               {
                 for ( pp = first; pp <= last; pp++ )
                 {
@@ -871,7 +877,8 @@
         FT_Bool  over_ref = FT_BOOL( shoot > ref );
 
 
-        if ( AF_LATIN_IS_TOP_BLUE( bs ) ^ over_ref )
+        if ( ( AF_LATIN_IS_TOP_BLUE( bs )    ||
+               AF_LATIN_IS_SUB_TOP_BLUE( bs) ) ^ over_ref )
         {
           *blue_ref   =
           *blue_shoot = ( shoot + ref ) / 2;
@@ -887,6 +894,8 @@
       blue->flags = 0;
       if ( AF_LATIN_IS_TOP_BLUE( bs ) )
         blue->flags |= AF_LATIN_BLUE_TOP;
+      if ( AF_LATIN_IS_SUB_TOP_BLUE( bs ) )
+        blue->flags |= AF_LATIN_BLUE_SUB_TOP;
       if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) )
         blue->flags |= AF_LATIN_BLUE_NEUTRAL;
 
@@ -1259,6 +1268,40 @@
         }
       }
 
+      /* use sub-top blue zone only if it doesn't overlap with */
+      /* another (non-sup-top) blue zone; otherwise, the       */
+      /* effect would be similar to a neutral blue zone, which */
+      /* is not desired here                                   */
+      for ( nn = 0; nn < axis->blue_count; nn++ )
+      {
+        AF_LatinBlue  blue = &axis->blues[nn];
+        FT_UInt       i;
+
+
+        if ( !( blue->flags & AF_LATIN_BLUE_SUB_TOP ) )
+          continue;
+        if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
+          continue;
+
+        for ( i = 0; i < axis->blue_count; i++ )
+        {
+          AF_LatinBlue  b = &axis->blues[i];
+
+
+          if ( b->flags & AF_LATIN_BLUE_SUB_TOP )
+            continue;
+          if ( !( b->flags & AF_LATIN_BLUE_ACTIVE ) )
+            continue;
+
+          if ( b->ref.fit <= blue->shoot.fit &&
+               b->shoot.fit >= blue->ref.fit )
+          {
+            blue->flags &= ~AF_LATIN_BLUE_ACTIVE;
+            break;
+          }
+        }
+      }
+
 #ifdef FT_DEBUG_LEVEL_TRACE
       for ( nn = 0; nn < axis->blue_count; nn++ )
       {
@@ -2071,7 +2114,8 @@
         /* the major direction) -- this assumes the TrueType convention  */
         /* for the orientation of contours                               */
         is_top_blue =
-          (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
+          (FT_Byte)( ( blue->flags & ( AF_LATIN_BLUE_TOP     |
+                                       AF_LATIN_BLUE_SUB_TOP ) ) != 0 );
         is_neutral_blue =
           (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_NEUTRAL ) != 0);
         is_major_dir =
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -53,6 +53,8 @@
 
 #define AF_LATIN_IS_TOP_BLUE( b ) \
           ( (b)->properties & AF_BLUE_PROPERTY_LATIN_TOP )
+#define AF_LATIN_IS_SUB_TOP_BLUE( b ) \
+          ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SUB_TOP )
 #define AF_LATIN_IS_NEUTRAL_BLUE( b ) \
           ( (b)->properties & AF_BLUE_PROPERTY_LATIN_NEUTRAL )
 #define AF_LATIN_IS_X_HEIGHT_BLUE( b ) \
@@ -65,8 +67,10 @@
 
 #define AF_LATIN_BLUE_ACTIVE      ( 1U << 0 ) /* zone height is <= 3/4px   */
 #define AF_LATIN_BLUE_TOP         ( 1U << 1 ) /* we have a top blue zone   */
-#define AF_LATIN_BLUE_NEUTRAL     ( 1U << 2 ) /* we have neutral blue zone */
-#define AF_LATIN_BLUE_ADJUSTMENT  ( 1U << 3 ) /* used for scale adjustment */
+#define AF_LATIN_BLUE_SUB_TOP     ( 1U << 2 ) /* we have a subscript top   */
+                                              /* blue zone                 */
+#define AF_LATIN_BLUE_NEUTRAL     ( 1U << 3 ) /* we have neutral blue zone */
+#define AF_LATIN_BLUE_ADJUSTMENT  ( 1U << 4 ) /* used for scale adjustment */
                                               /* optimization              */