Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7643 views
1
#include "mupdf/pdf.h"
2
3
static pdf_obj *
4
pdf_lookup_name_imp(fz_context *ctx, pdf_obj *node, pdf_obj *needle)
5
{
6
pdf_obj *kids = pdf_dict_get(ctx, node, PDF_NAME_Kids);
7
pdf_obj *names = pdf_dict_get(ctx, node, PDF_NAME_Names);
8
9
if (pdf_is_array(ctx, kids))
10
{
11
int l = 0;
12
int r = pdf_array_len(ctx, kids) - 1;
13
14
while (l <= r)
15
{
16
int m = (l + r) >> 1;
17
pdf_obj *kid = pdf_array_get(ctx, kids, m);
18
pdf_obj *limits = pdf_dict_get(ctx, kid, PDF_NAME_Limits);
19
pdf_obj *first = pdf_array_get(ctx, limits, 0);
20
pdf_obj *last = pdf_array_get(ctx, limits, 1);
21
22
if (pdf_objcmp(ctx, needle, first) < 0)
23
r = m - 1;
24
else if (pdf_objcmp(ctx, needle, last) > 0)
25
l = m + 1;
26
else
27
{
28
pdf_obj *obj;
29
30
if (pdf_mark_obj(ctx, node))
31
break;
32
obj = pdf_lookup_name_imp(ctx, kid, needle);
33
pdf_unmark_obj(ctx, node);
34
return obj;
35
}
36
}
37
}
38
39
if (pdf_is_array(ctx, names))
40
{
41
int l = 0;
42
int r = (pdf_array_len(ctx, names) / 2) - 1;
43
44
while (l <= r)
45
{
46
int m = (l + r) >> 1;
47
int c;
48
pdf_obj *key = pdf_array_get(ctx, names, m * 2);
49
pdf_obj *val = pdf_array_get(ctx, names, m * 2 + 1);
50
51
c = pdf_objcmp(ctx, needle, key);
52
if (c < 0)
53
r = m - 1;
54
else if (c > 0)
55
l = m + 1;
56
else
57
return val;
58
}
59
60
/* Spec says names should be sorted (hence the binary search,
61
* above), but Acrobat copes with non-sorted. Drop back to a
62
* simple search if the binary search fails. */
63
r = pdf_array_len(ctx, names)/2;
64
for (l = 0; l < r; l++)
65
if (!pdf_objcmp(ctx, needle, pdf_array_get(ctx, names, l * 2)))
66
return pdf_array_get(ctx, names, l * 2 + 1);
67
}
68
69
return NULL;
70
}
71
72
pdf_obj *
73
pdf_lookup_name(fz_context *ctx, pdf_document *doc, pdf_obj *which, pdf_obj *needle)
74
{
75
pdf_obj *root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root);
76
pdf_obj *names = pdf_dict_get(ctx, root, PDF_NAME_Names);
77
pdf_obj *tree = pdf_dict_get(ctx, names, which);
78
return pdf_lookup_name_imp(ctx, tree, needle);
79
}
80
81
pdf_obj *
82
pdf_lookup_dest(fz_context *ctx, pdf_document *doc, pdf_obj *needle)
83
{
84
pdf_obj *root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root);
85
pdf_obj *dests = pdf_dict_get(ctx, root, PDF_NAME_Dests);
86
pdf_obj *names = pdf_dict_get(ctx, root, PDF_NAME_Names);
87
pdf_obj *dest = NULL;
88
89
/* PDF 1.1 has destinations in a dictionary */
90
if (dests)
91
{
92
if (pdf_is_name(ctx, needle))
93
return pdf_dict_get(ctx, dests, needle);
94
else
95
return pdf_dict_gets(ctx, dests, pdf_to_str_buf(ctx, needle));
96
}
97
98
/* PDF 1.2 has destinations in a name tree */
99
if (names && !dest)
100
{
101
pdf_obj *tree = pdf_dict_get(ctx, names, PDF_NAME_Dests);
102
return pdf_lookup_name_imp(ctx, tree, needle);
103
}
104
105
return NULL;
106
}
107
108
static void
109
pdf_load_name_tree_imp(fz_context *ctx, pdf_obj *dict, pdf_document *doc, pdf_obj *node)
110
{
111
pdf_obj *kids = pdf_dict_get(ctx, node, PDF_NAME_Kids);
112
pdf_obj *names = pdf_dict_get(ctx, node, PDF_NAME_Names);
113
int i;
114
115
UNUSED(ctx);
116
117
if (kids && !pdf_mark_obj(ctx, node))
118
{
119
int len = pdf_array_len(ctx, kids);
120
for (i = 0; i < len; i++)
121
pdf_load_name_tree_imp(ctx, dict, doc, pdf_array_get(ctx, kids, i));
122
pdf_unmark_obj(ctx, node);
123
}
124
125
if (names)
126
{
127
int len = pdf_array_len(ctx, names);
128
for (i = 0; i + 1 < len; i += 2)
129
{
130
pdf_obj *key = pdf_array_get(ctx, names, i);
131
pdf_obj *val = pdf_array_get(ctx, names, i + 1);
132
if (pdf_is_string(ctx, key))
133
{
134
key = pdf_to_utf8_name(ctx, doc, key);
135
pdf_dict_put(ctx, dict, key, val);
136
pdf_drop_obj(ctx, key);
137
}
138
else if (pdf_is_name(ctx, key))
139
{
140
pdf_dict_put(ctx, dict, key, val);
141
}
142
}
143
}
144
}
145
146
pdf_obj *
147
pdf_load_name_tree(fz_context *ctx, pdf_document *doc, pdf_obj *which)
148
{
149
pdf_obj *root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME_Root);
150
pdf_obj *names = pdf_dict_get(ctx, root, PDF_NAME_Names);
151
pdf_obj *tree = pdf_dict_get(ctx, names, which);
152
if (pdf_is_dict(ctx, tree))
153
{
154
pdf_obj *dict = pdf_new_dict(ctx, doc, 100);
155
pdf_load_name_tree_imp(ctx, dict, doc, tree);
156
return dict;
157
}
158
return NULL;
159
}
160
161