freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2] GSoC-2017-ewaldhew 7927aff 22/42: [psaux] Add Type 1 operati


From: Hew Yih Shiuan Ewald
Subject: [freetype2] GSoC-2017-ewaldhew 7927aff 22/42: [psaux] Add Type 1 operations to Adobe CFF interpreter.
Date: Sun, 27 Aug 2017 20:33:20 -0400 (EDT)

branch: GSoC-2017-ewaldhew
commit 7927aff5104c02de9db7363960a06af7b9fb6d91
Author: Ewald Hew <address@hidden>
Commit: Ewald Hew <address@hidden>

    [psaux] Add Type 1 operations to Adobe CFF interpreter.
    
    The following Type 1 specific ops have been added (copied from t1decode):
      closepath
      vstem3
      hstem3
      seac
      sbw
      callothersubr
      pop
      setcurrentpoint
      hsbw
    
    The following require a Type 1 mode, because of differences in 
specification:
      hstem
      vstem
      vmoveto
      callsubr
      div
      rmoveto
      hmoveto
      Numbers
    
    The subsequent commits will implement these changes and adapt accesses of
    data and objects to the new interpreter.
    
    NOTE: Will not compile in the meantime!
    
    * src/psaux/psintrp.c: Add opcodes to enum.
    Copy relevant code over from t1decode.c (t1_decoder_parse_charstrings).
---
 src/psaux/psintrp.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 262 insertions(+), 22 deletions(-)

diff --git a/src/psaux/psintrp.c b/src/psaux/psintrp.c
index d342d6a..133c3bc 100644
--- a/src/psaux/psintrp.c
+++ b/src/psaux/psintrp.c
@@ -205,11 +205,11 @@
     cf2_cmdHLINETO,      /* 6 */
     cf2_cmdVLINETO,      /* 7 */
     cf2_cmdRRCURVETO,    /* 8 */
-    cf2_cmdRESERVED_9,   /* 9 */
+    cf2_cmdCLOSEPATH,    /* 9      T1 only */
     cf2_cmdCALLSUBR,     /* 10 */
     cf2_cmdRETURN,       /* 11 */
     cf2_cmdESC,          /* 12 */
-    cf2_cmdRESERVED_13,  /* 13 */
+    cf2_cmdHSBW,         /* 13     T1 only */
     cf2_cmdENDCHAR,      /* 14 */
     cf2_cmdVSINDEX,      /* 15 */
     cf2_cmdBLEND,        /* 16 */
