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
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
|
|
}
|