1292 lines
32 KiB
C++
1292 lines
32 KiB
C++
/*++
|
||
|
||
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
|
||
}
|