105b261ecSmrg/*
205b261ecSmrg * Copyright © 1998 Keith Packard
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that
705b261ecSmrg * copyright notice and this permission notice appear in supporting
805b261ecSmrg * documentation, and that the name of Keith Packard not be used in
905b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1005b261ecSmrg * specific, written prior permission.  Keith Packard makes no
1105b261ecSmrg * representations about the suitability of this software for any purpose.  It
1205b261ecSmrg * is provided "as is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2105b261ecSmrg */
2205b261ecSmrg
2305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2405b261ecSmrg#include <dix-config.h>
2505b261ecSmrg#endif
2605b261ecSmrg
2705b261ecSmrg#include "fb.h"
2805b261ecSmrg#include "mizerarc.h"
2905b261ecSmrg#include <limits.h>
3005b261ecSmrg
3135c4bbdfSmrgtypedef void (*FbArc) (FbBits * dst,
3235c4bbdfSmrg                       FbStride dstStride,
3335c4bbdfSmrg                       int dstBpp,
3435c4bbdfSmrg                       xArc * arc, int dx, int dy, FbBits and, FbBits xor);
3505b261ecSmrg
3605b261ecSmrgvoid
3735c4bbdfSmrgfbPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs)
3805b261ecSmrg{
3935c4bbdfSmrg    FbArc arc;
4035c4bbdfSmrg
4135c4bbdfSmrg    if (pGC->lineWidth == 0) {
4235c4bbdfSmrg        arc = 0;
4335c4bbdfSmrg        if (pGC->lineStyle == LineSolid && pGC->fillStyle == FillSolid) {
4435c4bbdfSmrg            switch (pDrawable->bitsPerPixel) {
4535c4bbdfSmrg            case 8:
4635c4bbdfSmrg                arc = fbArc8;
4735c4bbdfSmrg                break;
4835c4bbdfSmrg            case 16:
4935c4bbdfSmrg                arc = fbArc16;
5035c4bbdfSmrg                break;
5135c4bbdfSmrg            case 32:
5235c4bbdfSmrg                arc = fbArc32;
5335c4bbdfSmrg                break;
5435c4bbdfSmrg            }
5535c4bbdfSmrg        }
5635c4bbdfSmrg        if (arc) {
5735c4bbdfSmrg            FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
5835c4bbdfSmrg            FbBits *dst;
5935c4bbdfSmrg            FbStride dstStride;
6035c4bbdfSmrg            int dstBpp;
6135c4bbdfSmrg            int dstXoff, dstYoff;
6235c4bbdfSmrg            BoxRec box;
6335c4bbdfSmrg            int x2, y2;
6435c4bbdfSmrg            RegionPtr cclip;
6535c4bbdfSmrg
664642e01fSmrg#ifdef FB_ACCESS_WRAPPER
6735c4bbdfSmrg            int wrapped = 1;
684642e01fSmrg#endif
6935c4bbdfSmrg
7035c4bbdfSmrg            cclip = fbGetCompositeClip(pGC);
7135c4bbdfSmrg            fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
7235c4bbdfSmrg            while (narcs--) {
7335c4bbdfSmrg                if (miCanZeroArc(parcs)) {
7435c4bbdfSmrg                    box.x1 = parcs->x + pDrawable->x;
7535c4bbdfSmrg                    box.y1 = parcs->y + pDrawable->y;
7635c4bbdfSmrg                    /*
7735c4bbdfSmrg                     * Because box.x2 and box.y2 get truncated to 16 bits, and the
7835c4bbdfSmrg                     * RECT_IN_REGION test treats the resulting number as a signed
7935c4bbdfSmrg                     * integer, the RECT_IN_REGION test alone can go the wrong way.
8035c4bbdfSmrg                     * This can result in a server crash because the rendering
8135c4bbdfSmrg                     * routines in this file deal directly with cpu addresses
8235c4bbdfSmrg                     * of pixels to be stored, and do not clip or otherwise check
8335c4bbdfSmrg                     * that all such addresses are within their respective pixmaps.
8435c4bbdfSmrg                     * So we only allow the RECT_IN_REGION test to be used for
8535c4bbdfSmrg                     * values that can be expressed correctly in a signed short.
8635c4bbdfSmrg                     */
8735c4bbdfSmrg                    x2 = box.x1 + (int) parcs->width + 1;
8835c4bbdfSmrg                    box.x2 = x2;
8935c4bbdfSmrg                    y2 = box.y1 + (int) parcs->height + 1;
9035c4bbdfSmrg                    box.y2 = y2;
9135c4bbdfSmrg                    if ((x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) &&
9235c4bbdfSmrg                        (RegionContainsRect(cclip, &box) == rgnIN)) {
934642e01fSmrg#ifdef FB_ACCESS_WRAPPER
9435c4bbdfSmrg                        if (!wrapped) {
9535c4bbdfSmrg                            fbPrepareAccess(pDrawable);
9635c4bbdfSmrg                            wrapped = 1;
9735c4bbdfSmrg                        }
984642e01fSmrg#endif
9935c4bbdfSmrg                        (*arc) (dst, dstStride, dstBpp,
10035c4bbdfSmrg                                parcs, pDrawable->x + dstXoff,
10135c4bbdfSmrg                                pDrawable->y + dstYoff, pPriv->and, pPriv->xor);
10235c4bbdfSmrg                    }
10335c4bbdfSmrg                    else {
1044642e01fSmrg#ifdef FB_ACCESS_WRAPPER
10535c4bbdfSmrg                        if (wrapped) {
10635c4bbdfSmrg                            fbFinishAccess(pDrawable);
10735c4bbdfSmrg                            wrapped = 0;
10835c4bbdfSmrg                        }
1094642e01fSmrg#endif
11035c4bbdfSmrg                        miZeroPolyArc(pDrawable, pGC, 1, parcs);
11135c4bbdfSmrg                    }
11235c4bbdfSmrg                }
11335c4bbdfSmrg                else {
1144642e01fSmrg#ifdef FB_ACCESS_WRAPPER
11535c4bbdfSmrg                    if (wrapped) {
11635c4bbdfSmrg                        fbFinishAccess(pDrawable);
11735c4bbdfSmrg                        wrapped = 0;
11835c4bbdfSmrg                    }
1194642e01fSmrg#endif
12035c4bbdfSmrg                    miPolyArc(pDrawable, pGC, 1, parcs);
12135c4bbdfSmrg                }
12235c4bbdfSmrg                parcs++;
12335c4bbdfSmrg            }
1244642e01fSmrg#ifdef FB_ACCESS_WRAPPER
12535c4bbdfSmrg            if (wrapped) {
12635c4bbdfSmrg                fbFinishAccess(pDrawable);
12735c4bbdfSmrg                wrapped = 0;
12835c4bbdfSmrg            }
12905b261ecSmrg#endif
13035c4bbdfSmrg        }
13135c4bbdfSmrg        else
13235c4bbdfSmrg            miZeroPolyArc(pDrawable, pGC, narcs, parcs);
13305b261ecSmrg    }
13405b261ecSmrg    else
13535c4bbdfSmrg        miPolyArc(pDrawable, pGC, narcs, parcs);
13605b261ecSmrg}
137