Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7639 views
1
#include "mupdf/pdf.h"
2
3
#include "pdf-name-table.h"
4
5
#include <stdarg.h>
6
7
typedef enum pdf_objkind_e
8
{
9
PDF_INT = 'i',
10
PDF_REAL = 'f',
11
PDF_STRING = 's',
12
PDF_NAME = 'n',
13
PDF_ARRAY = 'a',
14
PDF_DICT = 'd',
15
PDF_INDIRECT = 'r'
16
} pdf_objkind;
17
18
struct keyval
19
{
20
pdf_obj *k;
21
pdf_obj *v;
22
};
23
24
enum
25
{
26
PDF_FLAGS_MARKED = 1,
27
PDF_FLAGS_SORTED = 2,
28
PDF_FLAGS_MEMO = 4,
29
PDF_FLAGS_MEMO_BOOL = 8,
30
PDF_FLAGS_DIRTY = 16
31
};
32
33
struct pdf_obj_s
34
{
35
short refs;
36
unsigned char kind;
37
unsigned char flags;
38
};
39
40
typedef struct pdf_obj_num_s
41
{
42
pdf_obj super;
43
union
44
{
45
int i;
46
float f;
47
} u;
48
} pdf_obj_num;
49
50
typedef struct pdf_obj_string_s
51
{
52
pdf_obj super;
53
unsigned short len;
54
char buf[1];
55
} pdf_obj_string;
56
57
typedef struct pdf_obj_name_s
58
{
59
pdf_obj super;
60
char n[1];
61
} pdf_obj_name;
62
63
typedef struct pdf_obj_array_s
64
{
65
pdf_obj super;
66
pdf_document *doc;
67
int parent_num;
68
int len;
69
int cap;
70
pdf_obj **items;
71
} pdf_obj_array;
72
73
typedef struct pdf_obj_dict_s
74
{
75
pdf_obj super;
76
pdf_document *doc;
77
int parent_num;
78
int len;
79
int cap;
80
struct keyval *items;
81
} pdf_obj_dict;
82
83
typedef struct pdf_obj_ref_s
84
{
85
pdf_obj super;
86
pdf_document *doc; /* Only needed for arrays, dicts and indirects */
87
int num;
88
int gen;
89
} pdf_obj_ref;
90
91
#define NAME(obj) ((pdf_obj_name *)(obj))
92
#define NUM(obj) ((pdf_obj_num *)(obj))
93
#define STRING(obj) ((pdf_obj_string *)(obj))
94
#define DICT(obj) ((pdf_obj_dict *)(obj))
95
#define ARRAY(obj) ((pdf_obj_array *)(obj))
96
#define REF(obj) ((pdf_obj_ref *)(obj))
97
98
pdf_obj *
99
pdf_new_null(fz_context *ctx, pdf_document *doc)
100
{
101
return PDF_OBJ_NULL;
102
}
103
104
pdf_obj *
105
pdf_new_bool(fz_context *ctx, pdf_document *doc, int b)
106
{
107
return b ? PDF_OBJ_TRUE : PDF_OBJ_FALSE;
108
}
109
110
pdf_obj *
111
pdf_new_int(fz_context *ctx, pdf_document *doc, int i)
112
{
113
pdf_obj_num *obj;
114
obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_num)), "pdf_obj(int)");
115
obj->super.refs = 1;
116
obj->super.kind = PDF_INT;
117
obj->super.flags = 0;
118
obj->u.i = i;
119
return &obj->super;
120
}
121
122
pdf_obj *
123
pdf_new_real(fz_context *ctx, pdf_document *doc, float f)
124
{
125
pdf_obj_num *obj;
126
obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_num)), "pdf_obj(real)");
127
obj->super.refs = 1;
128
obj->super.kind = PDF_REAL;
129
obj->super.flags = 0;
130
obj->u.f = f;
131
return &obj->super;
132
}
133
134
pdf_obj *
135
pdf_new_string(fz_context *ctx, pdf_document *doc, const char *str, int len)
136
{
137
pdf_obj_string *obj;
138
obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj_string, buf) + len + 1), "pdf_obj(string)");
139
obj->super.refs = 1;
140
obj->super.kind = PDF_STRING;
141
obj->super.flags = 0;
142
obj->len = len;
143
memcpy(obj->buf, str, len);
144
obj->buf[len] = '\0';
145
return &obj->super;
146
}
147
148
static int
149
namecmp(const void *key, const void *name)
150
{
151
return strcmp((char *)key, *(char **)name);
152
}
153
154
pdf_obj *
155
pdf_new_name(fz_context *ctx, pdf_document *doc, const char *str)
156
{
157
pdf_obj_name *obj;
158
char **stdname;
159
160
stdname = bsearch(str, &PDF_NAMES[1], PDF_OBJ_ENUM_NAME__LIMIT-1, sizeof(char *), namecmp);
161
if (stdname != NULL)
162
return (pdf_obj *)(intptr_t)(stdname - &PDF_NAMES[0]);
163
164
obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj_name, n) + strlen(str) + 1), "pdf_obj(name)");
165
obj->super.refs = 1;
166
obj->super.kind = PDF_NAME;
167
obj->super.flags = 0;
168
strcpy(obj->n, str);
169
return &obj->super;
170
}
171
172
pdf_obj *
173
pdf_new_indirect(fz_context *ctx, pdf_document *doc, int num, int gen)
174
{
175
pdf_obj_ref *obj;
176
obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_ref)), "pdf_obj(indirect)");
177
obj->super.refs = 1;
178
obj->super.kind = PDF_INDIRECT;
179
obj->super.flags = 0;
180
obj->doc = doc;
181
obj->num = num;
182
obj->gen = gen;
183
return &obj->super;
184
}
185
186
pdf_obj *
187
pdf_keep_obj(fz_context *ctx, pdf_obj *obj)
188
{
189
if (obj >= PDF_OBJ__LIMIT)
190
obj->refs ++;
191
return obj;
192
}
193
194
int pdf_is_indirect(fz_context *ctx, pdf_obj *obj)
195
{
196
return obj >= PDF_OBJ__LIMIT ? obj->kind == PDF_INDIRECT : 0;
197
}
198
199
#define RESOLVE(obj) \
200
if (obj >= PDF_OBJ__LIMIT && obj->kind == PDF_INDIRECT) \
201
obj = pdf_resolve_indirect(ctx, obj); \
202
203
int pdf_is_null(fz_context *ctx, pdf_obj *obj)
204
{
205
RESOLVE(obj);
206
return obj == PDF_OBJ_NULL;
207
}
208
209
int pdf_is_bool(fz_context *ctx, pdf_obj *obj)
210
{
211
RESOLVE(obj);
212
return obj == PDF_OBJ_TRUE || obj == PDF_OBJ_FALSE;
213
}
214
215
int pdf_is_int(fz_context *ctx, pdf_obj *obj)
216
{
217
RESOLVE(obj);
218
return obj >= PDF_OBJ__LIMIT ? obj->kind == PDF_INT : 0;
219
}
220
221
int pdf_is_real(fz_context *ctx, pdf_obj *obj)
222
{
223
RESOLVE(obj);
224
return obj >= PDF_OBJ__LIMIT ? obj->kind == PDF_REAL : 0;
225
}
226
227
int pdf_is_number(fz_context *ctx, pdf_obj *obj)
228
{
229
RESOLVE(obj);
230
return obj >= PDF_OBJ__LIMIT ? (obj->kind == PDF_REAL || obj->kind == PDF_INT) : 0;
231
}
232
233
int pdf_is_string(fz_context *ctx, pdf_obj *obj)
234
{
235
RESOLVE(obj);
236
return obj >= PDF_OBJ__LIMIT ? obj->kind == PDF_STRING : 0;
237
}
238
239
int pdf_is_name(fz_context *ctx, pdf_obj *obj)
240
{
241
RESOLVE(obj);
242
if (obj < PDF_OBJ__LIMIT)
243
return obj != NULL && obj < PDF_OBJ_NAME__LIMIT;
244
return obj->kind == PDF_NAME;
245
}
246
247
int pdf_is_array(fz_context *ctx, pdf_obj *obj)
248
{
249
RESOLVE(obj);
250
return obj >= PDF_OBJ__LIMIT ? obj->kind == PDF_ARRAY : 0;
251
}
252
253
int pdf_is_dict(fz_context *ctx, pdf_obj *obj)
254
{
255
RESOLVE(obj);
256
return obj >= PDF_OBJ__LIMIT ? obj->kind == PDF_DICT : 0;
257
}
258
259
int pdf_to_bool(fz_context *ctx, pdf_obj *obj)
260
{
261
RESOLVE(obj);
262
return obj == PDF_OBJ_TRUE;
263
}
264
265
int pdf_to_int(fz_context *ctx, pdf_obj *obj)
266
{
267
RESOLVE(obj);
268
if (obj < PDF_OBJ__LIMIT)
269
return 0;
270
if (obj->kind == PDF_INT)
271
return NUM(obj)->u.i;
272
if (obj->kind == PDF_REAL)
273
return (int)(NUM(obj)->u.f + 0.5f); /* No roundf in MSVC */
274
return 0;
275
}
276
277
float pdf_to_real(fz_context *ctx, pdf_obj *obj)
278
{
279
RESOLVE(obj);
280
if (obj < PDF_OBJ__LIMIT)
281
return 0;
282
if (obj->kind == PDF_REAL)
283
return NUM(obj)->u.f;
284
if (obj->kind == PDF_INT)
285
return NUM(obj)->u.i;
286
return 0;
287
}
288
289
char *pdf_to_name(fz_context *ctx, pdf_obj *obj)
290
{
291
RESOLVE(obj);
292
if (!obj)
293
return "";
294
if (obj < PDF_OBJ_NAME__LIMIT)
295
return PDF_NAMES[(intptr_t)obj];
296
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_NAME)
297
return "";
298
return NAME(obj)->n;
299
}
300
301
char *pdf_to_str_buf(fz_context *ctx, pdf_obj *obj)
302
{
303
RESOLVE(obj);
304
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_STRING)
305
return "";
306
return STRING(obj)->buf;
307
}
308
309
int pdf_to_str_len(fz_context *ctx, pdf_obj *obj)
310
{
311
RESOLVE(obj);
312
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_STRING)
313
return 0;
314
return STRING(obj)->len;
315
}
316
317
void pdf_set_int(fz_context *ctx, pdf_obj *obj, int i)
318
{
319
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_INT)
320
return;
321
NUM(obj)->u.i = i;
322
}
323
324
/* for use by pdf_crypt_obj_imp to decrypt AES string in place */
325
void pdf_set_str_len(fz_context *ctx, pdf_obj *obj, int newlen)
326
{
327
RESOLVE(obj);
328
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_STRING)
329
return; /* This should never happen */
330
if (newlen > STRING(obj)->len)
331
return; /* This should never happen */
332
STRING(obj)->len = newlen;
333
}
334
335
pdf_obj *pdf_to_dict(fz_context *ctx, pdf_obj *obj)
336
{
337
RESOLVE(obj);
338
return (obj >= PDF_OBJ__LIMIT && obj->kind == PDF_DICT ? obj : NULL);
339
}
340
341
int pdf_to_num(fz_context *ctx, pdf_obj *obj)
342
{
343
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_INDIRECT)
344
return 0;
345
return REF(obj)->num;
346
}
347
348
int pdf_to_gen(fz_context *ctx, pdf_obj *obj)
349
{
350
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_INDIRECT)
351
return 0;
352
return REF(obj)->gen;
353
}
354
355
pdf_document *pdf_get_indirect_document(fz_context *ctx, pdf_obj *obj)
356
{
357
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_INDIRECT)
358
return NULL;
359
return REF(obj)->doc;
360
}
361
362
int pdf_objcmp_resolve(fz_context *ctx, pdf_obj *a, pdf_obj *b)
363
{
364
RESOLVE(a);
365
RESOLVE(b);
366
return pdf_objcmp(ctx, a, b);
367
}
368
369
int
370
pdf_objcmp(fz_context *ctx, pdf_obj *a, pdf_obj *b)
371
{
372
int i;
373
374
if (a == b)
375
return 0;
376
377
if (!a || !b)
378
return 1;
379
380
if (a < PDF_OBJ_NAME__LIMIT)
381
{
382
if (b < PDF_OBJ_NAME__LIMIT)
383
return a != b;
384
385
if (b->kind != PDF_NAME)
386
return 1;
387
return strcmp(NAME(b)->n, PDF_NAMES[(intptr_t)a]);
388
}
389
390
if (b < PDF_OBJ_NAME__LIMIT)
391
{
392
if (a->kind != PDF_NAME)
393
return 1;
394
return strcmp(NAME(a)->n, PDF_NAMES[(intptr_t)b]);
395
}
396
397
if (a < PDF_OBJ__LIMIT || b < PDF_OBJ__LIMIT)
398
return a != b;
399
400
if (a->kind != b->kind)
401
return 1;
402
403
switch (a->kind)
404
{
405
case PDF_INT:
406
return NUM(a)->u.i - NUM(b)->u.i;
407
408
case PDF_REAL:
409
if (NUM(a)->u.f < NUM(b)->u.f)
410
return -1;
411
if (NUM(a)->u.f > NUM(b)->u.f)
412
return 1;
413
return 0;
414
415
case PDF_STRING:
416
if (STRING(a)->len < STRING(b)->len)
417
{
418
if (memcmp(STRING(a)->buf, STRING(b)->buf, STRING(a)->len) <= 0)
419
return -1;
420
return 1;
421
}
422
if (STRING(a)->len > STRING(b)->len)
423
{
424
if (memcmp(STRING(a)->buf, STRING(b)->buf, STRING(b)->len) >= 0)
425
return 1;
426
return -1;
427
}
428
return memcmp(STRING(a)->buf, STRING(b)->buf, STRING(a)->len);
429
430
case PDF_NAME:
431
return strcmp(NAME(a)->n, NAME(b)->n);
432
433
case PDF_INDIRECT:
434
if (REF(a)->num == REF(b)->num)
435
return REF(a)->gen - REF(b)->gen;
436
return REF(a)->num - REF(b)->num;
437
438
case PDF_ARRAY:
439
if (ARRAY(a)->len != ARRAY(b)->len)
440
return ARRAY(a)->len - ARRAY(b)->len;
441
for (i = 0; i < ARRAY(a)->len; i++)
442
if (pdf_objcmp(ctx, ARRAY(a)->items[i], ARRAY(b)->items[i]))
443
return 1;
444
return 0;
445
446
case PDF_DICT:
447
if (DICT(a)->len != DICT(b)->len)
448
return DICT(a)->len - DICT(b)->len;
449
for (i = 0; i < DICT(a)->len; i++)
450
{
451
if (pdf_objcmp(ctx, DICT(a)->items[i].k, DICT(b)->items[i].k))
452
return 1;
453
if (pdf_objcmp(ctx, DICT(a)->items[i].v, DICT(b)->items[i].v))
454
return 1;
455
}
456
return 0;
457
458
}
459
return 1;
460
}
461
462
static char *
463
pdf_objkindstr(pdf_obj *obj)
464
{
465
if (!obj)
466
return "<NULL>";
467
if (obj < PDF_OBJ_NAME__LIMIT)
468
return "name";
469
if (obj == PDF_OBJ_TRUE || obj == PDF_OBJ_FALSE)
470
return "boolean";
471
if (obj == PDF_OBJ_NULL)
472
return "null";
473
474
switch (obj->kind)
475
{
476
case PDF_INT: return "integer";
477
case PDF_REAL: return "real";
478
case PDF_STRING: return "string";
479
case PDF_NAME: return "name";
480
case PDF_ARRAY: return "array";
481
case PDF_DICT: return "dictionary";
482
case PDF_INDIRECT: return "reference";
483
}
484
return "<unknown>";
485
}
486
487
pdf_obj *
488
pdf_new_array(fz_context *ctx, pdf_document *doc, int initialcap)
489
{
490
pdf_obj_array *obj;
491
int i;
492
493
obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_array)), "pdf_obj(array)");
494
obj->super.refs = 1;
495
obj->super.kind = PDF_ARRAY;
496
obj->super.flags = 0;
497
obj->doc = doc;
498
obj->parent_num = 0;
499
500
obj->len = 0;
501
obj->cap = initialcap > 1 ? initialcap : 6;
502
503
fz_try(ctx)
504
{
505
obj->items = Memento_label(fz_malloc_array(ctx, obj->cap, sizeof(pdf_obj*)), "pdf_obj(array items)");
506
}
507
fz_catch(ctx)
508
{
509
fz_free(ctx, obj);
510
fz_rethrow(ctx);
511
}
512
for (i = 0; i < obj->cap; i++)
513
obj->items[i] = NULL;
514
515
return &obj->super;
516
}
517
518
static void
519
pdf_array_grow(fz_context *ctx, pdf_obj_array *obj)
520
{
521
int i;
522
int new_cap = (obj->cap * 3) / 2;
523
524
obj->items = fz_resize_array(ctx, obj->items, new_cap, sizeof(pdf_obj*));
525
obj->cap = new_cap;
526
527
for (i = obj->len ; i < obj->cap; i++)
528
obj->items[i] = NULL;
529
}
530
531
pdf_obj *
532
pdf_copy_array(fz_context *ctx, pdf_obj *obj)
533
{
534
pdf_document *doc;
535
pdf_obj *arr;
536
int i;
537
int n;
538
539
RESOLVE(obj);
540
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_ARRAY)
541
fz_throw(ctx, FZ_ERROR_GENERIC, "assert: not an array (%s)", pdf_objkindstr(obj));
542
543
doc = ARRAY(obj)->doc;
544
545
n = pdf_array_len(ctx, obj);
546
arr = pdf_new_array(ctx, doc, n);
547
for (i = 0; i < n; i++)
548
pdf_array_push(ctx, arr, pdf_array_get(ctx, obj, i));
549
550
return arr;
551
}
552
553
int
554
pdf_array_len(fz_context *ctx, pdf_obj *obj)
555
{
556
RESOLVE(obj);
557
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_ARRAY)
558
return 0;
559
return ARRAY(obj)->len;
560
}
561
562
pdf_obj *
563
pdf_array_get(fz_context *ctx, pdf_obj *obj, int i)
564
{
565
RESOLVE(obj);
566
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_ARRAY)
567
return NULL;
568
if (i < 0 || i >= ARRAY(obj)->len)
569
return NULL;
570
return ARRAY(obj)->items[i];
571
}
572
573
static void object_altered(fz_context *ctx, pdf_obj *obj, pdf_obj *val)
574
{
575
pdf_document *doc;
576
int parent;
577
578
/*
579
obj should be a dict or an array. We don't care about
580
any other types, as they aren't 'containers'.
581
*/
582
if (obj < PDF_OBJ__LIMIT)
583
return;
584
585
switch (obj->kind)
586
{
587
case PDF_DICT:
588
doc = DICT(obj)->doc;
589
parent = DICT(obj)->parent_num;
590
break;
591
case PDF_ARRAY:
592
doc = ARRAY(obj)->doc;
593
parent = ARRAY(obj)->parent_num;
594
break;
595
default:
596
return;
597
}
598
/*
599
parent_num = 0 while an object is being parsed from the file.
600
No further action is necessary.
601
*/
602
if (parent == 0 || doc->freeze_updates)
603
return;
604
605
/*
606
Otherwise we need to ensure that the containing hierarchy of objects
607
has been moved to the incremental xref section and the newly linked
608
object needs to record the parent_num
609
*/
610
pdf_xref_ensure_incremental_object(ctx, doc, parent);
611
pdf_set_obj_parent(ctx, val, parent);
612
}
613
614
void
615
pdf_array_put(fz_context *ctx, pdf_obj *obj, int i, pdf_obj *item)
616
{
617
RESOLVE(obj);
618
if (obj >= PDF_OBJ__LIMIT)
619
{
620
if (obj->kind != PDF_ARRAY)
621
fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
622
else if (i < 0)
623
fz_warn(ctx, "assert: index %d < 0", i);
624
else if (i >= ARRAY(obj)->len)
625
fz_warn(ctx, "assert: index %d > length %d", i, ARRAY(obj)->len);
626
else
627
{
628
pdf_drop_obj(ctx, ARRAY(obj)->items[i]);
629
ARRAY(obj)->items[i] = pdf_keep_obj(ctx, item);
630
}
631
632
object_altered(ctx, obj, item);
633
}
634
return; /* Can't warn :( */
635
}
636
637
void
638
pdf_array_put_drop(fz_context *ctx, pdf_obj *obj, int i, pdf_obj *item)
639
{
640
pdf_array_put(ctx, obj, i, item);
641
pdf_drop_obj(ctx, item);
642
}
643
644
void
645
pdf_array_push(fz_context *ctx, pdf_obj *obj, pdf_obj *item)
646
{
647
RESOLVE(obj);
648
if (obj >= PDF_OBJ__LIMIT)
649
{
650
if (obj->kind != PDF_ARRAY)
651
fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
652
else
653
{
654
if (ARRAY(obj)->len + 1 > ARRAY(obj)->cap)
655
pdf_array_grow(ctx, ARRAY(obj));
656
ARRAY(obj)->items[ARRAY(obj)->len] = pdf_keep_obj(ctx, item);
657
ARRAY(obj)->len++;
658
}
659
660
object_altered(ctx, obj, item);
661
}
662
return; /* Can't warn :( */
663
}
664
665
void
666
pdf_array_push_drop(fz_context *ctx, pdf_obj *obj, pdf_obj *item)
667
{
668
RESOLVE(obj);
669
if (obj >= PDF_OBJ__LIMIT)
670
{
671
fz_try(ctx)
672
pdf_array_push(ctx, obj, item);
673
fz_always(ctx)
674
pdf_drop_obj(ctx, item);
675
fz_catch(ctx)
676
fz_rethrow(ctx);
677
}
678
}
679
680
void
681
pdf_array_insert(fz_context *ctx, pdf_obj *obj, pdf_obj *item, int i)
682
{
683
RESOLVE(obj);
684
if (obj >= PDF_OBJ__LIMIT)
685
{
686
if (obj->kind != PDF_ARRAY)
687
fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
688
else
689
{
690
if (i < 0 || i > ARRAY(obj)->len)
691
fz_throw(ctx, FZ_ERROR_GENERIC, "attempt to insert object %d in array of length %d", i, ARRAY(obj)->len);
692
if (ARRAY(obj)->len + 1 > ARRAY(obj)->cap)
693
pdf_array_grow(ctx, ARRAY(obj));
694
memmove(ARRAY(obj)->items + i + 1, ARRAY(obj)->items + i, (ARRAY(obj)->len - i) * sizeof(pdf_obj*));
695
ARRAY(obj)->items[i] = pdf_keep_obj(ctx, item);
696
ARRAY(obj)->len++;
697
}
698
699
object_altered(ctx, obj, item);
700
}
701
return; /* Can't warn :( */
702
}
703
704
void
705
pdf_array_insert_drop(fz_context *ctx, pdf_obj *obj, pdf_obj *item, int i)
706
{
707
RESOLVE(obj);
708
if (obj >= PDF_OBJ__LIMIT)
709
{
710
fz_try(ctx)
711
pdf_array_insert(ctx, obj, item, i);
712
fz_always(ctx)
713
pdf_drop_obj(ctx, item);
714
fz_catch(ctx)
715
fz_rethrow(ctx);
716
}
717
}
718
719
void
720
pdf_array_delete(fz_context *ctx, pdf_obj *obj, int i)
721
{
722
RESOLVE(obj);
723
if (obj >= PDF_OBJ__LIMIT)
724
{
725
if (obj->kind != PDF_ARRAY)
726
fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
727
else
728
{
729
pdf_drop_obj(ctx, ARRAY(obj)->items[i]);
730
ARRAY(obj)->items[i] = 0;
731
ARRAY(obj)->len--;
732
memmove(ARRAY(obj)->items + i, ARRAY(obj)->items + i + 1, (ARRAY(obj)->len - i) * sizeof(pdf_obj*));
733
}
734
}
735
return; /* Can't warn :( */
736
}
737
738
int
739
pdf_array_contains(fz_context *ctx, pdf_obj *arr, pdf_obj *obj)
740
{
741
int i, len;
742
743
len = pdf_array_len(ctx, arr);
744
for (i = 0; i < len; i++)
745
if (!pdf_objcmp(ctx, pdf_array_get(ctx, arr, i), obj))
746
return 1;
747
748
return 0;
749
}
750
751
pdf_obj *pdf_new_rect(fz_context *ctx, pdf_document *doc, const fz_rect *rect)
752
{
753
pdf_obj *arr = NULL;
754
pdf_obj *item = NULL;
755
756
fz_var(arr);
757
fz_var(item);
758
fz_try(ctx)
759
{
760
arr = pdf_new_array(ctx, doc, 4);
761
762
item = pdf_new_real(ctx, doc, rect->x0);
763
pdf_array_push(ctx, arr, item);
764
pdf_drop_obj(ctx, item);
765
item = NULL;
766
767
item = pdf_new_real(ctx, doc, rect->y0);
768
pdf_array_push(ctx, arr, item);
769
pdf_drop_obj(ctx, item);
770
item = NULL;
771
772
item = pdf_new_real(ctx, doc, rect->x1);
773
pdf_array_push(ctx, arr, item);
774
pdf_drop_obj(ctx, item);
775
item = NULL;
776
777
item = pdf_new_real(ctx, doc, rect->y1);
778
pdf_array_push(ctx, arr, item);
779
pdf_drop_obj(ctx, item);
780
item = NULL;
781
}
782
fz_catch(ctx)
783
{
784
pdf_drop_obj(ctx, item);
785
pdf_drop_obj(ctx, arr);
786
fz_rethrow(ctx);
787
}
788
789
return arr;
790
}
791
792
pdf_obj *pdf_new_matrix(fz_context *ctx, pdf_document *doc, const fz_matrix *mtx)
793
{
794
pdf_obj *arr = NULL;
795
pdf_obj *item = NULL;
796
797
fz_var(arr);
798
fz_var(item);
799
fz_try(ctx)
800
{
801
arr = pdf_new_array(ctx, doc, 6);
802
803
item = pdf_new_real(ctx, doc, mtx->a);
804
pdf_array_push(ctx, arr, item);
805
pdf_drop_obj(ctx, item);
806
item = NULL;
807
808
item = pdf_new_real(ctx, doc, mtx->b);
809
pdf_array_push(ctx, arr, item);
810
pdf_drop_obj(ctx, item);
811
item = NULL;
812
813
item = pdf_new_real(ctx, doc, mtx->c);
814
pdf_array_push(ctx, arr, item);
815
pdf_drop_obj(ctx, item);
816
item = NULL;
817
818
item = pdf_new_real(ctx, doc, mtx->d);
819
pdf_array_push(ctx, arr, item);
820
pdf_drop_obj(ctx, item);
821
item = NULL;
822
823
item = pdf_new_real(ctx, doc, mtx->e);
824
pdf_array_push(ctx, arr, item);
825
pdf_drop_obj(ctx, item);
826
item = NULL;
827
828
item = pdf_new_real(ctx, doc, mtx->f);
829
pdf_array_push(ctx, arr, item);
830
pdf_drop_obj(ctx, item);
831
item = NULL;
832
}
833
fz_catch(ctx)
834
{
835
pdf_drop_obj(ctx, item);
836
pdf_drop_obj(ctx, arr);
837
fz_rethrow(ctx);
838
}
839
840
return arr;
841
}
842
843
/* dicts may only have names as keys! */
844
845
static int keyvalcmp(const void *ap, const void *bp)
846
{
847
const struct keyval *a = ap;
848
const struct keyval *b = bp;
849
const char *an;
850
const char *bn;
851
852
/* We should never get a->k == NULL or b->k == NULL. If we
853
* do, then they match. */
854
if (a->k < PDF_OBJ_NAME__LIMIT)
855
an = PDF_NAMES[(intptr_t)a->k];
856
else if (a->k >= PDF_OBJ__LIMIT && a->k->kind == PDF_NAME)
857
an = NAME(a->k)->n;
858
else
859
return 0;
860
861
if (b->k < PDF_OBJ_NAME__LIMIT)
862
bn = PDF_NAMES[(intptr_t)b->k];
863
else if (b->k >= PDF_OBJ__LIMIT && b->k->kind == PDF_NAME)
864
bn = NAME(b->k)->n;
865
else
866
return 0;
867
868
return strcmp(an, bn);
869
}
870
871
pdf_obj *
872
pdf_new_dict(fz_context *ctx, pdf_document *doc, int initialcap)
873
{
874
pdf_obj_dict *obj;
875
int i;
876
877
obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_dict)), "pdf_obj(dict)");
878
obj->super.refs = 1;
879
obj->super.kind = PDF_DICT;
880
obj->super.flags = 0;
881
obj->doc = doc;
882
obj->parent_num = 0;
883
884
obj->len = 0;
885
obj->cap = initialcap > 1 ? initialcap : 10;
886
887
fz_try(ctx)
888
{
889
DICT(obj)->items = Memento_label(fz_malloc_array(ctx, DICT(obj)->cap, sizeof(struct keyval)), "pdf_obj(dict items)");
890
}
891
fz_catch(ctx)
892
{
893
fz_free(ctx, obj);
894
fz_rethrow(ctx);
895
}
896
for (i = 0; i < DICT(obj)->cap; i++)
897
{
898
DICT(obj)->items[i].k = NULL;
899
DICT(obj)->items[i].v = NULL;
900
}
901
902
return &obj->super;
903
}
904
905
static void
906
pdf_dict_grow(fz_context *ctx, pdf_obj *obj)
907
{
908
int i;
909
int new_cap = (DICT(obj)->cap * 3) / 2;
910
911
DICT(obj)->items = fz_resize_array(ctx, DICT(obj)->items, new_cap, sizeof(struct keyval));
912
DICT(obj)->cap = new_cap;
913
914
for (i = DICT(obj)->len; i < DICT(obj)->cap; i++)
915
{
916
DICT(obj)->items[i].k = NULL;
917
DICT(obj)->items[i].v = NULL;
918
}
919
}
920
921
pdf_obj *
922
pdf_copy_dict(fz_context *ctx, pdf_obj *obj)
923
{
924
pdf_obj *dict;
925
int i, n;
926
927
RESOLVE(obj);
928
if (obj >= PDF_OBJ__LIMIT)
929
{
930
pdf_document *doc = DICT(obj)->doc;
931
932
if (obj->kind != PDF_DICT)
933
fz_warn(ctx, "assert: not a dict (%s)", pdf_objkindstr(obj));
934
935
n = pdf_dict_len(ctx, obj);
936
dict = pdf_new_dict(ctx, doc, n);
937
for (i = 0; i < n; i++)
938
pdf_dict_put(ctx, dict, pdf_dict_get_key(ctx, obj, i), pdf_dict_get_val(ctx, obj, i));
939
940
return dict;
941
}
942
return NULL; /* Can't warn :( */
943
}
944
945
int
946
pdf_dict_len(fz_context *ctx, pdf_obj *obj)
947
{
948
RESOLVE(obj);
949
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
950
return 0;
951
return DICT(obj)->len;
952
}
953
954
pdf_obj *
955
pdf_dict_get_key(fz_context *ctx, pdf_obj *obj, int i)
956
{
957
RESOLVE(obj);
958
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
959
return NULL;
960
if (i < 0 || i >= DICT(obj)->len)
961
return NULL;
962
return DICT(obj)->items[i].k;
963
}
964
965
pdf_obj *
966
pdf_dict_get_val(fz_context *ctx, pdf_obj *obj, int i)
967
{
968
RESOLVE(obj);
969
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
970
return NULL;
971
if (i < 0 || i >= DICT(obj)->len)
972
return NULL;
973
return DICT(obj)->items[i].v;
974
}
975
976
void
977
pdf_dict_put_val_drop(fz_context *ctx, pdf_obj *obj, int i, pdf_obj *new_obj)
978
{
979
RESOLVE(obj);
980
if (!obj || obj->kind != PDF_DICT)
981
{
982
pdf_drop_obj(ctx, new_obj);
983
return;
984
}
985
if (i < 0 || i >= DICT(obj)->len)
986
{
987
/* FIXME: Should probably extend the dict here */
988
pdf_drop_obj(ctx, new_obj);
989
return;
990
}
991
pdf_drop_obj(ctx, DICT(obj)->items[i].v);
992
DICT(obj)->items[i].v = new_obj;
993
}
994
995
static int
996
pdf_dict_finds(fz_context *ctx, pdf_obj *obj, const char *key, int *location)
997
{
998
if ((obj->flags & PDF_FLAGS_SORTED) && DICT(obj)->len > 0)
999
{
1000
int l = 0;
1001
int r = DICT(obj)->len - 1;
1002
1003
if (strcmp(pdf_to_name(ctx, DICT(obj)->items[r].k), key) < 0)
1004
{
1005
if (location)
1006
*location = r + 1;
1007
return -1;
1008
}
1009
1010
while (l <= r)
1011
{
1012
int m = (l + r) >> 1;
1013
int c = -strcmp(pdf_to_name(ctx, DICT(obj)->items[m].k), key);
1014
if (c < 0)
1015
r = m - 1;
1016
else if (c > 0)
1017
l = m + 1;
1018
else
1019
return m;
1020
1021
if (location)
1022
*location = l;
1023
}
1024
}
1025
1026
else
1027
{
1028
int i;
1029
for (i = 0; i < DICT(obj)->len; i++)
1030
if (strcmp(pdf_to_name(ctx, DICT(obj)->items[i].k), key) == 0)
1031
return i;
1032
1033
if (location)
1034
*location = DICT(obj)->len;
1035
}
1036
1037
return -1;
1038
}
1039
1040
static int
1041
pdf_dict_find(fz_context *ctx, pdf_obj *obj, pdf_obj *key, int *location)
1042
{
1043
if ((obj->flags & PDF_FLAGS_SORTED) && DICT(obj)->len > 0)
1044
{
1045
int l = 0;
1046
int r = DICT(obj)->len - 1;
1047
pdf_obj *k = DICT(obj)->items[r].k;
1048
1049
if (k == key || (k >= PDF_OBJ__LIMIT && strcmp(NAME(k)->n, PDF_NAMES[(intptr_t)key]) < 0))
1050
{
1051
if (location)
1052
*location = r + 1;
1053
return -1;
1054
}
1055
1056
while (l <= r)
1057
{
1058
int m = (l + r) >> 1;
1059
int c;
1060
1061
k = DICT(obj)->items[m].k;
1062
c = (k < PDF_OBJ__LIMIT ? key-k : -strcmp(NAME(k)->n, PDF_NAMES[(intptr_t)key]));
1063
if (c < 0)
1064
r = m - 1;
1065
else if (c > 0)
1066
l = m + 1;
1067
else
1068
return m;
1069
1070
if (location)
1071
*location = l;
1072
}
1073
}
1074
else
1075
{
1076
int i;
1077
for (i = 0; i < DICT(obj)->len; i++)
1078
{
1079
pdf_obj *k = DICT(obj)->items[i].k;
1080
if (k < PDF_OBJ__LIMIT)
1081
{
1082
if (k == key)
1083
return i;
1084
}
1085
else
1086
{
1087
if (!strcmp(PDF_NAMES[(intptr_t)key], NAME(k)->n))
1088
return i;
1089
}
1090
}
1091
1092
if (location)
1093
*location = DICT(obj)->len;
1094
}
1095
1096
return -1;
1097
}
1098
1099
pdf_obj *
1100
pdf_dict_gets(fz_context *ctx, pdf_obj *obj, const char *key)
1101
{
1102
int i;
1103
1104
RESOLVE(obj);
1105
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
1106
return NULL;
1107
1108
i = pdf_dict_finds(ctx, obj, key, NULL);
1109
if (i >= 0)
1110
return DICT(obj)->items[i].v;
1111
1112
return NULL;
1113
}
1114
1115
pdf_obj *
1116
pdf_dict_getp(fz_context *ctx, pdf_obj *obj, const char *keys)
1117
{
1118
RESOLVE(obj);
1119
if (obj >= PDF_OBJ__LIMIT)
1120
{
1121
char buf[256];
1122
char *k, *e;
1123
1124
if (strlen(keys)+1 > 256)
1125
fz_throw(ctx, FZ_ERROR_GENERIC, "buffer overflow in pdf_dict_getp");
1126
1127
strcpy(buf, keys);
1128
1129
e = buf;
1130
while (*e && obj)
1131
{
1132
k = e;
1133
while (*e != '/' && *e != '\0')
1134
e++;
1135
1136
if (*e == '/')
1137
{
1138
*e = '\0';
1139
e++;
1140
}
1141
1142
obj = pdf_dict_gets(ctx, obj, k);
1143
}
1144
1145
return obj;
1146
}
1147
return NULL; /* Can't warn */
1148
}
1149
1150
pdf_obj *
1151
pdf_dict_getl(fz_context *ctx, pdf_obj *obj, ...)
1152
{
1153
va_list keys;
1154
pdf_obj *key;
1155
1156
va_start(keys, obj);
1157
1158
while (obj != NULL && (key = va_arg(keys, pdf_obj *)) != NULL)
1159
{
1160
obj = pdf_dict_get(ctx, obj, key);
1161
}
1162
1163
va_end(keys);
1164
return obj;
1165
}
1166
1167
pdf_obj *
1168
pdf_dict_get(fz_context *ctx, pdf_obj *obj, pdf_obj *key)
1169
{
1170
int i;
1171
1172
RESOLVE(obj);
1173
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
1174
return NULL;
1175
1176
if (key < PDF_OBJ__LIMIT)
1177
i = pdf_dict_find(ctx, obj, key, NULL);
1178
else
1179
i = pdf_dict_finds(ctx, obj, pdf_to_name(ctx, key), NULL);
1180
if (i >= 0)
1181
return DICT(obj)->items[i].v;
1182
return NULL;
1183
}
1184
1185
pdf_obj *
1186
pdf_dict_getsa(fz_context *ctx, pdf_obj *obj, const char *key, const char *abbrev)
1187
{
1188
pdf_obj *v;
1189
v = pdf_dict_gets(ctx, obj, key);
1190
if (v)
1191
return v;
1192
return pdf_dict_gets(ctx, obj, abbrev);
1193
}
1194
1195
pdf_obj *
1196
pdf_dict_geta(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *abbrev)
1197
{
1198
pdf_obj *v;
1199
v = pdf_dict_get(ctx, obj, key);
1200
if (v)
1201
return v;
1202
return pdf_dict_get(ctx, obj, abbrev);
1203
}
1204
1205
void
1206
pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
1207
{
1208
RESOLVE(obj);
1209
if (obj >= PDF_OBJ__LIMIT)
1210
{
1211
int location;
1212
int i;
1213
1214
if (obj->kind != PDF_DICT)
1215
{
1216
fz_warn(ctx, "assert: not a dict (%s)", pdf_objkindstr(obj));
1217
return;
1218
}
1219
1220
RESOLVE(key);
1221
if (!key || (key >= PDF_OBJ__LIMIT && key->kind != PDF_NAME))
1222
{
1223
fz_warn(ctx, "assert: key is not a name (%s)", pdf_objkindstr(obj));
1224
return;
1225
}
1226
1227
if (!val)
1228
{
1229
fz_warn(ctx, "assert: val does not exist for key (%s)", pdf_to_name(ctx, key));
1230
return;
1231
}
1232
1233
if (DICT(obj)->len > 100 && !(obj->flags & PDF_FLAGS_SORTED))
1234
pdf_sort_dict(ctx, obj);
1235
1236
if (key < PDF_OBJ__LIMIT)
1237
i = pdf_dict_find(ctx, obj, key, &location);
1238
else
1239
i = pdf_dict_finds(ctx, obj, pdf_to_name(ctx, key), &location);
1240
if (i >= 0 && i < DICT(obj)->len)
1241
{
1242
if (DICT(obj)->items[i].v != val)
1243
{
1244
pdf_obj *d = DICT(obj)->items[i].v;
1245
DICT(obj)->items[i].v = pdf_keep_obj(ctx, val);
1246
pdf_drop_obj(ctx, d);
1247
}
1248
}
1249
else
1250
{
1251
if (DICT(obj)->len + 1 > DICT(obj)->cap)
1252
pdf_dict_grow(ctx, obj);
1253
1254
i = location;
1255
if ((obj->flags & PDF_FLAGS_SORTED) && DICT(obj)->len > 0)
1256
memmove(&DICT(obj)->items[i + 1],
1257
&DICT(obj)->items[i],
1258
(DICT(obj)->len - i) * sizeof(struct keyval));
1259
1260
DICT(obj)->items[i].k = pdf_keep_obj(ctx, key);
1261
DICT(obj)->items[i].v = pdf_keep_obj(ctx, val);
1262
DICT(obj)->len ++;
1263
}
1264
1265
object_altered(ctx, obj, val);
1266
}
1267
return; /* Can't warn :( */
1268
}
1269
1270
void
1271
pdf_dict_put_drop(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
1272
{
1273
fz_try(ctx)
1274
pdf_dict_put(ctx, obj, key, val);
1275
fz_always(ctx)
1276
pdf_drop_obj(ctx, val);
1277
fz_catch(ctx)
1278
fz_rethrow(ctx);
1279
}
1280
1281
void
1282
pdf_dict_puts(fz_context *ctx, pdf_obj *obj, const char *key, pdf_obj *val)
1283
{
1284
pdf_document *doc;
1285
pdf_obj *keyobj;
1286
1287
RESOLVE(obj);
1288
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
1289
fz_throw(ctx, FZ_ERROR_GENERIC, "not a dictionary (%s)", pdf_objkindstr(obj));
1290
1291
doc = DICT(obj)->doc;
1292
keyobj = pdf_new_name(ctx, doc, key);
1293
1294
fz_try(ctx)
1295
pdf_dict_put(ctx, obj, keyobj, val);
1296
fz_always(ctx)
1297
pdf_drop_obj(ctx, keyobj);
1298
fz_catch(ctx)
1299
fz_rethrow(ctx);
1300
}
1301
1302
void
1303
pdf_dict_puts_drop(fz_context *ctx, pdf_obj *obj, const char *key, pdf_obj *val)
1304
{
1305
pdf_document *doc;
1306
pdf_obj *keyobj;
1307
1308
RESOLVE(obj);
1309
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
1310
fz_throw(ctx, FZ_ERROR_GENERIC, "not a dictionary (%s)", pdf_objkindstr(obj));
1311
1312
doc = DICT(obj)->doc;
1313
keyobj = pdf_new_name(ctx, doc, key);
1314
1315
fz_var(keyobj);
1316
1317
fz_try(ctx)
1318
pdf_dict_put(ctx, obj, keyobj, val);
1319
fz_always(ctx)
1320
{
1321
pdf_drop_obj(ctx, keyobj);
1322
pdf_drop_obj(ctx, val);
1323
}
1324
fz_catch(ctx)
1325
{
1326
fz_rethrow(ctx);
1327
}
1328
}
1329
1330
void
1331
pdf_dict_putp(fz_context *ctx, pdf_obj *obj, const char *keys, pdf_obj *val)
1332
{
1333
pdf_document *doc;
1334
char buf[256];
1335
char *k, *e;
1336
pdf_obj *cobj = NULL;
1337
1338
RESOLVE(obj);
1339
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
1340
fz_throw(ctx, FZ_ERROR_GENERIC, "not a dictionary (%s)", pdf_objkindstr(obj));
1341
1342
doc = DICT(obj)->doc;
1343
1344
if (strlen(keys)+1 > 256)
1345
fz_throw(ctx, FZ_ERROR_GENERIC, "buffer overflow in pdf_dict_putp");
1346
1347
strcpy(buf, keys);
1348
1349
e = buf;
1350
while (*e)
1351
{
1352
k = e;
1353
while (*e != '/' && *e != '\0')
1354
e++;
1355
1356
if (*e == '/')
1357
{
1358
*e = '\0';
1359
e++;
1360
}
1361
1362
if (*e)
1363
{
1364
/* Not the last key in the key path. Create subdict if not already there. */
1365
cobj = pdf_dict_gets(ctx, obj, k);
1366
if (cobj == NULL)
1367
{
1368
cobj = pdf_new_dict(ctx, doc, 1);
1369
fz_try(ctx)
1370
pdf_dict_puts(ctx, obj, k, cobj);
1371
fz_always(ctx)
1372
pdf_drop_obj(ctx, cobj);
1373
fz_catch(ctx)
1374
fz_rethrow(ctx);
1375
}
1376
/* Move to subdict */
1377
obj = cobj;
1378
}
1379
else
1380
{
1381
/* Last key. Use it to store the value */
1382
/* Use val = NULL to request delete */
1383
if (val)
1384
pdf_dict_puts(ctx, obj, k, val);
1385
else
1386
pdf_dict_dels(ctx, obj, k);
1387
}
1388
}
1389
}
1390
1391
void
1392
pdf_dict_putp_drop(fz_context *ctx, pdf_obj *obj, const char *keys, pdf_obj *val)
1393
{
1394
fz_try(ctx)
1395
pdf_dict_putp(ctx, obj, keys, val);
1396
fz_always(ctx)
1397
pdf_drop_obj(ctx, val);
1398
fz_catch(ctx)
1399
fz_rethrow(ctx);
1400
}
1401
1402
static void
1403
pdf_dict_vputl(fz_context *ctx, pdf_obj *obj, pdf_obj *val, va_list keys)
1404
{
1405
pdf_obj *key;
1406
pdf_obj *next_key;
1407
pdf_obj *next_obj;
1408
pdf_document *doc;
1409
1410
RESOLVE(obj);
1411
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
1412
fz_throw(ctx, FZ_ERROR_GENERIC, "not a dictionary (%s)", pdf_objkindstr(obj));
1413
1414
doc = DICT(obj)->doc;
1415
1416
key = va_arg(keys, pdf_obj *);
1417
if (key == NULL)
1418
return;
1419
1420
while ((next_key = va_arg(keys, pdf_obj *)) != NULL)
1421
{
1422
next_obj = pdf_dict_get(ctx, obj, key);
1423
if (next_obj == NULL)
1424
goto new_obj;
1425
obj = next_obj;
1426
key = next_key;
1427
}
1428
1429
pdf_dict_put(ctx, obj, key, val);
1430
return;
1431
1432
new_obj:
1433
/* We have to create entries */
1434
do
1435
{
1436
next_obj = pdf_new_dict(ctx, doc, 1);
1437
pdf_dict_put_drop(ctx, obj, key, next_obj);
1438
obj = next_obj;
1439
key = next_key;
1440
}
1441
while ((next_key = va_arg(keys, pdf_obj *)) != NULL);
1442
1443
pdf_dict_put(ctx, obj, key, val);
1444
return;
1445
}
1446
1447
void
1448
pdf_dict_putl(fz_context *ctx, pdf_obj *obj, pdf_obj *val, ...)
1449
{
1450
va_list keys;
1451
va_start(keys, val);
1452
1453
fz_try(ctx)
1454
pdf_dict_vputl(ctx, obj, val, keys);
1455
fz_always(ctx)
1456
va_end(keys);
1457
fz_catch(ctx)
1458
fz_rethrow(ctx);
1459
}
1460
1461
void
1462
pdf_dict_putl_drop(fz_context *ctx, pdf_obj *obj, pdf_obj *val, ...)
1463
{
1464
va_list keys;
1465
va_start(keys, val);
1466
1467
fz_try(ctx)
1468
pdf_dict_vputl(ctx, obj, val, keys);
1469
fz_always(ctx)
1470
{
1471
pdf_drop_obj(ctx, val);
1472
va_end(keys);
1473
}
1474
fz_catch(ctx)
1475
fz_rethrow(ctx);
1476
}
1477
1478
void
1479
pdf_dict_dels(fz_context *ctx, pdf_obj *obj, const char *key)
1480
{
1481
RESOLVE(obj);
1482
if (obj >= PDF_OBJ__LIMIT)
1483
{
1484
if (obj->kind != PDF_DICT)
1485
fz_warn(ctx, "assert: not a dict (%s)", pdf_objkindstr(obj));
1486
else
1487
{
1488
int i = pdf_dict_finds(ctx, obj, key, NULL);
1489
if (i >= 0)
1490
{
1491
pdf_drop_obj(ctx, DICT(obj)->items[i].k);
1492
pdf_drop_obj(ctx, DICT(obj)->items[i].v);
1493
obj->flags &= ~PDF_FLAGS_SORTED;
1494
DICT(obj)->items[i] = DICT(obj)->items[DICT(obj)->len-1];
1495
DICT(obj)->len --;
1496
}
1497
}
1498
1499
object_altered(ctx, obj, NULL);
1500
}
1501
return; /* Can't warn :( */
1502
}
1503
1504
void
1505
pdf_dict_del(fz_context *ctx, pdf_obj *obj, pdf_obj *key)
1506
{
1507
RESOLVE(key);
1508
if (!key)
1509
return; /* Can't warn */
1510
1511
if (key < PDF_OBJ__LIMIT)
1512
pdf_dict_dels(ctx, obj, PDF_NAMES[(intptr_t)key]);
1513
else if (key->kind == PDF_NAME)
1514
pdf_dict_dels(ctx, obj, NAME(obj)->n);
1515
/* else Can't warn */
1516
}
1517
1518
void
1519
pdf_sort_dict(fz_context *ctx, pdf_obj *obj)
1520
{
1521
RESOLVE(obj);
1522
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
1523
return;
1524
if (!(obj->flags & PDF_FLAGS_SORTED))
1525
{
1526
qsort(DICT(obj)->items, DICT(obj)->len, sizeof(struct keyval), keyvalcmp);
1527
obj->flags |= PDF_FLAGS_SORTED;
1528
}
1529
}
1530
1531
int
1532
pdf_obj_marked(fz_context *ctx, pdf_obj *obj)
1533
{
1534
RESOLVE(obj);
1535
if (obj < PDF_OBJ__LIMIT)
1536
return 0;
1537
return !!(obj->flags & PDF_FLAGS_MARKED);
1538
}
1539
1540
int
1541
pdf_mark_obj(fz_context *ctx, pdf_obj *obj)
1542
{
1543
int marked;
1544
RESOLVE(obj);
1545
if (obj < PDF_OBJ__LIMIT)
1546
return 0;
1547
marked = !!(obj->flags & PDF_FLAGS_MARKED);
1548
obj->flags |= PDF_FLAGS_MARKED;
1549
return marked;
1550
}
1551
1552
void
1553
pdf_unmark_obj(fz_context *ctx, pdf_obj *obj)
1554
{
1555
RESOLVE(obj);
1556
if (obj < PDF_OBJ__LIMIT)
1557
return;
1558
obj->flags &= ~PDF_FLAGS_MARKED;
1559
}
1560
1561
void
1562
pdf_set_obj_memo(fz_context *ctx, pdf_obj *obj, int memo)
1563
{
1564
if (obj < PDF_OBJ__LIMIT)
1565
return;
1566
1567
obj->flags |= PDF_FLAGS_MEMO;
1568
if (memo)
1569
obj->flags |= PDF_FLAGS_MEMO_BOOL;
1570
else
1571
obj->flags &= ~PDF_FLAGS_MEMO_BOOL;
1572
}
1573
1574
int
1575
pdf_obj_memo(fz_context *ctx, pdf_obj *obj, int *memo)
1576
{
1577
if (obj < PDF_OBJ__LIMIT)
1578
return 0;
1579
if (!(obj->flags & PDF_FLAGS_MEMO))
1580
return 0;
1581
*memo = !!(obj->flags & PDF_FLAGS_MEMO_BOOL);
1582
return 1;
1583
}
1584
1585
int pdf_obj_is_dirty(fz_context *ctx, pdf_obj *obj)
1586
{
1587
RESOLVE(obj);
1588
if (obj < PDF_OBJ__LIMIT)
1589
return 0;
1590
return !!(obj->flags & PDF_FLAGS_DIRTY);
1591
}
1592
1593
void pdf_dirty_obj(fz_context *ctx, pdf_obj *obj)
1594
{
1595
RESOLVE(obj);
1596
if (obj < PDF_OBJ__LIMIT)
1597
return;
1598
obj->flags |= PDF_FLAGS_DIRTY;
1599
}
1600
1601
void pdf_clean_obj(fz_context *ctx, pdf_obj *obj)
1602
{
1603
if (obj < PDF_OBJ__LIMIT)
1604
return;
1605
obj->flags &= ~PDF_FLAGS_DIRTY;
1606
}
1607
1608
static void
1609
pdf_drop_array(fz_context *ctx, pdf_obj *obj)
1610
{
1611
int i;
1612
1613
for (i = 0; i < DICT(obj)->len; i++)
1614
pdf_drop_obj(ctx, ARRAY(obj)->items[i]);
1615
1616
fz_free(ctx, DICT(obj)->items);
1617
fz_free(ctx, obj);
1618
}
1619
1620
static void
1621
pdf_drop_dict(fz_context *ctx, pdf_obj *obj)
1622
{
1623
int i;
1624
1625
for (i = 0; i < DICT(obj)->len; i++) {
1626
pdf_drop_obj(ctx, DICT(obj)->items[i].k);
1627
pdf_drop_obj(ctx, DICT(obj)->items[i].v);
1628
}
1629
1630
fz_free(ctx, DICT(obj)->items);
1631
fz_free(ctx, obj);
1632
}
1633
1634
void
1635
pdf_drop_obj(fz_context *ctx, pdf_obj *obj)
1636
{
1637
if (obj >= PDF_OBJ__LIMIT)
1638
{
1639
if (--obj->refs)
1640
return;
1641
if (obj->kind == PDF_ARRAY)
1642
pdf_drop_array(ctx, obj);
1643
else if (obj->kind == PDF_DICT)
1644
pdf_drop_dict(ctx, obj);
1645
else
1646
fz_free(ctx, obj);
1647
}
1648
}
1649
1650
void
1651
pdf_set_obj_parent(fz_context *ctx, pdf_obj *obj, int num)
1652
{
1653
int n, i;
1654
1655
if (obj < PDF_OBJ__LIMIT)
1656
return;
1657
1658
switch(obj->kind)
1659
{
1660
case PDF_ARRAY:
1661
ARRAY(obj)->parent_num = num;
1662
n = pdf_array_len(ctx, obj);
1663
for (i = 0; i < n; i++)
1664
pdf_set_obj_parent(ctx, pdf_array_get(ctx, obj, i), num);
1665
break;
1666
case PDF_DICT:
1667
DICT(obj)->parent_num = num;
1668
n = pdf_dict_len(ctx, obj);
1669
for (i = 0; i < n; i++)
1670
pdf_set_obj_parent(ctx, pdf_dict_get_val(ctx, obj, i), num);
1671
break;
1672
}
1673
}
1674
1675
int pdf_obj_parent_num(fz_context *ctx, pdf_obj *obj)
1676
{
1677
if (obj < PDF_OBJ__LIMIT)
1678
return 0;
1679
1680
switch(obj->kind)
1681
{
1682
case PDF_ARRAY:
1683
return ARRAY(obj)->parent_num;
1684
case PDF_DICT:
1685
return DICT(obj)->parent_num;
1686
default:
1687
return 0;
1688
}
1689
}
1690
1691
pdf_obj *pdf_new_obj_from_str(fz_context *ctx, pdf_document *doc, const char *src)
1692
{
1693
pdf_obj *result;
1694
pdf_lexbuf lexbuf;
1695
fz_stream *stream = fz_open_memory(ctx, (unsigned char *)src, strlen(src));
1696
1697
pdf_lexbuf_init(ctx, &lexbuf, PDF_LEXBUF_SMALL);
1698
fz_try(ctx)
1699
{
1700
result = pdf_parse_stm_obj(ctx, doc, stream, &lexbuf);
1701
}
1702
fz_always(ctx)
1703
{
1704
pdf_lexbuf_fin(ctx, &lexbuf);
1705
fz_drop_stream(ctx, stream);
1706
}
1707
fz_catch(ctx)
1708
{
1709
fz_rethrow(ctx);
1710
}
1711
1712
return result;
1713
}
1714
1715
/* Pretty printing objects */
1716
1717
struct fmt
1718
{
1719
char *buf;
1720
int cap;
1721
int len;
1722
int indent;
1723
int tight;
1724
int col;
1725
int sep;
1726
int last;
1727
};
1728
1729
static void fmt_obj(fz_context *ctx, struct fmt *fmt, pdf_obj *obj);
1730
1731
static inline int iswhite(int ch)
1732
{
1733
return
1734
ch == '\000' ||
1735
ch == '\011' ||
1736
ch == '\012' ||
1737
ch == '\014' ||
1738
ch == '\015' ||
1739
ch == '\040';
1740
}
1741
1742
static inline int isdelim(int ch)
1743
{
1744
return
1745
ch == '(' || ch == ')' ||
1746
ch == '<' || ch == '>' ||
1747
ch == '[' || ch == ']' ||
1748
ch == '{' || ch == '}' ||
1749
ch == '/' ||
1750
ch == '%';
1751
}
1752
1753
static inline void fmt_putc(fz_context *ctx, struct fmt *fmt, int c)
1754
{
1755
if (fmt->sep && !isdelim(fmt->last) && !isdelim(c)) {
1756
fmt->sep = 0;
1757
fmt_putc(ctx, fmt, ' ');
1758
}
1759
fmt->sep = 0;
1760
1761
if (fmt->buf && fmt->len < fmt->cap)
1762
fmt->buf[fmt->len] = c;
1763
1764
if (c == '\n')
1765
fmt->col = 0;
1766
else
1767
fmt->col ++;
1768
1769
fmt->len ++;
1770
1771
fmt->last = c;
1772
}
1773
1774
static inline void fmt_indent(fz_context *ctx, struct fmt *fmt)
1775
{
1776
int i = fmt->indent;
1777
while (i--) {
1778
fmt_putc(ctx, fmt, ' ');
1779
fmt_putc(ctx, fmt, ' ');
1780
}
1781
}
1782
1783
static inline void fmt_puts(fz_context *ctx, struct fmt *fmt, char *s)
1784
{
1785
while (*s)
1786
fmt_putc(ctx, fmt, *s++);
1787
}
1788
1789
static inline void fmt_sep(fz_context *ctx, struct fmt *fmt)
1790
{
1791
fmt->sep = 1;
1792
}
1793
1794
static void fmt_str(fz_context *ctx, struct fmt *fmt, pdf_obj *obj)
1795
{
1796
char *s = pdf_to_str_buf(ctx, obj);
1797
int n = pdf_to_str_len(ctx, obj);
1798
int i, c;
1799
1800
fmt_putc(ctx, fmt, '(');
1801
for (i = 0; i < n; i++)
1802
{
1803
c = (unsigned char)s[i];
1804
if (c == '\n')
1805
fmt_puts(ctx, fmt, "\\n");
1806
else if (c == '\r')
1807
fmt_puts(ctx, fmt, "\\r");
1808
else if (c == '\t')
1809
fmt_puts(ctx, fmt, "\\t");
1810
else if (c == '\b')
1811
fmt_puts(ctx, fmt, "\\b");
1812
else if (c == '\f')
1813
fmt_puts(ctx, fmt, "\\f");
1814
else if (c == '(')
1815
fmt_puts(ctx, fmt, "\\(");
1816
else if (c == ')')
1817
fmt_puts(ctx, fmt, "\\)");
1818
else if (c == '\\')
1819
fmt_puts(ctx, fmt, "\\\\");
1820
else if (c < 32 || c >= 127) {
1821
fmt_putc(ctx, fmt, '\\');
1822
fmt_putc(ctx, fmt, '0' + ((c / 64) & 7));
1823
fmt_putc(ctx, fmt, '0' + ((c / 8) & 7));
1824
fmt_putc(ctx, fmt, '0' + ((c) & 7));
1825
}
1826
else
1827
fmt_putc(ctx, fmt, c);
1828
}
1829
fmt_putc(ctx, fmt, ')');
1830
}
1831
1832
static void fmt_hex(fz_context *ctx, struct fmt *fmt, pdf_obj *obj)
1833
{
1834
char *s = pdf_to_str_buf(ctx, obj);
1835
int n = pdf_to_str_len(ctx, obj);
1836
int i, b, c;
1837
1838
fmt_putc(ctx, fmt, '<');
1839
for (i = 0; i < n; i++) {
1840
b = (unsigned char) s[i];
1841
c = (b >> 4) & 0x0f;
1842
fmt_putc(ctx, fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
1843
c = (b) & 0x0f;
1844
fmt_putc(ctx, fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
1845
}
1846
fmt_putc(ctx, fmt, '>');
1847
}
1848
1849
static void fmt_name(fz_context *ctx, struct fmt *fmt, pdf_obj *obj)
1850
{
1851
unsigned char *s = (unsigned char *) pdf_to_name(ctx, obj);
1852
int i, c;
1853
1854
fmt_putc(ctx, fmt, '/');
1855
1856
for (i = 0; s[i]; i++)
1857
{
1858
if (isdelim(s[i]) || iswhite(s[i]) ||
1859
s[i] == '#' || s[i] < 32 || s[i] >= 127)
1860
{
1861
fmt_putc(ctx, fmt, '#');
1862
c = (s[i] >> 4) & 0xf;
1863
fmt_putc(ctx, fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
1864
c = s[i] & 0xf;
1865
fmt_putc(ctx, fmt, c < 0xA ? c + '0' : c + 'A' - 0xA);
1866
}
1867
else
1868
{
1869
fmt_putc(ctx, fmt, s[i]);
1870
}
1871
}
1872
}
1873
1874
static void fmt_array(fz_context *ctx, struct fmt *fmt, pdf_obj *obj)
1875
{
1876
int i, n;
1877
1878
n = pdf_array_len(ctx, obj);
1879
if (fmt->tight) {
1880
fmt_putc(ctx, fmt, '[');
1881
for (i = 0; i < n; i++) {
1882
fmt_obj(ctx, fmt, pdf_array_get(ctx, obj, i));
1883
fmt_sep(ctx, fmt);
1884
}
1885
fmt_putc(ctx, fmt, ']');
1886
}
1887
else {
1888
fmt_puts(ctx, fmt, "[ ");
1889
for (i = 0; i < n; i++) {
1890
if (fmt->col > 60) {
1891
fmt_putc(ctx, fmt, '\n');
1892
fmt_indent(ctx, fmt);
1893
}
1894
fmt_obj(ctx, fmt, pdf_array_get(ctx, obj, i));
1895
fmt_putc(ctx, fmt, ' ');
1896
}
1897
fmt_putc(ctx, fmt, ']');
1898
fmt_sep(ctx, fmt);
1899
}
1900
}
1901
1902
static void fmt_dict(fz_context *ctx, struct fmt *fmt, pdf_obj *obj)
1903
{
1904
int i, n;
1905
pdf_obj *key, *val;
1906
1907
n = pdf_dict_len(ctx, obj);
1908
if (fmt->tight) {
1909
fmt_puts(ctx, fmt, "<<");
1910
for (i = 0; i < n; i++) {
1911
fmt_obj(ctx, fmt, pdf_dict_get_key(ctx, obj, i));
1912
fmt_sep(ctx, fmt);
1913
fmt_obj(ctx, fmt, pdf_dict_get_val(ctx, obj, i));
1914
fmt_sep(ctx, fmt);
1915
}
1916
fmt_puts(ctx, fmt, ">>");
1917
}
1918
else {
1919
fmt_puts(ctx, fmt, "<<\n");
1920
fmt->indent ++;
1921
for (i = 0; i < n; i++) {
1922
key = pdf_dict_get_key(ctx, obj, i);
1923
val = pdf_dict_get_val(ctx, obj, i);
1924
fmt_indent(ctx, fmt);
1925
fmt_obj(ctx, fmt, key);
1926
fmt_putc(ctx, fmt, ' ');
1927
if (!pdf_is_indirect(ctx, val) && pdf_is_array(ctx, val))
1928
fmt->indent ++;
1929
fmt_obj(ctx, fmt, val);
1930
fmt_putc(ctx, fmt, '\n');
1931
if (!pdf_is_indirect(ctx, val) && pdf_is_array(ctx, val))
1932
fmt->indent --;
1933
}
1934
fmt->indent --;
1935
fmt_indent(ctx, fmt);
1936
fmt_puts(ctx, fmt, ">>");
1937
}
1938
}
1939
1940
static void fmt_obj(fz_context *ctx, struct fmt *fmt, pdf_obj *obj)
1941
{
1942
char buf[256];
1943
1944
if (!obj)
1945
fmt_puts(ctx, fmt, "<NULL>");
1946
else if (pdf_is_indirect(ctx, obj))
1947
{
1948
fz_snprintf(buf, sizeof buf, "%d %d R", pdf_to_num(ctx, obj), pdf_to_gen(ctx, obj));
1949
fmt_puts(ctx, fmt, buf);
1950
}
1951
else if (pdf_is_null(ctx, obj))
1952
fmt_puts(ctx, fmt, "null");
1953
else if (pdf_is_bool(ctx, obj))
1954
fmt_puts(ctx, fmt, pdf_to_bool(ctx, obj) ? "true" : "false");
1955
else if (pdf_is_int(ctx, obj))
1956
{
1957
fz_snprintf(buf, sizeof buf, "%d", pdf_to_int(ctx, obj));
1958
fmt_puts(ctx, fmt, buf);
1959
}
1960
else if (pdf_is_real(ctx, obj))
1961
{
1962
fz_snprintf(buf, sizeof buf, "%g", pdf_to_real(ctx, obj));
1963
fmt_puts(ctx, fmt, buf);
1964
}
1965
else if (pdf_is_string(ctx, obj))
1966
{
1967
char *str = pdf_to_str_buf(ctx, obj);
1968
int len = pdf_to_str_len(ctx, obj);
1969
int added = 0;
1970
int i, c;
1971
for (i = 0; i < len; i++) {
1972
c = (unsigned char)str[i];
1973
if (c != 0 && strchr("()\\\n\r\t\b\f", c))
1974
added ++;
1975
else if (c < 32 || c >= 127)
1976
added += 3;
1977
}
1978
if (added < len)
1979
fmt_str(ctx, fmt, obj);
1980
else
1981
fmt_hex(ctx, fmt, obj);
1982
}
1983
else if (pdf_is_name(ctx, obj))
1984
fmt_name(ctx, fmt, obj);
1985
else if (pdf_is_array(ctx, obj))
1986
fmt_array(ctx, fmt, obj);
1987
else if (pdf_is_dict(ctx, obj))
1988
fmt_dict(ctx, fmt, obj);
1989
else
1990
fmt_puts(ctx, fmt, "<unknown object>");
1991
}
1992
1993
int
1994
pdf_sprint_obj(fz_context *ctx, char *s, int n, pdf_obj *obj, int tight)
1995
{
1996
struct fmt fmt;
1997
1998
fmt.indent = 0;
1999
fmt.col = 0;
2000
fmt.sep = 0;
2001
fmt.last = 0;
2002
2003
fmt.tight = tight;
2004
fmt.buf = s;
2005
fmt.cap = n;
2006
fmt.len = 0;
2007
fmt_obj(ctx, &fmt, obj);
2008
2009
if (fmt.buf && fmt.len < fmt.cap)
2010
fmt.buf[fmt.len] = '\0';
2011
2012
return fmt.len;
2013
}
2014
2015
int
2016
pdf_fprint_obj(fz_context *ctx, FILE *fp, pdf_obj *obj, int tight)
2017
{
2018
char buf[1024];
2019
char *ptr;
2020
int n;
2021
2022
n = pdf_sprint_obj(ctx, NULL, 0, obj, tight);
2023
if ((n + 1) < sizeof buf)
2024
{
2025
pdf_sprint_obj(ctx, buf, sizeof buf, obj, tight);
2026
fputs(buf, fp);
2027
fputc('\n', fp);
2028
}
2029
else
2030
{
2031
ptr = fz_malloc(ctx, n + 1);
2032
pdf_sprint_obj(ctx, ptr, n + 1, obj, tight);
2033
fputs(ptr, fp);
2034
fputc('\n', fp);
2035
fz_free(ctx, ptr);
2036
}
2037
return n;
2038
}
2039
2040
int pdf_output_obj(fz_context *ctx, fz_output *out, pdf_obj *obj, int tight)
2041
{
2042
char buf[1024];
2043
char *ptr;
2044
int n;
2045
2046
n = pdf_sprint_obj(ctx, NULL, 0, obj, tight);
2047
if ((n + 1) < sizeof buf)
2048
{
2049
pdf_sprint_obj(ctx, buf, sizeof buf, obj, tight);
2050
fz_puts(ctx, out, buf);
2051
}
2052
else
2053
{
2054
ptr = fz_malloc(ctx, n + 1);
2055
pdf_sprint_obj(ctx, ptr, n + 1, obj, tight);
2056
fz_puts(ctx, out, buf);
2057
fz_free(ctx, ptr);
2058
}
2059
return n;
2060
}
2061
2062
#ifndef NDEBUG
2063
void
2064
pdf_print_obj(fz_context *ctx, pdf_obj *obj)
2065
{
2066
pdf_fprint_obj(ctx, stdout, obj, 0);
2067
}
2068
2069
void
2070
pdf_print_ref(fz_context *ctx, pdf_obj *ref)
2071
{
2072
pdf_print_obj(ctx, pdf_resolve_indirect(ctx, ref));
2073
}
2074
#endif
2075
2076
int pdf_obj_refs(fz_context *ctx, pdf_obj *ref)
2077
{
2078
return (ref >= PDF_OBJ__LIMIT ? ref->refs : 0);
2079
}
2080
2081