x_erase.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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 version is for XDrawablePlotters, and should be identical to
  16. y_erase.c (the version for XPlotters) except that XPlotter-specific
  17. lines are commented out. (Search for #if 0...#endif.) The function
  18. y_erase() is of course renamed x_erase() here. */
  19. #include "sys-defines.h"
  20. #include "extern.h"
  21. /* If we aren't double buffering, this is the number of
  22. most-recently-allocated color cells that we _don't_ deallocate when we
  23. do an erase(). This is a heuristic. This quantity must be >= 0. */
  24. #define NUM_KEPT_COLORS 256
  25. /* If we're doing double buffering, when we do an erase() we of course
  26. don't deallocate the color cells that were used in the current frame.
  27. We also don't deallocate the cells used in the previous NUM_KEPT_FRAMES
  28. frames. This is a heuristic. This quantity must be >= 0. */
  29. #define NUM_KEPT_FRAMES 16
  30. bool
  31. _pl_x_erase_page (S___(Plotter *_plotter))
  32. {
  33. bool head_found;
  34. int window_width, window_height;
  35. int i, current_frame_number, current_page_number;
  36. plColorRecord *cptr, **link = NULL;
  37. plDrawState *stateptr;
  38. /* set the foreground color in the GC we use for erasing,
  39. to be the background color in the drawing state */
  40. _pl_x_set_bg_color (S___(_plotter));
  41. /* compute rectangle size; note flipped-y convention */
  42. window_width = (_plotter->data->imax - _plotter->data->imin) + 1;
  43. window_height = (_plotter->data->jmin - _plotter->data->jmax) + 1;
  44. if (_plotter->x_double_buffering != X_DBL_BUF_NONE)
  45. {
  46. /* Following two sorts of server-supported double buffering
  47. (X_DBL_BUF_DBE, X_DBL_BUF_MBX) are possible only for X Plotters, not
  48. X Drawable Plotters. `By hand' double buffering is possible
  49. for both. */
  50. #if 0
  51. #ifdef HAVE_X11_EXTENSIONS_XDBE_H
  52. #ifdef HAVE_DBE_SUPPORT
  53. if (_plotter->x_double_buffering == X_DBL_BUF_DBE)
  54. /* we're using the X double buffering extension */
  55. {
  56. XdbeSwapInfo info;
  57. /* Copy current frame of buffered graphics to window. Implement
  58. this by swapping the front and back buffers for widget's
  59. window. Former front buffer will become graphics buffer.
  60. Currently, the buffers are `x_drawable2' (front) and `x_drawable3'
  61. (back, into which we draw). */
  62. info.swap_window = _plotter->x_drawable2;
  63. info.swap_action = XdbeUndefined;
  64. XdbeSwapBuffers (_plotter->x_dpy, &info, 1);
  65. }
  66. else
  67. #endif /* HAVE_DBE_SUPPORT */
  68. #endif /* HAVE_X11_EXTENSIONS_XDBE_H */
  69. #ifdef HAVE_X11_EXTENSIONS_MULTIBUF_H
  70. #ifdef HAVE_MBX_SUPPORT
  71. if (_plotter->x_double_buffering == X_DBL_BUF_MBX)
  72. /* we're using the X multibuffering extension */
  73. {
  74. Multibuffer multibuf;
  75. /* Copy current frame of buffered graphics to window. Implement
  76. this by making multibuffer into which we've been drawing the
  77. current multibuffer. */
  78. XmbufDisplayBuffers (_plotter->x_dpy, 1, &(_plotter->x_drawable3), 0, 0);
  79. /* swap the two multibuffers, making the other one the off-screen
  80. graphics buffer into which we draw (`x_drawable3') */
  81. multibuf = _plotter->x_drawable3;
  82. _plotter->x_drawable3 = _plotter->y_drawable4;
  83. _plotter->y_drawable4 = multibuf;
  84. }
  85. else
  86. #endif /* HAVE_MBX_SUPPORT */
  87. #endif /* HAVE_X11_EXTENSIONS_MULTIBUF_H */
  88. #endif /* 0 */
  89. /* we must be doing double buffering `by hand', rather than using
  90. an X protocol extension */
  91. if (_plotter->x_double_buffering == X_DBL_BUF_BY_HAND)
  92. {
  93. /* copy current frame of buffered graphics to drawable(s) */
  94. if (_plotter->x_drawable1)
  95. XCopyArea (_plotter->x_dpy,
  96. _plotter->x_drawable3, _plotter->x_drawable1,
  97. _plotter->drawstate->x_gc_bg,
  98. 0, 0,
  99. (unsigned int)window_width,
  100. (unsigned int)window_height,
  101. 0, 0);
  102. if (_plotter->x_drawable2)
  103. XCopyArea (_plotter->x_dpy,
  104. _plotter->x_drawable3, _plotter->x_drawable2,
  105. _plotter->drawstate->x_gc_bg,
  106. 0, 0,
  107. (unsigned int)window_width,
  108. (unsigned int)window_height,
  109. 0, 0);
  110. }
  111. /* irrespective of which of the three sorts of double buffering is
  112. being performed, clear the (new) graphics buffer, by filling it
  113. with background color */
  114. XFillRectangle (_plotter->x_dpy, _plotter->x_drawable3,
  115. _plotter->drawstate->x_gc_bg,
  116. /* upper left corner */
  117. 0, 0,
  118. (unsigned int)window_width,
  119. (unsigned int)window_height);
  120. }
  121. else
  122. /* not double buffering at all */
  123. {
  124. /* erase drawable(s) by filling with background color */
  125. if (_plotter->x_drawable1)
  126. XFillRectangle (_plotter->x_dpy, _plotter->x_drawable1,
  127. _plotter->drawstate->x_gc_bg,
  128. /* upper left corner */
  129. 0, 0,
  130. (unsigned int)window_width, (unsigned int)window_height);
  131. if (_plotter->x_drawable2)
  132. XFillRectangle (_plotter->x_dpy, _plotter->x_drawable2,
  133. _plotter->drawstate->x_gc_bg,
  134. /* upper left corner */
  135. 0, 0,
  136. (unsigned int)window_width, (unsigned int)window_height);
  137. }
  138. #if 0
  139. /* If an X Plotter, update background color of y_canvas widget,
  140. irrespective of whether or not we're double buffering. This fixes
  141. things so that if the window is resized to a larger size, the new
  142. portions of the window will be filled with the correct color. */
  143. {
  144. Arg wargs[1]; /* werewolves */
  145. #ifdef USE_MOTIF
  146. XtSetArg (wargs[0], XmNbackground, _plotter->drawstate->x_gc_bgcolor);
  147. #else
  148. XtSetArg (wargs[0], XtNbackground, _plotter->drawstate->x_gc_bgcolor);
  149. #endif
  150. XtSetValues (_plotter->y_toplevel, wargs, (Cardinal)1);
  151. XtSetValues (_plotter->y_canvas, wargs, (Cardinal)1);
  152. }
  153. #endif /* 0 */
  154. /* Flush the color cell cache, to the extent we can. But heuristically,
  155. keep in the cache a certain number of cells that aren't strictly
  156. needed, but which may be needed in the following frames. There are
  157. two cases.
  158. 1. If we're not double buffering, preserve some maximum number
  159. (NUM_KEPT_COLORS) of the most recently allocated cells.
  160. Implementing the cache as a list, though suboptimal from the
  161. point of view of speed, makes it easy to implement this heuristic.
  162. 2. If we're double buffering, preserve all cells that were used
  163. in the present frame (which was just transferred to the
  164. drawable(s), e.g., to an on-screen window). This is mandatory.
  165. But also use a heuristic: preserve all cells used in the
  166. preceding NUM_KEPT_FRAMES frames.
  167. In both cases, if a cached cell is to be preserved, it must contain a
  168. genuine pixel value (the `allocated' flag must be set).
  169. We also insist that for a cell to be preserved, it have a `page number
  170. stamp' equal to the current page number. That's because XDrawable
  171. Plotters, unlike X Plotters, don't free the color cell cache in
  172. end_page(), i.e., when closepl() is called. That's because X Drawable
  173. Plotters are `persistent' in the sense the graphics remain visible
  174. until the next reopening, and beyond. So the cache may include cells
  175. left over from previous pages, which get freed only here, when erase()
  176. is called. */
  177. cptr = _plotter->x_colorlist;
  178. _plotter->x_colorlist = NULL;
  179. i = 0;
  180. head_found = false;
  181. current_frame_number = _plotter->data->frame_number;
  182. current_page_number = _plotter->data->page_number;
  183. while (cptr)
  184. {
  185. plColorRecord *cptrnext;
  186. cptrnext = cptr->next;
  187. if (cptr->allocated)
  188. {
  189. if ((_plotter->x_double_buffering == X_DBL_BUF_NONE
  190. && cptr->page_number == current_page_number
  191. && i < NUM_KEPT_COLORS)
  192. ||
  193. (_plotter->x_double_buffering != X_DBL_BUF_NONE
  194. && cptr->page_number == current_page_number
  195. && cptr->frame_number >= current_frame_number - NUM_KEPT_FRAMES))
  196. /* cached cell contains a genuine pixel value, and it meets our
  197. criteria, so preserve it */
  198. {
  199. if (head_found)
  200. *link = cptr;
  201. else
  202. {
  203. _plotter->x_colorlist = cptr;
  204. head_found = true;
  205. }
  206. cptr->next = NULL;
  207. link = &(cptr->next);
  208. i++;
  209. }
  210. else
  211. /* cached cell contains a genuine pixel value, but it doesn't
  212. meet our criteria, so deallocate it */
  213. {
  214. XFreeColors (_plotter->x_dpy, _plotter->x_cmap,
  215. &(cptr->rgb.pixel), 1, (unsigned long)0);
  216. free (cptr);
  217. }
  218. }
  219. else
  220. /* cached cell doesn't include a genuine pixel value, so free it */
  221. free (cptr);
  222. cptr = cptrnext;
  223. }
  224. /* flag status of all colors in GC's in the drawing state stack as false
  225. (on account of flushing, may need to be searched for or reallocated) */
  226. for (stateptr = _plotter->drawstate; stateptr; stateptr = stateptr->previous)
  227. {
  228. stateptr->x_gc_fgcolor_status = false;
  229. stateptr->x_gc_fillcolor_status = false;
  230. stateptr->x_gc_bgcolor_status = false;
  231. }
  232. /* maybe flush X output buffer and handle X events (a no-op for
  233. XDrawablePlotters, which is overridden for XPlotters) */
  234. _maybe_handle_x_events (S___(_plotter));
  235. return true;
  236. }