/*-----------------------------------------------------------------------*/
/*                                 TIGA                                  */
/*       Copyright (c) 1989-1990 Texas Instruments Incorporated.         */
/*                         All Rights Reserved                           */
/*-----------------------------------------------------------------------*/
/*  TIGA - Graphics Manager Extension                                    */
/*-----------------------------------------------------------------------*/
/*                                                                       */
/* styled_ovalarc and styled_piearc functions                            */
/*                                                                       */
/*   The styled_ovalarc and styled_piearc functions draw an arc taken    */
/*   from an ellipse in standard position--the major and minor axes of   */
/*   the ellipse are parallel to the x and y axes.  The arc drawn by     */
/*   either function is one pixel thick, and is drawn using a line-style */
/*   pattern.  The styled_ovalarc function draws only the arc, while the */
/*   styled_piearc function also draws two styled lines connecting the   */
/*   center of the ellipse to the start and end points of the arc.       */
/*                                                                       */
/*   The ellipse from which the arc is taken is specified in terms of    */
/*   the minimum enclosing rectangle in which it is inscribed.  This     */
/*   rectangle is described by the first four arguments, which give its  */
/*   width w, height h, and the coordinates (xleft,ytop) at its top left */
/*   corner.                                                             */
/*                                                                       */
/*   The arc is described by the next two arguments, theta and arc,      */
/*   which specify its starting angle and the angular extent of the arc. */
/*   Both arguments are given in integer degrees of elliptical arc.      */
/*   Positive angles are in the clockwise direction, while negative      */
/*   angles are counterclockwise.  Starting angle theta is measured from */
/*   the center of the right side of the enclosing rectangle, and is     */
/*   treated as modulus 360.  Arc extent arc specifies the number of     */
/*   degrees (positive or negative) spanned by the arc.  If the arc      */
/*   extent is outside the range [-359,+359], the entire ellipse is      */
/*   drawn, and in the case of the styled_piearc function, no lines are  */
/*   drawn from the center of the ellipse.                               */
/*                                                                       */
/*   The line-style pattern is specified in argument style, a long       */
/*   integer containing a 32-bit repeating line-style pattern.  As the   */
/*   arc is drawn from start to end, pattern bits are used in the order  */
/*   0,1,...,31, where bit 0 is the LSB.  The pattern is repeated modulo */
/*   32, as the arc is drawn.  A bit value of 1 in the pattern specifies */
/*   that color1 is to be used to draw the corresponding pixel.  A bit   */
/*   value of 0 means either that the corresponding pixel is to be drawn */
/*   in color0 (if the LSB of mode = 1) or not drawn (if the LSB of      */
/*   mode = 0).                                                          */
/*                                                                       */
/*   Four drawing modes are supported:                                   */
/*       mode 0 -- Don't draw background pixels (leave gaps), and        */
/*                 load new line-style pattern from style argument.      */
/*       mode 1 -- Draw background pixels in color0, and load new        */
/*                 line-style pattern from style argument.               */
/*       mode 2 -- Don't draw background pixels (leave gaps), and        */
/*                 re-use old line-style pattern (ignore style arg).     */
/*       mode 3 -- Draw background pixels in color0, and re-use old      */
/*                 line-style pattern (ignore style argument).           */
/*   Any mode bits to the left of the 2 LSBs are ignored by the function.*/
/*-----------------------------------------------------------------------*/
/* Usage:  styled_ovalarc(w, h, xleft, ytop, theta, arc, style, mode)    */
/*         styled_piearc(w, h, xleft, ytop, theta, arc, style, mode)     */
/*                                                                       */
/* Description of the arguments:                                         */
/*   short w, h;   { width and height of min. enclosing rectangle }      */
/*   short xleft, ytop;  { coordinates at top left corner of rect. }     */
/*   short theta;  { starting angle, degrees of elliptical arc }         */
/*   short arc;    { arc angular extent, degrees of elliptical arc }     */
/*   long style;   { 32-bit line-style pattern }                         */
/*   short mode;   { drawing mode }                                      */
/*-----------------------------------------------------------------------*/
/* Revision history:                                                     */
/*   08/14/89...Original version written..................Jerry Van Aken */
/*   03/26/90...Added direct-mode entry points............W.S.Egr        */
/*-----------------------------------------------------------------------*/
#define FIXONE  (1<<16)             /* fixed point 1.0 */
#define FIXHALF (1<<15)             /* fixed point 0.5 */
#define abs(x)  ((x)<0?-(x):(x))    /* absolute value  */

#include <gsptypes.h>
#include <gspglobs.h>

 /* Declare external functions */
 extern void arcstyle(), trig_values();

typedef struct { long sin, cos; } TRIGVALS;  /* fixed-pt sine, cosine */
typedef struct { short x, y; } POINT2D;  /* 2D point */

static int w, h, xleft, ytop, theta, arc, mode;

