~ubuntu-branches/ubuntu/utopic/texlive-bin/utopic

« back to all changes in this revision

Viewing changes to texk/dvipdfmx/dvipdfmx-20110311/src/cff_dict.c

  • Committer: Package Import Robot
  • Author(s): Norbert Preining
  • Date: 2012-05-07 10:47:49 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20120507104749-p00ot5sajjbkp1hp
Tags: 2011.20120507-1
* new upstream checkout: uptex 1.10
* drop patches for config file inclusion in (x)dvipdfmx, included upstream
* add man page for etex
* include pmpost patches and build it
* adapt/unfuzzify patches for current sources
* disable mtx building, we have prepmx package in Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  $Header: /home/cvsroot/dvipdfmx/src/cff_dict.c,v 1.18 2011/03/06 03:14:13 chofchof Exp $
2
 
    
3
 
    This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
4
 
 
5
 
    Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata,
6
 
    the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
7
 
    
8
 
    This program is free software; you can redistribute it and/or modify
9
 
    it under the terms of the GNU General Public License as published by
10
 
    the Free Software Foundation; either version 2 of the License, or
11
 
    (at your option) any later version.
12
 
    
13
 
    This program is distributed in the hope that it will be useful,
14
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
    GNU General Public License for more details.
17
 
    
18
 
    You should have received a copy of the GNU General Public License
19
 
    along with this program; if not, write to the Free Software
20
 
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21
 
*/
22
 
 
23
 
/*
24
 
 * CFF Font Dictionary
25
 
 *
26
 
 *  Adobe Technical Note #5176 "The Compact Font Format Specification"
27
 
 */
28
 
 
29
 
#include <math.h>
30
 
#include <stdlib.h>
31
 
#include <errno.h>
32
 
 
33
 
#include "error.h"
34
 
#include "mem.h"
35
 
 
36
 
#ifndef CFF_DEBUG_STR
37
 
#define CFF_DEBUG_STR "CFF"
38
 
#define CFF_DEBUG     5
39
 
#endif
40
 
 
41
 
/* work_buffer for get_real() */
42
 
#include "mfileio.h"
43
 
 
44
 
#include "cff_types.h"
45
 
#include "cff_limits.h"
46
 
 
47
 
/* #include "cff_string.h" */
48
 
#include "cff_dict.h"
49
 
/* cff_update_dict requires this. */
50
 
#include "cff.h"
51
 
 
52
 
#define CFF_PARSE_OK                0
53
 
#define CFF_ERROR_PARSE_ERROR      -1
54
 
#define CFF_ERROR_STACK_OVERFLOW   -2
55
 
#define CFF_ERROR_STACK_UNDERFLOW  -3
56
 
#define CFF_ERROR_STACK_RANGECHECK -4
57
 
 
58
 
#define DICT_ENTRY_MAX 16
59
 
cff_dict *cff_new_dict (void)
60
 
{
61
 
  cff_dict *dict;
62
 
 
63
 
  dict = NEW(1, cff_dict);
64
 
  dict->max     = DICT_ENTRY_MAX;
65
 
  dict->count   = 0;
66
 
  dict->entries = NEW(dict->max, cff_dict_entry);
67
 
 
68
 
  return dict;
69
 
}
70
 
 
71
 
void cff_release_dict (cff_dict *dict)
72
 
{
73
 
  if (dict) {
74
 
    if (dict->entries) {
75
 
      int i;
76
 
      for (i=0;i<dict->count;i++) {
77
 
        if ((dict->entries)[i].values)
78
 
          RELEASE((dict->entries)[i].values);
79
 
      }
80
 
      RELEASE(dict->entries);
81
 
    }
82
 
  RELEASE(dict);
83
 
  }
84
 
}
85
 
 
86
 
