Edit

IABSD.fr/xenocara/lib/libXrender/src/Poly.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2022-11-06 17:49:17
    Hash : 3b0b5ae7
    Message : Update libXrender to version 0.9.11

  • lib/libXrender/src/Poly.c
  • /*
     *
     * Copyright © 2002 Keith Packard
     *
     * 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, and that the name of Keith Packard not be used in
     * advertising or publicity pertaining to distribution of the software without
     * specific, written prior permission.  Keith Packard makes no
     * representations about the suitability of this software for any purpose.  It
     * is provided "as is" without express or implied warranty.
     *
     * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     * PERFORMANCE OF THIS SOFTWARE.
     */
    
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    #include "Xrenderint.h"
    
    typedef struct _Edge Edge;
    
    struct _Edge {
        XLineFixed	edge;
        XFixed	current_x;
        Bool	clockWise;
        Edge	*next, *prev;
    };
    
    static int
    CompareEdge (const void *o1, const void *o2)
    {
        const Edge	*e1 = o1, *e2 = o2;
    
        return e1->edge.p1.y - e2->edge.p1.y;
    }
    
    static XFixed
    XRenderComputeX (XLineFixed *line, XFixed y)
    {
        XFixed  dx = line->p2.x - line->p1.x;
        double  ex = (double) (y - line->p1.y) * (double) dx;
        XFixed  dy = line->p2.y - line->p1.y;
    
        return (XFixed) line->p1.x + (XFixed) (ex / dy);
    }
    
    static double
    XRenderComputeInverseSlope (XLineFixed *l)
    {
        return (XFixedToDouble (l->p2.x - l->p1.x) /
    	    XFixedToDouble (l->p2.y - l->p1.y));
    }
    
    static double
    XRenderComputeXIntercept (XLineFixed *l, double inverse_slope)
    {
        return XFixedToDouble (l->p1.x) - inverse_slope * XFixedToDouble (l->p1.y);
    }
    
    static XFixed
    XRenderComputeIntersect (XLineFixed *l1, XLineFixed *l2)
    {
        /*
         * x = m1y + b1
         * x = m2y + b2
         * m1y + b1 = m2y + b2
         * y * (m1 - m2) = b2 - b1
         * y = (b2 - b1) / (m1 - m2)
         */
        double  m1 = XRenderComputeInverseSlope (l1);
        double  b1 = XRenderComputeXIntercept (l1, m1);
        double  m2 = XRenderComputeInverseSlope (l2);
        double  b2 = XRenderComputeXIntercept (l2, m2);
    
        if ( m1 == m2 ) return XDoubleToFixed(32766); /* lines don't intersect */
    
        return XDoubleToFixed ((b2 - b1) / (m1 - m2));
    }
    
    static int
    XRenderComputeTrapezoids (Edge		*edges,
    			  int		nedges,
    			  int		winding _X_UNUSED,
    			  XTrapezoid	*traps,
    			  int           *ntraps,
    			  int           maxtraps)
    {
        int		ok = 1, inactive;
        Edge	*active;
        Edge	*e, *en, *next;
        XFixed	y, next_y, intersect;
    
        qsort (edges, (size_t) nedges, sizeof (Edge), CompareEdge);
    
        *ntraps = 0;
        y = edges[0].edge.p1.y;
        active = NULL;
        inactive = 0;
        while (active || inactive < nedges)
        {
    	/* insert new active edges into list */
    	while (inactive < nedges)
    	{
    	    e = &edges[inactive];
    	    if (e->edge.p1.y > y)
    		break;
    	    /* move this edge into the active list */
    	    inactive++;
    	    e->next = active;
    	    e->prev = NULL;
    	    if (active)
    		active->prev = e;
    	    active = e;
    	}
    	/* compute x coordinates along this group */
    	for (e = active; e; e = e->next)
    	    e->current_x = XRenderComputeX (&e->edge, y);
    
    	/* sort active list */
    	for (e = active; e; e = next)
    	{
    	    next = e->next;
    	    /*
    	     * Find one later in the list that belongs before the
    	     * current one
    	     */
    	    for (en = next; en; en = en->next)
    	    {
    		if (en->current_x < e->current_x ||
    		    (en->current_x == e->current_x &&
    		     en->edge.p2.x < e->edge.p2.x))
    		{
    		    /*
    		     * insert en before e
    		     *
    		     * extract en
    		     */
    		    en->prev->next = en->next;
    		    if (en->next)
    			en->next->prev = en->prev;
    		    /*
    		     * insert en
    		     */
    		    if (e->prev)
    			e->prev->next = en;
    		    else
    			active = en;
    		    en->prev = e->prev;
    		    e->prev = en;
    		    en->next = e;
    		    /*
    		     * start over at en
    		     */
    		    next = en;
    		    break;
    		}
    	    }
    	}
    #if 0
    	printf ("y: %6.3g:", y / 65536.0);
    	for (e = active; e; e = e->next)
    	{
    	    printf (" %6.3g", e->current_x / 65536.0);
    	}
    	printf ("\n");
    #endif
    	/* find next inflection point */
    	next_y = active->edge.p2.y;
    	for (e = active; e; e = en)
    	{
    	    if (e->edge.p2.y < next_y)
    		next_y = e->edge.p2.y;
    	    en = e->next;
    	    /* check intersect */
    	    if (en && e->edge.p2.x > en->edge.p2.x)
    	    {
    		intersect = XRenderComputeIntersect (&e->edge, &e->next->edge);
    		/* make sure this point is below the actual intersection */
    		intersect = intersect + 1;
    		if (intersect < next_y && intersect > y)
    		    next_y = intersect;
    	    }
    	}
    	/* check next inactive point */
    	if (inactive < nedges && edges[inactive].edge.p1.y < next_y)
    	    next_y = edges[inactive].edge.p1.y;
    
    	/* walk the list generating trapezoids */
    	for (e = active; e && (en = e->next); e = en->next)
    	{
    	    traps->top = y;
    	    traps->bottom = next_y;
    	    traps->left = e->edge;
    	    traps->right = en->edge;
    	    traps++;
    	    (*ntraps)++;
                if ( --maxtraps <= 0 ) {
    	       ok = 0;
    	       break;
    	    }
    	}
    
    	y = next_y;
    
    	/* delete inactive edges from list */
    	for (e = active; e; e = next)
    	{
    	    next = e->next;
    	    if (e->edge.p2.y <= y)
    	    {
    		if (e->prev)
    		    e->prev->next = e->next;
    		else
    		    active = e->next;
    		if (e->next)
    		    e->next->prev = e->prev;
    	    }
    	}
        }
        return ok;
    }
    
    void
    XRenderCompositeDoublePoly (Display		    *dpy,
    			    int			    op,
    			    Picture		    src,
    			    Picture		    dst,
    			    _Xconst XRenderPictFormat	*maskFormat,
    			    int			    xSrc,
    			    int			    ySrc,
    			    int			    xDst _X_UNUSED,
    			    int			    yDst _X_UNUSED,
    			    _Xconst XPointDouble    *fpoints,
    			    int			    npoints,
    			    int			    winding)
    {
        Edge	    *edges;
        XTrapezoid	    *traps;
        int		    i, nedges, ntraps;
        XFixed	    prevx = 0, prevy = 0, firstx = 0, firsty = 0;
        XFixed	    top = 0, bottom = 0;	/* GCCism */
    
        edges = Xmalloc (((size_t) npoints * sizeof (Edge)) +
                         ((size_t) (npoints * npoints) * sizeof (XTrapezoid)));
        if (!edges)
    	return;
        traps = (XTrapezoid *) (edges + npoints);
        nedges = 0;
        for (i = 0; i <= npoints; i++)
        {
    	XFixed	x, y;
    
    	if (i == npoints)
    	{
    	    x = firstx;
    	    y = firsty;
    	}
    	else
    	{
    	    x = XDoubleToFixed (fpoints[i].x);
    	    y = XDoubleToFixed (fpoints[i].y);
    	}
    	if (i)
    	{
    	    if (y < top)
    		top = y;
    	    else if (y > bottom)
    		bottom = y;
    	    if (prevy < y)
    	    {
    		edges[nedges].edge.p1.x = prevx;
    		edges[nedges].edge.p1.y = prevy;
    		edges[nedges].edge.p2.x = x;
    		edges[nedges].edge.p2.y = y;
    		edges[nedges].clockWise = True;
    		nedges++;
    	    }
    	    else if (prevy > y)
    	    {
    		edges[nedges].edge.p1.x = x;
    		edges[nedges].edge.p1.y = y;
    		edges[nedges].edge.p2.x = prevx;
    		edges[nedges].edge.p2.y = prevy;
    		edges[nedges].clockWise = False;
    		nedges++;
    	    }
    	    /* drop horizontal edges */
    	}
    	else
    	{
    	    top = y;
    	    bottom = y;
    	    firstx = x;
    	    firsty = y;
    	}
    	prevx = x;
    	prevy = y;
        }
        if ( XRenderComputeTrapezoids (edges, nedges, winding, traps, &ntraps, npoints * npoints )) {
           /* XXX adjust xSrc/xDst */
           XRenderCompositeTrapezoids (dpy, op, src, dst, maskFormat, xSrc, ySrc, traps, ntraps);
        }
        Xfree (edges);
    }