Back to index

texmacs  1.0.7.15
t1_load.c
Go to the documentation of this file.
00001 /*  $Header: /home/cvsroot/dvipdfmx/src/t1_load.c,v 1.13 2009/04/08 03:10:58 chofchof 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     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU General Public License for more details.
00019 
00020     You should have received a copy of the GNU General Public License
00021     along with this program; if not, write to the Free Software
00022     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00023 */
00024 
00025 #if HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #include <string.h>
00030 #include <math.h>
00031 
00032 #include "system.h"
00033 #include "mfileio.h"
00034 #include "mem.h"
00035 #include "error.h"
00036 #include "numbers.h"
00037 
00038 #include "pdfobj.h"
00039 #include "pdffont.h"
00040 
00041 #include "pdfencoding.h"
00042 #include "unicode.h"
00043 
00044 #include "dpxutil.h"
00045 
00046 #include "pst_obj.h"
00047 #include "pst.h"
00048 
00049 #include "cff_limits.h"
00050 #include "cff_types.h"
00051 #include "cff_dict.h"
00052 #include "cff.h"
00053 
00054 #include "t1_load.h"
00055 
00056 /* Migrated from t1crypt */
00057 #define T1_EEKEY   55665u
00058 #define T1_CHARKEY 4330u
00059 
00060 #if  0
00061 /* We no longer need encryption. */
00062 static unsigned short r = T1_EEKEY, c1 = 52845, c2 = 22719;
00063 
00064 static unsigned char t1_encrypt (unsigned char plain)
00065 {
00066   unsigned char cipher;
00067   cipher = (plain ^ (r >> 8));
00068   r = (cipher + r) * c1 + c2;
00069   return cipher;
00070 }
00071 
00072 static void t1_crypt_init (unsigned short key)
00073 {
00074   r = key;
00075 }
00076 #endif /* 0 */
00077 
00078 static void
00079 t1_decrypt (unsigned short key,
00080            unsigned char *dst, const unsigned char *src,
00081            long skip, long len)
00082 {
00083   len -= skip;
00084   while (skip--)
00085     key = (key + *src++) * 52845u + 22719u;
00086   while (len--) {
00087     unsigned char c = *src++;
00088     *dst++ = (c ^ (key >> 8));
00089     key = (key + c) * 52845u + 22719u;
00090   }
00091 }
00092 /* T1CRYPT */
00093 
00094 #define MATCH_NAME(t,n) ((t) && PST_NAMETYPE((t))    && !strncmp(pst_data_ptr((t)),(n),strlen((n))))
00095 #define MATCH_OP(t,n)   ((t) && PST_UNKNOWNTYPE((t)) && !strncmp(pst_data_ptr((t)),(n),strlen((n))))
00096 
00097 #define RELEASE_TOK(t) if ((t) != NULL) {\
00098   pst_release_obj((t));\
00099   (t) = NULL;\
00100 }
00101 
00102 static char *
00103 get_next_key (unsigned char **start, unsigned char *end)
00104 {
00105   char *key = NULL;
00106   pst_obj *tok;
00107 
00108   while (*start < end &&
00109         (tok = pst_get_token(start, end)) != NULL) {
00110     if (PST_NAMETYPE(tok)) {
00111       key = (char *) pst_getSV(tok);
00112       RELEASE_TOK(tok);
00113       break;
00114     }
00115     RELEASE_TOK(tok);
00116   }
00117 
00118   return key;
00119 }
00120 
00121 static int
00122 seek_operator (unsigned char **start, unsigned char *end, const char *op)
00123 {
00124   pst_obj *tok = NULL;
00125 
00126   while (*start < end &&
00127         (tok = pst_get_token(start, end)) != NULL) {
00128     if (MATCH_OP(tok, op)) {
00129       break;
00130     }
00131     RELEASE_TOK(tok);
00132   }
00133 
00134   if (tok == NULL)
00135     return -1;
00136   RELEASE_TOK(tok);
00137 
00138   return 0;
00139 }
00140 
00141 
00142 static int
00143 parse_svalue (unsigned char **start, unsigned char *end, char **value)
00144 {
00145   pst_obj *tok;
00146 
00147   tok = pst_get_token(start, end);
00148   if (tok == NULL)
00149     return -1;
00150   else if (PST_NAMETYPE(tok) || PST_STRINGTYPE(tok))
00151     *value = (char *) pst_getSV(tok);
00152   else {
00153     RELEASE_TOK(tok);
00154     return -1;
00155   }
00156   RELEASE_TOK(tok);
00157 
00158   return 1;
00159 }
00160 
00161 static int
00162 parse_bvalue (unsigned char **start, unsigned char *end, double *value)
00163 {
00164   pst_obj *tok;
00165 
00166   tok = pst_get_token(start, end);
00167   if (tok == NULL)
00168     return -1;
00169   else if (PST_BOOLEANTYPE(tok))
00170     *value = (double) pst_getIV(tok);
00171   else {
00172     RELEASE_TOK(tok);
00173     return -1;
00174   }
00175   RELEASE_TOK(tok);
00176 
00177   return 1;
00178 }
00179 
00180 static int
00181 parse_nvalue (unsigned char **start, unsigned char *end, double *value, int max)
00182 {
00183   int argn = 0;
00184   pst_obj *tok;
00185 
00186   tok = pst_get_token(start, end);
00187   if (tok == NULL)
00188     return -1;
00189   /*
00190    * All array elements must be numeric token. (ATM compatible)
00191    */
00192   if (PST_NUMBERTYPE(tok) && max > 0) {
00193     value[0] = (double) pst_getRV(tok);
00194     argn = 1;
00195   } else if (PST_MARKTYPE(tok)) {
00196     /* It does not distinguish '[' and '{'... */
00197     RELEASE_TOK(tok);
00198     while (*start < end &&
00199           (tok = pst_get_token(start, end)) != NULL &&
00200           PST_NUMBERTYPE(tok) && argn < max) {
00201       value[argn++] = (double) pst_getRV(tok);
00202       RELEASE_TOK(tok);
00203     }
00204     if (tok == NULL)
00205       return -1;
00206     if (!MATCH_OP(tok, "]") && !MATCH_OP(tok, "}")) {
00207       argn = -1;
00208     }
00209   }
00210   RELEASE_TOK(tok);
00211 
00212   return argn;
00213 }
00214 
00215 static const char *const StandardEncoding[256] = {
00216   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00217   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00218   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00219   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00220   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00221   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00222   ".notdef", ".notdef", "space", "exclam", "quotedbl",
00223   "numbersign", "dollar", "percent", "ampersand", "quoteright",
00224   "parenleft", "parenright", "asterisk", "plus", "comma",
00225   "hyphen", "period", "slash", "zero", "one",
00226   "two", "three", "four", "five", "six",
00227   "seven", "eight", "nine", "colon", "semicolon",
00228   "less", "equal", "greater", "question", "at",
00229   "A", "B", "C", "D", "E",
00230   "F", "G", "H", "I", "J",
00231   "K", "L", "M", "N", "O",
00232   "P", "Q", "R", "S", "T",
00233   "U", "V", "W", "X", "Y",
00234   "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
00235   "underscore", "quoteleft", "a", "b", "c",
00236   "d", "e", "f", "g", "h",
00237   "i", "j", "k", "l", "m",
00238   "n", "o", "p", "q", "r",
00239   "s", "t", "u", "v", "w",
00240   "x", "y", "z", "braceleft", "bar",
00241   "braceright", "asciitilde", ".notdef", ".notdef", ".notdef",
00242   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00243   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00244   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00245   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00246   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00247   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00248   ".notdef", "exclamdown", "cent", "sterling", "fraction",
00249   "yen", "florin", "section", "currency", "quotesingle",
00250   "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
00251   "fl", ".notdef", "endash", "dagger", "daggerdbl",
00252   "periodcentered", ".notdef", "paragraph", "bullet", "quotesinglbase",
00253   "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand",
00254   ".notdef", "questiondown", ".notdef", "grave", "acute",
00255   "circumflex", "tilde", "macron", "breve", "dotaccent",
00256   "dieresis", ".notdef", "ring", "cedilla", ".notdef",
00257   "hungarumlaut", "ogonek", "caron", "emdash", ".notdef",
00258   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00259   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00260   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00261   "AE", ".notdef", "ordfeminine", ".notdef", ".notdef",
00262   ".notdef", ".notdef", "Lslash", "Oslash", "OE",
00263   "ordmasculine", ".notdef", ".notdef", ".notdef", ".notdef",
00264   ".notdef", "ae", ".notdef", ".notdef", ".notdef",
00265   "dotlessi", ".notdef", ".notdef", "lslash", "oslash",
00266   "oe", "germandbls", ".notdef", ".notdef", ".notdef",
00267   ".notdef"
00268 };
00269 
00270 static const char *const ISOLatin1Encoding[256] = {
00271   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00272   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00273   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00274   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00275   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00276   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00277   ".notdef", ".notdef", "space", "exclam", "quotedbl",
00278   "numbersign", "dollar", "percent", "ampersand", "quotesingle",
00279   "parenleft", "parenright", "asterisk", "plus", "comma",
00280   "hyphen", "period", "slash", "zero", "one",
00281   "two", "three", "four", "five", "six",
00282   "seven", "eight", "nine", "colon", "semicolon",
00283   "less", "equal", "greater", "question", "at",
00284   "A", "B", "C", "D", "E",
00285   "F", "G", "H", "I", "J",
00286   "K", "L", "M", "N", "O",
00287   "P", "Q", "R", "S", "T",
00288   "U", "V", "W", "X", "Y",
00289   "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
00290   "underscore", "grave", "a", "b", "c",
00291   "d", "e", "f", "g", "h",
00292   "i", "j", "k", "l", "m",
00293   "n", "o", "p", "q", "r",
00294   "s", "t", "u", "v", "w",
00295   "x", "y", "z", "braceleft", "bar",
00296   "braceright", "asciitilde", ".notdef", ".notdef", ".notdef",
00297   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00298   ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
00299   ".notdef", ".notdef", ".notdef", ".notdef", "dotlessi",
00300   "quoteleft", "quoteright", "circumflex", "tilde", "macron",
00301   "breve", "dotaccent", "dieresis", ".notdef", "ring",
00302   "cedilla", ".notdef", "hungarumlaut", "ogonek", "caron",
00303   "space", "exclamdown", "cent", "sterling", "currency",
00304   "yen", "brokenbar", "section", "dieresis", "copyright",
00305   "ordfeminine", "guillemotleft", "logicalnot", "hyphen",
00306   "registered",
00307   "macron", "degree", "plusminus", "twosuperior", "threesuperior",
00308   "acute", "mu", "paragraph", "periodcentered", "cedilla",
00309   "onesuperior", "ordmasculine", "guillemotright", "onequarter",
00310   "onehalf",
00311   "threequarters", "questiondown", "Agrave", "Aacute", "Acircumflex",
00312   "Atilde", "Adieresis", "Aring", "AE", "Ccedilla",
00313   "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave",
00314   "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde",
00315   "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis",
00316   "multiply", "Oslash", "Ugrave", "Uacute", "Ucircumflex",
00317   "Udieresis", "Yacute", "Thorn", "germandbls", "agrave",
00318   "aacute", "acircumflex", "atilde", "adieresis", "aring",
00319   "ae", "ccedilla", "egrave", "eacute", "ecircumflex",
00320   "edieresis", "igrave", "iacute", "icircumflex", "idieresis",
00321   "eth", "ntilde", "ograve", "oacute", "ocircumflex",
00322   "otilde", "odieresis", "divide", "oslash", "ugrave",
00323   "uacute", "ucircumflex", "udieresis", "yacute", "thorn",
00324   "ydieresis"
00325 };
00326 
00327 static int
00328 parse_encoding (char **enc_vec, unsigned char **start, unsigned char *end, int mode)
00329 {
00330   pst_obj *tok;
00331   int      code;
00332 
00333   /*
00334    *  StandardEncoding def
00335    * or
00336    *  ISOLatin1Encoding def
00337    * or
00338    *  0 1 255 {1 index exch /.notdef put } for
00339    *  dup int name put
00340    *  ...
00341    *  [readonly] def
00342    */
00343   tok = pst_get_token(start, end);
00344   if (MATCH_OP(tok, "StandardEncoding")) {
00345     RELEASE_TOK(tok);
00346     if (enc_vec) {
00347       for (code = 0; code < 256; code++) {
00348        if (StandardEncoding[code] &&
00349            strcmp(StandardEncoding[code], ".notdef") != 0) {
00350          enc_vec[code] = NEW(strlen(StandardEncoding[code])+1, char);
00351          strcpy(enc_vec[code], StandardEncoding[code]);
00352        } else {
00353          enc_vec[code] = NULL;
00354        }
00355       }
00356     }
00357   } else if (MATCH_OP(tok, "ISOLatin1Encoding")) {
00358     RELEASE_TOK(tok);
00359     if (enc_vec) {
00360       for (code = 0; code < 256; code++) {
00361        if (ISOLatin1Encoding[code] &&
00362            strcmp(ISOLatin1Encoding[code], ".notdef") != 0) {
00363          enc_vec[code] = NEW(strlen(ISOLatin1Encoding[code])+1, char);
00364          strcpy(enc_vec[code], ISOLatin1Encoding[code]);
00365        } else {
00366          enc_vec[code] = NULL;
00367        }
00368       }
00369     }
00370   } else if (MATCH_OP(tok, "ExpertEncoding")) {
00371     RELEASE_TOK(tok);
00372     if (enc_vec) {
00373       WARN("ExpertEncoding not supported.");
00374       RELEASE_TOK(tok);
00375       return -1;
00376     }
00377     /*
00378      * Not supported yet.
00379      */
00380   } else {
00381     RELEASE_TOK(tok);
00382     seek_operator(start, end, "array");
00383     /*
00384      * Pick all seaquences that matches "dup n /Name put" until
00385      * occurrence of "def" or "readonly".
00386      */
00387     while (*start < end &&
00388           (tok = pst_get_token(start, end)) != NULL) {
00389       if (MATCH_OP(tok, "def") || MATCH_OP(tok, "readonly")) {
00390        RELEASE_TOK(tok);
00391        break;
00392       } else if (!MATCH_OP(tok, "dup")) {
00393        RELEASE_TOK(tok);
00394        continue;
00395       }
00396       RELEASE_TOK(tok);
00397 
00398       tok = pst_get_token(start, end);
00399       if (!tok || !PST_INTEGERTYPE(tok) ||
00400          (code = pst_getIV(tok)) > 255 || code < 0) {
00401        RELEASE_TOK(tok);
00402        continue;
00403       }
00404       RELEASE_TOK(tok);
00405 
00406       tok = pst_get_token(start, end);
00407       if (!tok || !PST_NAMETYPE(tok)) {
00408        RELEASE_TOK(tok);
00409        continue;
00410       }
00411       if (enc_vec) {
00412        if (enc_vec[code])
00413          RELEASE(enc_vec[code]);
00414        enc_vec[code] = (char *) pst_getSV(tok);
00415       }
00416       RELEASE_TOK(tok);
00417 
00418       tok = pst_get_token(start, end);
00419       if (!MATCH_OP(tok, "put")) {
00420        if (enc_vec[code]) {
00421          RELEASE(enc_vec[code]);
00422          enc_vec[code] = NULL;
00423        }
00424        RELEASE_TOK(tok);
00425        continue;
00426       }
00427       RELEASE_TOK(tok);
00428     }
00429   }
00430 
00431   return 0;
00432 }
00433 
00434 #ifndef CS_STR_LEN_MAX
00435 #define CS_STR_LEN_MAX 65536UL
00436 #endif
00437 #ifndef CFF_GLYPH_MAX
00438 #define CFF_GLYPH_MAX  CFF_SID_MAX
00439 #endif
00440 
00441 static int
00442 parse_subrs (cff_font *font,
00443             unsigned char **start, unsigned char *end, int lenIV, int mode)
00444 {
00445   cff_index *subrs;
00446   pst_obj   *tok;
00447   long       i, count, offset, max_size;
00448   long      *offsets, *lengths;
00449   card8     *data;
00450 
00451   tok = pst_get_token(start, end);
00452   if (!PST_INTEGERTYPE(tok) || pst_getIV(tok) < 0) {
00453     WARN("Parsing Subrs failed.");
00454     RELEASE_TOK(tok);
00455     return -1;
00456   }
00457 
00458   count = pst_getIV(tok);
00459   RELEASE_TOK(tok);
00460 
00461   if (count == 0) {
00462     font->subrs[0] = NULL;
00463     return 0;
00464   }
00465 
00466   tok = pst_get_token(start, end);
00467   if (!MATCH_OP(tok, "array")) {
00468     RELEASE_TOK(tok);
00469     return -1;
00470   }
00471   RELEASE_TOK(tok);
00472 
00473   if (mode != 1) {
00474     max_size = CS_STR_LEN_MAX;
00475     data     = NEW(max_size, card8);
00476     offsets  = NEW(count, long);
00477     lengths  = NEW(count, long);
00478     memset(offsets, 0, sizeof(long)*count);
00479     memset(lengths, 0, sizeof(long)*count);
00480   } else {
00481     max_size = 0;
00482     data     = NULL;
00483     offsets  = NULL;
00484     lengths  = NULL;
00485   }
00486 
00487   offset = 0;
00488   /* dup subr# n-bytes RD n-binary-bytes NP */
00489   for (i = 0; i < count;) {
00490     long idx, len;
00491 
00492     tok = pst_get_token(start, end);
00493     if (!tok) {
00494       if (data)    RELEASE(data);
00495       if (offsets) RELEASE(offsets);
00496       if (lengths) RELEASE(lengths);
00497       return -1;
00498     } else if (MATCH_OP(tok, "ND") ||
00499               MATCH_OP(tok, "|-") || MATCH_OP(tok, "def")) {
00500       RELEASE_TOK(tok);
00501       break;
00502     } else if (!MATCH_OP(tok, "dup")) {
00503       RELEASE_TOK(tok);
00504       continue;
00505     }
00506     RELEASE_TOK(tok);
00507 
00508     /* Found "dup" */
00509     tok = pst_get_token(start, end);
00510     if (!PST_INTEGERTYPE(tok) || pst_getIV(tok) < 0 ||
00511        pst_getIV(tok) >= count) {
00512       RELEASE_TOK(tok);
00513       if (data)    RELEASE(data);
00514       if (offsets) RELEASE(offsets);
00515       if (lengths) RELEASE(lengths);
00516       return -1;
00517     }
00518     idx = pst_getIV(tok);
00519     RELEASE_TOK(tok);
00520 
00521     tok = pst_get_token(start, end);
00522     if (!PST_INTEGERTYPE(tok) || pst_getIV(tok) < 0 ||
00523        pst_getIV(tok) > CS_STR_LEN_MAX) {
00524       RELEASE_TOK(tok);
00525       return -1;
00526     }
00527     len = pst_getIV(tok);
00528     RELEASE_TOK(tok);
00529 
00530     tok = pst_get_token(start, end);
00531     if (!MATCH_OP(tok, "RD") && !MATCH_OP(tok, "-|") &&
00532        seek_operator(start, end, "readstring") < 0) {
00533       RELEASE_TOK(tok);
00534       if (data)    RELEASE(data);
00535       if (offsets) RELEASE(offsets);
00536       if (lengths) RELEASE(lengths);
00537       return -1;
00538     }
00539     RELEASE_TOK(tok);
00540 
00541     *start += 1;
00542     if (*start + len >= end) {
00543       if (data)    RELEASE(data);
00544       if (offsets) RELEASE(offsets);
00545       if (lengths) RELEASE(lengths);
00546       return -1;
00547     }
00548     if (mode != 1) {
00549       if (offset + len >= max_size) {
00550        max_size += CS_STR_LEN_MAX;
00551        data = RENEW(data, max_size, card8);
00552       }
00553       if (lenIV >= 0) {
00554        t1_decrypt(T1_CHARKEY, data+offset, *start, lenIV, len);
00555        offsets[idx] = offset;
00556        offset += (lengths[idx] = len - lenIV);
00557       } else if (len > 0) {
00558        offsets[idx] = offset;
00559        lengths[idx] = len;
00560        memcpy(&data[offset], *start, len);
00561        offset += len;
00562       }
00563     }
00564     *start += len;
00565     i++;
00566   }
00567 
00568   if (mode != 1) {
00569     if (font->subrs[0] == NULL) {
00570       subrs = font->subrs[0] = cff_new_index(count);
00571       subrs->data = NEW(offset, card8);
00572       offset = 0;
00573       for (i = 0; i < count; i++) {
00574         subrs->offset[i] = offset + 1;
00575         if (lengths[i] > 0) {
00576          memcpy(subrs->data + offset, data + offsets[i], lengths[i]);
00577          offset += lengths[i];
00578         }
00579       }
00580       subrs->offset[count] = offset + 1;
00581     } else {
00582       /* Adobe's OPO_____.PFB and OPBO____.PFB have two /Subrs dicts,
00583        * and also have /CharStrings not followed by dicts.
00584        * Simply ignores those data. By ChoF on 2009/04/08. */
00585       WARN("Already found /Subrs; ignores the other /Subrs dicts.");
00586     }
00587     RELEASE(data);
00588     RELEASE(offsets);
00589     RELEASE(lengths);
00590   }
00591 
00592   return 0;
00593 }
00594 
00595 static int
00596 parse_charstrings (cff_font *font,
00597                  unsigned char **start, unsigned char *end, int lenIV, int mode)
00598 {
00599   cff_index    *charstrings;
00600   cff_charsets *charset;
00601   pst_obj      *tok;
00602   long          i, count, have_notdef;
00603   long          max_size, offset;
00604 
00605   /* /CharStrings n dict dup begin
00606    * /GlyphName n-bytes RD -n-binary-bytes- ND
00607    * ...
00608    * end
00609    *  - stack - ... /CharStrings dict
00610    */
00611   tok = pst_get_token(start, end);
00612   if (!PST_INTEGERTYPE(tok) ||
00613       pst_getIV(tok) < 0 || pst_getIV(tok) > CFF_GLYPH_MAX) {
00614     unsigned char *s = pst_getSV(tok);
00615     WARN("Ignores non dict \"/CharStrings %s ...\"", s);
00616     RELEASE(s);
00617     RELEASE_TOK(tok);
00618     return 0;
00619   }
00620   count = pst_getIV(tok);
00621   RELEASE_TOK(tok);
00622 
00623   if (mode != 1) {
00624     charstrings = cff_new_index(count);
00625     max_size    = CS_STR_LEN_MAX;
00626     charstrings->data = NEW(max_size, card8);
00627   } else {
00628     charstrings = NULL;
00629     max_size    = 0;
00630   }
00631   font->cstrings = charstrings;
00632 
00633   charset = font->charsets = NEW(1, cff_charsets);
00634   charset->format = 0;
00635   charset->num_entries = count-1;
00636   charset->data.glyphs = NEW(count-1, s_SID);
00637   memset(charset->data.glyphs, 0, sizeof(s_SID)*(count-1));
00638 
00639   offset      = 0;
00640   have_notdef = 0; /* .notdef must be at gid = 0 in CFF */
00641 
00642   seek_operator(start, end, "begin");
00643   for (i = 0; i < count; i++) {
00644     char *glyph_name;
00645     long  len, gid, j;
00646 
00647     /* BUG-20061126 (by ChoF):
00648      * Some fonts (e.g., belleek/blsy.pfb) does not have the correct number
00649      * of glyphs. Modify the codes even to work with these broken fonts.
00650      */
00651     tok = pst_get_token(start, end);
00652     glyph_name = (char *)pst_getSV(tok);
00653 
00654     if (PST_NAMETYPE(tok)) {
00655       RELEASE_TOK(tok);
00656       if (!glyph_name) {
00657         return -1;
00658       } else if (!strcmp(glyph_name, ".notdef")) {
00659         gid = 0;
00660         have_notdef = 1;
00661       } else if (have_notdef) {
00662         gid = i;
00663       } else if (i == count - 1) {
00664         WARN("No .notdef glyph???");
00665         return -1;
00666       } else {
00667         gid = i+1;
00668       }
00669     } else if (PST_UNKNOWNTYPE(tok) && !strcmp(glyph_name, "end")) {
00670       RELEASE_TOK(tok);
00671       break;
00672     } else {
00673       RELEASE_TOK(tok);
00674       return -1;
00675     }
00676 
00677     if (gid > 0)
00678       charset->data.glyphs[gid-1] = cff_add_string(font, glyph_name, 0);
00679     /*
00680      * We don't care about duplicate strings here since
00681      * later a subset font of this font will be generated.
00682      */
00683 
00684     RELEASE(glyph_name);
00685 
00686     tok = pst_get_token(start, end);
00687     if (!PST_INTEGERTYPE(tok) ||
00688        pst_getIV(tok) < 0 || pst_getIV(tok) > CS_STR_LEN_MAX) {
00689       RELEASE_TOK(tok);
00690       return -1;
00691     }
00692     len = pst_getIV(tok);
00693     RELEASE_TOK(tok);
00694 
00695     tok = pst_get_token(start, end);
00696     if (!MATCH_OP(tok, "RD") &&
00697        !MATCH_OP(tok, "-|") &&
00698        seek_operator(start, end, "readstring") < 0) {
00699       RELEASE_TOK(tok);
00700       return -1;
00701     }
00702     RELEASE_TOK(tok);
00703 
00704     if (*start + len + 1 >= end) {
00705       return -1;
00706     }
00707     if (mode != 1) {
00708       if (offset + len >= max_size) {
00709        max_size += MAX(len, CS_STR_LEN_MAX);
00710        charstrings->data = RENEW(charstrings->data, max_size, card8);
00711       }
00712       if (gid == 0) {
00713        if (lenIV >= 0) {
00714          memmove(charstrings->data + len - lenIV, charstrings->data, offset);
00715          for (j = 1; j <= i; j++) {
00716            charstrings->offset[j] += len - lenIV;
00717          }
00718        } else {
00719          memmove(charstrings->data + len, charstrings->data, offset);
00720          for (j = 1; j <= i; j++) {
00721            charstrings->offset[j] += len;
00722          }
00723        }
00724       }
00725     }
00726 
00727     *start += 1;
00728     if (mode != 1) {
00729       if (lenIV >= 0) {
00730        long offs = gid ? offset : 0;
00731        charstrings->offset[gid] = offs + 1; /* start at 1 */
00732        t1_decrypt(T1_CHARKEY, charstrings->data+offs, *start, lenIV, len);
00733        offset += len - lenIV;
00734       } else {
00735        if (gid == 0) {
00736          charstrings->offset[gid] = 1;
00737          memcpy(&charstrings->data[0], *start, len);
00738        } else {
00739          charstrings->offset[gid] = offset + 1;
00740          memcpy(&charstrings->data[offset], *start, len);
00741        }
00742        offset += len;
00743       }
00744     }
00745     *start += len;
00746 
00747     tok = pst_get_token(start, end);
00748     if (!MATCH_OP(tok, "ND") && !MATCH_OP(tok, "|-")) {
00749       RELEASE_TOK(tok);
00750       return -1;
00751     }
00752     RELEASE_TOK(tok);
00753   }
00754   if (mode != 1)
00755     charstrings->offset[count] = offset + 1;
00756   font->num_glyphs = count;
00757 
00758   return 0;
00759 }
00760 
00761 #define CHECK_ARGN_EQ(n) if (argn != (n)) {\
00762   WARN("%d values expected but only %d read.", (n), argn);\
00763   RELEASE(key);\
00764   return -1;\
00765 }
00766 #define CHECK_ARGN_GE(n) if (argn < (n)) {\
00767   WARN("%d values expected but only %d read.", (n), argn);\
00768   RELEASE(key);\
00769   return -1;\
00770 }
00771 
00772 #define MAX_ARGS 127
00773 static int
00774 parse_part2 (cff_font *font, unsigned char **start, unsigned char *end, int mode)
00775 {
00776   char  *key;
00777   double argv[MAX_ARGS];
00778   int    argn, lenIV = 4;
00779 
00780   while (*start < end &&
00781         (key = get_next_key(start, end)) != NULL) {
00782     if (!strcmp(key, "Subrs")) {
00783       /* levIV must appear before Subrs */
00784       if (parse_subrs(font, start, end, lenIV, mode) < 0) {
00785        RELEASE(key);
00786        return -1;
00787       }
00788     } else if (!strcmp(key, "CharStrings")) {
00789       if (parse_charstrings(font, start, end, lenIV, mode) < 0) {
00790        RELEASE(key);
00791        return -1;
00792       }
00793     } else if (!strcmp(key, "lenIV")) {
00794       argn = parse_nvalue(start, end, argv, 1);
00795       CHECK_ARGN_EQ(1);
00796       lenIV = (int) argv[0];
00797     } else if (!strcmp(key, "BlueValues") ||
00798               !strcmp(key, "OtherBlues") ||
00799               !strcmp(key, "FamilyBlues") ||
00800               !strcmp(key, "FamilyOtherBlues") ||
00801               !strcmp(key, "StemSnapH") ||
00802               !strcmp(key, "StemSnapV")) {
00803       /*
00804        * Operand values are delta in CFF font dictionary encoding.
00805        */
00806       argn = parse_nvalue(start, end, argv, MAX_ARGS);
00807       CHECK_ARGN_GE(0);
00808       cff_dict_add(font->private[0], key, argn);
00809       while (argn-- > 0) {
00810        cff_dict_set(font->private[0], key, argn,
00811                    (argn == 0) ? argv[argn] : argv[argn] - argv[argn-1]);
00812       }
00813     } else if (!strcmp(key, "StdHW") ||
00814               !strcmp(key, "StdVW") ||
00815               !strcmp(key, "BlueScale") ||
00816               !strcmp(key, "BlueShift") ||
00817               !strcmp(key, "BlueFuzz")  ||
00818               !strcmp(key, "LanguageGroup") ||
00819               !strcmp(key, "ExpansionFactor")) {
00820       /*
00821        * Value of StdHW and StdVW is described as an array in the
00822        * Type 1 Font Specification but is a number in CFF format.
00823        */
00824       argn = parse_nvalue(start, end, argv, 1);
00825       CHECK_ARGN_EQ(1);
00826       cff_dict_add(font->private[0], key, 1);
00827       cff_dict_set(font->private[0], key, 0, argv[0]);
00828     } else if (!strcmp(key, "ForceBold")) {
00829       argn = parse_bvalue(start, end, &(argv[0]));
00830       CHECK_ARGN_EQ(1);
00831       if (argv[0] != 0) {
00832        cff_dict_add(font->private[0], key, 1);
00833        cff_dict_set(font->private[0], key, 0, 1);
00834       }
00835     }
00836     /*
00837      * MinFeature, RndStemUp, UniqueID, Password ignored.
00838      */
00839     RELEASE(key);
00840   }
00841 
00842   return 0;
00843 }
00844 
00845 #ifndef TYPE1_NAME_LEN_MAX
00846 #define TYPE1_NAME_LEN_MAX 127
00847 #endif
00848 
00849 static long
00850 parse_part1 (cff_font *font, char **enc_vec,
00851             unsigned char **start, unsigned char *end, int mode)
00852 {
00853   char  *key, *strval;
00854   double argv[MAX_ARGS];
00855   int    argn; /* Macro CHECK_ARGN_XX assume 'argn' is used. */
00856 
00857   /*
00858    * We skip PostScript code inserted before the beginning of 
00859    * font dictionary so that parser will not be confused with
00860    * it. See LMRoman10-Regular (lmr10.pfb) for example.
00861    */
00862   if (seek_operator(start, end, "begin") < 0)
00863     return -1;
00864 
00865   while (*start < end &&
00866         (key = get_next_key(start, end)) != NULL) {
00867     if (!strcmp(key, "Encoding")) {
00868       if (parse_encoding(enc_vec, start, end, mode) < 0) {
00869        RELEASE(key);
00870        return -1;
00871       }
00872     } else if (!strcmp(key, "FontName")) {
00873       argn = parse_svalue(start, end, &strval);
00874       CHECK_ARGN_EQ(1);
00875       if (strlen(strval) > TYPE1_NAME_LEN_MAX) {
00876        WARN("FontName too long: %s (%d bytes)", strval, strlen(strval));
00877        strval[TYPE1_NAME_LEN_MAX] = '\0';
00878       }
00879       cff_set_name(font, strval);
00880       RELEASE(strval);
00881     } else if (!strcmp(key, "FontType")) {
00882       argn = parse_nvalue(start, end, argv, 1);
00883       CHECK_ARGN_EQ(1);
00884       if (argv[0] != 1.0) {
00885        WARN("FontType %d not supported.", (int) argv[0]);
00886        RELEASE(key);
00887        return -1;
00888       }
00889 #if 0
00890       /* DISABLED:
00891        *
00892        * Subsetted font shouldn't have UniqueID.
00893        */
00894     } else if (!strcmp(key, "UniqueID")) {
00895       argn = parse_nvalue(start, end, argv, 1);
00896       CHECK_ARGN_EQ(1);
00897       cff_dict_add(font->topdict, key, 1);
00898       cff_dict_set(font->topdict, key, 0, argv[0]);
00899 #endif
00900     } else if (!strcmp(key, "ItalicAngle") ||
00901               !strcmp(key, "StrokeWidth") ||
00902               !strcmp(key, "PaintType")) {
00903       argn = parse_nvalue(start, end, argv, 1);
00904       CHECK_ARGN_EQ(1);
00905       if (argv[0] != 0.0) {
00906 #if 0
00907        /*
00908         * Positive value in Bitstream CharterBT-Italic ???
00909         */
00910        if (!strcmp(key, "ItalicAngle") && argv[0] > 0) {
00911          WARN("Positive ItalicAngle value: %g", argv[0]);
00912          argv[0] *= -1;
00913        }
00914 #endif
00915        cff_dict_add(font->topdict, key, 1);
00916        cff_dict_set(font->topdict, key, 0, argv[0]);
00917       }
00918     } else if (!strcmp(key, "UnderLinePosition") ||
00919               !strcmp(key, "UnderLineThickness")) {
00920       argn = parse_nvalue(start, end, argv, 1);
00921       CHECK_ARGN_EQ(1);
00922       cff_dict_add(font->topdict, key, 1);
00923       cff_dict_set(font->topdict, key, 0, argv[0]);
00924     } else if (!strcmp(key, "FontBBox")) {
00925       argn = parse_nvalue(start, end, argv, 4);
00926       CHECK_ARGN_EQ(4);
00927       cff_dict_add(font->topdict, key, 4);
00928       while (argn-- > 0) {
00929        cff_dict_set(font->topdict, key, argn, argv[argn]);
00930       }
00931     } else if (!strcmp(key, "FontMatrix")) {
00932       argn = parse_nvalue(start, end, argv, 6);
00933       CHECK_ARGN_EQ(6);
00934       if (argv[0] != 0.001 || argv[1] != 0.0 || argv[2] != 0.0 ||
00935          argv[3] != 0.001 || argv[4] != 0.0 || argv[5] != 0.0) {
00936        cff_dict_add(font->topdict, key, 6);
00937        while (argn-- > 0) {
00938          cff_dict_set(font->topdict, key, argn, argv[argn]);
00939        }
00940       }
00941     } else if (!strcmp(key, "version")  || !strcmp(key, "Notice") ||
00942               !strcmp(key, "FullName") || !strcmp(key, "FamilyName") ||
00943               !strcmp(key, "Weight")   || !strcmp(key, "Copyright")) {
00944       /*
00945        * FontInfo
00946        */
00947       argn = parse_svalue(start, end, &strval);
00948       CHECK_ARGN_EQ(1);
00949       {
00950        s_SID sid;
00951 
00952        cff_dict_add(font->topdict, key, 1);
00953        if ((sid = cff_get_sid(font, strval)) == CFF_STRING_NOTDEF)
00954          sid = cff_add_string(font, strval, 0); /* FIXME */
00955        /*
00956         * We don't care about duplicate strings here since
00957         * later a subset font of this font will be generated.
00958         */
00959        cff_dict_set(font->topdict, key, 0, sid);
00960       }
00961       RELEASE(strval);
00962     } else if (!strcmp(key, "IsFixedPitch")) {
00963       argn = parse_bvalue(start, end, &(argv[0]));
00964       CHECK_ARGN_EQ(1);
00965       if (argv[0] != 0.0) {
00966        cff_dict_add(font->private[0], key, 1);
00967        cff_dict_set(font->private[0], key, 0, 1);
00968       }
00969     }
00970     RELEASE(key);
00971   }
00972 
00973   return 0;
00974 }
00975 
00976 int
00977 is_pfb (FILE *fp)
00978 {
00979   char sig[15];
00980   int i, ch;
00981 
00982   rewind(fp);
00983   if ((ch = fgetc(fp)) != 128 ||
00984       (ch = fgetc (fp)) < 0 || ch > 3) {
00985     return 0;
00986   }
00987   for (i = 0; i < 4; i++) {
00988     if ((ch = fgetc(fp)) < 0) {
00989       return 0;
00990     }
00991   }
00992   for (i = 0; i < 14; i++) {
00993     if ((ch = fgetc(fp)) < 0) {
00994       return 0;
00995     }
00996     sig[i] = (char) ch;
00997   }
00998   if (!memcmp(sig, "%!PS-AdobeFont", 14) ||
00999       !memcmp(sig, "%!FontType1", 11)) {
01000     return 1;
01001   } else if (!memcmp(sig, "%!PS", 4)) {
01002     sig[14] = '\0';
01003     WARN("Ambiguous PostScript resource type: %s", sig);
01004     return 1;
01005   } else {
01006     WARN("Not a PFB font file?");
01007     return 0;
01008   }
01009 
01010   return 0;
01011 }
01012 
01013 
01014 #define PFB_SEG_TYPE_ASCII  1
01015 #define PFB_SEG_TYPE_BINARY 2
01016 
01017 static unsigned char *
01018 get_pfb_segment (FILE *fp, int expected_type, long *length)
01019 {
01020   unsigned char *buffer;
01021   long bytesread;
01022 
01023   buffer = NULL; bytesread = 0;
01024   for (;;) {
01025     int ch;
01026 
01027     ch = fgetc(fp);
01028     if (ch < 0) {
01029       break;
01030     } else if (ch != 128) {
01031       ERROR("Not a pfb file?");
01032     }
01033     ch = fgetc(fp);
01034     if (ch < 0 || ch != expected_type) {
01035       seek_relative(fp, -2);
01036       break;
01037     }
01038     {
01039       long slen, rlen;
01040       int  i;
01041 
01042       slen = 0;
01043       for (i = 0; i < 4; i++) {
01044        if ((ch = fgetc(fp)) < 0) {
01045          if (buffer)
01046            RELEASE(buffer);
01047          return NULL;
01048        }
01049        slen = slen + (ch << (8*i));
01050       }
01051       buffer = RENEW(buffer, bytesread + slen, unsigned char);
01052       while (slen > 0) {
01053        rlen = fread(buffer + bytesread, sizeof(unsigned char), slen, fp);
01054        if (rlen < 0) {
01055          if (buffer)
01056            RELEASE(buffer);
01057          return NULL;
01058        }
01059        slen -= rlen;
01060        bytesread += rlen;
01061       }
01062     }
01063   }
01064   if (bytesread == 0) {
01065     ERROR("PFB segment length zero?");
01066   }
01067 
01068   buffer = RENEW(buffer, bytesread+1, unsigned char);
01069   buffer[bytesread] = 0;
01070 
01071   if (length)
01072     *length = bytesread;
01073   return buffer;
01074 }
01075 
01076 char *
01077 t1_get_standard_glyph (int code)
01078 {
01079   if (!StandardEncoding[code])
01080     return NULL;
01081 
01082   return (char *) StandardEncoding[code];
01083 }
01084 
01085 int
01086 t1_get_fontname (FILE *fp, char *fontname)
01087 {
01088   unsigned char *buffer, *start, *end;
01089   long  length;
01090   char *key;
01091   int   fn_found = 0;
01092 
01093   rewind(fp);
01094   buffer = get_pfb_segment(fp, PFB_SEG_TYPE_ASCII, &length);
01095   if (buffer == NULL || length == 0)
01096     ERROR("Reading PFB (ASCII part) file failed.");
01097   start = buffer;
01098   end   = buffer + length;
01099 
01100   if (seek_operator(&start, end, "begin") < 0) {
01101     RELEASE(buffer);
01102     return -1;
01103   }
01104 
01105   while (!fn_found && start < end &&
01106         (key = get_next_key(&start, end)) != NULL) {
01107     if (!strcmp(key, "FontName")) {
01108       char *strval;
01109       if (parse_svalue(&start, end, &strval) == 1) {
01110        if (strlen(strval) > TYPE1_NAME_LEN_MAX) {
01111          WARN("FontName \"%s\" too long. (%d bytes)", strval, strlen(strval));
01112          strval[TYPE1_NAME_LEN_MAX] = '\0';
01113        }
01114        strcpy(fontname, strval);
01115        RELEASE(strval);
01116        fn_found = 1;
01117       }
01118     }
01119     RELEASE(key);
01120   }
01121   RELEASE(buffer);
01122 
01123   return 0;
01124 }
01125 
01126 static void
01127 init_cff_font (cff_font *cff)
01128 {
01129   cff->stream = NULL;
01130   cff->filter = 0;
01131   cff->fontname = NULL;
01132   cff->index    = 0;
01133   cff->flag = FONTTYPE_FONT;
01134 
01135   cff->header.major = 1;
01136   cff->header.minor = 0;
01137   cff->header.hdr_size = 4;
01138   cff->header.offsize  = 4;
01139   cff->name     = cff_new_index(1);
01140   cff->topdict  = cff_new_dict();
01141   cff->string   = NULL;
01142   cff->gsubr    = cff_new_index(0); /* No Global Subr */
01143   cff->encoding = NULL;
01144   cff->charsets = NULL;
01145   cff->fdselect = NULL;
01146   cff->cstrings = NULL;
01147   cff->fdarray  = NULL;
01148   cff->private  = NEW(1, cff_dict *);
01149   cff->private[0] = cff_new_dict();
01150   cff->subrs = NEW(1, cff_index *);
01151   cff->subrs[0] = NULL;
01152 
01153   cff->offset  = 0;
01154   cff->gsubr_offset = 0;
01155   cff->num_glyphs   = 0;
01156   cff->num_fds      = 1;
01157   cff->_string = cff_new_index(0);
01158 }
01159 
01160 cff_font *
01161 t1_load_font (char **enc_vec, int mode, FILE *fp)
01162 {
01163   long length;
01164   cff_font *cff;
01165   unsigned char *buffer, *start, *end;
01166 
01167   rewind(fp);
01168   /* ASCII section */
01169   buffer = get_pfb_segment(fp, PFB_SEG_TYPE_ASCII, &length);
01170   if (buffer == NULL || length == 0) {
01171     ERROR("Reading PFB (ASCII part) file failed.");
01172     return NULL;
01173   }
01174 
01175   cff = NEW(1, cff_font);
01176   init_cff_font(cff);
01177 
01178   start = buffer; end = buffer + length;
01179   if (parse_part1(cff, enc_vec, &start, end, mode) < 0) {
01180     cff_close(cff);
01181     RELEASE(buffer);
01182     ERROR("Reading PFB (ASCII part) file failed.");
01183     return NULL;
01184   }
01185   RELEASE(buffer);
01186 
01187   /* Binary section */
01188   buffer = get_pfb_segment(fp, PFB_SEG_TYPE_BINARY, &length);
01189   if (buffer == NULL || length == 0) {
01190     cff_close(cff);
01191     RELEASE(buffer);
01192     ERROR("Reading PFB (BINARY part) file failed.");
01193     return NULL;
01194   } else {
01195     t1_decrypt(T1_EEKEY, buffer, buffer, 0, length);
01196   }
01197   start = buffer + 4; end = buffer + length;
01198   if (parse_part2(cff, &start, end, mode) < 0) {
01199     cff_close(cff);
01200     RELEASE(buffer);
01201     ERROR("Reading PFB (BINARY part) file failed.");
01202     return NULL;
01203   }
01204   RELEASE(buffer);
01205 
01206   cff_update_string(cff);
01207 
01208   /* Remaining section ignored. */
01209 
01210   return cff;
01211 }