/*-----------------------------------------------------------------------*/
/*                                 TIGA                                  */
/*       Copyright (c) 1987-1990 Texas Instruments Incorporated.         */
/*                         All Rights Reserved                           */
/*-----------------------------------------------------------------------*/
/*  TIGA - Graphics Manager Extension                                    */
/*-----------------------------------------------------------------------*/
/*                                                                       */
/* draw_ovalarc and draw_piearc functions                                */
/*                                                                       */
/*   The draw_ovalarc and draw_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.                */
/*   The draw_ovalarc function draws only the arc, while the draw_piearc */
/*   function also draws two 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 last two arguments, tstart and tarc,    */
/*   which specify its starting angle and extent.                        */
/*   Both arguments are given in degrees of elliptical arc.              */
/*   Positive angles are in the clockwise direction, while negative      */
/*   angles are counterclockwise.                                        */
/*   Starting angle tstart is measured from the center of the right side */
/*   of the enclosing rectangle, and is treated as modulus 360.          */
/*   Arc extent tarc 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.                                                   */
/*-----------------------------------------------------------------------*/
/* Usage:  draw_piearc(w, h, xleft, ytop, tstart, tarc);                 */
/*         draw_ovalarc(w, h, xleft, ytop, tstart, tarc);                */
/*                                                                       */
/* 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 tstart;  { starting angle, degrees of elliptical arc }         */
/*   long tarc;  { arc angle, degrees of elliptical arc }                */
/*-----------------------------------------------------------------------*/
/* Revision history:                                                     */
/*   2/10/87...Original version written...................Jerry Van Aken */
/*   11/9/87...Redefined arc start and end points.........JV             */
/*   9/16/88...Added TIGA direct mode and check for dstbm.Graham Short   */
/*-----------------------------------------------------------------------*/

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


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

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

 static struct params *p, myparams;
 static int pie;  /* = TRUE if piearc, = FALSE if ovalarc */
 static long w, h;  /* width and height of ellipse's enclosing rect */
 static long xleft, ytop;  /* top left corner of enclosing rectangle */

 /* Coordinates specified relative to top left corner of minimum
  * enclosing rectangle for ellipse.
  */
 static long tstart, tarc;  /* arc start and arc span angles */
 static long xc, yc;  /* center of ellipse */

 /*-------------------- draw_ovalarc() --------------------------*/

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

 dm_draw_ovalarc(data_ptr)
 short *data_ptr;
 {
    pie = FALSE;
    w      = *data_ptr++;
    h      = *data_ptr++;
    xleft  = *data_ptr++;
    ytop   = *data_ptr++;
    tstart = *data_ptr++;
    tarc   = *data_ptr;
    draw_eliparc();
}

 /*-------------------- draw_piearc() --------------------------*/

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

 dm_draw_piearc(data_ptr)
 short *data_ptr;
 {
    pie = TRUE;
    w      = *data_ptr++;
    h      = *data_ptr++;
    xleft  = *data_ptr++;
    ytop   = *data_ptr++;
    tstart = *data_ptr++;
    tarc   = *data_ptr;
    draw_eliparc();
}

/*-------------------- draw_eliparc() --------------------------*/

draw_eliparc()
{
    long qs, qe;  /* start and end quadrants (q = 0, 1, 2 or 3) */
    long q;       /* current quadrant of ellipse */
    long qtemp;
    long xs, ys;  /* arc start point coordinates */
    long xe, ye;  /* arc end point coordinates */

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

    if (tarc > 359 || tarc < -359) {
        draw_oval(w, h, xleft, ytop);
        return;
    }

    p = &myparams;
    p->width = w;
    p->height = h;

    /* 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);
    }

    /* Calculate center point of ellipse (relative to rect. corner). */
    xc = w >> 1;
    yc = h >> 1;

    /* If pie arc, draw two lines from center to arc end points. */
    if (pie) {
        draw_line(xc + xleft, yc + ytop, xs + xleft, ys + ytop);
        draw_line(xc + xleft, yc + ytop, xe + xleft, ye + ytop);
    }

    /* Draw the arc;
     * does arc start and end in same quadrant?
     */
    if (qs == qe && tarc < 180 && tarc > -180)
        /* Entire arc is contained within a single quadrant. */
        if (qs is_odd)
            arc_quadrant(qs, xs, ys, xe, ye);
        else
            arc_quadrant(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_quadrant(qs, w-xc, h, xs, ys);
                 break;
        case 1:
                 arc_quadrant(qs, xs, ys, 0, h-yc);
                 break;
        case 2:
                 arc_quadrant(qs, xc, 0, xs, ys);
                 break;
        case 3:
                 arc_quadrant(qs, xs, ys, w, yc);
                 break;
        }
        /* draw portion of arc lying in ending quadrant qe */
        switch (qe) {
        case 0:
                 arc_quadrant(qe, xe, ye, w, h-yc);
                 break;
        case 1:
                 arc_quadrant(qe, xc, h, xe, ye);
                 break;
        case 2:
                 arc_quadrant(qe, xe, ye, 0, yc);
                 break;
        case 3:
                 arc_quadrant(qe, w-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_quadrant(qtemp, w-xc, h, w, h-yc);
                     break;
            case 1:
                     arc_quadrant(qtemp, xc, h, 0, h-yc);
                     break;
            case 2:
                     arc_quadrant(qtemp, xc, 0, 0, yc);
                     break;
            case 3:
                     arc_quadrant(qtemp, w-xc, 0, w, yc);
                     break;
            }
    }
 }

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

 arc_quadrant(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) {      /* in quadrant number 0 or 3 */
        p->deltax = 1;
        p->xnorm = xs;
    } else {                     /* in quadrant number 1 or 2 */
        p->deltax = -1;
        p->xnorm = w - xs;
    }
    if (q < 2) {                 /* in quadrant number 0 or 1 */
        p->deltay = -1;
        p->ynorm = ys;
    } else {                     /* in quadrant number 2 or 3 */
        p->deltay = 1;
        p->ynorm = h - ys;
    }
    p->xcount = xs - xe;
    p->ycount = ys - ye;
    p->xcoord = xleft + xs;
    p->ycoord = ytop + ys;
    arc_draw(p);
 }

