1 /* Copyright (C) 1989, 2000 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16
17 */
18
19 /*$Id: gsstate.c,v 1.11.2.1.2.1 2003/01/17 00:49:03 giles Exp $ */
20 /* Miscellaneous graphics state operators for Ghostscript library */
21 #include "gx.h"
22 #include "memory_.h"
23 #include "gserrors.h"
24 #include "gsstruct.h"
25 #include "gsutil.h" /* for gs_next_ids */
26 #include "gzstate.h"
27 #include "gxcspace.h" /* here for gscolor2.h */
28 #include "gsalpha.h"
29 #include "gscolor2.h"
30 #include "gscoord.h" /* for gs_initmatrix */
31 #include "gscie.h"
32 #include "gscssub.h"
33 #include "gxclipsr.h"
34 #include "gxcmap.h"
35 #include "gxdevice.h"
36 #include "gxpcache.h"
37 #include "gzht.h"
38 #include "gzline.h"
39 #include "gspath.h"
40 #include "gzpath.h"
41 #include "gzcpath.h"
42
43 /* Forward references */
44 private gs_state *gstate_alloc(P3(gs_memory_t *, client_name_t,
45 const gs_state *));
46 private gs_state *gstate_clone(P4(gs_state *, gs_memory_t *, client_name_t,
47 gs_state_copy_reason_t));
48 private void gstate_free_contents(P1(gs_state *));
49 private int gstate_copy(P4(gs_state *, const gs_state *,
50 gs_state_copy_reason_t, client_name_t));
51
52 /*
53 * Graphics state storage management is complicated. There are many
54 * different classes of storage associated with a graphics state:
55 *
56 * (1) The gstate object itself. This includes some objects physically
57 * embedded within the gstate object, but because of garbage collection
58 * requirements, there are no embedded objects that can be
59 * referenced by non-transient pointers. We assume that the gstate
60 * stack "owns" its gstates and that we can free the top gstate when
61 * doing a restore.
62 *
63 * (2) Objects that are referenced directly by the gstate and whose lifetime
64 * is independent of the gstate. These are garbage collected, not
65 * reference counted, so we don't need to do anything special with them
66 * when manipulating gstates. Currently this includes:
67 * font, device
68 *
69 * (3) Objects that are referenced directly by the gstate, may be shared
70 * among gstates, and should disappear when no gstates reference them.
71 * These fall into two groups:
72 *
73 * (3a) Objects that are logically connected to individual gstates.
74 * We use reference counting to manage these. Currently these are:
75 * halftone, dev_ht, cie_render, black_generation,
76 * undercolor_removal, set_transfer.*, cie_joint_caches,
77 * clip_stack, {opacity,shape}.mask
78 * effective_transfer.* may point to some of the same objects as
79 * set_transfer.*, but don't contribute to the reference count.
80 * Similarly, dev_color may point to the dev_ht object. For
81 * simplicity, we initialize all of these pointers to 0 and then
82 * allocate the object itself when needed.
83 *
84 * (3b) Objects whose lifetimes are associated with something else.
85 * Currently these are:
86 * ht_cache, which is associated with the entire gstate
87 * stack, is allocated with the very first graphics state,
88 * and currently is never freed;
89 * pattern_cache, which is associated with the entire
90 * stack, is allocated when first needed, and currently
91 * is never freed;
92 * view_clip, which is associated with the current
93 * save level (effectively, with the gstate sub-stack
94 * back to the save) and is managed specially;
95 * transparency_stack, which is associated with the entire
96 * stack but only stored in the topmost graphics state.
97 *
98 * (4) Objects that are referenced directly by exactly one gstate and that
99 * are not referenced (except transiently) from any other object.
100 * These fall into two groups:
101 *
102 * (4b) Objects allocated individually, for the given reason:
103 * line_params.dash.pattern (variable-length),
104 * color_space, path, clip_path, effective_clip.path,
105 * ccolor, dev_color
106 * (may be referenced from image enumerators or elsewhere)
107 *
108 * (4b) The "client data" for a gstate. For the interpreter, this is
109 * the refs associated with the gstate, such as the screen procedures.
110 * Client-supplied procedures manage client data.
111 *
112 * (5) Objects referenced indirectly from gstate objects of category (4),
113 * including objects that may also be referenced directly by the gstate.
114 * The individual routines that manipulate these are responsible
115 * for doing the right kind of reference counting or whatever.
116 * Currently:
117 * path, clip_path, and (if different from both clip_path
118 * and view_clip) effective_clip.path require
119 * gx_path_assign/free, which uses a reference count;
120 * color_space and ccolor require cs_adjust_color/cspace_count
121 * or cs_adjust_counts, which use a reference count;
122 * dev_color has no references to storage that it owns.
123 * We count on garbage collection or restore to deallocate
124 * sub-objects of halftone.
125 *
126 * Note that when after a gsave, the existing gstate references the related
127 * objects that we allocate at the same time, and the newly allocated gstate
128 * references the old related objects. Similarly, during a grestore, we
129 * free the related objects referenced by the current gstate, but after the
130 * grestore, we free the saved gstate, not the current one. However, when
131 * we allocate gstates off-stack, the newly allocated gstate does reference
132 * the newly allocated component objects. Note also that setgstate /
133 * currentgstate may produce gstates in which different allocators own
134 * different sub-objects; this is OK, because restore guarantees that there
135 * won't be any dangling pointers (as long as we don't allow pointers from
136 * global gstates to local objects).
137 */
138
139 /*
140 * Define these elements of the graphics state that are allocated
141 * individually for each state, except for line_params.dash.pattern.
142 * Note that effective_clip_shared is not on the list.
143 */
144 typedef struct gs_state_parts_s {
145 gx_path *path;
146 gx_clip_path *clip_path;
147 gx_clip_path *effective_clip_path;
148 gs_color_space *color_space;
149 gs_client_color *ccolor;
150 gx_device_color *dev_color;
151 } gs_state_parts;
152
153 #define GSTATE_ASSIGN_PARTS(pto, pfrom)\
154 ((pto)->path = (pfrom)->path, (pto)->clip_path = (pfrom)->clip_path,\
155 (pto)->effective_clip_path = (pfrom)->effective_clip_path,\
156 (pto)->color_space = (pfrom)->color_space,\
157 (pto)->ccolor = (pfrom)->ccolor, (pto)->dev_color = (pfrom)->dev_color)
158
159 /* GC descriptors */
160 extern_st(st_imager_state);
161 public_st_gs_state();
162
163 /* GC procedures for gs_state */
164 private ENUM_PTRS_WITH(gs_state_enum_ptrs, gs_state *gsvptr)
165 ENUM_PREFIX(st_imager_state, gs_state_num_ptrs + 2);
166 #define e1(i,elt) ENUM_PTR(i,gs_state,elt);
167 gs_state_do_ptrs(e1)
168 case gs_state_num_ptrs: /* handle device specially */
169 ENUM_RETURN(gx_device_enum_ptr(gsvptr->device));
170 case gs_state_num_ptrs + 1: /* handle device filter stack specially */
171 ENUM_RETURN(gsvptr->dfilter_stack);
172 #undef e1
173 ENUM_PTRS_END
RELOC_PTRS_WITH(gs_state_reloc_ptrs,gs_state * gsvptr)174 private RELOC_PTRS_WITH(gs_state_reloc_ptrs, gs_state *gsvptr)
175 {
176 RELOC_PREFIX(st_imager_state);
177 {
178 #define r1(i,elt) RELOC_PTR(gs_state,elt);
179 gs_state_do_ptrs(r1)
180 #undef r1
181 gsvptr->device = gx_device_reloc_ptr(gsvptr->device, gcst);
182 RELOC_PTR(gs_state, dfilter_stack);
183 }
184 }
185 RELOC_PTRS_END
186
187 /* Copy client data, using the copy_for procedure if available, */
188 /* the copy procedure otherwise. */
189 private int
gstate_copy_client_data(gs_state * pgs,void * dto,void * dfrom,gs_state_copy_reason_t reason)190 gstate_copy_client_data(gs_state * pgs, void *dto, void *dfrom,
191 gs_state_copy_reason_t reason)
192 {
193 return (pgs->client_procs.copy_for != 0 ?
194 (*pgs->client_procs.copy_for) (dto, dfrom, reason) :
195 (*pgs->client_procs.copy) (dto, dfrom));
196 }
197
198 /* ------ Operations on the entire graphics state ------ */
199
200 /* Define the initial value of the graphics state. */
201 private const gs_imager_state gstate_initial = {
202 gs_imager_state_initial(1.0)
203 };
204
205 /*
206 * Allocate a path for the graphics state. We use stable memory because
207 * some PostScript files have Type 3 fonts whose BuildChar procedure
208 * uses the sequence save ... setcachedevice ... restore, and the path
209 * built between the setcachedevice and the restore must not be freed.
210 * If it weren't for this, we don't think stable memory would be needed.
211 */
212 private gs_memory_t *
gstate_path_memory(gs_memory_t * mem)213 gstate_path_memory(gs_memory_t *mem)
214 {
215 return gs_memory_stable(mem);
216 }
217
218 /* Allocate and initialize a graphics state. */
219 gs_state *
gs_state_alloc(gs_memory_t * mem)220 gs_state_alloc(gs_memory_t * mem)
221 {
222 gs_state *pgs = gstate_alloc(mem, "gs_state_alloc", NULL);
223 int code;
224
225 if (pgs == 0)
226 return 0;
227 pgs->saved = 0;
228 *(gs_imager_state *)pgs = gstate_initial;
229
230 /*
231 * Just enough of the state is initialized at this point
232 * that it's OK to call gs_state_free if an allocation fails.
233 */
234
235 code = gs_imager_state_initialize((gs_imager_state *) pgs, mem);
236 if (code < 0)
237 goto fail;
238
239 /* Finish initializing the color rendering state. */
240
241 rc_alloc_struct_1(pgs->halftone, gs_halftone, &st_halftone, mem,
242 goto fail, "gs_state_alloc(halftone)");
243 pgs->halftone->type = ht_type_none;
244 pgs->ht_cache = gx_ht_alloc_cache(mem,
245 gx_ht_cache_default_tiles(),
246 gx_ht_cache_default_bits());
247
248 /* Initialize other things not covered by initgraphics */
249
250 pgs->path = gx_path_alloc(gstate_path_memory(mem), "gs_state_alloc(path)");
251 pgs->clip_path = gx_cpath_alloc(mem, "gs_state_alloc(clip_path)");
252 pgs->clip_stack = 0;
253 pgs->view_clip = gx_cpath_alloc(mem, "gs_state_alloc(view_clip)");
254 pgs->view_clip->rule = 0; /* no clipping */
255 pgs->effective_clip_id = pgs->clip_path->id;
256 pgs->effective_view_clip_id = gs_no_id;
257 pgs->effective_clip_path = pgs->clip_path;
258 pgs->effective_clip_shared = true;
259 /* Initialize things so that gx_remap_color won't crash. */
260 gs_cspace_init_DeviceGray(pgs->color_space);
261 {
262 int i;
263
264 for (i = 0; i < countof(pgs->device_color_spaces.indexed); ++i)
265 pgs->device_color_spaces.indexed[i] = 0;
266 }
267 gx_set_device_color_1(pgs);
268 pgs->device = 0; /* setting device adjusts refcts */
269 gs_nulldevice(pgs);
270 gs_setalpha(pgs, 1.0);
271 gs_settransfer(pgs, gs_identity_transfer);
272 gs_setflat(pgs, 1.0);
273 gs_setfilladjust(pgs, 0.25, 0.25);
274 gs_setlimitclamp(pgs, false);
275 gs_setstrokeadjust(pgs, true);
276 pgs->font = 0; /* Not right, but acceptable until the */
277 /* PostScript code does the first setfont. */
278 pgs->root_font = 0; /* ditto */
279 pgs->in_cachedevice = 0;
280 pgs->in_charpath = (gs_char_path_mode) 0;
281 pgs->show_gstate = 0;
282 pgs->level = 0;
283 pgs->dfilter_stack = 0;
284 pgs->transparency_group_stack = 0;
285 if (gs_initgraphics(pgs) >= 0)
286 return pgs;
287 /* Something went very wrong. */
288 fail:
289 gs_state_free(pgs);
290 return 0;
291 }
292
293 /* Set the client data in a graphics state. */
294 /* This should only be done to a newly created state. */
295 void
gs_state_set_client(gs_state * pgs,void * pdata,const gs_state_client_procs * pprocs)296 gs_state_set_client(gs_state * pgs, void *pdata,
297 const gs_state_client_procs * pprocs)
298 {
299 pgs->client_data = pdata;
300 pgs->client_procs = *pprocs;
301 }
302
303 /* Get the client data from a graphics state. */
304 #undef gs_state_client_data /* gzstate.h makes this a macro */
305 void *
gs_state_client_data(const gs_state * pgs)306 gs_state_client_data(const gs_state * pgs)
307 {
308 return pgs->client_data;
309 }
310
311 /* Free a graphics state. */
312 int
gs_state_free(gs_state * pgs)313 gs_state_free(gs_state * pgs)
314 {
315 gstate_free_contents(pgs);
316 gs_free_object(pgs->memory, pgs, "gs_state_free");
317 return 0;
318 }
319
320 /* Save the graphics state. */
321 int
gs_gsave(gs_state * pgs)322 gs_gsave(gs_state * pgs)
323 {
324 gs_state *pnew = gstate_clone(pgs, pgs->memory, "gs_gsave",
325 copy_for_gsave);
326
327 if (pnew == 0)
328 return_error(gs_error_VMerror);
329 /*
330 * It isn't clear from the Adobe documentation whether gsave retains
331 * the current clip stack or clears it. The following statement
332 * bets on the latter. If it's the former, this should become
333 * rc_increment(pnew->clip_stack);
334 */
335 pnew->clip_stack = 0;
336 pgs->saved = pnew;
337 if (pgs->show_gstate == pgs)
338 pgs->show_gstate = pnew->show_gstate = pnew;
339 pgs->level++;
340 if_debug2('g', "[g]gsave -> 0x%lx, level = %d\n",
341 (ulong) pnew, pgs->level);
342 return 0;
343 }
344
345 /*
346 * Save the graphics state for a 'save'.
347 * We cut the stack below the new gstate, and return the old one.
348 * In addition to an ordinary gsave, we create a new view clip path.
349 */
350 int
gs_gsave_for_save(gs_state * pgs,gs_state ** psaved)351 gs_gsave_for_save(gs_state * pgs, gs_state ** psaved)
352 {
353 int code;
354 gx_clip_path *old_cpath = pgs->view_clip;
355 gx_clip_path *new_cpath;
356 gx_device_color_spaces_t save_spaces;
357 int i;
358
359 if (old_cpath) {
360 new_cpath =
361 gx_cpath_alloc_shared(old_cpath, pgs->memory,
362 "gs_gsave_for_save(view_clip)");
363 if (new_cpath == 0)
364 return_error(gs_error_VMerror);
365 } else {
366 new_cpath = 0;
367 }
368 code = gs_gsave(pgs);
369 if (code < 0)
370 goto fail;
371 for (i = 0; i < countof(save_spaces.indexed); ++i) {
372 gs_color_space *pcs = pgs->device_color_spaces.indexed[i];
373
374 if (pcs) {
375 pgs->device_color_spaces.indexed[i] = 0;
376 code = gs_setsubstitutecolorspace(pgs, (gs_color_space_index)i,
377 pcs);
378 if (code < 0) {
379 /*
380 * Patch the second saved pointer so we won't try to
381 * gsave after the grestore.
382 */
383 if (pgs->saved->saved == 0)
384 pgs->saved->saved = pgs;
385 gs_grestore(pgs);
386 if (pgs->saved == pgs)
387 pgs->saved = 0;
388 goto fail;
389 }
390 }
391 }
392 if (pgs->effective_clip_path == pgs->view_clip)
393 pgs->effective_clip_path = new_cpath;
394 pgs->view_clip = new_cpath;
395 /* Cut the stack so we can't grestore past here. */
396 *psaved = pgs->saved;
397 pgs->saved = 0;
398 return code;
399 fail:
400 if (new_cpath)
401 gx_cpath_free(new_cpath, "gs_gsave_for_save(view_clip)");
402 return code;
403 }
404
405 /* Restore the graphics state. Can fully empty graphics stack */
406 int /* return 0 if ok, 1 if stack was empty */
gs_grestore_only(gs_state * pgs)407 gs_grestore_only(gs_state * pgs)
408 {
409 gs_state *saved = pgs->saved;
410 void *pdata = pgs->client_data;
411 void *sdata;
412 gs_transparency_state_t *tstack = pgs->transparency_stack;
413
414 if_debug2('g', "[g]grestore 0x%lx, level was %d\n",
415 (ulong) saved, pgs->level);
416 if (!saved)
417 return 1;
418 sdata = saved->client_data;
419 if (saved->pattern_cache == 0)
420 saved->pattern_cache = pgs->pattern_cache;
421 /* Swap back the client data pointers. */
422 pgs->client_data = sdata;
423 saved->client_data = pdata;
424 if (pdata != 0 && sdata != 0)
425 gstate_copy_client_data(pgs, pdata, sdata, copy_for_grestore);
426 gstate_free_contents(pgs);
427 *pgs = *saved;
428 pgs->transparency_stack = tstack;
429 if (pgs->show_gstate == saved)
430 pgs->show_gstate = pgs;
431 gs_free_object(pgs->memory, saved, "gs_grestore");
432 return 0;
433 }
434
435 /* Restore the graphics state per PostScript semantics */
436 int
gs_grestore(gs_state * pgs)437 gs_grestore(gs_state * pgs)
438 {
439 int code;
440 if (!pgs->saved)
441 return gs_gsave(pgs); /* shouldn't ever happen */
442 code = gs_grestore_only(pgs);
443 if (code < 0)
444 return code;
445
446 /* Wraparound: make sure there are always >= 1 saves on stack */
447 if (pgs->saved)
448 return 0;
449 return gs_gsave(pgs);
450 }
451
452 /* Restore the graphics state for a 'restore', splicing the old stack */
453 /* back on. Note that we actually do a grestoreall + 2 grestores. */
454 int
gs_grestoreall_for_restore(gs_state * pgs,gs_state * saved)455 gs_grestoreall_for_restore(gs_state * pgs, gs_state * saved)
456 {
457 int code;
458 gx_device_color_spaces_t freed_spaces;
459
460 while (pgs->saved->saved) {
461 code = gs_grestore(pgs);
462 if (code < 0)
463 return code;
464 }
465 /* Make sure we don't leave dangling pointers in the caches. */
466 gx_ht_clear_cache(pgs->ht_cache);
467 if (pgs->pattern_cache)
468 (*pgs->pattern_cache->free_all) (pgs->pattern_cache);
469 pgs->saved->saved = saved;
470 freed_spaces = pgs->device_color_spaces;
471 code = gs_grestore(pgs);
472 if (code < 0)
473 return code;
474 gx_device_color_spaces_free(&freed_spaces, pgs->memory,
475 "gs_grestoreall_for_restore");
476 if (pgs->view_clip) {
477 gx_cpath_free(pgs->view_clip, "gs_grestoreall_for_restore");
478 pgs->view_clip = 0;
479 }
480 return gs_grestore(pgs);
481 }
482
483
484 /* Restore to the bottommost graphics state (at this save level). */
485 int
gs_grestoreall(gs_state * pgs)486 gs_grestoreall(gs_state * pgs)
487 {
488 if (!pgs->saved) /* shouldn't happen */
489 return gs_gsave(pgs);
490 while (pgs->saved->saved) {
491 int code = gs_grestore(pgs);
492
493 if (code < 0)
494 return code;
495 }
496 return gs_grestore(pgs);
497 }
498
499 /* Allocate and return a new graphics state. */
500 gs_state *
gs_gstate(gs_state * pgs)501 gs_gstate(gs_state * pgs)
502 {
503 gs_state *copied = gs_state_copy(pgs, pgs->memory);
504 int i;
505
506 if (copied == 0)
507 return 0;
508 /* Don't capture the substituted color spaces. */
509 for (i = 0; i < countof(copied->device_color_spaces.indexed); ++i)
510 copied->device_color_spaces.indexed[i] = 0;
511 return copied;
512 }
513 gs_state *
gs_state_copy(gs_state * pgs,gs_memory_t * mem)514 gs_state_copy(gs_state * pgs, gs_memory_t * mem)
515 {
516 gs_state *pnew;
517 /* Prevent 'capturing' the view clip path. */
518 gx_clip_path *view_clip = pgs->view_clip;
519
520 pgs->view_clip = 0;
521 pnew = gstate_clone(pgs, mem, "gs_gstate", copy_for_gstate);
522 rc_increment(pnew->clip_stack);
523 pgs->view_clip = view_clip;
524 if (pnew == 0)
525 return 0;
526 pnew->saved = 0;
527 /*
528 * Prevent dangling references from the show_gstate pointer. If
529 * this context is its own show_gstate, set the pointer in the clone
530 * to point to the clone; otherwise, set the pointer in the clone to
531 * 0, and let gs_setgstate fix it up.
532 */
533 pnew->show_gstate =
534 (pgs->show_gstate == pgs ? pnew : 0);
535 return pnew;
536 }
537
538 /* Copy one previously allocated graphics state to another. */
539 int
gs_copygstate(gs_state * pto,const gs_state * pfrom)540 gs_copygstate(gs_state * pto, const gs_state * pfrom)
541 {
542 return gstate_copy(pto, pfrom, copy_for_copygstate, "gs_copygstate");
543 }
544
545 /* Copy the current graphics state to a previously allocated one. */
546 int
gs_currentgstate(gs_state * pto,const gs_state * pgs)547 gs_currentgstate(gs_state * pto, const gs_state * pgs)
548 {
549 int code =
550 gstate_copy(pto, pgs, copy_for_currentgstate, "gs_currentgstate");
551
552 if (code >= 0)
553 pto->view_clip = 0;
554 return code;
555 }
556
557 /* Restore the current graphics state from a previously allocated one. */
558 int
gs_setgstate(gs_state * pgs,const gs_state * pfrom)559 gs_setgstate(gs_state * pgs, const gs_state * pfrom)
560 {
561 /*
562 * The implementation is the same as currentgstate,
563 * except we must preserve the saved pointer, the level,
564 * the view clip, and possibly the show_gstate.
565 */
566 gs_state *saved_show = pgs->show_gstate;
567 int level = pgs->level;
568 gx_clip_path *view_clip = pgs->view_clip;
569 gs_transparency_state_t *tstack = pgs->transparency_stack;
570 int code;
571
572 pgs->view_clip = 0; /* prevent refcount decrementing */
573 code = gstate_copy(pgs, pfrom, copy_for_setgstate, "gs_setgstate");
574 if (code < 0)
575 return code;
576 pgs->level = level;
577 pgs->view_clip = view_clip;
578 pgs->show_gstate =
579 (pgs->show_gstate == pfrom ? pgs : saved_show);
580 pgs->transparency_stack = tstack;
581 return 0;
582 }
583
584 /* Get the allocator pointer of a graphics state. */
585 /* This is provided only for the interpreter */
586 /* and for color space implementation. */
587 gs_memory_t *
gs_state_memory(const gs_state * pgs)588 gs_state_memory(const gs_state * pgs)
589 {
590 return pgs->memory;
591 }
592
593 /* Get the saved pointer of the graphics state. */
594 /* This is provided only for Level 2 grestore. */
595 gs_state *
gs_state_saved(const gs_state * pgs)596 gs_state_saved(const gs_state * pgs)
597 {
598 return pgs->saved;
599 }
600
601 /* Swap the saved pointer of the graphics state. */
602 /* This is provided only for save/restore. */
603 gs_state *
gs_state_swap_saved(gs_state * pgs,gs_state * new_saved)604 gs_state_swap_saved(gs_state * pgs, gs_state * new_saved)
605 {
606 gs_state *saved = pgs->saved;
607
608 pgs->saved = new_saved;
609 return saved;
610 }
611
612 /* Swap the memory pointer of the graphics state. */
613 /* This is provided only for the interpreter. */
614 gs_memory_t *
gs_state_swap_memory(gs_state * pgs,gs_memory_t * mem)615 gs_state_swap_memory(gs_state * pgs, gs_memory_t * mem)
616 {
617 gs_memory_t *memory = pgs->memory;
618
619 pgs->memory = mem;
620 return memory;
621 }
622
623 /* ------ Operations on components ------ */
624
625 /* Reset most of the graphics state */
626 int
gs_initgraphics(gs_state * pgs)627 gs_initgraphics(gs_state * pgs)
628 {
629 int code;
630
631 gs_initmatrix(pgs);
632 if ((code = gs_newpath(pgs)) < 0 ||
633 (code = gs_initclip(pgs)) < 0 ||
634 (code = gs_setlinewidth(pgs, 1.0)) < 0 ||
635 (code = gs_setlinecap(pgs, gstate_initial.line_params.cap)) < 0 ||
636 (code = gs_setlinejoin(pgs, gstate_initial.line_params.join)) < 0 ||
637 (code = gs_setcurvejoin(pgs, gstate_initial.line_params.curve_join)) < 0 ||
638 (code = gs_setdash(pgs, (float *)0, 0, 0.0)) < 0 ||
639 (gs_setdashadapt(pgs, false),
640 (code = gs_setdotlength(pgs, 0.0, false))) < 0 ||
641 (code = gs_setdotorientation(pgs)) < 0 ||
642 (code = gs_setgray(pgs, 0.0)) < 0 ||
643 (code = gs_setmiterlimit(pgs, gstate_initial.line_params.miter_limit)) < 0
644 )
645 return code;
646 gs_init_rop(pgs);
647 return 0;
648 }
649
650 /* setfilladjust */
651 int
gs_setfilladjust(gs_state * pgs,floatp adjust_x,floatp adjust_y)652 gs_setfilladjust(gs_state * pgs, floatp adjust_x, floatp adjust_y)
653 {
654 #define CLAMP_TO_HALF(v)\
655 ((v) <= 0 ? fixed_0 : (v) >= 0.5 ? fixed_half : float2fixed(v));
656
657 pgs->fill_adjust.x = CLAMP_TO_HALF(adjust_x);
658 pgs->fill_adjust.y = CLAMP_TO_HALF(adjust_y);
659 return 0;
660 #undef CLAMP_TO_HALF
661 }
662
663 /* currentfilladjust */
664 int
gs_currentfilladjust(const gs_state * pgs,gs_point * adjust)665 gs_currentfilladjust(const gs_state * pgs, gs_point * adjust)
666 {
667 adjust->x = fixed2float(pgs->fill_adjust.x);
668 adjust->y = fixed2float(pgs->fill_adjust.y);
669 return 0;
670 }
671
672 /* setlimitclamp */
673 void
gs_setlimitclamp(gs_state * pgs,bool clamp)674 gs_setlimitclamp(gs_state * pgs, bool clamp)
675 {
676 pgs->clamp_coordinates = clamp;
677 }
678
679 /* currentlimitclamp */
680 bool
gs_currentlimitclamp(const gs_state * pgs)681 gs_currentlimitclamp(const gs_state * pgs)
682 {
683 return pgs->clamp_coordinates;
684 }
685
686 /* ------ Internal routines ------ */
687
688 /* Free the privately allocated parts of a gstate. */
689 private void
gstate_free_parts(const gs_state * parts,gs_memory_t * mem,client_name_t cname)690 gstate_free_parts(const gs_state * parts, gs_memory_t * mem, client_name_t cname)
691 {
692 gs_free_object(mem, parts->dev_color, cname);
693 gs_free_object(mem, parts->ccolor, cname);
694 gs_free_object(mem, parts->color_space, cname);
695 if (!parts->effective_clip_shared)
696 gx_cpath_free(parts->effective_clip_path, cname);
697 gx_cpath_free(parts->clip_path, cname);
698 gx_path_free(parts->path, cname);
699 }
700
701 /* Allocate the privately allocated parts of a gstate. */
702 private int
gstate_alloc_parts(gs_state * parts,const gs_state * shared,gs_memory_t * mem,client_name_t cname)703 gstate_alloc_parts(gs_state * parts, const gs_state * shared,
704 gs_memory_t * mem, client_name_t cname)
705 {
706 gs_memory_t *path_mem = gstate_path_memory(mem);
707
708 parts->path =
709 (shared ?
710 gx_path_alloc_shared(shared->path, path_mem,
711 "gstate_alloc_parts(path)") :
712 gx_path_alloc(path_mem, "gstate_alloc_parts(path)"));
713 parts->clip_path =
714 (shared ?
715 gx_cpath_alloc_shared(shared->clip_path, mem,
716 "gstate_alloc_parts(clip_path)") :
717 gx_cpath_alloc(mem, "gstate_alloc_parts(clip_path)"));
718 if (!shared || shared->effective_clip_shared) {
719 parts->effective_clip_path = parts->clip_path;
720 parts->effective_clip_shared = true;
721 } else {
722 parts->effective_clip_path =
723 gx_cpath_alloc_shared(shared->effective_clip_path, mem,
724 "gstate_alloc_parts(effective_clip_path)");
725 parts->effective_clip_shared = false;
726 }
727 parts->color_space =
728 gs_alloc_struct(mem, gs_color_space, &st_color_space, cname);
729 parts->ccolor =
730 gs_alloc_struct(mem, gs_client_color, &st_client_color, cname);
731 parts->dev_color =
732 gs_alloc_struct(mem, gx_device_color, &st_device_color, cname);
733 if (parts->path == 0 || parts->clip_path == 0 ||
734 parts->effective_clip_path == 0 ||
735 parts->color_space == 0 || parts->ccolor == 0 ||
736 parts->dev_color == 0
737 ) {
738 gstate_free_parts(parts, mem, cname);
739 return_error(gs_error_VMerror);
740 }
741 return 0;
742 }
743
744 /*
745 * Allocate a gstate and its contents.
746 * If pfrom is not NULL, the path, clip_path, and (if distinct from both
747 * clip_path and view_clip) effective_clip_path share the segments of
748 * pfrom's corresponding path(s).
749 */
750 private gs_state *
gstate_alloc(gs_memory_t * mem,client_name_t cname,const gs_state * pfrom)751 gstate_alloc(gs_memory_t * mem, client_name_t cname, const gs_state * pfrom)
752 {
753 gs_state *pgs =
754 gs_alloc_struct(mem, gs_state, &st_gs_state, cname);
755
756 if (pgs == 0)
757 return 0;
758 if (gstate_alloc_parts(pgs, pfrom, mem, cname) < 0) {
759 gs_free_object(mem, pgs, cname);
760 return 0;
761 }
762 pgs->memory = mem;
763 return pgs;
764 }
765
766 /* Copy the dash pattern from one gstate to another. */
767 private int
gstate_copy_dash(gs_state * pto,const gs_state * pfrom)768 gstate_copy_dash(gs_state * pto, const gs_state * pfrom)
769 {
770 return gs_setdash(pto, pfrom->line_params.dash.pattern,
771 pfrom->line_params.dash.pattern_size,
772 pfrom->line_params.dash.offset);
773 }
774
775 /* Clone an existing graphics state. */
776 /* Return 0 if the allocation fails. */
777 /* If reason is for_gsave, the clone refers to the old contents, */
778 /* and we switch the old state to refer to the new contents. */
779 private gs_state *
gstate_clone(gs_state * pfrom,gs_memory_t * mem,client_name_t cname,gs_state_copy_reason_t reason)780 gstate_clone(gs_state * pfrom, gs_memory_t * mem, client_name_t cname,
781 gs_state_copy_reason_t reason)
782 {
783 gs_state *pgs = gstate_alloc(mem, cname, pfrom);
784 gs_state_parts parts;
785
786 if (pgs == 0)
787 return 0;
788 GSTATE_ASSIGN_PARTS(&parts, pgs);
789 *pgs = *pfrom;
790 pgs->transparency_stack = 0;
791 /* Copy the dash pattern if necessary. */
792 if (pgs->line_params.dash.pattern) {
793 int code;
794
795 pgs->line_params.dash.pattern = 0; /* force allocation */
796 code = gstate_copy_dash(pgs, pfrom);
797 if (code < 0)
798 goto fail;
799 }
800 if (pgs->client_data != 0) {
801 void *pdata = pgs->client_data = (*pgs->client_procs.alloc) (mem);
802
803 if (pdata == 0 ||
804 gstate_copy_client_data(pgs, pdata, pfrom->client_data, reason) < 0
805 )
806 goto fail;
807 }
808 gs_imager_state_copied((gs_imager_state *)pgs);
809 /* Don't do anything to clip_stack. */
810 rc_increment(pgs->device);
811 *parts.color_space = *pfrom->color_space;
812 *parts.ccolor = *pfrom->ccolor;
813 *parts.dev_color = *pfrom->dev_color;
814 if (reason == copy_for_gsave) {
815 float *dfrom = pfrom->line_params.dash.pattern;
816 float *dto = pgs->line_params.dash.pattern;
817
818 GSTATE_ASSIGN_PARTS(pfrom, &parts);
819 pgs->line_params.dash.pattern = dfrom;
820 pfrom->line_params.dash.pattern = dto;
821 } else {
822 GSTATE_ASSIGN_PARTS(pgs, &parts);
823 }
824 cs_adjust_counts(pgs, 1);
825 return pgs;
826 fail:
827 gs_free_object(mem, pgs->line_params.dash.pattern, cname);
828 GSTATE_ASSIGN_PARTS(pgs, &parts);
829 gstate_free_parts(pgs, mem, cname);
830 gs_free_object(mem, pgs, cname);
831 return 0;
832 }
833
834 /* Release the composite parts of a graphics state, */
835 /* but not the state itself. */
836 private void
gstate_free_contents(gs_state * pgs)837 gstate_free_contents(gs_state * pgs)
838 {
839 gs_memory_t *mem = pgs->memory;
840 const char *const cname = "gstate_free_contents";
841
842 rc_decrement(pgs->device, cname);
843 rc_decrement(pgs->clip_stack, cname);
844 cs_adjust_counts(pgs, -1);
845 if (pgs->client_data != 0)
846 (*pgs->client_procs.free) (pgs->client_data, mem);
847 gs_free_object(mem, pgs->line_params.dash.pattern, cname);
848 gstate_free_parts(pgs, mem, cname);
849 gs_imager_state_release((gs_imager_state *)pgs);
850 }
851
852 /* Copy one gstate to another. */
853 private int
gstate_copy(gs_state * pto,const gs_state * pfrom,gs_state_copy_reason_t reason,client_name_t cname)854 gstate_copy(gs_state * pto, const gs_state * pfrom,
855 gs_state_copy_reason_t reason, client_name_t cname)
856 {
857 gs_state_parts parts;
858 gx_device_color_spaces_t saved_spaces;
859
860 GSTATE_ASSIGN_PARTS(&parts, pto);
861 saved_spaces = pto->device_color_spaces;
862 /* Copy the dash pattern if necessary. */
863 if (pfrom->line_params.dash.pattern || pto->line_params.dash.pattern) {
864 int code = gstate_copy_dash(pto, pfrom);
865
866 if (code < 0)
867 return code;
868 }
869 /*
870 * It's OK to decrement the counts before incrementing them,
871 * because anything that is going to survive has a count of
872 * at least 2 (pto and somewhere else) initially.
873 * Handle references from contents.
874 */
875 cs_adjust_counts(pto, -1);
876 gx_path_assign_preserve(pto->path, pfrom->path);
877 gx_cpath_assign_preserve(pto->clip_path, pfrom->clip_path);
878 /*
879 * effective_clip_shared will be copied, but we need to do the
880 * right thing with effective_clip_path.
881 */
882 if (pfrom->effective_clip_shared) {
883 /*
884 * pfrom->effective_clip_path is either pfrom->view_clip or
885 * pfrom->clip_path.
886 */
887 parts.effective_clip_path =
888 (pfrom->effective_clip_path == pfrom->view_clip ?
889 pto->view_clip : parts.clip_path);
890 } else
891 gx_cpath_assign_preserve(pto->effective_clip_path,
892 pfrom->effective_clip_path);
893 *parts.color_space = *pfrom->color_space;
894 *parts.ccolor = *pfrom->ccolor;
895 *parts.dev_color = *pfrom->dev_color;
896 cs_adjust_counts(pto, 1);
897 /* Handle references from gstate object. */
898 #define RCCOPY(element)\
899 rc_pre_assign(pto->element, pfrom->element, cname)
900 RCCOPY(device);
901 RCCOPY(clip_stack);
902 {
903 struct gx_pattern_cache_s *pcache = pto->pattern_cache;
904 void *pdata = pto->client_data;
905 gs_memory_t *mem = pto->memory;
906 gs_state *saved = pto->saved;
907 float *pattern = pto->line_params.dash.pattern;
908
909 gs_imager_state_pre_assign((gs_imager_state *)pto,
910 (gs_imager_state *)pfrom);
911 *pto = *pfrom;
912 pto->client_data = pdata;
913 pto->memory = mem;
914 pto->saved = saved;
915 pto->line_params.dash.pattern = pattern;
916 if (pto->pattern_cache == 0)
917 pto->pattern_cache = pcache;
918 if (pfrom->client_data != 0) {
919 /* We need to break 'const' here. */
920 gstate_copy_client_data((gs_state *) pfrom, pdata,
921 pfrom->client_data, reason);
922 }
923 }
924 GSTATE_ASSIGN_PARTS(pto, &parts);
925 pto->device_color_spaces = saved_spaces;
926 #undef RCCOPY
927 pto->show_gstate =
928 (pfrom->show_gstate == pfrom ? pto : 0);
929 return 0;
930 }
931