No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / groff / src / preproc / pic / common.cpp
blobfd883d5139123e2ac94a154a3cb2986d9e31ddfb
1 /* $NetBSD$ */
3 // -*- C++ -*-
4 /* Copyright (C) 1989, 1990, 1991, 1992, 2003 Free Software Foundation, Inc.
5 Written by James Clark (jjc@jclark.com)
7 This file is part of groff.
9 groff is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
14 groff is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License along
20 with groff; see the file COPYING. If not, write to the Free Software
21 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
23 #include "pic.h"
24 #include "common.h"
26 // output a dashed circle as a series of arcs
28 void common_output::dashed_circle(const position &cent, double rad,
29 const line_type &lt)
31 assert(lt.type == line_type::dashed);
32 line_type slt = lt;
33 slt.type = line_type::solid;
34 double dash_angle = lt.dash_width/rad;
35 int ndashes;
36 double gap_angle;
37 if (dash_angle >= M_PI/4.0) {
38 if (dash_angle < M_PI/2.0) {
39 gap_angle = M_PI/2.0 - dash_angle;
40 ndashes = 4;
42 else if (dash_angle < M_PI) {
43 gap_angle = M_PI - dash_angle;
44 ndashes = 2;
46 else {
47 circle(cent, rad, slt, -1.0);
48 return;
51 else {
52 ndashes = 4*int(ceil(M_PI/(4.0*dash_angle)));
53 gap_angle = (M_PI*2.0)/ndashes - dash_angle;
55 for (int i = 0; i < ndashes; i++) {
56 double start_angle = i*(dash_angle+gap_angle) - dash_angle/2.0;
57 solid_arc(cent, rad, start_angle, start_angle + dash_angle, lt);
61 // output a dotted circle as a series of dots
63 void common_output::dotted_circle(const position &cent, double rad,
64 const line_type &lt)
66 assert(lt.type == line_type::dotted);
67 double gap_angle = lt.dash_width/rad;
68 int ndots;
69 if (gap_angle >= M_PI/2.0) {
70 // always have at least 2 dots
71 gap_angle = M_PI;
72 ndots = 2;
74 else {
75 ndots = 4*int(M_PI/(2.0*gap_angle));
76 gap_angle = (M_PI*2.0)/ndots;
78 double ang = 0.0;
79 for (int i = 0; i < ndots; i++, ang += gap_angle)
80 dot(cent + position(cos(ang), sin(ang))*rad, lt);
83 // recursive function for dash drawing, used by dashed_ellipse
85 void common_output::ellipse_arc(const position &cent,
86 const position &z0, const position &z1,
87 const distance &dim, const line_type &lt)
89 assert(lt.type == line_type::solid);
90 assert(dim.x != 0 && dim.y != 0);
91 double eps = 0.0001;
92 position zml = (z0 + z1) / 2;
93 // apply affine transformation (from ellipse to circle) to compute angle
94 // of new position, then invert transformation to get exact position
95 double psi = atan2(zml.y / dim.y, zml.x / dim.x);
96 position zm = position(dim.x * cos(psi), dim.y * sin(psi));
97 // to approximate the ellipse arc with one or more circle arcs, we
98 // first compute the radius of curvature in zm
99 double a_2 = dim.x * dim.x;
100 double a_4 = a_2 * a_2;
101 double b_2 = dim.y * dim.y;
102 double b_4 = b_2 * b_2;
103 double e_2 = a_2 - b_2;
104 double temp = a_4 * zm.y * zm.y + b_4 * zm.x * zm.x;
105 double rho = sqrt(temp / a_4 / b_4 * temp / a_4 / b_4 * temp);
106 // compute center of curvature circle
107 position M = position(e_2 * zm.x / a_2 * zm.x / a_2 * zm.x,
108 -e_2 * zm.y / b_2 * zm.y / b_2 * zm.y);
109 // compute distance between circle and ellipse arc at start and end
110 double phi0 = atan2(z0.y - M.y, z0.x - M.x);
111 double phi1 = atan2(z1.y - M.y, z1.x - M.x);
112 position M0 = position(rho * cos(phi0), rho * sin(phi0)) + M;
113 position M1 = position(rho * cos(phi1), rho * sin(phi1)) + M;
114 double dist0 = hypot(z0 - M0) / sqrt(z0 * z0);
115 double dist1 = hypot(z1 - M1) / sqrt(z1 * z1);
116 if (dist0 < eps && dist1 < eps)
117 solid_arc(M + cent, rho, phi0, phi1, lt);
118 else {
119 ellipse_arc(cent, z0, zm, dim, lt);
120 ellipse_arc(cent, zm, z1, dim, lt);
124 // output a dashed ellipse as a series of arcs
126 void common_output::dashed_ellipse(const position &cent, const distance &dim,
127 const line_type &lt)
129 assert(lt.type == line_type::dashed);
130 double dim_x = dim.x / 2;
131 double dim_y = dim.y / 2;
132 line_type slt = lt;
133 slt.type = line_type::solid;
134 double dw = lt.dash_width;
135 // we use an approximation to compute the ellipse length (found in:
136 // Bronstein, Semendjajew, Taschenbuch der Mathematik)
137 double lambda = (dim.x - dim.y) / (dim.x + dim.y);
138 double le = M_PI / 2 * (dim.x + dim.y)
139 * ((64 - 3 * lambda * lambda * lambda * lambda )
140 / (64 - 16 * lambda * lambda));
141 // for symmetry we make nmax a multiple of 8
142 int nmax = 8 * int(le / dw / 8 + 0.5);
143 if (nmax < 8) {
144 nmax = 8;
145 dw = le / 8;
147 int ndash = nmax / 2;
148 double gapwidth = (le - dw * ndash) / ndash;
149 double l = 0;
150 position z = position(dim_x, 0);
151 position zdot = z;
152 int j = 0;
153 int jmax = int(10 / lt.dash_width);
154 for (int i = 0; i <= nmax; i++) {
155 position zold = z;
156 position zpre = zdot;
157 double ld = (int(i / 2) + 0.5) * dw + int((i + 1) / 2) * gapwidth;
158 double lold = 0;
159 double dl = 1;
160 // find next position for fixed arc length
161 while (l < ld) {
162 j++;
163 lold = l;
164 zold = z;
165 double phi = j * 2 * M_PI / jmax;
166 z = position(dim_x * cos(phi), dim_y * sin(phi));
167 dl = hypot(z - zold);
168 l += dl;
170 // interpolate linearly between the last two points,
171 // using the length difference as the scaling factor
172 double delta = (ld - lold) / dl;
173 zdot = zold + (z - zold) * delta;
174 // compute angle of new position on the affine circle
175 // and use it to get the exact value on the ellipse
176 double psi = atan2(zdot.y / dim_y, zdot.x / dim_x);
177 zdot = position(dim_x * cos(psi), dim_y * sin(psi));
178 if ((i % 2 == 0) && (i > 1))
179 ellipse_arc(cent, zpre, zdot, dim / 2, slt);
183 // output a dotted ellipse as a series of dots
185 void common_output::dotted_ellipse(const position &cent, const distance &dim,
186 const line_type &lt)
188 assert(lt.type == line_type::dotted);
189 double dim_x = dim.x / 2;
190 double dim_y = dim.y / 2;
191 line_type slt = lt;
192 slt.type = line_type::solid;
193 // we use an approximation to compute the ellipse length (found in:
194 // Bronstein, Semendjajew, Taschenbuch der Mathematik)
195 double lambda = (dim.x - dim.y) / (dim.x + dim.y);
196 double le = M_PI / 2 * (dim.x + dim.y)
197 * ((64 - 3 * lambda * lambda * lambda * lambda )
198 / (64 - 16 * lambda * lambda));
199 // for symmetry we make nmax a multiple of 4
200 int ndots = 4 * int(le / lt.dash_width / 4 + 0.5);
201 if (ndots < 4)
202 ndots = 4;
203 double l = 0;
204 position z = position(dim_x, 0);
205 int j = 0;
206 int jmax = int(10 / lt.dash_width);
207 for (int i = 1; i <= ndots; i++) {
208 position zold = z;
209 double lold = l;
210 double ld = i * le / ndots;
211 double dl = 1;
212 // find next position for fixed arc length
213 while (l < ld) {
214 j++;
215 lold = l;
216 zold = z;
217 double phi = j * 2 * M_PI / jmax;
218 z = position(dim_x * cos(phi), dim_y * sin(phi));
219 dl = hypot(z - zold);
220 l += dl;
222 // interpolate linearly between the last two points,
223 // using the length difference as the scaling factor
224 double delta = (ld - lold) / dl;
225 position zdot = zold + (z - zold) * delta;
226 // compute angle of new position on the affine circle
227 // and use it to get the exact value on the ellipse
228 double psi = atan2(zdot.y / dim_y, zdot.x / dim_x);
229 zdot = position(dim_x * cos(psi), dim_y * sin(psi));
230 dot(cent + zdot, slt);
234 // return non-zero iff we can compute a center
236 int compute_arc_center(const position &start, const position &cent,
237 const position &end, position *result)
239 // This finds the point along the vector from start to cent that
240 // is equidistant between start and end.
241 distance c = cent - start;
242 distance e = end - start;
243 double n = c*e;
244 if (n == 0.0)
245 return 0;
246 *result = start + c*((e*e)/(2.0*n));
247 return 1;
250 // output a dashed arc as a series of arcs
252 void common_output::dashed_arc(const position &start, const position &cent,
253 const position &end, const line_type &lt)
255 assert(lt.type == line_type::dashed);
256 position c;
257 if (!compute_arc_center(start, cent, end, &c)) {
258 line(start, &end, 1, lt);
259 return;
261 distance start_offset = start - c;
262 distance end_offset = end - c;
263 double start_angle = atan2(start_offset.y, start_offset.x);
264 double end_angle = atan2(end_offset.y, end_offset.x);
265 double rad = hypot(c - start);
266 double dash_angle = lt.dash_width/rad;
267 double total_angle = end_angle - start_angle;
268 while (total_angle < 0)
269 total_angle += M_PI + M_PI;
270 if (total_angle <= dash_angle*2.0) {
271 solid_arc(cent, rad, start_angle, end_angle, lt);
272 return;
274 int ndashes = int((total_angle - dash_angle)/(dash_angle*2.0) + .5);
275 double dash_and_gap_angle = (total_angle - dash_angle)/ndashes;
276 for (int i = 0; i <= ndashes; i++)
277 solid_arc(cent, rad, start_angle + i*dash_and_gap_angle,
278 start_angle + i*dash_and_gap_angle + dash_angle, lt);
281 // output a dotted arc as a series of dots
283 void common_output::dotted_arc(const position &start, const position &cent,
284 const position &end, const line_type &lt)
286 assert(lt.type == line_type::dotted);
287 position c;
288 if (!compute_arc_center(start, cent, end, &c)) {
289 line(start, &end, 1, lt);
290 return;
292 distance start_offset = start - c;
293 distance end_offset = end - c;
294 double start_angle = atan2(start_offset.y, start_offset.x);
295 double total_angle = atan2(end_offset.y, end_offset.x) - start_angle;
296 while (total_angle < 0)
297 total_angle += M_PI + M_PI;
298 double rad = hypot(c - start);
299 int ndots = int(total_angle/(lt.dash_width/rad) + .5);
300 if (ndots == 0)
301 dot(start, lt);
302 else {
303 for (int i = 0; i <= ndots; i++) {
304 double a = start_angle + (total_angle*i)/ndots;
305 dot(cent + position(cos(a), sin(a))*rad, lt);
310 void common_output::solid_arc(const position &cent, double rad,
311 double start_angle, double end_angle,
312 const line_type &lt)
314 line_type slt = lt;
315 slt.type = line_type::solid;
316 arc(cent + position(cos(start_angle), sin(start_angle))*rad,
317 cent,
318 cent + position(cos(end_angle), sin(end_angle))*rad,
319 slt);
323 void common_output::rounded_box(const position &cent, const distance &dim,
324 double rad, const line_type &lt, double fill)
326 if (fill >= 0.0)
327 filled_rounded_box(cent, dim, rad, fill);
328 switch (lt.type) {
329 case line_type::invisible:
330 break;
331 case line_type::dashed:
332 dashed_rounded_box(cent, dim, rad, lt);
333 break;
334 case line_type::dotted:
335 dotted_rounded_box(cent, dim, rad, lt);
336 break;
337 case line_type::solid:
338 solid_rounded_box(cent, dim, rad, lt);
339 break;
340 default:
341 assert(0);
346 void common_output::dashed_rounded_box(const position &cent,
347 const distance &dim, double rad,
348 const line_type &lt)
350 line_type slt = lt;
351 slt.type = line_type::solid;
353 double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
354 int n_hor_dashes = int(hor_length/(lt.dash_width*2.0) + .5);
355 double hor_gap_width = (n_hor_dashes != 0
356 ? hor_length/n_hor_dashes - lt.dash_width
357 : 0.0);
359 double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
360 int n_vert_dashes = int(vert_length/(lt.dash_width*2.0) + .5);
361 double vert_gap_width = (n_vert_dashes != 0
362 ? vert_length/n_vert_dashes - lt.dash_width
363 : 0.0);
364 // Note that each corner arc has to be split into two for dashing,
365 // because one part is dashed using vert_gap_width, and the other
366 // using hor_gap_width.
367 double offset = lt.dash_width/2.0;
368 dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
369 -M_PI/4.0, 0, slt, lt.dash_width, vert_gap_width, &offset);
370 dash_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
371 cent + position(dim.x/2.0, dim.y/2.0 - rad),
372 slt, lt.dash_width, vert_gap_width, &offset);
373 dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
374 0, M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
376 offset = lt.dash_width/2.0;
377 dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
378 M_PI/4.0, M_PI/2, slt, lt.dash_width, hor_gap_width, &offset);
379 dash_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
380 cent + position(-dim.x/2.0 + rad, dim.y/2.0),
381 slt, lt.dash_width, hor_gap_width, &offset);
382 dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
383 M_PI/2, 3*M_PI/4.0, slt, lt.dash_width, hor_gap_width, &offset);
385 offset = lt.dash_width/2.0;
386 dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
387 3.0*M_PI/4.0, M_PI, slt, lt.dash_width, vert_gap_width, &offset);
388 dash_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad),
389 cent + position(-dim.x/2.0, -dim.y/2.0 + rad),
390 slt, lt.dash_width, vert_gap_width, &offset);
391 dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
392 M_PI, 5.0*M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
394 offset = lt.dash_width/2.0;
395 dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
396 5*M_PI/4.0, 3*M_PI/2.0, slt, lt.dash_width, hor_gap_width, &offset);
397 dash_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0),
398 cent + position(dim.x/2.0 - rad, -dim.y/2.0),
399 slt, lt.dash_width, hor_gap_width, &offset);
400 dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
401 3*M_PI/2, 7*M_PI/4, slt, lt.dash_width, hor_gap_width, &offset);
404 // Used by dashed_rounded_box.
406 void common_output::dash_arc(const position &cent, double rad,
407 double start_angle, double end_angle,
408 const line_type &lt,
409 double dash_width, double gap_width,
410 double *offsetp)
412 double length = (end_angle - start_angle)*rad;
413 double pos = 0.0;
414 for (;;) {
415 if (*offsetp >= dash_width) {
416 double rem = dash_width + gap_width - *offsetp;
417 if (pos + rem > length) {
418 *offsetp += length - pos;
419 break;
421 else {
422 pos += rem;
423 *offsetp = 0.0;
426 else {
427 double rem = dash_width - *offsetp;
428 if (pos + rem > length) {
429 solid_arc(cent, rad, start_angle + pos/rad, end_angle, lt);
430 *offsetp += length - pos;
431 break;
433 else {
434 solid_arc(cent, rad, start_angle + pos/rad,
435 start_angle + (pos + rem)/rad, lt);
436 pos += rem;
437 *offsetp = dash_width;
443 // Used by dashed_rounded_box.
445 void common_output::dash_line(const position &start, const position &end,
446 const line_type &lt,
447 double dash_width, double gap_width,
448 double *offsetp)
450 distance dist = end - start;
451 double length = hypot(dist);
452 if (length == 0.0)
453 return;
454 double pos = 0.0;
455 for (;;) {
456 if (*offsetp >= dash_width) {
457 double rem = dash_width + gap_width - *offsetp;
458 if (pos + rem > length) {
459 *offsetp += length - pos;
460 break;
462 else {
463 pos += rem;
464 *offsetp = 0.0;
467 else {
468 double rem = dash_width - *offsetp;
469 if (pos + rem > length) {
470 line(start + dist*(pos/length), &end, 1, lt);
471 *offsetp += length - pos;
472 break;
474 else {
475 position p(start + dist*((pos + rem)/length));
476 line(start + dist*(pos/length), &p, 1, lt);
477 pos += rem;
478 *offsetp = dash_width;
484 void common_output::dotted_rounded_box(const position &cent,
485 const distance &dim, double rad,
486 const line_type &lt)
488 line_type slt = lt;
489 slt.type = line_type::solid;
491 double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
492 int n_hor_dots = int(hor_length/lt.dash_width + .5);
493 double hor_gap_width = (n_hor_dots != 0
494 ? hor_length/n_hor_dots
495 : lt.dash_width);
497 double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
498 int n_vert_dots = int(vert_length/lt.dash_width + .5);
499 double vert_gap_width = (n_vert_dots != 0
500 ? vert_length/n_vert_dots
501 : lt.dash_width);
502 double epsilon = lt.dash_width/(rad*100.0);
504 double offset = 0.0;
505 dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
506 -M_PI/4.0, 0, slt, vert_gap_width, &offset);
507 dot_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
508 cent + position(dim.x/2.0, dim.y/2.0 - rad),
509 slt, vert_gap_width, &offset);
510 dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
511 0, M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
513 offset = 0.0;
514 dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
515 M_PI/4.0, M_PI/2, slt, hor_gap_width, &offset);
516 dot_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
517 cent + position(-dim.x/2.0 + rad, dim.y/2.0),
518 slt, hor_gap_width, &offset);
519 dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
520 M_PI/2, 3*M_PI/4.0 - epsilon, slt, hor_gap_width, &offset);
522 offset = 0.0;
523 dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
524 3.0*M_PI/4.0, M_PI, slt, vert_gap_width, &offset);
525 dot_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad),
526 cent + position(-dim.x/2.0, -dim.y/2.0 + rad),
527 slt, vert_gap_width, &offset);
528 dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
529 M_PI, 5.0*M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
531 offset = 0.0;
532 dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
533 5*M_PI/4.0, 3*M_PI/2.0, slt, hor_gap_width, &offset);
534 dot_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0),
535 cent + position(dim.x/2.0 - rad, -dim.y/2.0),
536 slt, hor_gap_width, &offset);
537 dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
538 3*M_PI/2, 7*M_PI/4 - epsilon, slt, hor_gap_width, &offset);
541 // Used by dotted_rounded_box.
543 void common_output::dot_arc(const position &cent, double rad,
544 double start_angle, double end_angle,
545 const line_type &lt, double gap_width,
546 double *offsetp)
548 double length = (end_angle - start_angle)*rad;
549 double pos = 0.0;
550 for (;;) {
551 if (*offsetp == 0.0) {
552 double ang = start_angle + pos/rad;
553 dot(cent + position(cos(ang), sin(ang))*rad, lt);
555 double rem = gap_width - *offsetp;
556 if (pos + rem > length) {
557 *offsetp += length - pos;
558 break;
560 else {
561 pos += rem;
562 *offsetp = 0.0;
567 // Used by dotted_rounded_box.
569 void common_output::dot_line(const position &start, const position &end,
570 const line_type &lt, double gap_width,
571 double *offsetp)
573 distance dist = end - start;
574 double length = hypot(dist);
575 if (length == 0.0)
576 return;
577 double pos = 0.0;
578 for (;;) {
579 if (*offsetp == 0.0)
580 dot(start + dist*(pos/length), lt);
581 double rem = gap_width - *offsetp;
582 if (pos + rem > length) {
583 *offsetp += length - pos;
584 break;
586 else {
587 pos += rem;
588 *offsetp = 0.0;
593 void common_output::solid_rounded_box(const position &cent,
594 const distance &dim, double rad,
595 const line_type &lt)
597 position tem = cent - dim/2.0;
598 arc(tem + position(0.0, rad),
599 tem + position(rad, rad),
600 tem + position(rad, 0.0),
601 lt);
602 tem = cent + position(-dim.x/2.0, dim.y/2.0);
603 arc(tem + position(rad, 0.0),
604 tem + position(rad, -rad),
605 tem + position(0.0, -rad),
606 lt);
607 tem = cent + dim/2.0;
608 arc(tem + position(0.0, -rad),
609 tem + position(-rad, -rad),
610 tem + position(-rad, 0.0),
611 lt);
612 tem = cent + position(dim.x/2.0, -dim.y/2.0);
613 arc(tem + position(-rad, 0.0),
614 tem + position(-rad, rad),
615 tem + position(0.0, rad),
616 lt);
617 position end;
618 end = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
619 line(cent - dim/2.0 + position(0.0, rad), &end, 1, lt);
620 end = cent + position(dim.x/2.0 - rad, dim.y/2.0);
621 line(cent + position(-dim.x/2.0 + rad, dim.y/2.0), &end, 1, lt);
622 end = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
623 line(cent + position(dim.x/2.0, dim.y/2.0 - rad), &end, 1, lt);
624 end = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
625 line(cent + position(dim.x/2.0 - rad, -dim.y/2.0), &end, 1, lt);
628 void common_output::filled_rounded_box(const position &cent,
629 const distance &dim, double rad,
630 double fill)
632 line_type ilt;
633 ilt.type = line_type::invisible;
634 circle(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, ilt, fill);
635 circle(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, ilt, fill);
636 circle(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, ilt, fill);
637 circle(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, ilt, fill);
638 position vec[4];
639 vec[0] = cent + position(dim.x/2.0, dim.y/2.0 - rad);
640 vec[1] = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
641 vec[2] = cent + position(-dim.x/2.0, -dim.y/2.0 + rad);
642 vec[3] = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
643 polygon(vec, 4, ilt, fill);
644 vec[0] = cent + position(dim.x/2.0 - rad, dim.y/2.0);
645 vec[1] = cent + position(-dim.x/2.0 + rad, dim.y/2.0);
646 vec[2] = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
647 vec[3] = cent + position(dim.x/2.0 - rad, -dim.y/2.0);
648 polygon(vec, 4, ilt, fill);