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 GIF Plotters. By construction, for GIF Plotters our
23 path buffer always contains either a segment list, or an ellipse object.
24 If it's a segment list, it contains either (1) a sequence of line
25 segments, or (2) a single circular or elliptic arc segment. Those are
26 all sorts of path that libxmi can handle. (For an ellipse or
27 circular/elliptic arc segment to have been added to the path buffer, the
28 map from user to device coordinates must preserve axes.) */
29
30 #include "sys-defines.h"
31 #include "extern.h"
32 #include "xmi.h" /* use libxmi scan conversion module */
33
34 #define DIST(p1, p2) sqrt( ((p1).x - (p2).x) * ((p1).x - (p2).x) \
35 + ((p1).y - (p2).y) * ((p1).y - (p2).y))
36
37 void
_pl_i_paint_path(S___ (Plotter * _plotter))38 _pl_i_paint_path (S___(Plotter *_plotter))
39 {
40 if (_plotter->drawstate->pen_type == 0
41 && _plotter->drawstate->fill_type == 0)
42 /* nothing to draw */
43 return;
44
45 switch ((int)_plotter->drawstate->path->type)
46 {
47 case (int)PATH_SEGMENT_LIST:
48 {
49 int i, polyline_len;
50 bool identical_user_coordinates = true;
51 double xu_last, yu_last;
52 miGC *pGC;
53 miPoint *miPoints, offset;
54 miPixel fgPixel, bgPixel;
55 miPixel pixels[2];
56 plPoint p0, p1, pc;
57
58 /* sanity checks */
59 if (_plotter->drawstate->path->num_segments == 0)/* nothing to do */
60 break;
61 if (_plotter->drawstate->path->num_segments == 1)/* shouldn't happen */
62 break;
63
64 if (_plotter->drawstate->path->num_segments == 2
65 && _plotter->drawstate->path->segments[1].type == S_ARC)
66 /* segment buffer contains a single circular arc, not a polyline */
67 {
68 p0 = _plotter->drawstate->path->segments[0].p;
69 p1 = _plotter->drawstate->path->segments[1].p;
70 pc = _plotter->drawstate->path->segments[1].pc;
71
72 /* use libxmi rendering */
73 _pl_i_draw_elliptic_arc (R___(_plotter) p0, p1, pc);
74
75 break;
76 }
77
78 if (_plotter->drawstate->path->num_segments == 2
79 && _plotter->drawstate->path->segments[1].type == S_ELLARC)
80 /* segment buffer contains a single elliptic arc, not a polyline */
81 {
82 p0 = _plotter->drawstate->path->segments[0].p;
83 p1 = _plotter->drawstate->path->segments[1].p;
84 pc = _plotter->drawstate->path->segments[1].pc;
85
86 /* use libxmi rendering */
87 _pl_i_draw_elliptic_arc_2 (R___(_plotter) p0, p1, pc);
88
89 break;
90 }
91
92 /* neither of above applied, so segment buffer contains a polyline,
93 not an arc */
94
95 /* construct point array for libxmi module; convert vertices to
96 device coordinates, removing runs */
97 miPoints = (miPoint *)_pl_xmalloc (_plotter->drawstate->path->num_segments * sizeof(miPoint));
98
99 polyline_len = 0;
100 xu_last = 0.0;
101 yu_last = 0.0;
102 identical_user_coordinates = true;
103 for (i = 0; i < _plotter->drawstate->path->num_segments; i++)
104 {
105 double xu, yu;
106 int device_x, device_y;
107
108 xu = _plotter->drawstate->path->segments[i].p.x;
109 yu = _plotter->drawstate->path->segments[i].p.y;
110 if (i > 0 && (xu != xu_last || yu != yu_last))
111 /* in user space, not all points are the same */
112 identical_user_coordinates = false;
113 device_x = IROUND(XD(xu, yu));
114 device_y = IROUND(YD(xu, yu));
115 if ((polyline_len == 0)
116 || (device_x != miPoints[polyline_len-1].x)
117 || (device_y != miPoints[polyline_len-1].y))
118 /* add point, in integer device coordinates, to the array */
119 {
120 miPoints[polyline_len].x = device_x;
121 miPoints[polyline_len].y = device_y;
122 polyline_len++;
123 }
124 xu_last = xu;
125 yu_last = yu;
126 }
127
128 /* determine background pixel color */
129 bgPixel.type = MI_PIXEL_INDEX_TYPE;
130 bgPixel.u.index = _plotter->drawstate->i_bg_color_index;
131 pixels[0] = bgPixel;
132 pixels[1] = bgPixel;
133
134 /* construct an miGC (graphics context for the libxmi module); copy
135 attributes from the Plotter's GC to it */
136 pGC = miNewGC (2, pixels);
137 _set_common_mi_attributes (_plotter->drawstate, (void *)pGC);
138
139 if (_plotter->drawstate->fill_type)
140 /* not transparent, will fill */
141 {
142 /* flattened drawing primitives, i.e., box/circle/ellipse,
143 are always convex */
144 miPolygonShape polygon_shape
145 = (_plotter->drawstate->path->primitive ? MI_SHAPE_CONVEX : MI_SHAPE_GENERAL);
146
147 /* set fg color in GC (and bg color too) */
148 _pl_i_set_fill_color (S___(_plotter));
149 fgPixel.type = MI_PIXEL_INDEX_TYPE;
150 fgPixel.u.index = _plotter->drawstate->i_fill_color_index;
151 pixels[0] = bgPixel;
152 pixels[1] = fgPixel;
153 miSetGCPixels (pGC, 2, pixels);
154
155 /* do the filling */
156
157 if (_plotter->drawstate->path->num_segments > 1
158 && polyline_len == 1)
159 /* special case: all user-space points in polyline were
160 mapped to a single integer pixel, so just paint it */
161 miDrawPoints ((miPaintedSet *)_plotter->i_painted_set, pGC,
162 MI_COORD_MODE_ORIGIN, 1, miPoints);
163 else
164 /* normal case */
165 miFillPolygon ((miPaintedSet *)_plotter->i_painted_set, pGC,
166 polygon_shape,
167 MI_COORD_MODE_ORIGIN, polyline_len, miPoints);
168 }
169
170 if (_plotter->drawstate->pen_type)
171 /* pen is present, so edge the polyline */
172 {
173 /* set fg color in GC (and bg color too) */
174 _pl_i_set_pen_color (S___(_plotter));
175 fgPixel.type = MI_PIXEL_INDEX_TYPE;
176 fgPixel.u.index = _plotter->drawstate->i_pen_color_index;
177 pixels[0] = bgPixel;
178 pixels[1] = fgPixel;
179 miSetGCPixels (pGC, 2, pixels);
180
181 if (polyline_len == 1)
182 /* All user-space points in the polyline were mapped to a
183 single pixel. If (1) they weren't all the same to begin
184 with, or (2) they were all the same to begin with and the
185 cap mode is "round", then draw as a filled circle of
186 diameter equal to the line width; otherwise draw
187 nothing. */
188 {
189 if (identical_user_coordinates == false
190 || _plotter->drawstate->cap_type == PL_CAP_ROUND)
191 {
192 unsigned int sp_size
193 = (unsigned int)_plotter->drawstate->quantized_device_line_width;
194 if (sp_size == 0)
195 sp_size = 1;
196
197 if (sp_size == 1)
198 /* subcase: just draw a point */
199 miDrawPoints ((miPaintedSet *)_plotter->i_painted_set, pGC,
200 MI_COORD_MODE_ORIGIN, 1, miPoints);
201 else
202 /* draw a filled circle */
203 {
204 int sp_offset;
205 miArc arc;
206
207 sp_offset =
208 (_plotter->drawstate->quantized_device_line_width + 1) / 2;
209 arc.x = miPoints[0].x - sp_offset;
210 arc.y = miPoints[0].y - sp_offset;
211 arc.width = sp_size;
212 arc.height = sp_size;
213 arc.angle1 = 0;
214 arc.angle2 = 64 * 360;
215 miFillArcs ((miPaintedSet *)_plotter->i_painted_set,
216 pGC, 1, &arc);
217 }
218 }
219 }
220 else
221 /* normal case: draw a nondegenerate polyline in integer
222 device space */
223 miDrawLines ((miPaintedSet *)_plotter->i_painted_set, pGC,
224 MI_COORD_MODE_ORIGIN, polyline_len, miPoints);
225 }
226
227 /* deallocate miGC and free temporary points array */
228 miDeleteGC (pGC);
229 free (miPoints);
230
231 /* copy from painted set to canvas, and clear */
232 offset.x = 0;
233 offset.y = 0;
234 miCopyPaintedSetToCanvas ((miPaintedSet *)_plotter->i_painted_set,
235 (miCanvas *)_plotter->i_canvas,
236 offset);
237 miClearPaintedSet ((miPaintedSet *)_plotter->i_painted_set);
238 }
239
240 /* something was drawn in frame */
241 _plotter->i_frame_nonempty = true;
242 break;
243
244 case (int)PATH_ELLIPSE:
245 {
246 int ninetymult;
247 int x_orientation, y_orientation;
248 int xorigin, yorigin;
249 unsigned int squaresize_x, squaresize_y;
250 plPoint pc;
251 double rx, ry, angle;
252
253 pc = _plotter->drawstate->path->pc;
254 rx = _plotter->drawstate->path->rx;
255 ry = _plotter->drawstate->path->ry;
256 angle = _plotter->drawstate->path->angle;
257
258 /* if angle is multiple of 90 degrees, modify to permit use of
259 libxmi's arc rendering */
260 ninetymult = IROUND(angle / 90.0);
261 if (angle == (double) (90 * ninetymult))
262 {
263 angle = 0.0;
264 if (ninetymult % 2)
265 {
266 double temp;
267
268 temp = rx;
269 rx = ry;
270 ry = temp;
271 }
272 }
273
274 rx = (rx < 0.0 ? -rx : rx); /* avoid obscure libxmi problems */
275 ry = (ry < 0.0 ? -ry : ry);
276
277 /* axes flipped? (by default y-axis is, due to libxmi's flipped-y
278 convention) */
279 x_orientation = (_plotter->drawstate->transform.m[0] >= 0 ? 1 : -1);
280 y_orientation = (_plotter->drawstate->transform.m[3] >= 0 ? 1 : -1);
281
282 /* location of `origin' (upper left corner of bounding rect. for
283 ellipse) and width and height; libxmi's flipped-y convention
284 affects these values */
285 xorigin = IROUND(XD(pc.x - x_orientation * rx,
286 pc.y - y_orientation * ry));
287 yorigin = IROUND(YD(pc.x - x_orientation * rx,
288 pc.y - y_orientation * ry));
289 squaresize_x = (unsigned int)IROUND(XDV(2 * x_orientation * rx, 0.0));
290 squaresize_y = (unsigned int)IROUND(YDV(0.0, 2 * y_orientation * ry));
291 /* Because this ellipse object was added to the path buffer, we
292 already know that (1) the user->device frame map preserves
293 coordinate axes, (2) effectively, angle == 0. These are
294 necessary for the libxmi scan-conversion module to do the
295 drawing. */
296
297 /* draw ellipse (elliptic arc aligned with the coordinate axes, arc
298 range = 64*360 64'ths of a degree) */
299 _pl_i_draw_elliptic_arc_internal (R___(_plotter)
300 xorigin, yorigin,
301 squaresize_x, squaresize_y,
302 0, 64 * 360);
303 }
304 break;
305
306 default: /* shouldn't happen */
307 break;
308 }
309 }
310
311 /* Use libxmi rendering to draw what would be a circular arc in the user
312 frame. If this is called, the map from user to device coordinates is
313 assumed to preserve coordinate axes (it may be anisotropic [x and y
314 directions scaled differently], and it may include a reflection through
315 either or both axes). So it will be a circular or elliptic arc in the
316 device frame, of the sort that libxmi supports. */
317
318 void
_pl_i_draw_elliptic_arc(R___ (Plotter * _plotter)plPoint p0,plPoint p1,plPoint pc)319 _pl_i_draw_elliptic_arc (R___(Plotter *_plotter) plPoint p0, plPoint p1, plPoint pc)
320 {
321 double radius;
322 double theta0, theta1;
323 int startangle, anglerange;
324 int x_orientation, y_orientation;
325 int xorigin, yorigin;
326 unsigned int squaresize_x, squaresize_y;
327
328 /* axes flipped? (by default y-axis is, due to xmi's flipped-y convention) */
329 x_orientation = (_plotter->drawstate->transform.m[0] >= 0 ? 1 : -1);
330 y_orientation = (_plotter->drawstate->transform.m[3] >= 0 ? 1 : -1);
331
332 /* radius of circular arc in user frame is distance to p0, and also to p1 */
333 radius = DIST(pc, p0);
334
335 /* location of `origin' (upper left corner of bounding rect. on display)
336 and width and height; X's flipped-y convention affects these values */
337 xorigin = IROUND(XD(pc.x - x_orientation * radius,
338 pc.y - y_orientation * radius));
339 yorigin = IROUND(YD(pc.x - x_orientation * radius,
340 pc.y - y_orientation * radius));
341 squaresize_x = (unsigned int)IROUND(XDV(2 * x_orientation * radius, 0.0));
342 squaresize_y = (unsigned int)IROUND(YDV(0.0, 2 * y_orientation * radius));
343
344 theta0 = _xatan2 (-y_orientation * (p0.y - pc.y),
345 x_orientation * (p0.x - pc.x)) / M_PI;
346 theta1 = _xatan2 (-y_orientation * (p1.y - pc.y),
347 x_orientation * (p1.x - pc.x)) / M_PI;
348
349 if (theta1 < theta0)
350 theta1 += 2.0; /* adjust so that difference > 0 */
351 if (theta0 < 0.0)
352 {
353 theta0 += 2.0; /* adjust so that startangle > 0 */
354 theta1 += 2.0;
355 }
356
357 if (theta1 - theta0 > 1.0) /* swap if angle appear to be > 180 degrees */
358 {
359 double tmp;
360
361 tmp = theta0;
362 theta0 = theta1;
363 theta1 = tmp;
364 theta1 += 2.0; /* adjust so that difference > 0 */
365 }
366
367 if (theta0 >= 2.0 && theta1 >= 2.0)
368 /* avoid obscure X bug */
369 {
370 theta0 -= 2.0;
371 theta1 -= 2.0;
372 }
373
374 startangle = IROUND(64 * theta0 * 180.0); /* in 64'ths of a degree */
375 anglerange = IROUND(64 * (theta1 - theta0) * 180.0); /* likewise */
376
377 _pl_i_draw_elliptic_arc_internal (R___(_plotter)
378 xorigin, yorigin,
379 squaresize_x, squaresize_y,
380 startangle, anglerange);
381 }
382
383 /* Use libxmi rendering to draw what would be a quarter-ellipse in the user
384 frame. If this is called, the map from user to device coordinates is
385 assumed to preserve coordinate axes (it may be anisotropic [x and y
386 directions scaled differently], and it may include a reflection through
387 either or both axes). So it will be a quarter-ellipse in the device
388 frame, of the sort that libxmi supports. */
389 void
_pl_i_draw_elliptic_arc_2(R___ (Plotter * _plotter)plPoint p0,plPoint p1,plPoint pc)390 _pl_i_draw_elliptic_arc_2 (R___(Plotter *_plotter) plPoint p0, plPoint p1, plPoint pc)
391 {
392 double rx, ry;
393 double x0, y0, x1, y1, xc, yc;
394 int startangle, endangle, anglerange;
395 int x_orientation, y_orientation;
396 int xorigin, yorigin;
397 unsigned int squaresize_x, squaresize_y;
398
399 /* axes flipped? (by default y-axis is, due to xmi's flipped-y convention) */
400 x_orientation = (_plotter->drawstate->transform.m[0] >= 0 ? 1 : -1);
401 y_orientation = (_plotter->drawstate->transform.m[3] >= 0 ? 1 : -1);
402
403 xc = pc.x, yc = pc.y;
404 x0 = p0.x, y0 = p0.y;
405 x1 = p1.x, y1 = p1.y;
406
407 if (y0 == yc && x1 == xc)
408 /* initial pt. on x-axis, final pt. on y-axis */
409 {
410 /* semi-axes in user frame */
411 rx = (x0 > xc) ? x0 - xc : xc - x0;
412 ry = (y1 > yc) ? y1 - yc : yc - y1;
413 /* starting and ending angles; note flipped-y convention */
414 startangle = ((x0 > xc ? 1 : -1) * x_orientation == 1) ? 0 : 180;
415 endangle = ((y1 > yc ? 1 : -1) * y_orientation == -1) ? 90 : 270;
416 }
417 else
418 /* initial pt. on y-axis, final pt. on x-axis */
419 {
420 /* semi-axes in user frame */
421 rx = (x1 > xc) ? x1 - xc : xc - x1;
422 ry = (y0 > yc) ? y0 - yc : yc - y0;
423 /* starting and ending angles; note flipped-y convention */
424 startangle = ((y0 > yc ? 1 : -1) * y_orientation == -1) ? 90 : 270;
425 endangle = ((x1 > xc ? 1 : -1) * x_orientation == 1) ? 0 : 180;
426 }
427
428 if (endangle < startangle)
429 endangle += 360;
430 anglerange = endangle - startangle; /* always 90 or 270 */
431
432 /* our convention: a quarter-ellipse can only be 90 degrees
433 of a libxmi ellipse, not 270 degrees, so interchange points */
434 if (anglerange == 270)
435 {
436 int tmp;
437
438 tmp = startangle;
439 startangle = endangle;
440 endangle = tmp;
441 anglerange = 90;
442 }
443
444 if (startangle >= 360)
445 /* avoid obscure libxmi bug */
446 startangle -= 360; /* endangle no longer relevant */
447
448 /* location of `origin' (upper left corner of bounding rect. on display)
449 and width and height; xmi's flipped-y convention affects these values */
450 xorigin = IROUND(XD(xc - x_orientation * rx,
451 yc - y_orientation * ry));
452 yorigin = IROUND(YD(xc - x_orientation * rx,
453 yc - y_orientation * ry));
454 squaresize_x = (unsigned int)IROUND(XDV(2 * x_orientation * rx, 0.0));
455 squaresize_y = (unsigned int)IROUND(YDV(0.0, 2 * y_orientation * ry));
456
457 /* reexpress in 64'ths of a degree (libxmi convention) */
458 startangle *= 64;
459 anglerange *= 64;
460
461 _pl_i_draw_elliptic_arc_internal (R___(_plotter)
462 xorigin, yorigin,
463 squaresize_x, squaresize_y,
464 startangle, anglerange);
465 }
466
467 /* Draw an elliptic arc aligned with the coordinate axes, by invoking a
468 function in the libxmi API. Takes account of the possible need for
469 filling.
470
471 The cases squaresize_x = 0 and squaresize_y = 0 are handled specially,
472 since miFillArcs() and miDrawArcs() do not support them. */
473
474 void
_pl_i_draw_elliptic_arc_internal(R___ (Plotter * _plotter)int xorigin,int yorigin,unsigned int squaresize_x,unsigned int squaresize_y,int startangle,int anglerange)475 _pl_i_draw_elliptic_arc_internal (R___(Plotter *_plotter) int xorigin, int yorigin, unsigned int squaresize_x, unsigned int squaresize_y, int startangle, int anglerange)
476 {
477 miGC *pGC;
478 miArc arc;
479 miPixel fgPixel, bgPixel;
480 miPixel pixels[2];
481 miPoint offset;
482
483 /* determine background pixel color */
484 bgPixel.type = MI_PIXEL_INDEX_TYPE;
485 bgPixel.u.index = _plotter->drawstate->i_bg_color_index;
486 pixels[0] = bgPixel;
487 pixels[1] = bgPixel;
488
489 /* construct an miGC (graphics context for the libxmi module); copy
490 attributes from the Plotter's GC to it */
491 pGC = miNewGC (2, pixels);
492 _set_common_mi_attributes (_plotter->drawstate, pGC);
493
494 /* libxmi's definition of an elliptic arc aligned with the axes */
495 arc.x = xorigin;
496 arc.y = yorigin;
497 arc.width = squaresize_x;
498 arc.height = squaresize_y;
499 arc.angle1 = startangle;
500 arc.angle2 = anglerange;
501
502 if (_plotter->drawstate->fill_type)
503 /* not transparent, so fill the arc */
504 {
505 /* set fg color in GC (and bg color too) */
506 _pl_i_set_fill_color (S___(_plotter));
507 fgPixel.type = MI_PIXEL_INDEX_TYPE;
508 fgPixel.u.index = _plotter->drawstate->i_fill_color_index;
509 pixels[0] = bgPixel;
510 pixels[1] = fgPixel;
511 miSetGCPixels (pGC, 2, pixels);
512
513 /* fill the arc */
514 if (squaresize_x <= 1 || squaresize_y <= 1)
515 /* a special case, which miFillArcs() doesn't handle in the way we'd
516 like; just paint a single pixel, irrespective of angle range */
517 {
518 miPoint point;
519
520 point.x = xorigin;
521 point.y = yorigin;
522 miDrawPoints ((miPaintedSet *)_plotter->i_painted_set,
523 pGC, MI_COORD_MODE_ORIGIN, 1, &point);
524 }
525 else
526 /* default case */
527 miFillArcs ((miPaintedSet *)_plotter->i_painted_set, pGC, 1, &arc);
528 }
529
530 if (_plotter->drawstate->pen_type)
531 /* pen is present, so edge the arc */
532 {
533 unsigned int sp_size = 0; /* keep compiler happy */
534
535 /* set fg color in GC (and bg color too) */
536 _pl_i_set_pen_color (S___(_plotter));
537 fgPixel.type = MI_PIXEL_INDEX_TYPE;
538 fgPixel.u.index = _plotter->drawstate->i_pen_color_index;
539 pixels[0] = bgPixel;
540 pixels[1] = fgPixel;
541 miSetGCPixels (pGC, 2, pixels);
542
543 if (squaresize_x <= 1 || squaresize_y <= 1)
544 /* Won't call miDrawArcs in the usual way, because it performs
545 poorly when one of these two is zero, at least. Irrespective of
546 angle range, will fill a disk of diameter equal to line width */
547 {
548 int sp_offset;
549
550 sp_size
551 = (unsigned int)_plotter->drawstate->quantized_device_line_width;
552 sp_offset
553 = (int)(_plotter->drawstate->quantized_device_line_width + 1) / 2;
554
555 if (sp_size == 0)
556 sp_size = 1;
557 arc.x -= sp_offset;
558 arc.y -= sp_offset;
559 arc.width = sp_size;
560 arc.height = sp_size;
561 arc.angle1 = 0;
562 arc.angle2 = 64 * 360;
563 }
564
565 /* edge the arc by invoking libxmi's reentrant arc-drawing function,
566 passing it as final argument a pointer to persistent storage
567 maintained by the Plotter */
568
569 if (squaresize_x <= 1 || squaresize_y <= 1)
570 /* miDrawArcs doesn't handle this case as we'd wish, will
571 treat specially */
572 {
573 if (sp_size == 1)
574 /* special subcase: line width is small too, so just paint a
575 single pixel rather than filling abovementioned disk */
576 {
577 miPoint point;
578
579 point.x = xorigin;
580 point.y = yorigin;
581 miDrawPoints ((miPaintedSet *)_plotter->i_painted_set,
582 pGC, MI_COORD_MODE_ORIGIN, 1, &point);
583 }
584 else
585 /* normal version of special case: draw filled disk of diameter
586 equal to the line width, irrespective of the angle range */
587 miFillArcs((miPaintedSet *)_plotter->i_painted_set, pGC, 1, &arc);
588 }
589 else
590 /* default case, which is what is almost always used */
591 miDrawArcs_r ((miPaintedSet *)_plotter->i_painted_set, pGC, 1, &arc,
592 (miEllipseCache *)(_plotter->i_arc_cache_data));
593 }
594
595 /* deallocate miGC */
596 miDeleteGC (pGC);
597
598 /* copy from painted set to canvas, and clear */
599 offset.x = 0;
600 offset.y = 0;
601 miCopyPaintedSetToCanvas ((miPaintedSet *)_plotter->i_painted_set,
602 (miCanvas *)_plotter->i_canvas,
603 offset);
604 miClearPaintedSet ((miPaintedSet *)_plotter->i_painted_set);
605 }
606
607 bool
_pl_i_paint_paths(S___ (Plotter * _plotter))608 _pl_i_paint_paths (S___(Plotter *_plotter))
609 {
610 return false;
611 }
612