⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gperotate.cpp

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	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 + -