mirror of http://192.168.1.51:8099/lmh188/twain3.0
2480 lines
86 KiB
C
2480 lines
86 KiB
C
|
/*====================================================================*
|
||
|
- Copyright (C) 2001 Leptonica. All rights reserved.
|
||
|
-
|
||
|
- 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 COPYRIGHT HOLDERS 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 ANY
|
||
|
- 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.
|
||
|
*====================================================================*/
|
||
|
|
||
|
/*!
|
||
|
* \file roplow.c
|
||
|
* <pre>
|
||
|
* 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()
|
||
|
*
|
||
|
* Low level in-place full height vertical block transfer
|
||
|
* void rasteropVipLow()
|
||
|
*
|
||
|
* Low level in-place full width horizontal block transfer
|
||
|
* void rasteropHipLow()
|
||
|
* static void shiftDataHorizontalLow()
|
||
|
* </pre>
|
||
|
*/
|
||
|
|
||
|
#include <string.h>
|
||
|
#include "allheaders.h"
|
||
|
|
||
|
/* Static helpers */
|
||
|
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 void shiftDataHorizontalLow(l_uint32 *datad, l_int32 wpld,
|
||
|
l_uint32 *datas, l_int32 wpls,
|
||
|
l_int32 shift);
|
||
|
|
||
|
#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 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 *
|
||
|
*--------------------------------------------------------------------*/
|
||
|
/*!
|
||
|
* \brief rasteropUniLow()
|
||
|
*
|
||
|
* \param[in] datad ptr to dest image data
|
||
|
* \param[in] dpixw width of dest
|
||
|
* \param[in] dpixh height of dest
|
||
|
* \param[in] depth depth of src and dest
|
||
|
* \param[in] dwpl wpl of dest
|
||
|
* \param[in] dx x val of UL corner of dest rectangle
|
||
|
* \param[in] dy y val of UL corner of dest rectangle
|
||
|
* \param[in] dw width of dest rectangle
|
||
|
* \param[in] dh height of dest rectangle
|
||
|
* \param[in] 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);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------*
|
||
|
* Static low-level uni rasterop with word alignment *
|
||
|
*--------------------------------------------------------------------*/
|
||
|
/*!
|
||
|
* \brief rasteropUniWordAlignedLow()
|
||
|
*
|
||
|
* \param[in] datad ptr to dest image data
|
||
|
* \param[in] dwpl wpl of dest
|
||
|
* \param[in] dx x val of UL corner of dest rectangle
|
||
|
* \param[in] dy y val of UL corner of dest rectangle
|
||
|
* \param[in] dw width of dest rectangle
|
||
|
* \param[in] dh height of dest rectangle
|
||
|
* \param[in] 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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------*
|
||
|
* Static low-level uni rasterop without word alignment *
|
||
|
*--------------------------------------------------------------------*/
|
||
|
/*!
|
||
|
* \brief rasteropUniGeneralLow()
|
||
|
*
|
||
|
* \param[in] datad ptr to dest image data
|
||
|
* \param[in] dwpl wpl of dest
|
||
|
* \param[in] dx x val of UL corner of dest rectangle
|
||
|
* \param[in] dy y val of UL corner of dest rectangle
|
||
|
* \param[in] dw width of dest rectangle
|
||
|
* \param[in] dh height of dest rectangle
|
||
|
* \param[in] 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? */
|
||
|
dfwmask = 0;
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------*
|
||
|
* Low-level src and dest rasterops *
|
||
|
*--------------------------------------------------------------------*/
|
||
|
/*!
|
||
|
* \brief rasteropLow()
|
||
|
*
|
||
|
* \param[in] datad ptr to dest image data
|
||
|
* \param[in] dpixw width of dest
|
||
|
* \param[in] dpixh height of dest
|
||
|
* \param[in] depth depth of src and dest
|
||
|
* \param[in] dwpl wpl of dest
|
||
|
* \param[in] dx x val of UL corner of dest rectangle
|
||
|
* \param[in] dy y val of UL corner of dest rectangle
|
||
|
* \param[in] dw width of dest rectangle
|
||
|
* \param[in] dh height of dest rectangle
|
||
|
* \param[in] op op code
|
||
|
* \param[in] datas ptr to src image data
|
||
|
* \param[in] spixw width of src
|
||
|
* \param[in] spixh height of src
|
||
|
* \param[in] swpl wpl of src
|
||
|
* \param[in] sx x val of UL corner of src rectangle
|
||
|
* \param[in] 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);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------*
|
||
|
* Static low-level rasterop with vertical word alignment *
|
||
|
*--------------------------------------------------------------------*/
|
||
|
/*!
|
||
|
* \brief rasteropWordAlignedLow()
|
||
|
*
|
||
|
* \param[in] datad ptr to dest image data
|
||
|
* \param[in] dwpl wpl of dest
|
||
|
* \param[in] dx x val of UL corner of dest rectangle
|
||
|
* \param[in] dy y val of UL corner of dest rectangle
|
||
|
* \param[in] dw width of dest rectangle
|
||
|
* \param[in] dh height of dest rectangle
|
||
|
* \param[in] op op code
|
||
|
* \param[in] datas ptr to src image data
|
||
|
* \param[in] swpl wpl of src
|
||
|
* \param[in] sx x val of UL corner of src rectangle
|
||
|
* \param[in] 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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------*
|
||
|
* Static low-level rasterop with vertical word alignment *
|
||
|
*--------------------------------------------------------------------*/
|
||
|
/*!
|
||
|
* \brief rasteropVAlignedLow()
|
||
|
*
|
||
|
* \param[in] datad ptr to dest image data
|
||
|
* \param[in] dwpl wpl of dest
|
||
|
* \param[in] dx x val of UL corner of dest rectangle
|
||
|
* \param[in] dy y val of UL corner of dest rectangle
|
||
|
* \param[in] dw width of dest rectangle
|
||
|
* \param[in] dh height of dest rectangle
|
||
|
* \param[in] op op code
|
||
|
* \param[in] datas ptr to src image data
|
||
|
* \param[in] swpl wpl of src
|
||
|
* \param[in] sx x val of UL corner of src rectangle
|
||
|
* \param[in] 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? */
|
||
|
dfwmask = 0;
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------*
|
||
|
* Static low-level rasterop without vertical word alignment *
|
||
|
*--------------------------------------------------------------------*/
|
||
|
/*!
|
||
|
* \brief rasteropGeneralLow()
|
||
|
*
|
||
|
* \param[in] datad ptr to dest image data
|
||
|
* \param[in] dwpl wpl of dest
|
||
|
* \param[in] dx x val of UL corner of dest rectangle
|
||
|
* \param[in] dy y val of UL corner of dest rectangle
|
||
|
* \param[in] dw width of dest rectangle
|
||
|
* \param[in] dh height of dest rectangle
|
||
|
* \param[in] op op code
|
||
|
* \param[in] datas ptr to src image data
|
||
|
* \param[in] swpl wpl of src
|
||
|
* \param[in] sx x val of UL corner of src rectangle
|
||
|
* \param[in] 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? */
|
||
|
dfwmask = 0;
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------*
|
||
|
* Low level in-place full height vertical block transfer *
|
||
|
*--------------------------------------------------------------------*/
|
||
|
/*!
|
||
|
* \brief rasteropVipLow()
|
||
|
*
|
||
|
* \param[in] data ptr to image data
|
||
|
* \param[in] pixw width
|
||
|
* \param[in] pixh height
|
||
|
* \param[in] depth depth
|
||
|
* \param[in] wpl wpl
|
||
|
* \param[in] x x val of UL corner of rectangle
|
||
|
* \param[in] w width of rectangle
|
||
|
* \param[in] shift + shifts data downward in vertical column
|
||
|
* \return 0 if OK; 1 on error.
|
||
|
*
|
||
|
* <pre>
|
||
|
* Notes:
|
||
|
* (1) This clears the pixels that are left exposed after the
|
||
|
* translation. You can consider them as pixels that are
|
||
|
* shifted in from outside the image. This can be later
|
||
|
* overridden by the incolor parameter in higher-level functions
|
||
|
* that call this. For example, for images with depth > 1,
|
||
|
* these pixels are cleared to black; to be white they
|
||
|
* must later be SET to white. See, e.g., pixRasteropVip().
|
||
|
* (2) This function scales the width to accommodate any depth,
|
||
|
* performs clipping, and then does the in-place rasterop.
|
||
|
* </pre>
|
||
|
*/
|
||
|
void
|
||
|
rasteropVipLow(l_uint32 *data,
|
||
|
l_int32 pixw,
|
||
|
l_int32 pixh,
|
||
|
l_int32 depth,
|
||
|
l_int32 wpl,
|
||
|
l_int32 x,
|
||
|
l_int32 w,
|
||
|
l_int32 shift)
|
||
|
{
|
||
|
l_int32 fwpartb; /* boolean (1, 0) if first word is partial */
|
||
|
l_int32 fwpart2b; /* boolean (1, 0) if first word is doubly partial */
|
||
|
l_uint32 fwmask; /* mask for first partial word */
|
||
|
l_int32 fwbits; /* first word bits in ovrhang */
|
||
|
l_uint32 *pdfwpart; /* ptr to first partial dest word */
|
||
|
l_uint32 *psfwpart; /* ptr to first partial src word */
|
||
|
l_int32 fwfullb; /* boolean (1, 0) if there exists a full word */
|
||
|
l_int32 nfullw; /* number of full words */
|
||
|
l_uint32 *pdfwfull; /* ptr to first full dest word */
|
||
|
l_uint32 *psfwfull; /* ptr to first full src word */
|
||
|
l_int32 lwpartb; /* boolean (1, 0) if last word is partial */
|
||
|
l_uint32 lwmask; /* mask for last partial word */
|
||
|
l_int32 lwbits; /* last word bits in ovrhang */
|
||
|
l_uint32 *pdlwpart; /* ptr to last partial dest word */
|
||
|
l_uint32 *pslwpart; /* ptr to last partial src word */
|
||
|
l_int32 dirwpl; /* directed wpl (-wpl * sign(shift)) */
|
||
|
l_int32 absshift; /* absolute value of shift; for use in iterator */
|
||
|
l_int32 vlimit; /* vertical limit value for iterations */
|
||
|
l_int32 i, j;
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------*
|
||
|
* Scale horizontal dimensions by depth *
|
||
|
*--------------------------------------------------------*/
|
||
|
if (depth != 1) {
|
||
|
pixw *= depth;
|
||
|
x *= depth;
|
||
|
w *= depth;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------*
|
||
|
* Clip horizontally *
|
||
|
*--------------------------------------------------------*/
|
||
|
if (x < 0) {
|
||
|
w += x; /* reduce w */
|
||
|
x = 0; /* clip to x = 0 */
|
||
|
}
|
||
|
if (x >= pixw || w <= 0) /* no part of vertical slice is in the image */
|
||
|
return;
|
||
|
|
||
|
if (x + w > pixw)
|
||
|
w = pixw - x; /* clip to x + w = pixw */
|
||
|
|
||
|
/*--------------------------------------------------------*
|
||
|
* Preliminary calculations *
|
||
|
*--------------------------------------------------------*/
|
||
|
/* is the first word partial? */
|
||
|
if ((x & 31) == 0) { /* if not */
|
||
|
fwpartb = 0;
|
||
|
fwbits = 0;
|
||
|
} else { /* if so */
|
||
|
fwpartb = 1;
|
||
|
fwbits = 32 - (x & 31);
|
||
|
fwmask = rmask32[fwbits];
|
||
|
if (shift >= 0) { /* go up from bottom */
|
||
|
pdfwpart = data + wpl * (pixh - 1) + (x >> 5);
|
||
|
psfwpart = data + wpl * (pixh - 1 - shift) + (x >> 5);
|
||
|
} else { /* go down from top */
|
||
|
pdfwpart = data + (x >> 5);
|
||
|
psfwpart = data - wpl * shift + (x >> 5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* is the first word doubly partial? */
|
||
|
if (w >= fwbits) { /* if not */
|
||
|
fwpart2b = 0;
|
||
|
} else { /* if so */
|
||
|
fwpart2b = 1;
|
||
|
fwmask &= lmask32[32 - fwbits + w];
|
||
|
}
|
||
|
|
||
|
/* is there a full dest word? */
|
||
|
if (fwpart2b == 1) { /* not */
|
||
|
fwfullb = 0;
|
||
|
nfullw = 0;
|
||
|
} else {
|
||
|
nfullw = (w - fwbits) >> 5;
|
||
|
if (nfullw == 0) { /* if not */
|
||
|
fwfullb = 0;
|
||
|
} else { /* if so */
|
||
|
fwfullb = 1;
|
||
|
if (fwpartb) {
|
||
|
pdfwfull = pdfwpart + 1;
|
||
|
psfwfull = psfwpart + 1;
|
||
|
} else if (shift >= 0) { /* go up from bottom */
|
||
|
pdfwfull = data + wpl * (pixh - 1) + (x >> 5);
|
||
|
psfwfull = data + wpl * (pixh - 1 - shift) + (x >> 5);
|
||
|
} else { /* go down from top */
|
||
|
pdfwfull = data + (x >> 5);
|
||
|
psfwfull = data - wpl * shift + (x >> 5);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* is the last word partial? */
|
||
|
lwbits = (x + w) & 31;
|
||
|
if (fwpart2b == 1 || lwbits == 0) { /* if not */
|
||
|
lwpartb = 0;
|
||
|
} else {
|
||
|
lwpartb = 1;
|
||
|
lwmask = lmask32[lwbits];
|
||
|
if (fwpartb) {
|
||
|
pdlwpart = pdfwpart + 1 + nfullw;
|
||
|
pslwpart = psfwpart + 1 + nfullw;
|
||
|
} else if (shift >= 0) { /* go up from bottom */
|
||
|
pdlwpart = data + wpl * (pixh - 1) + (x >> 5) + nfullw;
|
||
|
pslwpart = data + wpl * (pixh - 1 - shift) + (x >> 5) + nfullw;
|
||
|
} else { /* go down from top */
|
||
|
pdlwpart = data + (x >> 5) + nfullw;
|
||
|
pslwpart = data - wpl * shift + (x >> 5) + nfullw;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* determine the direction of flow from the shift
|
||
|
* If the shift >= 0, data flows downard from src
|
||
|
* to dest, starting at the bottom and working up.
|
||
|
* If shift < 0, data flows upward from src to
|
||
|
* dest, starting at the top and working down. */
|
||
|
dirwpl = (shift >= 0) ? -wpl : wpl;
|
||
|
absshift = L_ABS(shift);
|
||
|
vlimit = L_MAX(0, pixh - absshift);
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------*
|
||
|
* Now we're ready to do the ops *
|
||
|
*--------------------------------------------------------*/
|
||
|
|
||
|
/* Do the first partial word */
|
||
|
if (fwpartb) {
|
||
|
for (i = 0; i < vlimit; i++) {
|
||
|
*pdfwpart = COMBINE_PARTIAL(*pdfwpart, *psfwpart, fwmask);
|
||
|
pdfwpart += dirwpl;
|
||
|
psfwpart += dirwpl;
|
||
|
}
|
||
|
|
||
|
/* Clear the incoming pixels */
|
||
|
for (i = vlimit; i < pixh; i++) {
|
||
|
*pdfwpart = COMBINE_PARTIAL(*pdfwpart, 0x0, fwmask);
|
||
|
pdfwpart += dirwpl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Do the full words */
|
||
|
if (fwfullb) {
|
||
|
for (i = 0; i < vlimit; i++) {
|
||
|
for (j = 0; j < nfullw; j++)
|
||
|
*(pdfwfull + j) = *(psfwfull + j);
|
||
|
pdfwfull += dirwpl;
|
||
|
psfwfull += dirwpl;
|
||
|
}
|
||
|
|
||
|
/* Clear the incoming pixels */
|
||
|
for (i = vlimit; i < pixh; i++) {
|
||
|
for (j = 0; j < nfullw; j++)
|
||
|
*(pdfwfull + j) = 0x0;
|
||
|
pdfwfull += dirwpl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Do the last partial word */
|
||
|
if (lwpartb) {
|
||
|
for (i = 0; i < vlimit; i++) {
|
||
|
*pdlwpart = COMBINE_PARTIAL(*pdlwpart, *pslwpart, lwmask);
|
||
|
pdlwpart += dirwpl;
|
||
|
pslwpart += dirwpl;
|
||
|
}
|
||
|
|
||
|
/* Clear the incoming pixels */
|
||
|
for (i = vlimit; i < pixh; i++) {
|
||
|
*pdlwpart = COMBINE_PARTIAL(*pdlwpart, 0x0, lwmask);
|
||
|
pdlwpart += dirwpl;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------*
|
||
|
* Low level in-place full width horizontal block transfer *
|
||
|
*--------------------------------------------------------------------*/
|
||
|
/*!
|
||
|
* \brief rasteropHipLow()
|
||
|
*
|
||
|
* \param[in] data ptr to image data
|
||
|
* \param[in] pixh height
|
||
|
* \param[in] depth depth
|
||
|
* \param[in] wpl wpl
|
||
|
* \param[in] y y val of UL corner of rectangle
|
||
|
* \param[in] h height of rectangle
|
||
|
* \param[in] shift + shifts data to the left in a horizontal column
|
||
|
* \return 0 if OK; 1 on error.
|
||
|
*
|
||
|
* <pre>
|
||
|
* Notes:
|
||
|
* (1) This clears the pixels that are left exposed after the rasterop.
|
||
|
* Therefore, for Pix with depth > 1, these pixels become black,
|
||
|
* and must be subsequently SET if they are to be white.
|
||
|
* For example, see pixRasteropHip().
|
||
|
* (2) This function performs clipping and calls shiftDataHorizontalLow()
|
||
|
* to do the in-place rasterop on each line.
|
||
|
* </pre>
|
||
|
*/
|
||
|
void
|
||
|
rasteropHipLow(l_uint32 *data,
|
||
|
l_int32 pixh,
|
||
|
l_int32 depth,
|
||
|
l_int32 wpl,
|
||
|
l_int32 y,
|
||
|
l_int32 h,
|
||
|
l_int32 shift)
|
||
|
{
|
||
|
l_int32 i;
|
||
|
l_uint32 *line;
|
||
|
|
||
|
/* clip band if necessary */
|
||
|
if (y < 0) {
|
||
|
h += y; /* reduce h */
|
||
|
y = 0; /* clip to y = 0 */
|
||
|
}
|
||
|
if (h <= 0 || y > pixh) /* no part of horizontal slice is in the image */
|
||
|
return;
|
||
|
|
||
|
if (y + h > pixh)
|
||
|
h = pixh - y; /* clip to y + h = pixh */
|
||
|
|
||
|
for (i = y; i < y + h; i++) {
|
||
|
line = data + i * wpl;
|
||
|
shiftDataHorizontalLow(line, wpl, line, wpl, shift * depth);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!
|
||
|
* \brief shiftDataHorizontalLow()
|
||
|
*
|
||
|
* \param[in] datad ptr to beginning of dest line
|
||
|
* \param[in] wpld wpl of dest
|
||
|
* \param[in] datas ptr to beginning of src line
|
||
|
* \param[in] wpls wpl of src
|
||
|
* \param[in] shift horizontal shift of block; >0 is to right
|
||
|
* \return void
|
||
|
*
|
||
|
* <pre>
|
||
|
* Notes:
|
||
|
* (1) This can also be used for in-place operation; see, e.g.,
|
||
|
* rasteropHipLow().
|
||
|
* (2) We are clearing the pixels that are shifted in from
|
||
|
* outside the image. This can be overridden by the
|
||
|
* incolor parameter in higher-level functions that call this.
|
||
|
* </pre>
|
||
|
*/
|
||
|
static void
|
||
|
shiftDataHorizontalLow(l_uint32 *datad,
|
||
|
l_int32 wpld,
|
||
|
l_uint32 *datas,
|
||
|
l_int32 wpls,
|
||
|
l_int32 shift)
|
||
|
{
|
||
|
l_int32 j, firstdw, wpl, rshift, lshift;
|
||
|
l_uint32 *lined, *lines;
|
||
|
|
||
|
lined = datad;
|
||
|
lines = datas;
|
||
|
|
||
|
if (shift >= 0) { /* src shift to right; data flows to
|
||
|
* right, starting at right edge and
|
||
|
* progressing leftward. */
|
||
|
firstdw = shift / 32;
|
||
|
wpl = L_MIN(wpls, wpld - firstdw);
|
||
|
lined += firstdw + wpl - 1;
|
||
|
lines += wpl - 1;
|
||
|
rshift = shift & 31;
|
||
|
if (rshift == 0) {
|
||
|
for (j = 0; j < wpl; j++)
|
||
|
*lined-- = *lines--;
|
||
|
|
||
|
/* clear out the rest to the left edge */
|
||
|
for (j = 0; j < firstdw; j++)
|
||
|
*lined-- = 0;
|
||
|
} else {
|
||
|
lshift = 32 - rshift;
|
||
|
for (j = 1; j < wpl; j++) {
|
||
|
*lined-- = *(lines - 1) << lshift | *lines >> rshift;
|
||
|
lines--;
|
||
|
}
|
||
|
*lined = *lines >> rshift; /* partial first */
|
||
|
|
||
|
/* clear out the rest to the left edge */
|
||
|
*lined &= ~lmask32[rshift];
|
||
|
lined--;
|
||
|
for (j = 0; j < firstdw; j++)
|
||
|
*lined-- = 0;
|
||
|
}
|
||
|
} else { /* src shift to left; data flows to left, starting
|
||
|
* at left edge and progressing rightward. */
|
||
|
firstdw = (-shift) / 32;
|
||
|
wpl = L_MIN(wpls - firstdw, wpld);
|
||
|
lines += firstdw;
|
||
|
lshift = (-shift) & 31;
|
||
|
if (lshift == 0) {
|
||
|
for (j = 0; j < wpl; j++)
|
||
|
*lined++ = *lines++;
|
||
|
|
||
|
/* clear out the rest to the right edge */
|
||
|
for (j = 0; j < firstdw; j++)
|
||
|
*lined++ = 0;
|
||
|
} else {
|
||
|
rshift = 32 - lshift;
|
||
|
for (j = 1; j < wpl; j++) {
|
||
|
*lined++ = *lines << lshift | *(lines + 1) >> rshift;
|
||
|
lines++;
|
||
|
}
|
||
|
*lined = *lines << lshift; /* partial last */
|
||
|
|
||
|
/* clear out the rest to the right edge */
|
||
|
/* first clear the lshift pixels of this partial word */
|
||
|
*lined &= ~rmask32[lshift];
|
||
|
lined++;
|
||
|
/* then the remaining words to the right edge */
|
||
|
for (j = 0; j < firstdw; j++)
|
||
|
*lined++ = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|