/*
87
 
 * Operand stack:
88
 
 *  only numbers are stored (as double)
89
 
 *
90
 
 * Operand types:
91
 
 *
92
 
 * number : double (integer or real)
93
 
 * boolean: stored as a number
94
 
 * SID    : stored as a number
95
 
 * array  : array of numbers
96
 
 * delta  : array of numbers
97
 
 */
98
 
 
99
 
#define CFF_DICT_STACK_LIMIT 64
100
 
static int    stack_top = 0;
101
 
static double arg_stack[CFF_DICT_STACK_LIMIT];
102
 
 
103
 
/*
104
 
 * CFF DICT encoding:
105
 
 * TODO: default values
106
 
 */
107
 
 
108
 
#define CFF_LAST_DICT_OP1 22
109
 
#define CFF_LAST_DICT_OP2 39
110
 
#define CFF_LAST_DICT_OP (CFF_LAST_DICT_OP1 + CFF_LAST_DICT_OP2)
111
 
 
112
 
static struct {
113
 
  const char *opname;
114
 
  int   argtype;
115
 
} dict_operator[CFF_LAST_DICT_OP] = {
116
 
  {"version",     CFF_TYPE_SID},
117
 
  {"Notice",      CFF_TYPE_SID},
118
 
  {"FullName",    CFF_TYPE_SID},
119
 
  {"FamilyName",  CFF_TYPE_SID},
120
 
  {"Weight",      CFF_TYPE_SID},
121
 
  {"FontBBox",    CFF_TYPE_ARRAY},
122
 
  {"BlueValues",       CFF_TYPE_DELTA},
123
 
  {"OtherBlues",       CFF_TYPE_DELTA},
124
 
  {"FamilyBlues",      CFF_TYPE_DELTA},
125
 
  {"FamilyOtherBlues", CFF_TYPE_DELTA},
126
 
  {"StdHW",            CFF_TYPE_NUMBER},
127
 
  {"StdVW",            CFF_TYPE_NUMBER},
128
 
  {NULL, -1},  /* first byte of two-byte operator */
129
 
  /* Top */
130
 
  {"UniqueID",    CFF_TYPE_NUMBER},
131
 
  {"XUID",        CFF_TYPE_ARRAY},
132
 
  {"charset",     CFF_TYPE_OFFSET},
133
 
  {"Encoding",    CFF_TYPE_OFFSET},
134
 
  {"CharStrings", CFF_TYPE_OFFSET},
135
 
  {"Private",     CFF_TYPE_SZOFF}, /* two numbers (size and offset) */
136
 
  /* Private */
137
 
  {"Subrs",         CFF_TYPE_OFFSET},
138
 
  {"defaultWidthX", CFF_TYPE_NUMBER},
139
 
  {"nominalWidthX", CFF_TYPE_NUMBER},
140
 
  /* Operator 2 */
141
 
  {"Copyright",          CFF_TYPE_SID},
142
 
  {"IsFixedPitch",       CFF_TYPE_BOOLEAN},
143
 
  {"ItalicAngle",        CFF_TYPE_NUMBER},
144
 
  {"UnderlinePosition",  CFF_TYPE_NUMBER},
145
 
  {"UnderlineThickness", CFF_TYPE_NUMBER},
146
 
  {"PaintType",      CFF_TYPE_NUMBER},
147
 
  {"CharstringType", CFF_TYPE_NUMBER},
148
 
  {"FontMatrix",     CFF_TYPE_ARRAY},
149
 
  {"StrokeWidth",    CFF_TYPE_NUMBER},
150
 
  {"BlueScale", CFF_TYPE_NUMBER},
151
 
  {"BlueShift", CFF_TYPE_NUMBER},
152
 
  {"BlueFuzz",  CFF_TYPE_NUMBER},
153
 
  {"StemSnapH", CFF_TYPE_DELTA},
154
 
  {"StemSnapV", CFF_TYPE_DELTA},
155
 
  {"ForceBold", CFF_TYPE_BOOLEAN},
156
 
  {NULL, -1},
157
 
  {NULL, -1},
158
 
  {"LanguageGroup",     CFF_TYPE_NUMBER},
159
 
  {"ExpansionFactor",   CFF_TYPE_NUMBER},
160
 
  {"InitialRandomSeed", CFF_TYPE_NUMBER},
161
 
  {"SyntheticBase", CFF_TYPE_NUMBER},
162
 
  {"PostScript",    CFF_TYPE_SID},
163
 
  {"BaseFontName",  CFF_TYPE_SID},
164
 
  {"BaseFontBlend", CFF_TYPE_DELTA}, /* MMaster ? */
165
 
  {NULL, -1},
166
 
  {NULL, -1},
167
 
  {NULL, -1},
168
 
  {NULL, -1},
169
 
  {NULL, -1},
170
 
  {NULL, -1},
171
 
  /* CID-Keyed font */
172
 
  {"ROS",             CFF_TYPE_ROS}, /* SID SID number */
173
 
  {"CIDFontVersion",  CFF_TYPE_NUMBER},
174
 
  {"CIDFontRevision", CFF_TYPE_NUMBER},
175
 
  {"CIDFontType",     CFF_TYPE_NUMBER},
176
 
  {"CIDCount",        CFF_TYPE_NUMBER},
177
 
  {"UIDBase",         CFF_TYPE_NUMBER},
178
 
  {"FDArray",         CFF_TYPE_OFFSET},
179
 
  {"FDSelect",        CFF_TYPE_OFFSET},
180
 
  {"FontName",        CFF_TYPE_SID},
181
 
};
182
 
 
183
 
