blob: c953a0c991e59bea5479a82fba81a51c577d2f6e [file] [log] [blame]
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
- This software is distributed in the hope that it will be
- useful, but with NO WARRANTY OF ANY KIND.
- No author or distributor accepts responsibility to anyone for the
- consequences of using this software, or for whether it serves any
- particular purpose or works at all, unless he or she says so in
- writing. Everyone is granted permission to copy, modify and
- redistribute this source code, for commercial or non-commercial
- purposes, with the following restrictions: (1) the origin of this
- source code must not be misrepresented; (2) modified versions must
- be plainly marked as such; and (3) this notice may not be removed
- or altered from any source or modified source distribution.
*====================================================================*/
/*
* roplow.c
*
* Low level dest-only
* void rasteropUniLow()
* static void rasteropUniWordAlignedlLow()
* static void rasteropUniGeneralLow()
*
* Low level src and dest
* void rasteropLow()
* static void rasteropWordAlignedLow()
* static void rasteropVAlignedLow()
* static void rasteropGeneralLow()
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "allheaders.h"
#define COMBINE_PARTIAL(d, s, m) ( ((d) & ~(m)) | ((s) & (m)) )
static const l_int32 SHIFT_LEFT = 0;
static const l_int32 SHIFT_RIGHT = 1;
static void rasteropUniWordAlignedLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
l_int32 dy, l_int32 dw, l_int32 dh,
l_int32 op);
static void rasteropUniGeneralLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
l_int32 dy, l_int32 dw, l_int32 dh,
l_int32 op);
static void rasteropWordAlignedLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
l_int32 dy, l_int32 dw, l_int32 dh,
l_int32 op, l_uint32 *datas, l_int32 swpl,
l_int32 sx, l_int32 sy);
static void rasteropVAlignedLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
l_int32 dy, l_int32 dw, l_int32 dh,
l_int32 op, l_uint32 *datas, l_int32 swpl,
l_int32 sx, l_int32 sy);
static void rasteropGeneralLow(l_uint32 *datad, l_int32 dwpl, l_int32 dx,
l_int32 dy, l_int32 dw, l_int32 dh,
l_int32 op, l_uint32 *datas, l_int32 swpl,
l_int32 sx, l_int32 sy);
static const l_uint32 lmask32[] = {0x0,
0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff};
static const l_uint32 rmask32[] = {0x0,
0x00000001, 0x00000003, 0x00000007, 0x0000000f,
0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};
/*--------------------------------------------------------------------*
* Low-level dest-only rasterops *
*--------------------------------------------------------------------*/
/*!
* rasteropUniLow()
*
* Input: datad (ptr to dest image data)
* dpixw (width of dest)
* dpixh (height of dest)
* depth (depth of src and dest)
* dwpl (wpl of dest)
* dx (x val of UL corner of dest rectangle)
* dy (y val of UL corner of dest rectangle)
* dw (width of dest rectangle)
* dh (height of dest rectangle)
* op (op code)
* Return: void
*
* Action: scales width, performs clipping, checks alignment, and
* dispatches for the rasterop.
*/
void
rasteropUniLow(l_uint32 *datad,
l_int32 dpixw,
l_int32 dpixh,
l_int32 depth,
l_int32 dwpl,
l_int32 dx,
l_int32 dy,
l_int32 dw,
l_int32 dh,
l_int32 op)
{
l_int32 dhangw, dhangh;
/* -------------------------------------------------------*
* scale horizontal dimensions by depth
* -------------------------------------------------------*/
if (depth != 1) {
dpixw *= depth;
dx *= depth;
dw *= depth;
}
/* -------------------------------------------------------*
* clip rectangle to dest image
* -------------------------------------------------------*/
/* first, clip horizontally (dx, dw) */
if (dx < 0) {
dw += dx; /* reduce dw */
dx = 0;
}
dhangw = dx + dw - dpixw; /* rect ovhang dest to right */
if (dhangw > 0)
dw -= dhangw; /* reduce dw */
/* then, clip vertically (dy, dh) */
if (dy < 0) {
dh += dy; /* reduce dh */
dy = 0;
}
dhangh = dy + dh - dpixh; /* rect ovhang dest below */
if (dhangh > 0)
dh -= dhangh; /* reduce dh */
/* if clipped entirely, quit */
if ((dw <= 0) || (dh <= 0))
return;
/* -------------------------------------------------------*
* dispatch to aligned or non-aligned blitters
* -------------------------------------------------------*/
if ((dx & 31) == 0)
rasteropUniWordAlignedLow(datad, dwpl, dx, dy, dw, dh, op);
else
rasteropUniGeneralLow(datad, dwpl, dx, dy, dw, dh, op);
return;
}
/*--------------------------------------------------------------------*
* Static low-level uni rasterop with word alignment *
*--------------------------------------------------------------------*/
/*!
* rasteropUniWordAlignedLow()
*
* Input: datad (ptr to dest image data)
* dwpl (wpl of dest)
* dx (x val of UL corner of dest rectangle)
* dy (y val of UL corner of dest rectangle)
* dw (width of dest rectangle)
* dh (height of dest rectangle)
* op (op code)
* Return: void
*
* This is called when the dest rect is left aligned
* on (32-bit) word boundaries. That is: dx & 31 == 0.
*
* We make an optimized implementation of this because
* it is a common case: e.g., operating on a full dest image.
*/
static void
rasteropUniWordAlignedLow(l_uint32 *datad,
l_int32 dwpl,
l_int32 dx,
l_int32 dy,
l_int32 dw,
l_int32 dh,
l_int32 op)
{
l_int32 nfullw; /* number of full words */
l_uint32 *pfword; /* ptr to first word */
l_int32 lwbits; /* number of ovrhang bits in last partial word */
l_uint32 lwmask; /* mask for last partial word */
l_uint32 *lined;
l_int32 i, j;
/*--------------------------------------------------------*
* Preliminary calculations *
*--------------------------------------------------------*/
nfullw = dw >> 5;
lwbits = dw & 31;
if (lwbits)
lwmask = lmask32[lwbits];
pfword = datad + dwpl * dy + (dx >> 5);
/*--------------------------------------------------------*
* Now we're ready to do the ops *
*--------------------------------------------------------*/
switch (op)
{
case PIX_CLR:
for (i = 0; i < dh; i++) {
lined = pfword + i * dwpl;
for (j = 0; j < nfullw; j++)
*lined++ = 0x0;
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, 0x0, lwmask);
}
break;
case PIX_SET:
for (i = 0; i < dh; i++) {
lined = pfword + i * dwpl;
for (j = 0; j < nfullw; j++)
*lined++ = 0xffffffff;
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, 0xffffffff, lwmask);
}
break;
case PIX_NOT(PIX_DST):
for (i = 0; i < dh; i++) {
lined = pfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = ~(*lined);
lined++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, ~(*lined), lwmask);
}
break;
default:
fprintf(stderr, "Operation %d not permitted here!\n", op);
}
return;
}
/*--------------------------------------------------------------------*
* Static low-level uni rasterop without word alignment *
*--------------------------------------------------------------------*/
/*!
* rasteropUniGeneralLow()
*
* Input: datad (ptr to dest image data)
* dwpl (wpl of dest)
* dx (x val of UL corner of dest rectangle)
* dy (y val of UL corner of dest rectangle)
* dw (width of dest rectangle)
* dh (height of dest rectangle)
* op (op code)
* Return: void
*/
static void
rasteropUniGeneralLow(l_uint32 *datad,
l_int32 dwpl,
l_int32 dx,
l_int32 dy,
l_int32 dw,
l_int32 dh,
l_int32 op)
{
l_int32 dfwpartb; /* boolean (1, 0) if first dest word is partial */
l_int32 dfwpart2b; /* boolean (1, 0) if first dest word is doubly partial */
l_uint32 dfwmask; /* mask for first partial dest word */
l_int32 dfwbits; /* first word dest bits in ovrhang */
l_uint32 *pdfwpart; /* ptr to first partial dest word */
l_int32 dfwfullb; /* boolean (1, 0) if there exists a full dest word */
l_int32 dnfullw; /* number of full words in dest */
l_uint32 *pdfwfull; /* ptr to first full dest word */
l_int32 dlwpartb; /* boolean (1, 0) if last dest word is partial */
l_uint32 dlwmask; /* mask for last partial dest word */
l_int32 dlwbits; /* last word dest bits in ovrhang */
l_uint32 *pdlwpart; /* ptr to last partial dest word */
l_int32 i, j;
/*--------------------------------------------------------*
* Preliminary calculations *
*--------------------------------------------------------*/
/* is the first word partial? */
if ((dx & 31) == 0) { /* if not */
dfwpartb = 0;
dfwbits = 0;
}
else { /* if so */
dfwpartb = 1;
dfwbits = 32 - (dx & 31);
dfwmask = rmask32[dfwbits];
pdfwpart = datad + dwpl * dy + (dx >> 5);
}
/* is the first word doubly partial? */
if (dw >= dfwbits) /* if not */
dfwpart2b = 0;
else { /* if so */
dfwpart2b = 1;
dfwmask &= lmask32[32 - dfwbits + dw];
}
/* is there a full dest word? */
if (dfwpart2b == 1) { /* not */
dfwfullb = 0;
dnfullw = 0;
}
else {
dnfullw = (dw - dfwbits) >> 5;
if (dnfullw == 0) /* if not */
dfwfullb = 0;
else { /* if so */
dfwfullb = 1;
if (dfwpartb)
pdfwfull = pdfwpart + 1;
else
pdfwfull = datad + dwpl * dy + (dx >> 5);
}
}
/* is the last word partial? */
dlwbits = (dx + dw) & 31;
if (dfwpart2b == 1 || dlwbits == 0) /* if not */
dlwpartb = 0;
else {
dlwpartb = 1;
dlwmask = lmask32[dlwbits];
if (dfwpartb)
pdlwpart = pdfwpart + 1 + dnfullw;
else
pdlwpart = datad + dwpl * dy + (dx >> 5) + dnfullw;
}
/*--------------------------------------------------------*
* Now we're ready to do the ops *
*--------------------------------------------------------*/
switch (op)
{
case PIX_CLR:
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart, 0x0, dfwmask);
pdfwpart += dwpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = 0x0;
pdfwfull += dwpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart, 0x0, dlwmask);
pdlwpart += dwpl;
}
}
break;
case PIX_SET:
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart, 0xffffffff, dfwmask);
pdfwpart += dwpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = 0xffffffff;
pdfwfull += dwpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart, 0xffffffff, dlwmask);
pdlwpart += dwpl;
}
}
break;
case PIX_NOT(PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart, ~(*pdfwpart), dfwmask);
pdfwpart += dwpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = ~(*(pdfwfull + j));
pdfwfull += dwpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart, ~(*pdlwpart), dlwmask);
pdlwpart += dwpl;
}
}
break;
default:
fprintf(stderr, "Operation %d not permitted here!\n", op);
}
return;
}
/*--------------------------------------------------------------------*
* Low-level src and dest rasterops *
*--------------------------------------------------------------------*/
/*!
* rasteropLow()
*
* Input: datad (ptr to dest image data)
* dpixw (width of dest)
* dpixh (height of dest)
* depth (depth of src and dest)
* dwpl (wpl of dest)
* dx (x val of UL corner of dest rectangle)
* dy (y val of UL corner of dest rectangle)
* dw (width of dest rectangle)
* dh (height of dest rectangle)
* op (op code)
* datas (ptr to src image data)
* spixw (width of src)
* spixh (height of src)
* swpl (wpl of src)
* sx (x val of UL corner of src rectangle)
* sy (y val of UL corner of src rectangle)
* Return: void
*
* Action: Scales width, performs clipping, checks alignment, and
* dispatches for the rasterop.
*
* Warning: the two images must have equal depth. This is not checked.
*/
void
rasteropLow(l_uint32 *datad,
l_int32 dpixw,
l_int32 dpixh,
l_int32 depth,
l_int32 dwpl,
l_int32 dx,
l_int32 dy,
l_int32 dw,
l_int32 dh,
l_int32 op,
l_uint32 *datas,
l_int32 spixw,
l_int32 spixh,
l_int32 swpl,
l_int32 sx,
l_int32 sy)
{
l_int32 dhangw, shangw, dhangh, shangh;
/* -------------------------------------------------------*
* scale horizontal dimensions by depth
* -------------------------------------------------------*/
if (depth != 1) {
dpixw *= depth;
dx *= depth;
dw *= depth;
spixw *= depth;
sx *= depth;
}
/* -------------------------------------------------------*
* clip to max rectangle within both src and dest
* -------------------------------------------------------*/
/* first, clip horizontally (sx, dx, dw) */
if (dx < 0) {
sx -= dx; /* increase sx */
dw += dx; /* reduce dw */
dx = 0;
}
if (sx < 0) {
dx -= sx; /* increase dx */
dw += sx; /* reduce dw */
sx = 0;
}
dhangw = dx + dw - dpixw; /* rect ovhang dest to right */
if (dhangw > 0)
dw -= dhangw; /* reduce dw */
shangw = sx + dw - spixw; /* rect ovhang src to right */
if (shangw > 0)
dw -= shangw; /* reduce dw */
/* then, clip vertically (sy, dy, dh) */
if (dy < 0) {
sy -= dy; /* increase sy */
dh += dy; /* reduce dh */
dy = 0;
}
if (sy < 0) {
dy -= sy; /* increase dy */
dh += sy; /* reduce dh */
sy = 0;
}
dhangh = dy + dh - dpixh; /* rect ovhang dest below */
if (dhangh > 0)
dh -= dhangh; /* reduce dh */
shangh = sy + dh - spixh; /* rect ovhang src below */
if (shangh > 0)
dh -= shangh; /* reduce dh */
/* if clipped entirely, quit */
if ((dw <= 0) || (dh <= 0))
return;
/* -------------------------------------------------------*
* dispatch to aligned or non-aligned blitters
* -------------------------------------------------------*/
if (((dx & 31) == 0) && ((sx & 31) == 0))
rasteropWordAlignedLow(datad, dwpl, dx, dy, dw, dh, op,
datas, swpl, sx, sy);
else if ((dx & 31) == (sx & 31))
rasteropVAlignedLow(datad, dwpl, dx, dy, dw, dh, op,
datas, swpl, sx, sy);
else
rasteropGeneralLow(datad, dwpl, dx, dy, dw, dh, op,
datas, swpl, sx, sy);
return;
}
/*--------------------------------------------------------------------*
* Static low-level rasterop with vertical word alignment *
*--------------------------------------------------------------------*/
/*!
* rasteropWordAlignedLow()
*
* Input: datad (ptr to dest image data)
* dwpl (wpl of dest)
* dx (x val of UL corner of dest rectangle)
* dy (y val of UL corner of dest rectangle)
* dw (width of dest rectangle)
* dh (height of dest rectangle)
* op (op code)
* datas (ptr to src image data)
* swpl (wpl of src)
* sx (x val of UL corner of src rectangle)
* sy (y val of UL corner of src rectangle)
* Return: void
*
* This is called when both the src and dest rects
* are left aligned on (32-bit) word boundaries.
* That is: dx & 31 == 0 and sx & 31 == 0
*
* We make an optimized implementation of this because
* it is a common case: e.g., two images are rasterop'd
* starting from their UL corners (0,0).
*/
static void
rasteropWordAlignedLow(l_uint32 *datad,
l_int32 dwpl,
l_int32 dx,
l_int32 dy,
l_int32 dw,
l_int32 dh,
l_int32 op,
l_uint32 *datas,
l_int32 swpl,
l_int32 sx,
l_int32 sy)
{
l_int32 nfullw; /* number of full words */
l_uint32 *psfword; /* ptr to first src word */
l_uint32 *pdfword; /* ptr to first dest word */
l_int32 lwbits; /* number of ovrhang bits in last partial word */
l_uint32 lwmask; /* mask for last partial word */
l_uint32 *lines, *lined;
l_int32 i, j;
/*--------------------------------------------------------*
* Preliminary calculations *
*--------------------------------------------------------*/
nfullw = dw >> 5;
lwbits = dw & 31;
if (lwbits)
lwmask = lmask32[lwbits];
psfword = datas + swpl * sy + (sx >> 5);
pdfword = datad + dwpl * dy + (dx >> 5);
/*--------------------------------------------------------*
* Now we're ready to do the ops *
*--------------------------------------------------------*/
switch (op)
{
case PIX_SRC:
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = *lines;
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, *lines, lwmask);
}
break;
case PIX_NOT(PIX_SRC):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = ~(*lines);
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, ~(*lines), lwmask);
}
break;
case (PIX_SRC | PIX_DST):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = (*lines | *lined);
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, (*lines | *lined), lwmask);
}
break;
case (PIX_SRC & PIX_DST):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = (*lines & *lined);
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, (*lines & *lined), lwmask);
}
break;
case (PIX_SRC ^ PIX_DST):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = (*lines ^ *lined);
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, (*lines ^ *lined), lwmask);
}
break;
case (PIX_NOT(PIX_SRC) | PIX_DST):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = (~(*lines) | *lined);
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, (~(*lines) | *lined), lwmask);
}
break;
case (PIX_NOT(PIX_SRC) & PIX_DST):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = (~(*lines) & *lined);
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, (~(*lines) & *lined), lwmask);
}
break;
case (PIX_SRC | PIX_NOT(PIX_DST)):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = (*lines | ~(*lined));
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, (*lines | ~(*lined)), lwmask);
}
break;
case (PIX_SRC & PIX_NOT(PIX_DST)):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = (*lines & ~(*lined));
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, (*lines & ~(*lined)), lwmask);
}
break;
case (PIX_NOT(PIX_SRC | PIX_DST)):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = ~(*lines | *lined);
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, ~(*lines | *lined), lwmask);
}
break;
case (PIX_NOT(PIX_SRC & PIX_DST)):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = ~(*lines & *lined);
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, ~(*lines & *lined), lwmask);
}
break;
/* this is three cases: ~(s ^ d), ~s ^ d, s ^ ~d */
case (PIX_NOT(PIX_SRC ^ PIX_DST)):
for (i = 0; i < dh; i++) {
lines = psfword + i * swpl;
lined = pdfword + i * dwpl;
for (j = 0; j < nfullw; j++) {
*lined = ~(*lines ^ *lined);
lined++;
lines++;
}
if (lwbits)
*lined = COMBINE_PARTIAL(*lined, ~(*lines ^ *lined), lwmask);
}
break;
default:
fprintf(stderr, "Operation %d invalid\n", op);
}
return;
}
/*--------------------------------------------------------------------*
* Static low-level rasterop with vertical word alignment *
*--------------------------------------------------------------------*/
/*!
* rasteropVAlignedLow()
*
* Input: datad (ptr to dest image data)
* dwpl (wpl of dest)
* dx (x val of UL corner of dest rectangle)
* dy (y val of UL corner of dest rectangle)
* dw (width of dest rectangle)
* dh (height of dest rectangle)
* op (op code)
* datas (ptr to src image data)
* swpl (wpl of src)
* sx (x val of UL corner of src rectangle)
* sy (y val of UL corner of src rectangle)
* Return: void
*
* This is called when the left side of the src and dest
* rects have the same alignment relative to (32-bit) word
* boundaries; i.e., (dx & 31) == (sx & 31)
*/
static void
rasteropVAlignedLow(l_uint32 *datad,
l_int32 dwpl,
l_int32 dx,
l_int32 dy,
l_int32 dw,
l_int32 dh,
l_int32 op,
l_uint32 *datas,
l_int32 swpl,
l_int32 sx,
l_int32 sy)
{
l_int32 dfwpartb; /* boolean (1, 0) if first dest word is partial */
l_int32 dfwpart2b; /* boolean (1, 0) if first dest word is doubly partial */
l_uint32 dfwmask; /* mask for first partial dest word */
l_int32 dfwbits; /* first word dest bits in ovrhang */
l_uint32 *pdfwpart; /* ptr to first partial dest word */
l_uint32 *psfwpart; /* ptr to first partial src word */
l_int32 dfwfullb; /* boolean (1, 0) if there exists a full dest word */
l_int32 dnfullw; /* number of full words in dest */
l_uint32 *pdfwfull; /* ptr to first full dest word */
l_uint32 *psfwfull; /* ptr to first full src word */
l_int32 dlwpartb; /* boolean (1, 0) if last dest word is partial */
l_uint32 dlwmask; /* mask for last partial dest word */
l_int32 dlwbits; /* last word dest bits in ovrhang */
l_uint32 *pdlwpart; /* ptr to last partial dest word */
l_uint32 *pslwpart; /* ptr to last partial src word */
l_int32 i, j;
/*--------------------------------------------------------*
* Preliminary calculations *
*--------------------------------------------------------*/
/* is the first word partial? */
if ((dx & 31) == 0) { /* if not */
dfwpartb = 0;
dfwbits = 0;
}
else { /* if so */
dfwpartb = 1;
dfwbits = 32 - (dx & 31);
dfwmask = rmask32[dfwbits];
pdfwpart = datad + dwpl * dy + (dx >> 5);
psfwpart = datas + swpl * sy + (sx >> 5);
}
/* is the first word doubly partial? */
if (dw >= dfwbits) /* if not */
dfwpart2b = 0;
else { /* if so */
dfwpart2b = 1;
dfwmask &= lmask32[32 - dfwbits + dw];
}
/* is there a full dest word? */
if (dfwpart2b == 1) { /* not */
dfwfullb = 0;
dnfullw = 0;
}
else {
dnfullw = (dw - dfwbits) >> 5;
if (dnfullw == 0) /* if not */
dfwfullb = 0;
else { /* if so */
dfwfullb = 1;
if (dfwpartb) {
pdfwfull = pdfwpart + 1;
psfwfull = psfwpart + 1;
}
else {
pdfwfull = datad + dwpl * dy + (dx >> 5);
psfwfull = datas + swpl * sy + (sx >> 5);
}
}
}
/* is the last word partial? */
dlwbits = (dx + dw) & 31;
if (dfwpart2b == 1 || dlwbits == 0) /* if not */
dlwpartb = 0;
else {
dlwpartb = 1;
dlwmask = lmask32[dlwbits];
if (dfwpartb) {
pdlwpart = pdfwpart + 1 + dnfullw;
pslwpart = psfwpart + 1 + dnfullw;
}
else {
pdlwpart = datad + dwpl * dy + (dx >> 5) + dnfullw;
pslwpart = datas + swpl * sy + (sx >> 5) + dnfullw;
}
}
/*--------------------------------------------------------*
* Now we're ready to do the ops *
*--------------------------------------------------------*/
switch (op)
{
case PIX_SRC:
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart, *psfwpart, dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = *(psfwfull + j);
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart, *pslwpart, dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case PIX_NOT(PIX_SRC):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart, ~(*psfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = ~(*(psfwfull + j));
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart, ~(*pslwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC | PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(*psfwpart | *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) |= *(psfwfull + j);
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(*pslwpart | *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC & PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(*psfwpart & *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) &= *(psfwfull + j);
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(*pslwpart & *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC ^ PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(*psfwpart ^ *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) ^= *(psfwfull + j);
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(*pslwpart ^ *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_NOT(PIX_SRC) | PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(~(*psfwpart) | *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) |= ~(*(psfwfull + j));
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(~(*pslwpart) | *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_NOT(PIX_SRC) & PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(~(*psfwpart) & *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) &= ~(*(psfwfull + j));
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(~(*pslwpart) & *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC | PIX_NOT(PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(*psfwpart | ~(*pdfwpart)), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = *(psfwfull + j) | ~(*(pdfwfull + j));
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(*pslwpart | ~(*pdlwpart)), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC & PIX_NOT(PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(*psfwpart & ~(*pdfwpart)), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = *(psfwfull + j) & ~(*(pdfwfull + j));
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(*pslwpart & ~(*pdlwpart)), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_NOT(PIX_SRC | PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
~(*psfwpart | *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = ~(*(psfwfull + j) | *(pdfwfull + j));
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
~(*pslwpart | *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_NOT(PIX_SRC & PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
~(*psfwpart & *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = ~(*(psfwfull + j) & *(pdfwfull + j));
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
~(*pslwpart & *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
/* this is three cases: ~(s ^ d), ~s ^ d, s ^ ~d */
case (PIX_NOT(PIX_SRC ^ PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++) {
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
~(*psfwpart ^ *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++)
*(pdfwfull + j) = ~(*(psfwfull + j) ^ *(pdfwfull + j));
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
~(*pslwpart ^ *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
default:
fprintf(stderr, "Operation %x invalid\n", op);
}
return;
}
/*--------------------------------------------------------------------*
* Static low-level rasterop without vertical word alignment *
*--------------------------------------------------------------------*/
/*!
* rasteropGeneralLow()
*
* Input: datad (ptr to dest image data)
* dwpl (wpl of dest)
* dx (x val of UL corner of dest rectangle)
* dy (y val of UL corner of dest rectangle)
* dw (width of dest rectangle)
* dh (height of dest rectangle)
* op (op code)
* datas (ptr to src image data)
* swpl (wpl of src)
* sx (x val of UL corner of src rectangle)
* sy (y val of UL corner of src rectangle)
* Return: void
*
* This is called when the src and dest rects are
* do not have the same (32-bit) word alignment.
*
* The method is a generalization of rasteropVAlignLow().
* There, the src image pieces were directly merged
* with the dest. Here, we shift the source bits
* to fill words that are aligned with the dest, and
* then use those "source words" exactly in place
* of the source words that were used in rasteropVAlignLow().
*
* The critical parameter is thus the shift required
* for the src. Consider the left edge of the rectangle.
* The overhang into the src and dest words are found,
* and the difference is exactly this shift. There are
* two separate cases, depending on whether the src pixels
* are shifted left or right. If the src overhang is
* larger than the dest overhang, the src is shifted to
* the right, a number of pixels equal to the shift are
* left over for filling the next dest word, if necessary.
* But if the dest overhang is larger than the src,
* the src is shifted to the left, and it may also be
* necessary to shift an equal number of pixels in from
* the next src word. However, in both cases, after
* the first partial (or complete) dest word has been
* filled, the next src pixels will come from a left
* shift that exhausts the pixels in the src word.
*/
static void
rasteropGeneralLow(l_uint32 *datad,
l_int32 dwpl,
l_int32 dx,
l_int32 dy,
l_int32 dw,
l_int32 dh,
l_int32 op,
l_uint32 *datas,
l_int32 swpl,
l_int32 sx,
l_int32 sy)
{
l_int32 dfwpartb; /* boolean (1, 0) if first dest word is partial */
l_int32 dfwpart2b; /* boolean (1, 0) if 1st dest word is doubly partial */
l_uint32 dfwmask; /* mask for first partial dest word */
l_int32 dfwbits; /* first word dest bits in overhang; 0-31 */
l_int32 dhang; /* dest overhang in first partial word, */
/* or 0 if dest is word aligned (same as dfwbits) */
l_uint32 *pdfwpart; /* ptr to first partial dest word */
l_uint32 *psfwpart; /* ptr to first partial src word */
l_int32 dfwfullb; /* boolean (1, 0) if there exists a full dest word */
l_int32 dnfullw; /* number of full words in dest */
l_uint32 *pdfwfull; /* ptr to first full dest word */
l_uint32 *psfwfull; /* ptr to first full src word */
l_int32 dlwpartb; /* boolean (1, 0) if last dest word is partial */
l_uint32 dlwmask; /* mask for last partial dest word */
l_int32 dlwbits; /* last word dest bits in ovrhang */
l_uint32 *pdlwpart; /* ptr to last partial dest word */
l_uint32 *pslwpart; /* ptr to last partial src word */
l_uint32 sword; /* compose src word aligned with the dest words */
l_int32 sfwbits; /* first word src bits in overhang (1-32), */
/* or 32 if src is word aligned */
l_int32 shang; /* source overhang in the first partial word, */
/* or 0 if src is word aligned (not same as sfwbits) */
l_int32 sleftshift; /* bits to shift left for source word to align */
/* with the dest. Also the number of bits that */
/* get shifted to the right to align with the dest. */
l_int32 srightshift; /* bits to shift right for source word to align */
/* with dest. Also, the number of bits that get */
/* shifted left to align with the dest. */
l_int32 srightmask; /* mask for selecting sleftshift bits that have */
/* been shifted right by srightshift bits */
l_int32 sfwshiftdir; /* either SHIFT_LEFT or SHIFT_RIGHT */
l_int32 sfwaddb; /* boolean: do we need an additional sfw right shift? */
l_int32 slwaddb; /* boolean: do we need an additional slw right shift? */
l_int32 i, j;
/*--------------------------------------------------------*
* Preliminary calculations *
*--------------------------------------------------------*/
/* To get alignment of src with dst (e.g., in the
* full words) the src must do a left shift of its
* relative overhang in the current src word,
* and OR that with a right shift of
* (31 - relative overhang) from the next src word.
* We find the absolute overhangs, the relative overhangs,
* the required shifts and the src mask */
if ((sx & 31) == 0)
shang = 0;
else
shang = 32 - (sx & 31);
if ((dx & 31) == 0)
dhang = 0;
else
dhang = 32 - (dx & 31);
if (shang == 0 && dhang == 0) { /* this should be treated by an
aligned operation, not by
this general rasterop! */
sleftshift = 0;
srightshift = 0;
srightmask = rmask32[0];
}
else {
if (dhang > shang)
sleftshift = dhang - shang;
else
sleftshift = 32 - (shang - dhang);
srightshift = 32 - sleftshift;
srightmask = rmask32[sleftshift];
}
/* is the first dest word partial? */
if ((dx & 31) == 0) { /* if not */
dfwpartb = 0;
dfwbits = 0;
}
else { /* if so */
dfwpartb = 1;
dfwbits = 32 - (dx & 31);
dfwmask = rmask32[dfwbits];
pdfwpart = datad + dwpl * dy + (dx >> 5);
psfwpart = datas + swpl * sy + (sx >> 5);
sfwbits = 32 - (sx & 31);
if (dfwbits > sfwbits) {
sfwshiftdir = SHIFT_LEFT; /* and shift by sleftshift */
if (dw < shang)
sfwaddb = 0;
else
sfwaddb = 1; /* and rshift in next src word by srightshift */
}
else
sfwshiftdir = SHIFT_RIGHT; /* and shift by srightshift */
}
/* is the first dest word doubly partial? */
if (dw >= dfwbits) /* if not */
dfwpart2b = 0;
else { /* if so */
dfwpart2b = 1;
dfwmask &= lmask32[32 - dfwbits + dw];
}
/* is there a full dest word? */
if (dfwpart2b == 1) { /* not */
dfwfullb = 0;
dnfullw = 0;
}
else {
dnfullw = (dw - dfwbits) >> 5;
if (dnfullw == 0) /* if not */
dfwfullb = 0;
else { /* if so */
dfwfullb = 1;
pdfwfull = datad + dwpl * dy + ((dx + dhang) >> 5);
psfwfull = datas + swpl * sy + ((sx + dhang) >> 5); /* yes, dhang */
}
}
/* is the last dest word partial? */
dlwbits = (dx + dw) & 31;
if (dfwpart2b == 1 || dlwbits == 0) /* if not */
dlwpartb = 0;
else {
dlwpartb = 1;
dlwmask = lmask32[dlwbits];
pdlwpart = datad + dwpl * dy + ((dx + dhang) >> 5) + dnfullw;
pslwpart = datas + swpl * sy + ((sx + dhang) >> 5) + dnfullw;
if (dlwbits <= srightshift) /* must be <= here !!! */
slwaddb = 0; /* we got enough bits from current src word */
else
slwaddb = 1; /* must rshift in next src word by srightshift */
}
/*--------------------------------------------------------*
* Now we're ready to do the ops *
*--------------------------------------------------------*/
switch (op)
{
case PIX_SRC:
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart, sword, dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) = sword;
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart, sword, dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case PIX_NOT(PIX_SRC):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart, ~sword, dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) = ~sword;
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart, ~sword, dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC | PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(sword | *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) |= sword;
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(sword | *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC & PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(sword & *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) &= sword;
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(sword & *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC ^ PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(sword ^ *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) ^= sword;
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(sword ^ *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_NOT(PIX_SRC) | PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(~sword | *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) |= ~sword;
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(~sword | *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_NOT(PIX_SRC) & PIX_DST):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(~sword & *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) &= ~sword;
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(~sword & *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC | PIX_NOT(PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(sword | ~(*pdfwpart)), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) = sword | ~(*(pdfwfull + j));
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(sword | ~(*pdlwpart)), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_SRC & PIX_NOT(PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
(sword & ~(*pdfwpart)), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) = sword & ~(*(pdfwfull + j));
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
(sword & ~(*pdlwpart)), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_NOT(PIX_SRC | PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
~(sword | *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) = ~(sword | *(pdfwfull + j));
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
~(sword | *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
case (PIX_NOT(PIX_SRC & PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
~(sword & *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) = ~(sword & *(pdfwfull + j));
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
~(sword & *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
/* this is three cases: ~(s ^ d), ~s ^ d, s ^ ~d */
case (PIX_NOT(PIX_SRC ^ PIX_DST)):
/* do the first partial word */
if (dfwpartb) {
for (i = 0; i < dh; i++)
{
if (sfwshiftdir == SHIFT_LEFT) {
sword = *psfwpart << sleftshift;
if (sfwaddb)
sword = COMBINE_PARTIAL(sword,
*(psfwpart + 1) >> srightshift,
srightmask);
}
else /* shift right */
sword = *psfwpart >> srightshift;
*pdfwpart = COMBINE_PARTIAL(*pdfwpart,
~(sword ^ *pdfwpart), dfwmask);
pdfwpart += dwpl;
psfwpart += swpl;
}
}
/* do the full words */
if (dfwfullb) {
for (i = 0; i < dh; i++) {
for (j = 0; j < dnfullw; j++) {
sword = COMBINE_PARTIAL(*(psfwfull + j) << sleftshift,
*(psfwfull + j + 1) >> srightshift,
srightmask);
*(pdfwfull + j) = ~(sword ^ *(pdfwfull + j));
}
pdfwfull += dwpl;
psfwfull += swpl;
}
}
/* do the last partial word */
if (dlwpartb) {
for (i = 0; i < dh; i++) {
sword = *pslwpart << sleftshift;
if (slwaddb)
sword = COMBINE_PARTIAL(sword,
*(pslwpart + 1) >> srightshift,
srightmask);
*pdlwpart = COMBINE_PARTIAL(*pdlwpart,
~(sword ^ *pdlwpart), dlwmask);
pdlwpart += dwpl;
pslwpart += swpl;
}
}
break;
default:
fprintf(stderr, "Operation %x invalid\n", op);
}
return;
}