home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / UsingPDF / GhostScript / source / gs5.10 / gsstate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-17  |  32.9 KB  |  1,047 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gsstate.c */
  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 "gscolor2.h"
  29. #include "gscoord.h"        /* for gs_initmatrix */
  30. #include "gscie.h"
  31. #include "gxcmap.h"
  32. #include "gxdevice.h"
  33. #include "gxpcache.h"
  34. #include "gzht.h"
  35. #include "gzline.h"
  36. #include "gspath.h"
  37. #include "gzpath.h"
  38. #include "gzcpath.h"
  39.  
  40. /* Imported values */
  41. /* The following should include a 'const', but for some reason */
  42. /* the Watcom compiler won't accept it, even though it happily accepts */
  43. /* the same construct everywhere else. */
  44. extern /*const*/ gx_color_map_procs *cmap_procs_default;
  45.  
  46. /* Forward references */
  47. private gs_state *gstate_alloc(P2(gs_memory_t *, client_name_t));
  48. private void gstate_set_contents(P2(gs_state *, gs_state_contents *));
  49. private gs_state *gstate_clone(P4(gs_state *, gs_memory_t *, client_name_t,
  50.                   gs_state_copy_reason_t));
  51. private void gstate_free_contents(P1(gs_state *));
  52. private void gstate_share_paths(P1(const gs_state *));
  53. private int gstate_copy(P4(gs_state *, const gs_state *,
  54.                gs_state_copy_reason_t, client_name_t));
  55.  
  56. /*
  57.  * Graphics state storage management is complicated.  There are many
  58.  * different classes of storage associated with a graphics state:
  59.  *
  60.  * (1) The gstate object itself.  This includes some objects physically
  61.  *    embedded within the gstate object, but because of garbage collection
  62.  *    requirements, there are no embedded objects that can be
  63.  *    referenced by non-transient pointers.  We assume that the gstate
  64.  *    stack "owns" its gstates and that we can free the top gstate when
  65.  *    doing a restore.
  66.  *
  67.  * (2) Objects that are referenced directly by the gstate and whose lifetime
  68.  *    is independent of the gstate.  These are garbage collected, not
  69.  *    reference counted, so we don't need to do anything special with them
  70.  *    when manipulating gstates.  Currently this includes:
  71.  *        font, device
  72.  *
  73.  * (3) Objects that are referenced directly by the gstate, may be shared
  74.  *    among gstates, and should disappear when no gstates reference them.
  75.  *    These fall into two groups:
  76.  *
  77.  *   (3a) Objects that are logically connected to individual gstates.
  78.  *    We use reference counting to manage these.  Currently these are:
  79.  *        halftone, dev_ht, cie_render, black_generation,
  80.  *        undercolor_removal, set_transfer.*, cie_joint_caches
  81.  *    effective_transfer.* may point to some of the same objects as
  82.  *    set_transfer.*, but don't contribute to the reference count.
  83.  *    Similarly, dev_color may point to the dev_ht object.  For
  84.  *    simplicity, we initialize all of these pointers to 0 and then
  85.  *    allocate the object itself when needed.
  86.  *
  87.  *   (3b) Objects whose lifetimes are associated with something else.
  88.  *    Currently these are:
  89.  *        ht_cache, which is associated with the entire gstate
  90.  *          stack, is allocated with the very first graphics state,
  91.  *          and currently is never freed;
  92.  *        pattern_cache, which is associated with the entire
  93.  *          stack, is allocated when first needed, and currently
  94.  *          is never freed;
  95.  */
  96. #ifdef DPNEXT
  97. /*
  98.  *        view_clip, which is associated with the current
  99.  *          save level (effectively, with the gstate sub-stack
  100.  *          back to the save) and is managed specially;
  101.  *        saved_view_clip, which is only used in the gstate on the
  102.  *          top of a stack saved by 'save'.
  103.  */
  104. #endif
  105. /* (4) Objects that are referenced directly by exactly one gstate and that
  106.  *    are not referenced (except transiently) from any other object.
  107.  *    These fall into three groups:
  108.  *
  109.  *   (4a) Objects lumped into a single gs_state_contents object in order
  110.  *    to reduce the load on the allocator for gsave and grestore.  Each
  111.  *    gs_gstate_contents is referenced by exactly one gstate, and nowhere
  112.  *    else.  We reference the individual members through pointers, just as
  113.  *    though they were allocated individually, so that we wouldn't have to
  114.  *    keep remembering to put & in front of references to its components,
  115.  *    which would otherwise have to be embedded in the gstate object.
  116.  *    Again, we do not allow non-transient references to the objects
  117.  *    embedded in this object, aside from a single pointer from the gstate
  118.  *    object to each embedded component.  Currently these are:
  119.  *        path, clip_path, ccolor, dev_color
  120.  *
  121.  *   (4b) Objects allocated individually:
  122.  *        line_params.dash.pattern, color_space
  123.  *    color_space is a special case because it is referenced both
  124.  *    directly and also indirectly from image enumerators.
  125.  *    line_params.dash.pattern is also a special case, because it is
  126.  *    variable-length.  Otherwise, we could include these elements in
  127.  *    the contents object (4a).
  128.  *
  129.  *   (4c) The "client data" for a gstate.  For the interpreter, this is
  130.  *    the refs associated with the gstate, such as the screen procedures.
  131.  *    Client-supplied procedures manage client data.
  132.  *
  133.  * (5) Objects referenced indirectly from gstate objects of category (4),
  134.  *    including objects that may also be referenced directly by the gstate.
  135.  *    The individual routines that manipulate these are responsible
  136.  *    for doing the right kind of reference counting or whatever.
  137.  *    Currently:
  138.  *        path and clip_path require gx_path_share/release,
  139.  *          which use a 1-bit reference count;
  140.  *        color_space and ccolor require cs_adjust_color/cspace_count
  141.  *          or cs_adjust_counts, which use a full reference count;
  142.  *        dev_color has no references to storage that it owns.
  143.  *    We count on garbage collection or restore to deallocate
  144.  *      sub-objects of halftone.
  145.  *
  146.  * This situation is unnecessarily complicated.  We should get rid of
  147.  * the contents object and use reference counting to manage individually
  148.  * the objects it currently contains.  We should use full reference
  149.  * counting for paths, and use the freeing procedure to release the
  150.  * individual path elements.  However, making these changes runs a large
  151.  * risk of introducing hard-to-find bugs, so we don't plan to make them
  152.  * in the foreseeable future.
  153.  *
  154.  * Note that when we do a gsave, the newly allocated gstate doesn't
  155.  * necessarily reference the related objects that we allocate at the same
  156.  * time; in particular, the old contents go with the new gstate object and
  157.  * vice versa.  The same is true of grestore.  However, when we allocate
  158.  * gstates off-stack, the newly allocated gstate does reference the newly
  159.  * allocated component objects.  Note also that setgstate / currentgstate
  160.  * may produce gstates in which different allocators own different
  161.  * sub-objects; this is OK, because restore guarantees that there won't
  162.  * be any dangling pointers (as long as we don't allow pointers from
  163.  * global gstates to local objects).
  164.  */
  165.  
  166. /* The structure for allocating (most of) the contents of a gstate */
  167. /* all at once.  The typedef is in gzstate.c. */
  168. struct gs_state_contents_s {
  169.     gx_path path;
  170.     gx_clip_path clip_path;
  171.     gs_client_color ccolor;
  172.     gx_device_color dev_color;
  173. };
  174.  
  175. /* Enumerate the pointers in a graphics state, other than the ones */
  176. /* that point to the gs_state_contents and the ones in the imager state. */
  177. #ifdef DPNEXT
  178. #define gs_state_do_ptrs(m)\
  179.   m(0,saved) m(1,contents)\
  180.   /*m(---,path)*/ /*m(---,clip_path)*/\
  181.   m(2,color_space)\
  182.   /*m(---,client_color)*/ /*m(---,dev_color)*/\
  183.   m(3,font) m(4,root_font) m(5,show_gstate) /*m(---,device)*/\
  184.   m(6,client_data) m(7,view_clip) m(8,saved_view_clip)
  185. #define gs_state_num_ptrs 9
  186. #else
  187. #define gs_state_do_ptrs(m)\
  188.   m(0,saved) m(1,contents)\
  189.   /*m(---,path)*/ /*m(---,clip_path)*/\
  190.   m(2,color_space)\
  191.   /*m(---,client_color)*/ /*m(---,dev_color)*/\
  192.   m(3,font) m(4,root_font) m(5,show_gstate) /*m(---,device)*/\
  193.   m(6,client_data)
  194. #define gs_state_num_ptrs 7
  195. #endif
  196. /* Enumerate the pointers to the gs_state_contents. */
  197. #define gs_state_do_contents_ptrs(m)\
  198.   m(0,path) m(1,clip_path) m(2,ccolor) m(3,dev_color)
  199.  
  200. /* GC descriptors */
  201. private_st_line_params();
  202. private_st_imager_state();
  203. private_st_gs_state();
  204. #ifdef DPNEXT
  205. private_st_gx_clip_state();
  206. #endif
  207.  
  208. /* GC procedures for gs_imager_state */
  209. #define pis ((gs_imager_state *)vptr)
  210. private ENUM_PTRS_BEGIN(imager_state_enum_ptrs) ENUM_SUPER(gs_imager_state, st_line_params, line_params, st_imager_state_num_ptrs - st_line_params_num_ptrs);
  211. #define e1(i,elt) ENUM_PTR(i,gs_imager_state,elt);
  212.     gs_cr_state_do_ptrs(e1)
  213. #undef e1
  214. ENUM_PTRS_END
  215. private RELOC_PTRS_BEGIN(imager_state_reloc_ptrs) {
  216.     RELOC_SUPER(gs_imager_state, st_line_params, line_params);
  217. #define r1(i,elt) RELOC_PTR(gs_imager_state,elt);
  218.     gs_cr_state_do_ptrs(r1)
  219. #undef r1
  220. } RELOC_PTRS_END
  221. #undef pis
  222.  
  223. /* Components of the graphics state */
  224. gs_private_st_composite(st_gs_state_contents, gs_state_contents,
  225.   "gs_state_contents", state_contents_enum_ptrs, state_contents_reloc_ptrs);
  226. public_st_transfer_map();
  227.  
  228. /* GC procedures for gs_state */
  229. #define gsvptr ((gs_state *)vptr)
  230. private ENUM_PTRS_BEGIN(gs_state_enum_ptrs) ENUM_PREFIX(st_imager_state, gs_state_num_ptrs + 1);
  231. #define e1(i,elt) ENUM_PTR(i,gs_state,elt);
  232.     gs_state_do_ptrs(e1)
  233.     case gs_state_num_ptrs:        /* handle device specially */
  234.       ENUM_RETURN(gx_device_enum_ptr(gsvptr->device));
  235. #undef e1
  236. ENUM_PTRS_END
  237. private RELOC_PTRS_BEGIN(gs_state_reloc_ptrs) {
  238.     RELOC_PREFIX(st_imager_state);
  239.     { /* Save the contents pointer before relocation. */
  240.       byte *cont = (byte *)gsvptr->contents;
  241.       long reloc;
  242. #define r1(i,elt) RELOC_PTR(gs_state,elt);
  243.       gs_state_do_ptrs(r1)
  244. #undef r1
  245.       gsvptr->device = gx_device_reloc_ptr(gsvptr->device, gcst);
  246.       /* Now relocate the pointers into the contents. */
  247.       reloc = cont - (byte *)gsvptr->contents;
  248. #define r1(i,elt)\
  249.   gsvptr->elt = (void *)((byte *)gsvptr->elt - reloc);
  250.       gs_state_do_contents_ptrs(r1)
  251. #undef r1
  252.     }
  253. } RELOC_PTRS_END
  254. #undef gsvptr
  255.  
  256. /* GC procedures for gs_state_contents */
  257. #define cptr ((gs_state_contents *)vptr)
  258. private ENUM_PTRS_BEGIN_PROC(state_contents_enum_ptrs) {
  259.     gs_ptr_type_t ret;
  260. #define next_comp(np, st, e)\
  261.   if ( index < np ) { ret = (*st.enum_ptrs)(&cptr->e, sizeof(cptr->e), index, pep); goto rx; }\
  262.   index -= np
  263. #define last_comp(np, st, e)\
  264.   return (*st.enum_ptrs)(&cptr->e, sizeof(cptr->e), index, pep)
  265.     next_comp(st_path_max_ptrs, st_path, path);
  266.     next_comp(st_clip_path_max_ptrs, st_clip_path, clip_path);
  267.     next_comp(st_client_color_max_ptrs, st_client_color, ccolor);
  268.     last_comp(st_device_color_max_ptrs, st_device_color, dev_color);
  269. #undef next_comp
  270. #undef last_comp
  271. rx:    if ( ret == 0 )
  272.     {    /* A component ran out of pointers early. */
  273.         /* Just return a null so we can keep going. */
  274.         *pep = 0;
  275.         return ptr_struct_type;
  276.     }
  277.     return ret;
  278. ENUM_PTRS_END_PROC }
  279. private RELOC_PTRS_BEGIN(state_contents_reloc_ptrs) {
  280.     (*st_path.reloc_ptrs)(&cptr->path, sizeof(gx_path), gcst);
  281.     (*st_clip_path.reloc_ptrs)(&cptr->clip_path, sizeof(gx_clip_path), gcst);
  282.     (*st_client_color.reloc_ptrs)(&cptr->ccolor, sizeof(gs_client_color), gcst);
  283.     (*st_device_color.reloc_ptrs)(&cptr->dev_color, sizeof(gx_device_color), gcst);
  284. } RELOC_PTRS_END
  285. #undef cptr
  286.  
  287. /* Copy client data, using the copy_for procedure if available, */
  288. /* the copy procedure otherwise. */
  289. private int near
  290. gstate_copy_client_data(gs_state *pgs, void *dto, void *dfrom,
  291.   gs_state_copy_reason_t reason)
  292. {    return (pgs->client_procs.copy_for != 0 ?
  293.         (*pgs->client_procs.copy_for)(dto, dfrom, reason) :
  294.         (*pgs->client_procs.copy)(dto, dfrom));
  295. }
  296.  
  297. /* ------ Operations on the entire graphics state ------ */
  298.  
  299. /* Initialize an imager state, other than the parts covered by */
  300. /* gs_imager_state_initial. */
  301. /* The halftone, dev_ht, and ht_cache elements are not set or used. */
  302. private float
  303. null_transfer(floatp gray, const gx_transfer_map *pmap)
  304. {    return gray;
  305. }
  306. int
  307. gs_imager_state_initialize(gs_imager_state *pis, gs_memory_t *mem)
  308. {    pis->memory = mem;
  309.     /* Skip halftone */
  310.     { int i;
  311.       for ( i = 0; i < gs_color_select_count; ++i )
  312.         pis->screen_phase[i].x = pis->screen_phase[i].y = 0;
  313.     }
  314.     /* Skip dev_ht */
  315.     /* Skip ht_cache */
  316.     pis->cie_render = 0;
  317.     pis->black_generation = 0;
  318.     pis->undercolor_removal = 0;
  319.     /* Allocate an initial transfer map. */
  320.     rc_alloc_struct_n(pis->set_transfer.colored.gray,
  321.               gx_transfer_map, &st_transfer_map,
  322.               mem, return_error(gs_error_VMerror),
  323.               "gs_imager_state_init(transfer)", 4);
  324.     pis->set_transfer.colored.gray->proc = null_transfer;
  325.     pis->set_transfer.colored.gray->id = gs_next_ids(1);
  326.     pis->set_transfer.colored.gray->values[0] = frac_0;
  327.     pis->set_transfer.colored.red =
  328.       pis->set_transfer.colored.green =
  329.       pis->set_transfer.colored.blue =
  330.       pis->set_transfer.colored.gray;
  331.     pis->effective_transfer = pis->set_transfer;
  332.     pis->cie_joint_caches = 0;
  333.     pis->cmap_procs = cmap_procs_default;
  334.     pis->pattern_cache = 0;
  335.     return 0;
  336. }
  337.  
  338. /* Release an imager state. */
  339. void
  340. gs_imager_state_release(gs_imager_state *pis)
  341. {    static const char cname[] = "gs_imager_state_release";
  342. #define rcdecr(element)\
  343.   rc_decrement(pis->element, cname)
  344.  
  345.     rcdecr(cie_joint_caches);
  346.     rcdecr(set_transfer.colored.gray);
  347.     rcdecr(set_transfer.colored.blue);
  348.     rcdecr(set_transfer.colored.green);
  349.     rcdecr(set_transfer.colored.red);
  350.     rcdecr(undercolor_removal);
  351.     rcdecr(black_generation);
  352.     rcdecr(cie_render);
  353. #undef rcdecr
  354. }
  355.  
  356. /* Allocate and initialize a graphics state. */
  357. gs_state *
  358. gs_state_alloc(gs_memory_t *mem)
  359. {    gs_state *pgs = gstate_alloc(mem, "gs_state_alloc");
  360.  
  361.     if ( pgs == 0 )
  362.       return 0;
  363.     { static const gs_imager_state gstate_initial =
  364.         { gs_imager_state_initial(1.0) };
  365.       *(gs_imager_state *)pgs = gstate_initial;
  366.     }
  367.     /* Just enough of the state is initialized at this point */
  368.     /* that it's OK to call gs_state_free if an allocation fails. */
  369.     rc_alloc_struct_1(pgs->halftone, gs_halftone, &st_halftone, mem,
  370.               goto fail, "gs_state_alloc(halftone)");
  371.     pgs->saved = 0;
  372.     gstate_set_contents(pgs, pgs->contents);
  373.  
  374.     /* Initialize the color rendering state, except for elements */
  375.     /* which are in the gs_state contents (halftone). */
  376.  
  377.     pgs->halftone->type = ht_type_none;
  378.     pgs->dev_ht = 0;
  379.     pgs->ht_cache = gx_ht_alloc_cache(mem,
  380.                       gx_ht_cache_default_tiles(),
  381.                       gx_ht_cache_default_bits());
  382.     gs_imager_state_initialize((gs_imager_state *)pgs, mem);
  383.     pgs->client_data = 0;
  384.  
  385.     /* Initialize other things not covered by initgraphics */
  386.  
  387.     gx_path_init(pgs->path, mem);
  388.     gx_cpath_init(pgs->clip_path, mem);
  389. #ifdef DPNEXT
  390.     rc_alloc_struct_1(pgs->view_clip, gx_clip_state, &st_gx_clip_state,
  391.               mem, goto fail, "gs_state_alloc(view_clip)");
  392.     pgs->view_clip->path =
  393.       gs_alloc_struct(mem, gx_clip_path, &st_clip_path,
  394.               "gs_state_alloc(view_clip path)");
  395.     if ( pgs->view_clip->path == 0 )
  396.       goto fail;
  397.     gx_cpath_init(pgs->view_clip->path, mem);
  398.     pgs->saved_view_clip = 0;
  399. #endif
  400.     /* Initialize things so that gx_remap_color won't crash. */
  401.     pgs->color_space->type = &gs_color_space_type_DeviceGray;
  402.     gx_set_device_color_1(pgs);
  403.     pgs->overprint = false;
  404.     gs_nulldevice(pgs);
  405.     gs_setalpha(pgs, 1.0);
  406.     gs_settransfer(pgs, null_transfer);
  407.     gs_setflat(pgs, 1.0);
  408.     gs_setfilladjust(pgs, 0.25, 0.25);
  409.     gs_setlimitclamp(pgs, false);
  410.     gs_setstrokeadjust(pgs, true);
  411.     pgs->font = 0;        /* Not right, but acceptable until the */
  412.                 /* PostScript code does the first setfont. */
  413.     pgs->root_font = 0;    /* ditto */
  414.     pgs->in_cachedevice = 0;
  415.     pgs->in_charpath = (gs_char_path_mode)0;
  416.     pgs->show_gstate = 0;
  417.     pgs->level = 0;
  418.     pgs->client_data = 0;
  419.     if ( gs_initgraphics(pgs) < 0 )
  420.        {    /* Something went very wrong */
  421.         return 0;
  422.        }
  423.     return pgs;
  424. fail:    gs_state_free(pgs);
  425.     return 0;
  426. }
  427.  
  428. /* Set the client data in a graphics state. */
  429. /* This should only be done to a newly created state. */
  430. void
  431. gs_state_set_client(gs_state *pgs, void *pdata,
  432.   const gs_state_client_procs *pprocs)
  433. {    pgs->client_data = pdata;
  434.     pgs->client_procs = *pprocs;
  435. }
  436.  
  437. /* Get the client data from a graphics state. */
  438. #undef gs_state_client_data        /* gzstate.h makes this a macro */
  439. void *
  440. gs_state_client_data(const gs_state *pgs)
  441. {    return pgs->client_data;
  442. }
  443.  
  444. /* Free a graphics state */
  445. #ifdef DPNEXT
  446. /* Note that we do not free the view clip path. */
  447. #endif
  448. int
  449. gs_state_free(gs_state *pgs)
  450. {    gstate_free_contents(pgs);
  451.     gs_free_object(pgs->memory, pgs, "gs_state_free");
  452.     return 0;
  453. }
  454.  
  455. /* Save the graphics state. */
  456. int
  457. gs_gsave(gs_state *pgs)
  458. {    gs_state *pnew = gstate_clone(pgs, pgs->memory, "gs_gsave",
  459.                       copy_for_gsave);
  460.  
  461.     if ( pnew == 0 )
  462.       return_error(gs_error_VMerror);
  463.     gx_path_share(pgs->path);
  464.     gx_cpath_share(pgs->clip_path);
  465.     pgs->saved = pnew;
  466.     if ( pgs->show_gstate == pgs )
  467.       pgs->show_gstate = pnew->show_gstate = pnew;
  468.     pgs->level++;
  469.     if_debug2('g', "[g]gsave -> 0x%lx, level = %d\n",
  470.           (ulong)pnew, pgs->level);
  471.     return 0;
  472. }
  473.  
  474. /* Save the graphics state for a 'save'. */
  475. /* We cut the stack below the new gstate, and return the old one. */
  476. #ifdef DPNEXT
  477. /* In addition to an ordinary gsave, we un-share the view clip path. */
  478. #endif
  479. int
  480. gs_gsave_for_save(gs_state *pgs, gs_state **psaved)
  481. {    int code;
  482. #ifdef DPNEXT
  483.     gx_clip_path *new_cpath =
  484.       gs_alloc_struct(pgs->memory, gx_clip_path, &st_clip_path,
  485.               "gs_gsave_for_save(view_clip path)");
  486.     gx_clip_path *old_cpath = pgs->view_clip->path;
  487.  
  488.     if ( new_cpath == 0 )
  489.       return_error(gs_error_VMerror);
  490.     code = gs_gsave(pgs);
  491.     if ( code < 0 ) {
  492.       gs_free_object(pgs->memory, new_cpath,
  493.              "gs_gsave_for_save(view_clip path)");
  494.       return code;
  495.     }
  496.     *new_cpath = *old_cpath;
  497.     gx_cpath_share(new_cpath);
  498.     pgs->saved->saved_view_clip = old_cpath;
  499.     pgs->view_clip->path = new_cpath;
  500. #else
  501.     code = gs_gsave(pgs);
  502.     if ( code < 0 )
  503.       return code;
  504. #endif
  505.     /* Cut the stack so we can't grestore past here. */
  506.     *psaved = pgs->saved;
  507.     pgs->saved = 0;
  508.     return code;
  509. }
  510.  
  511. /* Restore the graphics state. */
  512. int
  513. gs_grestore(gs_state *pgs)
  514. {    gs_state *saved = pgs->saved;
  515.     void *pdata = pgs->client_data;
  516.     void *sdata;
  517.  
  518.     if_debug2('g', "[g]grestore 0x%lx, level was %d\n",
  519.           (ulong)saved, pgs->level);
  520.     if ( !saved )        /* shouldn't happen */
  521.       return gs_gsave(pgs);
  522.     sdata = saved->client_data;
  523.     if ( saved->pattern_cache == 0 )
  524.       saved->pattern_cache = pgs->pattern_cache;
  525.     /* Swap back the client data pointers. */
  526.     pgs->client_data = sdata;
  527.     saved->client_data = pdata;
  528.     if ( pdata != 0 && sdata != 0 )
  529.       gstate_copy_client_data(pgs, pdata, sdata, copy_for_grestore);
  530.     gstate_free_contents(pgs);
  531.     *pgs = *saved;
  532.     if ( pgs->show_gstate == saved )
  533.       pgs->show_gstate = pgs;
  534.     gs_free_object(pgs->memory, saved, "gs_grestore");
  535.     if ( pgs->saved )
  536.       return 0;
  537.     return gs_gsave(pgs);
  538. }
  539.  
  540. /* Restore the graphics state for a 'restore', splicing the old stack */
  541. /* back on.  Note that we actually do 2 grestores. */
  542. #ifdef DPNEXT
  543. /* In addition to an ordinary grestore, we restore the view clip path. */
  544. #endif
  545. int
  546. gs_grestore2_for_restore(gs_state *pgs, gs_state *saved)
  547. {    int code;
  548.  
  549.     /* Check that the caller has done a grestoreall. */
  550.     if ( pgs->saved == 0 || pgs->saved->saved != 0 )
  551.       return_error(gs_error_Fatal);
  552. #ifdef DPNEXT
  553.     { gx_clip_path *cpath = pgs->view_clip->path;
  554.       gx_clip_path *saved_cpath = saved->saved_view_clip;
  555.  
  556.       gx_cpath_release(cpath);
  557.       if ( saved )
  558.         { pgs->view_clip->path = saved_cpath;
  559.           gs_free_object(pgs->memory, cpath,
  560.                  "grestore2_for_restore(view clip path)");
  561.           saved->saved_view_clip = 0;
  562.         }
  563.       else
  564.         { gx_cpath_init(cpath, pgs->memory);
  565.           cpath->rule = 0;
  566.         }
  567.     }
  568. #endif
  569.     pgs->saved->saved = saved;
  570.     code = gs_grestore(pgs);
  571.     if ( code < 0 )
  572.       return code;
  573.     return gs_grestore(pgs);
  574. }
  575.  
  576.  
  577. /* Restore to the bottommost graphics state.  Also clear */
  578. /* the halftone caches, so stale pointers don't survive a restore. */
  579. int
  580. gs_grestoreall(gs_state *pgs)
  581. {    int code;
  582.     if ( !pgs->saved )        /* shouldn't happen */
  583.       return gs_gsave(pgs);
  584.     while ( pgs->saved->saved )
  585.     {    int code = gs_grestore(pgs);
  586.         if ( code < 0 )
  587.           return code;
  588.     }
  589.     code = gs_grestore(pgs);
  590.     if ( code < 0 )
  591.       return code;
  592.     gx_ht_clear_cache(pgs->ht_cache);
  593.     if ( pgs->pattern_cache )
  594.       (*pgs->pattern_cache->free_all)(pgs->pattern_cache);
  595.     return code;
  596. }
  597.  
  598. /* Allocate and return a new graphics state. */
  599. gs_state *
  600. gs_gstate(gs_state *pgs)
  601. {    return gs_state_copy(pgs, pgs->memory);
  602. }
  603. gs_state *
  604. gs_state_copy(gs_state *pgs, gs_memory_t *mem)
  605. {    gs_state *pnew;
  606.  
  607. #if 0 /****************/
  608.     if ( mem == pgs->memory )
  609. #endif /****************/
  610.       gstate_share_paths(pgs);
  611.     pnew = gstate_clone(pgs, mem, "gs_gstate", copy_for_gstate);
  612.     if ( pnew == 0 )
  613.       return 0;
  614.     pnew->saved = 0;
  615.     /*
  616.      * Prevent dangling references from the show_gstate pointer.  If
  617.      * this context is its own show_gstate, set the pointer in the clone
  618.      * to point to the clone; otherwise, set the pointer in the clone to
  619.      * 0, and let gs_setgstate fix it up.
  620.      */
  621.     pnew->show_gstate =
  622.       (pgs->show_gstate == pgs ? pnew : 0);
  623.     return pnew;
  624. }
  625.  
  626. /* Copy one previously allocated graphics state to another. */
  627. int
  628. gs_copygstate(gs_state *pto, const gs_state *pfrom)
  629. {    return gstate_copy(pto, pfrom, copy_for_copygstate, "gs_copygstate");
  630. }
  631.  
  632. /* Copy the current graphics state to a previously allocated one. */
  633. int
  634. gs_currentgstate(gs_state *pto, const gs_state *pgs)
  635. {    gstate_share_paths(pgs);
  636.     return gstate_copy(pto, pgs, copy_for_currentgstate, "gs_currentgstate");
  637. }
  638.  
  639. /* Restore the current graphics state from a previously allocated one. */
  640. int
  641. gs_setgstate(gs_state *pgs, const gs_state *pfrom)
  642. {    /*
  643.      * The implementation is the same as currentgstate,
  644.      * except we must preserve the saved pointer, the level,
  645.      * and possibly the show_gstate.
  646.      */
  647.     gs_state *saved_show = pgs->show_gstate;
  648.     int level = pgs->level;
  649.     int code = gstate_copy(pgs, pfrom, copy_for_setgstate, "gs_setgstate");
  650.  
  651.     if ( code < 0 )
  652.       return code;
  653.     pgs->level = level;
  654.     pgs->show_gstate =
  655.       (pgs->show_gstate == pfrom ? pgs : saved_show);
  656.     return 0;
  657. }
  658.  
  659. /* Get the allocator pointer of a graphics state. */
  660. /* This is provided only for the interpreter */
  661. /* and for color space implementation. */
  662. gs_memory_t *
  663. gs_state_memory(const gs_state *pgs)
  664. {    return pgs->memory;
  665. }
  666.  
  667. /* Get the saved pointer of the graphics state. */
  668. /* This is provided only for Level 2 grestore. */
  669. gs_state *
  670. gs_state_saved(const gs_state *pgs)
  671. {    return pgs->saved;
  672. }
  673.  
  674. /* Swap the saved pointer of the graphics state. */
  675. /* This is provided only for save/restore. */
  676. gs_state *
  677. gs_state_swap_saved(gs_state *pgs, gs_state *new_saved)
  678. {    gs_state *saved = pgs->saved;
  679.     pgs->saved = new_saved;
  680.     return saved;
  681. }
  682.  
  683. /* Swap the memory pointer of the graphics state. */
  684. /* This is provided only for the interpreter. */
  685. gs_memory_t *
  686. gs_state_swap_memory(gs_state *pgs, gs_memory_t *mem)
  687. {    gs_memory_t *memory = pgs->memory;
  688.     pgs->memory = mem;
  689.     return memory;
  690. }
  691.  
  692. /* ------ Operations on components ------ */
  693.  
  694. /* Reset most of the graphics state */
  695. int
  696. gs_initgraphics(gs_state *pgs)
  697. {    int code;
  698.     gs_initmatrix(pgs);
  699.     if (    (code = gs_newpath(pgs)) < 0 ||
  700.         (code = gs_initclip(pgs)) < 0 ||
  701.         (code = gs_setlinewidth(pgs, 1.0)) < 0 ||
  702.         (code = gs_setlinecap(pgs, gs_cap_butt)) < 0 ||
  703.         (code = gs_setlinejoin(pgs, gs_join_miter)) < 0 ||
  704.         (code = gs_setdash(pgs, (float *)0, 0, 0.0)) < 0 ||
  705.         (gs_setdashadapt(pgs, false),
  706.          (code = gs_setdotlength(pgs, 0.0, false))) < 0 ||
  707.         (code = gs_setgray(pgs, 0.0)) < 0 ||
  708.         (code = gs_setmiterlimit(pgs, 10.0)) < 0
  709.        )
  710.       return code;
  711.     gs_init_rop(pgs);
  712.     return 0;
  713. }
  714.  
  715. /* setfilladjust */
  716. int
  717. gs_setfilladjust(gs_state *pgs, floatp adjust_x, floatp adjust_y)
  718. {
  719. #define adjust_fill_adjust(v)\
  720.   if ( v < 0 ) v = 0; else if ( v > 0.5 ) v = 0.5
  721.     adjust_fill_adjust(adjust_x);
  722.     pgs->fill_adjust.x = float2fixed(adjust_x);
  723.     adjust_fill_adjust(adjust_y);
  724.     pgs->fill_adjust.y = float2fixed(adjust_y);
  725.     return 0;
  726. }
  727.  
  728. /* currentfilladjust */
  729. int
  730. gs_currentfilladjust(const gs_state *pgs, gs_point *adjust)
  731. {    adjust->x = fixed2float(pgs->fill_adjust.x);
  732.     adjust->y = fixed2float(pgs->fill_adjust.y);
  733.     return 0;
  734. }
  735.  
  736. /* setlimitclamp */
  737. void
  738. gs_setlimitclamp(gs_state *pgs, bool clamp)
  739. {    pgs->clamp_coordinates = clamp;
  740. }
  741.  
  742. /* currentlimitclamp */
  743. bool
  744. gs_currentlimitclamp(const gs_state *pgs)
  745. {    return pgs->clamp_coordinates;
  746. }
  747.  
  748. /* ------ Internal routines ------ */
  749.  
  750. /* Allocate a gstate and its contents. */
  751. private gs_state *
  752. gstate_alloc(gs_memory_t *mem, client_name_t cname)
  753. {    gs_state *pgs =
  754.       gs_alloc_struct(mem, gs_state, &st_gs_state, cname);
  755.     gs_state_contents *cont =
  756.       gs_alloc_struct(mem, gs_state_contents, &st_gs_state_contents, cname);
  757.     gs_color_space *pcs =
  758.       gs_alloc_struct(mem, gs_color_space, &st_color_space, cname);
  759.  
  760.     if ( pgs == 0 || cont == 0 || pcs == 0 )
  761.       {    gs_free_object(mem, pcs, cname);
  762.         gs_free_object(mem, cont, cname);
  763.         gs_free_object(mem, pgs, cname);
  764.         return 0;
  765.       }
  766.     pgs->memory = mem;
  767.     pgs->contents = cont;
  768.     pgs->color_space = pcs;
  769.     return pgs;
  770. }
  771.  
  772. /* Set the contents pointers of a gstate. */
  773. private void
  774. gstate_set_contents(gs_state *pgs, gs_state_contents *cont)
  775. {    pgs->contents = cont;
  776. #define gset(element)\
  777.   pgs->element = &cont->element;
  778.     gset(path);
  779.     gset(clip_path);
  780.     gset(ccolor);
  781.     gset(dev_color);
  782. #undef gset
  783. }
  784.  
  785. /* Copy the dash pattern from one gstate to another. */
  786. private int
  787. gstate_copy_dash(gs_state *pto, const gs_state *pfrom)
  788. {    return gs_setdash(pto, pfrom->line_params.dash.pattern,
  789.               pfrom->line_params.dash.pattern_size,
  790.               pfrom->line_params.dash.offset);
  791. }
  792.  
  793. /* Clone an existing graphics state. */
  794. /* Return 0 if the allocation fails. */
  795. /* The client is responsible for calling gx_[c]path_share on */
  796. /* whichever of the old and new paths is appropriate. */
  797. /* If reason is for_gsave, the clone refers to the old contents, */
  798. /* and we switch the old state to refer to the new contents. */
  799. private gs_state *
  800. gstate_clone(gs_state *pfrom, gs_memory_t *mem, client_name_t cname,
  801.   gs_state_copy_reason_t reason)
  802. {    gs_state_contents *cfrom = pfrom->contents;
  803.     gs_color_space *csfrom = pfrom->color_space;
  804.     gs_state *pgs = gstate_alloc(mem, cname);
  805.     gs_state_contents *cont;
  806.     gs_color_space *pcs;
  807.  
  808.     if ( pgs == 0 )
  809.       return 0;
  810.     cont = pgs->contents;
  811.     pcs = pgs->color_space;
  812.     /* Increment references from gstate object. */
  813.     *pgs = *pfrom;
  814.     /* Copy the dash pattern if necessary. */
  815.     if ( pgs->line_params.dash.pattern )
  816.       { int code;
  817.         pgs->line_params.dash.pattern = 0; /* force allocation */
  818.         code = gstate_copy_dash(pgs, pfrom);
  819.         if ( code < 0 )
  820.           goto fail;
  821.       }
  822.     if ( pgs->client_data != 0 )
  823.     {    void *pdata = pgs->client_data =
  824.           (*pgs->client_procs.alloc)(mem);
  825.         if ( pdata == 0 ||
  826.              gstate_copy_client_data(pgs, pdata, pfrom->client_data, reason) < 0
  827.            )
  828.           goto fail;
  829.     }
  830.     rc_increment(pgs->set_transfer.colored.gray);
  831.     rc_increment(pgs->set_transfer.colored.red);
  832.     rc_increment(pgs->set_transfer.colored.green);
  833.     rc_increment(pgs->set_transfer.colored.blue);
  834.     rc_increment(pgs->halftone);
  835.     rc_increment(pgs->dev_ht);
  836.     rc_increment(pgs->cie_render);
  837.     rc_increment(pgs->black_generation);
  838.     rc_increment(pgs->undercolor_removal);
  839.     rc_increment(pgs->cie_joint_caches);
  840.     if ( reason == copy_for_gsave )
  841.       {    float *dfrom = pfrom->line_params.dash.pattern;
  842.         float *dto = pgs->line_params.dash.pattern;
  843.  
  844.         gstate_set_contents(pgs, cfrom);
  845.         pgs->color_space = csfrom;
  846.         pgs->line_params.dash.pattern = dfrom;
  847.         gstate_set_contents(pfrom, cont);
  848.         pfrom->color_space = pcs;
  849.         pfrom->line_params.dash.pattern = dto;
  850.       }
  851.     else
  852.       {    gstate_set_contents(pgs, cont);
  853.         pgs->color_space = pcs;
  854.       }
  855.     *cont = *cfrom;
  856.     *pcs = *csfrom;
  857.     cs_adjust_counts(pgs, 1);
  858. #ifdef DPNEXT
  859.     rc_increment(pgs->view_clip);
  860. #endif
  861.     return pgs;
  862. fail:    gs_free_object(mem, pgs->line_params.dash.pattern, cname);
  863.     gs_free_object(mem, pcs, cname);
  864.     gs_free_object(mem, cont, cname);
  865.     gs_free_object(mem, pgs, cname);
  866.     return 0;
  867. }
  868.  
  869. /* Release the composite parts of a graphics state, */
  870. /* but not the state itself. */
  871. private void
  872. gstate_free_contents(gs_state *pgs)
  873. {    gs_memory_t *mem = pgs->memory;
  874.     static const char cname[] = "gstate_free_contents";
  875.     gx_device_halftone *pdht = pgs->dev_ht;
  876. #define rcdecr(element)\
  877.   rc_decrement(pgs->element, cname)
  878.  
  879.     gx_path_release(pgs->path);
  880.     gx_cpath_release(pgs->clip_path);
  881.     rcdecr(cie_joint_caches);
  882.     rcdecr(set_transfer.colored.gray);
  883.     rcdecr(set_transfer.colored.blue);
  884.     rcdecr(set_transfer.colored.green);
  885.     rcdecr(set_transfer.colored.red);
  886.     rcdecr(undercolor_removal);
  887.     rcdecr(black_generation);
  888.     rcdecr(cie_render);
  889.     if ( pdht != 0 && pdht->rc.ref_count == 1 )
  890.       { /* Make sure we don't leave dangling pointers in the cache. */
  891.         gx_ht_cache *pcache = pgs->ht_cache;
  892.  
  893.         if ( pcache->order.bits == pdht->order.bits ||
  894.          pcache->order.levels == pdht->order.levels
  895.            )
  896.           gx_ht_clear_cache(pcache);
  897.         gx_device_halftone_release(pdht, pdht->rc.memory);
  898.       }
  899.     rcdecr(dev_ht);
  900.     rcdecr(halftone);
  901. #ifdef DPNEXT
  902.     rcdecr(view_clip);
  903. #endif
  904.     cs_adjust_counts(pgs, -1);
  905.     if ( pgs->client_data != 0 )
  906.       (*pgs->client_procs.free)(pgs->client_data, mem);
  907.     gs_free_object(mem, pgs->line_params.dash.pattern, cname);
  908.     gs_free_object(mem, pgs->color_space, cname);
  909.     gs_free_object(mem, pgs->contents, cname);
  910. #undef rcdecr
  911. }
  912.  
  913. /*
  914.  * Mark both the old and new paths as shared when copying a gstate off-stack.
  915.  * If the old path was previously shared, we must search up
  916.  * the graphics state stack so we can mark its original ancestor
  917.  * as shared, because the off-stack copy defeats the one-bit
  918.  * reference count.
  919.  */
  920. private void
  921. gstate_share_paths(const gs_state *pgs)
  922. {    gx_path *ppath = pgs->path;
  923.     gx_clip_path *pcpath = pgs->clip_path;
  924.  
  925.     if ( ppath->shares_segments )
  926.       {    const gs_state *pcur;
  927.         const gs_state *prev;
  928.         const subpath *first;
  929.         for ( pcur = pgs, first = ppath->first_subpath;
  930.               (prev = pcur->saved) != 0 &&
  931.                 prev->path->first_subpath == first;
  932.               pcur = prev
  933.             )
  934.           if ( !prev->path->shares_segments )
  935.             {    gx_path_share(prev->path);
  936.             break;
  937.             }
  938.       }
  939.     else
  940.       gx_path_share(ppath);
  941.     /*
  942.      * If the clip path is a rectangle, free its path representation
  943.      * rather than copying it.
  944.      */
  945.     if ( pcpath->list.count <= 1 && pcpath->segments_valid )
  946.       { gx_path_release(&pcpath->path);
  947.         pcpath->segments_valid = false;
  948.       }
  949.     if ( pcpath->path.shares_segments )
  950.       {    const gs_state *pcur;
  951.         const gs_state *prev;
  952.         const subpath *first;
  953.         for ( pcur = pgs, first = pcpath->path.first_subpath;
  954.               (prev = pcur->saved) != 0 &&
  955.                 prev->clip_path->path.first_subpath == first;
  956.               pcur = prev
  957.             )
  958.           if ( !prev->clip_path->path.shares_segments )
  959.             {    gx_cpath_share(prev->clip_path);
  960.             break;
  961.             }
  962.       }
  963.     if ( pcpath->shares_list )
  964.       {    const gs_state *pcur;
  965.         const gs_state *prev;
  966.         const gx_clip_rect *head;
  967.         for ( pcur = pgs, head = pcpath->list.head;
  968.               (prev = pcur->saved) != 0 &&
  969.                 prev->clip_path->list.head == head;
  970.               pcur = prev
  971.             )
  972.           if ( !prev->clip_path->shares_list )
  973.             {    gx_cpath_share(prev->clip_path);
  974.             break;
  975.             }
  976.       }
  977.     gx_cpath_share(pcpath);
  978. }
  979.  
  980. /* Copy one gstate to another. */
  981. private int
  982. gstate_copy(gs_state *pto, const gs_state *pfrom,
  983.   gs_state_copy_reason_t reason, client_name_t cname)
  984. {    gs_state_contents *cto = pto->contents;
  985.     gs_color_space *csto = pto->color_space;
  986.  
  987.     /* Copy the dash pattern if necessary. */
  988.     if ( pfrom->line_params.dash.pattern || pto->line_params.dash.pattern )
  989.       { int code = gstate_copy_dash(pto, pfrom);
  990.         if ( code < 0 )
  991.           return 0;
  992.       }
  993.     /* It's OK to decrement the counts before incrementing them, */
  994.     /* because anything that is going to survive has a count of */
  995.     /* at least 2 (pto and somewhere else) initially. */
  996.     /* Handle references from contents. */
  997.     cs_adjust_counts(pto, -1);
  998.     gx_path_release(pto->path);
  999.     gx_cpath_release(pto->clip_path);
  1000.     *cto = *pfrom->contents;
  1001.     *csto = *pfrom->color_space;
  1002.     cs_adjust_counts(pto, 1);
  1003.     gx_path_share(pto->path);
  1004.     gx_cpath_share(pto->clip_path);
  1005.     /* Handle references from gstate object. */
  1006. #define rccopy(element)\
  1007.   rc_pre_assign(pto->element, pfrom->element, cname)
  1008.     rccopy(cie_joint_caches);
  1009.     rccopy(set_transfer.colored.gray);
  1010.     rccopy(set_transfer.colored.blue);
  1011.     rccopy(set_transfer.colored.green);
  1012.     rccopy(set_transfer.colored.red);
  1013.     rccopy(undercolor_removal);
  1014.     rccopy(black_generation);
  1015.     rccopy(cie_render);
  1016.     rccopy(dev_ht);
  1017.     rccopy(halftone);
  1018.     {    struct gx_pattern_cache_s *pcache = pto->pattern_cache;
  1019.         void *pdata = pto->client_data;
  1020.         gs_memory_t *mem = pto->memory;
  1021.         gs_state *saved = pto->saved;
  1022.         float *pattern = pto->line_params.dash.pattern;
  1023.  
  1024.         *pto = *pfrom;
  1025.         pto->client_data = pdata;
  1026.         pto->memory = mem;
  1027.         pto->saved = saved;
  1028.         pto->line_params.dash.pattern = pattern;
  1029.         if ( pto->pattern_cache == 0 )
  1030.           pto->pattern_cache = pcache;
  1031.         if ( pfrom->client_data != 0 )
  1032.           { /* We need to break 'const' here. */
  1033.             gstate_copy_client_data((gs_state *)pfrom, pdata,
  1034.                         pfrom->client_data, reason);
  1035.           }
  1036.     }
  1037.     gstate_set_contents(pto, cto);
  1038.     pto->color_space = csto;
  1039. #ifdef DPNEXT
  1040.     rccopy(view_clip);
  1041. #endif
  1042. #undef rccopy
  1043.     pto->show_gstate =
  1044.       (pfrom->show_gstate == pfrom ? pto : 0);
  1045.     return 0;
  1046. }
  1047.