beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / pdf / pdftables.w
blobd8b5cf103215b9eff7c1f969d10906baf54fdde7
1 % pdftables.w
3 % Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software; you can redistribute it and/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation; either version 2 of the License, or (at your
10 % option) any later version.
12 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
20 @ @c
22 #include "ptexlib.h"
24 @ @c
25 const char *pdf_obj_typenames[PDF_OBJ_TYPE_MAX + 1] = {
26 "font", "outline", "dest", "obj", "xform", "ximage", "thread",
27 "pagestream", "page", "pages", "catalog", "info", "link", "annot", "annots",
28 "bead", "beads", "objstm", "others"
31 int pdf_last_annot;
32 int pdf_last_link;
33 int pdf_last_obj;
34 int pdf_retval; /* global multi-purpose return value */
36 @ AVL sort entry into |avl_table[]|
38 static int compare_info(const void *pa, const void *pb, void *param)
40 const oentry *a = (const oentry *) pa;
41 const oentry *b = (const oentry *) pb;
42 (void) param;
43 if (a->u_type == b->u_type) {
44 if (a->u_type == union_type_int)
45 return ((a->u.int0 < b->u.int0 ? -1 : (a->u.int0 > b->u.int0 ? 1 : 0)));
46 else /* string type */
47 return strcmp(a->u.str0, b->u.str0);
48 } else if (a->u_type == union_type_int) {
49 return -1;
50 } else {
51 return 1;
55 static void avl_put_obj(PDF pdf, int t, oentry * oe)
57 void **pp;
58 if (pdf->obj_tree[t] == NULL) {
59 pdf->obj_tree[t] = avl_create(compare_info, NULL, &avl_xallocator);
60 if (pdf->obj_tree[t] == NULL)
61 formatted_error("pdf backend","avl_create() pdf->obj_tree failed");
63 pp = avl_probe(pdf->obj_tree[t], oe);
64 if (pp == NULL)
65 formatted_error("pdf backend","avl_probe() out of memory in insertion");
68 static void avl_put_int_obj(PDF pdf, int int0, int objptr, int t)
70 oentry *oe = xtalloc(1, oentry);
71 oe->u.int0 = int0;
72 oe->u_type = union_type_int;
73 oe->objptr = objptr;
74 avl_put_obj(pdf, t, oe);
77 static void avl_put_str_obj(PDF pdf, char *str0, int objptr, int t)
79 oentry *oe = xtalloc(1, oentry);
80 oe->u.str0 = str0; /* no xstrdup() here */
81 oe->u_type = union_type_cstring;
82 oe->objptr = objptr;
83 avl_put_obj(pdf, t, oe);
86 static int avl_find_int_obj(PDF pdf, int t, int i)
88 oentry *p;
89 oentry tmp;
90 tmp.u.int0 = i;
91 tmp.u_type = union_type_int;
92 if (pdf->obj_tree[t] == NULL)
93 return 0;
94 p = (oentry *) avl_find(pdf->obj_tree[t], &tmp);
95 if (p == NULL)
96 return 0;
97 return p->objptr;
100 static int avl_find_str_obj(PDF pdf, int t, char *s)
102 oentry *p;
103 oentry tmp;
104 tmp.u.str0 = s;
105 tmp.u_type = union_type_cstring;
106 if (pdf->obj_tree[t] == NULL)
107 return 0;
108 p = (oentry *) avl_find(pdf->obj_tree[t], &tmp);
109 if (p == NULL)
110 return 0;
111 return p->objptr;
114 @ Create an object with type |t| and identifier |i|
117 int pdf_create_obj(PDF pdf, int t, int i)
119 int a;
120 char *ss = NULL;
121 if (pdf->obj_ptr == sup_obj_tab_size)
122 overflow("indirect objects table size", (unsigned) pdf->obj_tab_size);
123 if (pdf->obj_ptr == pdf->obj_tab_size) {
124 a = pdf->obj_tab_size / 5;
125 if (pdf->obj_tab_size < sup_obj_tab_size - a)
126 pdf->obj_tab_size = pdf->obj_tab_size + a;
127 else
128 pdf->obj_tab_size = sup_obj_tab_size;
129 pdf->obj_tab = xreallocarray(pdf->obj_tab, obj_entry, (unsigned) pdf->obj_tab_size);
131 pdf->obj_ptr++;
132 obj_info(pdf, pdf->obj_ptr) = i;
133 obj_type(pdf, pdf->obj_ptr) = t;
134 set_obj_fresh(pdf, pdf->obj_ptr);
135 obj_aux(pdf, pdf->obj_ptr) = 0;
136 if (i < 0) {
137 ss = makecstring(-i);
138 avl_put_str_obj(pdf, ss, pdf->obj_ptr, t);
139 } else if (i > 0)
140 avl_put_int_obj(pdf, i, pdf->obj_ptr, t);
141 if (t <= HEAD_TAB_MAX) {
142 obj_link(pdf, pdf->obj_ptr) = pdf->head_tab[t];
143 pdf->head_tab[t] = pdf->obj_ptr;
144 if ((t == obj_type_dest) && (i < 0))
145 append_dest_name(pdf, makecstring(-obj_info(pdf, pdf->obj_ptr)), pdf->obj_ptr); /* why not just -i */
147 return pdf->obj_ptr;
150 @ @c
151 int find_obj(PDF pdf, int t, int i, boolean byname)
153 char *ss = NULL;
154 int ret;
155 if (byname) {
156 ss = makecstring(i);
157 ret = avl_find_str_obj(pdf, t, ss);
158 free(ss);
159 } else {
160 ret = avl_find_int_obj(pdf, t, i);
162 return ret;
165 @ The following function finds an object with identifier |i| and type |t|.
166 Identifier |i| is either an integer or a token list index. If no such object
167 exists then it will be created. This function is used mainly to find destination
168 for link annotations and outlines; however it is also used in |ship_out| (to
169 check whether a Page object already exists) so we need to declare it together
170 with subroutines needed in |hlist_out| and |vlist_out|.
173 int pdf_get_obj(PDF pdf, int t, int i, boolean byname)
175 int r;
176 str_number s;
177 if (byname > 0) {
178 s = tokens_to_string(i);
179 r = find_obj(pdf, t, s, true);
180 } else {
181 s = 0;
182 r = find_obj(pdf, t, i, false);
184 if (r == 0) {
185 if (byname > 0) {
186 r = pdf_create_obj(pdf, t, -s);
187 s = 0;
188 } else {
189 r = pdf_create_obj(pdf, t, i);
191 if (t == obj_type_dest)
192 set_obj_dest_ptr(pdf, r, null);
194 if (s != 0)
195 flush_str(s);
196 return r;
199 @ object checking
201 void check_obj_exists(PDF pdf, int objnum)
203 if (objnum < 0 || objnum > pdf->obj_ptr)
204 normal_error("pdf backend", "cannot find referenced object");
207 void check_obj_type(PDF pdf, int t, int objnum)
209 int u;
210 check_obj_exists(pdf, objnum);
211 u = obj_type(pdf, objnum);
212 if (t != u) {
213 formatted_error("pdf backend", "referenced object has wrong type %s; should be %s",
214 pdf_obj_typenames[u], pdf_obj_typenames[t]);
218 @ @c
219 void set_rect_dimens(PDF pdf, halfword p, halfword parent_box, scaledpos cur, scaled_whd alt_rule, scaled margin)
221 scaledpos ll, ur; /* positions relative to cur */
222 scaledpos pos_ll, pos_ur, tmp;
223 posstructure localpos;
224 localpos.dir = pdf->posstruct->dir;
225 ll.h = 0; /* pdf contains current point on page */
226 if (is_running(alt_rule.dp))
227 ll.v = depth(parent_box) - cur.v;
228 else
229 ll.v = alt_rule.dp;
230 if (is_running(alt_rule.wd))
231 ur.h = width(parent_box) - cur.h;
232 else
233 ur.h = alt_rule.wd;
234 if (is_running(alt_rule.ht))
235 ur.v = -height(parent_box) - cur.v;
236 else
237 ur.v = -alt_rule.ht;
238 synch_pos_with_cur(&localpos, pdf->posstruct, ll);
239 pos_ll = localpos.pos;
240 synch_pos_with_cur(&localpos, pdf->posstruct, ur);
241 pos_ur = localpos.pos;
242 if (pos_ll.h > pos_ur.h) {
243 tmp.h = pos_ll.h;
244 pos_ll.h = pos_ur.h;
245 pos_ur.h = tmp.h;
247 if (pos_ll.v > pos_ur.v) {
248 tmp.v = pos_ll.v;
249 pos_ll.v = pos_ur.v;
250 pos_ur.v = tmp.v;
252 if (global_shipping_mode == SHIPPING_PAGE && matrixused()) {
253 matrixtransformrect(pos_ll.h, pos_ll.v, pos_ur.h, pos_ur.v);
254 pos_ll.h = getllx();
255 pos_ll.v = getlly();
256 pos_ur.h = geturx();
257 pos_ur.v = getury();
259 pdf_ann_left(p) = pos_ll.h - margin;
260 pdf_ann_bottom(p) = pos_ll.v - margin;
261 pdf_ann_right(p) = pos_ur.h + margin;
262 pdf_ann_top(p) = pos_ur.v + margin;
265 @ @c
266 void libpdffinish(PDF pdf)
268 strbuf_free(pdf->fb);
269 xfree(pdf->job_id_string);
270 fm_free();
271 t1_free();
272 enc_free();
273 epdf_free();
274 ttf_free();
275 sfd_free();
276 glyph_unicode_free();
277 zip_free(pdf);