@@ -233,13 +233,13 @@
   enum
   {
     cf2_escDOTSECTION,   /* 0 */
-    cf2_escRESERVED_1,   /* 1 */
-    cf2_escRESERVED_2,   /* 2 */
+    cf2_escVSTEM3,       /* 1      T1 only */
+    cf2_escHSTEM3,       /* 2      T1 only */
     cf2_escAND,          /* 3 */
     cf2_escOR,           /* 4 */
     cf2_escNOT,          /* 5 */
-    cf2_escRESERVED_6,   /* 6 */
-    cf2_escRESERVED_7,   /* 7 */
+    cf2_escSEAC,         /* 6      T1 only */
+    cf2_escSBW,          /* 7      T1 only */
     cf2_escRESERVED_8,   /* 8 */
     cf2_escABS,          /* 9 */
     cf2_escADD,          /* 10     like otherADD */
@@ -248,8 +248,8 @@
     cf2_escRESERVED_13,  /* 13 */
     cf2_escNEG,          /* 14 */
     cf2_escEQ,           /* 15 */
-    cf2_escRESERVED_16,  /* 16 */
-    cf2_escRESERVED_17,  /* 17 */
+    cf2_escCALLOTHERSUBR,/* 16     T1 only */
+    cf2_escPOP,          /* 17     T1 only */
     cf2_escDROP,         /* 18 */
     cf2_escRESERVED_19,  /* 19 */
     cf2_escPUT,          /* 20     like otherPUT    */
@@ -265,7 +265,7 @@
     cf2_escROLL,         /* 30 */
     cf2_escRESERVED_31,  /* 31 */
     cf2_escRESERVED_32,  /* 32 */
-    cf2_escRESERVED_33,  /* 33 */
+    cf2_escSETCURRENTPT, /* 33     T1 only */
     cf2_escHFLEX,        /* 34 */
     cf2_escFLEX,         /* 35 */
     cf2_escHFLEX1,       /* 36 */
@@ -484,6 +484,12 @@
     CF2_Fixed  scaleY        = font->innerTransform.d;
     CF2_Fixed  nominalWidthX = cf2_getNominalWidthX( decoder );
 
+    /* Stuff for Type 1 */
+    FT_Pos     orig_x, orig_y;
+    FT_Int     known_othersubr_result_cnt   = 0;
+    FT_Int     unknown_othersubr_result_cnt = 0;
+    FT_Bool    large_int;
+
     /* save this for hinting seac accents */
     CF2_Fixed  hintOriginY = curY;
 
@@ -606,6 +612,12 @@
     /* main interpreter loop */
     while ( 1 )
     {
+      if ( font->isT1 )
+      {
+        FT_ASSERT( known_othersubr_result_cnt == 0   ||
+                   unknown_othersubr_result_cnt == 0 );
+      }
+
       if ( cf2_buf_isEnd( charstring ) )
       {
         /* If we've reached the end of the charstring, simulate a */
@@ -627,6 +639,27 @@
           op1 = cf2_cmdRESERVED_0;
       }
 
+      if ( font->isT1 )
+      {
+        if ( unknown_othersubr_result_cnt > 0 &&
+             !( op1 == cf2_cmdCALLSUBR ||
+                op1 == cf2_cmdRETURN   ||
+                op1 == cf2_escPOP      ||
+                op1 >= 32 /* Numbers */ ) )
+        {
+          /* all operands have been transferred by previous pops */
+          unknown_othersubr_result_cnt = 0;
+        }
+
+        if ( large_int && !( op1 >= 32 || op1 == cf2_escDIV ) )
+        {
+          FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+                     " no `div' after large integer\n" ));
+
+          large_int = FALSE;
+        }
+      }
+
       /* check for errors once per loop */
       if ( *error )
         goto exit;
@@ -642,8 +675,6 @@
       {
       case cf2_cmdRESERVED_0:
       case cf2_cmdRESERVED_2:
-      case cf2_cmdRESERVED_9:
-      case cf2_cmdRESERVED_13:
       case cf2_cmdRESERVED_17:
         /* we may get here if we have a prior error */
         FT_TRACE4(( " unknown op (%d)\n", op1 ));
@@ -777,6 +808,13 @@
         if ( font->decoder->width_only )
           goto exit;
 
+        if ( font->isT1 && !decoder->flex_state )
+        {
+          if ( builder->parse_state == T1_Parse_Start )
+            goto Syntax_Error;
+          builder->parse_state = T1_Parse_Have_Moveto;
+        }
+
         curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
 
         cf2_glyphpath_moveTo( &glyphPath, curX, curY );
@@ -878,6 +916,24 @@
         }
         continue; /* no need to clear stack again */
 
