g_savestate.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* This file is part of the GNU plotutils package. Copyright (C) 1995,
  2. 1996, 1997, 1998, 1999, 2000, 2005, 2008, Free Software Foundation, Inc.
  3. The GNU plotutils package is free software. You may redistribute it
  4. and/or modify it under the terms of the GNU General Public License as
  5. published by the Free Software foundation; either version 2, or (at your
  6. option) any later version.
  7. The GNU plotutils package is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. General Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. with the GNU plotutils package; see the file COPYING. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  14. Boston, MA 02110-1301, USA. */
  15. /* This file contains the savestate method, which is a GNU extension to
  16. libplot. It creates a new drawing state and pushes it onto the stack of
  17. drawing states. By definition, a `drawing state' comprises the set of
  18. drawing attributes, and the state of any path being incrementally drawn.
  19. The new state will have the same drawing attributes as the old state.
  20. If a path was being drawn incrementally in the old state, the new state
  21. will not contain it. The old state may be returned to by invoking the
  22. restorestate routine, which pops drawing states off the stack. If the
  23. incremental drawing of a path was in progress, it may be returned to at
  24. that time.
  25. This version of savestate() assumes that the device-specific part of the
  26. drawing state contains no strings. Plotter objects for which this is
  27. not true must supplement this by defining push_state() appropriately,
  28. since they need to call malloc() to allocate space for the string in the
  29. new state. */
  30. /* This file also contains the restorestate method, which is a GNU
  31. extension to libplot. It pops off the drawing state on the top of the
  32. stack of drawing states. Drawing states (other than the one which is
  33. always present, and may not be popped off) are created and pushed onto
  34. the stack by invoking the savestate() routine.
  35. This version of restorestate() assumes that the device-specific part of
  36. the state contains no strings or other dynamically allocated data.
  37. Versions of libplot in which this is not true must supplement this by
  38. defining pop_state() appropriately, since they need to call free() to
  39. deallocate space for the strings. */
  40. /* N.B. The drawing state stack, during user use of libplot, always
  41. contains at least one drawing state. The first state is added by
  42. openpl() and deleted by closepl(). */
  43. #include "sys-defines.h"
  44. #include "extern.h"
  45. int
  46. _API_savestate(S___(Plotter *_plotter))
  47. {
  48. plDrawState *oldstate = _plotter->drawstate; /* non-NULL */
  49. plDrawState *drawstate;
  50. char *fill_rule, *line_mode, *join_mode, *cap_mode;
  51. char *font_name, *true_font_name;
  52. if (!_plotter->data->open)
  53. {
  54. _plotter->error (R___(_plotter)
  55. "savestate: invalid operation");
  56. return -1;
  57. }
  58. /* create a new state */
  59. drawstate = (plDrawState *)_pl_xmalloc (sizeof(plDrawState));
  60. /* copy from old state */
  61. memcpy (drawstate, oldstate, sizeof(plDrawState));
  62. /* elements of state that are strings are treated specially */
  63. fill_rule = (char *)_pl_xmalloc (strlen (oldstate->fill_rule) + 1);
  64. line_mode = (char *)_pl_xmalloc (strlen (oldstate->line_mode) + 1);
  65. join_mode = (char *)_pl_xmalloc (strlen (oldstate->join_mode) + 1);
  66. cap_mode = (char *)_pl_xmalloc (strlen (oldstate->cap_mode) + 1);
  67. strcpy (fill_rule, oldstate->fill_rule);
  68. strcpy (line_mode, oldstate->line_mode);
  69. strcpy (join_mode, oldstate->join_mode);
  70. strcpy (cap_mode, oldstate->cap_mode);
  71. drawstate->fill_rule = fill_rule;
  72. drawstate->line_mode = line_mode;
  73. drawstate->join_mode = join_mode;
  74. drawstate->cap_mode = cap_mode;
  75. /* dash array, if non-empty, is treated specially too */
  76. if (oldstate->dash_array_len > 0)
  77. {
  78. int i;
  79. double *dash_array;
  80. dash_array = (double *)_pl_xmalloc (oldstate->dash_array_len * sizeof(double));
  81. for (i = 0; i < oldstate->dash_array_len; i++)
  82. dash_array[i] = oldstate->dash_array[i];
  83. drawstate->dash_array = dash_array;
  84. }
  85. /* The font_name, true_font_name, font_type, typeface_index, and
  86. font_index fields are special, since for the initial drawing state
  87. they're Plotter-dependent.
  88. For later drawing states, we just copy them from the previous state.
  89. Since only the first two (font_name and true_font_name) are strings,
  90. for later states we don't worry about the other three: they've already
  91. been copied.
  92. The fill_rule_type field is also treated specially in the initial
  93. drawing state, because not all Plotters support both types of filling
  94. (odd vs. nonzero winding number). */
  95. font_name = (char *)_pl_xmalloc (strlen (oldstate->font_name) + 1);
  96. strcpy (font_name, oldstate->font_name);
  97. drawstate->font_name = font_name;
  98. true_font_name = (char *)_pl_xmalloc (strlen (oldstate->true_font_name) + 1);
  99. strcpy (true_font_name, oldstate->true_font_name);
  100. drawstate->true_font_name = true_font_name;
  101. /* Our memcpy copied the pointer to the compound path under construction
  102. (if any). So we knock it out, to start afresh */
  103. drawstate->path = (plPath *)NULL;
  104. drawstate->paths = (plPath **)NULL;
  105. drawstate->num_paths = 0;
  106. /* install new state at head of the state list */
  107. drawstate->previous = oldstate;
  108. _plotter->drawstate = drawstate;
  109. /* add any device-dependent fields to new state */
  110. _plotter->push_state (S___(_plotter));
  111. return 0;
  112. }
  113. int
  114. _API_restorestate(S___(Plotter *_plotter))
  115. {
  116. plDrawState *oldstate = _plotter->drawstate->previous;
  117. if (!_plotter->data->open)
  118. {
  119. _plotter->error (R___(_plotter)
  120. "restorestate: invalid operation");
  121. return -1;
  122. }
  123. if (_plotter->drawstate->previous == NULL)
  124. /* this is an attempt to pop the lowest state off the stack */
  125. {
  126. _plotter->error (R___(_plotter)
  127. "restorestate: invalid operation");
  128. return -1;
  129. }
  130. _API_endpath (S___(_plotter)); /* flush path if any */
  131. /* tear down any device-dependent fields in state */
  132. _plotter->pop_state (S___(_plotter));
  133. /* elements of current state that are strings are first freed */
  134. free ((char *)_plotter->drawstate->fill_rule);
  135. free ((char *)_plotter->drawstate->line_mode);
  136. free ((char *)_plotter->drawstate->join_mode);
  137. free ((char *)_plotter->drawstate->cap_mode);
  138. free ((char *)_plotter->drawstate->true_font_name);
  139. free ((char *)_plotter->drawstate->font_name);
  140. /* free dash array too, if nonempty */
  141. if (_plotter->drawstate->dash_array_len > 0)
  142. free ((double *)_plotter->drawstate->dash_array);
  143. /* pop state off the stack */
  144. free (_plotter->drawstate);
  145. _plotter->drawstate = oldstate;
  146. return 0;
  147. }
  148. void
  149. _pl_g_push_state (S___(Plotter *_plotter))
  150. {
  151. return;
  152. }
  153. void
  154. _pl_g_pop_state (S___(Plotter *_plotter))
  155. {
  156. return;
  157. }