/* Parse DICT data */
184
 
static double get_integer (card8 **data, card8 *endptr, int *status)
185
 
{
186
 
  long result = 0;
187
 
  card8 b0, b1, b2;
188
 
 
189
 
  b0 = *(*data)++;
190
 
  if (b0 == 28 && *data < endptr - 2) { /* shortint */
191
 
    b1 = *(*data)++;
192
 
    b2 = *(*data)++;
193
 
    result = b1*256+b2;
194
 
    if (result > 0x7fffL)
195
 
      result -= 0x10000L;
196
 
  } else if (b0 == 29 && *data < endptr - 4) { /* longint */
197
 
    int i;
198
 
    result = *(*data)++;
199
 
    if (result > 0x7f)
200
 
      result -= 0x100;
201
 
    for (i=0;i<3;i++) {
202
 
      result = result*256+(**data);
203
 
      *data += 1;
204
 
    }
205
 
  } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
206
 
    result = b0 - 139;
207
 
  } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
208
 
    b1 = *(*data)++;
209
 
    result = (b0-247)*256+b1+108;
210
 
  } else if (b0 >= 251 && b0 <= 254) {
211
 
    b1 = *(*data)++;
212
 
    result = -(b0-251)*256-b1-108;
213
 
  } else {
214
 
    *status = CFF_ERROR_PARSE_ERROR;
215
 
  }
216
 
 
217
 
  return (double) result;
218
 
}
219
 
 
220
 
/* Simply uses strtod */
221
 
static double get_real(card8 **data, card8 *endptr, int *status)
222
 
