Back to index

texmacs  1.0.7.15
cs_type2.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/cs_type2.c,v 1.10 2004/02/15 12:59:43 hirata Exp $
00002     
00003     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
00004 
00005     Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
00006     the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
00007     
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012     
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017     
00018     You should have received a copy of the GNU General Public License
00019     along with this program; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00021 */
00022 
00023 /*
00024  * Type 2 Charstring support:
00025  *  Decode and encode Type 2 charstring
00026  *
00027  * All local/global subroutine calls in a given charstring is replace by the
00028  * content of subroutine charstrings. We do this because some PostScript RIP
00029  * may have problems with sparse subroutine array. Workaround for this is to
00030  * re-order subroutine array so that no gap appears in the subroutine array,
00031  * or put dummy charstrings that contains only `return' in the gap. However,
00032  * re-ordering of subroutine is rather difficult for Type 2 charstrings due
00033  * to the bias which depends on the total number of subroutines. Replacing
00034  * callgsubr/callsubr calls with the content of the corresponding subroutine
00035  * charstring may be more efficient than putting dummy subroutines in the
00036  * case of subsetted font. Adobe distiller seems doing same thing.
00037  *
00038  * And also note that subroutine numbers within subroutines can depend on the
00039  * content of operand stack as follows:
00040  *
00041  *   ... l m callsubr << subr #(m+bias): n add callsubr >> ...
00042  *
00043  * I've not implemented the `random' operator which generates a pseudo-random
00044  * number in the range (0, 1] and push them into argument stack.
00045  * How pseudo-random sequences are generated is not documented in the Type 2
00046  * charstring spec..
00047  */
00048 
00049 #include <stdio.h>
00050 
00051 /* fabs, sqrt ... */
00052 #include <math.h>
00053 
00054 #include "error.h"
00055 
00056 /* data types, limits */
00057 #include "cff_types.h"
00058 #include "cff_limits.h"
00059 
00060 #include "cs_type2.h"
00061 
00062 #define CS_TYPE2_DEBUG_STR "Type2 Charstring Parser"
00063 #define CS_TYPE2_DEBUG     5
00064 
00065 /* decoder/encoder status codes */
00066 #define CS_BUFFER_ERROR -3
00067 #define CS_STACK_ERROR  -2
00068 #define CS_PARSE_ERROR  -1
00069 #define CS_PARSE_OK      0
00070 #define CS_PARSE_END     1
00071 #define CS_SUBR_RETURN   2
00072 #define CS_CHAR_END      3
00073 
00074 static int status = CS_PARSE_ERROR;
00075 
00076 #define DST_NEED(a,b) {if ((a) < (b)) { status = CS_BUFFER_ERROR ; return ; }}
00077 #define SRC_NEED(a,b) {if ((a) < (b)) { status = CS_PARSE_ERROR  ; return ; }}
00078 #define NEED(a,b)     {if ((a) < (b)) { status = CS_STACK_ERROR  ; return ; }}
00079 
00080 /* hintmask and cntrmask need number of stem zones */
00081 static int num_stems = 0;
00082 static int phase     = 0;
00083 
00084 /* subroutine nesting */
00085 static int nest      = 0;
00086 
00087 /* advance width */
00088 static int    have_width = 0;
00089 static double width      = 0.0;
00090 
00091 /*
00092  * Standard Encoding Accented Characters:
00093  *  Optional four arguments for endchar. See, CFF spec., p.35.
00094  *  This is obsolete feature and is no longer supported.
00095  */
00096 #if 0
00097 /* adx ady bchar achar endchar */
00098 static double seac[4] = {0.0, 0.0, 0.0, 0.0};
00099 #endif
00100 
00101 /* Operand stack and Transient array */
00102 static int    stack_top = 0;
00103 static double arg_stack[CS_ARG_STACK_MAX];
00104 static double trn_array[CS_TRANS_ARRAY_MAX];
00105 
00106 /*
00107  * Type 2 CharString encoding
00108  */
00109 
00110 /*
00111  * 1-byte CharString operaotrs:
00112  *  cs_escape is first byte of two-byte operator
00113  */
00114 
00115 /*      RESERVED      0 */
00116 #define cs_hstem      1
00117 /*      RESERVED      2 */
00118 #define cs_vstem      3
00119 #define cs_vmoveto    4
00120 #define cs_rlineto    5
00121 #define cs_hlineto    6
00122 #define cs_vlineto    7
00123 #define cs_rrcurveto  8
00124 /*      cs_closepath  9  : TYPE1 */
00125 #define cs_callsubr   10
00126 #define cs_return     11
00127 #define cs_escape     12
00128 /*      cs_hsbw       13 : TYPE1 */
00129 #define cs_endchar    14
00130 /*      RESERVED      15 */
00131 /*      RESERVED      16 */
00132 /*      RESERVED      17 */
00133 #define cs_hstemhm    18
00134 #define cs_hintmask   19
00135 #define cs_cntrmask   20
00136 #define cs_rmoveto    21
00137 #define cs_hmoveto    22
00138 #define cs_vstemhm    23
00139 #define cs_rcurveline 24
00140 #define cs_rlinecurve 25
00141 #define cs_vvcurveto  26
00142 #define cs_hhcurveto  27
00143 /*      SHORTINT      28 : first byte of shortint*/
00144 #define cs_callgsubr  29
00145 #define cs_vhcurveto  30
00146 #define cs_hvcurveto  31
00147 
00148 /*
00149  * 2-byte CharString operaotrs:
00150  *  "dotsection" is obsoleted in Type 2 charstring.
00151  */
00152 
00153 #define cs_dotsection 0
00154 /*      cs_vstem3     1 : TYPE1 */
00155 /*      cs_hstem3     2 : TYPE1 */
00156 #define cs_and        3
00157 #define cs_or         4
00158 #define cs_not        5
00159 /*      cs_seac       6 : TYPE1 */
00160 /*      cs_sbw        7 : TYPE1 */
00161 /*      RESERVED      8  */
00162 #define cs_abs        9
00163 #define cs_add        10
00164 #define cs_sub        11
00165 #define cs_div        12
00166 /*      RESERVED      13 */
00167 #define cs_neg        14
00168 #define cs_eq         15
00169 /*      cs_callothersubr 16 : TYPE1 */
00170 /*      cs_pop           17 : TYPE1 */
00171 #define cs_drop       18
00172 /*      RESERVED      19 */
00173 #define cs_put        20
00174 #define cs_get        21
00175 #define cs_ifelse     22 
00176 #define cs_random     23
00177 #define cs_mul        24
00178 /*      RESERVED      25 */
00179 #define cs_sqrt       26
00180 #define cs_dup        27
00181 #define cs_exch       28
00182 #define cs_index      29
00183 #define cs_roll       30
00184 /*      cs_setcurrentpoint 31 : TYPE1 */
00185 /*      RESERVED      32 */
00186 /*      RESERVED      33 */
00187 #define cs_hflex      34
00188 #define cs_flex       35
00189 #define cs_hflex1     36
00190 #define cs_flex1      37
00191 
00192 /*
00193  * clear_stack() put all operands sotred in operand stack to dest.
00194  */
00195 static void
00196 clear_stack (card8 **dest, card8 *limit)
00197 {
00198   int i;
00199 
00200   for (i = 0; i < stack_top; i++) {
00201     double value;
00202     long   ivalue;
00203     value  = arg_stack[i];
00204     /* Nearest integer value */
00205     ivalue = (long) floor(value+0.5);
00206     if (value >= 0x8000L || value <= (-0x8000L - 1)) {
00207       /*
00208        * This number cannot be represented as a single operand.
00209        * We must use `a b mul ...' or `a c div' to represent large values.
00210        */
00211       ERROR("%s: Argument value too large. (This is bug)", CS_TYPE2_DEBUG_STR);
00212     } else if (fabs(value - ivalue) > 3.0e-5) {
00213       /* 16.16-bit signed fixed value  */
00214       DST_NEED(limit, *dest + 5);
00215       *(*dest)++ = 255;
00216       ivalue = (long) floor(value); /* mantissa */
00217       *(*dest)++ = (ivalue >> 8) & 0xff;
00218       *(*dest)++ = ivalue & 0xff;
00219       ivalue = (long)((value - ivalue) * 0x10000l); /* fraction */
00220       *(*dest)++ = (ivalue >> 8) & 0xff;
00221       *(*dest)++ = ivalue & 0xff;
00222       /* Everything else are integers. */
00223     } else if (ivalue >= -107 && ivalue <= 107) {
00224       DST_NEED(limit, *dest + 1);
00225       *(*dest)++ = ivalue + 139;
00226     } else if (ivalue >= 108 && ivalue <= 1131) {
00227       DST_NEED(limit, *dest + 2);
00228       ivalue = 0xf700u + ivalue - 108;
00229       *(*dest)++ = (ivalue >> 8) & 0xff;
00230       *(*dest)++ = ivalue & 0xff;
00231     } else if (ivalue >= -1131 && ivalue <= -108) {
00232       DST_NEED(limit, *dest + 2);
00233       ivalue = 0xfb00u - ivalue - 108;
00234       *(*dest)++ = (ivalue >> 8) & 0xff;
00235       *(*dest)++ = ivalue & 0xff;
00236     } else if (ivalue >= -32768 && ivalue <= 32767) { /* shortint */
00237       DST_NEED(limit, *dest + 3);
00238       *(*dest)++ = 28;
00239       *(*dest)++ = (ivalue >> 8) & 0xff;
00240       *(*dest)++ = (ivalue) & 0xff;
00241     } else { /* Shouldn't come here */
00242       ERROR("%s: Unexpected error.", CS_TYPE2_DEBUG_STR);
00243     }
00244   }
00245 
00246   stack_top = 0; /* clear stack */
00247 
00248   return;
00249 }
00250 
00251 /*
00252  * Single byte operators:
00253  *  Path construction, Operator for finishing a path, Hint operators.
00254  *
00255  * phase:
00256  *  0: inital state
00257  *  1: hint declaration, first stack-clearing operator appeared
00258  *  2: in path construction
00259  */
00260 
00261 static void
00262 do_operator1 (card8 **dest, card8 *limit, card8 **data, card8 *endptr)
00263 {
00264   card8 op = **data;
00265 
00266   *data += 1;
00267 
00268   switch (op) {
00269   case cs_hstemhm:
00270   case cs_vstemhm:
00271   /* charstring may have hintmask if above operator have seen */
00272   case cs_hstem:
00273   case cs_vstem:
00274     if (phase == 0 && (stack_top % 2)) {
00275       have_width = 1;
00276       width = arg_stack[0];
00277     }
00278     num_stems += stack_top/2;
00279     clear_stack(dest, limit);
00280     DST_NEED(limit, *dest + 1);
00281     *(*dest)++ = op;
00282     phase = 1;
00283     break;
00284   case cs_hintmask:
00285   case cs_cntrmask:
00286     if (phase < 2) {
00287       if (phase == 0 && (stack_top % 2)) {
00288        have_width = 1;
00289        width = arg_stack[0];
00290       }
00291       num_stems += stack_top/2;
00292     }
00293     clear_stack(dest, limit);
00294     DST_NEED(limit, *dest + 1);
00295     *(*dest)++ = op;
00296     if (num_stems > 0) {
00297       int masklen = (num_stems + 7) / 8;
00298       DST_NEED(limit, *dest + masklen);
00299       SRC_NEED(endptr, *data + masklen);
00300       memmove(*dest, *data, masklen);
00301       *data += masklen;
00302       *dest += masklen;
00303     }
00304     phase = 2;
00305     break;
00306   case cs_rmoveto:
00307     if (phase == 0 && (stack_top % 2)) {
00308       have_width = 1;
00309       width = arg_stack[0];
00310     }
00311     clear_stack(dest, limit);
00312     DST_NEED(limit, *dest + 1);
00313     *(*dest)++ = op;
00314     phase = 2;
00315     break;
00316   case cs_hmoveto:
00317   case cs_vmoveto:
00318     if (phase == 0 && (stack_top % 2) == 0) {
00319       have_width = 1;
00320       width = arg_stack[0];
00321     }
00322     clear_stack(dest, limit);
00323     DST_NEED(limit, *dest + 1);
00324     *(*dest)++ = op;
00325     phase = 2;
00326     break;
00327   case cs_endchar:
00328     if (stack_top == 1) {
00329       have_width = 1;
00330       width = arg_stack[0];
00331       clear_stack(dest, limit);
00332     } else if (stack_top == 4 || stack_top == 5) {
00333       WARN("\"seac\" character deprecated in Type 2 charstring.");
00334       status = CS_PARSE_ERROR;
00335       return;
00336     } else if (stack_top > 0) {
00337       WARN("%s: Operand stack not empty.", CS_TYPE2_DEBUG_STR);
00338     }
00339     DST_NEED(limit, *dest + 1);
00340     *(*dest)++ = op;
00341     status = CS_CHAR_END;
00342     break;
00343   /* above oprators are candidate for first stack-clearing operator */
00344   case cs_rlineto:
00345   case cs_hlineto:
00346   case cs_vlineto:
00347   case cs_rrcurveto:
00348   case cs_rcurveline:
00349   case cs_rlinecurve:
00350   case cs_vvcurveto:
00351   case cs_hhcurveto:
00352   case cs_vhcurveto:
00353   case cs_hvcurveto:
00354     if (phase < 2) {
00355       WARN("%s: Broken Type 2 charstring.", CS_TYPE2_DEBUG_STR);
00356       status = CS_PARSE_ERROR;
00357       return;
00358     }
00359     clear_stack(dest, limit);
00360     DST_NEED(limit, *dest + 1);
00361     *(*dest)++ = op;
00362     break;
00363   /* all operotors above are stack-clearing operator */
00364   /* no output */
00365   case cs_return:
00366   case cs_callgsubr:
00367   case cs_callsubr:
00368     ERROR("%s: Unexpected call(g)subr/return", CS_TYPE2_DEBUG_STR);
00369     break;
00370   default:
00371     /* no-op ? */
00372     WARN("%s: Unknown charstring operator: 0x%02x", CS_TYPE2_DEBUG_STR, op);
00373     status = CS_PARSE_ERROR;
00374     break;
00375   }
00376 
00377   return;
00378 }
00379 
00380 /*
00381  * Double byte operators:
00382  *  Flex, arithmetic, conditional, and storage operators.
00383  *
00384  * Following operators are not supported:
00385  *  random: How random ?
00386  */
00387 static void
00388 do_operator2 (card8 **dest, card8 *limit, card8 **data, card8 *endptr)
00389 {
00390   card8 op;
00391 
00392   *data += 1;
00393 
00394   SRC_NEED(endptr, *data + 1);
00395 
00396   op = **data;
00397   *data += 1;
00398 
00399   switch(op) {
00400   case cs_dotsection: /* deprecated */
00401     WARN("Operator \"dotsection\" deprecated in Type 2 charstring.");
00402     status = CS_PARSE_ERROR;
00403     return;
00404     break;
00405   case cs_hflex:
00406   case cs_flex:
00407   case cs_hflex1:
00408   case cs_flex1:
00409     if (phase < 2) {
00410       WARN("%s: Broken Type 2 charstring.", CS_TYPE2_DEBUG_STR);
00411       status = CS_PARSE_ERROR;
00412       return;
00413     }
00414     clear_stack(dest, limit);
00415     DST_NEED(limit, *dest + 2);
00416     *(*dest)++ = cs_escape;
00417     *(*dest)++ = op;
00418     break;
00419   /* all operator above are stack-clearing */
00420   /* no output */
00421   case cs_and:
00422     NEED(stack_top, 2);
00423     stack_top--;
00424     if (arg_stack[stack_top] && arg_stack[stack_top-1]) {
00425       arg_stack[stack_top-1] = 1.0;
00426     } else {
00427       arg_stack[stack_top-1] = 0.0;
00428     }
00429     break;
00430   case cs_or:
00431     NEED(stack_top, 2);
00432     stack_top--;
00433     if (arg_stack[stack_top] || arg_stack[stack_top-1]) {
00434       arg_stack[stack_top-1] = 1.0;
00435     } else {
00436       arg_stack[stack_top-1] = 0.0;
00437     }
00438     break;
00439   case cs_not:
00440     NEED(stack_top, 1);
00441     if (arg_stack[stack_top-1]) {
00442       arg_stack[stack_top-1] = 0.0;
00443     } else {
00444       arg_stack[stack_top-1] = 1.0;
00445     }
00446     break;
00447   case cs_abs:
00448     NEED(stack_top, 1);
00449     arg_stack[stack_top-1] = fabs(arg_stack[stack_top-1]);
00450     break;
00451   case cs_add:
00452     NEED(stack_top, 2);
00453     arg_stack[stack_top-2] += arg_stack[stack_top-1];
00454     stack_top--;
00455     break;
00456   case cs_sub:
00457     NEED(stack_top, 2);
00458     arg_stack[stack_top-2] -= arg_stack[stack_top-1];
00459     stack_top--;
00460     break;
00461   case cs_div: /* doesn't check overflow */
00462     NEED(stack_top, 2);
00463     arg_stack[stack_top-2] /= arg_stack[stack_top-1];
00464     stack_top--;
00465     break;
00466   case cs_neg:
00467     NEED(stack_top, 1);
00468     arg_stack[stack_top-1] *= -1.0;
00469     break;
00470   case cs_eq:
00471     NEED(stack_top, 2);
00472     stack_top--;
00473     if (arg_stack[stack_top] == arg_stack[stack_top-1]) {
00474       arg_stack[stack_top-1] = 1.0;
00475     } else {
00476       arg_stack[stack_top-1] = 0.0;
00477     }
00478     break;
00479   case cs_drop:
00480     NEED(stack_top, 1);
00481     stack_top--;
00482     break;
00483   case cs_put:
00484     NEED(stack_top, 2);
00485     {
00486       int idx = (int)arg_stack[--stack_top];
00487       NEED(CS_TRANS_ARRAY_MAX, idx);
00488       trn_array[idx] = arg_stack[--stack_top];
00489     }
00490     break;
00491   case cs_get:
00492     NEED(stack_top, 1);
00493     {
00494       int idx = (int)arg_stack[stack_top-1];
00495       NEED(CS_TRANS_ARRAY_MAX, idx);
00496       arg_stack[stack_top-1] = trn_array[idx];
00497     }
00498     break;
00499   case cs_ifelse:
00500     NEED(stack_top, 4);
00501     stack_top -= 3;
00502     if (arg_stack[stack_top+1] > arg_stack[stack_top+2]) {
00503       arg_stack[stack_top-1] = arg_stack[stack_top];
00504     }
00505     break;
00506   case cs_mul:
00507     NEED(stack_top, 2);
00508     arg_stack[stack_top-2] = arg_stack[stack_top-2] * arg_stack[stack_top-1];
00509     stack_top--;
00510     break;
00511   case cs_sqrt:
00512     NEED(stack_top, 1);
00513     arg_stack[stack_top-1] = sqrt(arg_stack[stack_top-1]);
00514     break;
00515   case cs_dup:
00516     NEED(stack_top, 1);
00517     NEED(CS_ARG_STACK_MAX, stack_top+1);
00518     arg_stack[stack_top] = arg_stack[stack_top-1];
00519     stack_top++;
00520     break;
00521   case cs_exch:
00522     NEED(stack_top, 2);
00523     {
00524       double save = arg_stack[stack_top-2];
00525       arg_stack[stack_top-2] = arg_stack[stack_top-1];
00526       arg_stack[stack_top-1] = save;
00527     }
00528     break;
00529   case cs_index:
00530     NEED(stack_top, 2); /* need two arguments at least */
00531     {
00532       int idx = (int)arg_stack[stack_top-1];
00533       if (idx < 0) {
00534        arg_stack[stack_top-1] = arg_stack[stack_top-2];
00535       } else {
00536        NEED(stack_top, idx+2);
00537        arg_stack[stack_top-1] = arg_stack[stack_top-idx-2];
00538       }
00539     }
00540     break;
00541   case cs_roll:
00542     NEED(stack_top, 2);
00543     {
00544       int N, J;
00545       J = (int)arg_stack[--stack_top];
00546       N = (int)arg_stack[--stack_top];
00547       NEED(stack_top, N);
00548       if (J > 0) {
00549        J = J % N;
00550        while (J-- > 0) {
00551          double save = arg_stack[stack_top-1];
00552          int i = stack_top - 1;
00553          while (i > stack_top-N) {
00554            arg_stack[i] = arg_stack[i-1];
00555            i--;
00556          }
00557          arg_stack[i] = save;
00558        }
00559       } else {
00560        J = (-J) % N;
00561        while (J-- > 0) {
00562          double save = arg_stack[stack_top-N];
00563          int i = stack_top - N;
00564          while (i < stack_top-1) {
00565            arg_stack[i] = arg_stack[i+1];
00566            i++;
00567          }
00568          arg_stack[i] = save;
00569        }
00570       }
00571     }
00572     break;
00573   case cs_random:
00574     WARN("%s: Charstring operator \"random\" found.", CS_TYPE2_DEBUG_STR);
00575     NEED(CS_ARG_STACK_MAX, stack_top+1);
00576     arg_stack[stack_top++] = 1.0;
00577     break;
00578   default:
00579     /* no-op ? */
00580     WARN("%s: Unknown charstring operator: 0x0c%02x", CS_TYPE2_DEBUG_STR, op);
00581     status = CS_PARSE_ERROR;
00582     break;
00583   }
00584 
00585   return;
00586 }
00587 
00588 /*
00589  * integer:
00590  *  exactly the same as the DICT encoding (except 29)
00591  */
00592 static void
00593 get_integer (card8 **data, card8 *endptr)
00594 {
00595   long result = 0;
00596   card8 b0 = **data, b1, b2;
00597 
00598   *data += 1;
00599 
00600   if (b0 == 28) { /* shortint */
00601     SRC_NEED(endptr, *data + 2);
00602     b1 = **data;
00603     b2 = *(*data+1);
00604     result = b1*256+b2;
00605     if (result > 0x7fff)
00606       result -= 0x10000L;
00607     *data += 2;
00608   } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
00609     result = b0 - 139;
00610   } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
00611     SRC_NEED(endptr, *data + 1);
00612     b1 = **data;
00613     result = (b0-247)*256+b1+108;
00614     *data += 1;
00615   } else if (b0 >= 251 && b0 <= 254) {
00616     SRC_NEED(endptr, *data + 1);
00617     b1 = **data;
00618     result = -(b0-251)*256-b1-108;
00619     *data += 1;
00620   } else {
00621     status = CS_PARSE_ERROR;
00622     return;
00623   }
00624 
00625   NEED(CS_ARG_STACK_MAX, stack_top+1);
00626   arg_stack[stack_top++] = (double) result;
00627 
00628   return;
00629 }
00630 
00631 /*
00632  * Signed 16.16-bits fixed number for Type 2 charstring encoding
00633  */
00634 static void
00635 get_fixed (card8 **data, card8 *endptr)
00636 {
00637   long ivalue;
00638   double rvalue;
00639 
00640   *data += 1;
00641 
00642   SRC_NEED(endptr, *data + 4);
00643 
00644   ivalue = *(*data) * 0x100 + *(*data+1);
00645   rvalue = (ivalue > 0x7fffL) ? (ivalue - 0x10000L) : ivalue;
00646   ivalue = *(*data+2) * 0x100 + *(*data+3);
00647   rvalue += ((double) ivalue) / 0x10000L;
00648 
00649   NEED(CS_ARG_STACK_MAX, stack_top+1);
00650   arg_stack[stack_top++] = rvalue;
00651   *data += 4;
00652 
00653   return;
00654 }
00655 
00656 /*
00657  * Subroutines:
00658  *  The bias for subroutine number is introduced in type 2 charstrings.
00659  *
00660  * subr:     set to a pointer to the subroutine charstring.
00661  * len:      set to the length of subroutine charstring.
00662  * subr_idx: CFF INDEX data that contains subroutines.
00663  * id:       biased subroutine number.
00664  */
00665 static void
00666 get_subr (card8 **subr, long *len, cff_index *subr_idx, long id)
00667 {
00668   card16 count;
00669 
00670   if (subr_idx == NULL)
00671     ERROR("%s: Subroutine called but no subroutine found.", CS_TYPE2_DEBUG_STR);
00672 
00673   count = subr_idx->count;
00674 
00675   /* Adding bias number */
00676   if (count < 1240) {
00677     id += 107;
00678   } else if (count < 33900) {
00679     id += 1131;
00680   } else {
00681     id += 32768;
00682   }
00683 
00684   if (id > count)
00685     ERROR("%s: Invalid Subr index: %ld (max=%u)", CS_TYPE2_DEBUG_STR, id, count);
00686 
00687   *len = (subr_idx->offset)[id + 1] - (subr_idx->offset)[id];
00688   *subr = subr_idx->data + (subr_idx->offset)[id] - 1;
00689 
00690   return;
00691 }
00692 
00693 /*
00694  * NOTE:
00695  *  The Type 2 interpretation of a number encoded in five-bytes (those with
00696  *  an initial byte value of 255) differs from how it is interpreted in the
00697  *  Type 1 format.
00698  */
00699 
00700 static void
00701 do_charstring (card8 **dest, card8 *limit,
00702               card8 **data, card8 *endptr,
00703               cff_index *gsubr_idx, cff_index *subr_idx)
00704 {
00705   card8 b0 = 0, *subr;
00706   long  len;
00707 
00708   if (nest > CS_SUBR_NEST_MAX)
00709     ERROR("%s: Subroutine nested too deeply.", CS_TYPE2_DEBUG_STR);
00710 
00711   nest++;
00712 
00713   while (*data < endptr && status == CS_PARSE_OK) {
00714     b0 = **data;
00715     if (b0 == 255) { /* 16-bit.16-bit fixed signed number */
00716       get_fixed(data, endptr);
00717     } else if (b0 == cs_return) {
00718       status = CS_SUBR_RETURN;
00719     } else if (b0 == cs_callgsubr) {
00720       if (stack_top < 1) {
00721        status = CS_STACK_ERROR;
00722       } else {
00723        stack_top--;
00724        get_subr(&subr, &len, gsubr_idx, (long) arg_stack[stack_top]);
00725        if (*dest + len > limit)
00726          ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR);
00727        do_charstring(dest, limit, &subr, subr + len,
00728                     gsubr_idx, subr_idx);
00729        *data += 1;
00730       }
00731     } else if (b0 == cs_callsubr) {
00732       if (stack_top < 1) {
00733        status = CS_STACK_ERROR;
00734       } else {
00735        stack_top--;
00736        get_subr(&subr, &len, subr_idx, (long) arg_stack[stack_top]);
00737        if (limit < *dest + len)
00738          ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR);
00739        do_charstring(dest, limit, &subr, subr + len,
00740                     gsubr_idx, subr_idx);
00741        *data += 1;
00742       }
00743     } else if (b0 == cs_escape) {
00744       do_operator2(dest, limit, data, endptr);
00745     } else if (b0 < 32 && b0 != 28) { /* 19, 20 need mask */
00746       do_operator1(dest, limit, data, endptr);
00747     } else if ((b0 <= 22 && b0 >= 27) || b0 == 31) { /* reserved */
00748       status = CS_PARSE_ERROR; /* not an error ? */
00749     } else { /* integer */
00750       get_integer(data, endptr);
00751     }
00752   }
00753 
00754   if (status == CS_SUBR_RETURN) {
00755     status = CS_PARSE_OK;
00756   } else if (status == CS_CHAR_END && *data < endptr) {
00757     WARN("%s: Garbage after endchar.", CS_TYPE2_DEBUG_STR);
00758   } else if (status < CS_PARSE_OK) { /* error */
00759     ERROR("%s: Parsing charstring failed: (status=%d, stack=%d)",
00760          CS_TYPE2_DEBUG_STR, status, stack_top);
00761   }
00762 
00763   nest--;
00764 
00765   return;
00766 }
00767 
00768 static void
00769 cs_parse_init (void)
00770 {
00771   status = CS_PARSE_OK;
00772   nest   = 0;
00773   phase  = 0;
00774   num_stems = 0;
00775   stack_top = 0;
00776 }
00777 
00778 /*
00779  * Not just copying...
00780  */
00781 long
00782 cs_copy_charstring (card8 *dst, long dstlen,
00783                   card8 *src, long srclen,
00784                   cff_index *gsubr, cff_index *subr,
00785                   double default_width, double nominal_width, cs_ginfo *ginfo)
00786 {
00787   card8 *save = dst;
00788 
00789   cs_parse_init();
00790 
00791   width = 0.0;
00792   have_width = 0;
00793 
00794   /* expand call(g)subrs */
00795   do_charstring(&dst, dst + dstlen, &src, src + srclen, gsubr, subr);
00796 
00797   if (ginfo) {
00798     ginfo->flags = 0; /* not used */
00799     if (have_width) {
00800       ginfo->wx = nominal_width + width;
00801     } else {
00802       ginfo->wx = default_width;
00803     }
00804   }
00805 
00806   return (long)(dst - save);
00807 }