/*
 * Routine below is called by both styled_ovalarc and styled_piearc.
 */
static void styled_eliparc()
{
    int xc, yc;
    TRIGVALS dir;
    POINT2D dydx, daddr, arc1, arc2, ray1, ray2;

    if (w <= 0 || h <= 0)
        return;
    if (arc < 0)
        mode += 4;    /* bit 2 of mode = counterclockwise */

    /* Get sine and cosine of arc starting angle theta. */
    trig_values(theta, &dir);

    /* Get x and y coordinates of arc starting point on ellipse. */
    arc1.x = w*(FIXONE + dir.cos) + FIXONE >> 17;
    arc1.y = h*(FIXONE + dir.sin) + FIXONE >> 17;
    ray1.x = w*dir.cos + FIXHALF >> 15;
    ray1.y = h*dir.sin + FIXHALF >> 15;

    if (abs(arc) > 359) {   /* draw entire ellipse */
        mode += 8;    /* bit 3 of mode = draw entire oval */
        arc2 = arc1;        /* set arc end point = arc start point */
        ray2 = ray1;
    } else {                /* draw just an arc */
        /* Get sine and cosine of arc ending angle (theta+arc). */
        trig_values(theta+arc, &dir);

        /* Get x and y coordinates of arc ending point on ellipse. */
        arc2.x = w*(FIXONE + dir.cos) + FIXONE >> 17;
        arc2.y = h*(FIXONE + dir.sin) + FIXONE >> 17;
        ray2.x = w*dir.cos + FIXHALF >> 15;
        ray2.y = h*dir.sin + FIXHALF >> 15;
        if (abs(arc) > 179 && ray2.x == ray1.x && ray2.y == ray1.y)
            mode += 8;
    }

    /* If pie arc, draw lines from center to ends of arc. */
    if (mode & 16)               /* draw pie arc */
        if ((mode & 8) == 0) {     /* not entire ellipse */
            xc = xleft + w/2;
            yc = ytop + h/2;
            styled_line(xleft+arc2.x, ytop+arc2.y, xc, yc, 0, mode);
            styled_line(xc, yc, xleft+arc1.x, ytop+arc1.y, 0, mode);
        }

    /* Draw arc. */
    dydx.x  = w;
    dydx.y  = h;
    daddr.x = xleft;
    daddr.y = ytop;
    arcstyle(dydx, daddr, arc1, arc2, ray1, ray2, mode);
}


/*-------------------------- STYLED OVAL ARC --------------------------*/
void styled_ovalarc(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
int arg1, arg2, arg3, arg4, arg5, arg6, arg8;
long arg7;
{
    w       = arg1;
    h       = arg2;
    xleft   = arg3;
    ytop    = arg4;
    theta   = arg5;
    arc     = arg6;
    mode    = arg8 & 3;           /* specify oval arc */
    if ((mode & 2) == 0) {        /* use new line style pattern */
        env.stylemask = arg7;
        mode += 2;
    }
    styled_eliparc();
}


/*-------------- STYLED OVAL ARC (direct-mode entry ) -----------------*/
void dm_styled_ovalarc(data_ptr)
short *data_ptr;
{
    w       = data_ptr[0];
    h       = data_ptr[1];
    xleft   = data_ptr[2];
    ytop    = data_ptr[3];
    theta   = data_ptr[4];
    arc     = data_ptr[5];
    mode    = data_ptr[8] & 3;    /* specify oval arc */
    if ((mode & 2) == 0) {        /* use new line style pattern */
        unsigned long *lp = (unsigned long *)&data_ptr[6];

        env.stylemask = *lp;
        mode += 2;
    }
    styled_eliparc();
}


/*-------------------------- STYLED PIE ARC ---------------------------*/
void styled_piearc(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
int arg1, arg2, arg3, arg4, arg5, arg6, arg8;
long arg7;
{
    w       = arg1;
    h       = arg2;
    xleft   = arg3;
    ytop    = arg4;
    theta   = arg5;
    arc     = arg6;
    mode    = (arg8 & 3) + 16;    /* specify pie arc */
    if ((mode & 2) == 0) {        /* use new line style pattern */
        env.stylemask = arg7;
        mode += 2;
    }
    styled_eliparc();
}


/*-------------- STYLED PIE ARC (direct-mode entry ) -----------------*/
void dm_styled_piearc(data_ptr)
short *data_ptr;
{
    w       = data_ptr[0];
    h       = data_ptr[1];
    xleft   = data_ptr[2];
    ytop    = data_ptr[3];
    theta   = data_ptr[4];
    arc     = data_ptr[5];
    mode    = (data_ptr[8] & 3) + 16;   /* specify oval arc */
    if ((mode & 2) == 0) {              /* use new line style pattern */
        unsigned long *lp = (unsigned long *)&data_ptr[6];

        env.stylemask = *lp;
        mode += 2;
    }
    styled_eliparc();
}
