📄 gperotate.cpp
字号:
unsigned char *ptr;
switch(IRotate)
{
case DMDO_0:
ptr = OrigPtr + CurrentCoord.y * Stride + CurrentCoord.x * BytesPerAccess;
break;
case DMDO_90:
ptr = OrigPtr + (Height - CurrentCoord.x)*Stride + CurrentCoord.y * BytesPerAccess;
break;
case DMDO_180:
ptr = OrigPtr + (Height - CurrentCoord.y)*Stride + (Width - CurrentCoord.x) * BytesPerAccess;
break;
case DMDO_270:
ptr = OrigPtr + CurrentCoord.x * Stride + (Width - CurrentCoord.y) * BytesPerAccess;
break;
default:
ptr = OrigPtr + CurrentCoord.y * Stride + CurrentCoord.x * BytesPerAccess;
break;
}
return ptr;
}
#undef SWAP
#define SWAP(a,b,type) { type tmp=a; a=b; b=tmp; }
// when calling this function, either src or dst or both are the primary surface and rotated.
SCODE GPERotate::EmulatedBltRotate( GPEBltParms *pParms )
{
SCODE (GPE::*pBlt)(GPEBltParms*) = pParms->pBlt;
SCODE sc;
BOOL bSaveBltFunc = FALSE;
if( pParms->pDst->InVideoMemory() ||
( pParms->pSrc && pParms->pSrc->InVideoMemory() ) ||
( pParms->pMask && pParms->pMask->InVideoMemory() ) ||
( pParms->pBrush && pParms->pBrush->InVideoMemory() ) )
{
// If we have a pending blt and now attempt a software operation using
// video memory, the pipeline must be flushed.
WaitForNotBusy();
}
if (pParms->pBlt != EmulatedBltRotate)
{
bSaveBltFunc = TRUE;
}
pParms->pBlt = (SCODE (GPE::*)(GPEBltParms*))EmulatedBltRotate_Internal;
// Check to see if this should be handled by the ClearType(tm) library.
if (pParms->pBlt == (SCODE (GPE::*)(GPEBltParms*))EmulatedBltRotate_Internal)
{
ClearTypeBltSelect(pParms);
}
// Check to see if this should be handled by the AAFont library.
if (pParms->pBlt == (SCODE (GPE::*)(GPEBltParms*))EmulatedBltRotate_Internal)
{
AATextBltSelect(pParms);
}
// Check to see if this should be handled by the emul library.
if (pParms->pBlt == (SCODE (GPE::*)(GPEBltParms*))EmulatedBltRotate_Internal)
{
EmulatedBltSelect02(pParms);
EmulatedBltSelect08(pParms);
EmulatedBltSelect16(pParms);
}
if (pParms->pBlt != (SCODE (GPE::*)(GPEBltParms*))EmulatedBltRotate_Internal)
{
DispPerfType(DISPPERF_ACCEL_EMUL);
}
/* Bilinear is only supported in the PocketPC tree */
#if defined (OSV_PPC) || ( defined (_WINCEOSVER) && (_WINCEOSVER >= 500))
// Check to see if we need to use Bilinear stretching
if (pParms->iMode == BILINEAR)
{
LONG DstWidth = pParms->prclDst->right - pParms->prclDst->left;
LONG DstHeight = pParms->prclDst->bottom - pParms->prclDst->top;
if (pParms->bltFlags == BLT_STRETCH
&& pParms->xPositive
&& pParms->yPositive
&& pParms->pDst->Format() > gpe8Bpp
&& (pParms->rop4 == 0xCCCC
|| pParms->rop4 == 0xEEEE
|| pParms->rop4 == 0x8888)
&& DstWidth > 0
&& DstHeight > 0
&& DstWidth >= pParms->prclSrc->right - pParms->prclSrc->left
&& DstHeight >= pParms->prclSrc->bottom - pParms->prclSrc->top)
{
pParms->pBlt = (SCODE (GPE::*)(GPEBltParms*))EmulatedBltRotate_Bilinear;
}
}
#endif /* OSV_PPC || (_WINCEOSVER>=500) */
sc = (this->*(pParms->pBlt))(pParms);
if (bSaveBltFunc)
pParms->pBlt = pBlt;
return sc;
}
SCODE GPERotate::EmulatedBltRotate_Internal( GPEBltParms *pParms )
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("New Blt. rop4=%04X\r\n"), pParms->rop4));
unsigned char rop3 = (unsigned char)pParms->rop4;
unsigned char maskedROP3 = (unsigned char)( pParms->rop4 >> 8 );
unsigned char unmaskedROP3 = rop3;
int complexBlt = 0;
int width = pParms->prclDst->right - pParms->prclDst->left;
int height = pParms->prclDst->bottom - pParms->prclDst->top;
int x;
RECTL rclBrush;
int dstMatters = ((( pParms->rop4 >> 1 ) ^ pParms->rop4 ) & 0x5555 ) != 0;
int dstXPositive = pParms->xPositive; // These differ from pParms->?Positive if flipping is being performed
int dstYPositive = pParms->yPositive;
RECTL *prclDst = pParms->prclDst;
RECTL tmpRclDst;
int xShrinkStretch = 0;
int xShrink=0;
int xStretch=0;
int yShrinkStretch = 0;
int yShrink=0;
int yStretch=0;
int srcWidth;
int srcHeight;
int rowXAccum, xAccum, xDMajor, xDMinor; // only valid if xShrinkStretch
int yAccum, yDMajor, yDMinor; // only valid if yShrinkStretch
int originalMaskRowInc, originalSrcRowInc; // Used if yShrinkStretch
unsigned char *prevMaskPtr, *prevSrcPtr;
unsigned long prevMaskCache, prevSrcCache;
unsigned long prevMaskCacheState, prevSrcCacheState;
unsigned long originalSrc;
#if defined (_WINCEOSVER) && (_WINCEOSVER >= 500)
unsigned long SrcRGBMask;
#endif
int dstXStartSkip = 0; // Number of dst pixels to not write (left if dstXPositive else right)
int dstYStartSkip = 0; // Number of rows to ignore (top if dstYPositive)
int srcXStartSkip = 0;
int srcYStartSkip = 0;
POINTL prevSrcCoord;
int quickWrite = 0;
#if defined (_WINCEOSVER) && (_WINCEOSVER >= 500)
// Variables used for AlphaBlend.
ULONG RedMask;
ULONG GreenMask;
ULONG BlueMask;
ULONG AlphaMask;
ULONG RedShift;
ULONG GreenShift;
ULONG BlueShift;
ULONG AlphaShift;
ULONG SrcAlphaMask;
ULONG SrcAlphaShift;
BOOL BlendPalette = FALSE;
// If the BLENDFUNCTION isn't Null, the destination pixel value will need
// to be read.
int alphaBlend = 0;
if (*(DWORD *)&(pParms->blendFunction) != *(DWORD *)&g_NullBlendFunction)
{
// Get the format of the source and destination surfaces.
GPEFormat * pDstFormat = pParms->pDst->FormatPtr();
if (pDstFormat->m_PaletteEntries == 3)
{
RedMask = pDstFormat->m_pPalette[0];
GreenMask = pDstFormat->m_pPalette[1];
BlueMask = pDstFormat->m_pPalette[2];
AlphaMask = 0;
// If this is a 32 bpp surface, try to add an "implicit" Alpha mask.
if (EGPEFormatToBpp[pDstFormat->m_eFormat] == 32
&& !(0xFF000000 & (RedMask | GreenMask | BlueMask)))
{
AlphaMask = 0xFF000000;
}
}
else if (pDstFormat->m_PaletteEntries == 4 && EGPEFormatToBpp[pDstFormat->m_eFormat] > 8)
{
RedMask = pDstFormat->m_pPalette[0];
GreenMask = pDstFormat->m_pPalette[1];
BlueMask = pDstFormat->m_pPalette[2];
AlphaMask = pDstFormat->m_pPalette[3];
}
else
{
RedMask = 0x000000FF;
GreenMask = 0x0000FF00;
BlueMask = 0x00FF0000;
AlphaMask = 0xFF000000;
BlendPalette = TRUE;
}
// Compute the shifts for each mask.
ULONG bit;
ULONG Mask = RedMask;
for (bit = 0; Mask && !(Mask & 1); bit++)
{
Mask >>= 1;
}
RedShift = bit;
Mask = GreenMask;
for (bit = 0; Mask && !(Mask & 1); bit++)
{
Mask >>= 1;
}
GreenShift = bit;
Mask = BlueMask;
for (bit = 0; Mask && !(Mask & 1); bit++)
{
Mask >>= 1;
}
BlueShift = bit;
Mask = AlphaMask;
for (bit = 0; Mask && !(Mask & 1); bit++)
{
Mask >>= 1;
}
AlphaShift = bit;
// If this is a per-pixel blend, get the source alpha format.
if (pParms->blendFunction.AlphaFormat)
{
DWORD SavedSrcAlphaMask;
if (pParms->pSrc->FormatPtr()->m_PaletteEntries == 4)
{
SrcAlphaMask = pParms->pSrc->FormatPtr()->m_pPalette[3];
}
else if (pParms->pSrc->FormatPtr()->m_PaletteEntries == 3)
{
// If a fourth mask isn't provided, GDI guarantees that
// 0xFF000000 is a valid alpha mask.
SrcAlphaMask = 0xFF000000;
}
else
{
ASSERT(0);
}
SavedSrcAlphaMask = SrcAlphaMask;
SrcAlphaShift = 0;
while (!(SrcAlphaMask & 1))
{
SrcAlphaMask >>= 1;
SrcAlphaShift++;
}
SrcAlphaMask = SavedSrcAlphaMask;
}
dstMatters = 1;
alphaBlend = 1;
}
#endif /* (_WINCEOSVER >= 500) */
// Handle improperly ordered prclDst resulting from stretch Blt
// Note that only prclDst is ever improperly ordered
if( width < 0 || height < 0 )
{
tmpRclDst = *prclDst;
prclDst = &tmpRclDst;
if( width < 0 )
{
SWAP( tmpRclDst.left, tmpRclDst.right, LONG )
width = -width;
dstXPositive = !dstXPositive;
}
if( height < 0 )
{
SWAP( tmpRclDst.top, tmpRclDst.bottom, LONG )
height = -height;
dstYPositive = !dstYPositive;
}
}
// prclDst is now properly ordered
if( pParms->bltFlags & BLT_STRETCH ) // Check for stretching or shrinking vertically &/or horizontally
{
srcWidth = pParms->prclSrc->right - pParms->prclSrc->left;
srcHeight = pParms->prclSrc->bottom - pParms->prclSrc->top;
if( width > srcWidth )
{
xStretch = 1;
xDMajor = width;
xDMinor = srcWidth;
}
if( width < srcWidth )
{
xShrink = 1;
xDMajor = srcWidth;
xDMinor = width;
}
if( xStretch || xShrink)
{
xShrinkStretch = 1;
// Convert to Bresenham parameters
xDMinor *= 2;
xDMajor = xDMinor - 2 * xDMajor;
rowXAccum = xShrink?(2*width - srcWidth):(3*srcWidth - 2*width);
// loaded into xAccum at start of each row
}
if( height > srcHeight )
{
yStretch = 1;
yDMajor = height;
yDMinor = srcHeight;
}
if( height < srcHeight )
{
yShrink = 1;
yDMajor = srcHeight;
yDMinor = height;
}
if( yStretch || yShrink)
{
yShrinkStretch = 1;
// Convert to Bresenham parameters
yDMinor *= 2;
yDMajor = yDMinor - 2 * yDMajor;
yAccum = yShrink?(2*height - srcHeight):(3*srcHeight - 2*height);
}
if( pParms->prclClip ) // ONLY happens if stretch blting
{
RECTL rclClipped = *prclDst;
if( rclClipped.left < pParms->prclClip->left )
rclClipped.left = pParms->prclClip->left;
if( rclClipped.top < pParms->prclClip->top )
rclClipped.top = pParms->prclClip->top;
if( rclClipped.bottom > pParms->prclClip->bottom )
rclClipped.bottom = pParms->prclClip->bottom;
if( rclClipped.right > pParms->prclClip->right )
rclClipped.right = pParms->prclClip->right;
if( rclClipped.right <= rclClipped.left || rclClipped.bottom <= rclClipped.top )
return S_OK; // the clipping left nothing to do
dstXStartSkip = dstXPositive?(rclClipped.left-prclDst->left):(prclDst->right-rclClipped.right);
dstYStartSkip = dstYPositive?(rclClipped.top-prclDst->top):(prclDst->bottom-rclClipped.bottom);
width = rclClipped.right - rclClipped.left; // Calculate fully clipped destination width
height = rclClipped.bottom - rclClipped.top; // Fully clipped height
}
if( xShrink )
{
while( rowXAccum < 0 )
{
rowXAccum += xDMinor;
srcXStartSkip++;
}
rowXAccum += xDMajor;
}
int skipCount;
for( skipCount = dstXStartSkip; skipCount; skipCount-- )
{
if( xShrink )
{
while( rowXAccum < 0 )
{
rowXAccum += xDMinor;
srcXStartSkip++;
}
srcXStartSkip++; // <--- this is the srcSkip inherent with a dstSkip
rowXAccum += xDMajor;
}
else if( xStretch )
{
if( rowXAccum < 0 )
rowXAccum += xDMinor;
else
{
rowXAccum += xDMajor;
srcXStartSkip++;
}
}
else
srcXStartSkip++;
}
if( yShrink )
{
yAccum += dstYStartSkip * yDMajor;
srcYStartSkip += dstYStartSkip; // <--- this is the srcSkip inherent with a dstSkip
}
else if( yStretch )
{
for( skipCount = dstYStartSkip; skipCount; skipCount-- )
{
if( yAccum < 0 )
yAccum += yDMinor;
else
{
yAccum += yDMajor;
srcYStartSkip++;
}
}
}
else
srcYStartSkip += dstYStartSkip;
}
int transparentBlt = pParms->bltFlags & BLT_TRANSPARENT;
unsigned long transparentColor = pParms->solidColor;
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("pSrc=0x%08x, pDst=0x%08x, pBrush=%08x, pMask=%08x\r\n"),
pParms->pSrc, pParms->pDst, pParms->pBrush, pParms->pMask ));
if( pParms->pBrush )
{
// Calculate an rclBrush so that the correct starting pixel is chosen for the brush iterator
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Pattern depth: %d Bpp\r\n"), EGPEFormatToBpp[pParms->pBrush->Format()] ) );
int topIndent = (pParms->pptlBrush)?pParms->pBrush->Height()-pParms->pptlBrush->y:0;
int leftIndent = (pParms->pptlBrush)?pParms->pBrush->Width()-pParms->pptlBrush->x:0;
rclBrush.left = ( leftIndent + prclDst->left ) % pParms->pBrush->Width();
rclBrush.right = ( leftIndent + prclDst->right ) % pParms->pBrush->Width();
rclBrush.top = ( topIndent + prclDst->top ) % pParms->pBrush->Height();
rclBrush.bottom = ( topIndent + prclDst->bottom ) % pParms->pBrush->Height();
}
PixelIterator mask;
PixelIteratorRotate src, dst;
BrushPixelIterator brush;
src.Ptr = src.RowPtr = src.OrigPtr =
mask.Ptr = mask.RowPtr = brush.Ptr = brush.RowPtr = (unsigned char *)0;
if( pParms->pSrc )
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("pSrc depth: %d Bpp\r\n"), EGPEFormatToBpp[pParms->pSrc->Format()] ) );
src.InitPixelIterator( pParms->pSrc, pParms->xPositive, pParms->yPositive, pParms->prclSrc,
srcXStartSkip, srcYStartSkip );
#if defined (_WINCEOSVER) && (_WINCEOSVER >= 500)
// If we're doing a transparent blt, we will need to know the real RGB
// masks.
if (transparentBlt)
{
GPEFormat * pFormat = pParms->pSrc->FormatPtr();
// Make sure we're dealing with a known format.
if (EGPEFormatToBpp[pFormat->m_eFormat] > 8
&& (pFormat->m_PaletteEntries == 4
||pFormat->m_PaletteEntries == 3))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -