[psaux] Make `t1_decoder_parse_metrics' handle `op_div' (#57519).

* src/psaux/t1decode.c (t1_decoder_parse_metrics): Copy
corresponding code from old engine's `t1_decoder_parse_charstrings'
function.
diff --git a/ChangeLog b/ChangeLog
index e7b3e7b..16a7456 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2020-02-21  Werner Lemberg  <wl@gnu.org>
+
+	[psaux] Make `t1_decoder_parse_metrics' handle `op_div' (#57519).
+
+	* src/psaux/t1decode.c (t1_decoder_parse_metrics): Copy
+	corresponding code from old engine's `t1_decoder_parse_charstrings'
+	function.
+
 2020-02-19  Nikolaus Waxweiler  <nikolaus.waxweiler@daltonmaag.com>
 
 	[autofit] Add support for Hanifi Rohingya script.
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index 9ca5d47..fa1745d 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -659,10 +659,8 @@
         if ( value > 32000 || value < -32000 )
         {
           if ( large_int )
-          {
             FT_ERROR(( "t1_decoder_parse_charstrings:"
                        " no `div' after large integer\n" ));
-          }
           else
             large_int = TRUE;
         }
@@ -1699,6 +1697,7 @@
     FT_Byte*         ip;
     FT_Byte*         limit;
     T1_Builder       builder = &decoder->builder;
+    FT_Bool          large_int;
 
 #ifdef FT_DEBUG_LEVEL_TRACE
     FT_Bool          bol = TRUE;
@@ -1716,6 +1715,8 @@
     limit = zone->limit  = charstring_base + charstring_len;
     ip    = zone->cursor = zone->base;
 
+    large_int = FALSE;
+
     /* now, execute loop */
     while ( ip < limit )
     {
@@ -1776,6 +1777,9 @@
         case 7:
           op = op_sbw;
           break;
+        case 12:
+          op = op_div;
+          break;
 
         default:
           goto No_Width;
@@ -1805,13 +1809,19 @@
         /* anyway.                                                         */
         if ( value > 32000 || value < -32000 )
         {
-          FT_ERROR(( "t1_decoder_parse_metrics:"
-                     " large integer found for width\n" ));
-          goto Syntax_Error;
+          if ( large_int )
+          {
+            FT_ERROR(( "t1_decoder_parse_metrics:"
+                       " no `div' after large integer\n" ));
+            goto Syntax_Error;
+          }
+          else
+            large_int = TRUE;
         }
         else
         {
-          value = (FT_Int32)( (FT_UInt32)value << 16 );
+          if ( !large_int )
+            value = (FT_Int32)( (FT_UInt32)value << 16 );
         }
 
         break;
@@ -1836,7 +1846,8 @@
               value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
           }
 
-          value = (FT_Int32)( (FT_UInt32)value << 16 );
+          if ( !large_int )
+            value = (FT_Int32)( (FT_UInt32)value << 16 );
         }
         else
         {
@@ -1846,6 +1857,13 @@
         }
       }
 
+      if ( large_int && !( op == op_none || op == op_div ) )
+      {
+        FT_ERROR(( "t1_decoder_parse_metrics:"
+                   " no `div' after large integer\n" ));
+        goto Syntax_Error;
+      }
+
       /**********************************************************************
        *
        * Push value on stack, or process operator
@@ -1860,6 +1878,9 @@
         }
 
 #ifdef FT_DEBUG_LEVEL_TRACE
+        if ( large_int )
+          FT_TRACE4(( " %d", value ));
+        else
           FT_TRACE4(( " %d", value / 65536 ));
 #endif
 
@@ -1878,11 +1899,14 @@
 
 #ifdef FT_DEBUG_LEVEL_TRACE
 
-        if ( top - decoder->stack != num_args )
-          FT_TRACE0(( "t1_decoder_parse_metrics:"
-                      " too much operands on the stack"
-                      " (seen %d, expected %d)\n",
-                      top - decoder->stack, num_args ));
+        if ( op != op_div )
+        {
+          if ( top - decoder->stack != num_args )
+            FT_TRACE0(( "t1_decoder_parse_metrics:"
+                        " too much operands on the stack"
+                        " (seen %d, expected %d)\n",
+                        top - decoder->stack, num_args ));
+        }
 
 #endif /* FT_DEBUG_LEVEL_TRACE */
 
@@ -1926,12 +1950,26 @@
           FT_TRACE4(( "\n" ));
           return FT_Err_Ok;
 
+        case op_div:
+          FT_TRACE4(( " div" ));
+
+          /* if `large_int' is set, we divide unscaled numbers; */
+          /* otherwise, we divide numbers in 16.16 format --    */
+          /* in both cases, it is the same operation            */
+          *top = FT_DivFix( top[0], top[1] );
+          top++;
+
+          large_int = FALSE;
+          break;
+
         default:
           FT_ERROR(( "t1_decoder_parse_metrics:"
                      " unhandled opcode %d\n", op ));
           goto Syntax_Error;
         }
 
+        decoder->top = top;
+
       } /* general operator processing */
 
     } /* while ip < limit */