PageRenderTime 67ms CodeModel.GetById 20ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 0ms

/TeXmacs-1.0.7.11-src/src/Plugins/Pdf/dvipdfmx/t1_load.c

#
C | 1211 lines | 1001 code | 111 blank | 99 comment | 288 complexity | 6ae5f36bbf1f857e06cfbc8d434f1b08 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
   1/*  $Header: /home/cvsroot/dvipdfmx/src/t1_load.c,v 1.13 2009/04/08 03:10:58 chofchof Exp $
   2
   3    This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
   4
   5    Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
   6    the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
   7
   8    Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
   9
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 2 of the License, or
  13    (at your option) any later version.
  14
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19
  20    You should have received a copy of the GNU General Public License
  21    along with this program; if not, write to the Free Software
  22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  23*/
  24
  25#if HAVE_CONFIG_H
  26#include "config.h"
  27#endif
  28
  29#include <string.h>
  30#include <math.h>
  31
  32#include "system.h"
  33#include "mfileio.h"
  34#include "mem.h"
  35#include "error.h"
  36#include "numbers.h"
  37
  38#include "pdfobj.h"
  39#include "pdffont.h"
  40
  41#include "pdfencoding.h"
  42#include "unicode.h"
  43
  44#include "dpxutil.h"
  45
  46#include "pst_obj.h"
  47#include "pst.h"
  48
  49#include "cff_limits.h"
  50#include "cff_types.h"
  51#include "cff_dict.h"
  52#include "cff.h"
  53
  54#include "t1_load.h"
  55
  56/* Migrated from t1crypt */
  57#define T1_EEKEY   55665u
  58#define T1_CHARKEY 4330u
  59
  60#if  0
  61/* We no longer need encryption. */
  62static unsigned short r = T1_EEKEY, c1 = 52845, c2 = 22719;
  63
  64static unsigned char t1_encrypt (unsigned char plain)
  65{
  66  unsigned char cipher;
  67  cipher = (plain ^ (r >> 8));
  68  r = (cipher + r) * c1 + c2;
  69  return cipher;
  70}
  71
  72static void t1_crypt_init (unsigned short key)
  73{
  74  r = key;
  75}
  76#endif /* 0 */
  77
  78static void
  79t1_decrypt (unsigned short key,
  80	    unsigned char *dst, const unsigned char *src,
  81	    long skip, long len)
  82{
  83  len -= skip;
  84  while (skip--)
  85    key = (key + *src++) * 52845u + 22719u;
  86  while (len--) {
  87    unsigned char c = *src++;
  88    *dst++ = (c ^ (key >> 8));
  89    key = (key + c) * 52845u + 22719u;
  90  }
  91}
  92/* T1CRYPT */
  93
  94#define MATCH_NAME(t,n) ((t) && PST_NAMETYPE((t))    && !strncmp(pst_data_ptr((t)),(n),strlen((n))))
  95#define MATCH_OP(t,n)   ((t) && PST_UNKNOWNTYPE((t)) && !strncmp(pst_data_ptr((t)),(n),strlen((n))))
  96
  97#define RELEASE_TOK(t) if ((t) != NULL) {\
  98  pst_release_obj((t));\
  99  (t) = NULL;\
 100}
 101
 102static char *
 103get_next_key (unsigned char **start, unsigned char *end)
 104{
 105  char *key = NULL;
 106  pst_obj *tok;
 107
 108  while (*start < end &&
 109	 (tok = pst_get_token(start, end)) != NULL) {
 110    if (PST_NAMETYPE(tok)) {
 111      key = (char *) pst_getSV(tok);
 112      RELEASE_TOK(tok);
 113      break;
 114    }
 115    RELEASE_TOK(tok);
 116  }
 117
 118  return key;
 119}
 120
 121static int
 122seek_operator (unsigned char **start, unsigned char *end, const char *op)
 123{
 124  pst_obj *tok = NULL;
 125
 126  while (*start < end &&
 127	 (tok = pst_get_token(start, end)) != NULL) {
 128    if (MATCH_OP(tok, op)) {
 129      break;
 130    }
 131    RELEASE_TOK(tok);
 132  }
 133
 134  if (tok == NULL)
 135    return -1;
 136  RELEASE_TOK(tok);
 137
 138  return 0;
 139}
 140
 141
 142static int
 143parse_svalue (unsigned char **start, unsigned char *end, char **value)
 144{
 145  pst_obj *tok;
 146
 147  tok = pst_get_token(start, end);
 148  if (tok == NULL)
 149    return -1;
 150  else if (PST_NAMETYPE(tok) || PST_STRINGTYPE(tok))
 151    *value = (char *) pst_getSV(tok);
 152  else {
 153    RELEASE_TOK(tok);
 154    return -1;
 155  }
 156  RELEASE_TOK(tok);
 157
 158  return 1;
 159}
 160
 161static int
 162parse_bvalue (unsigned char **start, unsigned char *end, double *value)
 163{
 164  pst_obj *tok;
 165
 166  tok = pst_get_token(start, end);
 167  if (tok == NULL)
 168    return -1;
 169  else if (PST_BOOLEANTYPE(tok))
 170    *value = (double) pst_getIV(tok);
 171  else {
 172    RELEASE_TOK(tok);
 173    return -1;
 174  }
 175  RELEASE_TOK(tok);
 176
 177  return 1;
 178}
 179
 180static int
 181parse_nvalue (unsigned char **start, unsigned char *end, double *value, int max)
 182{
 183  int argn = 0;
 184  pst_obj *tok;
 185
 186  tok = pst_get_token(start, end);
 187  if (tok == NULL)
 188    return -1;
 189  /*
 190   * All array elements must be numeric token. (ATM compatible)
 191   */
 192  if (PST_NUMBERTYPE(tok) && max > 0) {
 193    value[0] = (double) pst_getRV(tok);
 194    argn = 1;
 195  } else if (PST_MARKTYPE(tok)) {
 196    /* It does not distinguish '[' and '{'... */
 197    RELEASE_TOK(tok);
 198    while (*start < end &&
 199	   (tok = pst_get_token(start, end)) != NULL &&
 200	   PST_NUMBERTYPE(tok) && argn < max) {
 201      value[argn++] = (double) pst_getRV(tok);
 202      RELEASE_TOK(tok);
 203    }
 204    if (tok == NULL)
 205      return -1;
 206    if (!MATCH_OP(tok, "]") && !MATCH_OP(tok, "}")) {
 207      argn = -1;
 208    }
 209  }
 210  RELEASE_TOK(tok);
 211
 212  return argn;
 213}
 214
 215static const char *const StandardEncoding[256] = {
 216  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 217  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 218  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 219  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 220  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 221  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 222  ".notdef", ".notdef", "space", "exclam", "quotedbl",
 223  "numbersign", "dollar", "percent", "ampersand", "quoteright",
 224  "parenleft", "parenright", "asterisk", "plus", "comma",
 225  "hyphen", "period", "slash", "zero", "one",
 226  "two", "three", "four", "five", "six",
 227  "seven", "eight", "nine", "colon", "semicolon",
 228  "less", "equal", "greater", "question", "at",
 229  "A", "B", "C", "D", "E",
 230  "F", "G", "H", "I", "J",
 231  "K", "L", "M", "N", "O",
 232  "P", "Q", "R", "S", "T",
 233  "U", "V", "W", "X", "Y",
 234  "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
 235  "underscore", "quoteleft", "a", "b", "c",
 236  "d", "e", "f", "g", "h",
 237  "i", "j", "k", "l", "m",
 238  "n", "o", "p", "q", "r",
 239  "s", "t", "u", "v", "w",
 240  "x", "y", "z", "braceleft", "bar",
 241  "braceright", "asciitilde", ".notdef", ".notdef", ".notdef",
 242  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 243  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 244  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 245  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 246  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 247  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 248  ".notdef", "exclamdown", "cent", "sterling", "fraction",
 249  "yen", "florin", "section", "currency", "quotesingle",
 250  "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
 251  "fl", ".notdef", "endash", "dagger", "daggerdbl",
 252  "periodcentered", ".notdef", "paragraph", "bullet", "quotesinglbase",
 253  "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand",
 254  ".notdef", "questiondown", ".notdef", "grave", "acute",
 255  "circumflex", "tilde", "macron", "breve", "dotaccent",
 256  "dieresis", ".notdef", "ring", "cedilla", ".notdef",
 257  "hungarumlaut", "ogonek", "caron", "emdash", ".notdef",
 258  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 259  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 260  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 261  "AE", ".notdef", "ordfeminine", ".notdef", ".notdef",
 262  ".notdef", ".notdef", "Lslash", "Oslash", "OE",
 263  "ordmasculine", ".notdef", ".notdef", ".notdef", ".notdef",
 264  ".notdef", "ae", ".notdef", ".notdef", ".notdef",
 265  "dotlessi", ".notdef", ".notdef", "lslash", "oslash",
 266  "oe", "germandbls", ".notdef", ".notdef", ".notdef",
 267  ".notdef"
 268};
 269
 270static const char *const ISOLatin1Encoding[256] = {
 271  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 272  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 273  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 274  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 275  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 276  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 277  ".notdef", ".notdef", "space", "exclam", "quotedbl",
 278  "numbersign", "dollar", "percent", "ampersand", "quotesingle",
 279  "parenleft", "parenright", "asterisk", "plus", "comma",
 280  "hyphen", "period", "slash", "zero", "one",
 281  "two", "three", "four", "five", "six",
 282  "seven", "eight", "nine", "colon", "semicolon",
 283  "less", "equal", "greater", "question", "at",
 284  "A", "B", "C", "D", "E",
 285  "F", "G", "H", "I", "J",
 286  "K", "L", "M", "N", "O",
 287  "P", "Q", "R", "S", "T",
 288  "U", "V", "W", "X", "Y",
 289  "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
 290  "underscore", "grave", "a", "b", "c",
 291  "d", "e", "f", "g", "h",
 292  "i", "j", "k", "l", "m",
 293  "n", "o", "p", "q", "r",
 294  "s", "t", "u", "v", "w",
 295  "x", "y", "z", "braceleft", "bar",
 296  "braceright", "asciitilde", ".notdef", ".notdef", ".notdef",
 297  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 298  ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
 299  ".notdef", ".notdef", ".notdef", ".notdef", "dotlessi",
 300  "quoteleft", "quoteright", "circumflex", "tilde", "macron",
 301  "breve", "dotaccent", "dieresis", ".notdef", "ring",
 302  "cedilla", ".notdef", "hungarumlaut", "ogonek", "caron",
 303  "space", "exclamdown", "cent", "sterling", "currency",
 304  "yen", "brokenbar", "section", "dieresis", "copyright",
 305  "ordfeminine", "guillemotleft", "logicalnot", "hyphen",
 306  "registered",
 307  "macron", "degree", "plusminus", "twosuperior", "threesuperior",
 308  "acute", "mu", "paragraph", "periodcentered", "cedilla",
 309  "onesuperior", "ordmasculine", "guillemotright", "onequarter",
 310  "onehalf",
 311  "threequarters", "questiondown", "Agrave", "Aacute", "Acircumflex",
 312  "Atilde", "Adieresis", "Aring", "AE", "Ccedilla",
 313  "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave",
 314  "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde",
 315  "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis",
 316  "multiply", "Oslash", "Ugrave", "Uacute", "Ucircumflex",
 317  "Udieresis", "Yacute", "Thorn", "germandbls", "agrave",
 318  "aacute", "acircumflex", "atilde", "adieresis", "aring",
 319  "ae", "ccedilla", "egrave", "eacute", "ecircumflex",
 320  "edieresis", "igrave", "iacute", "icircumflex", "idieresis",
 321  "eth", "ntilde", "ograve", "oacute", "ocircumflex",
 322  "otilde", "odieresis", "divide", "oslash", "ugrave",
 323  "uacute", "ucircumflex", "udieresis", "yacute", "thorn",
 324  "ydieresis"
 325};
 326
 327static int
 328parse_encoding (char **enc_vec, unsigned char **start, unsigned char *end, int mode)
 329{
 330  pst_obj *tok;
 331  int      code;
 332
 333  /*
 334   *  StandardEncoding def
 335   * or
 336   *  ISOLatin1Encoding def
 337   * or
 338   *  0 1 255 {1 index exch /.notdef put } for
 339   *  dup int name put
 340   *  ...
 341   *  [readonly] def
 342   */
 343  tok = pst_get_token(start, end);
 344  if (MATCH_OP(tok, "StandardEncoding")) {
 345    RELEASE_TOK(tok);
 346    if (enc_vec) {
 347      for (code = 0; code < 256; code++) {
 348	if (StandardEncoding[code] &&
 349	    strcmp(StandardEncoding[code], ".notdef") != 0) {
 350	  enc_vec[code] = NEW(strlen(StandardEncoding[code])+1, char);
 351	  strcpy(enc_vec[code], StandardEncoding[code]);
 352	} else {
 353	  enc_vec[code] = NULL;
 354	}
 355      }
 356    }
 357  } else if (MATCH_OP(tok, "ISOLatin1Encoding")) {
 358    RELEASE_TOK(tok);
 359    if (enc_vec) {
 360      for (code = 0; code < 256; code++) {
 361	if (ISOLatin1Encoding[code] &&
 362	    strcmp(ISOLatin1Encoding[code], ".notdef") != 0) {
 363	  enc_vec[code] = NEW(strlen(ISOLatin1Encoding[code])+1, char);
 364	  strcpy(enc_vec[code], ISOLatin1Encoding[code]);
 365	} else {
 366	  enc_vec[code] = NULL;
 367	}
 368      }
 369    }
 370  } else if (MATCH_OP(tok, "ExpertEncoding")) {
 371    RELEASE_TOK(tok);
 372    if (enc_vec) {
 373      WARN("ExpertEncoding not supported.");
 374      RELEASE_TOK(tok);
 375      return -1;
 376    }
 377    /*
 378     * Not supported yet.
 379     */
 380  } else {
 381    RELEASE_TOK(tok);
 382    seek_operator(start, end, "array");
 383    /*
 384     * Pick all seaquences that matches "dup n /Name put" until
 385     * occurrence of "def" or "readonly".
 386     */
 387    while (*start < end &&
 388	   (tok = pst_get_token(start, end)) != NULL) {
 389      if (MATCH_OP(tok, "def") || MATCH_OP(tok, "readonly")) {
 390	RELEASE_TOK(tok);
 391	break;
 392      } else if (!MATCH_OP(tok, "dup")) {
 393	RELEASE_TOK(tok);
 394	continue;
 395      }
 396      RELEASE_TOK(tok);
 397
 398      tok = pst_get_token(start, end);
 399      if (!tok || !PST_INTEGERTYPE(tok) ||
 400	  (code = pst_getIV(tok)) > 255 || code < 0) {
 401	RELEASE_TOK(tok);
 402	continue;
 403      }
 404      RELEASE_TOK(tok);
 405
 406      tok = pst_get_token(start, end);
 407      if (!tok || !PST_NAMETYPE(tok)) {
 408	RELEASE_TOK(tok);
 409	continue;
 410      }
 411      if (enc_vec) {
 412	if (enc_vec[code])
 413	  RELEASE(enc_vec[code]);
 414	enc_vec[code] = (char *) pst_getSV(tok);
 415      }
 416      RELEASE_TOK(tok);
 417
 418      tok = pst_get_token(start, end);
 419      if (!MATCH_OP(tok, "put")) {
 420	if (enc_vec[code]) {
 421	  RELEASE(enc_vec[code]);
 422	  enc_vec[code] = NULL;
 423	}
 424	RELEASE_TOK(tok);
 425	continue;
 426      }
 427      RELEASE_TOK(tok);
 428    }
 429  }
 430
 431  return 0;
 432}
 433
 434#ifndef CS_STR_LEN_MAX
 435#define CS_STR_LEN_MAX 65536UL
 436#endif
 437#ifndef CFF_GLYPH_MAX
 438#define CFF_GLYPH_MAX  CFF_SID_MAX
 439#endif
 440
 441static int
 442parse_subrs (cff_font *font,
 443	     unsigned char **start, unsigned char *end, int lenIV, int mode)
 444{
 445  cff_index *subrs;
 446  pst_obj   *tok;
 447  long       i, count, offset, max_size;
 448  long      *offsets, *lengths;
 449  card8     *data;
 450
 451  tok = pst_get_token(start, end);
 452  if (!PST_INTEGERTYPE(tok) || pst_getIV(tok) < 0) {
 453    WARN("Parsing Subrs failed.");
 454    RELEASE_TOK(tok);
 455    return -1;
 456  }
 457
 458  count = pst_getIV(tok);
 459  RELEASE_TOK(tok);
 460
 461  if (count == 0) {
 462    font->subrs[0] = NULL;
 463    return 0;
 464  }
 465
 466  tok = pst_get_token(start, end);
 467  if (!MATCH_OP(tok, "array")) {
 468    RELEASE_TOK(tok);
 469    return -1;
 470  }
 471  RELEASE_TOK(tok);
 472
 473  if (mode != 1) {
 474    max_size = CS_STR_LEN_MAX;
 475    data     = NEW(max_size, card8);
 476    offsets  = NEW(count, long);
 477    lengths  = NEW(count, long);
 478    memset(offsets, 0, sizeof(long)*count);
 479    memset(lengths, 0, sizeof(long)*count);
 480  } else {
 481    max_size = 0;
 482    data     = NULL;
 483    offsets  = NULL;
 484    lengths  = NULL;
 485  }
 486
 487  offset = 0;
 488  /* dup subr# n-bytes RD n-binary-bytes NP */
 489  for (i = 0; i < count;) {
 490    long idx, len;
 491
 492    tok = pst_get_token(start, end);
 493    if (!tok) {
 494      if (data)    RELEASE(data);
 495      if (offsets) RELEASE(offsets);
 496      if (lengths) RELEASE(lengths);
 497      return -1;
 498    } else if (MATCH_OP(tok, "ND") ||
 499	       MATCH_OP(tok, "|-") || MATCH_OP(tok, "def")) {
 500      RELEASE_TOK(tok);
 501      break;
 502    } else if (!MATCH_OP(tok, "dup")) {
 503      RELEASE_TOK(tok);
 504      continue;
 505    }
 506    RELEASE_TOK(tok);
 507
 508    /* Found "dup" */
 509    tok = pst_get_token(start, end);
 510    if (!PST_INTEGERTYPE(tok) || pst_getIV(tok) < 0 ||
 511	pst_getIV(tok) >= count) {
 512      RELEASE_TOK(tok);
 513      if (data)    RELEASE(data);
 514      if (offsets) RELEASE(offsets);
 515      if (lengths) RELEASE(lengths);
 516      return -1;
 517    }
 518    idx = pst_getIV(tok);
 519    RELEASE_TOK(tok);
 520
 521    tok = pst_get_token(start, end);
 522    if (!PST_INTEGERTYPE(tok) || pst_getIV(tok) < 0 ||
 523	pst_getIV(tok) > CS_STR_LEN_MAX) {
 524      RELEASE_TOK(tok);
 525      return -1;
 526    }
 527    len = pst_getIV(tok);
 528    RELEASE_TOK(tok);
 529
 530    tok = pst_get_token(start, end);
 531    if (!MATCH_OP(tok, "RD") && !MATCH_OP(tok, "-|") &&
 532	seek_operator(start, end, "readstring") < 0) {
 533      RELEASE_TOK(tok);
 534      if (data)    RELEASE(data);
 535      if (offsets) RELEASE(offsets);
 536      if (lengths) RELEASE(lengths);
 537      return -1;
 538    }
 539    RELEASE_TOK(tok);
 540
 541    *start += 1;
 542    if (*start + len >= end) {
 543      if (data)    RELEASE(data);
 544      if (offsets) RELEASE(offsets);
 545      if (lengths) RELEASE(lengths);
 546      return -1;
 547    }
 548    if (mode != 1) {
 549      if (offset + len >= max_size) {
 550	max_size += CS_STR_LEN_MAX;
 551	data = RENEW(data, max_size, card8);
 552      }
 553      if (lenIV >= 0) {
 554	t1_decrypt(T1_CHARKEY, data+offset, *start, lenIV, len);
 555	offsets[idx] = offset;
 556	offset += (lengths[idx] = len - lenIV);
 557      } else if (len > 0) {
 558	offsets[idx] = offset;
 559	lengths[idx] = len;
 560	memcpy(&data[offset], *start, len);
 561	offset += len;
 562      }
 563    }
 564    *start += len;
 565    i++;
 566  }
 567
 568  if (mode != 1) {
 569    if (font->subrs[0] == NULL) {
 570      subrs = font->subrs[0] = cff_new_index(count);
 571      subrs->data = NEW(offset, card8);
 572      offset = 0;
 573      for (i = 0; i < count; i++) {
 574        subrs->offset[i] = offset + 1;
 575        if (lengths[i] > 0) {
 576	  memcpy(subrs->data + offset, data + offsets[i], lengths[i]);
 577	  offset += lengths[i];
 578        }
 579      }
 580      subrs->offset[count] = offset + 1;
 581    } else {
 582      /* Adobe's OPO_____.PFB and OPBO____.PFB have two /Subrs dicts,
 583       * and also have /CharStrings not followed by dicts.
 584       * Simply ignores those data. By ChoF on 2009/04/08. */
 585      WARN("Already found /Subrs; ignores the other /Subrs dicts.");
 586    }
 587    RELEASE(data);
 588    RELEASE(offsets);
 589    RELEASE(lengths);
 590  }
 591
 592  return 0;
 593}
 594
 595static int
 596parse_charstrings (cff_font *font,
 597		   unsigned char **start, unsigned char *end, int lenIV, int mode)
 598{
 599  cff_index    *charstrings;
 600  cff_charsets *charset;
 601  pst_obj      *tok;
 602  long          i, count, have_notdef;
 603  long          max_size, offset;
 604
 605  /* /CharStrings n dict dup begin
 606   * /GlyphName n-bytes RD -n-binary-bytes- ND
 607   * ...
 608   * end
 609   *  - stack - ... /CharStrings dict
 610   */
 611  tok = pst_get_token(start, end);
 612  if (!PST_INTEGERTYPE(tok) ||
 613      pst_getIV(tok) < 0 || pst_getIV(tok) > CFF_GLYPH_MAX) {
 614    unsigned char *s = pst_getSV(tok);
 615    WARN("Ignores non dict \"/CharStrings %s ...\"", s);
 616    RELEASE(s);
 617    RELEASE_TOK(tok);
 618    return 0;
 619  }
 620  count = pst_getIV(tok);
 621  RELEASE_TOK(tok);
 622
 623  if (mode != 1) {
 624    charstrings = cff_new_index(count);
 625    max_size    = CS_STR_LEN_MAX;
 626    charstrings->data = NEW(max_size, card8);
 627  } else {
 628    charstrings = NULL;
 629    max_size    = 0;
 630  }
 631  font->cstrings = charstrings;
 632
 633  charset = font->charsets = NEW(1, cff_charsets);
 634  charset->format = 0;
 635  charset->num_entries = count-1;
 636  charset->data.glyphs = NEW(count-1, s_SID);
 637  memset(charset->data.glyphs, 0, sizeof(s_SID)*(count-1));
 638
 639  offset      = 0;
 640  have_notdef = 0; /* .notdef must be at gid = 0 in CFF */
 641
 642  seek_operator(start, end, "begin");
 643  for (i = 0; i < count; i++) {
 644    char *glyph_name;
 645    long  len, gid, j;
 646
 647    /* BUG-20061126 (by ChoF):
 648     * Some fonts (e.g., belleek/blsy.pfb) does not have the correct number
 649     * of glyphs. Modify the codes even to work with these broken fonts.
 650     */
 651    tok = pst_get_token(start, end);
 652    glyph_name = (char *)pst_getSV(tok);
 653
 654    if (PST_NAMETYPE(tok)) {
 655      RELEASE_TOK(tok);
 656      if (!glyph_name) {
 657        return -1;
 658      } else if (!strcmp(glyph_name, ".notdef")) {
 659        gid = 0;
 660        have_notdef = 1;
 661      } else if (have_notdef) {
 662        gid = i;
 663      } else if (i == count - 1) {
 664        WARN("No .notdef glyph???");
 665        return -1;
 666      } else {
 667        gid = i+1;
 668      }
 669    } else if (PST_UNKNOWNTYPE(tok) && !strcmp(glyph_name, "end")) {
 670      RELEASE_TOK(tok);
 671      break;
 672    } else {
 673      RELEASE_TOK(tok);
 674      return -1;
 675    }
 676
 677    if (gid > 0)
 678      charset->data.glyphs[gid-1] = cff_add_string(font, glyph_name, 0);
 679    /*
 680     * We don't care about duplicate strings here since
 681     * later a subset font of this font will be generated.
 682     */
 683
 684    RELEASE(glyph_name);
 685
 686    tok = pst_get_token(start, end);
 687    if (!PST_INTEGERTYPE(tok) ||
 688	pst_getIV(tok) < 0 || pst_getIV(tok) > CS_STR_LEN_MAX) {
 689      RELEASE_TOK(tok);
 690      return -1;
 691    }
 692    len = pst_getIV(tok);
 693    RELEASE_TOK(tok);
 694
 695    tok = pst_get_token(start, end);
 696    if (!MATCH_OP(tok, "RD") &&
 697	!MATCH_OP(tok, "-|") &&
 698	seek_operator(start, end, "readstring") < 0) {
 699      RELEASE_TOK(tok);
 700      return -1;
 701    }
 702    RELEASE_TOK(tok);
 703
 704    if (*start + len + 1 >= end) {
 705      return -1;
 706    }
 707    if (mode != 1) {
 708      if (offset + len >= max_size) {
 709	max_size += MAX(len, CS_STR_LEN_MAX);
 710	charstrings->data = RENEW(charstrings->data, max_size, card8);
 711      }
 712      if (gid == 0) {
 713	if (lenIV >= 0) {
 714	  memmove(charstrings->data + len - lenIV, charstrings->data, offset);
 715	  for (j = 1; j <= i; j++) {
 716	    charstrings->offset[j] += len - lenIV;
 717	  }
 718	} else {
 719	  memmove(charstrings->data + len, charstrings->data, offset);
 720	  for (j = 1; j <= i; j++) {
 721	    charstrings->offset[j] += len;
 722	  }
 723	}
 724      }
 725    }
 726
 727    *start += 1;
 728    if (mode != 1) {
 729      if (lenIV >= 0) {
 730	long offs = gid ? offset : 0;
 731	charstrings->offset[gid] = offs + 1; /* start at 1 */
 732	t1_decrypt(T1_CHARKEY, charstrings->data+offs, *start, lenIV, len);
 733	offset += len - lenIV;
 734      } else {
 735	if (gid == 0) {
 736	  charstrings->offset[gid] = 1;
 737	  memcpy(&charstrings->data[0], *start, len);
 738	} else {
 739	  charstrings->offset[gid] = offset + 1;
 740	  memcpy(&charstrings->data[offset], *start, len);
 741	}
 742	offset += len;
 743      }
 744    }
 745    *start += len;
 746
 747    tok = pst_get_token(start, end);
 748    if (!MATCH_OP(tok, "ND") && !MATCH_OP(tok, "|-")) {
 749      RELEASE_TOK(tok);
 750      return -1;
 751    }
 752    RELEASE_TOK(tok);
 753  }
 754  if (mode != 1)
 755    charstrings->offset[count] = offset + 1;
 756  font->num_glyphs = count;
 757
 758  return 0;
 759}
 760
 761#define CHECK_ARGN_EQ(n) if (argn != (n)) {\
 762  WARN("%d values expected but only %d read.", (n), argn);\
 763  RELEASE(key);\
 764  return -1;\
 765}
 766#define CHECK_ARGN_GE(n) if (argn < (n)) {\
 767  WARN("%d values expected but only %d read.", (n), argn);\
 768  RELEASE(key);\
 769  return -1;\
 770}
 771
 772#define MAX_ARGS 127
 773static int
 774parse_part2 (cff_font *font, unsigned char **start, unsigned char *end, int mode)
 775{
 776  char  *key;
 777  double argv[MAX_ARGS];
 778  int    argn, lenIV = 4;
 779
 780  while (*start < end &&
 781	 (key = get_next_key(start, end)) != NULL) {
 782    if (!strcmp(key, "Subrs")) {
 783      /* levIV must appear before Subrs */
 784      if (parse_subrs(font, start, end, lenIV, mode) < 0) {
 785	RELEASE(key);
 786	return -1;
 787      }
 788    } else if (!strcmp(key, "CharStrings")) {
 789      if (parse_charstrings(font, start, end, lenIV, mode) < 0) {
 790	RELEASE(key);
 791	return -1;
 792      }
 793    } else if (!strcmp(key, "lenIV")) {
 794      argn = parse_nvalue(start, end, argv, 1);
 795      CHECK_ARGN_EQ(1);
 796      lenIV = (int) argv[0];
 797    } else if (!strcmp(key, "BlueValues") ||
 798	       !strcmp(key, "OtherBlues") ||
 799	       !strcmp(key, "FamilyBlues") ||
 800	       !strcmp(key, "FamilyOtherBlues") ||
 801	       !strcmp(key, "StemSnapH") ||
 802	       !strcmp(key, "StemSnapV")) {
 803      /*
 804       * Operand values are delta in CFF font dictionary encoding.
 805       */
 806      argn = parse_nvalue(start, end, argv, MAX_ARGS);
 807      CHECK_ARGN_GE(0);
 808      cff_dict_add(font->private[0], key, argn);
 809      while (argn-- > 0) {
 810	cff_dict_set(font->private[0], key, argn,
 811		     (argn == 0) ? argv[argn] : argv[argn] - argv[argn-1]);
 812      }
 813    } else if (!strcmp(key, "StdHW") ||
 814	       !strcmp(key, "StdVW") ||
 815	       !strcmp(key, "BlueScale") ||
 816	       !strcmp(key, "BlueShift") ||
 817	       !strcmp(key, "BlueFuzz")  ||
 818	       !strcmp(key, "LanguageGroup") ||
 819	       !strcmp(key, "ExpansionFactor")) {
 820      /*
 821       * Value of StdHW and StdVW is described as an array in the
 822       * Type 1 Font Specification but is a number in CFF format.
 823       */
 824      argn = parse_nvalue(start, end, argv, 1);
 825      CHECK_ARGN_EQ(1);
 826      cff_dict_add(font->private[0], key, 1);
 827      cff_dict_set(font->private[0], key, 0, argv[0]);
 828    } else if (!strcmp(key, "ForceBold")) {
 829      argn = parse_bvalue(start, end, &(argv[0]));
 830      CHECK_ARGN_EQ(1);
 831      if (argv[0] != 0) {
 832	cff_dict_add(font->private[0], key, 1);
 833	cff_dict_set(font->private[0], key, 0, 1);
 834      }
 835    }
 836    /*
 837     * MinFeature, RndStemUp, UniqueID, Password ignored.
 838     */
 839    RELEASE(key);
 840  }
 841
 842  return 0;
 843}
 844
 845#ifndef TYPE1_NAME_LEN_MAX
 846#define TYPE1_NAME_LEN_MAX 127
 847#endif
 848
 849static long
 850parse_part1 (cff_font *font, char **enc_vec,
 851	     unsigned char **start, unsigned char *end, int mode)
 852{
 853  char  *key, *strval;
 854  double argv[MAX_ARGS];
 855  int    argn; /* Macro CHECK_ARGN_XX assume 'argn' is used. */
 856
 857  /*
 858   * We skip PostScript code inserted before the beginning of 
 859   * font dictionary so that parser will not be confused with
 860   * it. See LMRoman10-Regular (lmr10.pfb) for example.
 861   */
 862  if (seek_operator(start, end, "begin") < 0)
 863    return -1;
 864
 865  while (*start < end &&
 866	 (key = get_next_key(start, end)) != NULL) {
 867    if (!strcmp(key, "Encoding")) {
 868      if (parse_encoding(enc_vec, start, end, mode) < 0) {
 869	RELEASE(key);
 870	return -1;
 871      }
 872    } else if (!strcmp(key, "FontName")) {
 873      argn = parse_svalue(start, end, &strval);
 874      CHECK_ARGN_EQ(1);
 875      if (strlen(strval) > TYPE1_NAME_LEN_MAX) {
 876	WARN("FontName too long: %s (%d bytes)", strval, strlen(strval));
 877	strval[TYPE1_NAME_LEN_MAX] = '\0';
 878      }
 879      cff_set_name(font, strval);
 880      RELEASE(strval);
 881    } else if (!strcmp(key, "FontType")) {
 882      argn = parse_nvalue(start, end, argv, 1);
 883      CHECK_ARGN_EQ(1);
 884      if (argv[0] != 1.0) {
 885	WARN("FontType %d not supported.", (int) argv[0]);
 886	RELEASE(key);
 887	return -1;
 888      }
 889#if 0
 890      /* DISABLED:
 891       *
 892       * Subsetted font shouldn't have UniqueID.
 893       */
 894    } else if (!strcmp(key, "UniqueID")) {
 895      argn = parse_nvalue(start, end, argv, 1);
 896      CHECK_ARGN_EQ(1);
 897      cff_dict_add(font->topdict, key, 1);
 898      cff_dict_set(font->topdict, key, 0, argv[0]);
 899#endif
 900    } else if (!strcmp(key, "ItalicAngle") ||
 901	       !strcmp(key, "StrokeWidth") ||
 902	       !strcmp(key, "PaintType")) {
 903      argn = parse_nvalue(start, end, argv, 1);
 904      CHECK_ARGN_EQ(1);
 905      if (argv[0] != 0.0) {
 906#if 0
 907	/*
 908	 * Positive value in Bitstream CharterBT-Italic ???
 909	 */
 910	if (!strcmp(key, "ItalicAngle") && argv[0] > 0) {
 911	  WARN("Positive ItalicAngle value: %g", argv[0]);
 912	  argv[0] *= -1;
 913	}
 914#endif
 915	cff_dict_add(font->topdict, key, 1);
 916	cff_dict_set(font->topdict, key, 0, argv[0]);
 917      }
 918    } else if (!strcmp(key, "UnderLinePosition") ||
 919	       !strcmp(key, "UnderLineThickness")) {
 920      argn = parse_nvalue(start, end, argv, 1);
 921      CHECK_ARGN_EQ(1);
 922      cff_dict_add(font->topdict, key, 1);
 923      cff_dict_set(font->topdict, key, 0, argv[0]);
 924    } else if (!strcmp(key, "FontBBox")) {
 925      argn = parse_nvalue(start, end, argv, 4);
 926      CHECK_ARGN_EQ(4);
 927      cff_dict_add(font->topdict, key, 4);
 928      while (argn-- > 0) {
 929	cff_dict_set(font->topdict, key, argn, argv[argn]);
 930      }
 931    } else if (!strcmp(key, "FontMatrix")) {
 932      argn = parse_nvalue(start, end, argv, 6);
 933      CHECK_ARGN_EQ(6);
 934      if (argv[0] != 0.001 || argv[1] != 0.0 || argv[2] != 0.0 ||
 935	  argv[3] != 0.001 || argv[4] != 0.0 || argv[5] != 0.0) {
 936	cff_dict_add(font->topdict, key, 6);
 937	while (argn-- > 0) {
 938	  cff_dict_set(font->topdict, key, argn, argv[argn]);
 939	}
 940      }
 941    } else if (!strcmp(key, "version")  || !strcmp(key, "Notice") ||
 942	       !strcmp(key, "FullName") || !strcmp(key, "FamilyName") ||
 943	       !strcmp(key, "Weight")   || !strcmp(key, "Copyright")) {
 944      /*
 945       * FontInfo
 946       */
 947      argn = parse_svalue(start, end, &strval);
 948      CHECK_ARGN_EQ(1);
 949      {
 950	s_SID sid;
 951
 952	cff_dict_add(font->topdict, key, 1);
 953	if ((sid = cff_get_sid(font, strval)) == CFF_STRING_NOTDEF)
 954	  sid = cff_add_string(font, strval, 0); /* FIXME */
 955	/*
 956	 * We don't care about duplicate strings here since
 957	 * later a subset font of this font will be generated.
 958	 */
 959	cff_dict_set(font->topdict, key, 0, sid);
 960      }
 961      RELEASE(strval);
 962    } else if (!strcmp(key, "IsFixedPitch")) {
 963      argn = parse_bvalue(start, end, &(argv[0]));
 964      CHECK_ARGN_EQ(1);
 965      if (argv[0] != 0.0) {
 966	cff_dict_add(font->private[0], key, 1);
 967	cff_dict_set(font->private[0], key, 0, 1);
 968      }
 969    }
 970    RELEASE(key);
 971  }
 972
 973  return 0;
 974}
 975
 976int
 977is_pfb (FILE *fp)
 978{
 979  char sig[15];
 980  int i, ch;
 981
 982  rewind(fp);
 983  if ((ch = fgetc(fp)) != 128 ||
 984      (ch = fgetc (fp)) < 0 || ch > 3) {
 985    return 0;
 986  }
 987  for (i = 0; i < 4; i++) {
 988    if ((ch = fgetc(fp)) < 0) {
 989      return 0;
 990    }
 991  }
 992  for (i = 0; i < 14; i++) {
 993    if ((ch = fgetc(fp)) < 0) {
 994      return 0;
 995    }
 996    sig[i] = (char) ch;
 997  }
 998  if (!memcmp(sig, "%!PS-AdobeFont", 14) ||
 999      !memcmp(sig, "%!FontType1", 11)) {
1000    return 1;
1001  } else if (!memcmp(sig, "%!PS", 4)) {
1002    sig[14] = '\0';
1003    WARN("Ambiguous PostScript resource type: %s", sig);
1004    return 1;
1005  } else {
1006    WARN("Not a PFB font file?");
1007    return 0;
1008  }
1009
1010  return 0;
1011}
1012
1013
1014#define PFB_SEG_TYPE_ASCII  1
1015#define PFB_SEG_TYPE_BINARY 2
1016
1017static unsigned char *
1018get_pfb_segment (FILE *fp, int expected_type, long *length)
1019{
1020  unsigned char *buffer;
1021  long bytesread;
1022
1023  buffer = NULL; bytesread = 0;
1024  for (;;) {
1025    int ch;
1026
1027    ch = fgetc(fp);
1028    if (ch < 0) {
1029      break;
1030    } else if (ch != 128) {
1031      ERROR("Not a pfb file?");
1032    }
1033    ch = fgetc(fp);
1034    if (ch < 0 || ch != expected_type) {
1035      seek_relative(fp, -2);
1036      break;
1037    }
1038    {
1039      long slen, rlen;
1040      int  i;
1041
1042      slen = 0;
1043      for (i = 0; i < 4; i++) {
1044	if ((ch = fgetc(fp)) < 0) {
1045	  if (buffer)
1046	    RELEASE(buffer);
1047	  return NULL;
1048	}
1049	slen = slen + (ch << (8*i));
1050      }
1051      buffer = RENEW(buffer, bytesread + slen, unsigned char);
1052      while (slen > 0) {
1053	rlen = fread(buffer + bytesread, sizeof(unsigned char), slen, fp);
1054	if (rlen < 0) {
1055	  if (buffer)
1056	    RELEASE(buffer);
1057	  return NULL;
1058	}
1059	slen -= rlen;
1060	bytesread += rlen;
1061      }
1062    }
1063  }
1064  if (bytesread == 0) {
1065    ERROR("PFB segment length zero?");
1066  }
1067
1068  buffer = RENEW(buffer, bytesread+1, unsigned char);
1069  buffer[bytesread] = 0;
1070
1071  if (length)
1072    *length = bytesread;
1073  return buffer;
1074}
1075
1076char *
1077t1_get_standard_glyph (int code)
1078{
1079  if (!StandardEncoding[code])
1080    return NULL;
1081
1082  return (char *) StandardEncoding[code];
1083}
1084
1085int
1086t1_get_fontname (FILE *fp, char *fontname)
1087{
1088  unsigned char *buffer, *start, *end;
1089  long  length;
1090  char *key;
1091  int   fn_found = 0;
1092
1093  rewind(fp);
1094  buffer = get_pfb_segment(fp, PFB_SEG_TYPE_ASCII, &length);
1095  if (buffer == NULL || length == 0)
1096    ERROR("Reading PFB (ASCII part) file failed.");
1097  start = buffer;
1098  end   = buffer + length;
1099
1100  if (seek_operator(&start, end, "begin") < 0) {
1101    RELEASE(buffer);
1102    return -1;
1103  }
1104
1105  while (!fn_found && start < end &&
1106	 (key = get_next_key(&start, end)) != NULL) {
1107    if (!strcmp(key, "FontName")) {
1108      char *strval;
1109      if (parse_svalue(&start, end, &strval) == 1) {
1110	if (strlen(strval) > TYPE1_NAME_LEN_MAX) {
1111	  WARN("FontName \"%s\" too long. (%d bytes)", strval, strlen(strval));
1112	  strval[TYPE1_NAME_LEN_MAX] = '\0';
1113	}
1114	strcpy(fontname, strval);
1115	RELEASE(strval);
1116	fn_found = 1;
1117      }
1118    }
1119    RELEASE(key);
1120  }
1121  RELEASE(buffer);
1122
1123  return 0;
1124}
1125
1126static void
1127init_cff_font (cff_font *cff)
1128{
1129  cff->stream = NULL;
1130  cff->filter = 0;
1131  cff->fontname = NULL;
1132  cff->index    = 0;
1133  cff->flag = FONTTYPE_FONT;
1134
1135  cff->header.major = 1;
1136  cff->header.minor = 0;
1137  cff->header.hdr_size = 4;
1138  cff->header.offsize  = 4;
1139  cff->name     = cff_new_index(1);
1140  cff->topdict  = cff_new_dict();
1141  cff->string   = NULL;
1142  cff->gsubr    = cff_new_index(0); /* No Global Subr */
1143  cff->encoding = NULL;
1144  cff->charsets = NULL;
1145  cff->fdselect = NULL;
1146  cff->cstrings = NULL;
1147  cff->fdarray  = NULL;
1148  cff->private  = NEW(1, cff_dict *);
1149  cff->private[0] = cff_new_dict();
1150  cff->subrs = NEW(1, cff_index *);
1151  cff->subrs[0] = NULL;
1152
1153  cff->offset  = 0;
1154  cff->gsubr_offset = 0;
1155  cff->num_glyphs   = 0;
1156  cff->num_fds      = 1;
1157  cff->_string = cff_new_index(0);
1158}
1159
1160cff_font *
1161t1_load_font (char **enc_vec, int mode, FILE *fp)
1162{
1163  long length;
1164  cff_font *cff;
1165  unsigned char *buffer, *start, *end;
1166
1167  rewind(fp);
1168  /* ASCII section */
1169  buffer = get_pfb_segment(fp, PFB_SEG_TYPE_ASCII, &length);
1170  if (buffer == NULL || length == 0) {
1171    ERROR("Reading PFB (ASCII part) file failed.");
1172    return NULL;
1173  }
1174
1175  cff = NEW(1, cff_font);
1176  init_cff_font(cff);
1177
1178  start = buffer; end = buffer + length;
1179  if (parse_part1(cff, enc_vec, &start, end, mode) < 0) {
1180    cff_close(cff);
1181    RELEASE(buffer);
1182    ERROR("Reading PFB (ASCII part) file failed.");
1183    return NULL;
1184  }
1185  RELEASE(buffer);
1186
1187  /* Binary section */
1188  buffer = get_pfb_segment(fp, PFB_SEG_TYPE_BINARY, &length);
1189  if (buffer == NULL || length == 0) {
1190    cff_close(cff);
1191    RELEASE(buffer);
1192    ERROR("Reading PFB (BINARY part) file failed.");
1193    return NULL;
1194  } else {
1195    t1_decrypt(T1_EEKEY, buffer, buffer, 0, length);
1196  }
1197  start = buffer + 4; end = buffer + length;
1198  if (parse_part2(cff, &start, end, mode) < 0) {
1199    cff_close(cff);
1200    RELEASE(buffer);
1201    ERROR("Reading PFB (BINARY part) file failed.");
1202    return NULL;
1203  }
1204  RELEASE(buffer);
1205
1206  cff_update_string(cff);
1207
1208  /* Remaining section ignored. */
1209
1210  return cff;
1211}