{
223
 
  double result = 0.0;
224
 
  int nibble = 0, pos = 0;
225
 
  int len = 0, fail = 0;
226
 
 
227
 
  if (**data != 30 || *data >= endptr -1) {
228
 
    *status = CFF_ERROR_PARSE_ERROR;
229
 
    return 0.0;
230
 
  }
231
 
 
232
 
  *data += 1; /* skip first byte (30) */
233
 
 
234
 
  pos = 0;
235
 
  while ((! fail) && len < WORK_BUFFER_SIZE - 2 && *data < endptr) {
236
 
    /* get nibble */
237
 
    if (pos % 2) {
238
 
      nibble = **data & 0x0f;
239
 
      *data += 1;
240
 
    } else {
241
 
      nibble = (**data >> 4) & 0x0f;
242
 
    }
243
 
    if (nibble >= 0x00 && nibble <= 0x09) {
244
 
      work_buffer[len++] = nibble + '0';
245
 
    } else if (nibble == 0x0a) { /* . */
246
 
      work_buffer[len++] = '.';
247
 
    } else if (nibble == 0x0b || nibble == 0x0c) { /* E, E- */
248
 
      work_buffer[len++] = 'e';
249
 
      if (nibble == 0x0c)
250
 
        work_buffer[len++] = '-';
251
 
    } else if (nibble == 0x0e) { /* `-' */
252
 
      work_buffer[len++] = '-';
253
 
    } else if (nibble == 0x0d) { /* skip */
254
 
      /* do nothing */
255
 
    } else if (nibble == 0x0f) { /* end */
256
 
      work_buffer[len++] = '\0';
257
 
      if (((pos % 2) == 0) && (**data != 0xff)) {
258
 
        fail = 1;
259
 
      }
260
 
      break;
261
 
    } else { /* invalid */
262
 
      fail = 1;
263
 
    }
264
 
    pos++;
265
 
  }
266
 
 
267
 
  /* returned values */
268
 
  if (fail || nibble != 0x0f) {
269
 
    *status = CFF_ERROR_PARSE_ERROR;
270
 
  } else {
271
 
    char *s;
272
 
    result = strtod(work_buffer, &s);
273
 
    if (*s != 0 || errno == ERANGE) {
274
 
      *status = CFF_ERROR_PARSE_ERROR;
275
 
    }
276
 
  }
277
 
 
278
 
  return result;
279
 
}
280
 
 
281
 
/* operators */
282
 
static void add_dict (cff_dict *dict,
283
 
                      card8 **data, card8 *endptr, int *status)
284
 
{
285
 
  int id, argtype;
286
 
 
287
 
  id = **data;
288
 
  if (id == 0x0c) {
289
 
    *data += 1;
290
 
    if (*data >= endptr ||
291
 
        (id = **data + CFF_LAST_DICT_OP1) >= CFF_LAST_DICT_OP) {
292
 
      *status = CFF_ERROR_PARSE_ERROR;
293
 
      return;
294
 
    }
295
 
  } else if (id >= CFF_LAST_DICT_OP1) {
296
 
    *status = CFF_ERROR_PARSE_ERROR;
297
 
    return;
298
 
  }
299
 
 
300
 
  argtype = dict_operator[id].argtype;
301
 
  if (dict_operator[id].opname == NULL || argtype < 0) {
302
 
    *status = CFF_ERROR_PARSE_ERROR;
303
 
    return;
304
 
  } else if (stack_top < 1) {
305
 
    *status = CFF_ERROR_STACK_UNDERFLOW;
306
 
    return;
307
 
  }
308
 
 
309
 
  if (dict->count >= dict->max) {
310
 
    dict->max += DICT_ENTRY_MAX;
311
 
    dict->entries = RENEW(dict->entries, dict->max, cff_dict_entry);
312
 
  }
313
 
 
314
 
  (dict->entries)[dict->count].id = id;
315
 
  (dict->entries)[dict->count].key = dict_operator[id].opname;
316
 
  if (argtype == CFF_TYPE_NUMBER ||
317
 
      argtype == CFF_TYPE_BOOLEAN ||
318
 
      argtype == CFF_TYPE_SID ||
319
 
      argtype == CFF_TYPE_OFFSET) {
320
 
    stack_top--;
321
 
    (dict->entries)[dict->count].count  = 1;
322
 
    (dict->entries)[dict->count].values = NEW(1, double);
323
 
    (dict->entries)[dict->count].values[0] = arg_stack[stack_top];
324
 
  } else {
325
 
    (dict->entries)[dict->count].count  = stack_top;
326
 
    (dict->entries)[dict->count].values = NEW(stack_top, double);
327
 
    while (stack_top > 0) {
328
 
      stack_top--;
329
 
      (dict->entries)[dict->count].values[stack_top] = arg_stack[stack_top];
330
 
    }
331
 
  }
332
 
 
333
 
  dict->count += 1;
334
 
  *data += 1;
335
 
 
336
 
  return;
337
 
}
338
 
 
339
 
