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

« back to all changes in this revision

Viewing changes to texk/dvipdfmx/dvipdfmx-20120420/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
}