Commit 26a7f0478b95a4da3551072a6c70a77187556f8c

Skef Iterum 2023-07-11T01:40:25

[cff] Make blend operator work with floats in private dicts. The CFF2 blend operator takes N default values and corresponding sets of deltas and pushes N values specific to a designspace location. CFF has a floating point numeric type and the FreeType blending code was not converting those into its internal 16.16 Fixed type format. Fixes #1243. * src/cff/cffparse.c (do_fixed): Handle floating point numbers. Also fix scaling overflow check for integer-to-fixed conversion. * src/cff/cffload.c (cff_blend_doBlend): Updated.

diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index f96002e..bee89f0 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -1364,11 +1364,12 @@
       FT_UInt32        sum;
 
 
-      /* convert inputs to 16.16 fixed-point */
-      sum = cff_parse_num( parser, &parser->stack[i + base] ) * 0x10000;
+      /* convert inputs to 16.16 fixed point */
+      sum = cff_parse_fixed( parser, &parser->stack[i + base] );
 
       for ( j = 1; j < blend->lenBV; j++ )
-        sum += cff_parse_num( parser, &parser->stack[delta++] ) * *weight++;
+        sum += FT_MulFix( cff_parse_fixed( parser, &parser->stack[delta++] ),
+                          *weight++ );
 
       /* point parser stack to new value on blend_stack */
       parser->stack[i + base] = subFont->blend_top;
diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c
index c850dfc..f8270aa 100644
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -499,6 +499,24 @@
   {
     if ( **d == 30 )
       return cff_parse_real( *d, parser->limit, scaling, NULL );
+    else if ( **d == 255 )
+    {
+      FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
+                         ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
+                         ( (FT_UInt32)*( d[0] + 3 ) <<  8 ) |
+                           (FT_UInt32)*( d[0] + 4 )         ) );
+
+      if ( scaling )
+      {
+        if ( FT_ABS( val ) > power_ten_limits[scaling] )
+        {
+           FT_TRACE4(( "!!!OVERFLOW:!!!" ));
+           return val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL;
+        }
+        val *= power_tens[scaling];
+      }
+      return val;
+    }
     else
     {
       FT_Long  val = cff_parse_integer( *d, parser->limit );
@@ -506,7 +524,7 @@
 
       if ( scaling )
       {
-        if ( FT_ABS( val ) > power_ten_limits[scaling] )
+        if ( ( FT_ABS( val ) << 16 ) > power_ten_limits[scaling] )
         {
           val = val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL;
           goto Overflow;