"Fossies" - the Fresh Open Source Software Archive

Member "yudit-3.0.7/swindow/SFontCFF.cpp" (7 Jun 2020, 51467 Bytes) of package /linux/misc/yudit-3.0.7.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "SFontCFF.cpp" see the Fossies "Dox" file reference documentation.

    1 /** 
    2  *  Yudit Unicode Editor Source File
    3  *
    4  *  GNU Copyright (C) 1997-2006  Gaspar Sinai <gaspar@yudit.org>  
    5  *
    6  *  This program is free software; you can redistribute it and/or modify
    7  *  it under the terms of the GNU General Public License, version 2,
    8  *  dated June 1991. See file COPYYING for details.
    9  *
   10  *  This program is distributed in the hope that it will be useful,
   11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  *  GNU General Public License for more details.
   14  *
   15  *  You should have received a copy of the GNU General Public License
   16  *  along with this program; if not, write to the Free Software
   17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18  */
   19 
   20 
   21 #include "swindow/SFontTTF.h"
   22 #include "swindow/STTables.h"
   23 
   24 /*
   25  * ntohl 
   26  */
   27 #ifndef USE_WINAPI
   28 #include <netinet/in.h>
   29 #else
   30 #include <winsock.h>
   31 #endif
   32 
   33 #include <stdio.h>
   34 #include <ctype.h>
   35 #include <math.h>
   36 
   37 #define DEBUG 0
   38 #define HAS_CFF2 0
   39 
   40 static const SString SS_TB_CFF("CFF ");
   41 static const SString SS_TB_CFF2("CFF2");
   42 
   43 #define SD_DICT_OP_Version 0x00
   44 #define SD_DICT_OP_Notice 0x01
   45 #define SD_DICT_OP_FullName 0x02
   46 #define SD_DICT_OP_FamilyName 0x03
   47 #define SD_DICT_OP_Weight 0x04
   48 #define SD_DICT_OP_FontBox 0x05
   49 #define SD_DICT_OP_BlueValues 0x06
   50 #define SD_DICT_OP_OtherBlues 0x07
   51 #define SD_DICT_OP_FamilyBlues 0x08
   52 #define SD_DICT_OP_FamilyOtherBlues 0x09
   53 #define SD_DICT_OP_StdHW 0x0a
   54 #define SD_DICT_OP_StdVW 0x0b
   55 // purosefully shifted << 8
   56 #define SD_DICT_OP_escape 0x0c00
   57 #define SD_DICT_OP_UniqeuID 0x0d
   58 #define SD_DICT_OP_XUID 0x0e
   59 #define SD_DICT_OP_CharSet 0x0f
   60 #define SD_DICT_OP_Encoding 0x10
   61 #define SD_DICT_OP_CharStrings 0x11
   62 #define SD_DICT_OP_Private 0x12
   63 #define SD_DICT_OP_Subrs 0x13
   64 #define SD_DICT_OP_DefaultWidthX 0x14
   65 #define SD_DICT_OP_NominalWidthX 0x15
   66 // Reserved
   67 // 16 + 7 = 23
   68 #define SD_DICT_OP_blend 0x17
   69 // Reserved
   70 #define SD_DICT_OP_shortint 0x1c
   71 #define SD_DICT_OP_longint 0x1d
   72 #define SD_DICT_OP_BCD 0x1e
   73 
   74 // 2 Byte DICT Operators
   75 #define SD_DICT_OP_Copyriight (0x00 | SD_DICT_OP_escape)
   76 #define SD_DICT_OP_isFixedPitch (0x01 | SD_DICT_OP_escape)
   77 #define SD_DICT_OP_isItalicAngle (0x02 | SD_DICT_OP_escape)
   78 #define SD_DICT_OP_UnderlinePosition (0x03 | SD_DICT_OP_escape)
   79 #define SD_DICT_OP_UnderlineThickness (0x04 | SD_DICT_OP_escape)
   80 #define SD_DICT_OP_PaintType (0x05 | SD_DICT_OP_escape)
   81 #define SD_DICT_OP_CharStringType (0x06 | SD_DICT_OP_escape)
   82 #define SD_DICT_OP_FontMatrix (0x07 | SD_DICT_OP_escape)
   83 #define SD_DICT_OP_StrokeWidth (0x08 | SD_DICT_OP_escape)
   84 #define SD_DICT_OP_BlueScale (0x09 | SD_DICT_OP_escape)
   85 #define SD_DICT_OP_BlueShift (0x0a | SD_DICT_OP_escape)
   86 #define SD_DICT_OP_BlueFuzx (0x0b | SD_DICT_OP_escape)
   87 #define SD_DICT_OP_SpemSnapH (0x0c | SD_DICT_OP_escape)
   88 #define SD_DICT_OP_SpemSnapV (0x0d | SD_DICT_OP_escape)
   89 #define SD_DICT_OP_ForceBold (0x0e | SD_DICT_OP_escape)
   90 //reserved
   91 #define SD_DICT_OP_LanguageGroup (0x11 | SD_DICT_OP_escape)
   92 #define SD_DICT_OP_ExpansionFactor (0x12 | SD_DICT_OP_escape)
   93 #define SD_DICT_OP_InitialRandomSpeed (0x13 | SD_DICT_OP_escape)
   94 #define SD_DICT_OP_SynteticBase (0x14 | SD_DICT_OP_escape)
   95 #define SD_DICT_OP_Posscript (0x15 | SD_DICT_OP_escape)
   96 #define SD_DICT_OP_BaseFontName (0x16 | SD_DICT_OP_escape)
   97 #define SD_DICT_OP_BaseFontBlend (0x17 | SD_DICT_OP_escape)
   98 // reserverd
   99 #define SD_DICT_OP_ROS (0x1e | SD_DICT_OP_escape)
  100 #define SD_DICT_OP_CIDFontVersion (0x1f | SD_DICT_OP_escape)
  101 #define SD_DICT_OP_CIDFontRevision (0x20 | SD_DICT_OP_escape)
  102 #define SD_DICT_OP_CIDFontType (0x21 | SD_DICT_OP_escape)
  103 #define SD_DICT_OP_CIDCount (0x22 | SD_DICT_OP_escape)
  104 #define SD_DICT_OP_UIDBase (0x23 | SD_DICT_OP_escape)
  105 #define SD_DICT_OP_FDArray (0x24 | SD_DICT_OP_escape)
  106 #define SD_DICT_OP_FDSelect (0x25 | SD_DICT_OP_escape)
  107 #define SD_DICT_OP_FontName (0x26 | SD_DICT_OP_escape)
  108 
  109 
  110 static SD_USHORT ntohs_p (SD_BYTE* byte) {
  111     SD_USHORT b0 = byte[0];
  112     SD_USHORT b1 = byte[1];
  113     // Big endian high byte low offset
  114     return (b0<<8) + b1;
  115 }
  116 
  117 static SD_USHORT ntohl_p (SD_BYTE* byte) {
  118     SD_ULONG b0 = byte[0];
  119     SD_ULONG b1 = byte[1];
  120     SD_ULONG b2 = byte[2];
  121     SD_ULONG b3 = byte[3];
  122     // Big endian high byte low offset
  123     return (b0<<24) | (b1<<16) | (b2 << 8) | b3;
  124 }
  125 
  126 
  127 static bool dictionaryFind (
  128     SBinVector<double>* operands,
  129     SD_BYTE* topDICT, SD_ULONG len, int op) {
  130 
  131     SD_BYTE*  dp = topDICT;
  132     
  133     SD_ULONG i = 0;
  134     SS_SINT_32 intValue = 0;
  135     double doubleValue = 0.0;
  136     operands->clear();
  137     // CFF
  138     //SD_ULONG maxOperands = 48;
  139     // CFF2
  140     SD_ULONG maxOperands = 513;
  141     while (i<len) {
  142 // MAKKA
  143 /*
  144          fprintf (stderr, "Next DICT operand/operator %u at %u ops:%u\n", 
  145                 (unsigned int)*dp, i, operands->size()); 
  146 */
  147 
  148         // size 1 integer
  149         if (*dp >= 32 && *dp <= 246) {
  150             intValue = (SS_SINT_32)dp[0] - 139;
  151             dp++; i++;
  152             doubleValue = (double) intValue;
  153             operands->append (doubleValue);
  154         // size 2 integer
  155         } else  if (*dp >= 247 && *dp <= 250) {
  156             SS_SINT_32 b0 = *dp;
  157             dp++; i++; 
  158             SS_SINT_32 b1 = *dp;
  159             dp++; i++; 
  160             intValue = (b0 - 247) * 256  + b1 + 108;
  161             doubleValue = (double) intValue;
  162             operands->append (doubleValue);
  163         // size 2 integer
  164         } else if (*dp >= 251 && *dp <= 254) {
  165             SS_SINT_32 b0 = *dp;
  166             dp++; i++; 
  167             SS_SINT_32 b1 = *dp;
  168             dp++; i++; 
  169             intValue = -(b0 - 251) * 256  - b1 - 108;
  170             doubleValue = (double) intValue;
  171             operands->append (doubleValue);
  172         // size 3 integer
  173         } else if (*dp == 28) {
  174             dp++; i++;
  175             SS_SINT_32 b1 = *dp;
  176             dp++; i++;
  177             SS_SINT_32 b2 = *dp;
  178             dp++; i++;
  179             SS_SINT_16 v = (b1<<8)|b2;  
  180             intValue = v; 
  181             doubleValue = (double) intValue;
  182             operands->append (doubleValue);
  183         // size 5 integer 
  184         } else if (*dp == 29) {
  185             dp++; i++;
  186             SS_SINT_32 b1 = *dp;
  187             dp++; i++;
  188             SS_SINT_32 b2 = *dp;
  189             dp++; i++;
  190             SS_SINT_32 b3 = *dp;
  191             dp++; i++;
  192             SS_SINT_32 b4 = *dp;
  193             dp++; i++;
  194             intValue = (b1<<24)|(b2<<16)|(b3<<8)|b4;
  195             doubleValue = (double) intValue;
  196             operands->append (doubleValue);
  197         // variable size float
  198         } else if (*dp == 30) {
  199             dp++; i++;
  200             SString s;
  201             while (i<len) {
  202                 SS_SINT_32 ba[2] = {
  203                     ((*dp) >> 8) & 0x0f, 
  204                     (*dp) & 0x0f
  205                 };
  206                 dp++; i++;
  207                 bool finished = false;
  208                 for (unsigned int j=0; j<2; j++) {
  209                     SS_SINT_32 b = ba[j];
  210                     if (b == 0xf) {
  211                         finished = true;
  212                         break;
  213                     }
  214                     if (b <= 9) {
  215                         s.append ((char) ('0' + (char)b));
  216                     } else if (b == 0xa) {
  217                         s.append ('.');
  218                     } else if (b == 0xb) {
  219                         s.append ('E');
  220                     } else if (b == 0xc) {
  221                         s.append ("E-");
  222                     // skip d
  223                     } else if (b == 0xe) {
  224                         s.append ('-');
  225                     }
  226                 }
  227                 if (finished) break;
  228             }
  229             s.append ((char)0);
  230             if (sscanf (s.array(), "%lf", &doubleValue) != 1) {
  231 #if DEBUG
  232                 fprintf (stderr, "Bad Float %s\n", s.array());
  233 #endif
  234                 operands->clear();
  235                 return false;
  236             }
  237             operands->append (doubleValue);
  238         // Operator
  239         //} else if ((*dp >= 0 && *dp <= 21) || *dp == 24
  240         } else if (*dp >= 0 && *dp <= 24) {
  241             intValue = *dp;
  242             dp++; i++;
  243             // 2 byte operator
  244             if (intValue == 0x0c ) {
  245                 intValue = (*dp) | SD_DICT_OP_escape;
  246                 dp++; i++;
  247             }        
  248 // MAKKA
  249 #if 0
  250             fprintf (stderr, "OperandSize %d operator 0x%04x\n",
  251                     operands->size(), intValue);
  252 #endif
  253 //fprintf (stderr, "int=%d\n", intValue);
  254             if (intValue == op) {
  255                 return true;
  256             }
  257             operands->clear();
  258                 
  259         // FIXME 255 is reserved.
  260         } else {
  261 #if 0
  262             fprintf (stderr, "Bad DICT operand/operator 0x%02x\n", 
  263                 (unsigned int)*dp); 
  264 #endif
  265             operands->clear();
  266             return false;
  267         }
  268         
  269         if (operands->size() > maxOperands) {
  270 #if 0
  271             fprintf (stderr, "Too many DICT operands.");
  272 #endif
  273             operands->clear();
  274             return false;
  275         }
  276     }
  277     operands->clear();
  278     return false;
  279 }
  280 
  281 /**
  282  * Get an element in the index table.
  283  */
  284 static SD_BYTE* indexFind (bool cff2, int at, SD_BYTE* indexTable, SD_ULONG* length) {
  285    SD_ULONG count;
  286    unsigned int countSize;
  287    if (cff2) {
  288         count  = ntohl_p(indexTable);  
  289         countSize = 4;
  290    } else {
  291         count  = ntohs_p(indexTable);  
  292         countSize = 2;
  293    }
  294    *length = 0;
  295    if (at < 0) {
  296       fprintf (stderr, "Negative index at %d\n", at);
  297       return 0;
  298    }
  299    if (count == 0) {
  300        fprintf (stderr, "count error\n");
  301        return 0;
  302    }
  303    if (at >= (int) count) {
  304       fprintf (stderr, "bounds Error\n");
  305       return 0;
  306    }
  307    SD_BYTE osize = indexTable[countSize]; 
  308    if (osize > 4 || osize == 0) {
  309       fprintf (stderr, "offsetSize Error\n");
  310       return 0;
  311    }
  312    SD_BYTE* ip = indexTable + countSize +1 + at * osize;
  313    SD_ULONG startOffset = 0;
  314    int j;
  315    for (j=0; j<osize; j++) {
  316       startOffset = (startOffset << 8) + (SD_ULONG) (*ip++);
  317    }
  318    
  319    ip = indexTable + countSize +1 + (at+1) * osize;
  320    SD_ULONG endOffset = 0;
  321    for (j=0; j<osize; j++) {
  322       endOffset = (endOffset << 8) + (SD_ULONG) (*ip++);
  323    }
  324    if (startOffset > endOffset) {
  325       fprintf (stderr, "Start-end offset Error at %d\n", at);
  326       return 0;
  327    }
  328    ip = indexTable + countSize +1 + (count) * osize;
  329    SD_ULONG lastOffset = 0;
  330    for (j=0; j<osize; j++) {
  331       lastOffset = (lastOffset << 8) + (SD_ULONG) (*ip++);
  332    }
  333    *length = endOffset - startOffset;
  334    return ip + startOffset -1;
  335 }
  336 
  337 /**
  338  * Get one of the 4 index tables following the header.
  339  */
  340 static SD_BYTE* getIndexTable (bool cff2, int at, SD_BYTE *header) {
  341 /*
  342    fprintf (stderr, "hsize = %u\n", 
  343         (unsigned int) ((SS_CFF_Header*)header)->hsize);
  344 */
  345    unsigned int countSize = cff2 ? 4: 2;
  346    SD_BYTE* now = header + ((SS_CFF_Header*)header)->hsize;
  347    for (int i=0; i<at; i++) {
  348       SD_ULONG count = cff2 ? ntohl_p(now): ntohs_p(now);  
  349       if (count == 0) {
  350         now = now + countSize;
  351         continue;
  352       }
  353       SD_BYTE osize = now[countSize];
  354       if (osize > 4 || osize == 0) {
  355         //  Error
  356         return 0;
  357       }
  358       SD_BYTE* ind = now + countSize+1 + (count) * osize;
  359 
  360       SD_ULONG lastOffset = 0;
  361       for (int j=0; j<osize; j++) {
  362          lastOffset = (lastOffset << 8) + (SD_ULONG) (*ind++);
  363       }
  364       // The first element is offset 1.
  365       now = ind + lastOffset-1;
  366    } 
  367    return now;
  368 } 
  369 
  370 SFontCFF::SFontCFF (void) {
  371     cff = 0;
  372     cff2 = 0;
  373 
  374     firstDict = 0;
  375     firstDictLength = 0;
  376 
  377     firstCharStringsIndex = 0;
  378     firstCharStringsLength = 0;
  379 
  380     globalSubrIndex = 0;
  381     globalSubrLength = 0;
  382     
  383     localSubrIndex = 0;
  384     localSubrLength = 0;
  385 
  386     fontDictSelect = 0;
  387     
  388 }
  389 
  390 
  391 SFontCFF::~SFontCFF () {
  392 }
  393 
  394 bool
  395 SFontCFF::initWithCFF (SD_BYTE* aCff) {
  396     cff = aCff;
  397    
  398     /* firstName */
  399     SD_BYTE* nameIndex = getIndexTable(false, 0, cff);  
  400     if (nameIndex == 0) {
  401         fprintf (stderr, "Can not find font name\n");
  402         return false;
  403     }
  404     SD_ULONG len;    
  405     SD_BYTE* ptr = indexFind (false, 0, nameIndex, &len);
  406     firstName = SString ((char*) ptr, (unsigned int)len);
  407 
  408     /* firstDict */
  409     SD_BYTE* topDictIndex = getIndexTable(false, 1, cff);  
  410     if (topDictIndex == 0) {
  411         return false;
  412     }
  413     if (ntohs_p(topDictIndex) != 1) {
  414         fprintf (stderr, "topDictionary has %d names in %*.*s\n",
  415             (int) ntohs_p(topDictIndex), SSARGS(firstName));
  416         return false;
  417     }
  418     firstDict = indexFind (false, 0, topDictIndex, &firstDictLength);
  419 
  420     /* firstCharStringsIndex */
  421     SBinVector<double> operands;
  422     bool found = dictionaryFind (
  423         &operands, firstDict, firstDictLength, 
  424             SD_DICT_OP_CharStrings);
  425     if (!found || operands.size() ==0 || operands[0] <= 0.0) {
  426 #if 0
  427         fprintf (stderr, "firstDictionary has no CharStrings in %*.*s\n",
  428             SSARGS(firstName));
  429 #endif
  430         return false;
  431     }
  432     firstCharStringsIndex= cff + (int)operands[0];
  433     firstCharStringsLength = ntohs_p(firstCharStringsIndex);
  434 
  435     /* globalSubrIndex */
  436     globalSubrIndex = getIndexTable(false, 3, cff);  
  437     globalSubrLength = ntohs_p(globalSubrIndex);
  438 
  439     /* localSubrIndex */
  440     operands.clear();
  441     found= dictionaryFind (&operands, firstDict, firstDictLength, 
  442             SD_DICT_OP_Private);
  443 
  444     localSubrIndex = 0;
  445     localSubrLength = 0;
  446 
  447     if (found && operands.size() == 2) {
  448         SD_BYTE* privateDict = 0;
  449         privateDict = cff + (int) operands[1];
  450         SD_ULONG pdictLen = (SD_ULONG) operands[0];
  451         operands.clear();
  452         found= dictionaryFind (
  453                 &operands, privateDict, pdictLen, 
  454                 SD_DICT_OP_Subrs);
  455         if (found && operands.size() == 1) {
  456             // relative to privateDict
  457             localSubrIndex = privateDict + (int) operands[0];
  458             localSubrLength = ntohs_p(localSubrIndex);
  459         }
  460         // dont check for CharStrings 
  461     }
  462 #if 0
  463     fprintf (stderr, "SFontType [%*.*s] initialized\n",
  464         SSARGS(firstName)); 
  465     fprintf (stderr, 
  466        "firstCharStrings:%lx,%u globalSubr:%lx,%u localSubr:%lx,%u\n",
  467         (unsigned long)firstCharStringsIndex, firstCharStringsLength, 
  468         (unsigned long) globalSubrIndex, globalSubrLength, 
  469         (unsigned long) localSubrIndex, localSubrLength);
  470 #endif
  471         
  472     return true;
  473 }
  474 
  475 // Not supported yet
  476 bool
  477 SFontCFF::initWithCFF2 (SD_BYTE* aCff2) {
  478 #if HAS_CFF2 
  479     cff2 = aCff2;
  480     firstDict =  cff2 + (SD_ULONG) cff2[2];
  481     // 16 bit
  482     firstDictLength = ntohs_p(cff2+3);
  483 #if DEBUG
  484     fprintf (stderr, "headerSize=%u, firstDictLength=%u\n", 
  485             (SD_ULONG) cff2[2], firstDictLength);
  486 #endif
  487     
  488     firstName = SString ("CFF2");
  489 
  490     /* firstCharStringsIndex */
  491     SBinVector<double> operands;
  492     bool found = dictionaryFind (
  493         &operands, firstDict, firstDictLength, 
  494             SD_DICT_OP_CharStrings);
  495     if (!found || operands.size() ==0 || operands[0] <= 0.0) {
  496         fprintf (stderr, "firstDictionary has no CharStrings in %*.*s\n",
  497             SSARGS(firstName));
  498         return false;
  499     }
  500     firstCharStringsIndex= cff2 + (int)operands[0];
  501     firstCharStringsLength = ntohl_p(firstCharStringsIndex);
  502 
  503     /* globalSubrIndex */
  504     globalSubrIndex = firstDict + firstDictLength;  
  505     globalSubrLength = ntohl_p(globalSubrIndex);
  506 
  507     /* localSubrIndex */
  508     operands.clear();
  509     // Finding FDSelect table.
  510     
  511     found= dictionaryFind (&operands, firstDict, firstDictLength, 
  512             SD_DICT_OP_FDArray);
  513 
  514     localSubrIndex = 0;
  515     localSubrLength = 0;
  516     fontDictIndex = 0;
  517     fontDictLength = 0;
  518     fontDictSelect = 0;
  519 
  520     if (found && operands.size() == 1) {
  521         if (operands.size () != 1) return -1;
  522         fontDictIndex = cff2 + (int) operands[0];
  523         fontDictLength = ntohl_p (fontDictIndex);
  524         if (fontDictLength > 1) {
  525             found= dictionaryFind (&operands, firstDict, firstDictLength, 
  526                 SD_DICT_OP_FDSelect);
  527             if (operands.size () != 1) {
  528                 fprintf(stderr, "Can not find FDSelect dictionary.\n");
  529                 return -1;
  530             }
  531             fontDictSelect = cff2 + (int) operands[0];
  532         }
  533         // FIXME
  534         if (fontDictLength != 1) {
  535             fprintf (stderr, "Only 1 fontDict is supported, got:%u\n", 
  536                 fontDictLength);
  537             return false;
  538         }
  539     }
  540 #if DEBUG
  541     fprintf (stderr, "SFontType [%*.*s] initialized\n",
  542         SSARGS(firstName)); 
  543     fprintf (stderr, 
  544        "firstCharStrings:%lx,%u globalSubr:%lx,%u fontDict:%lx,%u fontDictSelect=%lx\n",
  545         (unsigned long)firstCharStringsIndex, firstCharStringsLength, 
  546         (unsigned long) globalSubrIndex, globalSubrLength, 
  547         (unsigned long) fontDictIndex, fontDictLength,
  548         (unsigned long) fontDictSelect);
  549 #endif
  550         
  551     return true;
  552 #else /* has CFF2 */
  553     fprintf (stderr, "CFF2 format is not supported.\n");
  554     return false;
  555 #endif
  556 }
  557 
  558 // hasCFFData
  559 // TTF_GLYF*
  560 SD_BYTE*
  561 SFontCFF::getType2Glyph (SS_GlyphIndex glyphno, SD_ULONG* len) const {
  562   *len = 0;
  563   // TODO
  564   if (cff != 0) {
  565     SD_ULONG length;
  566     SD_BYTE* retP = indexFind (false, (int)glyphno, firstCharStringsIndex, &length);
  567     //SD_BYTE* retP = indexFind (false, (int)4, firstCharStringsIndex, &length);
  568 #if 0
  569     fprintf( stderr, "Byte %0x %0x\n", 
  570         (unsigned int) retP[0], (unsigned int) retP[1]);
  571 #endif
  572     *len = length;
  573     return retP;
  574   }
  575   if (cff2 != 0) {
  576     //fprintf (stderr, "TODO: get CFF2 Glyph %x\n", glyphno);
  577     SD_ULONG length;
  578     SD_BYTE* retP = indexFind (true, (int)glyphno, firstCharStringsIndex, &length);
  579     *len = length;
  580     return retP;
  581   }
  582   return 0;
  583 }
  584 
  585 bool
  586 SFontCFF::updateLocalSubr (SS_GlyphIndex glyphno) {
  587     if (cff) return true;
  588     if (fontDictLength != 1) return false;
  589     SD_ULONG length;
  590     int index = 0;
  591     // FIXME Add FDSelect for multiple dicts.
  592     SD_BYTE* dict = indexFind (true, index, fontDictIndex, &length);
  593     if (dict == 0 || length == 0) return false;
  594     SBinVector<double> operands;
  595    // fprintf (stderr, "updateLocal...\n");
  596     bool found= dictionaryFind (&operands, dict, length, 
  597                 SD_DICT_OP_Private);
  598     localSubrIndex = 0;
  599     localSubrLength = 0;
  600     if (found && operands.size() == 2) {
  601         SD_BYTE* privateDict = cff2 + (int) operands[1];
  602         SD_ULONG privateLength = (SD_ULONG) operands[0];
  603 #if 0
  604     fprintf (stderr, "XXXXXX   updateLocal %u at %g\n",
  605          privateLength, operands[1]);
  606 #endif
  607 
  608         operands.clear();
  609 // MAKKA
  610         found= dictionaryFind (
  611                 &operands, privateDict, privateLength, 
  612                 SD_DICT_OP_Subrs);
  613         if (found && operands.size() == 1) {
  614             // relative to privateDict
  615             //localSubrIndex = privateDict + (int) operands[0];
  616             localSubrIndex = privateDict + (int) operands[0];
  617             localSubrLength = ntohl_p(localSubrIndex);
  618             if (localSubrIndex[4] > 4 || localSubrIndex[4] == 0) return false;
  619         }
  620         // dont check for CharStrings 
  621 #if 0
  622         found= dictionaryFind (
  623                 &operands, privateDict, privateLength, 
  624                 SD_DICT_OP_blend);
  625         if (!found) {
  626             fprintf (stderr, "Number of blends not found.\n");
  627             return false;
  628         }
  629         numberOfBlends = operands;
  630         fprintf (stderr, "Number of blends: %u %g,%g,%g,%g\n", 
  631             numberOfBlends.size(), 
  632             numberOfBlends[0], 
  633             numberOfBlends[1], 
  634             numberOfBlends[2],
  635             numberOfBlends[3]
  636             );
  637         return false; 
  638 #endif
  639     }
  640 #if 0
  641     fprintf (stderr, "localSubrIndex=%lx,%u\n", 
  642         (unsigned long) localSubrIndex, localSubrLength); 
  643 #endif
  644     return true;
  645 }
  646 
  647 /*
  648  * In OpenType CFF fonts, except that glyph data is accessed 
  649  * through the CharStrings INDEX of the 'CFF ' table.
  650 */
  651 void
  652 SFontCFF::drawGlyphCFF (SCanvas* aCanvas, const SS_Matrix2D& aMatrix,
  653       SS_GlyphIndex glyphno) {
  654     SD_ULONG len = 0;
  655     SD_BYTE* glyph = (SD_BYTE*) getType2Glyph (glyphno, &len);
  656     if (glyph == 0 || len == 0) return;
  657     if (!updateLocalSubr(glyphno)) return;
  658     stack.clear();
  659     canvas = aCanvas;
  660     matrix = aMatrix;
  661     subrCount = 0;
  662     subrLimit = (cff==0) ? 10 : 10;
  663     stackLimit = (cff==0) ? 513 : 48;
  664     lastX = 0.0;
  665     lastY = 0.0;
  666     charStringsBegin = true;
  667     commandCounter = 0;
  668     stemCount = 0;
  669     hintStart = false;
  670     hasGlyphWidth = false;
  671     glyphWidth = 0.0;
  672     //fprintf(stderr, "draw start\n");
  673     parseCharStrings (glyph, len);
  674 #if 0
  675     fprintf(stderr, "draw end hasGlyphWidth: %d glyphWidth: %g\n",
  676         hasGlyphWidth, glyphWidth);
  677 #endif
  678     canvas->closepath();
  679 }
  680 
  681 bool
  682 SFontCFF::getBBOXCFF (SS_GlyphIndex glyphno,
  683       int* xMin, int* yMin, int* xMax, int* yMax) const
  684 {
  685     SD_ULONG len = 0;
  686     SD_BYTE* glyph = (SD_BYTE*) getType2Glyph (glyphno, &len);
  687     if (glyph ==0 || len == 0) return false;
  688     return false;
  689 }
  690 
  691 static int getBias (bool isCFF2, SD_BYTE* subrIndex) {
  692     SD_ULONG nSubrs = isCFF2 ? ntohl_p (subrIndex) : ntohs_p (subrIndex);
  693     if (nSubrs < 1240) return 107;
  694     if (nSubrs < 33900) return 1131;
  695     return 32768;
  696 }
  697 
  698 /*
  699  * The starting width is not taken care of
  700  */
  701 int
  702 SFontCFF::execute (SS_SINT_32 command) {
  703     SD_BYTE* ptr = 0;
  704     SD_ULONG length = 0;
  705     commandCounter++;
  706 //SGCXX
  707     //if (commandCounter > 50) return -1;
  708 #if DEBUG
  709     if (true || (command != SS_CFF_COMMAND_callgsubr &&
  710         command != SS_CFF_COMMAND_callsubr && 
  711         command != SS_CFF_COMMAND_return) ) 
  712     {
  713     fprintf (stderr, "Command[%d] %02x args %u hintStart=%d stemCount=%d\n", 
  714         commandCounter, command, stack.size(), (int)hintStart, stemCount);
  715     }
  716 #endif
  717     double vle = 0.0;
  718     switch (command) {
  719     case SS_CFF_COMMAND_CFF2_blend: // blend
  720         {
  721             if (cff) return 0;
  722             if (stack.size() == 0) return -1;
  723             double n = stack[stack.size()-1];
  724             stack.truncate (stack.size()-1);
  725             if (stack.size() < n || n < 0 || n > stack.size()) return -1;
  726             stack.truncate ((unsigned int) n);
  727         }
  728         return 2;
  729     case SS_CFF_COMMAND_CFF2_vsindex: // vsindex
  730         if (cff) return 0;
  731  //       fprintf (stderr, "SS_CFF_COMMAND_CFF2_vsindex\n");
  732         // we dont support it.
  733         return -1;
  734     case SS_CFF_COMMAND_rlineto: // rlineto
  735         {
  736             if (stack.size() < 2) return -1;
  737             for (unsigned int i=0; i+1<stack.size(); i=i+2) {
  738                 lastX = lastX + stack[i]; 
  739                 lastY = lastY + stack[i+1];
  740                 canvas->lineto (matrix.toX(lastX,lastY), matrix.toY(lastX,lastY)); 
  741             }
  742         }
  743        return 0;
  744     case SS_CFF_COMMAND_hlineto: // hlineto
  745        {
  746             for (unsigned int i=0; i<stack.size(); i++) {
  747                 if (i%2 ==0) {
  748                     lastX = lastX + stack[i]; 
  749                 } else {
  750                     lastY = lastY + stack[i]; 
  751                 }
  752                 canvas->lineto (matrix.toX(lastX,lastY), 
  753                     matrix.toY(lastX,lastY)); 
  754             }
  755             
  756         }
  757         return 0;
  758     case SS_CFF_COMMAND_vlineto: // vlineto
  759        {
  760             for (unsigned int i=0; i<stack.size(); i++) {
  761                 if (i%2 ==1) {
  762                     lastX = lastX + stack[i]; 
  763                 } else {
  764                     lastY = lastY + stack[i]; 
  765                 }
  766                 canvas->lineto (matrix.toX(lastX,lastY), 
  767                     matrix.toY(lastX,lastY)); 
  768             }
  769             
  770         }
  771         return 0;
  772     case SS_CFF_COMMAND_rrcurveto: // rrcurveto
  773         {
  774             unsigned int i=0;
  775             for (i=0; i+5<stack.size(); i=i+6) {
  776                 double xa = lastX + stack[i];
  777                 double ya = lastY + stack[i+1];
  778 
  779                 double xb = xa + stack[i+2];
  780                 double yb = ya + stack[i+3];
  781 
  782                 double xc = xb + stack[i+4];
  783                 double yc = yb + stack[i+5];
  784                 canvas->curveto (
  785                     matrix.toX (xa, ya), matrix.toY (xa, ya),
  786                     matrix.toX (xb, yb), matrix.toY (xb, yb),
  787                     matrix.toX (xc, yc), matrix.toY (xc, yc));
  788                 lastX = xc;
  789                 lastY=  yc;
  790             }
  791         }
  792        return 0;
  793     case SS_CFF_COMMAND_callsubr: // callsubr
  794         {
  795             if (stack.size() == 0) return -1;
  796             if (localSubrIndex == 0) return -1;
  797             int bias =  getBias(cff==0, localSubrIndex);
  798             int index = bias+(int)stack[stack.size()-1];
  799             ptr = indexFind (cff==0, index, localSubrIndex, &length);
  800 #if DEBUG
  801             fprintf (stderr, "callsubr[%d]\n", index);
  802 #endif
  803             stack.truncate (stack.size()-1);
  804             if (ptr == 0) {
  805                 return -1;
  806             }
  807             if (!parseCharStrings (ptr, length)) {
  808                 return -1;
  809             }
  810         }
  811         return 2;
  812     case SS_CFF_COMMAND_return: // return
  813         return 1;
  814     case SS_CFF_COMMAND_endchar: //  endchar
  815         return 0;
  816     case SS_CFF_COMMAND_rmoveto: // rmoveto
  817         {
  818             // FIXME cff2 does not have hasGlyphWidth
  819             if (charStringsBegin && stack.size() == 3) {
  820                 hasGlyphWidth = 1;
  821                 glyphWidth = stack[0];
  822                 stack.remove (0);
  823             }
  824             if (stack.size() != 2) return -1;
  825             if (!charStringsBegin) {
  826                 canvas->closepath();
  827             }
  828             charStringsBegin = false;
  829             lastX = lastX + stack[0]; 
  830             lastY = lastY + stack[1];
  831             canvas->moveto (matrix.toX(lastX, lastY), 
  832                 matrix.toY(lastX, lastY));
  833         }
  834        return 0;
  835     case SS_CFF_COMMAND_hmoveto: // hmoveto
  836        {
  837             // FIXME cff2 does not have hasGlyphWidth
  838             if (charStringsBegin && stack.size() == 2) {
  839                 hasGlyphWidth = 1;
  840                 glyphWidth = stack[0];
  841                 stack.remove (0);
  842             }
  843             if (stack.size() != 1) return -1;
  844             if (!charStringsBegin) {
  845                 canvas->closepath();
  846             }
  847             charStringsBegin = false;
  848             lastX = lastX + stack[0]; 
  849             stack.truncate (stack.size()-1);
  850             canvas->moveto (matrix.toX(lastX, lastY), matrix.toY(lastX, lastY));
  851        }
  852        return 0;
  853     case SS_CFF_COMMAND_vmoveto: // vmoveto
  854        {
  855             // FIXME cff2 does not have hasGlyphWidth
  856             if (charStringsBegin && stack.size() == 2) {
  857                 hasGlyphWidth = 1;
  858                 glyphWidth = stack[0];
  859                 stack.remove (0);
  860             }
  861             if (stack.size() != 1) return -1;
  862             if (!charStringsBegin) {
  863                 canvas->closepath();
  864             }
  865             charStringsBegin = false;
  866             lastY = lastY + stack[0]; 
  867             canvas->moveto (matrix.toX(lastX, lastY), matrix.toY(lastX, lastY));
  868        }
  869        return 0;
  870     case SS_CFF_COMMAND_rcurveline: // rcurveline
  871        {
  872             unsigned int i=0;
  873             for (i=0; i+5<stack.size(); i=i+6) {
  874                 double xa = lastX + stack[i];
  875                 double ya = lastY + stack[i+1];
  876                 double xb = xa + stack[i+2];
  877                 double yb = ya + stack[i+3];
  878                 double xc = xb + stack[i+4];
  879                 double yc = yb + stack[i+5];
  880 
  881                 canvas->curveto (
  882                     matrix.toX (xa, ya), matrix.toY (xa, ya),
  883                     matrix.toX (xb, yb), matrix.toY (xb, yb),
  884                     matrix.toX (xc, yc), matrix.toY (xc, yc));
  885 
  886                 lastX = xc;
  887                 lastY = yc;
  888             }
  889             if (i+1<stack.size()) {
  890                 lastX = lastX + stack[i];
  891                 lastY = lastY + stack[i+1];
  892                 canvas->lineto (
  893                     matrix.toX(lastX, lastY), matrix.toY (lastX, lastY));
  894             }
  895        }
  896        return 0;
  897     case SS_CFF_COMMAND_rlinecurve: // rlinecurve
  898        {
  899             unsigned int i=0;
  900             while (i+1<stack.size() && stack.size()-i >= 8) {
  901                 lastX = lastX + stack[i];
  902                 lastY = lastY + stack[i+1];
  903                 canvas->lineto (
  904                     matrix.toX(lastX, lastY), matrix.toY (lastX, lastY));
  905                 i=i+2;
  906             }
  907             while (i+5<stack.size()) {
  908                 double xa = lastX + stack[i];
  909                 double ya = lastY + stack[i+1];
  910                 double xb = xa + stack[i+2];
  911                 double yb = ya + stack[i+3];
  912                 double xc = xb + stack[i+4];
  913                 double yc = yb + stack[i+5];
  914 
  915                 canvas->curveto (
  916                     matrix.toX (xa, ya), matrix.toY (xa, ya),
  917                     matrix.toX (xb, yb), matrix.toY (xb, yb),
  918                     matrix.toX (xc, yc), matrix.toY (xc, yc));
  919 
  920                 lastX = xc;
  921                 lastY = yc;
  922                 i=i+6;
  923             }
  924        }
  925        return 0;
  926     case SS_CFF_COMMAND_vvcurveto: // vvcurveto
  927         {
  928             unsigned int i=0;
  929             double dx = 0.0;
  930             if (stack.size()%4 == 1) {
  931                 dx = stack[i++];
  932             }
  933             while (i+3<stack.size()) {
  934                 double xa = lastX + dx;
  935                 double ya = lastY + stack[i];
  936                 double xb = xa + stack[i+1];
  937                 double yb = ya + stack[i+2];
  938                 double xc = xb + 0.0;
  939                 double yc = yb + stack[i+3];
  940                 canvas->curveto (
  941                     matrix.toX (xa, ya), matrix.toY (xa, ya),
  942                     matrix.toX (xb, yb), matrix.toY (xb, yb),
  943                     matrix.toX (xc, yc), matrix.toY (xc, yc));
  944                 lastX = xc;
  945                 lastY = yc;
  946 /*
  947 fprintf (stderr, "vvcurveto %g,%g %g,%g %g,%g\n",
  948      matrix.toX (xa, ya), matrix.toY (xa, ya),
  949      matrix.toX (xb, yb), matrix.toY (xb, yb),
  950      matrix.toX (xc, yc), matrix.toY (xc, yc));
  951 */
  952                 dx = 0.0;
  953                 i = i+4;
  954             }
  955         }
  956        return 0;
  957     case SS_CFF_COMMAND_hhcurveto: // hhcurveto
  958         {
  959             unsigned int i=0;
  960             double dy = 0.0;
  961             if (stack.size()%4 == 1) {
  962                 dy = stack[i++];
  963             }
  964             while (i+3<stack.size()) {
  965                 double xa = lastX + stack[i];
  966                 double ya = lastY + dy;
  967                 double xb = xa + stack[i+1];
  968                 double yb = ya + stack[i+2];
  969                 double xc = xb + stack[i+3];
  970                 double yc = yb + 0.0;
  971                 canvas->curveto (
  972                     matrix.toX (xa, ya), matrix.toY (xa, ya),
  973                     matrix.toX (xb, yb), matrix.toY (xb, yb),
  974                     matrix.toX (xc, yc), matrix.toY (xc, yc));
  975 
  976                 lastX = xc;
  977                 lastY = yc;
  978                 dy = 0;
  979                 i=i+4;
  980             }
  981         }
  982        return 0;
  983     case SS_CFF_COMMAND_callgsubr: // callgsubr
  984         {
  985             if (stack.size() == 0) return -1;
  986             if (globalSubrIndex == 0) return -1;
  987             int bias =  getBias(cff==0, globalSubrIndex);
  988             int index = bias+(int)stack[stack.size()-1];
  989             ptr = indexFind (cff==0, index, globalSubrIndex, &length);
  990 #if DEBUG
  991             fprintf (stderr, "callsubr[%d]\n", index);
  992 #endif
  993             stack.truncate (stack.size()-1);
  994             if (ptr == 0) {
  995                 return -1;
  996             }
  997             if (!parseCharStrings (ptr, length)) {
  998                 return -1;
  999             }
 1000         }
 1001         return 2;
 1002     case SS_CFF_COMMAND_vhcurveto: // vhcurveto
 1003         {
 1004             unsigned int i=0;
 1005             while (i+3<stack.size()) {
 1006                 if ((i/4) % 2 == 0) {
 1007                     double xa = lastX + 0.0;
 1008                     double ya = lastY + stack[i];
 1009                     double xb = xa + stack[i+1];
 1010                     double yb = ya + stack[i+2];
 1011                     double dy = 0.0;
 1012                     if (i+5 == stack.size()) {
 1013                          dy = stack[i+4];
 1014                     }
 1015                     double xc = xb + stack[i+3];
 1016                     double yc = yb + dy; 
 1017                     canvas->curveto (
 1018                         matrix.toX (xa, ya), matrix.toY (xa, ya),
 1019                         matrix.toX (xb, yb), matrix.toY (xb, yb),
 1020                         matrix.toX (xc, yc), matrix.toY (xc, yc));
 1021 
 1022                     lastX = xc;
 1023                     lastY = yc;
 1024                 } else {
 1025                     double xa = lastX + stack[i];
 1026                     double ya = lastY + 0.0;
 1027                     double xb = xa + stack[i+1];
 1028                     double yb = ya + stack[i+2];
 1029                     double dx = 0;
 1030                     if (i+5 == stack.size()) {
 1031                         dx = stack[i+4];
 1032                     }
 1033                     double xc = xb + dx; 
 1034                     double yc = yb + stack[i+3];
 1035                     canvas->curveto (
 1036                         matrix.toX (xa, ya), matrix.toY (xa, ya),
 1037                         matrix.toX (xb, yb), matrix.toY (xb, yb),
 1038                         matrix.toX (xc, yc), matrix.toY (xc, yc));
 1039                     lastX = xc;
 1040                     lastY = yc;
 1041                 }
 1042                 i=i+4;
 1043             }
 1044         }
 1045        return 0;
 1046     case SS_CFF_COMMAND_hvcurveto: // hvcurveto
 1047         {
 1048             unsigned int i=0;
 1049             while (i+3<stack.size()) {
 1050                 if ((i/4) % 2 == 1) {
 1051                     double xa = lastX + 0.0;
 1052                     double ya = lastY + stack[i];
 1053                     double xb = xa + stack[i+1];
 1054                     double yb = ya + stack[i+2];
 1055                     double dy = 0.0;
 1056                     if (i+5 == stack.size()) {
 1057                         dy = stack[i+4];
 1058                     }
 1059                     double xc = xb + stack[i+3];
 1060                     double yc = yb + dy;
 1061                     canvas->curveto (
 1062                         matrix.toX (xa, ya), matrix.toY (xa, ya),
 1063                         matrix.toX (xb, yb), matrix.toY (xb, yb),
 1064                         matrix.toX (xc, yc), matrix.toY (xc, yc));
 1065                     lastX = xc;
 1066                     lastY = yc;
 1067                 } else {
 1068                     double xa = lastX + stack[i];
 1069                     double ya = lastY + 0.0;
 1070                     double xb = xa + stack[i+1];
 1071                     double yb = ya + stack[i+2];
 1072                     double dx = 0;
 1073                     if (i+5 == stack.size()) {
 1074                         dx = stack[i+4];
 1075                     }
 1076                     double xc = xb + dx;
 1077                     double yc = yb + stack[i+3];
 1078                     canvas->curveto (
 1079                         matrix.toX (xa, ya), matrix.toY (xa, ya),
 1080                         matrix.toX (xb, yb), matrix.toY (xb, yb),
 1081                         matrix.toX (xc, yc), matrix.toY (xc, yc));
 1082                     lastX = xc;
 1083                     lastY = yc;
 1084                 }
 1085                 i=i+4;
 1086             }
 1087         }
 1088        return 0;
 1089     case SS_CFF_COMMAND_flex: // flex as rrcurveto
 1090         {
 1091             unsigned int i=0;
 1092             for (i=0; i+5<stack.size(); i=i+6) {
 1093                 double xa = lastX + stack[i];
 1094                 double ya = lastY + stack[i+1];
 1095 
 1096                 double xb = xa + stack[i+2];
 1097                 double yb = ya + stack[i+3];
 1098 
 1099                 double xc = xb + stack[i+4];
 1100                 double yc = yb + stack[i+5];
 1101                 canvas->curveto (
 1102                     matrix.toX (xa, ya), matrix.toY (xa, ya),
 1103                     matrix.toX (xb, yb), matrix.toY (xb, yb),
 1104                     matrix.toX (xc, yc), matrix.toY (xc, yc));
 1105                 lastX = xc;
 1106                 lastY=  yc;
 1107             }
 1108         }
 1109        return 0;
 1110     case SS_CFF_COMMAND_hflex: // hflex as rrcurveto
 1111         {
 1112             if (stack.size() < 7) return -1;
 1113             double xa = lastX + stack[0];
 1114             double ya = lastY;
 1115 
 1116             double xb = xa + stack[1];
 1117             double yb = ya + stack[2];
 1118 
 1119             double xc = xb + stack[3];
 1120             double yc = yb;
 1121             canvas->curveto (
 1122                     matrix.toX (xa, ya), matrix.toY (xa, ya),
 1123                     matrix.toX (xb, yb), matrix.toY (xb, yb),
 1124                     matrix.toX (xc, yc), matrix.toY (xc, yc));
 1125             lastX = xc;
 1126             lastY=  yc;
 1127 
 1128             xa = lastX + stack[4];
 1129             ya = lastY;
 1130 
 1131             xb = xa + stack[5];
 1132             yb = ya;
 1133 
 1134             xc = xb + stack[6];
 1135             yc = yb;
 1136             canvas->curveto (
 1137                     matrix.toX (xa, ya), matrix.toY (xa, ya),
 1138                     matrix.toX (xb, yb), matrix.toY (xb, yb),
 1139                     matrix.toX (xc, yc), matrix.toY (xc, yc));
 1140             lastX = xc;
 1141             lastY=  yc;
 1142         }
 1143        return 0;
 1144     case SS_CFF_COMMAND_hflex1: // hflex as rrcurveto
 1145         {
 1146             if (stack.size() < 9) return -1;
 1147             double xa = lastX + stack[0];
 1148             double ya = lastY + stack[1];
 1149 
 1150             double xb = xa + stack[2];
 1151             double yb = ya + stack[3];
 1152 
 1153             double xc = xb + stack[4];
 1154             double yc = yb;
 1155             canvas->curveto (
 1156                     matrix.toX (xa, ya), matrix.toY (xa, ya),
 1157                     matrix.toX (xb, yb), matrix.toY (xb, yb),
 1158                     matrix.toX (xc, yc), matrix.toY (xc, yc));
 1159             lastX = xc;
 1160             lastY=  yc;
 1161 
 1162             xa = lastX + stack[5];
 1163             ya = lastY;
 1164 
 1165             xb = xa + stack[6];
 1166             yb = ya + stack[7];
 1167 
 1168             xc = xb + stack[8];
 1169             yc = yb;
 1170             canvas->curveto (
 1171                     matrix.toX (xa, ya), matrix.toY (xa, ya),
 1172                     matrix.toX (xb, yb), matrix.toY (xb, yb),
 1173                     matrix.toX (xc, yc), matrix.toY (xc, yc));
 1174             lastX = xc;
 1175             lastY=  yc;
 1176         }
 1177        return 0;
 1178     case SS_CFF_COMMAND_flex1: // flex1 as rrcurveto
 1179         {
 1180             if (stack.size() < 11) return -1;
 1181             double xa = lastX + stack[0];
 1182             double ya = lastY + stack[1];
 1183             double xs = stack[0];
 1184             double ys = stack[1];
 1185 
 1186             double xb = xa + stack[2];
 1187             xs += stack[2];
 1188             double yb = ya + stack[3];
 1189             ys += stack[3];
 1190 
 1191             double xc = xb + stack[4];
 1192             xs += stack[4];
 1193             double yc = yb + stack[5];
 1194             ys += stack[5];
 1195             canvas->curveto (
 1196                 matrix.toX (xa, ya), matrix.toY (xa, ya),
 1197                 matrix.toX (xb, yb), matrix.toY (xb, yb),
 1198                 matrix.toX (xc, yc), matrix.toY (xc, yc));
 1199             lastX = xc;
 1200             lastY=  yc;
 1201 
 1202             xa = lastX + stack[6];
 1203             xs += stack[6];
 1204             ya = lastY + stack[7];
 1205             ys += stack[7];
 1206 
 1207             xb = xa + stack[8];
 1208             xs += stack[8];
 1209             yb = ya + stack[9];
 1210             ys += stack[9];
 1211 
 1212             if (xs < 0) xs = - xs;
 1213             if (ys < 0) ys = - ys;
 1214             if (xs > ys) {
 1215                 xc = xb + stack[10];
 1216                 yc = yb;
 1217             } else {
 1218                 xc = xb;
 1219                 yc = yb + stack[10];
 1220             }
 1221             canvas->curveto (
 1222                 matrix.toX (xa, ya), matrix.toY (xa, ya),
 1223                 matrix.toX (xb, yb), matrix.toY (xb, yb),
 1224                 matrix.toX (xc, yc), matrix.toY (xc, yc));
 1225             lastX = xc;
 1226             lastY=  yc;
 1227         }
 1228         return 0;
 1229     case SS_CFF_COMMAND_hstem:
 1230         // width does not affect us
 1231         if (stack.size() % 2 == 1) {
 1232             hasGlyphWidth = 1;
 1233             glyphWidth = stack[0];
 1234             stack.remove (0);
 1235         }
 1236         stemCount += stack.size()/2;
 1237         return 0;
 1238     case SS_CFF_COMMAND_vstem:
 1239         if (stack.size() % 2 == 1) {
 1240             hasGlyphWidth = 1;
 1241             glyphWidth = stack[0];
 1242             stack.remove (0);
 1243         }
 1244         // width does not affect us
 1245         stemCount += stack.size()/2;
 1246         return 0;
 1247     case SS_CFF_COMMAND_hstemhm:
 1248         if (stack.size() % 2 == 1) {
 1249             hasGlyphWidth = 1;
 1250             glyphWidth = stack[0];
 1251             stack.remove (0);
 1252         }
 1253         // width does not affect us
 1254         stemCount += stack.size()/2;
 1255         return 0;
 1256     case SS_CFF_COMMAND_vstemhm:
 1257         if (stack.size() % 2 == 1) {
 1258             hasGlyphWidth = 1;
 1259             glyphWidth = stack[0];
 1260             stack.remove (0);
 1261         }
 1262         // width does not affect us
 1263         stemCount += stack.size()/2;
 1264         return 0;
 1265     case SS_CFF_COMMAND_hintmask:
 1266         if (stack.size() % 2 == 1) {
 1267             hasGlyphWidth = 1;
 1268             glyphWidth = stack[0];
 1269             stack.remove (0);
 1270         }
 1271         //fprintf (stderr, "hintmask adding %d\n", stack.size());
 1272         // width does not affect us
 1273         stemCount += stack.size()/2;
 1274         hintStart = true;
 1275         return 0;
 1276         //stack.clear();
 1277         //stack.append (0); 
 1278         return 0;
 1279     case SS_CFF_COMMAND_cntrmask:
 1280         if (stack.size() % 2 == 1) {
 1281             hasGlyphWidth = 1;
 1282             glyphWidth = stack[0];
 1283             stack.remove (0);
 1284         }
 1285         // width does not affect us
 1286         stemCount += stack.size()/2;
 1287         hintStart = true;
 1288         return 0;
 1289         //stack.clear();
 1290         //stack.append (0); 
 1291         return 0;
 1292     //case SS_CFF_COMMAND_shortint:
 1293     case SS_CFF_COMMAND_and: 
 1294         if (stack.size() < 2) return -1;
 1295         vle = (stack[stack.size()-2] != 0 && stack[stack.size()-1] != 0)
 1296             ? 1 : 0;
 1297         stack.replace (stack.size()-2, vle);
 1298         stack.truncate (stack.size()-1);
 1299         return 2;
 1300     case SS_CFF_COMMAND_or: 
 1301         if (stack.size() < 2) return -1;
 1302         vle = (stack[stack.size()-2] != 0 || stack[stack.size()-1] != 0)
 1303             ? 1 : 0;
 1304         stack.replace (stack.size()-2, vle);
 1305         stack.truncate (stack.size()-1);
 1306         return 2;
 1307     case SS_CFF_COMMAND_not: 
 1308         if (stack.size() < 1) return -1;
 1309         vle = (stack[stack.size()-1] == 0) ? 1 : 0;
 1310         stack.replace (stack.size()-1, vle);
 1311         return 2;
 1312     case SS_CFF_COMMAND_abs: 
 1313         if (stack.size() < 1) return -1;
 1314         vle = (stack[stack.size()-1] < 0) 
 1315             ? -stack[stack.size()-1] : stack[stack.size()-1];
 1316         stack.replace (stack.size()-1, vle);
 1317         return 2;
 1318     case SS_CFF_COMMAND_add: 
 1319         if (stack.size() < 2) return -1;
 1320         vle = stack[stack.size()-2] + stack[stack.size()-1];
 1321         stack.replace (stack.size()-2, vle);
 1322         stack.truncate (stack.size()-1);
 1323         return 2;
 1324     case SS_CFF_COMMAND_sub: 
 1325         if (stack.size() < 2) return -1;
 1326         vle = stack[stack.size()-2] - stack[stack.size()-1];
 1327         stack.replace (stack.size()-2, vle);
 1328         stack.truncate (stack.size()-1);
 1329         return 2;
 1330     case SS_CFF_COMMAND_div: 
 1331         if (stack.size() < 2) return -1;
 1332         vle = stack[stack.size()-2] / stack[stack.size()-1];
 1333         stack.replace (stack.size()-2, vle);
 1334         stack.truncate (stack.size()-1);
 1335         return 2;
 1336     case SS_CFF_COMMAND_neg: 
 1337         if (stack.size() < 1) return -1;
 1338         vle = - stack[stack.size()-1];
 1339         stack.replace (stack.size()-1, vle);
 1340         return 2;
 1341     case SS_CFF_COMMAND_eq: 
 1342         if (stack.size() < 2) return -1;
 1343         vle = (stack[stack.size()-2]==stack[stack.size()-1]) 
 1344             ? 1 : 0;
 1345         stack.replace (stack.size()-2, vle);
 1346         stack.truncate (stack.size()-1);
 1347         return 2;
 1348     case SS_CFF_COMMAND_drop: 
 1349         if (stack.size() < 1) return -1;
 1350         stack.truncate (stack.size()-1);
 1351         return 2;
 1352     case SS_CFF_COMMAND_put: 
 1353         if (stack.size() < 2) return -1;
 1354         if (stack[stack.size()-1] < 0 || stack[stack.size()-1] >= 32) {
 1355             return -1;
 1356         }
 1357         transientArray[(int)stack[stack.size()-1]] = stack[stack.size()-2];
 1358         stack.truncate (stack.size()-2);
 1359         return 2;
 1360     case SS_CFF_COMMAND_get: 
 1361         if (stack.size() < 1) return -1;
 1362         if (stack[stack.size()-1] < 0 || stack[stack.size()-1] >= 32) {
 1363             return -1;
 1364         }
 1365         stack.truncate (stack.size()-1);
 1366         stack.append (transientArray[(int)stack[stack.size()-1]]);
 1367         return 2;
 1368     case SS_CFF_COMMAND_ifelse: 
 1369         if (stack.size() < 4) return -1;
 1370         if (stack[stack.size()-2]<=stack[stack.size()-1]) {
 1371             vle = stack[stack.size()-3];
 1372             stack.replace (stack.size()-4, vle);
 1373         }
 1374         stack.truncate (stack.size()-3);
 1375         return 2;
 1376     case SS_CFF_COMMAND_random: 
 1377         // FIMXE
 1378         stack.append (0.5);
 1379         return 2;
 1380     case SS_CFF_COMMAND_mul: 
 1381         if (stack.size() < 2) return -1;
 1382         vle = stack[stack.size()-2] * stack[stack.size()-1];
 1383         stack.replace (stack.size()-2, vle);
 1384         stack.truncate (stack.size()-1);
 1385         return 2;
 1386     case SS_CFF_COMMAND_sqrt: 
 1387         if (stack.size() < 1) return -1;
 1388         vle = sqrt(stack[stack.size()-1]);
 1389         stack.replace (stack.size()-1, vle);
 1390         return 2;
 1391     case SS_CFF_COMMAND_dup: 
 1392         if (stack.size() < 1) return -1;
 1393         stack.append (stack[stack.size()-1]);
 1394         return 2;
 1395     case SS_CFF_COMMAND_exch: 
 1396     {
 1397         if (stack.size() < 2) return -1;
 1398         double tmp = stack[stack.size()-1];
 1399         stack.replace (stack.size()-1, stack[stack.size()-2]);
 1400         stack.replace (stack.size()-2, tmp);
 1401             
 1402     }
 1403         return 2;
 1404     case SS_CFF_COMMAND_index: 
 1405     {
 1406         if (stack.size() < 2) return -1;
 1407         double i = stack[stack.size()-1];
 1408         if (i < 0) {
 1409             stack.replace (stack.size()-1, stack[stack.size()-2]);
 1410         } else {
 1411             stack.replace (stack.size()-1, stack[stack.size()-(int)i-2]);
 1412         }
 1413     }
 1414         return 2;
 1415     case SS_CFF_COMMAND_roll: 
 1416     {
 1417         if (stack.size() < 1) return -1;
 1418         double count = stack[stack.size()-1];
 1419         if (count < 0) {
 1420             // downward roll
 1421             if (count < 64) return -1;
 1422             for (int i=0; i<(int)count; i++) {
 1423                 double tmp = stack[0];
 1424                 for (unsigned int j=0; j<stack.size()-2; j++) {
 1425                     vle = stack[j+1];
 1426                     stack.replace (j, vle);
 1427                 }
 1428                 stack.replace (stack.size()-2, tmp);
 1429             }
 1430         } else {
 1431             // upward roll
 1432             if (count > 64) return -1;
 1433             for (int i=0; i<(int)count; i++) {
 1434                 double tmp = stack[stack.size()-2];
 1435                 for (unsigned int j=0; j<stack.size()-2; j++) {
 1436                     vle = stack[stack.size()-3-j];
 1437                     stack.replace (stack.size()-2-j, vle);
 1438                 }
 1439                 stack.replace (0, tmp);
 1440             }
 1441         }
 1442         stack.truncate (stack.size()-1);
 1443     }
 1444         return 2;
 1445     default:
 1446 #if DEBUG
 1447        fprintf (stderr, "execute %04x [%u] failed\n", (int)command, stack.size());
 1448 #endif
 1449         break;
 1450     }
 1451     //fprintf (stderr, "return error\n");
 1452     return -1;
 1453 }
 1454 
 1455 // initialize stakc before calling
 1456 bool
 1457 SFontCFF::parseCharStrings(SD_BYTE* strings, SD_ULONG len) {
 1458 
 1459     SD_BYTE*  dp = strings;
 1460     SD_ULONG i = 0;
 1461     SS_SINT_32 intValue = 0;
 1462     double doubleValue = 0.0;
 1463     if (++subrCount > subrLimit+1) {
 1464 #if DEBUG
 1465         fprintf (stderr, "Too many subroutines : %u > %u\n", 
 1466             subrCount, subrLimit+1);
 1467 #endif
 1468         return false;
 1469     }
 1470 #if DEBUG
 1471 fprintf (stderr, "parseCharStrings %lx args %u len:%u\n", 
 1472         (unsigned long) strings, stack.size(), len);
 1473 #endif
 1474 
 1475     // remove hint arguments that comes after the command.
 1476     while (i<len) {
 1477         if (hintStart) {
 1478             int bytes = (stemCount + 7) / 8;
 1479             if (bytes == 0) bytes = 1;
 1480             while (bytes > 0 && i<len) {
 1481                 dp++; i++; 
 1482                 bytes--;
 1483             }
 1484             hintStart = false;
 1485         }
 1486 #if DEBUG
 1487 fprintf (stderr, "dp[%u] = %u  %lx\n", i, *dp, (unsigned long) dp);
 1488 #endif
 1489          // size 1 integer
 1490         if (*dp >= 32 && *dp <= 246) {
 1491             intValue = ((SS_SINT_32)dp[0]) - 139;
 1492             dp++; i++;
 1493             doubleValue = (double) intValue;
 1494             stack.append (doubleValue);
 1495 //fprintf (stderr, "1. value: %g\n", doubleValue);
 1496         // size 2 integer
 1497         } else  if (*dp >= 247 && *dp <= 250) {
 1498             SS_SINT_32 b0 = *dp;
 1499             dp++; i++; 
 1500             SS_SINT_32 b1 = *dp;
 1501             dp++; i++; 
 1502             intValue = (b0 - 247) * 256  + b1 + 108;
 1503             doubleValue = (double) intValue;
 1504 //fprintf (stderr, "2. value: %g\n", doubleValue);
 1505             stack.append (doubleValue);
 1506         // size 2 integer
 1507         } else if (*dp >= 251 && *dp <= 254) {
 1508             SS_SINT_32 b0 = *dp;
 1509             dp++; i++; 
 1510             SS_SINT_32 b1 = *dp;
 1511             dp++; i++; 
 1512             intValue = -(b0 - 251) * 256  - b1 - 108;
 1513             doubleValue = (double) intValue;
 1514 //fprintf (stderr, "3. value: %g\n", doubleValue);
 1515             stack.append (doubleValue);
 1516         // size 3 integer
 1517         } else if (*dp == 28) {
 1518             dp++; i++;
 1519             SS_SINT_32 b1 = *dp;
 1520             dp++; i++;
 1521             SS_SINT_32 b2 = *dp;
 1522             dp++; i++;
 1523             SS_SINT_16 v = (b1<<8)|b2;  
 1524             intValue = v; 
 1525             doubleValue = (double) intValue;
 1526 //fprintf (stderr, "4. value: %g\n", doubleValue);
 1527             stack.append (doubleValue);
 1528         // size 5 integer 
 1529         } else if (*dp == 255) {
 1530             dp++; i++;
 1531             SS_SINT_32 b1 = *dp;
 1532             dp++; i++;
 1533             SS_SINT_32 b2 = *dp;
 1534             dp++; i++;
 1535             SS_SINT_32 b3 = *dp;
 1536             dp++; i++;
 1537             SS_SINT_32 b4 = *dp;
 1538             dp++; i++;
 1539             intValue = (b1<<24)|(b2<<16)|(b3<<8)|b4;
 1540             doubleValue = (double) intValue / (double) (1 << 16);
 1541 //fprintf (stderr, "5. value: %g\n", doubleValue);
 1542             // fixed
 1543             stack.append (doubleValue);
 1544         // Operator
 1545         } else if (*dp == SS_CFF_COMMAND_shortint) {
 1546             dp++; i++;
 1547             SS_SINT_16 b1 = *dp;
 1548             b1 = b1 << 8;
 1549             dp++; i++;
 1550             b1 = b1 | *dp;
 1551             dp++; i++;
 1552             intValue = b1; 
 1553             doubleValue = (double) intValue;
 1554             stack.append (doubleValue);
 1555 //fprintf (stderr, "6. value: %g\n", doubleValue);
 1556         } else if ((*dp >= 0 && *dp <= 27) 
 1557             || *dp == 29 || *dp == 30 || *dp == 31) {
 1558 
 1559             intValue = *dp;
 1560             dp++; i++;
 1561             // 2 byte operator
 1562             if (intValue == 0x0c ) {
 1563                 intValue = (*dp) | SD_DICT_OP_escape;
 1564                 dp++; i++;
 1565             }       
 1566             int res = execute (intValue);
 1567             if (res == 1) {
 1568                 break; // return
 1569                 //return true;
 1570             }
 1571             // callsubr callgbsubr does not clear stack
 1572             if (res != 2) { 
 1573                 stack.clear();
 1574             }
 1575             if (res == -1) {
 1576                 return false;
 1577             }
 1578         } else {
 1579 #if DEBUG
 1580             fprintf(stderr, "parseCharStrings error %u\n", (unsigned int) *dp);
 1581 #endif
 1582             dp++; i++;
 1583         }
 1584         if (stack.size() > stackLimit) {
 1585 #if DEBUG
 1586             fprintf (stderr, "Too many DICT operands.");
 1587 #endif
 1588             return false;
 1589         }
 1590         //fprintf (stderr, "i=%u\n", i);
 1591     }
 1592     if (subrCount > 0) subrCount--;
 1593 #if DEBUG
 1594     fprintf (stderr, "end args at %i of %u, stack=%u\n", 
 1595         i, len, stack.size());
 1596 #endif
 1597     return true;
 1598 }