799 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			799 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
/************************************************************
 | 
						|
 | 
						|
Copyright 1989, 1998  The Open Group
 | 
						|
 | 
						|
Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
documentation for any purpose is hereby granted without fee, provided that
 | 
						|
the above copyright notice appear in all copies and that both that
 | 
						|
copyright notice and this permission notice appear in supporting
 | 
						|
documentation.
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | 
						|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | 
						|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of The Open Group shall not be
 | 
						|
used in advertising or otherwise to promote the sale, use or other dealings
 | 
						|
in this Software without prior written authorization from The Open Group.
 | 
						|
 | 
						|
Author:  Bob Scheifler, MIT X Consortium
 | 
						|
 | 
						|
********************************************************/
 | 
						|
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <math.h>
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xprotostr.h>
 | 
						|
#include "regionstr.h"
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "mifpoly.h"
 | 
						|
#include "mi.h"
 | 
						|
#include "mifillarc.h"
 | 
						|
 | 
						|
#define QUADRANT (90 * 64)
 | 
						|
#define HALFCIRCLE (180 * 64)
 | 
						|
#define QUADRANT3 (270 * 64)
 | 
						|
 | 
						|
#ifndef M_PI
 | 
						|
#define M_PI	3.14159265358979323846
 | 
						|
#endif
 | 
						|
 | 
						|
#define Dsin(d)	sin((double)d*(M_PI/11520.0))
 | 
						|
#define Dcos(d)	cos((double)d*(M_PI/11520.0))
 | 
						|
 | 
						|
void
 | 
						|
