/*-----------------------------------------------------------------------*/
/*                                 TIGA                                  */
/*       Copyright (c) 1987-1990 Texas Instruments Incorporated.         */
/*                         All Rights Reserved                           */
/*-----------------------------------------------------------------------*/
/*  TIGA - Graphics Manager Extension                                    */
/*-----------------------------------------------------------------------*/
/*                                                                       */
/* pen_ovalarc, pen_piearc, patnpen_ovalarc and patnpen_piearc functions */
/*                                                                       */
/*   The pen_ovalarc, pen_piearc, patnpen_ovalarc and patnpen_piearc     */
/*   functions draw arcs taken from an ellipse in standard position.     */
/*   (In standard position, the major and minor axes of the ellipse are  */
/*   parallel to the x and y axes.)  The ellipse is specified in terms   */
/*   of the minimum enclosing rectangle in which it is inscribed.  This  */
/*   rectangle is represented by its width w, height h, and the          */
/*   coordinates (xleft,ytop) at the top left corner of the rectangle.   */
/*   The arc extent is specified as an angle representing degrees of     */
/*   elliptical arc.  The starting point of the arc is also specified as */
/*   an angle. Angles are measured from a horizontal from the center of  */
/*   the rectangle to the right side.  Positive angles are in the        */
/*   clockwise direction, while negative angles are counterclockwise.    */
/*                                                                       */
/*   The pen_ovalarc and patnpen_ovalarc functions draw the arc using    */
/*   the pen.  The pen_ovalarc function fills the area under the pen     */
/*   with a solid color (the current color 1), while the patnpen_ovalarc */
/*   function fills with a pattern (the current pattern is drawn in      */
/*   colors 0 and 1).                                                    */
/*                                                                       */
/*   The patnpen_ovalarc and patnpen_piearc draw arcs similar to the     */
/*   pen_ovalarc and patnpen_ovalarc functions, except that in addition  */
/*   to the arc, two lines are drawn (using the pen) from the center of  */
/*   the ellipse to the two end points of the arc.  The pen_piearc       */
/*   function fills the area under the pen with a solid color (the       */
/*   current color 1), while the patnpen_piearc function fills with a    */
/*   pattern (the current pattern is drawn in colors 0 and 1).           */
/*-----------------------------------------------------------------------*/
/* Usage:  pen_piearc(w, h, xleft, ytop, xstart, ystart, xend, yend);    */
/*         pen_ovalarc(w, h, xleft, ytop, xstart, ystart, xend, yend);   */
/*                                                                       */
/* Description of the arguments:                                         */
/*   long w, h;  { width and height of min. enclosing rect. for oval }   */
/*   long xleft, ytop;  { coordinates of left and top side of rect. }    */
/*   long xstart, ystart;  { starting point for arc }                    */
/*   long xend, yend;  { ending point for arc }                          */
/*-----------------------------------------------------------------------*/
/* Revision history:                                                     */
/*   2/26/87...Original version written...................Jerry Van Aken */
/*   6/18/87...Redefined arc start and end points.........JV             */
/*   9/16/88...Added TIGA direct mode, dstbm check........Graham Short   */
/*-----------------------------------------------------------------------*/

