common.cpp revision 114402
133965Sjdp// -*- C++ -*-
233965Sjdp/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
333965Sjdp     Written by James Clark (jjc@jclark.com)
4130561Sobrien
5130561SobrienThis file is part of groff.
6130561Sobrien
7130561Sobriengroff is free software; you can redistribute it and/or modify it under
8130561Sobrienthe terms of the GNU General Public License as published by the Free
9130561SobrienSoftware Foundation; either version 2, or (at your option) any later
10130561Sobrienversion.
11130561Sobrien
12130561Sobriengroff is distributed in the hope that it will be useful, but WITHOUT ANY
13130561SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
14130561SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15130561Sobrienfor more details.
16130561Sobrien
17130561SobrienYou should have received a copy of the GNU General Public License along
1833965Sjdpwith groff; see the file COPYING.  If not, write to the Free Software
1933965SjdpFoundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20130561Sobrien
21130561Sobrien#include "pic.h"
22130561Sobrien#include "common.h"
23130561Sobrien
24130561Sobrien// output a dashed circle as a series of arcs
25130561Sobrien
26130561Sobrienvoid common_output::dashed_circle(const position &cent, double rad,
27130561Sobrien				  const line_type &lt)
28130561Sobrien{
29130561Sobrien  assert(lt.type == line_type::dashed);
30130561Sobrien  line_type slt = lt;
31130561Sobrien  slt.type = line_type::solid;
32130561Sobrien  double dash_angle = lt.dash_width/rad;
33130561Sobrien  int ndashes;
34130561Sobrien  double gap_angle;
35130561Sobrien  if (dash_angle >= M_PI/4.0) {
36130561Sobrien    if (dash_angle < M_PI/2.0) {
37130561Sobrien      gap_angle = M_PI/2.0 - dash_angle;
38130561Sobrien      ndashes = 4;
39130561Sobrien    }
40130561Sobrien    else if (dash_angle < M_PI) {
41130561Sobrien      gap_angle = M_PI - dash_angle;
42130561Sobrien      ndashes = 2;
43130561Sobrien    }
44130561Sobrien    else {
45130561Sobrien      circle(cent, rad, slt, -1.0);
46130561Sobrien      return;
47130561Sobrien    }
48130561Sobrien  }
49130561Sobrien  else {
50130561Sobrien    ndashes = 4*int(ceil(M_PI/(4.0*dash_angle)));
51130561Sobrien    gap_angle = (M_PI*2.0)/ndashes - dash_angle;
52130561Sobrien  }
53130561Sobrien  for (int i = 0; i < ndashes; i++) {
54130561Sobrien    double start_angle = i*(dash_angle+gap_angle) - dash_angle/2.0;
55130561Sobrien    solid_arc(cent, rad, start_angle, start_angle + dash_angle, lt);
56130561Sobrien  }
57130561Sobrien}
5833965Sjdp
59130561Sobrien// output a dotted circle as a series of dots
6033965Sjdp
6133965Sjdpvoid common_output::dotted_circle(const position &cent, double rad,
6277298Sobrien				  const line_type &lt)
6377298Sobrien{
6477298Sobrien  assert(lt.type == line_type::dotted);
6577298Sobrien  double gap_angle = lt.dash_width/rad;
6677298Sobrien  int ndots;
6777298Sobrien  if (gap_angle >= M_PI/2.0) {
68130561Sobrien    // always have at least 2 dots
6977298Sobrien    gap_angle = M_PI;
70130561Sobrien    ndots = 2;
71130561Sobrien  }
72130561Sobrien  else {
73130561Sobrien    ndots = 4*int(M_PI/(2.0*gap_angle));
74130561Sobrien    gap_angle = (M_PI*2.0)/ndots;
75130561Sobrien  }
7677298Sobrien  double ang = 0.0;
7777298Sobrien  for (int i = 0; i < ndots; i++, ang += gap_angle)
78130561Sobrien    dot(cent + position(cos(ang), sin(ang))*rad, lt);
7977298Sobrien}
8033965Sjdp
81130561Sobrien// return non-zero iff we can compute a center
82130561Sobrien
83130561Sobrienint compute_arc_center(const position &start, const position &cent,
84130561Sobrien		       const position &end, position *result)
85130561Sobrien{
8633965Sjdp  // This finds the point along the vector from start to cent that
87130561Sobrien  // is equidistant between start and end.
8833965Sjdp  distance c = cent - start;
8933965Sjdp  distance e = end - start;
9033965Sjdp  double n = c*e;
9133965Sjdp  if (n == 0.0)
9233965Sjdp    return 0;
9333965Sjdp  *result = start + c*((e*e)/(2.0*n));
9433965Sjdp  return 1;
95130561Sobrien}
96130561Sobrien
97130561Sobrien// output a dashed arc as a series of arcs
98130561Sobrien
99130561Sobrienvoid common_output::dashed_arc(const position &start, const position &cent,
100130561Sobrien			       const position &end, const line_type &lt)
101130561Sobrien{
102130561Sobrien  assert(lt.type == line_type::dashed);
103130561Sobrien  position c;
104130561Sobrien  if (!compute_arc_center(start, cent, end, &c)) {
105130561Sobrien    line(start, &end, 1, lt);
106130561Sobrien    return;
107130561Sobrien  }
108130561Sobrien  distance start_offset = start - c;
109130561Sobrien  distance end_offset = end - c;
110130561Sobrien  double start_angle = atan2(start_offset.y, start_offset.x);
111130561Sobrien  double end_angle = atan2(end_offset.y, end_offset.x);
112130561Sobrien  double rad = hypot(c - start);
113130561Sobrien  double dash_angle = lt.dash_width/rad;
114130561Sobrien  double total_angle = end_angle - start_angle;
115130561Sobrien  while (total_angle < 0)
116130561Sobrien    total_angle += M_PI + M_PI;
11733965Sjdp  if (total_angle <= dash_angle*2.0) {
11833965Sjdp    solid_arc(cent, rad, start_angle, end_angle, lt);
11933965Sjdp    return;
12033965Sjdp  }
12133965Sjdp  int ndashes = int((total_angle - dash_angle)/(dash_angle*2.0) + .5);
12233965Sjdp  double dash_and_gap_angle = (total_angle - dash_angle)/ndashes;
123130561Sobrien  for (int i = 0; i <= ndashes; i++)
124130561Sobrien    solid_arc(cent, rad, start_angle + i*dash_and_gap_angle,
125130561Sobrien	      start_angle + i*dash_and_gap_angle + dash_angle, lt);
126130561Sobrien}
127130561Sobrien
12833965Sjdp// output a dotted arc as a series of dots
129130561Sobrien
130130561Sobrienvoid common_output::dotted_arc(const position &start, const position &cent,
131130561Sobrien			       const position &end, const line_type &lt)
132130561Sobrien{
133130561Sobrien  assert(lt.type == line_type::dotted);
134130561Sobrien  position c;
135130561Sobrien  if (!compute_arc_center(start, cent, end, &c)) {
136130561Sobrien    line(start, &end, 1, lt);
13760484Sobrien    return;
138130561Sobrien  }
139130561Sobrien  distance start_offset = start - c;
140130561Sobrien  distance end_offset = end - c;
141130561Sobrien  double start_angle = atan2(start_offset.y, start_offset.x);
14233965Sjdp  double total_angle = atan2(end_offset.y, end_offset.x) - start_angle;
143130561Sobrien  while (total_angle < 0)
144130561Sobrien    total_angle += M_PI + M_PI;
145130561Sobrien  double rad = hypot(c - start);
146130561Sobrien  int ndots = int(total_angle/(lt.dash_width/rad) + .5);
147130561Sobrien  if (ndots == 0)
148130561Sobrien    dot(start, lt);
149130561Sobrien  else {
150130561Sobrien    for (int i = 0; i <= ndots; i++) {
151130561Sobrien      double a = start_angle + (total_angle*i)/ndots;
152130561Sobrien      dot(cent + position(cos(a), sin(a))*rad, lt);
153130561Sobrien    }
154130561Sobrien  }
155130561Sobrien}
156130561Sobrien
157130561Sobrienvoid common_output::solid_arc(const position &cent, double rad,
158130561Sobrien			      double start_angle, double end_angle,
159130561Sobrien			      const line_type &lt)
160130561Sobrien{
161130561Sobrien  line_type slt = lt;
162130561Sobrien  slt.type = line_type::solid;
163130561Sobrien  arc(cent + position(cos(start_angle), sin(start_angle))*rad,
164130561Sobrien      cent,
165130561Sobrien      cent + position(cos(end_angle), sin(end_angle))*rad,
166130561Sobrien      slt);
167130561Sobrien}
168130561Sobrien
169130561Sobrien
170130561Sobrienvoid common_output::rounded_box(const position &cent, const distance &dim,
171130561Sobrien				double rad, const line_type &lt, double fill)
172130561Sobrien{
173130561Sobrien  if (fill >= 0.0)
174130561Sobrien    filled_rounded_box(cent, dim, rad, fill);
175130561Sobrien  switch (lt.type) {
176130561Sobrien  case line_type::invisible:
177130561Sobrien    break;
178130561Sobrien  case line_type::dashed:
17933965Sjdp    dashed_rounded_box(cent, dim, rad, lt);
18033965Sjdp    break;
181130561Sobrien  case line_type::dotted:
182130561Sobrien    dotted_rounded_box(cent, dim, rad, lt);
183130561Sobrien    break;
184130561Sobrien  case line_type::solid:
185130561Sobrien    solid_rounded_box(cent, dim, rad, lt);
186130561Sobrien    break;
187130561Sobrien  default:
188130561Sobrien    assert(0);
189130561Sobrien  }
19033965Sjdp}
191104834Sobrien
19233965Sjdp
193130561Sobrienvoid common_output::dashed_rounded_box(const position &cent,
194130561Sobrien				       const distance &dim, double rad,
195130561Sobrien				       const line_type &lt)
196130561Sobrien{
197130561Sobrien  line_type slt = lt;
198130561Sobrien  slt.type = line_type::solid;
199130561Sobrien
200130561Sobrien  double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
201130561Sobrien  int n_hor_dashes = int(hor_length/(lt.dash_width*2.0) + .5);
20233965Sjdp  double hor_gap_width = (n_hor_dashes != 0
20333965Sjdp			  ? hor_length/n_hor_dashes - lt.dash_width
20433965Sjdp			  : 0.0);
20533965Sjdp
20633965Sjdp  double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
20733965Sjdp  int n_vert_dashes = int(vert_length/(lt.dash_width*2.0) + .5);
20833965Sjdp  double vert_gap_width = (n_vert_dashes != 0
20933965Sjdp			   ? vert_length/n_vert_dashes - lt.dash_width
21033965Sjdp			   : 0.0);
21133965Sjdp  // Note that each corner arc has to be split into two for dashing,
21233965Sjdp  // because one part is dashed using vert_gap_width, and the other
21333965Sjdp  // using hor_gap_width.
21433965Sjdp  double offset = lt.dash_width/2.0;
21589857Sobrien  dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
21689857Sobrien	   -M_PI/4.0, 0, slt, lt.dash_width, vert_gap_width, &offset);
21789857Sobrien  dash_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
21889857Sobrien	    cent + position(dim.x/2.0, dim.y/2.0 - rad),
21989857Sobrien	    slt, lt.dash_width, vert_gap_width, &offset);
22089857Sobrien  dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
22189857Sobrien	   0, M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
22233965Sjdp
22389857Sobrien  offset = lt.dash_width/2.0;
22489857Sobrien  dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
22589857Sobrien	   M_PI/4.0, M_PI/2, slt, lt.dash_width, hor_gap_width, &offset);
22689857Sobrien  dash_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
227130561Sobrien	    cent + position(-dim.x/2.0 + rad, dim.y/2.0),
22833965Sjdp	    slt, lt.dash_width, hor_gap_width, &offset);
22933965Sjdp  dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
230130561Sobrien	   M_PI/2, 3*M_PI/4.0, slt, lt.dash_width, hor_gap_width, &offset);
23133965Sjdp
23233965Sjdp  offset = lt.dash_width/2.0;
23333965Sjdp  dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
23433965Sjdp	   3.0*M_PI/4.0, M_PI, slt, lt.dash_width, vert_gap_width, &offset);
23533965Sjdp  dash_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad),
23633965Sjdp	    cent + position(-dim.x/2.0, -dim.y/2.0 + rad),
23733965Sjdp	    slt, lt.dash_width, vert_gap_width, &offset);
23833965Sjdp  dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
23933965Sjdp	   M_PI, 5.0*M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset);
24033965Sjdp
24189857Sobrien  offset = lt.dash_width/2.0;
242130561Sobrien  dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
24389857Sobrien	   5*M_PI/4.0, 3*M_PI/2.0, slt, lt.dash_width, hor_gap_width, &offset);
24489857Sobrien  dash_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0),
24533965Sjdp	    cent + position(dim.x/2.0 - rad, -dim.y/2.0),
24633965Sjdp	    slt, lt.dash_width, hor_gap_width, &offset);
24733965Sjdp  dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
24833965Sjdp	   3*M_PI/2, 7*M_PI/4, slt, lt.dash_width, hor_gap_width, &offset);
24989857Sobrien}
250130561Sobrien
25189857Sobrien// Used by dashed_rounded_box.
25289857Sobrien
25333965Sjdpvoid common_output::dash_arc(const position &cent, double rad,
25433965Sjdp			     double start_angle, double end_angle,
25533965Sjdp			     const line_type &lt,
25633965Sjdp			     double dash_width, double gap_width,
25789857Sobrien			     double *offsetp)
258130561Sobrien{
25989857Sobrien  double length = (end_angle - start_angle)*rad;
26089857Sobrien  double pos = 0.0;
26133965Sjdp  for (;;) {
26233965Sjdp    if (*offsetp >= dash_width) {
26333965Sjdp      double rem = dash_width + gap_width - *offsetp;
26433965Sjdp      if (pos + rem > length) {
26589857Sobrien	*offsetp += length - pos;
266130561Sobrien	break;
26789857Sobrien      }
26889857Sobrien      else {
26933965Sjdp	pos += rem;
27033965Sjdp	*offsetp = 0.0;
27133965Sjdp      }
27289857Sobrien    }
273130561Sobrien    else {
27489857Sobrien      double rem = dash_width  - *offsetp;
27589857Sobrien      if (pos + rem > length) {
27633965Sjdp	solid_arc(cent, rad, start_angle + pos/rad, end_angle, lt);
27789857Sobrien	*offsetp += length - pos;
27889857Sobrien	break;
27989857Sobrien      }
28089857Sobrien      else {
28189857Sobrien	solid_arc(cent, rad, start_angle + pos/rad,
282130561Sobrien		  start_angle + (pos + rem)/rad, lt);
28389857Sobrien	pos += rem;
28489857Sobrien	*offsetp = dash_width;
28589857Sobrien      }
28689857Sobrien    }
28789857Sobrien  }
28889857Sobrien}
28933965Sjdp
29033965Sjdp// Used by dashed_rounded_box.
29133965Sjdp
29233965Sjdpvoid common_output::dash_line(const position &start, const position &end,
29333965Sjdp			      const line_type &lt,
29489857Sobrien			      double dash_width, double gap_width,
29589857Sobrien			      double *offsetp)
296130561Sobrien{
29789857Sobrien  distance dist = end - start;
29889857Sobrien  double length = hypot(dist);
29989857Sobrien  if (length == 0.0)
30089857Sobrien    return;
30189857Sobrien  double pos = 0.0;
30289857Sobrien  for (;;) {
30389857Sobrien    if (*offsetp >= dash_width) {
304130561Sobrien      double rem = dash_width + gap_width - *offsetp;
30589857Sobrien      if (pos + rem > length) {
30689857Sobrien	*offsetp += length - pos;
30789857Sobrien	break;
30889857Sobrien      }
30989857Sobrien      else {
310130561Sobrien	pos += rem;
31133965Sjdp	*offsetp = 0.0;
31233965Sjdp      }
313130561Sobrien    }
314130561Sobrien    else {
315130561Sobrien      double rem = dash_width  - *offsetp;
316130561Sobrien      if (pos + rem > length) {
317130561Sobrien	line(start + dist*(pos/length), &end, 1, lt);
318130561Sobrien	*offsetp += length - pos;
319130561Sobrien	break;
320130561Sobrien      }
321130561Sobrien      else {
322130561Sobrien	position p(start + dist*((pos + rem)/length));
323130561Sobrien	line(start + dist*(pos/length), &p, 1, lt);
324130561Sobrien	pos += rem;
325130561Sobrien	*offsetp = dash_width;
326130561Sobrien      }
327130561Sobrien    }
328130561Sobrien  }
329130561Sobrien}
330130561Sobrien
331130561Sobrienvoid common_output::dotted_rounded_box(const position &cent,
332130561Sobrien				       const distance &dim, double rad,
333130561Sobrien				       const line_type &lt)
334130561Sobrien{
335130561Sobrien  line_type slt = lt;
336130561Sobrien  slt.type = line_type::solid;
337104834Sobrien
338104834Sobrien  double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad;
339104834Sobrien  int n_hor_dots = int(hor_length/lt.dash_width + .5);
34033965Sjdp  double hor_gap_width = (n_hor_dots != 0
34133965Sjdp			  ? hor_length/n_hor_dots
34233965Sjdp			  : lt.dash_width);
343
344  double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad;
345  int n_vert_dots = int(vert_length/lt.dash_width + .5);
346  double vert_gap_width = (n_vert_dots != 0
347			   ? vert_length/n_vert_dots
348			   : lt.dash_width);
349  double epsilon = lt.dash_width/(rad*100.0);
350
351  double offset = 0.0;
352  dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
353	   -M_PI/4.0, 0, slt, vert_gap_width, &offset);
354  dot_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad),
355	    cent + position(dim.x/2.0, dim.y/2.0 - rad),
356	    slt, vert_gap_width, &offset);
357  dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
358	   0, M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
359
360  offset = 0.0;
361  dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad,
362	   M_PI/4.0, M_PI/2, slt, hor_gap_width, &offset);
363  dot_line(cent + position(dim.x/2.0 - rad, dim.y/2.0),
364	    cent + position(-dim.x/2.0 + rad, dim.y/2.0),
365	    slt, hor_gap_width, &offset);
366  dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
367	   M_PI/2, 3*M_PI/4.0 - epsilon, slt, hor_gap_width, &offset);
368
369  offset = 0.0;
370  dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad,
371	   3.0*M_PI/4.0, M_PI, slt, vert_gap_width, &offset);
372  dot_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, vert_gap_width, &offset);
375  dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
376	   M_PI, 5.0*M_PI/4.0 - epsilon, slt, vert_gap_width, &offset);
377
378  offset = 0.0;
379  dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad,
380	   5*M_PI/4.0, 3*M_PI/2.0, slt, hor_gap_width, &offset);
381  dot_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, hor_gap_width, &offset);
384  dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad,
385	   3*M_PI/2, 7*M_PI/4 - epsilon, slt, hor_gap_width, &offset);
386}
387
388// Used by dotted_rounded_box.
389
390void common_output::dot_arc(const position &cent, double rad,
391			    double start_angle, double end_angle,
392			    const line_type &lt, double gap_width,
393			    double *offsetp)
394{
395  double length = (end_angle - start_angle)*rad;
396  double pos = 0.0;
397  for (;;) {
398    if (*offsetp == 0.0) {
399      double ang = start_angle + pos/rad;
400      dot(cent + position(cos(ang), sin(ang))*rad, lt);
401    }
402    double rem = gap_width - *offsetp;
403    if (pos + rem > length) {
404      *offsetp += length - pos;
405      break;
406    }
407    else {
408      pos += rem;
409      *offsetp = 0.0;
410    }
411  }
412}
413
414// Used by dotted_rounded_box.
415
416void common_output::dot_line(const position &start, const position &end,
417			     const line_type &lt, double gap_width,
418			     double *offsetp)
419{
420  distance dist = end - start;
421  double length = hypot(dist);
422  if (length == 0.0)
423    return;
424  double pos = 0.0;
425  for (;;) {
426    if (*offsetp == 0.0)
427      dot(start + dist*(pos/length), lt);
428    double rem = gap_width - *offsetp;
429    if (pos + rem > length) {
430      *offsetp += length - pos;
431      break;
432    }
433    else {
434      pos += rem;
435      *offsetp = 0.0;
436    }
437  }
438}
439
440void common_output::solid_rounded_box(const position &cent,
441				      const distance &dim, double rad,
442				      const line_type &lt)
443{
444  position tem = cent - dim/2.0;
445  arc(tem + position(0.0, rad),
446      tem + position(rad, rad),
447      tem + position(rad, 0.0),
448      lt);
449  tem = cent + position(-dim.x/2.0, dim.y/2.0);
450  arc(tem + position(rad, 0.0),
451      tem + position(rad, -rad),
452      tem + position(0.0, -rad),
453      lt);
454  tem = cent + dim/2.0;
455  arc(tem + position(0.0, -rad),
456      tem + position(-rad, -rad),
457      tem + position(-rad, 0.0),
458      lt);
459  tem = cent + position(dim.x/2.0, -dim.y/2.0);
460  arc(tem + position(-rad, 0.0),
461      tem + position(-rad, rad),
462      tem + position(0.0, rad),
463      lt);
464  position end;
465  end = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
466  line(cent - dim/2.0 + position(0.0, rad), &end, 1, lt);
467  end = cent + position(dim.x/2.0 - rad, dim.y/2.0);
468  line(cent + position(-dim.x/2.0 + rad, dim.y/2.0), &end, 1, lt);
469  end = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
470  line(cent + position(dim.x/2.0, dim.y/2.0 - rad), &end, 1, lt);
471  end = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
472  line(cent + position(dim.x/2.0 - rad, -dim.y/2.0), &end, 1, lt);
473}
474
475void common_output::filled_rounded_box(const position &cent,
476				       const distance &dim, double rad,
477				       double fill)
478{
479  line_type ilt;
480  ilt.type = line_type::invisible;
481  circle(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, ilt, fill);
482  circle(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, ilt, fill);
483  circle(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, ilt, fill);
484  circle(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, ilt, fill);
485  position vec[4];
486  vec[0] = cent + position(dim.x/2.0, dim.y/2.0 - rad);
487  vec[1] = cent + position(-dim.x/2.0, dim.y/2.0 - rad);
488  vec[2] = cent + position(-dim.x/2.0, -dim.y/2.0 + rad);
489  vec[3] = cent + position(dim.x/2.0, -dim.y/2.0 + rad);
490  polygon(vec, 4, ilt, fill);
491  vec[0] = cent + position(dim.x/2.0 - rad, dim.y/2.0);
492  vec[1] = cent + position(-dim.x/2.0 + rad, dim.y/2.0);
493  vec[2] = cent + position(-dim.x/2.0 + rad, -dim.y/2.0);
494  vec[3] = cent + position(dim.x/2.0 - rad, -dim.y/2.0);
495  polygon(vec, 4, ilt, fill);
496}
497