Sync-to-go: update copyright for 2015
[s-roff.git] / src / pre-pic / common.cpp
blobecd3078cd91044c833ab5bbc83d38e61077bba6f
1 /*@
2 * Copyright (c) 2014 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
4 * Copyright (C) 1989 - 1992, 2003, 2007
5 * Free Software Foundation, Inc.
6 * Written by James Clark (jjc@jclark.com)
8 * This is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2, or (at your option) any later
11 * version.
13 * This is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with groff; see the file COPYING. If not, write to the Free Software
20 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "config.h"
24 #include "pic-config.h"
26 #include "common.h"
27 #include "pic.h"
29 // output a dashed circle as a series of arcs
31 void common_output::dashed_circle(const position &cent, double rad,
32 const line_type &lt)
34 assert(lt.type == line_type::dashed);
35 line_type slt = lt;
36 slt.type = line_type::solid;
37 double dash_angle = lt.dash_width/rad;
38 int ndashes;
39 double gap_angle;
40 if (dash_angle >= M_PI/4.0) {
41 if (dash_angle < M_PI/2.0) {
42 gap_angle = M_PI/2.0 - dash_angle;
43 ndashes = 4;
45 else if (dash_angle < M_PI) {
46 gap_angle = M_PI - dash_angle;
47 ndashes = 2;
49 else {
50 circle(cent, rad, slt, -1.0);
51 return;
54 else {
55 ndashes = 4*int(ceil(M_PI/(4.0*dash_angle)));
56 gap_angle = (M_PI*2.0)/ndashes - dash_angle;
58 for (int i = 0; i < ndashes; i++) {
59 double start_angle = i*(dash_angle+gap_angle) - dash_angle/2.0;
60 solid_arc(cent, rad, start_angle, start_angle + dash_angle, lt);
64 // output a dotted circle as a series of dots
66 void common_output::dotted_circle(const position &cent, double rad,
67 const line_type &lt)
69 assert(lt.type == line_type::dotted);
70 double gap_angle = lt.dash_width/rad;
71 int ndots;
72 if (gap_angle >= M_PI/2.0) {
73 // always have at least 2 dots
74 gap_angle = M_PI;
75 ndots = 2;
77 else {
78 ndots = 4*int(M_PI/(2.0*gap_angle));
79 gap_angle = (M_PI*2.0)/ndots;
81 double ang = 0.0;
82 for (int i = 0; i < ndots; i++, ang += gap_angle)
83 dot(cent + position(cos(ang), sin(ang))*rad, lt);
86 // recursive function for dash drawing, used by dashed_ellipse
88 void common_output::ellipse_arc(const position &cent,
89 const position &z0, const position &z1,
90 const distance &dim, const line_type &lt)
92 assert(lt.type == line_type::solid);
93 assert(dim.x != 0 && dim.y != 0);
94 double eps = 0.0001;
95 position zml = (z0 + z1) / 2;
96 // apply affine transformation (from ellipse to circle) to compute angle
97 // of new position, then invert transformation to get exact position
98 double psi = atan2(zml.y / dim.y, zml.x / dim.x);
99 position zm = position(dim.x * cos(psi), dim.y * sin(psi));
100 // to approximate the ellipse arc with one or more circle arcs, we
101 // first compute the radius of curvature in zm
102 double a_2 = dim.x * dim.x;
103 double a_4 = a_2 * a_2;
104 double b_2 = dim.y * dim.y;
105 double b_4 = b_2 * b_2;
106 double e_2 = a_2 - b_2;
107 double temp = a_4 * zm.y * zm.y + b_4 * zm.x * zm.x;
108 double rho = sqrt(temp / a_4 / b_4 * temp / a_4 / b_4 * temp);
109 // compute center of curvature circle
110 position M = position(e_2 * zm.x / a_2 * zm.x / a_2 * zm.x,
111 -e_2 * zm.y / b_2 * zm.y / b_2 * zm.y);
112 // compute distance between circle and ellipse arc at start and end
113 double phi0 = atan2(z0.y - M.y, z0.x - M.x);
114 double phi1 = atan2(z1.y - M.y, z1.x - M.x);
115 position M0 = position(rho * cos(phi0), rho * sin(phi0)) + M;
116 position M1 = position(rho * cos(phi1), rho * sin(phi1)) + M;
117 double dist0 = hypot(z0 - M0) / sqrt(z0 * z0);
118 double dist1 = hypot(z1 - M1) / sqrt(z1 * z1);
119 if (dist0 < eps && dist1 < eps)
120 solid_arc(M + cent, rho, phi0, phi1, lt);
121 else {
122 ellipse_arc(cent, z0, zm, dim, lt);
123 ellipse_arc(cent, zm, z1, dim, lt);
127 // output a dashed ellipse as a series of arcs
129 void common_output::dashed_ellipse(const position &cent, const distance &dim,
130 const line_type &lt)
132 assert(lt.type == line_type::dashed);
133 double dim_x = dim.x / 2;
134 double dim_y = dim.y / 2;
135 line_type slt = lt;
136 slt.type = line_type::solid;
137 double dw = lt.dash_width;
138 // we use an approximation to compute the ellipse length (found in:
139 // Bronstein, Semendjajew, Taschenbuch der Mathematik)
140 double lambda = (dim.x - dim.y) / (dim.x + dim.y);
141 double le = M_PI / 2 * (dim.x + dim.y)
142 * ((64 - 3 * lambda * lambda * lambda * lambda )
143 / (64 - 16 * lambda * lambda));
144 // for symmetry we make nmax a multiple of 8
145 int nmax = 8 * int(le / dw / 8 + 0.5);
146 if (nmax < 8) {
147 nmax = 8;
148 dw = le / 8;
150 int ndash = nmax / 2;
151 double gapwidth = (le - dw * ndash) / ndash;
152 double l = 0;
153 position z = position(dim_x, 0);
154 position zdot = z;
155 int j = 0;
156 int jmax = int(10 / lt.dash_width);
157 for (int i = 0; i <= nmax; i++) {
158 position zold = z;
159 position zpre = zdot;
160 double ld = (int(i / 2) + 0.5) * dw + int((i + 1) / 2) * gapwidth;
161 double lold = 0;
162 double dl = 1;
163 // find next position for fixed arc length
164 while (l < ld) {
165 j++;
166 lold = l;
167 zold = z;
168 double phi = j * 2 * M_PI / jmax;
169 z = position(dim_x * cos(phi), dim_y * sin(phi));
170 dl = hypot(z - zold);
171 l += dl;
173 // interpolate linearly between the last two points,
174 // using the length difference as the scaling factor
175 double delta = (ld - lold) / dl;
176 zdot = zold + (z - zold) * delta;
177 // compute angle of new position on the affine circle
178 // and use it to get the exact value on the ellipse
179 double psi = atan2(zdot.y / dim_y, zdot.x / dim_x);
180 zdot = position(dim_x * cos(psi), dim_y * sin(psi));
181 if ((i % 2 == 0) && (i > 1))
182 ellipse_arc(cent, zpre, zdot, dim / 2, slt);
186 // output a dotted ellipse as a series of dots
188 void common_output::dotted_ellipse(const position &cent, const distance &dim,
189 const line_type &lt)
191 assert(lt.type == line_type::dotted);
192 double dim_x = dim.x / 2;
193 double dim_y = dim.y / 2;
194 line_type slt = lt;
195 slt.type = line_type::solid;
196 // we use an approximation to compute the ellipse length (found in:
197 // Bronstein, Semendjajew, Taschenbuch der Mathematik)
198 double lambda = (dim.x - dim.y) / (dim.x + dim.y);
199 double le = M_PI / 2 * (dim.x + dim.y)
200 * ((64 - 3 * lambda * lambda * lambda * lambda )
201 / (64 - 16 * lambda * lambda));
202 // for symmetry we make nmax a multiple of 4
203 int ndots = 4 * int(le / lt.dash_width / 4 + 0.5);
204 if (ndots < 4)
205 ndots = 4;
206 double l = 0;
207 position z = position(dim_x, 0);
208 int j = 0;
209 int jmax = int(10 / lt.dash_width);
210 for (int i = 1; i <= ndots; i++) {
211 position zold = z;
212 double lold = l;
213 double ld = i * le / ndots;
214 double dl = 1;
215 // find next position for fixed arc length
216 while (l < ld) {
217 j++;
218 lold = l;
219 zold = z;
220 double phi = j * 2 * M_PI / jmax;
221 z = position(dim_x * cos(phi), dim_y * sin(phi));
222 dl = hypot(z - zold);
223 l += dl;
225 // interpolate linearly between the last two points,
226 // using the length difference as the scaling factor
227 double delta = (ld - lold) / dl;
228 position zdot = zold + (z - zold) * delta;
229 // compute angle of new position on the affine circle
230 // and use it to get the exact value on the ellipse
231 double psi = atan2(zdot.y / dim_y, zdot.x / dim_x);
232 zdot = position(dim_x * cos(psi), dim_y * sin(psi));
233 dot(cent + zdot, slt);
237 // return non-zero iff we can compute a center
239 int compute_arc_center(const position &start, const position &cent,
240 const position &end, position *result)
242 // This finds the point along the vector from start to cent that
243 // is equidistant between start and end.
244 distance c = cent - start;
245 distance e = end - start;
246 double n = c*e;
247 if (n == 0.0)
248 return 0;
249 *result = start + c*((e*e)/(2.0*n));
250 return 1;
253 // output a dashed arc as a series of arcs
255 void common_output::dashed_arc(const position &start, const position &cent,
256 const position &end, const line_type &lt)
258 assert(lt.type == line_type::dashed);
259 position c;
260 if (!compute_arc_center(start, cent, end, &c)) {
261 line(start, &end, 1, lt);
262 return;
264 distance start_offset = start - c;
265 distance end_offset = end - c;
266 double start_angle = atan2(start_offset.y, start_offset.x);
267 double end_angle = atan2(end_offset.y, end_offset.x);
268 double rad = hypot(c - start);
269 double dash_angle = lt.dash_width/rad;
270 double total_angle = end_angle - start_angle;
271 while (total_angle < 0)
272 total_angle += M_PI + M_PI;
273 if (total_angle <= dash_angle*2.0) {
274 solid_arc(cent, rad, start_angle, end_angle, lt);
275 return;
277 int ndashes = int((total_angle - dash_angle)/(dash_angle*2.0) + .5);
278 double dash_and_gap_angle = (total_angle - dash_angle)/ndashes;
279 for (int i = 0; i <= ndashes; i++)
280 solid_arc(cent, rad, start_angle + i*dash_and_gap_angle,
281 start_angle + i*dash_and_gap_angle + dash_angle, lt);
284 // output a dotted arc as a series of dots
286 void common_output::dotted_arc(const position &start, const position &cent,
287 const position &end, const line_type &lt)
289 assert(lt.type == line_type::dotted);
290 position c;
291 if (!compute_arc_center(start, cent, end, &c)) {
292 line(start, &end, 1, lt);
293 return;
295 distance start_offset = start - c;
296 distance end_offset = end - c;
297 double start_angle = atan2(start_offset.y, start_offset.x);
298 double total_angle = atan2(end_offset.y, end_offset.x) - start_angle;
299 while (total_angle < 0)
300 total_angle += M_PI + M_PI;
301 double rad = hypot(c - start);
302 int ndots = int(total_angle/(lt.dash_width/rad) + .5);
303 if (ndots == 0)
304 dot(start, lt);
305 else {
306 for (int i = 0; i <= ndots; i++) {
307 double a = start_angle + (total_angle*i)/ndots;
308 dot(cent + position(cos(a), sin(a))*rad, lt);
313 void common_output::solid_arc(const position &cent, double rad,
314 double start_angle, double end_angle,
315 const line_type &lt)
317 line_type slt = lt;
318 slt.type = line_type::solid;
319 arc(cent + position(cos(start_angle), sin(start_angle))*rad,
320 cent,
321 cent + position(cos(end_angle), sin(end_angle))*rad,
322 slt);
325 void common_output::rounded_box(const position &cent, const distance &dim,
326 double rad, const line_type &lt,
327 double fill, char *color_fill)
329 if (fill >= 0.0 || color_fill)
330 filled_rounded_box(cent, dim, rad, fill);
331 switch (lt.type) {
332 case line_type::invisible:
333 break;
334 case line_type::dashed:
335 dashed_rounded_box(cent, dim, rad, lt);
336 break;
337 case line_type::dotted:
338 dotted_rounded_box(cent, dim, rad, lt);
339 break;
340 case line_type::solid:
341 solid_rounded_box(cent, dim, rad, lt);
342 break;
343 default:
344 assert(0);
348 void common_output::dashed_rounded_box(const position &cent,
349 const distance &dim, double rad,
350 const line_type &lt)
352 line_type slt = lt;
353 slt.type = line_type::solid;
355 double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
356 int n_hor_dashes = int(hor_length/(lt.dash_width*2.0) + .5);
357 double hor_gap_width = (n_hor_dashes != 0
358 ? hor_length/n_hor_dashes - lt.dash_width
359 : 0.0);
361 double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
362 int n_vert_dashes = int(vert_length/(lt.dash_width*2.0) + .5);
363 double vert_gap_width = (n_vert_dashes != 0
364 ? vert_length/n_vert_dashes - lt.dash_width
365 : 0.0);
366 // Note that each corner arc has to be split into two for dashing,
367 // because one part is dashed using vert_gap_width, and the other
368 // using hor_gap_width.
369 double offset = lt.dash_width/2.0;
370 dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
371 -M_PI/4.0, 0, slt, lt.dash_width, vert_gap_width, &offset);
372 dash_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
373 cent + position(dim.x/2.0, dim.y/2.0 - rad),
374 slt, lt.dash_width, vert_gap_width, &offset);
375 dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
376 0, M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
378 offset = lt.dash_width/2.0;
379 dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
380 M_PI/4.0, M_PI/2, slt, lt.dash_width, hor_gap_width, &offset);
381 dash_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
382 cent + position(-dim.x/2.0 + rad, dim.y/2.0),
383 slt, lt.dash_width, hor_gap_width, &offset);
384 dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
385 M_PI/2, 3*M_PI/4.0, slt, lt.dash_width, hor_gap_width, &offset);
387 offset = lt.dash_width/2.0;
388 dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
389 3.0*M_PI/4.0, M_PI, slt, lt.dash_width, vert_gap_width, &offset);
390 dash_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad),
391 cent + position(-dim.x/2.0, -dim.y/2.0 + rad),
392 slt, lt.dash_width, vert_gap_width, &offset);
393 dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
394 M_PI, 5.0*M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
396 offset = lt.dash_width/2.0;
397 dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
398 5*M_PI/4.0, 3*M_PI/2.0, slt, lt.dash_width, hor_gap_width, &offset);
399 dash_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0),
400 cent + position(dim.x/2.0 - rad, -dim.y/2.0),
401 slt, lt.dash_width, hor_gap_width, &offset);
402 dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
403 3*M_PI/2, 7*M_PI/4, slt, lt.dash_width, hor_gap_width, &offset);
406 // Used by dashed_rounded_box.
408 void common_output::dash_arc(const position &cent, double rad,
409 double start_angle, double end_angle,
410 const line_type &lt,
411 double dash_width, double gap_width,
412 double *offsetp)
414 double length = (end_angle - start_angle)*rad;
415 double pos = 0.0;
416 for (;;) {
417 if (*offsetp >= dash_width) {
418 double rem = dash_width + gap_width - *offsetp;
419 if (pos + rem > length) {
420 *offsetp += length - pos;
421 break;
423 else {
424 pos += rem;
425 *offsetp = 0.0;
428 else {
429 double rem = dash_width - *offsetp;
430 if (pos + rem > length) {
431 solid_arc(cent, rad, start_angle + pos/rad, end_angle, lt);
432 *offsetp += length - pos;
433 break;
435 else {
436 solid_arc(cent, rad, start_angle + pos/rad,
437 start_angle + (pos + rem)/rad, lt);
438 pos += rem;
439 *offsetp = dash_width;
445 // Used by dashed_rounded_box.
447 void common_output::dash_line(const position &start, const position &end,
448 const line_type &lt,
449 double dash_width, double gap_width,
450 double *offsetp)
452 distance dist = end - start;
453 double length = hypot(dist);
454 if (length == 0.0)
455 return;
456 double pos = 0.0;
457 for (;;) {
458 if (*offsetp >= dash_width) {
459 double rem = dash_width + gap_width - *offsetp;
460 if (pos + rem > length) {
461 *offsetp += length - pos;
462 break;
464 else {
465 pos += rem;
466 *offsetp = 0.0;
469 else {
470 double rem = dash_width - *offsetp;
471 if (pos + rem > length) {
472 line(start + dist*(pos/length), &end, 1, lt);
473 *offsetp += length - pos;
474 break;
476 else {
477 position p(start + dist*((pos + rem)/length));
478 line(start + dist*(pos/length), &p, 1, lt);
479 pos += rem;
480 *offsetp = dash_width;
486 void common_output::dotted_rounded_box(const position &cent,
487 const distance &dim, double rad,
488 const line_type &lt)
490 line_type slt = lt;
491 slt.type = line_type::solid;
493 double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
494 int n_hor_dots = int(hor_length/lt.dash_width + .5);
495 double hor_gap_width = (n_hor_dots != 0
496 ? hor_length/n_hor_dots
497 : lt.dash_width);
499 double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
500 int n_vert_dots = int(vert_length/lt.dash_width + .5);
501 double vert_gap_width = (n_vert_dots != 0
502 ? vert_length/n_vert_dots
503 : lt.dash_width);
504 double epsilon = lt.dash_width/(rad*100.0);
506 double offset = 0.0;
507 dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
508 -M_PI/4.0, 0, slt, vert_gap_width, &offset);
509 dot_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
510 cent + position(dim.x/2.0, dim.y/2.0 - rad),
511 slt, vert_gap_width, &offset);
512 dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
513 0, M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
515 offset = 0.0;
516 dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
517 M_PI/4.0, M_PI/2, slt, hor_gap_width, &offset);
518 dot_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
519 cent + position(-dim.x/2.0 + rad, dim.y/2.0),
520 slt, hor_gap_width, &offset);
521 dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
522 M_PI/2, 3*M_PI/4.0 - epsilon, slt, hor_gap_width, &offset);
524 offset = 0.0;
525 dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
526 3.0*M_PI/4.0, M_PI, slt, vert_gap_width, &offset);
527 dot_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad),
528 cent + position(-dim.x/2.0, -dim.y/2.0 + rad),
529 slt, vert_gap_width, &offset);
530 dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
531 M_PI, 5.0*M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
533 offset = 0.0;
534 dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
535 5*M_PI/4.0, 3*M_PI/2.0, slt, hor_gap_width, &offset);
536 dot_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0),
537 cent + position(dim.x/2.0 - rad, -dim.y/2.0),
538 slt, hor_gap_width, &offset);
539 dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
540 3*M_PI/2, 7*M_PI/4 - epsilon, slt, hor_gap_width, &offset);
543 // Used by dotted_rounded_box.
545 void common_output::dot_arc(const position &cent, double rad,
546 double start_angle, double end_angle,
547 const line_type &lt, double gap_width,
548 double *offsetp)
550 double length = (end_angle - start_angle)*rad;
551 double pos = 0.0;
552 for (;;) {
553 if (*offsetp == 0.0) {
554 double ang = start_angle + pos/rad;
555 dot(cent + position(cos(ang), sin(ang))*rad, lt);
557 double rem = gap_width - *offsetp;
558 if (pos + rem > length) {
559 *offsetp += length - pos;
560 break;
562 else {
563 pos += rem;
564 *offsetp = 0.0;
569 // Used by dotted_rounded_box.
571 void common_output::dot_line(const position &start, const position &end,
572 const line_type &lt, double gap_width,
573 double *offsetp)
575 distance dist = end - start;
576 double length = hypot(dist);
577 if (length == 0.0)
578 return;
579 double pos = 0.0;
580 for (;;) {
581 if (*offsetp == 0.0)
582 dot(start + dist*(pos/length), lt);
583 double rem = gap_width - *offsetp;
584 if (pos + rem > length) {
585 *offsetp += length - pos;
586 break;
588 else {
589 pos += rem;
590 *offsetp = 0.0;
595 void common_output::solid_rounded_box(const position &cent,
596 const distance &dim, double rad,
597 const line_type &lt)
599 position tem = cent - dim/2.0;
600 arc(tem + position(0.0, rad),
601 tem + position(rad, rad),
602 tem + position(rad, 0.0),
603 lt);
604 tem = cent + position(-dim.x/2.0, dim.y/2.0);
605 arc(tem + position(rad, 0.0),
606 tem + position(rad, -rad),
607 tem + position(0.0, -rad),
608 lt);
609 tem = cent + dim/2.0;
610 arc(tem + position(0.0, -rad),
611 tem + position(-rad, -rad),
612 tem + position(-rad, 0.0),
613 lt);
614 tem = cent + position(dim.x/2.0, -dim.y/2.0);
615 arc(tem + position(-rad, 0.0),
616 tem + position(-rad, rad),
617 tem + position(0.0, rad),
618 lt);
619 position end;
620 end = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
621 line(cent - dim/2.0 + position(0.0, rad), &end, 1, lt);
622 end = cent + position(dim.x/2.0 - rad, dim.y/2.0);
623 line(cent + position(-dim.x/2.0 + rad, dim.y/2.0), &end, 1, lt);
624 end = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
625 line(cent + position(dim.x/2.0, dim.y/2.0 - rad), &end, 1, lt);
626 end = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
627 line(cent + position(dim.x/2.0 - rad, -dim.y/2.0), &end, 1, lt);
630 void common_output::filled_rounded_box(const position &cent,
631 const distance &dim, double rad,
632 double fill)
634 line_type ilt;
635 ilt.type = line_type::invisible;
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 circle(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, ilt, fill);
639 circle(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, ilt, fill);
640 position vec[4];
641 vec[0] = cent + position(dim.x/2.0, dim.y/2.0 - rad);
642 vec[1] = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
643 vec[2] = cent + position(-dim.x/2.0, -dim.y/2.0 + rad);
644 vec[3] = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
645 polygon(vec, 4, ilt, fill);
646 vec[0] = cent + position(dim.x/2.0 - rad, dim.y/2.0);
647 vec[1] = cent + position(-dim.x/2.0 + rad, dim.y/2.0);
648 vec[2] = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
649 vec[3] = cent + position(dim.x/2.0 - rad, -dim.y/2.0);
650 polygon(vec, 4, ilt, fill);
653 // s-it2-mode