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
4 The GNU plotutils package is free software. You may redistribute it
5 and/or modify it under the terms of the GNU General Public License as
6 published by the Free Software foundation; either version 2, or (at your
7 option) any later version.
8
9 The GNU plotutils package is distributed in the hope that it will be
10 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with the GNU plotutils package; see the file COPYING. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
17 Boston, MA 02110-1301, USA. */
18
19 /* This file contains the internal paint_path() and paint_paths() methods,
20 which the public method endpath() is a wrapper around. */
21
22 /* This version is for HPGL and PCL Plotters. By construction, for these
23 Plotters our path buffer always contains either a segment list, or a
24 rectangle or circle object. If it's a segment list, it may include an
25 arbitrary sequence of line, circular arc, and Bezier elements. (For
26 circular arcs to be included, the map from user to device coordinates
27 must be uniform, so that e.g. the angle subtended by the arc will be the
28 same in user and device coordinates.) */
29
30 #include "sys-defines.h"
31 #include "extern.h"
32
33 #define DIST(p0,p1) (sqrt( ((p0).x - (p1).x)*((p0).x - (p1).x) \
34 + ((p0).y - (p1).y)*((p0).y - (p1).y)))
35
36 void
_pl_h_paint_path(S___ (Plotter * _plotter))37 _pl_h_paint_path (S___(Plotter *_plotter))
38 {
39 if (_plotter->drawstate->pen_type == 0
40 && _plotter->drawstate->fill_type == 0)
41 /* nothing to draw */
42 return;
43
44 switch ((int)_plotter->drawstate->path->type)
45 {
46 case (int)PATH_SEGMENT_LIST:
47 {
48 plIntPathSegment *xarray;
49 plPoint p0, pp1, pc, savedpoint;
50 bool closed, use_polygon_buffer;
51 double last_x, last_y;
52 int i, polyline_len;
53 bool identical_user_coordinates = true;
54
55 /* sanity checks */
56 if (_plotter->drawstate->path->num_segments == 0)/* nothing to do */
57 break;
58 if (_plotter->drawstate->path->num_segments == 1) /* shouldn't happen*/
59 break;
60
61 if ((_plotter->drawstate->path->num_segments >= 3)/*check for closure*/
62 && (_plotter->drawstate->path->segments[_plotter->drawstate->path->num_segments - 1].p.x == _plotter->drawstate->path->segments[0].p.x)
63 && (_plotter->drawstate->path->segments[_plotter->drawstate->path->num_segments - 1].p.y == _plotter->drawstate->path->segments[0].p.y))
64 closed = true;
65 else
66 closed = false; /* 2-point ones should be open */
67
68 /* convert vertices to integer device coordinates, removing runs */
69
70 /* array for points, with positions expressed in integer device coors*/
71 xarray = (plIntPathSegment *)_pl_xmalloc (_plotter->drawstate->path->num_segments * sizeof(plIntPathSegment));
72
73 /* add first point of path to xarray[] (type field is a moveto) */
74 xarray[0].p.x = IROUND(XD(_plotter->drawstate->path->segments[0].p.x,
75 _plotter->drawstate->path->segments[0].p.y));
76 xarray[0].p.y = IROUND(YD(_plotter->drawstate->path->segments[0].p.x,
77 _plotter->drawstate->path->segments[0].p.y));
78 polyline_len = 1;
79 /* save user coors of last point added to xarray[] */
80 last_x = _plotter->drawstate->path->segments[0].p.x;
81 last_y = _plotter->drawstate->path->segments[0].p.y;
82
83 for (i = 1; i < _plotter->drawstate->path->num_segments; i++)
84 {
85 plPathSegment datapoint;
86 double xuser, yuser, xdev, ydev;
87 int device_x, device_y;
88
89 datapoint = _plotter->drawstate->path->segments[i];
90 xuser = datapoint.p.x;
91 yuser = datapoint.p.y;
92 if (xuser != last_x || yuser != last_y)
93 /* in user space, not all points are the same */
94 identical_user_coordinates = false;
95
96 xdev = XD(xuser, yuser);
97 ydev = YD(xuser, yuser);
98 device_x = IROUND(xdev);
99 device_y = IROUND(ydev);
100
101 if (device_x != xarray[polyline_len-1].p.x
102 || device_y != xarray[polyline_len-1].p.y)
103 /* integer device coor(s) changed, so stash point (incl. type
104 field) */
105 {
106 plPathSegmentType element_type;
107 int device_xc, device_yc;
108
109 xarray[polyline_len].p.x = device_x;
110 xarray[polyline_len].p.y = device_y;
111 element_type = datapoint.type;
112 xarray[polyline_len].type = element_type;
113
114 if (element_type == S_ARC)
115 /* an arc element, so compute center, subtended angle too */
116 {
117 double angle;
118
119 device_xc = IROUND(XD(datapoint.pc.x, datapoint.pc.y));
120 device_yc = IROUND(YD(datapoint.pc.x, datapoint.pc.y));
121 xarray[polyline_len].pc.x = device_xc;
122 xarray[polyline_len].pc.y = device_yc;
123 p0.x = last_x;
124 p0.y = last_y;
125 pp1 = datapoint.p;
126 pc = datapoint.pc;
127 angle = _angle_of_arc (p0, pp1, pc);
128
129 /* if user coors -> device coors includes a reflection,
130 flip sign */
131 if (!_plotter->drawstate->transform.nonreflection)
132 angle = -angle;
133 xarray[polyline_len].angle = angle;
134 }
135 else if (element_type == S_CUBIC)
136 /* a cubic Bezier element, so compute control points too */
137 {
138 xarray[polyline_len].pc.x
139 = IROUND(XD(datapoint.pc.x, datapoint.pc.y));
140 xarray[polyline_len].pc.y
141 = IROUND(YD(datapoint.pc.x, datapoint.pc.y));
142 xarray[polyline_len].pd.x
143 = IROUND(XD(datapoint.pd.x, datapoint.pd.y));
144 xarray[polyline_len].pd.y
145 = IROUND(YD(datapoint.pd.x, datapoint.pd.y));
146 }
147
148 /* save user coors of last point added to xarray[] */
149 last_x = datapoint.p.x;
150 last_y = datapoint.p.y;
151 polyline_len++;
152 }
153 }
154
155 /* Check first for special subcase: all user-space juncture points
156 in the polyline were mapped to a single integer HP-GL
157 pseudo-pixel. If (1) they weren't all the same to begin with,
158 or (2) they were all the same to begin with and the cap mode is
159 "round", then draw as a filled circle, of diameter equal to the
160 line width; otherwise draw nothing. */
161
162 if (_plotter->drawstate->path->num_segments > 1 && polyline_len == 1)
163 /* all points mapped to a single integer pseudo-pixel */
164 {
165 if (identical_user_coordinates == false
166 || _plotter->drawstate->cap_type == PL_CAP_ROUND)
167 {
168 double r = 0.5 * _plotter->drawstate->line_width;
169 double device_frame_radius;
170
171 /* draw single filled circle, using HP-GL's native
172 circle-drawing facility */
173
174 /* move to center of circle */
175 savedpoint = _plotter->drawstate->pos;
176 _plotter->drawstate->pos =
177 _plotter->drawstate->path->segments[0].p;
178 _pl_h_set_position (S___(_plotter));
179 _plotter->drawstate->pos = savedpoint;
180
181 /* set fill color to pen color, arrange to do filling; sync
182 attributes too, incl. pen width */
183 {
184 /* emit HP-GL directives; select a fill color that's
185 actually the pen color */
186 _pl_h_set_fill_color (R___(_plotter) true);
187 _pl_h_set_attributes (S___(_plotter));
188 }
189
190 /* compute radius in device frame */
191 device_frame_radius =
192 sqrt(XDV(r,0)*XDV(r,0)+YDV(r,0)*YDV(r,0));
193
194 /* Syncing the fill color may have set the
195 _plotter->hpgl_bad_pen flag (e.g. if optimal pen is #0
196 [white] and we're not allowed to use pen #0 to draw
197 with). So we test _plotter->hpgl_bad_pen before using
198 the pen. */
199 if (_plotter->hpgl_bad_pen == false)
200 /* fill the circle (360 degree wedge) */
201 {
202 sprintf (_plotter->data->page->point, "WG%d,0,360;",
203 IROUND(device_frame_radius));
204 _update_buffer (_plotter->data->page);
205 }
206 /* KLUDGE: in pre-HP-GL/2, our `set_fill_color' function
207 may alter the line type, since it may request *solid*
208 crosshatching; so reset the line type */
209 if (_plotter->hpgl_version < 2)
210 _pl_h_set_attributes (S___(_plotter));
211 }
212
213 /* free our temporary array and depart */
214 free (xarray);
215 break;
216 }
217
218 /* At this point, we know we have a nondegenerate path in our
219 pseudo-integer device space. */
220
221 /* will draw vectors (or arcs) into polygon buffer if appropriate */
222 use_polygon_buffer = (_plotter->hpgl_version == 2
223 || (_plotter->hpgl_version == 1 /* i.e. "1.5" */
224 && (polyline_len > 2
225 || _plotter->drawstate->fill_type)) ? true : false);
226
227 /* Sync pen color. This is needed here only if HPGL_VERSION is 1,
228 but we always do it here so that HP-GL/2 output that draws a
229 polyline, if sent erroneously to a generic HP-GL device, will
230 yield a polyline in the correct color, so long as the color
231 isn't white. */
232 _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH);
233
234 /* set_pen_color() sets the advisory bad_pen flag if white pen (pen
235 #0) would have been selected, and we can't use pen #0 to draw
236 with. Such a situation isn't fatal if HPGL_VERSION is "1.5" or
237 "2", since we may be filling the polyline with a nonwhite color,
238 as well as using a white pen to draw it. But if HPGL_VERSION is
239 "1", we don't fill polylines, so we might as well punt right
240 now. */
241 if (_plotter->hpgl_bad_pen && _plotter->hpgl_version == 1)
242 {
243 /* free integer storage buffer and depart */
244 free (xarray);
245 break;
246 }
247
248 /* sync attributes, incl. pen width if possible; move pen to p0 */
249 _pl_h_set_attributes (S___(_plotter));
250
251 savedpoint = _plotter->drawstate->pos;
252 _plotter->drawstate->pos = _plotter->drawstate->path->segments[0].p;
253 _pl_h_set_position (S___(_plotter));
254 _plotter->drawstate->pos = savedpoint;
255
256 if (use_polygon_buffer)
257 /* have a polygon buffer, and can use it to fill polyline */
258 {
259 /* enter polygon mode */
260 strcpy (_plotter->data->page->point, "PM0;");
261 _update_buffer (_plotter->data->page);
262 }
263
264 if (use_polygon_buffer || _plotter->drawstate->pen_type)
265 /* either (1) we'll be drawing into a polygon buffer, and will be
266 using it for at least one of (a) filling and (b) edging, or
267 (2) we won't be drawing into a polygon buffer, so we won't be
268 filling, but we'll be edging (because pen_type isn't zero) */
269 {
270 /* ensure that pen is down for drawing */
271 if (_plotter->hpgl_pendown == false)
272 {
273 strcpy (_plotter->data->page->point, "PD;");
274 _update_buffer (_plotter->data->page);
275 _plotter->hpgl_pendown = true;
276 }
277
278 /* loop through points in xarray[], emitting HP-GL instructions */
279 i = 1;
280 while (i < polyline_len)
281 {
282 switch ((int)xarray[i].type)
283 {
284 case (int)S_LINE:
285 /* emit one or more pen advances */
286 strcpy (_plotter->data->page->point, "PA");
287 _update_buffer (_plotter->data->page);
288 sprintf (_plotter->data->page->point, "%d,%d",
289 xarray[i].p.x, xarray[i].p.y);
290 _update_buffer (_plotter->data->page);
291 i++;
292 while (i < polyline_len && xarray[i].type == S_LINE)
293 {
294 sprintf (_plotter->data->page->point,
295 ",%d,%d", xarray[i].p.x, xarray[i].p.y);
296 _update_buffer (_plotter->data->page);
297 i++;
298 }
299 sprintf (_plotter->data->page->point, ";");
300 _update_buffer (_plotter->data->page);
301 break;
302
303 case (int)S_CUBIC:
304 /* emit one or more cubic Bezier segments */
305 strcpy (_plotter->data->page->point, "BZ");
306 _update_buffer (_plotter->data->page);
307 sprintf (_plotter->data->page->point, "%d,%d,%d,%d,%d,%d",
308 xarray[i].pc.x, xarray[i].pc.y,
309 xarray[i].pd.x, xarray[i].pd.y,
310 xarray[i].p.x, xarray[i].p.y);
311 _update_buffer (_plotter->data->page);
312 i++;
313 while (i < polyline_len && xarray[i].type == S_CUBIC)
314 {
315 sprintf (_plotter->data->page->point, ",%d,%d,%d,%d,%d,%d",
316 xarray[i].pc.x, xarray[i].pc.y,
317 xarray[i].pd.x, xarray[i].pd.y,
318 xarray[i].p.x, xarray[i].p.y);
319 _update_buffer (_plotter->data->page);
320 i++;
321 }
322 sprintf (_plotter->data->page->point, ";");
323 _update_buffer (_plotter->data->page);
324 break;
325
326 case (int)S_ARC:
327 {
328 double degrees;
329 int int_degrees;
330
331 /* emit an arc, using integer sweep angle if possible */
332 degrees = 180.0 * xarray[i].angle / M_PI;
333 int_degrees = IROUND (degrees);
334 if (_plotter->hpgl_version > 0)
335 /* HPGL_VERSION = 1.5 or 2 */
336 {
337 if (degrees == (double)int_degrees)
338 sprintf (_plotter->data->page->point, "AA%d,%d,%d;",
339 xarray[i].pc.x, xarray[i].pc.y,
340 int_degrees);
341 else
342 sprintf (_plotter->data->page->point, "AA%d,%d,%.3f;",
343 xarray[i].pc.x, xarray[i].pc.y,
344 degrees);
345 }
346 else
347 /* HPGL_VERSION = 1, i.e. generic HP-GL */
348 /* note: generic HP-GL can only handle integer
349 sweep angles */
350 sprintf (_plotter->data->page->point, "AA%d,%d,%d;",
351 xarray[i].pc.x, xarray[i].pc.y,
352 int_degrees);
353 _update_buffer (_plotter->data->page);
354 i++;
355 }
356 break;
357
358 default:
359 /* shouldn't happen: unknown type for path segment,
360 ignore */
361 i++;
362 break;
363 }
364 }
365 }
366
367 if (use_polygon_buffer)
368 /* using polygon mode; will now employ polygon buffer to do
369 filling (possibly) and edging */
370 {
371 if (!closed)
372 /* polyline is open, so lift pen and exit polygon mode */
373 {
374 strcpy (_plotter->data->page->point, "PU;");
375 _update_buffer (_plotter->data->page);
376 _plotter->hpgl_pendown = false;
377 strcpy (_plotter->data->page->point, "PM2;");
378 _update_buffer (_plotter->data->page);
379 }
380 else
381 /* polyline is closed, so exit polygon mode and then lift pen */
382 {
383 strcpy (_plotter->data->page->point, "PM2;");
384 _update_buffer (_plotter->data->page);
385 strcpy (_plotter->data->page->point, "PU;");
386 _update_buffer (_plotter->data->page);
387 _plotter->hpgl_pendown = false;
388 }
389
390 if (_plotter->drawstate->fill_type)
391 /* polyline should be filled */
392 {
393 /* Sync fill color. This may set the
394 _plotter->hpgl_bad_pen flag (if optimal pen is #0
395 [white] and we're not allowed to use pen #0 to draw
396 with). So we test _plotter->hpgl_bad_pen before using
397 the pen to fill with. */
398 _pl_h_set_fill_color (R___(_plotter) false);
399 if (_plotter->hpgl_bad_pen == false)
400 /* fill polyline, specifying nonzero winding rule if
401 necessary */
402 {
403 switch (_plotter->drawstate->fill_rule_type)
404 {
405 case PL_FILL_ODD_WINDING:
406 default:
407 strcpy (_plotter->data->page->point, "FP;");
408 break;
409 case PL_FILL_NONZERO_WINDING:
410 if (_plotter->hpgl_version == 2)
411 strcpy (_plotter->data->page->point, "FP1;");
412 else /* pre-HP-GL/2 doesn't support nonzero rule */
413 strcpy (_plotter->data->page->point, "FP;");
414 break;
415 }
416 _update_buffer (_plotter->data->page);
417 }
418 /* KLUDGE: in pre-HP-GL/2, our `set_fill_color' function may
419 alter the line type, since it may request *solid*
420 crosshatching; so reset the line type */
421 if (_plotter->hpgl_version < 2)
422 _pl_h_set_attributes (S___(_plotter));
423 }
424
425 if (_plotter->drawstate->pen_type)
426 /* polyline should be edged */
427 {
428 /* Sync pen color. This may set the _plotter->hpgl_bad_pen
429 flag (if optimal pen is #0 and we're not allowed to use
430 pen #0 to draw with). So we test _plotter->hpgl_bad_pen
431 before using the pen. */
432 _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH);
433 if (_plotter->hpgl_bad_pen == false)
434 /* select appropriate pen for edging, and edge the
435 polyline */
436 {
437 _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH);
438 strcpy (_plotter->data->page->point, "EP;");
439 _update_buffer (_plotter->data->page);
440 }
441 }
442 }
443
444 /* We know where the pen now is: if we used a polygon buffer, then
445 _plotter->hpgl_pos is now xarray[0].p. If we didn't (as would
446 be the case if we're outputting generic HP-GL), then
447 _plotter->hpgl_pos is now xarray[polyline_len - 1].p.
448 Unfortunately we can't simply update _plotter->hpgl_pos, because
449 we want the generated HP-GL[/2] code to work properly on both
450 HP-GL and HP-GL/2 devices. So we punt. */
451 _plotter->hpgl_position_is_unknown = true;
452
453 /* free integer storage buffer and depart */
454 free (xarray);
455 }
456 break;
457
458 case (int)PATH_BOX:
459 {
460 plPoint p0, p1, savedpoint;
461
462 p0 = _plotter->drawstate->path->p0;
463 p1 = _plotter->drawstate->path->p1;
464
465 /* sync line attributes, incl. pen width */
466 _pl_h_set_attributes (S___(_plotter));
467
468 /* move HP-GL pen to first vertex */
469 savedpoint = _plotter->drawstate->pos;
470 _plotter->drawstate->pos = p0;
471 _pl_h_set_position (S___(_plotter));
472 _plotter->drawstate->pos = savedpoint;
473
474 if (_plotter->drawstate->fill_type)
475 /* rectangle should be filled */
476 {
477 /* Sync fill color. This may set the _plotter->hpgl_bad_pen
478 flag (e.g. if optimal pen is #0 [white] and we're not
479 allowed to use pen #0 to draw with). So we test
480 _plotter->hpgl_bad_pen before using the pen. */
481 _pl_h_set_fill_color (R___(_plotter) false);
482 if (_plotter->hpgl_bad_pen == false)
483 /* fill the rectangle */
484 {
485 sprintf (_plotter->data->page->point, "RA%d,%d;",
486 IROUND(XD(p1.x,p1.y)), IROUND(YD(p1.x,p1.y)));
487 _update_buffer (_plotter->data->page);
488 }
489 /* KLUDGE: in pre-HP-GL/2, our `set_fill_color' function may
490 alter the line type, since it may request *solid*
491 crosshatching; so reset it */
492 if (_plotter->hpgl_version < 2)
493 _pl_h_set_attributes (S___(_plotter));
494 }
495
496 if (_plotter->drawstate->pen_type)
497 /* rectangle should be edged */
498 {
499 /* Sync pen color. This may set the _plotter->hpgl_bad_pen
500 flag (e.g. if optimal pen is #0 [white] and we're not
501 allowed to use pen #0 to draw with). So we test
502 _plotter->hpgl_bad_pen before using the pen. */
503 _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH);
504 if (_plotter->hpgl_bad_pen == false)
505 /* edge the rectangle */
506 {
507 sprintf (_plotter->data->page->point, "EA%d,%d;",
508 IROUND(XD(p1.x,p1.y)), IROUND(YD(p1.x,p1.y)));
509 _update_buffer (_plotter->data->page);
510 }
511 }
512 }
513 break;
514
515 case (int)PATH_CIRCLE:
516 {
517 plPoint pc, savedpoint;
518 double r = _plotter->drawstate->path->radius;
519 double radius = sqrt(XDV(r,0)*XDV(r,0)+YDV(r,0)*YDV(r,0));
520
521 pc = _plotter->drawstate->path->pc;
522
523 /* sync attributes, incl. pen width; move to center of circle */
524 _pl_h_set_attributes (S___(_plotter));
525
526 savedpoint = _plotter->drawstate->pos;
527 _plotter->drawstate->pos = pc;
528 _pl_h_set_position (S___(_plotter));
529 _plotter->drawstate->pos = savedpoint;
530
531 if (_plotter->drawstate->fill_type)
532 /* circle should be filled */
533 {
534 /* Sync fill color. This may set the _plotter->hpgl_bad_pen
535 flag (e.g. if optimal pen is #0 [white] and we're not
536 allowed to use pen #0 to draw with). So we test
537 _plotter->hpgl_bad_pen before using the pen. */
538 _pl_h_set_fill_color (R___(_plotter) false);
539 if (_plotter->hpgl_bad_pen == false)
540 /* fill the circle (360 degree wedge) */
541 {
542 sprintf (_plotter->data->page->point, "WG%d,0,360;",
543 IROUND(radius));
544 _update_buffer (_plotter->data->page);
545 }
546 /* KLUDGE: in pre-HP-GL/2, our `set_fill_color' function may
547 alter the line type, since it may request *solid*
548 crosshatching; so reset it */
549 if (_plotter->hpgl_version < 2)
550 _pl_h_set_attributes (S___(_plotter));
551 }
552
553 if (_plotter->drawstate->pen_type)
554 /* circle should be edged */
555 {
556 /* Sync pen color. This may set the _plotter->hpgl_bad_pen
557 flag (e.g. if optimal pen is #0 [white] and we're not
558 allowed to use pen #0 to draw with). So we test
559 _plotter->hpgl_bad_pen before using the pen. */
560 _pl_h_set_pen_color (R___(_plotter) HPGL_OBJECT_PATH);
561 if (_plotter->hpgl_bad_pen == false)
562 /* do the edging */
563 {
564 sprintf (_plotter->data->page->point, "CI%d;", IROUND(radius));
565 _update_buffer (_plotter->data->page);
566 }
567 }
568 }
569 break;
570
571 default: /* unrecognized path type, shouldn't happen */
572 break;
573 }
574 }
575
576 /* A low-level method for moving the pen position of an HP-GL pen plotter
577 to agree with the Plotter's notion of what the graphics cursor position
578 should be. The state of the pen (up vs. down) after calling this
579 function is not uniquely determined. */
580
581 void
_pl_h_set_position(S___ (Plotter * _plotter))582 _pl_h_set_position (S___(Plotter *_plotter))
583 {
584 int xnew, ynew;
585
586 /* if plotter's pen position doesn't agree with what it should be,
587 adjust it */
588
589 xnew = IROUND(XD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y));
590 ynew = IROUND(YD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y));
591
592 if (_plotter->hpgl_position_is_unknown == true
593 || xnew != _plotter->hpgl_pos.x || ynew != _plotter->hpgl_pos.y)
594 {
595 if (_plotter->hpgl_pendown == true)
596 {
597 sprintf (_plotter->data->page->point, "PU;PA%d,%d;", xnew, ynew);
598 _plotter->hpgl_pendown = false;
599 }
600 else
601 sprintf (_plotter->data->page->point, "PA%d,%d;", xnew, ynew);
602 _update_buffer (_plotter->data->page);
603
604 /* update our knowledge of pen position */
605 _plotter->hpgl_position_is_unknown = false;
606 _plotter->hpgl_pos.x = xnew;
607 _plotter->hpgl_pos.y = ynew;
608 }
609 }
610
611 bool
_pl_h_paint_paths(S___ (Plotter * _plotter))612 _pl_h_paint_paths (S___(Plotter *_plotter))
613 {
614 return false;
615 }
616