x_openpl.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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 implementation is for XDrawablePlotters. It supports one or two
  16. drawables, which must be associated with the same display and have the
  17. same dimensions (width, height, depth). A `drawable' is either a window
  18. or a pixmap. */
  19. /* This file also contains the internal functions _pl_x_maybe_get_new_colormap
  20. and _pl_x_maybe_handle_x_events, which are no-ops. However, they are
  21. virtual and are overridden in the derived XPlotter class, which both
  22. attempts to switch to a private colormap when color cells run out, and
  23. processes its own X events. */
  24. #include "sys-defines.h"
  25. #include "extern.h"
  26. bool
  27. _pl_x_begin_page (S___(Plotter *_plotter))
  28. {
  29. Window root1, root2;
  30. int x, y;
  31. unsigned int border_width, depth1, depth2;
  32. unsigned int width1, height1, width2, height2;
  33. unsigned int width, height, depth;
  34. const char *double_buffer_s;
  35. if (_plotter->x_dpy == (Display *)NULL)
  36. /* pathological: user didn't set XDRAWABLE_DISPLAY parameter */
  37. {
  38. _plotter->error (R___(_plotter) "the Plotter cannot be opened, as the XDRAWABLE_DISPLAY parameter is null");
  39. return false;
  40. }
  41. /* find out how long polylines can get on this X display */
  42. _plotter->x_max_polyline_len = XMaxRequestSize(_plotter->x_dpy) / 2;
  43. /* determine dimensions of drawable(s) */
  44. if (_plotter->x_drawable1)
  45. XGetGeometry (_plotter->x_dpy, _plotter->x_drawable1,
  46. &root1, &x, &y, &width1, &height1, &border_width, &depth1);
  47. if (_plotter->x_drawable2)
  48. XGetGeometry (_plotter->x_dpy, _plotter->x_drawable2,
  49. &root2, &x, &y, &width2, &height2, &border_width, &depth2);
  50. if (_plotter->x_drawable1 && _plotter->x_drawable2)
  51. /* sanity check */
  52. {
  53. if (width1 != width2 || height1 != height2
  54. || depth1 != depth2 || root1 != root2)
  55. {
  56. _plotter->error(R___(_plotter) "the Plotter cannot be opened, as the X drawables have unequal parameters");
  57. return false;
  58. }
  59. }
  60. if (_plotter->x_drawable1)
  61. {
  62. width = width1;
  63. height = height1;
  64. depth = depth1;
  65. }
  66. else if (_plotter->x_drawable2)
  67. {
  68. width = width2;
  69. height = height2;
  70. depth = depth1;
  71. }
  72. else
  73. /* both are NULL, and we won't really be drawing, so these are irrelevant */
  74. {
  75. width = 1;
  76. height = 1;
  77. depth = 1;
  78. }
  79. _plotter->data->imin = 0;
  80. _plotter->data->imax = width - 1;
  81. /* note flipped-y convention for this device: for j, min > max */
  82. _plotter->data->jmin = height - 1;
  83. _plotter->data->jmax = 0;
  84. /* compute the NDC to device-frame affine map, set it in Plotter */
  85. _compute_ndc_to_device_map (_plotter->data);
  86. /* add X GC's to drawing state (which was constructed by openpl() before
  87. begin_page() was called), so we can at least fill with solid color */
  88. _pl_x_add_gcs_to_first_drawing_state (S___(_plotter));
  89. /* At this point, we don't clear the drawable(s) by filling them with the
  90. background color, which is what we would do here for an X Plotter (see
  91. y_openpl.c). For an X DrawablePlotter, unlike an X Plotter, initial
  92. clearing is not appropriate. However, if we're double buffering, we
  93. create an off-screen buffer and fill it with the color. */
  94. if (_plotter->x_drawable1 || _plotter->x_drawable2)
  95. {
  96. double_buffer_s =
  97. (const char *)_get_plot_param (_plotter->data, "USE_DOUBLE_BUFFERING");
  98. if (strcmp (double_buffer_s, "yes") == 0
  99. /* backward compatibility: "fast" now means the same as "yes" */
  100. || strcmp (double_buffer_s, "fast") == 0)
  101. /* user requested double buffering, so do so `by hand': allocate
  102. additional pixmap to serve as off-screen graphics buffer */
  103. {
  104. _plotter->x_double_buffering = X_DBL_BUF_BY_HAND;
  105. _plotter->x_drawable3
  106. = XCreatePixmap(_plotter->x_dpy,
  107. /* this 2nd arg merely determines the screen*/
  108. _plotter->x_drawable1 ?
  109. _plotter->x_drawable1 : _plotter->x_drawable2,
  110. (unsigned int)width,
  111. (unsigned int)height,
  112. (unsigned int)depth);
  113. /* erase buffer by filling it 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)width, (unsigned int)height);
  119. }
  120. }
  121. /* Note: at this point the drawing state, which we added X GC's to, a few
  122. lines above, won't be ready for drawing graphics, since it won't
  123. contain an X font or meaningful line width. To retrieve an X font and
  124. set the line width, user will need to invoke space() after openpl(). */
  125. return true;
  126. }
  127. /* Flesh out an XDrawable or X Plotter's first drawing state, by adding
  128. X11-specific elements: GC's or lists. This is invoked by the
  129. corresponding begin_page() routines, and hence by openpl().
  130. As supplemented, the drawing state won't be fully ready for drawing
  131. graphics, since it won't contain a X font. However, the the API
  132. function alabel(), before drawing a text string, invokes _set_font(),
  133. which in turns invokes the Plotter-specific function retrieve_font().
  134. And x_retrieve_font() does the job of retrieving an X font from the
  135. server and placing it in the drawing state. */
  136. void
  137. _pl_x_add_gcs_to_first_drawing_state (S___(Plotter *_plotter))
  138. {
  139. Drawable drawable;
  140. /* determine which if either drawable we'll construct the GC's for */
  141. if (_plotter->x_drawable1)
  142. drawable = _plotter->x_drawable1;
  143. else if (_plotter->x_drawable2)
  144. drawable = _plotter->x_drawable2;
  145. else
  146. drawable = (Drawable)NULL;
  147. if (drawable != (Drawable)NULL)
  148. /* prepare GC's for new drawing state, by copying attributes we use */
  149. {
  150. unsigned long gcmask_fg, gcmask_fill, gcmask_bg;
  151. gcmask_fg =
  152. /* constant attributes (never altered) */
  153. GCPlaneMask | GCFunction
  154. /* drawing attributes set by _pl_x_set_attributes() */
  155. /* NOTE: we also use GCDashOffset and GCDashList, but Xlib does not
  156. support retrieving the dash list from a GC, so we'll copy the
  157. dashing style in another (painful) way */
  158. | GCLineStyle | GCLineWidth | GCJoinStyle | GCCapStyle
  159. /* other GC elements set by the X Drawable driver */
  160. | GCForeground | GCFont;
  161. gcmask_fill =
  162. /* constant attributes (never altered) */
  163. GCPlaneMask | GCFunction | GCArcMode
  164. /* filling attributes set by _pl_x_set_attributes() */
  165. | GCFillRule
  166. /* other GC elements set by the X Drawable driver */
  167. | GCForeground;
  168. gcmask_bg =
  169. /* constant attributes (never altered) */
  170. GCPlaneMask | GCFunction
  171. /* other GC elements set by the X Drawable driver */
  172. | GCForeground;
  173. /* build new GC's from scratch */
  174. {
  175. XGCValues gcv_fg, gcv_fill, gcv_bg;
  176. /* Initialize GC used for drawing. (Always initialize the line
  177. style to LineSolid, irrespective of what the default drawing
  178. state contains; it would be silly for the default drawing state
  179. to include a non-solid value for the line style.) */
  180. gcv_fg.plane_mask = AllPlanes;
  181. gcv_fg.function = GXcopy;
  182. gcv_fg.line_width = _default_drawstate.x_gc_line_width;
  183. gcv_fg.line_style = LineSolid;
  184. gcv_fg.join_style = _default_drawstate.x_gc_join_style;
  185. gcv_fg.cap_style = _default_drawstate.x_gc_cap_style;
  186. gcmask_fg &= ~(GCFont); /* initialized much later; see below */
  187. gcmask_fg &= ~(GCForeground); /* color is initialized separately */
  188. /* initialize GC used for filling */
  189. gcv_fill.plane_mask = AllPlanes;
  190. gcv_fill.function = GXcopy;
  191. gcv_fill.arc_mode = ArcChord; /* libplot convention */
  192. gcv_fill.fill_rule = _default_drawstate.x_gc_fill_rule;
  193. gcmask_fill &= ~(GCForeground); /* color is initialized separately */
  194. /* initialize GC used for erasing */
  195. gcv_bg.plane_mask = AllPlanes;
  196. gcv_bg.function = GXcopy;
  197. gcmask_bg &= ~(GCForeground); /* color is initialized separately */
  198. /* create the 3 GC's */
  199. _plotter->drawstate->x_gc_fg =
  200. XCreateGC (_plotter->x_dpy, drawable, gcmask_fg, &gcv_fg);
  201. _plotter->drawstate->x_gc_fill =
  202. XCreateGC (_plotter->x_dpy, drawable, gcmask_fill, &gcv_fill);
  203. _plotter->drawstate->x_gc_bg =
  204. XCreateGC (_plotter->x_dpy, drawable, gcmask_bg, &gcv_bg);
  205. /* set X-specific elements in the drawing state, specifying
  206. (non-opaquely) what the 3 GC's contain */
  207. _plotter->drawstate->x_gc_line_width = gcv_fg.line_width;
  208. _plotter->drawstate->x_gc_line_style = gcv_fg.line_style;
  209. _plotter->drawstate->x_gc_join_style = gcv_fg.join_style;
  210. _plotter->drawstate->x_gc_cap_style = gcv_fg.cap_style;
  211. _plotter->drawstate->x_gc_dash_list = (char *)NULL;
  212. _plotter->drawstate->x_gc_dash_list_len = 0;
  213. _plotter->drawstate->x_gc_dash_offset = 0;
  214. _plotter->drawstate->x_gc_fill_rule = gcv_fill.fill_rule;
  215. /* do the separate initialization of color (i.e. GCForeground
  216. element) in each GC */
  217. _pl_x_set_pen_color (S___(_plotter));
  218. _pl_x_set_fill_color (S___(_plotter));
  219. _pl_x_set_bg_color (S___(_plotter));
  220. /* At this point, all 3 GC's are functional, except the GC used
  221. for drawing lacks a GCFont element.
  222. We do not retrieve a font from the X server here; not even a
  223. default font. fsetmatrix() or space(), when invoked (which we
  224. require after each invocation of openpl()), will select a
  225. default size for the font. A font will be retrieved from the X
  226. server only when fontname/fontsize/textangle is invoked to
  227. select a different font, or when alabel/labelwidth is invoked
  228. (see g_alabel.c).
  229. The invocation of fsetmatrix() or space() will also set the line
  230. width in the drawing state. Any changed attributes, such as
  231. line width, will be written to the GC's just before drawing; see
  232. g_attribs.c. */
  233. }
  234. }
  235. }
  236. /* This is the XDrawablePlotter-specific version of the
  237. _maybe_get_new_colormap() method, which is invoked when a Plotter's
  238. original colormap fills up. It's a no-op; in XPlotters, it's overridden
  239. by a version that actually does something. */
  240. void
  241. _pl_x_maybe_get_new_colormap (S___(Plotter *_plotter))
  242. {
  243. return;
  244. }
  245. /* This is the XDrawablePlotter-specific version of the
  246. _maybe_handle_x_events() method, which is invoked after most drawing
  247. operations. It's a no-op; in XPlotters, it's overridden by a version
  248. that actually does something. */
  249. void
  250. _pl_x_maybe_handle_x_events(S___(Plotter *_plotter))
  251. {
  252. return;
  253. }