Commit 54d43a39c5a25919293763af19cc6d7aeacafd2a

John Tytgat 2012-12-05T11:14:41

[pshinter] Clamp BlueScale value. This is Savannah bug #37856. * src/pshinter/pshglob.c (psh_calc_max_height): New function. (psh_globals_new): Use it to limit BlueScale value to `1 / max_of_blue_zone_heights'.

diff --git a/ChangeLog b/ChangeLog
index 8784c87..42ef501 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2012-12-03  John Tytgat  <John.Tytgat@esko.com>
+
+	[pshinter] Clamp BlueScale value.
+
+	This is Savannah bug #37856.
+
+	* src/pshinter/pshglob.c (psh_calc_max_height): New function.
+	(psh_globals_new): Use it to limit BlueScale value to
+	`1 / max_of_blue_zone_heights'.
+
 2012-12-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	[truetype, type1] Revise the use of FT_MulDiv.
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index 31231ad..9285efc 100644
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
 /*    PostScript hinter global hinting management (body).                  */
 /*    Inspired by the new auto-hinter module.                              */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2004, 2006, 2010 by                        */
+/*  Copyright 2001-2004, 2006, 2010, 2012 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -522,6 +522,28 @@
   }
 
 
+  /* calculate the maximum height of given blue zones */
+  static FT_Short
+  psh_calc_max_height( FT_UInt          num,
+                       const FT_Short*  values,
+                       FT_Short         cur_max )
+  {
+    FT_UInt  count;
+
+
+    for ( count = 0; count < num; count += 2 )
+    {
+      FT_Short  cur_height = values[count + 1] - values[count];
+
+
+      if ( cur_height > cur_max )
+        cur_max = cur_height;
+    }
+
+    return cur_max;
+  }
+
+
   FT_LOCAL_DEF( void )
   psh_blues_snap_stem( PSH_Blues      blues,
                        FT_Int         stem_top,
@@ -684,7 +706,32 @@
                            priv->family_blues, priv->num_family_other_blues,
                            priv->family_other_blues, priv->blue_fuzz, 1 );
 
-      globals->blues.blue_scale = priv->blue_scale;
+      /* limit the BlueScale value to `1 / max_of_blue_zone_heights' */
+      {
+        FT_Fixed  max_scale;
+        FT_Short  max_height = 1;
+
+
+        max_height = psh_calc_max_height( priv->num_blue_values,
+                                          priv->blue_values,
+                                          max_height );
+        max_height = psh_calc_max_height( priv->num_other_blues,
+                                          priv->other_blues,
+                                          max_height );
+        max_height = psh_calc_max_height( priv->num_family_blues,
+                                          priv->family_blues,
+                                          max_height );
+        max_height = psh_calc_max_height( priv->num_family_other_blues,
+                                          priv->family_other_blues,
+                                          max_height );
+
+        /* BlueScale is scaled 1000 times */
+        max_scale = FT_DivFix( 1000, max_height );
+        globals->blues.blue_scale = priv->blue_scale < max_scale
+                                      ? priv->blue_scale
+                                      : max_scale;
+      }
+
       globals->blues.blue_shift = priv->blue_shift;
       globals->blues.blue_fuzz  = priv->blue_fuzz;