/*
340
 
 * All operands are treated as number or array of numbers.
341
 
 *  Private: two numbers, size and offset
342
 
 *  ROS    : three numbers, SID, SID, and a number
343
 
 */
344
 
cff_dict *cff_dict_unpack (card8 *data, card8 *endptr)
345
 
{
346
 
  cff_dict *dict;
347
 
  int status = CFF_PARSE_OK;
348
 
 
349
 
  stack_top = 0;
350
 
 
351
 
  dict = cff_new_dict();
352
 
  while (data < endptr && status == CFF_PARSE_OK) {
353
 
    if (*data < 22) { /* operator */
354
 
      add_dict(dict, &data, endptr, &status);
355
 
    } else if (*data == 30) { /* real - First byte of a sequence (variable) */
356
 
      if (stack_top < CFF_DICT_STACK_LIMIT) {
357
 
        arg_stack[stack_top] = get_real(&data, endptr, &status);
358
 
        stack_top++;
359
 
      } else {
360
 
        status = CFF_ERROR_STACK_OVERFLOW;
361
 
      }
362
 
    } else if (*data == 255 || (*data >= 22 && *data <= 27)) { /* reserved */
363
 
      data++;
364
 
    } else { /* everything else are integer */
365
 
      if (stack_top < CFF_DICT_STACK_LIMIT) {
366
 
        arg_stack[stack_top] = get_integer(&data, endptr, &status);
367
 
        stack_top++;
368
 
      } else {
369
 
        status = CFF_ERROR_STACK_OVERFLOW;
370
 
      }
371
 
    }
372
 
  }
373
 
 
374
 
  if (status != CFF_PARSE_OK) {
375
 
    ERROR("%s: Parsing CFF DICT failed. (error=%d)", CFF_DEBUG_STR, status);
376
 
  } else if (stack_top != 0) {
377
 
    WARN("%s: Garbage in CFF DICT data.", CFF_DEBUG_STR);
378
 
    stack_top = 0;
379
 
  }
380
 
 
381
 
  return dict;
382
 
}
383
 
 
384
 
/* Pack DICT data */
385
 
static long pack_integer (card8 *dest, long destlen, long value)
386
 
{
387
 
  long len = 0;
388
 
 
389
 
  if (value >= -107 && value <= 107) {
390
 
    if (destlen < 1)
391
 
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
392
 
    dest[0] = (value + 139) & 0xff;
393
 
    len = 1;
394
 
  } else if (value >= 108 && value <= 1131) {
395
 
    if (destlen < 2)
396
 
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
397
 
    value = 0xf700u + value - 108;
398
 
    dest[0] = (value >> 8) & 0xff;
399
 
    dest[1] = value & 0xff;
400
 
    len = 2;
401
 
  } else if (value >= -1131 && value <= -108) {
402
 
    if (destlen < 2)
403
 
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
404
 
    value = 0xfb00u - value - 108;
405
 
    dest[0] = (value >> 8) & 0xff;
406
 
    dest[1] = value & 0xff;
407
 
    len = 2;
408
 
  } else if (value >= -32768 && value <= 32767) { /* shortint */
409
 
    if (destlen < 3)
410
 
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
411
 
    dest[0] = 28;
412
 
    dest[1] = (value >> 8) & 0xff;
413
 
    dest[2] = value & 0xff;
414
 
    len = 3;
415
 
  } else { /* longint */
416
 
    if (destlen < 5)
417
 
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
418
 
    dest[0] = 29;
419
 
    dest[1] = (value >> 24) & 0xff;
420
 
    dest[2] = (value >> 16) & 0xff;
421
 
    dest[3] = (value >> 8) & 0xff;
422
 
    dest[4] = value & 0xff;
423
 
    len = 5;
424
 
  }
425
 
 
426
 
  return len;
427
 
}
428
 
 
429
 