miFillArcSetup(xArc *arc, miFillArcRec *info)
 | 
						|
{
 | 
						|
    info->y = arc->height >> 1;
 | 
						|
    info->dy = arc->height & 1;
 | 
						|
    info->yorg = arc->y + info->y;
 | 
						|
    info->dx = arc->width & 1;
 | 
						|
    info->xorg = arc->x + (arc->width >> 1) + info->dx;
 | 
						|
    info->dx = 1 - info->dx;
 | 
						|
    if (arc->width == arc->height)
 | 
						|
    {
 | 
						|
	/* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */
 | 
						|
	/* even: xorg = yorg = 0   odd:  xorg = .5, yorg = -.5 */
 | 
						|
	info->ym = 8;
 | 
						|
	info->xm = 8;
 | 
						|
	info->yk = info->y << 3;
 | 
						|
	if (!info->dx)
 | 
						|
	{
 | 
						|
	    info->xk = 0;
 | 
						|
	    info->e = -1;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    info->y++;
 | 
						|
	    info->yk += 4;
 | 
						|
	    info->xk = -4;
 | 
						|
	    info->e = - (info->y << 3);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	/* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
 | 
						|
	/* even: xorg = yorg = 0   odd:  xorg = .5, yorg = -.5 */
 | 
						|
	info->ym = (arc->width * arc->width) << 3;
 | 
						|
	info->xm = (arc->height * arc->height) << 3;
 | 
						|
	info->yk = info->y * info->ym;
 | 
						|
	if (!info->dy)
 | 
						|
	    info->yk -= info->ym >> 1;
 | 
						|
	if (!info->dx)
 | 
						|
	{
 | 
						|
	    info->xk = 0;
 | 
						|
	    info->e = - (info->xm >> 3);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    info->y++;
 | 
						|
	    info->yk += info->ym;
 | 
						|
	    info->xk = -(info->xm >> 1);
 | 
						|
	    info->e = info->xk - info->yk;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
miFillArcDSetup(xArc *arc, miFillArcDRec *info)
 | 
						|
{
 | 
						|
    /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
 | 
						|
    /* even: xorg = yorg = 0   odd:  xorg = .5, yorg = -.5 */
 | 
						|
    info->y = arc->height >> 1;
 | 
						|
    info->dy = arc->height & 1;
 | 
						|
    info->yorg = arc->y + info->y;
 | 
						|
    info->dx = arc->width & 1;
 | 
						|
    info->xorg = arc->x + (arc->width >> 1) + info->dx;
 | 
						|
    info->dx = 1 - info->dx;
 | 
						|
    info->ym = ((double)arc->width) * (arc->width * 8);
 | 
						|
    info->xm = ((double)arc->height) * (arc->height * 8);
 | 
						|
    info->yk = info->y * info->ym;
 | 
						|
    if (!info->dy)
 | 
						|
	info->yk -= info->ym / 2.0;
 | 
						|
    if (!info->dx)
 | 
						|
    {
 | 
						|
	info->xk = 0;
 | 
						|
	info->e = - (info->xm / 8.0);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	info->y++;
 | 
						|
	info->yk += info->ym;
 | 
						|
	info->xk = -info->xm / 2.0;
 | 
						|
	info->e = info->xk - info->yk;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
miGetArcEdge(
 | 
						|
	     xArc *arc,
 | 
						|
	     miSliceEdgePtr edge,
 | 
						|
	     int k,
 | 
						|
	     Bool top, 
 | 
						|
	     Bool left )
 | 
						|
{
 | 
						|
    int xady, y;
 | 
						|
 | 
						|
    y = arc->height >> 1;
 | 
						|
    if (!(arc->width & 1))
 | 
						|
	y++;
 | 
						|
    if (!top)
 | 
						|
    {
 | 
						|
	y = -y;
 | 
						|
	if (arc->height & 1)
 | 
						|
	    y--;
 | 
						|
    }
 | 
						|
    xady = k + y * edge->dx;
 | 
						|
    if (xady <= 0)
 | 
						|
	edge->x = - ((-xady) / edge->dy + 1);
 | 
						|
    else
 | 
						|
	edge->x = (xady - 1) / edge->dy;
 | 
						|
    edge->e = xady - edge->x * edge->dy;
 | 
						|
    if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0)))
 | 
						|
	edge->e = edge->dy - edge->e + 1;
 | 
						|
    if (left)
 | 
						|
	edge->x++;
 | 
						|
    edge->x += arc->x + (arc->width >> 1);
 | 
						|
    if (edge->dx > 0)
 | 
						|
    {
 | 
						|
	edge->deltax = 1;
 | 
						|
	edge->stepx = edge->dx / edge->dy;
 | 
						|
	edge->dx = edge->dx % edge->dy;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	edge->deltax = -1;
 | 
						|
	edge->stepx = - ((-edge->dx) / edge->dy);
 | 
						|
	edge->dx = (-edge->dx) % edge->dy;
 | 
						|
    }
 | 
						|
    if (!top)
 | 
						|
    {
 | 
						|
	edge->deltax = -edge->deltax;
 | 
						|
	edge->stepx = -edge->stepx;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
miEllipseAngleToSlope (int angle, int width, int height, int *dxp, int *dyp,
 | 
						|
		       double *d_dxp, double *d_dyp)
 | 
						|
{
 | 
						|
    int	    dx, dy;
 | 
						|
    double  d_dx, d_dy, scale;
 | 
						|
    Bool    negative_dx, negative_dy;
 | 
						|
 | 
						|
    switch (angle) {
 | 
						|
    case 0:
 | 
						|
	*dxp = -1;
 | 
						|
	*dyp = 0;
 | 
						|
	if (d_dxp) {
 | 
						|
	    *d_dxp = width / 2.0;
 | 
						|
	    *d_dyp = 0;
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    case QUADRANT:
 | 
						|
	*dxp = 0;
 | 
						|
	*dyp = 1;
 | 
						|
	if (d_dxp) {
 | 
						|
	    *d_dxp = 0;
 | 
						|
	    *d_dyp = - height / 2.0;
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    case HALFCIRCLE:
 | 
						|
	*dxp = 1;
 | 
						|
	*dyp = 0;
 | 
						|
	if (d_dxp) {
 | 
						|
	    *d_dxp = - width / 2.0;
 | 
						|
	    *d_dyp = 0;
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    case QUADRANT3:
 | 
						|
	*dxp = 0;
 | 
						|
	*dyp = -1;
 | 
						|
	if (d_dxp) {
 | 
						|
	    *d_dxp = 0;
 | 
						|
	    *d_dyp = height / 2.0;
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    default:
 | 
						|
	d_dx = Dcos(angle) * width;
 | 
						|
	d_dy = Dsin(angle) * height;
 | 
						|
	if (d_dxp) {
 | 
						|
	    *d_dxp = d_dx / 2.0;
 | 
						|
	    *d_dyp = - d_dy / 2.0;
 | 
						|
	}
 | 
						|
	negative_dx = FALSE;
 | 
						|
	if (d_dx < 0.0)
 | 
						|
	{
 | 
						|
	    d_dx = -d_dx;
 | 
						|
	    negative_dx = TRUE;
 | 
						|
	}
 | 
						|
	negative_dy = FALSE;
 | 
						|
	if (d_dy < 0.0)
 | 
						|
	{
 | 
						|
	    d_dy = -d_dy;
 | 
						|
	    negative_dy = TRUE;
 | 
						|
	}
 | 
						|
	scale = d_dx;
 | 
						|
	if (d_dy > d_dx)
 | 
						|
	    scale = d_dy;
 | 
						|
	dx = floor ((d_dx * 32768) / scale + 0.5);
 | 
						|
	if (negative_dx)
 | 
						|
	    dx = -dx;
 | 
						|
	*dxp = dx;
 | 
						|
	dy = floor ((d_dy * 32768) / scale + 0.5);
 | 
						|
	if (negative_dy)
 | 
						|
	    dy = -dy;
 | 
						|
	*dyp = dy;
 | 
						|
	break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
miGetPieEdge(
 | 
						|
	     xArc *arc,
 | 
						|
	     int angle,
 | 
						|
	     miSliceEdgePtr edge,
 | 
						|
	     Bool top, 
 | 
						|
	     Bool left )
 | 
						|
{
 | 
						|
    int k;
 | 
						|
    int	dx, dy;
 | 
						|
 | 
						|
    miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0);
 | 
						|
 | 
						|
    if (dy == 0)
 | 
						|
    {
 | 
						|
	edge->x = left ? -65536 : 65536;
 | 
						|
	edge->stepx = 0;
 | 
						|
	edge->e = 0;
 | 
						|
	edge->dx = -1;
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    if (dx == 0)
 | 
						|
    {
 | 
						|
	edge->x = arc->x + (arc->width >> 1);
 | 
						|
	if (left && (arc->width & 1))
 | 
						|
	    edge->x++;
 | 
						|
	else if (!left && !(arc->width & 1))
 | 
						|
	    edge->x--;
 | 
						|
	edge->stepx = 0;
 | 
						|
	edge->e = 0;
 | 
						|
	edge->dx = -1;
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    if (dy < 0) {
 | 
						|
	dx = -dx;
 | 
						|
	dy = -dy;
 | 
						|
    }
 | 
						|
    k = (arc->height & 1) ? dx : 0;
 | 
						|
    if (arc->width & 1)
 | 
						|
	k += dy;
 | 
						|
    edge->dx = dx << 1;
 | 
						|
    edge->dy = dy << 1;
 | 
						|
    miGetArcEdge(arc, edge, k, top, left);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
miFillArcSliceSetup(xArc *arc, miArcSliceRec *slice, GCPtr pGC)
 | 
						|
{
 | 
						|
    int angle1, angle2;
 | 
						|
 | 
						|
    angle1 = arc->angle1;
 | 
						|
    if (arc->angle2 < 0)
 | 
						|
    {
 | 
						|
	angle2 = angle1;
 | 
						|
	angle1 += arc->angle2;
 | 
						|
    }
 | 
						|
    else
 | 
						|
	angle2 = angle1 + arc->angle2;
 | 
						|
    while (angle1 < 0)
 | 
						|
	angle1 += FULLCIRCLE;
 | 
						|
    while (angle1 >= FULLCIRCLE)
 | 
						|
	angle1 -= FULLCIRCLE;
 | 
						|
    while (angle2 < 0)
 | 
						|
	angle2 += FULLCIRCLE;
 | 
						|
    while (angle2 >= FULLCIRCLE)
 | 
						|
	angle2 -= FULLCIRCLE;
 | 
						|
    slice->min_top_y = 0;
 | 
						|
    slice->max_top_y = arc->height >> 1;
 | 
						|
    slice->min_bot_y = 1 - (arc->height & 1);
 | 
						|
    slice->max_bot_y = slice->max_top_y - 1;
 | 
						|
    slice->flip_top = FALSE;
 | 
						|
    slice->flip_bot = FALSE;
 | 
						|
    if (pGC->arcMode == ArcPieSlice)
 | 
						|
    {
 | 
						|
	slice->edge1_top = (angle1 < HALFCIRCLE);
 | 
						|
	slice->edge2_top = (angle2 <= HALFCIRCLE);
 | 
						|
	if ((angle2 == 0) || (angle1 == HALFCIRCLE))
 | 
						|
	{
 | 
						|
	    if (angle2 ? slice->edge2_top : slice->edge1_top)
 | 
						|
		slice->min_top_y = slice->min_bot_y;
 | 
						|
	    else
 | 
						|
		slice->min_top_y = arc->height;
 | 
						|
	    slice->min_bot_y = 0;
 | 
						|
	}
 | 
						|
	else if ((angle1 == 0) || (angle2 == HALFCIRCLE))
 | 
						|
	{
 | 
						|
	    slice->min_top_y = slice->min_bot_y;
 | 
						|
	    if (angle1 ? slice->edge1_top : slice->edge2_top)
 | 
						|
		slice->min_bot_y = arc->height;
 | 
						|
	    else
 | 
						|
		slice->min_bot_y = 0;
 | 
						|
	}
 | 
						|
	else if (slice->edge1_top == slice->edge2_top)
 | 
						|
	{
 | 
						|
	    if (angle2 < angle1)
 | 
						|
	    {
 | 
						|
		slice->flip_top = slice->edge1_top;
 | 
						|
		slice->flip_bot = !slice->edge1_top;
 | 
						|
	    }
 | 
						|
	    else if (slice->edge1_top)
 | 
						|
	    {
 | 
						|
		slice->min_top_y = 1;
 | 
						|
		slice->min_bot_y = arc->height;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		slice->min_bot_y = 0;
 | 
						|
		slice->min_top_y = arc->height;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	miGetPieEdge(arc, angle1, &slice->edge1,
 | 
						|
		     slice->edge1_top, !slice->edge1_top);
 | 
						|
	miGetPieEdge(arc, angle2, &slice->edge2,
 | 
						|
		     slice->edge2_top, slice->edge2_top);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	double w2, h2, x1, y1, x2, y2, dx, dy, scale;
 | 
						|
	int signdx, signdy, y, k;
 | 
						|
	Bool isInt1 = TRUE, isInt2 = TRUE;
 | 
						|
 | 
						|
	w2 = (double)arc->width / 2.0;
 | 
						|
	h2 = (double)arc->height / 2.0;
 | 
						|
	if ((angle1 == 0) || (angle1 == HALFCIRCLE))
 | 
						|
	{
 | 
						|
	    x1 = angle1 ? -w2 : w2;
 | 
						|
	    y1 = 0.0;
 | 
						|
	}
 | 
						|
	else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3))
 | 
						|
	{
 | 
						|
	    x1 = 0.0;
 | 
						|
	    y1 = (angle1 == QUADRANT) ? h2 : -h2;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    isInt1 = FALSE;
 | 
						|
	    x1 = Dcos(angle1) * w2;
 | 
						|
	    y1 = Dsin(angle1) * h2;
 | 
						|
	}
 | 
						|
	if ((angle2 == 0) || (angle2 == HALFCIRCLE))
 | 
						|
	{
 | 
						|
	    x2 = angle2 ? -w2 : w2;
 | 
						|
	    y2 = 0.0;
 | 
						|
	}
 | 
						|
	else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3))
 | 
						|
	{
 | 
						|
	    x2 = 0.0;
 | 
						|
	    y2 = (angle2 == QUADRANT) ? h2 : -h2;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    isInt2 = FALSE;
 | 
						|
	    x2 = Dcos(angle2) * w2;
 | 
						|
	    y2 = Dsin(angle2) * h2;
 | 
						|
	}
 | 
						|
	dx = x2 - x1;
 | 
						|
	dy = y2 - y1;
 | 
						|
	if (arc->height & 1)
 | 
						|
	{
 | 
						|
	    y1 -= 0.5;
 | 
						|
	    y2 -= 0.5;
 | 
						|
	}
 | 
						|
	if (arc->width & 1)
 | 
						|
	{
 | 
						|
	    x1 += 0.5;
 | 
						|
	    x2 += 0.5;
 | 
						|
	}
 | 
						|
	if (dy < 0.0)
 | 
						|
	{
 | 
						|
	    dy = -dy;
 | 
						|
	    signdy = -1;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    signdy = 1;
 | 
						|
	if (dx < 0.0)
 | 
						|
	{
 | 
						|
	    dx = -dx;
 | 
						|
	    signdx = -1;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    signdx = 1;
 | 
						|
	if (isInt1 && isInt2)
 | 
						|
	{
 | 
						|
	    slice->edge1.dx = dx * 2;
 | 
						|
	    slice->edge1.dy = dy * 2;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    scale = (dx > dy) ? dx : dy;
 | 
						|
	    slice->edge1.dx = floor((dx * 32768) / scale + .5);
 | 
						|
	    slice->edge1.dy = floor((dy * 32768) / scale + .5);
 | 
						|
	}
 | 
						|
	if (!slice->edge1.dy)
 | 
						|
	{
 | 
						|
	    if (signdx < 0)
 | 
						|
	    {
 | 
						|
		y = floor(y1 + 1.0);
 | 
						|
		if (y >= 0)
 | 
						|
		{
 | 
						|
		    slice->min_top_y = y;
 | 
						|
		    slice->min_bot_y = arc->height;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
		    slice->max_bot_y = -y - (arc->height & 1);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		y = floor(y1);
 | 
						|
		if (y >= 0)
 | 
						|
		    slice->max_top_y = y;
 | 
						|
		else
 | 
						|
		{
 | 
						|
		    slice->min_top_y = arc->height;
 | 
						|
		    slice->min_bot_y = -y - (arc->height & 1);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    slice->edge1_top = TRUE;
 | 
						|
	    slice->edge1.x = 65536;
 | 
						|
	    slice->edge1.stepx = 0;
 | 
						|
	    slice->edge1.e = 0;
 | 
						|
	    slice->edge1.dx = -1;
 | 
						|
	    slice->edge2 = slice->edge1;
 | 
						|
	    slice->edge2_top = FALSE;
 | 
						|
	}
 | 
						|
	else if (!slice->edge1.dx)
 | 
						|
	{
 | 
						|
	    if (signdy < 0)
 | 
						|
		x1 -= 1.0;
 | 
						|
	    slice->edge1.x = ceil(x1);
 | 
						|
	    slice->edge1_top = signdy < 0;
 | 
						|
	    slice->edge1.x += arc->x + (arc->width >> 1);
 | 
						|
	    slice->edge1.stepx = 0;
 | 
						|
	    slice->edge1.e = 0;
 | 
						|
	    slice->edge1.dx = -1;
 | 
						|
	    slice->edge2_top = !slice->edge1_top;
 | 
						|
	    slice->edge2 = slice->edge1;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    if (signdx < 0)
 | 
						|
		slice->edge1.dx = -slice->edge1.dx;
 | 
						|
	    if (signdy < 0)
 | 
						|
		slice->edge1.dx = -slice->edge1.dx;
 | 
						|
	    k = ceil(((x1 + x2) * slice->edge1.dy - (y1 + y2) * slice->edge1.dx) / 2.0);
 | 
						|
	    slice->edge2.dx = slice->edge1.dx;
 | 
						|
	    slice->edge2.dy = slice->edge1.dy;
 | 
						|
	    slice->edge1_top = signdy < 0;
 | 
						|
	    slice->edge2_top = !slice->edge1_top;
 | 
						|
	    miGetArcEdge(arc, &slice->edge1, k,
 | 
						|
			 slice->edge1_top, !slice->edge1_top);
 | 
						|
	    miGetArcEdge(arc, &slice->edge2, k,
 | 
						|
			 slice->edge2_top, slice->edge2_top);
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#define ADDSPANS() \
 | 
						|
    pts->x = xorg - x; \
 | 
						|
    pts->y = yorg - y; \
 | 
						|
    *wids = slw; \
 | 
						|
    pts++; \
 | 
						|
    wids++; \
 | 
						|
    if (miFillArcLower(slw)) \
 | 
						|
    { \
 | 
						|
	pts->x = xorg - x; \
 | 
						|
	pts->y = yorg + y + dy; \
 | 
						|
	pts++; \
 | 
						|
	*wids++ = slw; \
 | 
						|
    }
 | 
						|
 | 
						|
static void
 | 
						|
miFillEllipseI(
 | 
						|
	       DrawablePtr pDraw,
 | 
						|
	       GCPtr pGC,
 | 
						|
	       xArc *arc )
 | 
						|
{
 | 
						|
    int x, y, e;
 | 
						|
    int yk, xk, ym, xm, dx, dy, xorg, yorg;
 | 
						|
    int slw;
 | 
						|
    miFillArcRec info;
 | 
						|
    DDXPointPtr points;
 | 
						|
    DDXPointPtr pts;
 | 
						|
    int *widths;
 | 
						|
    int *wids;
 | 
						|
 | 
						|
    points = xalloc(sizeof(DDXPointRec) * arc->height);
 | 
						|
    if (!points)
 | 
						|
	return;
 | 
						|
    widths = xalloc(sizeof(int) * arc->height);
 | 
						|
    if (!widths)
 | 
						|
    {
 | 
						|
	xfree(points);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    miFillArcSetup(arc, &info);
 | 
						|
    MIFILLARCSETUP();
 | 
						|
    if (pGC->miTranslate)
 | 
						|
    {
 | 
						|
	xorg += pDraw->x;
 | 
						|
	yorg += pDraw->y;
 | 
						|
    }
 | 
						|
    pts = points;
 | 
						|
    wids = widths;
 | 
						|
    while (y > 0)
 | 
						|
    {
 | 
						|
	MIFILLARCSTEP(slw);
 | 
						|
	ADDSPANS();
 | 
						|
    }
 | 
						|
    (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
 | 
						|
    xfree(widths);
 | 
						|
    xfree(points);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
miFillEllipseD(
 | 
						|
	       DrawablePtr pDraw,
 | 
						|
	       GCPtr pGC,
 | 
						|
	       xArc *arc )
 | 
						|
{
 | 
						|
    int x, y;
 | 
						|
    int xorg, yorg, dx, dy, slw;
 | 
						|
    double e, yk, xk, ym, xm;
 | 
						|
    miFillArcDRec info;
 | 
						|
    DDXPointPtr points;
 | 
						|
    DDXPointPtr pts;
 | 
						|
    int *widths;
 | 
						|
    int *wids;
 | 
						|
 | 
						|
    points = xalloc(sizeof(DDXPointRec) * arc->height);
 | 
						|
    if (!points)
 | 
						|
	return;
 | 
						|
    widths = xalloc(sizeof(int) * arc->height);
 | 
						|
    if (!widths)
 | 
						|
    {
 | 
						|
	xfree(points);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    miFillArcDSetup(arc, &info);
 | 
						|
    MIFILLARCSETUP();
 | 
						|
    if (pGC->miTranslate)
 | 
						|
    {
 | 
						|
	xorg += pDraw->x;
 | 
						|
	yorg += pDraw->y;
 | 
						|
    }
 | 
						|
    pts = points;
 | 
						|
    wids = widths;
 | 
						|
    while (y > 0)
 | 
						|
    {
 | 
						|
	MIFILLARCSTEP(slw);
 | 
						|
	ADDSPANS();
 | 
						|
    }
 | 
						|
    (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
 | 
						|
    xfree(widths);
 | 
						|
    xfree(points);
 | 
						|
}
 | 
						|
 | 
						|
#define ADDSPAN(l,r) \
 | 
						|
    if (r >= l) \
 | 
						|
    { \
 | 
						|
	pts->x = l; \
 | 
						|
	pts->y = ya; \
 | 
						|
	pts++; \
 | 
						|
	*wids++ = r - l + 1; \
 | 
						|
    }
 | 
						|
 | 
						|
#define ADDSLICESPANS(flip) \
 | 
						|
    if (!flip) \
 | 
						|
    { \
 | 
						|
	ADDSPAN(xl, xr); \
 | 
						|
    } \
 | 
						|
    else \
 | 
						|
    { \
 | 
						|
	xc = xorg - x; \
 | 
						|
	ADDSPAN(xc, xr); \
 | 
						|
	xc += slw - 1; \
 | 
						|
	ADDSPAN(xl, xc); \
 | 
						|
    }
 | 
						|
 | 
						|
static void
 | 
						|
miFillArcSliceI(
 | 
						|
		DrawablePtr pDraw,
 | 
						|
		GCPtr pGC,
 | 
						|
		xArc *arc )
 | 
						|
{
 | 
						|
    int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
 | 
						|
    int x, y, e;
 | 
						|
    miFillArcRec info;
 | 
						|
    miArcSliceRec slice;
 | 
						|
    int ya, xl, xr, xc;
 | 
						|
    DDXPointPtr points;
 | 
						|
    DDXPointPtr pts;
 | 
						|
    int *widths;
 | 
						|
    int *wids;
 | 
						|
 | 
						|
    miFillArcSetup(arc, &info);
 | 
						|
    miFillArcSliceSetup(arc, &slice, pGC);
 | 
						|
    MIFILLARCSETUP();
 | 
						|
    slw = arc->height;
 | 
						|
    if (slice.flip_top || slice.flip_bot)
 | 
						|
	slw += (arc->height >> 1) + 1;
 | 
						|
    points = xalloc(sizeof(DDXPointRec) * slw);
 | 
						|
    if (!points)
 | 
						|
	return;
 | 
						|
    widths = xalloc(sizeof(int) * slw);
 | 
						|
    if (!widths)
 | 
						|
    {
 | 
						|
	xfree(points);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    if (pGC->miTranslate)
 | 
						|
    {
 | 
						|
	xorg += pDraw->x;
 | 
						|
	yorg += pDraw->y;
 | 
						|
	slice.edge1.x += pDraw->x;
 | 
						|
	slice.edge2.x += pDraw->x;
 | 
						|
    }
 | 
						|
    pts = points;
 | 
						|
    wids = widths;
 | 
						|
    while (y > 0)
 | 
						|
    {
 | 
						|
	MIFILLARCSTEP(slw);
 | 
						|
	MIARCSLICESTEP(slice.edge1);
 | 
						|
	MIARCSLICESTEP(slice.edge2);
 | 
						|
	if (miFillSliceUpper(slice))
 | 
						|
	{
 | 
						|
	    ya = yorg - y;
 | 
						|
	    MIARCSLICEUPPER(xl, xr, slice, slw);
 | 
						|
	    ADDSLICESPANS(slice.flip_top);
 | 
						|
	}
 | 
						|
	if (miFillSliceLower(slice))
 | 
						|
	{
 | 
						|
	    ya = yorg + y + dy;
 | 
						|
	    MIARCSLICELOWER(xl, xr, slice, slw);
 | 
						|
	    ADDSLICESPANS(slice.flip_bot);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
 | 
						|
    xfree(widths);
 | 
						|
    xfree(points);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
miFillArcSliceD(
 | 
						|
		DrawablePtr pDraw,
 | 
						|
		GCPtr pGC,
 | 
						|
		xArc *arc )
 | 
						|
{
 | 
						|
    int x, y;
 | 
						|
    int dx, dy, xorg, yorg, slw;
 | 
						|
    double e, yk, xk, ym, xm;
 | 
						|
    miFillArcDRec info;
 | 
						|
    miArcSliceRec slice;
 | 
						|
    int ya, xl, xr, xc;
 | 
						|
    DDXPointPtr points;
 | 
						|
    DDXPointPtr pts;
 | 
						|
    int *widths;
 | 
						|
    int *wids;
 | 
						|
 | 
						|
    miFillArcDSetup(arc, &info);
 | 
						|
    miFillArcSliceSetup(arc, &slice, pGC);
 | 
						|
    MIFILLARCSETUP();
 | 
						|
    slw = arc->height;
 | 
						|
    if (slice.flip_top || slice.flip_bot)
 | 
						|
	slw += (arc->height >> 1) + 1;
 | 
						|
    points = xalloc(sizeof(DDXPointRec) * slw);
 | 
						|
    if (!points)
 | 
						|
	return;
 | 
						|
    widths = xalloc(sizeof(int) * slw);
 | 
						|
    if (!widths)
 | 
						|
    {
 | 
						|
	xfree(points);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    if (pGC->miTranslate)
 | 
						|
    {
 | 
						|
	xorg += pDraw->x;
 | 
						|
	yorg += pDraw->y;
 | 
						|
	slice.edge1.x += pDraw->x;
 | 
						|
	slice.edge2.x += pDraw->x;
 | 
						|
    }
 | 
						|
    pts = points;
 | 
						|
    wids = widths;
 | 
						|
    while (y > 0)
 | 
						|
    {
 | 
						|
	MIFILLARCSTEP(slw);
 | 
						|
	MIARCSLICESTEP(slice.edge1);
 | 
						|
	MIARCSLICESTEP(slice.edge2);
 | 
						|
	if (miFillSliceUpper(slice))
 | 
						|
	{
 | 
						|
	    ya = yorg - y;
 | 
						|
	    MIARCSLICEUPPER(xl, xr, slice, slw);
 | 
						|
	    ADDSLICESPANS(slice.flip_top);
 | 
						|
	}
 | 
						|
	if (miFillSliceLower(slice))
 | 
						|
	{
 | 
						|
	    ya = yorg + y + dy;
 | 
						|
	    MIARCSLICELOWER(xl, xr, slice, slw);
 | 
						|
	    ADDSLICESPANS(slice.flip_bot);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
 | 
						|
    xfree(widths);
 | 
						|
    xfree(points);
 | 
						|
}
 | 
						|
 | 
						|
/* MIPOLYFILLARC -- The public entry for the PolyFillArc request.
 | 
						|
 * Since we don't have to worry about overlapping segments, we can just
 | 
						|
 * fill each arc as it comes.
 | 
						|
 */
 | 
						|
void
 | 
						|
miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    xArc *arc;
 | 
						|
 | 
						|
    for(i = narcs, arc = parcs; --i >= 0; arc++)
 | 
						|
    {
 | 
						|
	if (miFillArcEmpty(arc))
 | 
						|
	    continue;
 | 
						|
	if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
 | 
						|
	{
 | 
						|
	    if (miCanFillArc(arc))
 | 
						|
		miFillEllipseI(pDraw, pGC, arc);
 | 
						|
	    else
 | 
						|
		miFillEllipseD(pDraw, pGC, arc);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    if (miCanFillArc(arc))
 | 
						|
		miFillArcSliceI(pDraw, pGC, arc);
 | 
						|
	    else
 | 
						|
		miFillArcSliceD(pDraw, pGC, arc);
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 |