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
/>.
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.
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"
52 #define DIRECT_ALWAYS
2
68 static colstack_type
*colstacks
= NULL;
69 static int colstacks_size
= 0;
70 static int colstacks_used
= 0;
72 @ Initialization is done
, if the color stacks are used
, |init_colorstacks
()| is defined
73 as macro to avoid unnecessary procedure calls.
76 #define init_colorstacks
() if
(colstacks_size
== 0) colstacks_first_init
();
78 static void colstacks_first_init
(void
)
80 colstacks_size
= STACK_INCREMENT
;
81 colstacks
= xtalloc
((unsigned
) colstacks_size
, colstack_type
);
83 colstacks
[0].page_stack
= NULL;
84 colstacks
[0].form_stack
= NULL;
85 colstacks
[0].page_size
= 0;
86 colstacks
[0].form_size
= 0;
87 colstacks
[0].page_used
= 0;
88 colstacks
[0].form_used
= 0;
89 colstacks
[0].page_current
= xstrdup
(COLOR_DEFAULT
);
90 colstacks
[0].form_current
= xstrdup
(COLOR_DEFAULT
);
91 colstacks
[0].form_init
= xstrdup
(COLOR_DEFAULT
);
92 colstacks
[0].literal_mode
= DIRECT_ALWAYS
;
93 colstacks
[0].page_start
= true
;
97 int colorstackused
(void
)
100 return colstacks_used
;
103 @ A new color stack is setup with the given parameters. The stack number is returned
104 or
-1 in case of error
(no room
).
107 int newcolorstack
(const char
*str
, int literal_mode
, boolean page_start
)
109 colstack_type
*colstack
;
113 if
(colstacks_used
== MAX_COLORSTACKS
) {
116 if
(colstacks_used
== colstacks_size
) {
117 colstacks_size
+= STACK_INCREMENT
;
119 If |
(MAX_COLORSTACKS mod STACK_INCREMENT
= 0)| then we don't
120 need to check the case that size overruns |MAX_COLORSTACKS|.
122 colstacks
= xreallocarray
(colstacks
, colstack_type
, (unsigned
) colstacks_size
);
124 /* claim new color stack
*/
125 colstack_num
= colstacks_used
++;
126 colstack
= &colstacks[colstack_num];
127 /* configure the new color stack
*/
128 colstack-
>page_stack
= NULL;
129 colstack-
>form_stack
= NULL;
130 colstack-
>page_size
= 0;
131 colstack-
>page_used
= 0;
132 colstack-
>form_size
= 0;
133 colstack-
>form_used
= 0;
134 colstack-
>literal_mode
= literal_mode
;
135 colstack-
>page_start
= page_start
;
136 colstack-
>page_current
= NULL;
137 colstack-
>form_current
= NULL;
138 colstack-
>form_init
= NULL;
140 colstack-
>page_current
= xstrdup
(str
);
141 colstack-
>form_current
= xstrdup
(str
);
142 colstack-
>form_init
= xstrdup
(str
);
148 #define get_colstack
(n
) (&colstacks[n])
150 @ Puts a string on top of the string pool and updates |pool_ptr|.
152 @c static void put_cstring_on_str_pool
(char
*str
)
154 int save_selector
= selector
;
155 selector
= new_string
;
156 if
(str
== NULL ||
*str
== 0) {
160 selector
= save_selector
;
164 static int colorstackset
(int colstack_no
, str_number s
)
166 colstack_type
*colstack
= get_colstack
(colstack_no
);
168 if
(global_shipping_mode
== SHIPPING_PAGE
) {
169 xfree
(colstack-
>page_current
);
170 colstack-
>page_current
= makecstring
(s
);
172 xfree
(colstack-
>form_current
);
173 colstack-
>form_current
= makecstring
(s
);
175 return colstack-
>literal_mode
;
179 int colorstackcurrent
(int colstack_no
)
181 colstack_type
*colstack
= get_colstack
(colstack_no
);
183 if
(global_shipping_mode
== SHIPPING_PAGE
) {
184 put_cstring_on_str_pool
(colstack-
>page_current
);
186 put_cstring_on_str_pool
(colstack-
>form_current
);
188 return colstack-
>literal_mode
;
192 static int colorstackpush
(int colstack_no
, str_number s
)
194 colstack_type
*colstack
= get_colstack
(colstack_no
);
196 if
(global_shipping_mode
== SHIPPING_PAGE
) {
197 if
(colstack-
>page_used
== colstack-
>page_size
) {
198 colstack-
>page_size
+= STACK_INCREMENT
;
199 xretalloc
(colstack-
>page_stack
, (unsigned
) colstack-
>page_size
, char
*);
201 colstack-
>page_stack
[colstack-
>page_used
++] = colstack-
>page_current
;
202 str
= makecstring
(s
);
204 colstack-
>page_current
= NULL;
206 colstack-
>page_current
= xstrdup
(str
);
210 if
(colstack-
>form_used
== colstack-
>form_size
) {
211 colstack-
>form_size
+= STACK_INCREMENT
;
212 xretalloc
(colstack-
>form_stack
, (unsigned
) colstack-
>form_size
, char
*);
214 colstack-
>form_stack
[colstack-
>form_used
++] = colstack-
>form_current
;
215 str
= makecstring
(s
);
217 colstack-
>form_current
= NULL;
219 colstack-
>form_current
= xstrdup
(str
);
223 return colstack-
>literal_mode
;
227 int colorstackpop
(int colstack_no
)
229 colstack_type
*colstack
= get_colstack
(colstack_no
);
230 if
(global_shipping_mode
== SHIPPING_PAGE
) {
231 if
(colstack-
>page_used
== 0) {
232 formatted_warning
("pdf backend","pop empty color page stack %u",(unsigned int
) colstack_no
);
233 return colstack-
>literal_mode
;
235 xfree
(colstack-
>page_current
);
236 colstack-
>page_current
= colstack-
>page_stack
[--colstack-
>page_used
];
237 put_cstring_on_str_pool
(colstack-
>page_current
);
239 if
(colstack-
>form_used
== 0) {
240 formatted_warning
("pdf backend","pop empty color form stack %u",(unsigned int
) colstack_no
);
241 return colstack-
>literal_mode
;
243 xfree
(colstack-
>form_current
);
244 colstack-
>form_current
= colstack-
>form_stack
[--colstack-
>form_used
];
245 put_cstring_on_str_pool
(colstack-
>form_current
);
247 return colstack-
>literal_mode
;
251 void colorstackpagestart
(void
)
254 colstack_type
*colstack
;
255 if
(global_shipping_mode
== SHIPPING_PAGE
) {
256 /* see procedure |pdf_out_colorstack_startpage|
*/
260 for
(i
= 0; i
< colstacks_used
; i
++) {
261 colstack
= &colstacks[i];
262 for
(j
= 0; j
< colstack-
>form_used
; j
++) {
263 xfree
(colstack-
>form_stack
[j
]);
265 colstack-
>form_used
= 0;
266 xfree
(colstack-
>form_current
);
267 if
(colstack-
>form_init
== NULL) {
268 colstack-
>form_current
= NULL;
270 colstack-
>form_current
= xstrdup
(colstack-
>form_init
);
276 int colorstackskippagestart
(int colstack_no
)
278 colstack_type
*colstack
= get_colstack
(colstack_no
);
279 if
(!colstack-
>page_start
) {
282 if
(colstack-
>page_current
== NULL) {
285 if
(strcmp
(COLOR_DEFAULT
, colstack-
>page_current
) == 0) {
293 void pdf_out_colorstack
(PDF pdf
, halfword p
)
297 int cmd
= pdf_colorstack_cmd
(p
);
298 int stack_no
= pdf_colorstack_stack
(p
);
299 int literal_mode
= 0;
300 if
(stack_no
>= colorstackused
()) {
302 tprint
("Color stack ");
304 tprint
(" is not initialized for use!");
310 case colorstack_push
:
311 old_setting
= selector
;
312 selector
= new_string
;
313 show_token_list
(token_link
(pdf_colorstack_data
(p
)), null
, -1);
314 selector
= old_setting
;
316 if
(cmd
== colorstack_set
)
317 literal_mode
= colorstackset
(stack_no
, s
);
319 literal_mode
= colorstackpush
(stack_no
, s
);
320 if
(str_length
(s
) > 0)
321 pdf_literal
(pdf
, s
, literal_mode
, false
);
326 literal_mode
= colorstackpop
(stack_no
);
328 case colorstack_current
:
329 literal_mode
= colorstackcurrent
(stack_no
);
334 if
(cur_length
> 0) {
336 pdf_literal
(pdf
, s
, literal_mode
, false
);
342 void pdf_out_colorstack_startpage
(PDF pdf
)
348 int max
= colorstackused
();
350 start_status
= colorstackskippagestart
(i
);
351 if
(start_status
== 0) {
352 literal_mode
= colorstackcurrent
(i
);
353 if
(cur_length
> 0) {
355 pdf_literal
(pdf
, s
, literal_mode
, false
);