static long pack_real (card8 *dest, long destlen, double value)
430
 
{
431
 
  int i = 0, pos = 2;
432
 
  char buffer[32];
433
 
 
434
 
  if (destlen < 2)
435
 
    ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
436
 
 
437
 
  dest[0] = 30;
438
 
 
439
 
  if (value == 0.0) {
440
 
    dest[1] = 0x0f;
441
 
    return 2;
442
 
  }
443
 
 
444
 
  if (value < 0.0) {
445
 
    dest[1] = 0xe0;
446
 
    value *= -1.0;
447
 
    pos++;
448
 
  }
449
 
 
450
 
  /* To avoid the problem with Mac OS X 10.4 Quartz,
451
 
   * change the presion of the real numbers
452
 
   * on June 27, 2007 for musix20.pfb */
453
 
  sprintf(buffer, "%.13g", value);
454
 
 
455
 
  for (i = 0; buffer[i] != '\0'; i++) {
456
 
    unsigned char ch = 0;
457
 
    if (buffer[i] == '.') {
458
 
      ch = 0x0a;
459
 
    } else if (buffer[i] >= '0' && buffer[i] <= '9') {
460
 
      ch = buffer[i] - '0';
461
 
    } else if (buffer[i] == 'e') {
462
 
      ch = (buffer[++i] == '-' ? 0x0c : 0x0b);
463
 
    } else {
464
 
      ERROR("%s: Invalid character.", CFF_DEBUG_STR);
465
 
    }
466
 
 
467
 
    if (destlen < pos/2 + 1)
468
 
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
469
 
 
470
 
    if (pos % 2) {
471
 
      dest[pos/2] += ch;
472
 
    } else {
473
 
      dest[pos/2] = (ch << 4);
474
 
    }
475
 
    pos++;
476
 
  }
477
 
 
478
 
  if (pos % 2) {
479
 
    dest[pos/2] += 0x0f;
480
 
    pos++;
481
 
  } else {
482
 
    if (destlen < pos/2 + 1)
483
 
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
484
 
    dest[pos/2] = 0xff;
485
 
    pos += 2;
486
 
  }
487
 
 
488
 
  return pos/2;
489
 
}
490
 
 
491
 
static long cff_dict_put_number (double value,
492
 
                                 card8 *dest, long destlen,
493
 
                                 int type)
494
 
{
495
 
  long   len = 0;
496
 
  double nearint;
497
 
 
498
 
  nearint = floor(value+0.5);
499
 
  /* set offset to longint */
500
 
  if (type == CFF_TYPE_OFFSET) {
501
 
    long lvalue;
502
 
 
503
 
    lvalue = (long) value;
504
 
    if (destlen < 5)
505
 
      ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
506
 
    dest[0] = 29;
507
 
    dest[1] = (lvalue >> 24) & 0xff;
508
 
    dest[2] = (lvalue >> 16) & 0xff;
509
 
    dest[3] = (lvalue >>  8) & 0xff;
510
 
    dest[4] = lvalue         & 0xff;
511
 
    len = 5;
512
 
  } else if (value > CFF_INT_MAX || value < CFF_INT_MIN ||
513
 
             (fabs(value - nearint) > 1.0e-5)) { /* real */
514
 
    len = pack_real(dest, destlen, value);
515
 
  } else { /* integer */
516
 
    len = pack_integer(dest, destlen, (long) nearint);
517
 
  }
518
 
 
519
 
  return len;
520
 
}
521
 
 
522
 
static long
523
 
put_dict_entry (cff_dict_entry *de,
524
 
                card8 *dest, long destlen)
525
 
