1/* 2 * 3 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard makes no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#ifdef HAVE_DIX_CONFIG_H 25#include <dix-config.h> 26#endif 27 28#include "scrnintstr.h" 29#include "gcstruct.h" 30#include "pixmapstr.h" 31#include "windowstr.h" 32#include "servermd.h" 33#include "mi.h" 34#include "picturestr.h" 35#include "mipict.h" 36 37PicturePtr 38miCreateAlphaPicture (ScreenPtr pScreen, 39 PicturePtr pDst, 40 PictFormatPtr pPictFormat, 41 CARD16 width, 42 CARD16 height) 43{ 44 PixmapPtr pPixmap; 45 PicturePtr pPicture; 46 GCPtr pGC; 47 int error; 48 xRectangle rect; 49 50 if (width > 32767 || height > 32767) 51 return 0; 52 53 if (!pPictFormat) 54 { 55 if (pDst->polyEdge == PolyEdgeSharp) 56 pPictFormat = PictureMatchFormat (pScreen, 1, PICT_a1); 57 else 58 pPictFormat = PictureMatchFormat (pScreen, 8, PICT_a8); 59 if (!pPictFormat) 60 return 0; 61 } 62 63 pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 64 pPictFormat->depth, 0); 65 if (!pPixmap) 66 return 0; 67 pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); 68 if (!pGC) 69 { 70 (*pScreen->DestroyPixmap) (pPixmap); 71 return 0; 72 } 73 ValidateGC (&pPixmap->drawable, pGC); 74 rect.x = 0; 75 rect.y = 0; 76 rect.width = width; 77 rect.height = height; 78 (*pGC->ops->PolyFillRect)(&pPixmap->drawable, pGC, 1, &rect); 79 FreeScratchGC (pGC); 80 pPicture = CreatePicture (0, &pPixmap->drawable, pPictFormat, 81 0, 0, serverClient, &error); 82 (*pScreen->DestroyPixmap) (pPixmap); 83 return pPicture; 84} 85 86static xFixed 87miLineFixedX (xLineFixed *l, xFixed y, Bool ceil) 88{ 89 xFixed dx = l->p2.x - l->p1.x; 90 xFixed_32_32 ex = (xFixed_32_32) (y - l->p1.y) * dx; 91 xFixed dy = l->p2.y - l->p1.y; 92 if (ceil) 93 ex += (dy - 1); 94 return l->p1.x + (xFixed) (ex / dy); 95} 96 97void 98miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box) 99{ 100 box->y1 = MAXSHORT; 101 box->y2 = MINSHORT; 102 box->x1 = MAXSHORT; 103 box->x2 = MINSHORT; 104 for (; ntrap; ntrap--, traps++) 105 { 106 INT16 x1, y1, x2, y2; 107 108 if (!xTrapezoidValid(traps)) 109 continue; 110 y1 = xFixedToInt (traps->top); 111 if (y1 < box->y1) 112 box->y1 = y1; 113 114 y2 = xFixedToInt (xFixedCeil (traps->bottom)); 115 if (y2 > box->y2) 116 box->y2 = y2; 117 118 x1 = xFixedToInt (min (miLineFixedX (&traps->left, traps->top, FALSE), 119 miLineFixedX (&traps->left, traps->bottom, FALSE))); 120 if (x1 < box->x1) 121 box->x1 = x1; 122 123 x2 = xFixedToInt (xFixedCeil (max (miLineFixedX (&traps->right, traps->top, TRUE), 124 miLineFixedX (&traps->right, traps->bottom, TRUE)))); 125 if (x2 > box->x2) 126 box->x2 = x2; 127 } 128} 129 130void 131miTrapezoids (CARD8 op, 132 PicturePtr pSrc, 133 PicturePtr pDst, 134 PictFormatPtr maskFormat, 135 INT16 xSrc, 136 INT16 ySrc, 137 int ntrap, 138 xTrapezoid *traps) 139{ 140 ScreenPtr pScreen = pDst->pDrawable->pScreen; 141 PictureScreenPtr ps = GetPictureScreen(pScreen); 142 143 /* 144 * Check for solid alpha add 145 */ 146 if (op == PictOpAdd && miIsSolidAlpha (pSrc)) 147 { 148 for (; ntrap; ntrap--, traps++) 149 (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); 150 } 151 else if (maskFormat) 152 { 153 PicturePtr pPicture; 154 BoxRec bounds; 155 INT16 xDst, yDst; 156 INT16 xRel, yRel; 157 158 xDst = traps[0].left.p1.x >> 16; 159 yDst = traps[0].left.p1.y >> 16; 160 161 miTrapezoidBounds (ntrap, traps, &bounds); 162 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) 163 return; 164 pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat, 165 bounds.x2 - bounds.x1, 166 bounds.y2 - bounds.y1); 167 if (!pPicture) 168 return; 169 for (; ntrap; ntrap--, traps++) 170 (*ps->RasterizeTrapezoid) (pPicture, traps, 171 -bounds.x1, -bounds.y1); 172 xRel = bounds.x1 + xSrc - xDst; 173 yRel = bounds.y1 + ySrc - yDst; 174 CompositePicture (op, pSrc, pPicture, pDst, 175 xRel, yRel, 0, 0, bounds.x1, bounds.y1, 176 bounds.x2 - bounds.x1, 177 bounds.y2 - bounds.y1); 178 FreePicture (pPicture, 0); 179 } 180 else 181 { 182 if (pDst->polyEdge == PolyEdgeSharp) 183 maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1); 184 else 185 maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8); 186 for (; ntrap; ntrap--, traps++) 187 miTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); 188 } 189} 190