+      case cf2_cmdCLOSEPATH:
+        if ( !font->isT1 )
+        {
+          FT_TRACE4(( " unknown op (%d)\n", op1 ));
+        }
+        else
+        {
+          FT_TRACE4(( " closepath" ));
+
+          /* if there is no path, `closepath' is a no-op */
+          if ( builder->parse_state == T1_Parse_Have_Path   ||
+               builder->parse_state == T1_Parse_Have_Moveto )
+            t1_builder_close_contour( builder );
+
+          builder->parse_state = T1_Parse_Have_Width;
+        }
+        break;
+
       case cf2_cmdCALLGSUBR:
       case cf2_cmdCALLSUBR:
         {
@@ -903,6 +959,17 @@
           /* set up the new CFF region and pointer */
           subrNum = cf2_stack_popInt( opStack );
 
+          if ( font->isT1 && decoder->subrs_hash )
+          {
+            size_t*  val = ft_hash_num_lookup( subrNum,
+                                               decoder->subrs_hash );
+
+            if ( val )
+              subrNum = *val;
+            else
+              subrNum = -1;
+          }
+
           switch ( op1 )
           {
           case cf2_cmdCALLGSUBR:
@@ -1060,20 +1127,13 @@
             }
             continue;
 
-          /* these opcodes are reserved in both CFF & CFF2 */
-          case cf2_escRESERVED_1:
-          case cf2_escRESERVED_2:
-          case cf2_escRESERVED_6:
-          case cf2_escRESERVED_7:
+          /* these opcodes are always reserved */
           case cf2_escRESERVED_8:
           case cf2_escRESERVED_13:
-          case cf2_escRESERVED_16:
-          case cf2_escRESERVED_17:
           case cf2_escRESERVED_19:
           case cf2_escRESERVED_25:
           case cf2_escRESERVED_31:
           case cf2_escRESERVED_32:
-          case cf2_escRESERVED_33:
             FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
             break;
 
@@ -1083,7 +1143,7 @@
                 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
               else
               {
-                /* second switch for 2-byte operators handles just CFF */
+                /* second switch for 2-byte operators handles CFF and Type 1 */
                 switch ( op2 )
                 {
 
@@ -1093,6 +1153,22 @@
 
                   break;
 
+                case cf2_escVSTEM3:
+                  if ( !font->isT1 )
+                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+                  else
+                  {
+                  }
+                  break;
+
+                case cf2_escHSTEM3:
+                  if ( !font->isT1 )
+                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+                  else
+                  {
+                  }
+                  break;
+
                 case cf2_escAND:
                   {
                     CF2_F16Dot16  arg1;
@@ -1136,6 +1212,52 @@
                   }
                   continue; /* do not clear the stack */
 
+                case cf2_escSEAC:
+                  {
+                    if ( !font->isT1 )
+                      FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+                    else
+                    {
+                      return t1operator_seac( decoder,
+                                              top[0],
+                                              top[1],
+                                              top[2],
+                                              Fix2Int( top[3] ),
+                                              Fix2Int( top[4] ) );
+                    }
+                  }
+                  break;
+
+                case cf2_escSBW:
+                  {
+                    if ( !font->isT1 )
+                      FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+                    else
+                    {
+                      FT_TRACE4(( " sbw" ));
+
+                      builder->parse_state = T1_Parse_Have_Width;
+
+                      builder->left_bearing.x = ADD_LONG( 
builder->left_bearing.x,
+                                                          top[0] );
+                      builder->left_bearing.y = ADD_LONG( 
builder->left_bearing.y,
+                                                          top[1] );
+
+                      builder->advance.x = top[2];
+                      builder->advance.y = top[3];
+
+                      x = ADD_LONG( builder->pos_x, top[0] );
+                      y = ADD_LONG( builder->pos_y, top[1] );
+
+                      /* the `metrics_only' indicates that we only want to 
compute */
+                      /* the glyph's metrics (lsb + advance width), not load 
the   */
+                      /* rest of it; so exit immediately                       
    */
+                      if ( builder->metrics_only )
+                        return FT_Err_Ok;
+                    }
+                  }
+                  break;
+
                 case cf2_escABS:
                   {
                     CF2_F16Dot16  arg;
@@ -1198,6 +1320,9 @@
 
                     cf2_stack_pushFixed( opStack,
                                          FT_DivFix( dividend, divisor ) );
+
+                    if ( font->isT1 )
+                      large_int = FALSE;
                   }
                   continue; /* do not clear the stack */
 
@@ -1232,6 +1357,40 @@
                   }
                   continue; /* do not clear the stack */
 
+                case cf2_escCALLOTHERSUBR:
+                  if ( !font->isT1 )
+                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+                  else
+                  {
+                  }
+                  break;
+
+                case cf2_escPOP:
+                  if ( !font->isT1 )
+                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+                  else
+                  {
+                    FT_TRACE4(( " pop" ));
+
+                    if ( known_othersubr_result_cnt > 0 )
+                    {
+                      known_othersubr_result_cnt--;
+                      /* ignore, we pushed the operands ourselves */
+                      break;
+                    }
+
+                    if ( unknown_othersubr_result_cnt == 0 )
+                    {
+                      FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+                                 " no more operands for othersubr\n" ));
+                      goto Syntax_Error;
+                    }
+
+                    unknown_othersubr_result_cnt--;
+                    top++;   /* `push' the operand to callothersubr onto the 
stack */
+                  }
+                  break;
+
                 case cf2_escDROP:
                   FT_TRACE4(( " drop\n" ));
 