{
526
 
  long len = 0;
527
 
  int  i, type, id;
528
 
 
529
 
  if (de->count > 0) {
530
 
    id = de->id;
531
 
    if (dict_operator[id].argtype == CFF_TYPE_OFFSET ||
532
 
        dict_operator[id].argtype == CFF_TYPE_SZOFF) {
533
 
      type = CFF_TYPE_OFFSET;
534
 
    } else {
535
 
      type = CFF_TYPE_NUMBER;
536
 
    }
537
 
    for (i = 0; i < de->count; i++) {
538
 
      len += cff_dict_put_number(de->values[i],
539
 
                                 dest+len,
540
 
                                 destlen-len, type);
541
 
    }
542
 
    if (id >= 0 && id < CFF_LAST_DICT_OP1) {
543
 
      if (len + 1 > destlen)
544
 
        ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
545
 
      dest[len++] = id;
546
 
    } else if (id >= 0 && id < CFF_LAST_DICT_OP) {
547
 
      if (len + 2 > destlen)
548
 
        ERROR("in cff_dict_pack(): Buffer overflow");
549
 
      dest[len++] = 12;
550
 
      dest[len++] = id - CFF_LAST_DICT_OP1;
551
 
    } else {
552
 
      ERROR("%s: Invalid CFF DICT operator ID.", CFF_DEBUG_STR);
553
 
    }
554
 
  }
555
 
 
556
 
  return len;
557
 
}
558
 
 
559
 
long cff_dict_pack (cff_dict *dict, card8 *dest, long destlen)
560
 
{
561
 
  long len = 0;
562
 
  int  i;
563
 
 
564
 
  for (i = 0; i < dict->count; i++) {
565
 
    if (!strcmp(dict->entries[i].key, "ROS")) {
566
 
      len += put_dict_entry(&dict->entries[i], dest, destlen);
567
 
      break;
568
 
    }
569
 
  }
570
 
  for (i = 0; i < dict->count; i++) {
571
 
    if (strcmp(dict->entries[i].key, "ROS")) {
572
 
      len += put_dict_entry(&dict->entries[i], dest+len, destlen-len);
573
 
    }
574
 
  }
575
 
 
576
 
  return len;
577
 
}
578
 
 
579
 
void cff_dict_add (cff_dict *dict, const char *key, int count)
580
 
{
581
 
  int id, i;
582
 
 
583
 
  for (id=0;id<CFF_LAST_DICT_OP;id++) {
584
 
    if (key && dict_operator[id].opname &&
585
 
        strcmp(dict_operator[id].opname, key) == 0)
586
 
      break;
587
 
  }
588
 
 
589
 
  if (id == CFF_LAST_DICT_OP)
590
 
    ERROR("%s: Unknown CFF DICT operator.", CFF_DEBUG_STR);
591
 
 
592
 
  for (i=0;i<dict->count;i++) {
593
 
    if ((dict->entries)[i].id == id) {
594
 
      if ((dict->entries)[i].count != count)
595
 
        ERROR("%s: Inconsistent DICT argument number.", CFF_DEBUG_STR);
596
 
      return;
597
 
    }
598
 
  }
599
 
 
600
 
  if (dict->count + 1 >= dict->max) {
601
 
    dict->max += 8;
602
 
    dict->entries = RENEW(dict->entries, dict->max, cff_dict_entry);
603
 
  }
604
 
 
605
 
  (dict->entries)[dict->count].id    = id;
606
 
  (dict->entries)[dict->count].key   = dict_operator[id].opname;
607
 
  (dict->entries)[dict->count].count = count;
608
 
  if (count > 0) {
609
 
    (dict->entries)[dict->count].values = NEW(count, double);
610
 
    memset((dict->entries)[dict->count].values,
611
 
           0, sizeof(double)*count);
612
 
  } else {
613
 
    (dict->entries)[dict->count].values = NULL;
614
 
  }
615
 
  dict->count += 1;
616
 
 
617
 
  return;
618
 
}
619
 
 
620
 
