1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
/* This file contains the closepl method, which is a standard part of
libplot. It closes a Plotter object. */
/* This generic version does only basic mechanics, since GenericPlotters
don't emit any graphics code. */
#include "sys-defines.h"
#include "extern.h"
int
#ifdef _HAVE_PROTOS
_API_closepl (S___(Plotter *_plotter))
#else
_API_closepl (S___(_plotter))
S___(Plotter *_plotter;)
#endif
{
bool emit_not_just_the_first_page = true;
bool retval1;
int retval2 = 0;
if (!_plotter->data->open)
{
_plotter->error (R___(_plotter)
"closepl: invalid operation");
return -1;
}
_API_endpath (S___(_plotter)); /* flush path if any */
/* pop drawing states in progress, if any, off the stack */
if (_plotter->drawstate->previous != NULL)
{
while (_plotter->drawstate->previous)
_API_restorestate (S___(_plotter));
}
/* invoke Plotter-specific method to end the page; also do
device-dependent teardown Plotter-specific drawing state variables, do
reinitialization of Plotter-specific Plotter variables, and create
page header and trailer if any */
retval1 = _plotter->end_page (S___(_plotter));
/* remove first drawing state too, so we can start afresh */
_delete_first_drawing_state (S___(_plotter));
switch ((int)_plotter->data->output_model)
{
case (int)PL_OUTPUT_NONE:
/* we don't do output, so just delete the page buffer (presumably it
includes neither a header nor a trailer) */
if (_plotter->data->page)
_delete_outbuf (_plotter->data->page);
_plotter->data->page = (plOutbuf *)NULL;
break;
case (int)PL_OUTPUT_ONE_PAGE:
emit_not_just_the_first_page = false;
/* fall through */
case (int)PL_OUTPUT_ONE_PAGE_AT_A_TIME:
if (_plotter->data->page
&& (emit_not_just_the_first_page
|| _plotter->data->page_number == 1))
{
/* emit page header if any */
if (_plotter->data->page->header
&& _plotter->data->page->header->len > 0)
_write_string (_plotter->data,
_plotter->data->page->header->base);
/* emit all the graphics on the page */
if (_plotter->data->page && _plotter->data->page->len > 0)
_write_string (_plotter->data, _plotter->data->page->base);
/* emit page trailer if any */
if (_plotter->data->page->trailer
&& _plotter->data->page->trailer->len > 0)
_write_string (_plotter->data,
_plotter->data->page->trailer->base);
/* attempt to flush (will test whether stream is jammed) */
retval2 = _API_flushpl (S___(_plotter));
}
/* delete page header if any */
if (_plotter->data->page->header)
_delete_outbuf (_plotter->data->page->header);
_plotter->data->page->header = (plOutbuf *)NULL;
/* delete page trailer if any */
if (_plotter->data->page->trailer)
_delete_outbuf (_plotter->data->page->trailer);
_plotter->data->page->trailer = (plOutbuf *)NULL;
/* delete page's plOutbuf */
if (_plotter->data->page)
_delete_outbuf (_plotter->data->page);
_plotter->data->page = (plOutbuf *)NULL;
break;
case (int)PL_OUTPUT_PAGES_ALL_AT_ONCE:
/* Plotter will do its own output, in its terminate() routine.
It will do so by writing out the contents of all its cached pages
(a new one gets added to the list each time openpl() is invoked).
So do nothing. */
break;
case (int)PL_OUTPUT_VIA_CUSTOM_ROUTINES:
case (int)PL_OUTPUT_VIA_CUSTOM_ROUTINES_IN_REAL_TIME:
/* Plotter does its own output, and doesn't use libplot's
plOutbuf-based output system. So do nothing, except
attempt to flush (will test whether stream is jammed) */
retval2 = _API_flushpl (S___(_plotter));
break;
case (int)PL_OUTPUT_VIA_CUSTOM_ROUTINES_TO_NON_STREAM:
/* Plotter doesn't use libplot's plOutbuf-based output system, and in
fact doesn't send output to a stream at all. So do nothing: don't
attempt to flush output; the drawing state [including
Plotter-specific data] has already been deleted, so there may not
be enough information to perform a flush. This is an issue with
X Plotters in particular. */
break;
default: /* shouldn't happen */
break;
}
_plotter->data->open = false; /* flag device as closed */
if (retval1 == false || retval2 < 0)
return -1;
else return 0;
}
/* Plotter-specific teardowns and reinitializations that take place when
closepl() is invoked. In a generic Plotter, this does nothing. */
bool
#ifdef _HAVE_PROTOS
_g_end_page (S___(Plotter *_plotter))
#else
_g_end_page (S___(_plotter))
S___(Plotter *_plotter;)
#endif
{
return true;
}
void
#ifdef _HAVE_PROTOS
_delete_first_drawing_state (S___(Plotter *_plotter))
#else
_delete_first_drawing_state (S___(_plotter))
S___(Plotter *_plotter;)
#endif
{
/* elements of state that are strings or arrays are freed separately */
free ((char *)_plotter->drawstate->fill_rule);
free ((char *)_plotter->drawstate->line_mode);
free ((char *)_plotter->drawstate->join_mode);
free ((char *)_plotter->drawstate->cap_mode);
free ((char *)_plotter->drawstate->true_font_name);
free ((char *)_plotter->drawstate->font_name);
/* free dash array too, if nonempty */
if (_plotter->drawstate->dash_array_len > 0)
free ((double *)_plotter->drawstate->dash_array);
/* free the state itself */
free (_plotter->drawstate);
_plotter->drawstate = NULL;
}
|