t_path.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 internal path_is_flushable() method, which is
  16. invoked after any path segment is added to the segment list, provided
  17. (0) the segment list has become greater than or equal to the
  18. `max_unfilled_path_length' Plotter parameter, (1) the path isn't to be
  19. filled. In most Plotters, this operation simply returns true. */
  20. /* This file also contains the internal maybe_prepaint_segments() method.
  21. It is called immediately after any segment is added to a path. Some
  22. Plotters, at least under some circumstances, treat endpath() as a no-op.
  23. Instead, they plot the segments of a path in real time. */
  24. /**********************************************************************/
  25. /* This version of the internal method path_is_flushable() is for Tektronix
  26. Plotters, which (1) reduce all paths to line segments as they are
  27. constructed, and (2) plot the resulting line segments ("vectors") in
  28. real time. Unlike the generic version, which returns true, this version
  29. returns false. */
  30. #include "sys-defines.h"
  31. #include "extern.h"
  32. bool
  33. _pl_t_path_is_flushable (S___(Plotter *_plotter))
  34. {
  35. return false;
  36. }
  37. /**********************************************************************/
  38. /* This version of the internal method maybe_prepaint_segments() is for
  39. Tektronix Plotters, which (1) reduce all paths to line segments as they
  40. are constructed, and (2) plot the resulting line segments ("vectors") in
  41. real time. This is what does all the painting of line segments on a
  42. Tektronix display. */
  43. /* for Cohen-Sutherland clipper, see g_clipper.c */
  44. enum { ACCEPTED = 0x1, CLIPPED_FIRST = 0x2, CLIPPED_SECOND = 0x4 };
  45. void
  46. _pl_t_maybe_prepaint_segments (R___(Plotter *_plotter) int prev_num_segments)
  47. {
  48. int i;
  49. /* sanity check */
  50. if (_plotter->drawstate->path->num_segments < 2)
  51. return;
  52. if (_plotter->drawstate->path->num_segments == prev_num_segments)
  53. /* nothing to paint */
  54. return;
  55. /* skip drawing if pen level is set to `0' */
  56. if (_plotter->drawstate->pen_type == 0)
  57. return;
  58. /* Skip drawing if the pen color is white. Since our TekPlotter class
  59. doesn't support filling, this is ok to do if the Tektronix isn't a
  60. kermit emulator (the kermit emulator supports color). */
  61. if (_plotter->tek_display_type != TEK_DPY_KERMIT
  62. && _plotter->drawstate->fgcolor.red == 0xffff
  63. && _plotter->drawstate->fgcolor.green == 0xffff
  64. && _plotter->drawstate->fgcolor.blue == 0xffff)
  65. return;
  66. /* iterate over all new segments, i.e. segments to be painted */
  67. for (i = IMAX(1, prev_num_segments);
  68. i < _plotter->drawstate->path->num_segments;
  69. i++)
  70. {
  71. plPoint start, end; /* endpoints of line seg. (in device coors) */
  72. plIntPoint istart, iend; /* same, quantized to integer Tek coors */
  73. int clipval;
  74. bool same_point, force;
  75. /* nominal starting point and ending point for new line segment, in
  76. floating point device coordinates */
  77. start.x = XD(_plotter->drawstate->path->segments[i-1].p.x,
  78. _plotter->drawstate->path->segments[i-1].p.y);
  79. start.y = YD(_plotter->drawstate->path->segments[i-1].p.x,
  80. _plotter->drawstate->path->segments[i-1].p.y);
  81. end.x = XD(_plotter->drawstate->path->segments[i].p.x,
  82. _plotter->drawstate->path->segments[i].p.y);
  83. end.y = YD(_plotter->drawstate->path->segments[i].p.x,
  84. _plotter->drawstate->path->segments[i].p.y);
  85. same_point = (start.x == end.x && start.y == end.y) ? true : false;
  86. /* clip line segment to rectangular clipping region in device frame */
  87. clipval = _clip_line (&start.x, &start.y, &end.x, &end.y,
  88. TEK_DEVICE_X_MIN_CLIP, TEK_DEVICE_X_MAX_CLIP,
  89. TEK_DEVICE_Y_MIN_CLIP, TEK_DEVICE_Y_MAX_CLIP);
  90. if (!(clipval & ACCEPTED)) /* line segment is OOB */
  91. continue;
  92. /* convert clipped starting point, ending point to integer Tek coors */
  93. istart.x = IROUND(start.x);
  94. istart.y = IROUND(start.y);
  95. iend.x = IROUND(end.x);
  96. iend.y = IROUND(end.y);
  97. if (i == 1)
  98. /* New polyline is beginning, so start to draw it on the display:
  99. move to starting point of the first line segment, in Tek space.
  100. As a side-effect, the escape sequence emitted by _pl_t_tek_move()
  101. will shift the Tektronix to the desired mode, either PLOT or
  102. POINT. Note that if we are already in the desired mode,
  103. emitting the escape sequence will prevent a line being drawn at
  104. the time of the move (the "dark vector" concept). That is of
  105. course what we want. */
  106. _pl_t_tek_move (R___(_plotter) istart.x, istart.y);
  107. else
  108. /* A polyline is underway, >=1 line segments already. So check
  109. whether the position on the Tektronix is the same as the
  110. starting point of the new line segment; if it differs, move to
  111. the latter. Such a difference can occur on account of clipping.
  112. Also the Tektronix position could have changed on us if a
  113. savestate()...restorestate() occurred since the last call to
  114. cont(). */
  115. {
  116. int correct_tek_mode =
  117. _plotter->drawstate->points_are_connected ? TEK_MODE_PLOT : TEK_MODE_POINT;
  118. if (_plotter->tek_position_is_unknown
  119. || _plotter->tek_pos.x != istart.x
  120. || _plotter->tek_pos.y != istart.y
  121. || _plotter->tek_mode_is_unknown
  122. || _plotter->tek_mode != correct_tek_mode)
  123. /* Move to desired position. This automatically shifts the
  124. Tektronix to correct mode, PLOT or POINT; see comment
  125. above. */
  126. _pl_t_tek_move (R___(_plotter) istart.x, istart.y);
  127. }
  128. /* Sync Tek's linestyle with ours; an escape sequence is emitted only
  129. if necessary. Linestyle could have changed on us if a
  130. savestate()...restorestate() occurred since the last call to
  131. cont(). Sync Tek's color and background color too (significant
  132. only for kermit Tek emulator). */
  133. _pl_t_set_attributes (S___(_plotter));
  134. _pl_t_set_pen_color (S___(_plotter));
  135. _pl_t_set_bg_color (S___(_plotter));
  136. /* If this is initial line segment of a polyline, force output of a
  137. vector even if line segment has zero length, so that something
  138. visible will appear on the display. We do this only if (1) the
  139. line segment in the user frame was of nonzero length, or (2) it
  140. was of zero length but the cap mode is "round". This more or less
  141. agrees with our convention, on bitmap Plotters (X, PNM, GIF,
  142. etc.), for dealing with device-frame vectors that are of
  143. (quantized) zero length. */
  144. if (i == 1
  145. && (same_point == false
  146. || (same_point == true
  147. && _plotter->drawstate->cap_type == PL_CAP_ROUND)))
  148. force = true;
  149. else
  150. force = false;
  151. /* continue polyline by drawing vector on Tek display */
  152. _pl_t_tek_vector_compressed (R___(_plotter)
  153. iend.x, iend.y, istart.x, istart.y, force);
  154. /* update our notion of Tek's notion of position */
  155. _plotter->tek_pos.x = iend.x;
  156. _plotter->tek_pos.y = iend.y;
  157. }
  158. }