void cff_dict_remove (cff_dict *dict, const char *key)
621
 
{
622
 
  int i;
623
 
  for (i = 0; i < dict->count; i++) {
624
 
    if (key && strcmp(key, (dict->entries)[i].key) == 0) {
625
 
      (dict->entries)[i].count = 0;
626
 
      if ((dict->entries)[i].values)
627
 
        RELEASE((dict->entries)[i].values);
628
 
      (dict->entries)[i].values = NULL;
629
 
    }
630
 
  }
631
 
}
632
 
 
633
 
int cff_dict_known (cff_dict *dict, const char *key)
634
 
{
635
 
  int i;
636
 
 
637
 
  for (i = 0; i < dict->count; i++) {
638
 
    if (key && strcmp(key, (dict->entries)[i].key) == 0
639
 
        && (dict->entries)[i].count > 0)
640
 
      return 1;
641
 
  }
642
 
 
643
 
  return 0;
644
 
}
645
 
 
646
 
double cff_dict_get (cff_dict *dict, const char *key, int idx)
647
 
{
648
 
  double value = 0.0;
649
 
  int    i;
650
 
 
651
 
  ASSERT(key && dict);
652
 
 
653
 
  for (i = 0; i < dict->count; i++) {
654
 
    if (strcmp(key, (dict->entries)[i].key) == 0) {
655
 
      if ((dict->entries)[i].count > idx)
656
 
        value = (dict->entries)[i].values[idx];
657
 
      else
658
 
        ERROR("%s: Invalid index number.", CFF_DEBUG_STR);
659
 
      break;
660
 
    }
661
 
  }
662
 
 
663
 
  if (i == dict->count)
664
 
    ERROR("%s: DICT entry \"%s\" not found.", CFF_DEBUG_STR, key);
665
 
 
666
 
  return value;
667
 
}
668
 
 
669
 
void cff_dict_set (cff_dict *dict, const char *key, int idx, double value)
670
 
{
671
 
  int i;
672
 
 
673
 
  ASSERT(dict && key);
674
 
 
675
 
  for (i = 0 ; i < dict->count; i++) {
676
 
    if (strcmp(key, (dict->entries)[i].key) == 0) {
677
 
      if ((dict->entries)[i].count > idx)
678
 
        (dict->entries)[i].values[idx] = value;
679
 
      else
680
 
        ERROR("%s: Invalid index number.", CFF_DEBUG_STR);
681
 
      break;
682
 
    }
683
 
  }
684
 
 
685
 
  if (i == dict->count)
686
 
    ERROR("%s: DICT entry \"%s\" not found.", CFF_DEBUG_STR, key);
687
 
}
688
 
 
689
 
void cff_dict_update (cff_dict *dict, cff_font *cff)
690
 
{
691
 
  int i;
692
 
 
693
 
  for (i = 0;i < dict->count; i++) {
694
 
    if ((dict->entries)[i].count > 0) {
695
 
      char *str;
696
 
      int   id;
697
 
 
698
 
      id = (dict->entries)[i].id;
699
 
      if (dict_operator[id].argtype == CFF_TYPE_SID) {
700
 
        str = cff_get_string(cff, (dict->entries)[i].values[0]);
701
 
        (dict->entries)[i].values[0] = cff_add_string(cff, str, 1);
702
 
        RELEASE(str);
703
 
      } else if (dict_operator[id].argtype == CFF_TYPE_ROS) {
704
 
        str = cff_get_string(cff, (dict->entries)[i].values[0]);
705
 
        (dict->entries)[i].values[0] = cff_add_string(cff, str, 1);
706
 
        RELEASE(str);
707
 
        str = cff_get_string(cff, (dict->entries)[i].values[1]);
708
 
        (dict->entries)[i].values[1] = cff_add_string(cff, str, 1);
709
 
        RELEASE(str);
710
 
      }
711
 
    }
712
 
  }
713
 
}