fix getsup (HH)
[luatex.git] / source / texk / web2c / luatexdir / pdf / pdfcolorstack.w
blobac117d6ba0517564a00be4fe67ea49f175cdf2c2
1 % pdfcolorstack.w
3 % Copyright 2009-2011 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 @* Color Stack and Matrix Transformation Support.
26 @ In the following array and especially stack data structures are used.
28 They have the following properties:
30 \item{-} They automatically grow dynamically.
31 \item{-} The size never decreases.
32 \item{-} The variable with name ending in "size" contains the number how many
33 entries the data structure can hold.
34 \item{-} The variable with name ending in "used" contains the number of
35 actually used entries.
36 \item{-} Memory of strings in stack entries must be allocated and
37 freed if the stack is cleared.
39 @ Color Stack
42 #define MAX_COLORSTACKS 32768
45 The colorstack number is stored in two bytes (info field of the node);
46 condition (newcolorstack): |MAX_COLORSTACKS mod STACK_INCREMENT = 0|
49 #define COLOR_DEFAULT "0 g 0 G"
51 typedef struct {
52 char **page_stack;
53 char **form_stack;
54 char *page_current;
55 char *form_current;
56 char *form_init;
57 int page_size;
58 int form_size;
59 int page_used;
60 int form_used;
61 int literal_mode;
62 boolean page_start;
63 } colstack_type;
65 static colstack_type *colstacks = NULL;
66 static int colstacks_size = 0;
67 static int colstacks_used = 0;
69 @ Initialization is done, if the color stacks are used, |init_colorstacks()| is defined
70 as macro to avoid unnecessary procedure calls.
73 #define init_colorstacks() if (colstacks_size == 0) colstacks_first_init();
75 static void colstacks_first_init(void)
77 colstacks_size = STACK_INCREMENT;
78 colstacks = xtalloc((unsigned) colstacks_size, colstack_type);
79 colstacks_used = 1;
80 colstacks[0].page_stack = NULL;
81 colstacks[0].form_stack = NULL;
82 colstacks[0].page_size = 0;
83 colstacks[0].form_size = 0;
84 colstacks[0].page_used = 0;
85 colstacks[0].form_used = 0;
86 colstacks[0].page_current = xstrdup(COLOR_DEFAULT);
87 colstacks[0].form_current = xstrdup(COLOR_DEFAULT);
88 colstacks[0].form_init = xstrdup(COLOR_DEFAULT);
89 colstacks[0].literal_mode = direct_always;
90 colstacks[0].page_start = true;
93 @ @c
94 int colorstackused(void)
96 init_colorstacks();
97 return colstacks_used;
100 @ A new color stack is setup with the given parameters. The stack number is returned
101 or -1 in case of error (no room).
104 int newcolorstack(const char *str, int literal_mode, boolean page_start)
106 colstack_type *colstack;
107 int colstack_num;
108 init_colorstacks();
109 /* make room */
110 if (colstacks_used == MAX_COLORSTACKS) {
111 return -1;
113 if (colstacks_used == colstacks_size) {
114 colstacks_size += STACK_INCREMENT;
116 If |(MAX_COLORSTACKS mod STACK_INCREMENT = 0)| then we don't
117 need to check the case that size overruns |MAX_COLORSTACKS|.
119 colstacks = xreallocarray(colstacks, colstack_type, (unsigned) colstacks_size);
121 /* claim new color stack */
122 colstack_num = colstacks_used++;
123 colstack = &colstacks[colstack_num];
124 /* configure the new color stack */
125 colstack->page_stack = NULL;
126 colstack->form_stack = NULL;
127 colstack->page_size = 0;
128 colstack->page_used = 0;
129 colstack->form_size = 0;
130 colstack->form_used = 0;
131 colstack->literal_mode = literal_mode;
132 colstack->page_start = page_start;
133 colstack->page_current = NULL;
134 colstack->form_current = NULL;
135 colstack->form_init = NULL;
136 if (str) {
137 colstack->page_current = xstrdup(str);
138 colstack->form_current = xstrdup(str);
139 colstack->form_init = xstrdup(str);
141 return colstack_num;
144 @ @c
145 #define get_colstack(n) (&colstacks[n])
147 @ Puts a string on top of the string pool and updates |pool_ptr|.
149 @c static void put_cstring_on_str_pool(char *str)
151 int save_selector = selector;
152 selector = new_string;
153 if (str == NULL || *str == 0) {
154 return;
156 tprint(str);
157 selector = save_selector;
160 @ @c
161 static int colorstackset(int colstack_no, str_number s)
163 colstack_type *colstack = get_colstack(colstack_no);
165 if (global_shipping_mode == SHIPPING_PAGE) {
166 xfree(colstack->page_current);
167 colstack->page_current = makecstring(s);
168 } else {
169 xfree(colstack->form_current);
170 colstack->form_current = makecstring(s);
172 return colstack->literal_mode;
175 @ @c
176 int colorstackcurrent(int colstack_no)
178 colstack_type *colstack = get_colstack(colstack_no);
180 if (global_shipping_mode == SHIPPING_PAGE) {
181 put_cstring_on_str_pool(colstack->page_current);
182 } else {
183 put_cstring_on_str_pool(colstack->form_current);
185 return colstack->literal_mode;
188 @ @c
189 static int colorstackpush(int colstack_no, str_number s)
191 colstack_type *colstack = get_colstack(colstack_no);
192 char *str;
193 if (global_shipping_mode == SHIPPING_PAGE) {
194 if (colstack->page_used == colstack->page_size) {
195 colstack->page_size += STACK_INCREMENT;
196 xretalloc(colstack->page_stack, (unsigned) colstack->page_size, char *);
198 colstack->page_stack[colstack->page_used++] = colstack->page_current;
199 str = makecstring(s);
200 if (*str == 0) {
201 colstack->page_current = NULL;
202 } else {
203 colstack->page_current = xstrdup(str);
205 free(str);
206 } else {
207 if (colstack->form_used == colstack->form_size) {
208 colstack->form_size += STACK_INCREMENT;
209 xretalloc(colstack->form_stack, (unsigned) colstack->form_size, char *);
211 colstack->form_stack[colstack->form_used++] = colstack->form_current;
212 str = makecstring(s);
213 if (*str == 0) {
214 colstack->form_current = NULL;
215 } else {
216 colstack->form_current = xstrdup(str);
218 free(str);
220 return colstack->literal_mode;
223 @ @c
224 int colorstackpop(int colstack_no)
226 colstack_type *colstack = get_colstack(colstack_no);
227 if (global_shipping_mode == SHIPPING_PAGE) {
228 if (colstack->page_used == 0) {
229 formatted_warning("pdf backend","pop empty color page stack %u",(unsigned int) colstack_no);
230 return colstack->literal_mode;
232 xfree(colstack->page_current);
233 colstack->page_current = colstack->page_stack[--colstack->page_used];
234 put_cstring_on_str_pool(colstack->page_current);
235 } else {
236 if (colstack->form_used == 0) {
237 formatted_warning("pdf backend","pop empty color form stack %u",(unsigned int) colstack_no);
238 return colstack->literal_mode;
240 xfree(colstack->form_current);
241 colstack->form_current = colstack->form_stack[--colstack->form_used];
242 put_cstring_on_str_pool(colstack->form_current);
244 return colstack->literal_mode;
247 @ @c
248 void colorstackpagestart(void)
250 int i, j;
251 colstack_type *colstack;
252 if (global_shipping_mode == SHIPPING_PAGE) {
253 /* see procedure |pdf_out_colorstack_startpage| */
254 return;
257 for (i = 0; i < colstacks_used; i++) {
258 colstack = &colstacks[i];
259 for (j = 0; j < colstack->form_used; j++) {
260 xfree(colstack->form_stack[j]);
262 colstack->form_used = 0;
263 xfree(colstack->form_current);
264 if (colstack->form_init == NULL) {
265 colstack->form_current = NULL;
266 } else {
267 colstack->form_current = xstrdup(colstack->form_init);
272 @ @c
273 int colorstackskippagestart(int colstack_no)
275 colstack_type *colstack = get_colstack(colstack_no);
276 if (!colstack->page_start) {
277 return 1;
279 if (colstack->page_current == NULL) {
280 return 0;
282 if (strcmp(COLOR_DEFAULT, colstack->page_current) == 0) {
283 return 2;
285 return 0;
289 @ @c
290 void pdf_out_colorstack(PDF pdf, halfword p)
292 int old_setting;
293 str_number s;
294 int cmd = pdf_colorstack_cmd(p);
295 int stack_no = pdf_colorstack_stack(p);
296 int literal_mode = 0;
297 if (stack_no >= colorstackused()) {
298 tprint_nl("");
299 tprint("Color stack ");
300 print_int(stack_no);
301 tprint(" is not initialized for use!");
302 tprint_nl("");
303 return;
305 switch (cmd) {
306 case colorstack_set:
307 case colorstack_push:
308 old_setting = selector;
309 selector = new_string;
310 show_token_list(token_link(pdf_colorstack_data(p)), null, -1);
311 selector = old_setting;
312 s = make_string();
313 if (cmd == colorstack_set)
314 literal_mode = colorstackset(stack_no, s);
315 else
316 literal_mode = colorstackpush(stack_no, s);
317 if (str_length(s) > 0)
318 pdf_literal(pdf, s, literal_mode, false);
319 flush_str(s);
320 return;
321 break;
322 case colorstack_pop:
323 literal_mode = colorstackpop(stack_no);
324 break;
325 case colorstack_current:
326 literal_mode = colorstackcurrent(stack_no);
327 break;
328 default:
329 break;
331 if (cur_length > 0) {
332 s = make_string();
333 pdf_literal(pdf, s, literal_mode, false);
334 flush_str(s);
338 @ @c
339 void pdf_out_colorstack_startpage(PDF pdf)
341 int start_status;
342 int literal_mode;
343 str_number s;
344 int i = 0;
345 int max = colorstackused();
346 while (i < max) {
347 start_status = colorstackskippagestart(i);
348 if (start_status == 0) {
349 literal_mode = colorstackcurrent(i);
350 if (cur_length > 0) {
351 s = make_string();
352 pdf_literal(pdf, s, literal_mode, false);
353 flush_str(s);
356 i++;