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