Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1291 lines
32 KiB

/*++
Copyright (c) 1994-1999 Microsoft Corporation
Module Name:
str.c
Abstract:
stretch blt routines
Author:
Mark Enstrom (marke)
Environment:
C
Revision History:
08-26-92 Initial version
--*/
#include "precomp.hxx"
#include "stretch.hxx"
#define STRETCH_MAX_WIDTH 32767
#ifdef DBG_STRDIR
ULONG DbgStrBlt=0;
#endif
PFN_DIRSTRETCH
pfnStrArray[] = {
vDirectStretchError, // 0
vDirectStretchError, // 1
vDirectStretchError, // 4
vDirectStretch8, // 8
vDirectStretch16, // 16
vDirectStretchError, // 24
vDirectStretch32, // 32
vDirectStretchError, // 0 Narrow
vDirectStretchError, // 0 Narrow
vDirectStretchError, // 1 Narrow
vDirectStretchError, // 4 Narrow
vDirectStretch8Narrow, // 8 Narrow
vDirectStretch16, // 16 Narrow
vDirectStretchError, // 24 Narrow
vDirectStretch32, // 32 Narrow
vDirectStretchError // 0 Narrow
};
/******************************Public*Routine******************************\
*
* Routine Description:
*
* StretchBlt using integer math. Must be from one surface to another
* surface of the same format. Currently only 8,16 and 32 bit per pixel
* are supported
*
* Arguments:
*
* pvDst - Pointer to start of dst bitmap
* lDeltaDst - Bytes from start of dst scan line to start of next
* DstCx - Width of Dst Bitmap in pixels
* DstCy - Height of Dst Bitmap in pixels
* prclDst - Pointer to rectangle of Dst extents
* pvSrc - Pointer to start of Src bitmap
* lDeltaSrc - Bytes from start of Src scan line to start of next
* SrcCx - Width of Src Bitmap in pixels
* SrcCy - Height of Src Bitmap in pixels
* prclSrc - Pointer to rectangle of Src extents
* prclTrim - Return dst extents trimmed by clipping in this rect
* prclSClip - Clip Dest to this rect
* iBitmapFormat - Format of Src and Dst bitmaps
*
* Return Value:
*
* Status
*
* Revision History:
*
* 10-07-94 Initial code
*
\**************************************************************************/
BOOL
StretchDIBDirect(
PVOID pvDst,
LONG lDeltaDst,
ULONG DstCx,
ULONG DstCy,
PRECTL prclDst,
PVOID pvSrc,
LONG lDeltaSrc,
ULONG SrcCx,
ULONG SrcCy,
PRECTL prclSrc,
PRECTL prclTrim,
PRECTL prclClip,
ULONG iBitmapFormat
)
{
//
// validate parameters, then determine src to dst mapping
//
ASSERTGDI(pvDst != (PVOID)NULL,"Bad destination bitmap pointer");
ASSERTGDI(pvSrc != (PVOID)NULL,"Bad source bitmap pointer");
ASSERTGDI(prclDst != (PRECTL)NULL,"Bad destination rectangle");
ASSERTGDI(prclSrc != (PRECTL)NULL,"Bad source rectangle");
STR_BLT StrBlt;
#ifdef DBG_STRDIR
if (DbgStrBlt >= 3) {
DbgPrint("\n-----------------------------------------------------------");
DbgPrint("StretchBlt\n");
DbgPrint("rclDst = [0x%8lx,0x%8lx] to [0x%8lx,0x%8lx]\n",prclDst->left,prclDst->top,prclDst->right,prclDst->bottom);
DbgPrint("rclSrc = [0x%8lx,0x%8lx] to [0x%8lx,0x%8lx]\n",prclSrc->left,prclSrc->top,prclSrc->right,prclSrc->bottom);
}
#endif
LONG WidthDst = prclDst->right - prclDst->left;
LONG HeightDst = prclDst->bottom - prclDst->top;
LONG WidthSrc = prclSrc->right - prclSrc->left;
LONG HeightSrc = prclSrc->bottom - prclSrc->top;
ULONG XSrcToDstIntFloor;
ULONG XSrcToDstFracFloor;
ULONG ulXDstToSrcIntCeil;
ULONG ulXDstToSrcFracCeil;
ULONG YSrcToDstIntFloor;
ULONG YSrcToDstFracFloor;
ULONG ulYDstToSrcIntCeil;
ULONG ulYDstToSrcFracCeil;
LONG SrcIntScan;
LONG DstDeltaScanEnd;
//
// calculate EXCLUSIVE start and end points
//
LONG XSrcStart = prclSrc->left;
LONG XSrcEnd = prclSrc->right;
LONG XDstStart = prclDst->left;
LONG XDstEnd = prclDst->right;
LONG YSrcStart = prclSrc->top;
LONG YSrcEnd = prclSrc->bottom;
LONG YDstStart = prclDst->top;
LONG YDstEnd = prclDst->bottom;
ULONG ulXFracAccumulator;
ULONG ulYFracAccumulator;
BOOL bXSrcClipped = FALSE;
BOOL bYSrcClipped = FALSE;
RECTL rclDefClip;
PRECTL prclBounds = prclClip;
LONG LeftClipDistance;
LONG TopClipDistance;
PFN_DIRSTRETCH pfnStr;
//
// check for quick-out NULL RECTs. SrcWidth and SrcHeight must be
// positive here. Mirroring is taken care of earlier.
//
if (
(WidthDst <= 0) ||
(HeightDst <= 0) ||
(WidthSrc <= 0) ||
(HeightSrc <= 0)
)
{
return(TRUE);
}
//
// make sure extents fit with the limits of 32 bit integer
// arithmatic
//
if (
(WidthDst > STRETCH_MAX_WIDTH) ||
(HeightDst > STRETCH_MAX_WIDTH) ||
(WidthSrc > STRETCH_MAX_WIDTH) ||
(HeightSrc > STRETCH_MAX_WIDTH)
)
{
return(FALSE);
}
//
// if prclClip is null, then make bounds point to a
// default clip region of the entire dst rect
//
if (prclClip == (PRECTL)NULL) {
prclBounds = &rclDefClip;
rclDefClip.left = 0;
rclDefClip.right = DstCx;
rclDefClip.top = 0;
rclDefClip.bottom = DstCy;
}
//
// Calculate X Dst to Src mapping
//
//
// dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
//
// = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
//
// where 2k = 2 ^ 32
//
{
LARGE_INTEGER liWidthSrc;
LARGE_INTEGER liQuo;
ULONG ulTemp;
liWidthSrc.LowPart = (ULONG)-1;
liWidthSrc.HighPart = WidthSrc-1;
liQuo = RtlExtendedLargeIntegerDivide(liWidthSrc,(ULONG)WidthDst,(PULONG)NULL);
ulXDstToSrcIntCeil = liQuo.HighPart;
ulXDstToSrcFracCeil = liQuo.LowPart;
//
// now add 1, use fake carry
//
ulTemp = ulXDstToSrcFracCeil + 1;
ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
ulXDstToSrcFracCeil = ulTemp;
}
//
// Calculate Y Dst to Src mapping
//
//
// dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
//
// = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
//
// where 2k = 2 ^ 32
//
{
LARGE_INTEGER liHeightSrc;
LARGE_INTEGER liQuo;
ULONG ulTemp;
liHeightSrc.LowPart = (ULONG) -1;
liHeightSrc.HighPart = HeightSrc-1;
liQuo = RtlExtendedLargeIntegerDivide(liHeightSrc,HeightDst,NULL);
ulYDstToSrcIntCeil = (ULONG)liQuo.HighPart;
ulYDstToSrcFracCeil = liQuo.LowPart;
//
// now add 1, use fake carry
//
ulTemp = ulYDstToSrcFracCeil + 1;
ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
ulYDstToSrcFracCeil = ulTemp;
}
//
// Check for a x clipped src
//
if ((XSrcStart < 0) || (XSrcEnd > (LONG)SrcCx)) {
bXSrcClipped = TRUE;
//
// src is x clipped.
// calculate Src to Dst mapping, then calculate
// new XDstStart and/or XDstEnd based on clipped src
//
// Calculate X Src to Dst mapping
//
// Src->Dst = ( FLOOR( (2k*WidthDst)/WidthSrc) ) / 2k
//
// where 2k = 2 ^ 32
//
LARGE_INTEGER liHalfk = {0x7fffffff,0x00000000};
LARGE_INTEGER liWidthDst;
LARGE_INTEGER liQuo;
ULONG ulTemp;
bXSrcClipped = TRUE;
liWidthDst.HighPart = WidthDst;;
liWidthDst.LowPart = 0;
liQuo = RtlExtendedLargeIntegerDivide(liWidthDst,(ULONG)WidthSrc,(PULONG)NULL);
XSrcToDstIntFloor = (ULONG)liQuo.HighPart;
XSrcToDstFracFloor = liQuo.LowPart;
//
// is src left clipped
//
if (XSrcStart < 0)
{
//
// clip left Ad = FLOOR[ N * As + (2^(k-1) -1)]/2^k
//
LONG SrcClipped = -(LONG)XSrcStart;
ULONG DeltaDstInt;
LARGE_INTEGER liDeltaDstFrac;
LONG NewWidthSrc = WidthSrc;
NewWidthSrc -= SrcClipped;
if (NewWidthSrc <= 0)
{
return(TRUE);
}
//
// calc fraction N * As
//
DeltaDstInt = (ULONG)SrcClipped * XSrcToDstIntFloor;
liDeltaDstFrac = RtlEnlargedUnsignedMultiply((ULONG)SrcClipped,XSrcToDstFracFloor);
liDeltaDstFrac.HighPart += (LONG)DeltaDstInt;
//
// add in 2^(k-1) - 1 = 0x00000000 0x7fffffff
//
liDeltaDstFrac = RtlLargeIntegerAdd(liDeltaDstFrac,liHalfk);
XSrcStart = 0;
XDstStart += liDeltaDstFrac.HighPart;
}
if (XSrcEnd > (LONG)SrcCx)
{
//
// clip right edge, calc src offset from XSrcStart (SrcClipped)
//
// clip left Bd = FLOOR[ N * Bs + (2^(k-1) -1)]/2^k
//
// Note: use original value of WidthSrc, not value reduced by
// left clipping.
//
LONG SrcClipped = XSrcEnd - SrcCx;
ULONG DeltaDstInt;
LARGE_INTEGER liDstWidth;
WidthSrc = WidthSrc - SrcClipped;
//
// check for totally src clipped
//
if (WidthSrc <= 0)
{
return(TRUE);
}
//
// calc N * Bs
//
DeltaDstInt = (ULONG)WidthSrc * (ULONG)XSrcToDstIntFloor;
liDstWidth = RtlEnlargedUnsignedMultiply((ULONG)WidthSrc,XSrcToDstFracFloor);
liDstWidth.HighPart += (LONG)DeltaDstInt;
//
// add in (2^(k-1) -1)
//
liDstWidth = RtlLargeIntegerAdd(liDstWidth,liHalfk);
XSrcEnd = SrcCx;
XDstEnd = prclDst->left + liDstWidth.HighPart;
}
}
//
// Now clip Dst in X, and/or calc src clipping effect on dst
//
// adjust left and right edges if needed, record
// distance adjusted for fixing the src
//
if (XDstStart < prclBounds->left)
{
XDstStart = prclBounds->left;
}
if (XDstEnd > prclBounds->right)
{
XDstEnd = prclBounds->right;
}
//
// check for totally clipped out dst
//
if (XDstEnd <= XDstStart)
{
return(TRUE);
}
LeftClipDistance = XDstStart - prclDst->left;
if (!bXSrcClipped && (LeftClipDistance == 0))
{
ULONG ulTempInt,ulTempFrac;
//
// calc displacement for .5 in dst and add
//
ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
ulTempInt = ulXDstToSrcIntCeil >> 1;
XSrcStart += (LONG)ulTempInt;
ulXFracAccumulator = ulTempFrac;
} else {
//
// calc new src start
//
LARGE_INTEGER liMulResult;
LARGE_INTEGER liHalfDest;
ULONG ulIntResult;
//
// calculate starting XSrc based on LeftClipDistance.
//
liMulResult = RtlEnlargedUnsignedMultiply((ULONG)LeftClipDistance,ulXDstToSrcIntCeil);
ulIntResult = liMulResult.LowPart;
liMulResult = RtlEnlargedUnsignedMultiply((ULONG)LeftClipDistance,ulXDstToSrcFracCeil);
liMulResult.HighPart += ulIntResult;
//
// calculate change in Src for .5 change in dst. This is just 1/2 INT:FRAC
//
liHalfDest.LowPart = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
liHalfDest.HighPart = ulXDstToSrcIntCeil >> 1;
//
// add changed together for final XSrcStart
//
liMulResult = RtlLargeIntegerAdd(liMulResult,liHalfDest);
//
// separate int portion and fractional portion
//
XSrcStart = prclSrc->left + liMulResult.HighPart;
ulXFracAccumulator = liMulResult.LowPart;
}
//
// now check for src and dst clipping in Y
//
// Check for a Y clipped src
//
if ((YSrcStart < 0) || (YSrcEnd > (LONG)SrcCy))
{
bYSrcClipped = TRUE;
//
// src is y clipped.
// calculate Src to Dst mapping, then calculate
// new YDstStart and/or YDstEnd based on clipped src
//
// Calculate Y Src to Dst mapping
//
// Src->Dst = ( FLOOR( (2k*HeightDst)/HeightSrc) ) / 2k
//
// where 2k = 2 ^ 32
//
LARGE_INTEGER liHalfk = {0x7fffffff,0x00000000};
LARGE_INTEGER liHeightDst;
LARGE_INTEGER liQuo;
ULONG ulTemp;
bYSrcClipped = TRUE;
liHeightDst.HighPart = HeightDst;
liHeightDst.LowPart = 0;
liQuo = RtlExtendedLargeIntegerDivide(liHeightDst,(LONG)HeightSrc,(PULONG)NULL);
YSrcToDstIntFloor = (ULONG)liQuo.HighPart;
YSrcToDstFracFloor = liQuo.LowPart;
//
// is src top clipped
//
if (YSrcStart < 0)
{
//
// clip top
// clip left Ad = FLOOR[ d/s * As - liHalfK] + 1
//
LONG SrcClipped = -(LONG)YSrcStart;
LONG DeltaDstInt;
LARGE_INTEGER liDeltaDst;
LONG NewHeightSrc = HeightSrc;
NewHeightSrc -= SrcClipped;
if (NewHeightSrc <= 0)
{
return(TRUE);
}
DeltaDstInt = SrcClipped * (LONG)YSrcToDstIntFloor;
liDeltaDst = RtlEnlargedUnsignedMultiply((ULONG)SrcClipped,YSrcToDstFracFloor);
liDeltaDst.HighPart += DeltaDstInt;
//
// add in (2^(k-1) -1) "liHalfk"
//
liDeltaDst = RtlLargeIntegerAdd(liDeltaDst,liHalfk);
YSrcStart = 0;
YDstStart += liDeltaDst.HighPart;
}
if (YSrcEnd > (LONG)SrcCy)
{
//
// clip bottom edge, calc src offset from YSrcStart (SrcClipped)
// clip left Bd = FLOOR[ d/s * Bs + liHalfK]
//
// Note: use original value of HeightSrc, not value reduced
// by top clipping
//
LONG SrcClipped = YSrcEnd - SrcCy;
ULONG DeltaDstInt;
LARGE_INTEGER liDeltaDstFrac;
HeightSrc = HeightSrc - SrcClipped;
//
// check for totally src clipped
//
if (HeightSrc <= 0)
{
return(TRUE);
}
DeltaDstInt = (ULONG)HeightSrc * YSrcToDstIntFloor;
liDeltaDstFrac = RtlEnlargedUnsignedMultiply(HeightSrc,YSrcToDstFracFloor);
liDeltaDstFrac.HighPart += DeltaDstInt;
//
// add in (2^(k-1) -1) "liHalfk"
//
liDeltaDstFrac = RtlLargeIntegerAdd(liDeltaDstFrac,liHalfk);
YSrcEnd = SrcCy;
YDstEnd = prclDst->top + liDeltaDstFrac.HighPart;
}
}
//
// Now clip Dst in Y, and/or calc src clipping effect on dst
//
// adjust top and bottom edges if needed, record
// distance adjusted for fixing the src
//
if (YDstStart < prclBounds->top)
{
YDstStart = prclBounds->top;
}
if (YDstEnd > prclBounds->bottom)
{
YDstEnd = prclBounds->bottom;
}
//
// check for totally clipped out dst
//
if (YDstEnd <= YDstStart)
{
return(TRUE);
}
TopClipDistance = YDstStart - prclDst->top;
if (!bYSrcClipped && (TopClipDistance == 0))
{
ULONG ulTempInt,ulTempFrac;
//
// calc displacement for .5 in dst and add
//
ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
ulTempInt = ulYDstToSrcIntCeil >> 1;
YSrcStart += (LONG)ulTempInt;
ulYFracAccumulator = ulTempFrac;
} else {
//
// calc new src start
//
LARGE_INTEGER liMulResult;
LARGE_INTEGER liHalfDest;
ULONG ulIntResult;
//
// calculate Src offset for clipping offset in Dst
//
liMulResult = RtlEnlargedUnsignedMultiply((ULONG)TopClipDistance,ulYDstToSrcIntCeil);
ulIntResult = liMulResult.LowPart;
liMulResult = RtlEnlargedUnsignedMultiply(TopClipDistance,ulYDstToSrcFracCeil);
liMulResult.HighPart += ulIntResult;
//
// calculate change in Src for .5 change in dst. This is just 1/2 INT:FRAC
//
liHalfDest.LowPart = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
liHalfDest.HighPart = ulYDstToSrcIntCeil >> 1;
//
// add changed together for final YSrcStart
//
liMulResult = RtlLargeIntegerAdd(liMulResult,liHalfDest);
//
// separate int and frac portions
//
YSrcStart = prclSrc->top + liMulResult.HighPart;
ulYFracAccumulator = liMulResult.LowPart;
}
//
// fill out blt structure, then call format specific stretch code
//
#ifdef DBG_STRDIR
if (DbgStrBlt >= 2) {
DbgPrint("StretchBlt:\n");
DbgPrint("XSrcStart = %li\n",XSrcStart);
DbgPrint("YSrcStart = %li\n",YSrcStart);
DbgPrint("XDstStart,XDstEnd = %li to %li\n",XDstStart,XDstEnd);
DbgPrint("YDstStart,YDstEnd = %li to %li\n",YDstStart,YDstEnd);
}
#endif
//
// caclulate starting scan line address, since the inner loop
// routines are format dependent, they must add XDstStart/XSrcStart
// to pjDstScan/pjSrcScan to get the actual starting pixel address
//
StrBlt.pjSrcScan = (PBYTE)pvSrc + (YSrcStart * lDeltaSrc);
StrBlt.pjDstScan = (PBYTE)pvDst + (YDstStart * lDeltaDst);
StrBlt.lDeltaSrc = lDeltaSrc;
StrBlt.XSrcStart = XSrcStart;
StrBlt.XDstStart = XDstStart;
StrBlt.lDeltaDst = lDeltaDst;
StrBlt.XDstEnd = XDstEnd;
StrBlt.YDstCount = YDstEnd - YDstStart;
StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
StrBlt.ulXFracAccumulator = ulXFracAccumulator;
StrBlt.ulYFracAccumulator = ulYFracAccumulator;
pfnStr = pfnStrArray[ (((XDstEnd - XDstStart) < 7) << 3) | iBitmapFormat];
(*pfnStr)(&StrBlt);
//
// save clipped dst in prclTrim
//
prclTrim->left = XDstStart;
prclTrim->right = XDstEnd;
prclTrim->top = YDstStart;
prclTrim->bottom = YDstEnd;
return(TRUE);
}
#if !defined (_MIPS_)
#if !defined (_X86_)
/******************************Public*Routine******************************\
*
* Routine Name
*
* vDirectStretch8
*
* Routine Description:
*
* Stretch blt 8->8
*
* Arguments:
*
* pStrBlt - contains all params for blt
*
* Return Value:
*
* VOID
*
\**************************************************************************/
VOID
vDirectStretch8(
PSTR_BLT pStrBlt
)
{
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
PBYTE pjSrcScan = pStrBlt->pjSrcScan + xSrc;
PBYTE pjSrc;
PBYTE pjDst = pStrBlt->pjDstScan + xDst;
PBYTE pjDstEnd;
LONG yCount = pStrBlt->YDstCount;
ULONG StartAln = (ULONG)((ULONG_PTR)pjDst & 0x03);
LONG WidthX = pStrBlt->XDstEnd - xDst;
LONG WidthXAln;
ULONG EndAln = (ULONG)((ULONG_PTR)(pjDst + WidthX) & 0x03);
ULONG ulDst;
BOOL bExpand = (pStrBlt->ulYDstToSrcIntCeil == 0);
ULONG xAccum;
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG xTmp;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
LONG yInt = 0;
ULONG yTmp;
LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
WidthXAln = WidthX - EndAln - ((4-StartAln) & 0x03);
if (yCount <= 0)
{
return;
}
//
// if this is a shrinking blt, calc src scan line stride
//
if (!bExpand)
{
yInt = pStrBlt->lDeltaSrc * (LONG)pStrBlt->ulYDstToSrcIntCeil;
}
//
// loop drawing each scan line
//
//
// at least 7 wide (DST) blt
//
do {
BYTE jSrc0,jSrc1,jSrc2,jSrc3;
ULONG yTmp = yAccum + yFrac;
pjSrc = pjSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
//
// a single src scan line is being written
//
switch (StartAln) {
case 1:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 2:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 3:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
}
pjDstEnd = pjDst + WidthXAln;
while (pjDst != pjDstEnd)
{
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
jSrc1 = *pjSrc;
xAccum = xTmp + xFrac;
pjSrc = pjSrc + xInt + (xAccum < xTmp);
jSrc2 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
jSrc3 = *pjSrc;
xAccum = xTmp + xFrac;
pjSrc = pjSrc + xInt + (xAccum < xTmp);
ulDst = (jSrc3 << 24) | (jSrc2 << 16) | (jSrc1 << 8) | jSrc0;
*(PULONG)pjDst = ulDst;
pjDst += 4;
}
switch (EndAln) {
case 3:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 2:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
case 1:
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
}
pjSrcScan += yInt;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pjDst += lDstStride;
} while (--yCount);
}
#endif
#endif
/******************************Public*Routine******************************\
*
* Routine Name
*
* vDirectStretch8Narrow
*
* Routine Description:
*
* Stretch blt 8->8 when the width is 7 or less
*
* Arguments:
*
* pStrBlt - contains all params for blt
*
* Return Value:
*
* VOID
*
\**************************************************************************/
VOID
vDirectStretch8Narrow(
PSTR_BLT pStrBlt
)
{
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
PBYTE pjSrcScan = pStrBlt->pjSrcScan + xSrc;
PBYTE pjSrc;
PBYTE pjDst = pStrBlt->pjDstScan + xDst;
PBYTE pjDstEnd;
LONG yCount = pStrBlt->YDstCount;
LONG WidthX = pStrBlt->XDstEnd - xDst;
ULONG ulDst;
ULONG xAccum;
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG xTmp;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
LONG yInt = 0;
ULONG yTmp;
LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
if (yCount <= 0)
{
return;
}
yInt = pStrBlt->lDeltaSrc * (LONG)pStrBlt->ulYDstToSrcIntCeil;
//
// Narrow blt
//
do {
ULONG yTmp = yAccum + yFrac;
BYTE jSrc0;
PBYTE pjDstEndNarrow = pjDst + WidthX;
pjSrc = pjSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
do {
jSrc0 = *pjSrc;
xTmp = xAccum + xFrac;
pjSrc = pjSrc + xInt + (xTmp < xAccum);
*pjDst++ = jSrc0;
xAccum = xTmp;
} while (pjDst != pjDstEndNarrow);
pjSrcScan += yInt;
if (yTmp < yAccum)
{
pjSrcScan += pStrBlt->lDeltaSrc;
}
yAccum = yTmp;
pjDst += lDstStride;
} while (--yCount);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* vDirectStretch16
*
* Routine Description:
*
* Stretch blt 16->16
*
* Arguments:
*
* pStrBlt - contains all params for blt
*
* Return Value:
*
* VOID
*
\**************************************************************************/
VOID
vDirectStretch16(
PSTR_BLT pStrBlt
)
{
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
PUSHORT pusSrcScan = (PUSHORT)(pStrBlt->pjSrcScan) + xSrc;
PUSHORT pusSrc;
PUSHORT pusDst = (PUSHORT)(pStrBlt->pjDstScan) + xDst;
PUSHORT pusDstEnd;
LONG yCount = pStrBlt->YDstCount;
ULONG StartAln = ((ULONG)(ULONG_PTR)pusDst & 0x02) >> 1;
LONG WidthX = pStrBlt->XDstEnd - xDst;
LONG WidthXAln;
ULONG EndAln = ((ULONG)(ULONG_PTR)(pusDst + WidthX) & 0x02) >> 1;
ULONG ulDst;
BOOL bExpand = (pStrBlt->ulYDstToSrcIntCeil == 0);
ULONG xAccum;
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG xTmp;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
LONG yInt = 0;
ULONG yTmp;
LONG lDstStride = pStrBlt->lDeltaDst - 2*WidthX;
WidthXAln = WidthX - EndAln - StartAln;
if (yCount <= 0)
{
return;
}
//
// if this is a shrinking blt, calc src scan line stride
//
if (!bExpand)
{
yInt = pStrBlt->lDeltaSrc * (LONG)pStrBlt->ulYDstToSrcIntCeil;
}
//
// Loop stretching each scan line
//
do {
USHORT usSrc0,usSrc1;
ULONG yTmp = yAccum + yFrac;
pusSrc = pusSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
//
// a single src scan line is being written
//
if (StartAln)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
*pusDst++ = usSrc0;
xAccum = xTmp;
}
pusDstEnd = pusDst + WidthXAln;
while (pusDst != pusDstEnd)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
usSrc1 = *pusSrc;
xAccum = xTmp + xFrac;
pusSrc = pusSrc + xInt + (xAccum < xTmp);
ulDst = (ULONG)((usSrc1 << 16) | usSrc0);
*(PULONG)pusDst = ulDst;
pusDst+=2;
}
if (EndAln)
{
usSrc0 = *pusSrc;
xTmp = xAccum + xFrac;
pusSrc = pusSrc + xInt + (xTmp < xAccum);
*pusDst++ = usSrc0;
}
pusSrcScan = (PUSHORT)((PBYTE)pusSrcScan + yInt);
if (yTmp < yAccum)
{
pusSrcScan = (PUSHORT)((PBYTE)pusSrcScan + pStrBlt->lDeltaSrc);
}
yAccum = yTmp;
pusDst = (PUSHORT)((PBYTE)pusDst + lDstStride);
} while (--yCount);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* vDirectStretch32
*
* Routine Description:
*
* Stretch blt 32->32
*
* Arguments:
*
* pStrBlt - contains all params for blt
*
* Return Value:
*
* VOID
*
\**************************************************************************/
VOID
vDirectStretch32(
PSTR_BLT pStrBlt
)
{
LONG xDst = pStrBlt->XDstStart;
LONG xSrc = pStrBlt->XSrcStart;
PULONG pulSrcScan = (PULONG)(pStrBlt->pjSrcScan) + xSrc;
PULONG pulSrc;
PULONG pulDst = (PULONG)(pStrBlt->pjDstScan) + xDst;
PULONG pulDstEnd;
LONG yCount = pStrBlt->YDstCount;
LONG WidthX = pStrBlt->XDstEnd - xDst;
ULONG ulDst;
BOOL bExpand = (pStrBlt->ulYDstToSrcIntCeil == 0);
ULONG xAccum;
ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
ULONG xTmp;
ULONG yAccum = pStrBlt->ulYFracAccumulator;
ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
LONG yInt = 0;
ULONG yTmp;
LONG lDstStride = pStrBlt->lDeltaDst - 4*WidthX;
if (yCount <= 0)
{
return;
}
//
// if this is a shrinking blt, calc src scan line stride
//
if (!bExpand)
{
yInt = pStrBlt->lDeltaSrc * (LONG)pStrBlt->ulYDstToSrcIntCeil;
}
//
// general
//
do {
ULONG ulSrc;
ULONG yTmp = yAccum + yFrac;
pulSrc = pulSrcScan;
xAccum = pStrBlt->ulXFracAccumulator;
//
// a single src scan line is being written
//
pulDstEnd = pulDst + WidthX;
while (pulDst != pulDstEnd)
{
ulSrc = *pulSrc;
xTmp = xAccum + xFrac;
pulSrc = pulSrc + xInt + (xTmp < xAccum);
*(PULONG)pulDst = ulSrc;
pulDst++;
xAccum = xTmp;
}
pulSrcScan = (PULONG)((PBYTE)pulSrcScan + yInt);
if (yTmp < yAccum)
{
pulSrcScan = (PULONG)((PBYTE)pulSrcScan + pStrBlt->lDeltaSrc);
}
yAccum = yTmp;
pulDst = (PULONG)((PBYTE)pulDst + lDstStride);
} while (--yCount);
}
VOID vDirectStretchError(
PSTR_BLT pstr
)
{
#ifdef DBG_STRDIR
DbgPrint("Illegal stretch blt acceleration called\n");
#endif
}