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"
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
);
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
;
94 int colorstackused
(void
)
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
;
110 if
(colstacks_used
== MAX_COLORSTACKS
) {
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;
137 colstack-
>page_current
= xstrdup
(str
);
138 colstack-
>form_current
= xstrdup
(str
);
139 colstack-
>form_init
= xstrdup
(str
);
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) {
157 selector
= save_selector
;
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
);
169 xfree
(colstack-
>form_current
);
170 colstack-
>form_current
= makecstring
(s
);
172 return colstack-
>literal_mode
;
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
);
183 put_cstring_on_str_pool
(colstack-
>form_current
);
185 return colstack-
>literal_mode
;
189 static int colorstackpush
(int colstack_no
, str_number s
)
191 colstack_type
*colstack
= get_colstack
(colstack_no
);
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
);
201 colstack-
>page_current
= NULL;
203 colstack-
>page_current
= xstrdup
(str
);
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
);
214 colstack-
>form_current
= NULL;
216 colstack-
>form_current
= xstrdup
(str
);
220 return colstack-
>literal_mode
;
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
);
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
;
248 void colorstackpagestart
(void
)
251 colstack_type
*colstack
;
252 if
(global_shipping_mode
== SHIPPING_PAGE
) {
253 /* see procedure |pdf_out_colorstack_startpage|
*/
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;
267 colstack-
>form_current
= xstrdup
(colstack-
>form_init
);
273 int colorstackskippagestart
(int colstack_no
)
275 colstack_type
*colstack
= get_colstack
(colstack_no
);
276 if
(!colstack-
>page_start
) {
279 if
(colstack-
>page_current
== NULL) {
282 if
(strcmp
(COLOR_DEFAULT
, colstack-
>page_current
) == 0) {
290 void pdf_out_colorstack
(PDF pdf
, halfword p
)
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
()) {
299 tprint
("Color stack ");
301 tprint
(" is not initialized for use!");
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
;
313 if
(cmd
== colorstack_set
)
314 literal_mode
= colorstackset
(stack_no
, s
);
316 literal_mode
= colorstackpush
(stack_no
, s
);
317 if
(str_length
(s
) > 0)
318 pdf_literal
(pdf
, s
, literal_mode
, false
);
323 literal_mode
= colorstackpop
(stack_no
);
325 case colorstack_current
:
326 literal_mode
= colorstackcurrent
(stack_no
);
331 if
(cur_length
> 0) {
333 pdf_literal
(pdf
, s
, literal_mode
, false
);
339 void pdf_out_colorstack_startpage
(PDF pdf
)
345 int max
= colorstackused
();
347 start_status
= colorstackskippagestart
(i
);
348 if
(start_status
== 0) {
349 literal_mode
= colorstackcurrent
(i
);
350 if
(cur_length
> 0) {
352 pdf_literal
(pdf
, s
, literal_mode
, false
);