#define is_odd    &1
#define TRUE      1
#define FALSE     0

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

 /* Declare external functions */
 extern void arc_pen();
 extern void onarc();

 static struct params *p, arcparams;

 static int pie;  /* = TRUE if piearc, = FALSE if ovalarc */
 static int patnfill;  /* TRUE if pattern fill, FALSE if solid fill */
 static long xc, yc;  /* center of ellipse (relative to rectangle) */
 static long w, h;  /* width and height of ellipse's enclosing rect */
 static long tstart, tarc;  /* arc start and arc extent angles */

 /* Coordinates specified relative to screen origin */
 static long xleft, ytop;  /* top left corner of enclosing rectangle */

 /*-------------------- pen_ovalarc() --------------------------*/

 pen_ovalarc(arg1, arg2, arg3, arg4, arg5, arg6)
 long arg1, arg2, arg3, arg4, arg5, arg6;
 {
    pie = FALSE;
    patnfill = FALSE;
    w      = arg1;
    h      = arg2;
    xleft  = arg3;
    ytop   = arg4;
    tstart = arg5;
    tarc   = arg6;
    pen_eliparc();
}

 dm_pen_ovalarc(data_ptr)
 short *data_ptr;
 {
    pie = FALSE;
    patnfill = FALSE;
    w      = *data_ptr++;
    h      = *data_ptr++;
    xleft  = *data_ptr++;
    ytop   = *data_ptr++;
    tstart = *data_ptr++;
    tarc   = *data_ptr;
    pen_eliparc();
}


 /*-------------------- pen_piearc() --------------------------*/

 pen_piearc(arg1, arg2, arg3, arg4, arg5, arg6)
 long arg1, arg2, arg3, arg4, arg5, arg6;
 {
    pie = TRUE;
    patnfill = FALSE;
    w      = arg1;
    h      = arg2;
    xleft  = arg3;
    ytop   = arg4;
    tstart = arg5;
    tarc   = arg6;
    pen_eliparc();
}

 dm_pen_piearc(data_ptr)
 short *data_ptr;
 {
    pie = TRUE;
    patnfill = FALSE;
    w      = *data_ptr++;
    h      = *data_ptr++;
    xleft  = *data_ptr++;
    ytop   = *data_ptr++;
    tstart = *data_ptr++;
    tarc   = *data_ptr;
    pen_eliparc();
}

 /*-------------------- patnpen_ovalarc() ----------------------*/

 patnpen_ovalarc(arg1, arg2, arg3, arg4, arg5, arg6)
 long arg1, arg2, arg3, arg4, arg5, arg6;
 {
    pie = FALSE;
    patnfill = TRUE;
    w      = arg1;
    h      = arg2;
    xleft  = arg3;
    ytop   = arg4;
    tstart = arg5;
    tarc   = arg6;
    pen_eliparc();
}

 dm_patnpen_ovalarc(data_ptr)
 short *data_ptr;
 {
    pie = FALSE;
    patnfill = TRUE;
    w      = *data_ptr++;
    h      = *data_ptr++;
    xleft  = *data_ptr++;
    ytop   = *data_ptr++;
    tstart = *data_ptr++;
    tarc   = *data_ptr;
    pen_eliparc();
}

 /*-------------------- patnpen_piearc() ----------------------*/

 patnpen_piearc(arg1, arg2, arg3, arg4, arg5, arg6)
 long arg1, arg2, arg3, arg4, arg5, arg6;
 {
    pie = TRUE;
    patnfill = TRUE;
    w      = arg1;
    h      = arg2;
    xleft  = arg3;
    ytop   = arg4;
    tstart = arg5;
    tarc   = arg6;
    pen_eliparc();
}

 dm_patnpen_piearc(data_ptr)
 short *data_ptr;
 {
    pie = TRUE;
    patnfill = TRUE;
    w      = *data_ptr++;
    h      = *data_ptr++;
    xleft  = *data_ptr++;
    ytop   = *data_ptr++;
    tstart = *data_ptr++;
    tarc   = *data_ptr;
    pen_eliparc();
}

/*-------------------- pen_eliparc() --------------------------*/

