File: x_ellipse.c

package info (click to toggle)
plotutils 2.0-2
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 5,964 kB
  • ctags: 2,522
  • sloc: ansic: 38,416; sh: 1,853; yacc: 856; makefile: 181; lex: 144
file content (123 lines) | stat: -rw-r--r-- 4,117 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* This file contains the ellipse method, which is a GNU extension to
   libplot.  It draws an object: an ellipse with center xc,yc and semi-axes
   of length rx and ry (the former at a specified angle with the
   x-axis). */

#include "sys-defines.h"
#include "plot.h"
#include "extern.h"

/* In this version, we first check to see if the angle of inclination is
   zero, and the map from the user frame to the device frame preserves
   axes.  If these are both true, we can use native X rendering to draw the
   ellipse.  If they are not, we draw an inscribed polyline, by invoking
   the generic method. */

int
#ifdef _HAVE_PROTOS
_x_fellipse (double xc, double yc, double rx, double ry, double angle)
#else
_x_fellipse (xc, yc, rx, ry, angle)
     double xc, yc, rx, ry, angle;
#endif
{
  int ninetymult = IROUND(angle / 90.0);

  if (!_plotter->open)
    {
      _plotter->error ("fellipse: invalid operation");
      return -1;
    }

 /* if angle is multiple of 90 degrees, modify to permit use of native X
    arc rendering */
  if (angle == (double) (90 * ninetymult))
    {
      angle = 0.0;
      if (ninetymult % 2)
	{
	  double temp;
	  
	  temp = rx;
	  rx = ry;
	  ry = temp;
	}
    }

  /* if ellipse must be drawn at an angle, or affine map from user frame to
     device frame does not preserve coordinate axes, call the generic class
     method to draw an inscribed polyline */
  if (angle != 0.0 || !(_plotter->drawstate->transform.axes_preserved))
    return _g_fellipse (xc, yc, rx, ry, angle);

  /* otherwise use X11's native ellipse-drawing facility, as follows */

  _plotter->endpath (); /* flush polyline if any */

  rx = (rx < 0.0 ? -rx : rx);	/* avoid obscure X problems */
  ry = (ry < 0.0 ? -ry : ry);  

  {				/* use native X ellipse rendering  */
    int x_orientation, y_orientation;
    int xorigin, yorigin;
    unsigned int squaresize_x, squaresize_y;
    
    /* axes flipped? (by default y-axis is, due to  X's flipped-y convention) */
    x_orientation = (_plotter->drawstate->transform.m[0] >= 0 ? 1 : -1);
    y_orientation = (_plotter->drawstate->transform.m[3] >= 0 ? 1 : -1);

  /* location of `origin' (upper left corner of bounding rect. on display)
     and width and height; X's flipped-y convention affects these values */
    xorigin = IROUND(XD(xc - x_orientation * rx, 
			yc - y_orientation * ry));
    yorigin = IROUND(YD(xc - x_orientation * rx, 
			yc - y_orientation * ry));
    squaresize_x = (unsigned int)IROUND(XDV(2 * x_orientation * rx, 0.0));
    squaresize_y = (unsigned int)IROUND(YDV(0.0, 2 * y_orientation * ry));  
    
    /* sanity check */
    if (XOOB_INT(xorigin) || XOOB_INT(yorigin) || XOOB_UNSIGNED(squaresize_x)
	|| XOOB_UNSIGNED(squaresize_y)) return -1;

    /* don't use zero dimensions if user specified nonzero */
    if (squaresize_x == 0 && rx > 0.0)
      squaresize_x = 1;
    if (squaresize_y == 0 && ry > 0.0)
      squaresize_y = 1;
    
    /* place current line attributes in the X GC */
    _plotter->set_attributes();  

    if (_plotter->drawstate->fill_level) /* not transparent */
      {
	/* select fill color as X foreground color */
	_plotter->set_fill_color();

	if (_plotter->drawable1)
	  XFillArc(_plotter->dpy, _plotter->drawable1, 
		   _plotter->drawstate->gc, 
		   xorigin, yorigin, squaresize_x, squaresize_y, 0, 64 * 360);
	if (_plotter->drawable2)
	  XFillArc(_plotter->dpy, _plotter->drawable2, 
		   _plotter->drawstate->gc, 
		   xorigin, yorigin, squaresize_x, squaresize_y, 0, 64 * 360);
      }
    
    /* select pen color as X foreground color */
    _plotter->set_pen_color();

    if (_plotter->drawable1)
      XDrawArc(_plotter->dpy, _plotter->drawable1, _plotter->drawstate->gc, 
	       xorigin, yorigin, squaresize_x, squaresize_y, 0, 64 * 360);
    if (_plotter->drawable2)
      XDrawArc(_plotter->dpy, _plotter->drawable2, _plotter->drawstate->gc, 
	       xorigin, yorigin, squaresize_x, squaresize_y, 0, 64 * 360);
  }
  
  _plotter->drawstate->pos.x = xc; /* move to center (a libplot convention) */
  _plotter->drawstate->pos.y = yc;
  
  _handle_x_events();
  
  return 0;
}