1
/* $Header: /home/cvsroot/dvipdfmx/src/cff_dict.c,v 1.18 2011/03/06 03:14:13 chofchof Exp $
3
This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
5
Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata,
6
the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
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.
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.
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.
26
* Adobe Technical Note #5176 "The Compact Font Format Specification"
37
#define CFF_DEBUG_STR "CFF"
41
/* work_buffer for get_real() */
44
#include "cff_types.h"
45
#include "cff_limits.h"
47
/* #include "cff_string.h" */
49
/* cff_update_dict requires this. */
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
58
#define DICT_ENTRY_MAX 16
59
cff_dict *cff_new_dict (void)
63
dict = NEW(1, cff_dict);
64
dict->max = DICT_ENTRY_MAX;
66
dict->entries = NEW(dict->max, cff_dict_entry);
71
void cff_release_dict (cff_dict *dict)
76
for (i=0;i<dict->count;i++) {
77
if ((dict->entries)[i].values)
78
RELEASE((dict->entries)[i].values);
80
RELEASE(dict->entries);
88
* only numbers are stored (as double)
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
99
#define CFF_DICT_STACK_LIMIT 64
100
static int stack_top = 0;
101
static double arg_stack[CFF_DICT_STACK_LIMIT];
105
* TODO: default values
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)
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 */
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) */
137
{"Subrs", CFF_TYPE_OFFSET},
138
{"defaultWidthX", CFF_TYPE_NUMBER},
139
{"nominalWidthX", CFF_TYPE_NUMBER},
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},
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 ? */
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},
183
/* Parse DICT data */
184
static double get_integer (card8 **data, card8 *endptr, int *status)
190
if (b0 == 28 && *data < endptr - 2) { /* shortint */
194
if (result > 0x7fffL)
196
} else if (b0 == 29 && *data < endptr - 4) { /* longint */
202
result = result*256+(**data);
205
} else if (b0 >= 32 && b0 <= 246) { /* int (1) */
207
} else if (b0 >= 247 && b0 <= 250) { /* int (2) */
209
result = (b0-247)*256+b1+108;
210
} else if (b0 >= 251 && b0 <= 254) {
212
result = -(b0-251)*256-b1-108;
214
*status = CFF_ERROR_PARSE_ERROR;
217
return (double) result;
220
/* Simply uses strtod */
221
static double get_real(card8 **data, card8 *endptr, int *status)
224
int nibble = 0, pos = 0;
225
int len = 0, fail = 0;
227
if (**data != 30 || *data >= endptr -1) {
228
*status = CFF_ERROR_PARSE_ERROR;
232
*data += 1; /* skip first byte (30) */
235
while ((! fail) && len < WORK_BUFFER_SIZE - 2 && *data < endptr) {
238
nibble = **data & 0x0f;
241
nibble = (**data >> 4) & 0x0f;
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';
250
work_buffer[len++] = '-';
251
} else if (nibble == 0x0e) { /* `-' */
252
work_buffer[len++] = '-';
253
} else if (nibble == 0x0d) { /* skip */
255
} else if (nibble == 0x0f) { /* end */
256
work_buffer[len++] = '\0';
257
if (((pos % 2) == 0) && (**data != 0xff)) {
261
} else { /* invalid */
267
/* returned values */
268
if (fail || nibble != 0x0f) {
269
*status = CFF_ERROR_PARSE_ERROR;
272
result = strtod(work_buffer, &s);
273
if (*s != 0 || errno == ERANGE) {
274
*status = CFF_ERROR_PARSE_ERROR;
282
static void add_dict (cff_dict *dict,
283
card8 **data, card8 *endptr, int *status)
290
if (*data >= endptr ||
291
(id = **data + CFF_LAST_DICT_OP1) >= CFF_LAST_DICT_OP) {
292
*status = CFF_ERROR_PARSE_ERROR;
295
} else if (id >= CFF_LAST_DICT_OP1) {
296
*status = CFF_ERROR_PARSE_ERROR;
300
argtype = dict_operator[id].argtype;
301
if (dict_operator[id].opname == NULL || argtype < 0) {
302
*status = CFF_ERROR_PARSE_ERROR;
304
} else if (stack_top < 1) {
305
*status = CFF_ERROR_STACK_UNDERFLOW;
309
if (dict->count >= dict->max) {
310
dict->max += DICT_ENTRY_MAX;
311
dict->entries = RENEW(dict->entries, dict->max, cff_dict_entry);
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) {
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];
325
(dict->entries)[dict->count].count = stack_top;
326
(dict->entries)[dict->count].values = NEW(stack_top, double);
327
while (stack_top > 0) {
329
(dict->entries)[dict->count].values[stack_top] = arg_stack[stack_top];
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
344
cff_dict *cff_dict_unpack (card8 *data, card8 *endptr)
347
int status = CFF_PARSE_OK;
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);
360
status = CFF_ERROR_STACK_OVERFLOW;
362
} else if (*data == 255 || (*data >= 22 && *data <= 27)) { /* reserved */
364
} else { /* everything else are integer */
365
if (stack_top < CFF_DICT_STACK_LIMIT) {
366
arg_stack[stack_top] = get_integer(&data, endptr, &status);
369
status = CFF_ERROR_STACK_OVERFLOW;
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);
385
static long pack_integer (card8 *dest, long destlen, long value)
389
if (value >= -107 && value <= 107) {
391
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
392
dest[0] = (value + 139) & 0xff;
394
} else if (value >= 108 && value <= 1131) {
396
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
397
value = 0xf700u + value - 108;
398
dest[0] = (value >> 8) & 0xff;
399
dest[1] = value & 0xff;
401
} else if (value >= -1131 && value <= -108) {
403
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
404
value = 0xfb00u - value - 108;
405
dest[0] = (value >> 8) & 0xff;
406
dest[1] = value & 0xff;
408
} else if (value >= -32768 && value <= 32767) { /* shortint */
410
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
412
dest[1] = (value >> 8) & 0xff;
413
dest[2] = value & 0xff;
415
} else { /* longint */
417
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
419
dest[1] = (value >> 24) & 0xff;
420
dest[2] = (value >> 16) & 0xff;
421
dest[3] = (value >> 8) & 0xff;
422
dest[4] = value & 0xff;
429
static long pack_real (card8 *dest, long destlen, double value)
435
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
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);
455
for (i = 0; buffer[i] != '\0'; i++) {
456
unsigned char ch = 0;
457
if (buffer[i] == '.') {
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);
464
ERROR("%s: Invalid character.", CFF_DEBUG_STR);
467
if (destlen < pos/2 + 1)
468
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
473
dest[pos/2] = (ch << 4);
482
if (destlen < pos/2 + 1)
483
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
491
static long cff_dict_put_number (double value,
492
card8 *dest, long destlen,
498
nearint = floor(value+0.5);
499
/* set offset to longint */
500
if (type == CFF_TYPE_OFFSET) {
503
lvalue = (long) value;
505
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
507
dest[1] = (lvalue >> 24) & 0xff;
508
dest[2] = (lvalue >> 16) & 0xff;
509
dest[3] = (lvalue >> 8) & 0xff;
510
dest[4] = lvalue & 0xff;
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);
523
put_dict_entry (cff_dict_entry *de,
524
card8 *dest, long destlen)
531
if (dict_operator[id].argtype == CFF_TYPE_OFFSET ||
532
dict_operator[id].argtype == CFF_TYPE_SZOFF) {
533
type = CFF_TYPE_OFFSET;
535
type = CFF_TYPE_NUMBER;
537
for (i = 0; i < de->count; i++) {
538
len += cff_dict_put_number(de->values[i],
542
if (id >= 0 && id < CFF_LAST_DICT_OP1) {
543
if (len + 1 > destlen)
544
ERROR("%s: Buffer overflow.", CFF_DEBUG_STR);
546
} else if (id >= 0 && id < CFF_LAST_DICT_OP) {
547
if (len + 2 > destlen)
548
ERROR("in cff_dict_pack(): Buffer overflow");
550
dest[len++] = id - CFF_LAST_DICT_OP1;
552
ERROR("%s: Invalid CFF DICT operator ID.", CFF_DEBUG_STR);
559
long cff_dict_pack (cff_dict *dict, card8 *dest, long destlen)
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);
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);
579
void cff_dict_add (cff_dict *dict, const char *key, int count)
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)
589
if (id == CFF_LAST_DICT_OP)
590
ERROR("%s: Unknown CFF DICT operator.", CFF_DEBUG_STR);
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);
600
if (dict->count + 1 >= dict->max) {
602
dict->entries = RENEW(dict->entries, dict->max, cff_dict_entry);
605
(dict->entries)[dict->count].id = id;
606
(dict->entries)[dict->count].key = dict_operator[id].opname;
607
(dict->entries)[dict->count].count = count;
609
(dict->entries)[dict->count].values = NEW(count, double);
610
memset((dict->entries)[dict->count].values,
611
0, sizeof(double)*count);
613
(dict->entries)[dict->count].values = NULL;
620
void cff_dict_remove (cff_dict *dict, const char *key)
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;
633
int cff_dict_known (cff_dict *dict, const char *key)
637
for (i = 0; i < dict->count; i++) {
638
if (key && strcmp(key, (dict->entries)[i].key) == 0
639
&& (dict->entries)[i].count > 0)
646
double cff_dict_get (cff_dict *dict, const char *key, int idx)
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];
658
ERROR("%s: Invalid index number.", CFF_DEBUG_STR);
663
if (i == dict->count)
664
ERROR("%s: DICT entry \"%s\" not found.", CFF_DEBUG_STR, key);
669
void cff_dict_set (cff_dict *dict, const char *key, int idx, double value)
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;
680
ERROR("%s: Invalid index number.", CFF_DEBUG_STR);
685
if (i == dict->count)
686
ERROR("%s: DICT entry \"%s\" not found.", CFF_DEBUG_STR, key);
689
void cff_dict_update (cff_dict *dict, cff_font *cff)
693
for (i = 0;i < dict->count; i++) {
694
if ((dict->entries)[i].count > 0) {
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);
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);
707
str = cff_get_string(cff, (dict->entries)[i].values[1]);
708
(dict->entries)[i].values[1] = cff_add_string(cff, str, 1);