pen_eliparc()
{
    long qs, qe;  /* start and end quadrants (q = 0, 1, 2 or 3) */
    long q;       /* current quadrant of ellipse */
    long qtemp;
    /* coordinates spec'd relative to corner of encl. rectangle */
    long xs, ys;  /* computed coordinates of arc start point */
    long xe, ye;  /* computed coordinates of arc end point */

    /* abort if the drawing bitmap is not pointing to the screen */
    if( env.dstbm )
         return;

    p = &arcparams;
    p->width = w;
    p->height = h;
    p->patn = patnfill;

    /* Calculate center point of ellipse. */
    xc = w >> 1;
    yc = h >> 1;

    if (tarc > 359 || tarc < -359) {
        arc_quad(0, xc, h, w, yc);
        arc_quad(1, xc, h, 0, yc);
        arc_quad(2, xc, 0, 0, yc);
        arc_quad(3, xc, 0, w, yc);
        return;
    }

    /* Convert starting angle and arc angle to start and end points. */
    if (tarc >= 0) {
        onarc(w, h,      tstart, &xs, &ys, &qs);
        onarc(w, h, tstart+tarc, &xe, &ye, &qe);
    } else {
        onarc(w, h, tstart+tarc, &xs, &ys, &qs);
        onarc(w, h,      tstart, &xe, &ye, &qe);
    }

    /* If pie arc, draw two lines from center to arc end points. */
    if (pie)
        if (patnfill) {
            patnpen_line(xc+xleft, yc+ytop, xs+xleft, ys+ytop);
            patnpen_line(xc+xleft, yc+ytop, xe+xleft, ye+ytop);
        } else {
            pen_line(xc+xleft, yc+ytop, xs+xleft, ys+ytop);
            pen_line(xc+xleft, yc+ytop, xe+xleft, ye+ytop);
        }
    /* Draw the arc.  Does arc span more than one quadrant? */
    if (qs == qe && tarc < 180 && tarc > -180) {
        /* Entire arc is contained within a single quadrant. */
        if (qs is_odd)
            arc_quad(qs, xs, ys, xe, ye);
        else
            arc_quad(qs, xe, ye, xs, ys);
    } else {            /* Arc spans more than one quadrant. */
        /* draw portion of arc lying in starting quadrant qs */
        switch (qs) {
        case 0:
                 arc_quad(qs, xc, h, xs, ys);
                 break;
        case 1:
                 arc_quad(qs, xs, ys, 0, yc);
                 break;
        case 2:
                 arc_quad(qs, xc, 0, xs, ys);
                 break;
        case 3:
                 arc_quad(qs, xs, ys, w, yc);
                 break;
        }
        /* draw portion of arc lying in ending quadrant qe */
        switch (qe) {
        case 0:
                 arc_quad(qe, xe, ye, w, yc);
                 break;
        case 1:
                 arc_quad(qe, xc, h, xe, ye);
                 break;
        case 2:
                 arc_quad(qe, xe, ye, 0, yc);
                 break;
        case 3:
                 arc_quad(qe, xc, 0, xe, ye);
                 break;
        }
        /* quadrants between qs and qe get full quarter arc */
        if (qe <= qs)
            qe += 4;
        for (q = qs + 1; q < qe; ++q)
            switch (qtemp = (q & 3)) {
            case 0:
                     arc_quad(qtemp, xc, h, w, yc);
                     break;
            case 1:
                     arc_quad(qtemp, xc, h, 0, yc);
                     break;
            case 2:
                     arc_quad(qtemp, xc, 0, 0, yc);
                     break;
            case 3:
                     arc_quad(qtemp, xc, 0, w, yc);
                     break;
            }
    }
 }

 /*-------------------- arc_quad() --------------------------*/
 /* arc drawn from (xs,ys) to (xe,ye) within a single quadrant */

 arc_quad(q, xs, ys, xe, ye)
 long q;  /* quadrant number */
 long xs, ys;  /* arc start coordinates (relative to encl. rect.) */
 long xe, ye;  /* arc end coordinates (relative to encl. rect.) */
 {
    if (q == 0 || q == 3) {
        p->deltax = 0;
        p->xcount = xe - xs;
        p->xnorm = xs;
    } else {
        p->deltax = -1;
        p->xcount = xs - xe;
        p->xnorm = w - xs;
    }
    if (q < 2) {
        p->deltay = -1;
        p->ycount = ys - ye;
        p->ynorm = ys;
    } else {
        p->deltay = 1;
        p->ycount = ye - ys;
        p->ynorm = h - ys;
    }
    p->xcoord = xleft + xs;
    p->ycoord = ytop + ys;
    arc_pen(p);
 }

