mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-17 00:28:54 -04:00
361 lines
8.2 KiB
C
361 lines
8.2 KiB
C
/* $NetBSD: pxfillsp.c,v 1.2 2008/04/28 20:57:37 martin Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
* by Andrew Doran.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "px.h"
|
|
|
|
#include "pixmapstr.h"
|
|
#include "scrnintstr.h"
|
|
|
|
#include "cfb.h"
|
|
#include "mi.h"
|
|
#include "mispans.h"
|
|
|
|
void
|
|
pxFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt,
|
|
int *pwidth, int fSorted)
|
|
{
|
|
pxPrivGCPtr gcPriv;
|
|
int *pwidthFree, nTmp;
|
|
DDXPointPtr pptFree;
|
|
RegionPtr clip;
|
|
BoxPtr pOneBox;
|
|
|
|
PX_TRACE("pxFillSpans");
|
|
|
|
clip = cfbGetCompositeClip(pGC);
|
|
|
|
switch (REGION_NUM_RECTS(clip)) {
|
|
case 0:
|
|
return;
|
|
|
|
case 1:
|
|
pOneBox = &clip->extents;
|
|
break;
|
|
|
|
default:
|
|
nTmp = n * miFindMaxBand(clip);
|
|
|
|
pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
|
|
pptFree =
|
|
(DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
|
|
if (!pptFree || !pwidthFree) {
|
|
if (pptFree)
|
|
DEALLOCATE_LOCAL(pptFree);
|
|
if (pwidthFree)
|
|
DEALLOCATE_LOCAL(pwidthFree);
|
|
return;
|
|
}
|
|
n = miClipSpans(clip, ppt, pwidth, n, pptFree, pwidthFree,
|
|
fSorted);
|
|
pwidth = pwidthFree;
|
|
ppt = pptFree;
|
|
pOneBox = NULL;
|
|
break;
|
|
}
|
|
|
|
if (n != 0) {
|
|
gcPriv = pxGetGCPrivate(pGC);
|
|
(*gcPriv->doFillSpans)(pDrawable, pGC, gcPriv, pOneBox, n,
|
|
ppt, pwidth);
|
|
}
|
|
|
|
if (pOneBox == NULL) {
|
|
DEALLOCATE_LOCAL(pptFree);
|
|
DEALLOCATE_LOCAL(pwidthFree);
|
|
}
|
|
}
|
|
|
|
void
|
|
pxDoFillSpans(DrawablePtr pDrawable, GCPtr pGC, pxPrivGCPtr gcPriv,
|
|
BoxPtr pOneBox, int n, DDXPointPtr ppt, int *pwidth)
|
|
{
|
|
pxScreenPrivPtr sp;
|
|
DDXPointPtr pptmax;
|
|
int psy, x, y, w, h;
|
|
u_int32_t *pb;
|
|
pxPacket pxp;
|
|
|
|
PX_TRACE("pxDoFillSpans");
|
|
|
|
sp = gcPriv->sp;
|
|
|
|
pb = pxPacketStart(sp, &pxp, 5, 3);
|
|
pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPRIMATIVE;
|
|
pb[1] = gcPriv->pmask;
|
|
pb[2] = 0;
|
|
pb[3] = gcPriv->umet;
|
|
pb[4] = gcPriv->fgFill;
|
|
|
|
for (pptmax = ppt + n; ppt < pptmax; ppt++, pwidth++) {
|
|
w = pwidth[0];
|
|
x = ppt[0].x;
|
|
y = ppt[0].y;
|
|
|
|
if (pOneBox != NULL) {
|
|
if (y < pOneBox->y1 || y >= pOneBox->y2)
|
|
continue;
|
|
if (x < pOneBox->x1) {
|
|
w -= (pOneBox->x1 - x);
|
|
if (w <= 0)
|
|
continue;
|
|
x = pOneBox->x1;
|
|
}
|
|
if (x + w > pOneBox->x2) {
|
|
if (x >= pOneBox->x2)
|
|
continue;
|
|
w = pOneBox->x2 - x;
|
|
}
|
|
}
|
|
|
|
for (h = 1; h < 17; h++, ppt++, pwidth++) {
|
|
if (ppt + 1 == pptmax)
|
|
break;
|
|
if (ppt[1].x != x || pwidth[1] != w ||
|
|
ppt[1].y != y + 1)
|
|
break;
|
|
}
|
|
|
|
h = (h << 2) - 1;
|
|
psy = (y << 3) + h;
|
|
|
|
pb = pxPacketAddPrim(sp, &pxp);
|
|
pb[0] = (x << 19) | psy;
|
|
pb[1] = ((x + w) << 19) | psy;
|
|
pb[2] = h;
|
|
}
|
|
|
|
pxPacketFlush(sp, &pxp);
|
|
}
|
|
|
|
void
|
|
pxDoFillSpansS(DrawablePtr pDrawable, GCPtr pGC, pxPrivGCPtr gcPriv,
|
|
BoxPtr pOneBox, int n, DDXPointPtr ppt, int *pwidth)
|
|
{
|
|
int v1, v2, psy, x, y, w, xya, stampw, stamphm, xorg, yorg, h;
|
|
DDXPointPtr pptmax;
|
|
pxScreenPrivPtr sp;
|
|
u_int32_t *pb, *mask;
|
|
pxPacket pxp;
|
|
|
|
PX_TRACE("pxDoFillSpansS");
|
|
|
|
mask = (u_int32_t *)gcPriv->mask.data;
|
|
sp = gcPriv->sp;
|
|
stampw = sp->stampw;
|
|
stamphm = sp->stamphm;
|
|
|
|
pb = pxPacketStart(sp, &pxp, 4, 13);
|
|
pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_LW_PERPRIMATIVE |
|
|
STAMP_XY_PERPRIMATIVE;
|
|
pb[1] = gcPriv->pmask;
|
|
pb[2] = 0;
|
|
pb[3] = gcPriv->umet | STAMP_WE_XYMASK;
|
|
|
|
for (pptmax = ppt + n; ppt < pptmax; ppt++, pwidth++) {
|
|
w = pwidth[0];
|
|
x = ppt[0].x;
|
|
y = ppt[0].y;
|
|
|
|
if (pOneBox != NULL) {
|
|
if (y < pOneBox->y1 || y >= pOneBox->y2)
|
|
continue;
|
|
if (x < pOneBox->x1) {
|
|
w -= (pOneBox->x1 - x);
|
|
if (w <= 0)
|
|
continue;
|
|
x = pOneBox->x1;
|
|
}
|
|
if (x + w > pOneBox->x2) {
|
|
if (x >= pOneBox->x2)
|
|
continue;
|
|
w = pOneBox->x2 - x;
|
|
}
|
|
}
|
|
|
|
for (h = 1; h < 17; h++, ppt++, pwidth++) {
|
|
if (ppt + 1 == pptmax)
|
|
break;
|
|
if (ppt[1].x != x || pwidth[1] != w ||
|
|
ppt[1].y != y + 1)
|
|
break;
|
|
}
|
|
|
|
xorg = (x - pGC->patOrg.x - pDrawable->x) & 15;
|
|
yorg = (y - pGC->patOrg.y - pDrawable->y) & 15;
|
|
|
|
xya = XYMASKADDR(stampw, stamphm, x, y, xorg, yorg);
|
|
h = (h << 2) - 1;
|
|
psy = (y << 3) + h;
|
|
v1 = (x << 19) | psy;
|
|
v2 = ((x + w) << 19) | psy;
|
|
|
|
if (gcPriv->fillStyle != FillStippled) {
|
|
pb = pxPacketAddPrim(sp, &pxp);
|
|
pb[0] = ~mask[0];
|
|
pb[1] = ~mask[1];
|
|
pb[2] = ~mask[2];
|
|
pb[3] = ~mask[3];
|
|
pb[4] = ~mask[4];
|
|
pb[5] = ~mask[5];
|
|
pb[6] = ~mask[6];
|
|
pb[7] = ~mask[7];
|
|
pb[8] = xya;
|
|
pb[9] = v1;
|
|
pb[10] = v2;
|
|
pb[11] = h;
|
|
pb[12] = gcPriv->bgPixel;
|
|
}
|
|
|
|
pb = pxPacketAddPrim(sp, &pxp);
|
|
pb[0] = mask[0];
|
|
pb[1] = mask[1];
|
|
pb[2] = mask[2];
|
|
pb[3] = mask[3];
|
|
pb[4] = mask[4];
|
|
pb[5] = mask[5];
|
|
pb[6] = mask[6];
|
|
pb[7] = mask[7];
|
|
pb[8] = xya;
|
|
pb[9] = v1;
|
|
pb[10] = v2;
|
|
pb[11] = h;
|
|
pb[12] = gcPriv->fgFill;
|
|
}
|
|
|
|
pxPacketFlush(sp, &pxp);
|
|
}
|
|
|
|
void
|
|
pxDoFillSpansT(DrawablePtr pDrawable, GCPtr pGC, pxPrivGCPtr gcPriv,
|
|
BoxPtr pOneBox, int n, DDXPointPtr ppt, int *pwidth)
|
|
{
|
|
pxScreenPrivPtr sp;
|
|
DDXPointPtr pptmax;
|
|
int x, y, w, xorg, yorg, tbp, tw;
|
|
pxImgBufPtr ib;
|
|
PixmapPtr pix;
|
|
void *p;
|
|
|
|
PX_TRACE("pxDoFillSpansT");
|
|
|
|
sp = gcPriv->sp;
|
|
pix = pGC->tile.pixmap;
|
|
|
|
for (pptmax = ppt + n; ppt < pptmax; ppt++) {
|
|
w = *pwidth++;
|
|
x = ppt->x;
|
|
y = ppt->y;
|
|
|
|
if (pOneBox != NULL) {
|
|
if (y < pOneBox->y1 || y >= pOneBox->y2)
|
|
continue;
|
|
if (x < pOneBox->x1) {
|
|
w -= (pOneBox->x1 - x);
|
|
if (w <= 0)
|
|
continue;
|
|
x = pOneBox->x1;
|
|
}
|
|
if (x + w > pOneBox->x2) {
|
|
if (x >= pOneBox->x2)
|
|
continue;
|
|
w = pOneBox->x2 - x;
|
|
}
|
|
}
|
|
|
|
ib = pxAllocImgBuf(sp);
|
|
|
|
xorg = x - pGC->patOrg.x - pDrawable->x;
|
|
yorg = y - pGC->patOrg.y - pDrawable->y;
|
|
|
|
tbp = pix->drawable.bitsPerPixel >> 3;
|
|
tw = pix->drawable.width;
|
|
p = (caddr_t)pix->devPrivate.ptr +
|
|
(yorg % pix->drawable.height + pix->drawable.y) * pix->devKind +
|
|
(pix->drawable.x * tbp);
|
|
|
|
(*sp->tileBuf)(ib->ptr, p, w, tw, xorg % tw);
|
|
pxSetScanlineRaw(sp, x, y, w, gcPriv->umet, gcPriv->pmask, ib);
|
|
}
|
|
}
|
|
|
|
void
|
|
pxDoFillSpansUS(DrawablePtr pDrawable, GCPtr pGC, pxPrivGCPtr gcPriv,
|
|
BoxPtr pOneBox, int n, DDXPointPtr ppt, int *pwidth)
|
|
{
|
|
pxScreenPrivPtr sp;
|
|
DDXPointPtr pptmax;
|
|
int x, y, w, xorg, yorg;
|
|
pxImgBufPtr ib;
|
|
|
|
PX_TRACE("pxDoFillSpansUS");
|
|
|
|
sp = gcPriv->sp;
|
|
|
|
for (pptmax = ppt + n; ppt < pptmax; ppt++) {
|
|
w = *pwidth++;
|
|
x = ppt->x;
|
|
y = ppt->y;
|
|
|
|
if (pOneBox != NULL) {
|
|
if (y < pOneBox->y1 || y >= pOneBox->y2)
|
|
continue;
|
|
if (x < pOneBox->x1) {
|
|
w -= (pOneBox->x1 - x);
|
|
if (w <= 0)
|
|
continue;
|
|
x = pOneBox->x1;
|
|
}
|
|
if (x + w > pOneBox->x2) {
|
|
if (x >= pOneBox->x2)
|
|
continue;
|
|
w = pOneBox->x2 - x;
|
|
}
|
|
}
|
|
|
|
ib = pxAllocImgBuf(sp);
|
|
|
|
xorg = x - pGC->patOrg.x - pDrawable->x;
|
|
yorg = y - pGC->patOrg.y - pDrawable->y;
|
|
|
|
if (gcPriv->fillStyle == FillStippled) {
|
|
pxGetScanlineRaw(sp, x, y, w, ib);
|
|
pxStippleBuf(pGC->stipple, ib->ptr, w, pGC->fillStyle,
|
|
gcPriv->fgFill, gcPriv->bgPixel, xorg, yorg);
|
|
} else {
|
|
pxStippleBufOpaque(pGC->stipple, ib->ptr, w,
|
|
pGC->fillStyle, gcPriv->fgFill, gcPriv->bgPixel,
|
|
xorg, yorg);
|
|
}
|
|
pxSetScanlineRaw(sp, x, y, w, gcPriv->umet, gcPriv->pmask,
|
|
ib);
|
|
}
|
|
}
|