@@ -1433,6 +1592,43 @@
                   }
                   continue; /* do not clear the stack */
 
+                case cf2_escSETCURRENTPT:
+                  if ( !font->isT1 )
+                    FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+                  else
+                  {
+                    FT_TRACE4(( " setcurrentpoint" ));
+
+                    /* From the T1 specification, section 6.4:                
*/
+                    /*                                                        
*/
+                    /*   The setcurrentpoint command is used only in          
*/
+                    /*   conjunction with results from OtherSubrs procedures. 
*/
+
+                    /* known_othersubr_result_cnt != 0 is already handled     
*/
+                    /* above.                                                 
*/
+
+                    /* Note, however, that both Ghostscript and Adobe         
*/
+                    /* Distiller handle this situation by silently ignoring   
*/
+                    /* the inappropriate `setcurrentpoint' instruction.  So   
*/
+                    /* we do the same.                                        
*/
+#if 0
+
+                    if ( decoder->flex_state != 1 )
+                    {
+                      FT_ERROR(( "t1_decoder_parse_charstrings:"
+                                 " unexpected `setcurrentpoint'\n" ));
+                      goto Syntax_Error;
+                    }
+                    else
+                      ...
+#endif
+
+                    x = top[0];
+                    y = top[1];
+                    decoder->flex_state = 0;
+                  }
+                  break;
+
                 } /* end of 2nd switch checking op2 */
               }
             }
@@ -1441,6 +1637,36 @@
 
         break;
 
+      case cf2_cmdHSBW:
+        if ( !font->isT1 )
+        {
+          FT_TRACE4(( " unknown op (%d)\n", op1 ));
+        }
+        else
+        {
+          FT_TRACE4(( " hsbw" ));
+
+          builder->parse_state = T1_Parse_Have_Width;
+
+          builder->left_bearing.x = ADD_LONG( builder->left_bearing.x,
+                                              top[0] );
+
+          builder->advance.x = top[1];
+          builder->advance.y = 0;
+
+          orig_x = x = ADD_LONG( builder->pos_x, top[0] );
+          orig_y = y = builder->pos_y;
+
+          FT_UNUSED( orig_y );
+
+          /* the `metrics_only' indicates that we only want to compute */
+          /* the glyph's metrics (lsb + advance width), not load the   */
+          /* rest of it; so exit immediately                           */
+          if ( builder->metrics_only )
+            return FT_Err_Ok;
+        }
+        break;
+
       case cf2_cmdENDCHAR:
         FT_TRACE4(( " endchar\n" ));
 
@@ -1461,8 +1687,8 @@
         /* close path if still open */
         cf2_glyphpath_closeOpenPath( &glyphPath );
 
-        /* disable seac for CFF2 (charstring ending with args on stack) */
-        if ( !font->isCFF2 && cf2_stack_count( opStack ) > 1 )
+        /* disable seac for CFF2 and Type1 (charstring ending with args on 
stack) */
+        if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 )
         {
           /* must be either 4 or 5 --                       */
           /* this is a (deprecated) implied `seac' operator */
@@ -1606,6 +1832,13 @@
         if ( font->decoder->width_only )
           goto exit;
 
+        if ( font->isT1 && !decoder->flex_state )
+        {
+          if ( builder->parse_state == T1_Parse_Start )
+            goto Syntax_Error;
+          builder->parse_state = T1_Parse_Have_Moveto;
+        }
+
         curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
         curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
 
@@ -1626,6 +1859,13 @@
         if ( font->decoder->width_only )
           goto exit;
 
+        if ( font->isT1 && !decoder->flex_state )
+        {
+          if ( builder->parse_state == T1_Parse_Start )
+            goto Syntax_Error;
+          builder->parse_state = T1_Parse_Have_Moveto;
+        }
+        
         curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
 
         cf2_glyphpath_moveTo( &glyphPath, curX, curY );



reply via email to

[Prev in Thread] Current Thread [Next in Thread]