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

📄 scdcrendimages_i.cpp

📁 Source code for EMFexplorer 1.0
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		// TODO: use the foreground ROP where the mask is 1,
		// and the background ROP where the mask is 0
		// For now, just do like plgblt

		// Create alpha bitmap
		// We need a top-down image for GDI+. So bottom-up images must ne flipped.
		HBITMAP hbm = SCBuildAlphaBitmap(pBits, pBmi, dwUsage, pExpandedMask, bFlip);
		if (hbm)
		{
			Rect destRect(pDest->left, pDest->top, PRECT_WIDTH(pDest), PRECT_HEIGHT(pDest));
#if 0
			// won't work. GDI+ would discard transparency information.
			#if 0
			// Nither this:
			Bitmap bmp(hbm, (HPALETTE)NULL);
			#else
			// Nor this:
			DIBSECTION ds;
			GetObject(hbm, sizeof(DIBSECTION), &ds);
			Bitmap bmp((BITMAPINFO*)&ds.dsBmih, ds.dsBm.bmBits);
			#endif
#else
			// We must access the GDI+ bits and update them in 32bpp format
			DIBSECTION ds;
			GetObject(hbm, sizeof(DIBSECTION), &ds);
			Bitmap bmp(iWidth, iHeight, 4*iWidth,
				PixelFormat32bppARGB, (BYTE*)ds.dsBm.bmBits); 
#endif
			// Draw the alpha bitmap
			m_pGraphics->DrawImage(&bmp, destRect,
				pSrc->left, pSrc->top, PRECT_WIDTH(pSrc), PRECT_HEIGHT(pSrc), UnitPixel, m_pImgAttribs);

			DeleteObject(hbm);
		}

		delete [] pExpandedMask;
	}
}

///
///	Transparent blt (for 4bpp and 8bpp).
///		Note: dwRop3 Stores the transparent color.
///
void CSCEMFdcRenderer::SCDrawImageTransparent(LPCRECT pDest, LPCRECT pSrc, LPCBYTE pBits,
								 LPCBITMAPINFO pBmi, DWORD dwUsage, DWORD dwRop3,
								 XFORM* pXForm, COLORREF crBkColorSrc)
{
	ASSERT(m_pGraphics);
	ASSERT(pBmi && pBits && pDest && pSrc);
	//32bpp should use AlphaBlend
	//ASSERT(4==pBmi->bmiHeader.biBitCount || 8==pBmi->bmiHeader.biBitCount);

	// dwUsage can be DIB_RGB_COLORS
	ASSERT(dwUsage==DIB_RGB_COLORS);

	// Make up the opaque bitmap
	Bitmap bmp(pBmi, (VOID*)pBits); 
	ASSERT(bmp.GetLastStatus()==Ok);

	// Create transparency attributes
	COLORREF crTransparentColor = (COLORREF)dwRop3;
	ColorMap clrMap;
	clrMap.oldColor = Color(255, GetRValue(crTransparentColor), GetGValue(crTransparentColor), GetBValue(crTransparentColor));
	clrMap.newColor = Color(0, GetRValue(crTransparentColor), GetGValue(crTransparentColor), GetBValue(crTransparentColor));

	ImageAttributes imgAttribs;
	imgAttribs.SetRemapTable(1, &clrMap, ColorAdjustTypeBitmap);

	// Note: very special stuff here.
	// Convert sizes when a source transformation is present
	Matrix SvdMatrix;
	RECT rcSrc;
	if (pXForm)
	{
		// save current transform
		m_pGraphics->GetTransform(&SvdMatrix);

		// Convert the source with the source transform only
		// (because pXForm is the "world-space to page-space transformation of
		// the source device context" -- not the destination device -- when the record was registered)
		CopyRect(&rcSrc, pSrc);
		pSrc = &rcSrc;

		Matrix matrix(pXForm->eM11, pXForm->eM12, pXForm->eM21, pXForm->eM22,
			pXForm->eDx, pXForm->eDy);
		matrix.TransformPoints((Point*)pSrc, 2);
	}

	// Destination
	Rect destRect(pDest->left, pDest->top, PRECT_WIDTH(pDest), PRECT_HEIGHT(pDest));

	// Draw the alpha bitmap
	m_pGraphics->DrawImage(&bmp, destRect,
		pSrc->left, pSrc->top, PRECT_WIDTH(pSrc), PRECT_HEIGHT(pSrc), UnitPixel, &imgAttribs);
}


///
///	Alpha blend
///		Note: dwRop3 Stores the blend function (a global alpha value to be applied to
///		the entire source bitmap, and format information for the source bitmap).
///
void CSCEMFdcRenderer::SCDrawImageAlpha(LPCRECT pDest, LPCRECT pSrc, LPCBYTE pBits,
								 LPCBITMAPINFO pBmi, DWORD dwUsage, DWORD dwRop3,
								 XFORM* pXForm, COLORREF crBkColorSrc)
{
	ASSERT(m_pGraphics);
	ASSERT(pBmi && pBits && pDest && pSrc);

	// dwUsage can be DIB_RGB_COLORS
	ASSERT(dwUsage==DIB_RGB_COLORS);

	// Make up the opaque bitmap
	Bitmap bmp(pBmi, (VOID*)pBits); 
	ASSERT(bmp.GetLastStatus()==Ok);

	// Create transparency attributes
	BLENDFUNCTION& blend = (BLENDFUNCTION&)dwRop3;
	ASSERT(AC_SRC_OVER==blend.BlendOp);
	ASSERT(0==blend.BlendFlags);

	FLOAT fSCA = float(blend.SourceConstantAlpha)/255.0f;
	ColorMatrix colorMatrix =
	{1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
	 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
	 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
	 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
	 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};

#if 1
	// Very confusing GDI documentation (either in preliminary or in final version)
	// We assume "has per-pixel alpha values" means "32bpp with alpha in the high-order byte",
	// which doesn't not exclude having alpha in a color table in other cases.
	if (AC_SRC_ALPHA==blend.AlphaFormat)
	{// image has per-pixel alpha values (in the image data?)
		// "When the AlphaFormat parameter is AC_SRC_ALPHA, the source bitmap must be 32 bpp"
		ASSERT(32==pBmi->bmiHeader.biBitCount);

		if (255!=blend.SourceConstantAlpha)
		{
			// "If the source has both the SourceConstantAlpha (that is, it is not 0xFF)
			// and per-pixel alpha, the source is pre-multiplied by the SourceConstantAlpha
			// and then the blend is based on the per-pixel alpha, as shown in the following table"
			// Src.rgb = Src.rgb * SourceConstantAlpha / 255.0
			// Src.Alpha = Src.Alpha * SourceConstantAlpha / 255.0
			// Dst.rgb = Src.rgb  + (1 - Src.Alpha) * Dst.rgb
			// Dst.Alpha = Src.Alpha + (1 - Src.Alpha) * Dst.Alpha
			colorMatrix.m[0][0] = 
			colorMatrix.m[0][1] = 
			colorMatrix.m[0][2] = 
			colorMatrix.m[1][0] = 
			colorMatrix.m[1][1] = 
			colorMatrix.m[1][2] = 
			colorMatrix.m[2][0] = 
			colorMatrix.m[2][1] = 
			colorMatrix.m[2][2] = fSCA;
			colorMatrix.m[3][3] = fSCA;

			// TODO: we don't have acces to the dest: call GDI.
		}
		// else the alpha channel, alone, controls transparency
			// Dst.rgb = Src.rgb + (1 - Src.Alpha) * Dst.rgb
			// Dst.alpha = Src.Alpha + (1 - Src.Alpha) * Dst.Alpha
	} else
	{// source bitmap has no per-pixel alpha value (in the image data?)
		// "If the source bitmap has no per-pixel alpha value (that is, AC_SRC_ALPHA is
		// not set), the SourceConstantAlpha value determines the blend of the source and
		// destination bitmaps,  as shown in the following table"
		if (255!=blend.SourceConstantAlpha)
		{// the blend is based on a constant source alpha value
			// let SCA = SourceConstantAlpha
			// Dst.rgb = Src.rgb * (SCA/255.0) + Dst.rgb * (1.0 - (SCA/255.0))
			// Dst.Alpha = Src.Alpha * (SCA/255.0) + Dst.Alpha * (1.0 - (SCA/255.0))
			colorMatrix.m[0][0] = 
			colorMatrix.m[0][1] = 
			colorMatrix.m[0][2] = 
			colorMatrix.m[1][0] = 
			colorMatrix.m[1][1] = 
			colorMatrix.m[1][2] = 
			colorMatrix.m[2][0] = 
			colorMatrix.m[2][1] = 
			colorMatrix.m[2][2] = fSCA;
			colorMatrix.m[3][3] = fSCA;

			// TODO: we don't have acces to the dest: call GDI.
		} else
		{// source bitmap has per-pixel alpha (in a color table?)
			// "If the source bitmap does not use SourceConstantAlpha
			// (that is, it equals 0xFF), the per-pixel alpha determines the blend of
			// the source and destination bitmaps"
			// Dst.rgb = Src.rgb + (1 - Src.Alpha) * Dst.rgb
			// Dst.alpha = Src.Alpha + (1 - Src.Alpha) * Dst.Alpha
		}
	}
#endif
	
	ImageAttributes imgAttribs;
	imgAttribs.SetColorMatrix(&colorMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap);

	// Note: very special stuff here.
	// Convert sizes when a source transformation is present
	Matrix SvdMatrix;
	RECT rcSrc;
	if (pXForm)
	{
		// save current transform
		m_pGraphics->GetTransform(&SvdMatrix);

		// Convert the source with the source transform only
		// (because pXForm is the "world-space to page-space transformation of
		// the source device context" -- not the destination device -- when the record was registered)
		CopyRect(&rcSrc, pSrc);
		pSrc = &rcSrc;

		Matrix matrix(pXForm->eM11, pXForm->eM12, pXForm->eM21, pXForm->eM22,
			pXForm->eDx, pXForm->eDy);
		matrix.TransformPoints((Point*)pSrc, 2);
	}

	// Destination
	Rect destRect(pDest->left, pDest->top, PRECT_WIDTH(pDest), PRECT_HEIGHT(pDest));

	// Draw the alpha bitmap
	m_pGraphics->DrawImage(&bmp, destRect,
		pSrc->left, pSrc->top, PRECT_WIDTH(pSrc), PRECT_HEIGHT(pSrc), UnitPixel, &imgAttribs);
}

///
///	Pattern Blt: uses the ROP or the current brush to fill the given rectangle.
///
void CSCEMFdcRenderer::SCPatBlt(LPCRECT pDest, DWORD dwRop3, XFORM* pXForm/*=NULL*/)
{
	ASSERT(m_pGraphics);
	ASSERT(pDest);

	Rect destRect(pDest->left, pDest->top, PRECT_WIDTH(pDest), PRECT_HEIGHT(pDest));

	switch (dwRop3)
	{
	case PATCOPY:
		// "Copies the specified pattern into the destination bitmap."
		//ASSERT(m_pBrush);
		if (m_pBrush)
		{
			// include border (see T_SCDrawPolygon for documentation)?
			//destRect.Inflate(1, 1); // No. PatBlt uses no pen.
			m_pGraphics->FillRectangle(m_pBrush, destRect);
		} else
		{// Want to patblt with NULL brush?
			TRACE0("Patblt with NULL brush");
		}
		return;
		
//		case PATINVERT:
//			// "Combines the colors of the specified pattern with the colors of the
//			// destination rectangle by using the Boolean XOR operator."
//			// => needs merging
//			break;
//			
//		case DSTINVERT:
//			// "Inverts the destination rectangle."
//			// => needs merging
//			break;
		
	case BLACKNESS:
		// "Fills the destination rectangle using the color associated with index 0
		// in the physical palette."
		// (This color is black for the default physical palette.)
		SCSysPaletteFillRect(this, destRect, 0);
		return;

	case WHITENESS:
		// "Fills the destination rectangle using the color associated with index 1
		// in the physical palette. This color is white for the default physical palette."
		// Bogus GDI documentation?: index 1 doesn't correspond to WHITENESS as expected
		// (And we know that the 20 static colors (reserved) use the following indices:
		// 0-9, 246-255; but that's true for Windows 3.0 and 3.1; for other systems, !!??)
		#if 0
			SCSysPaletteFillRect(this, destRect, 1);   // won't work
		#else
			SCSysPaletteFillRect(this, destRect, 255); // awaiting bug?
		#endif
		return;

//		default:
//			ASSERT(0); // not supported
	}

#if 0
	// Mixing GDI and GDI+ may require reducing interpolation quality
	InterpolationMode uiOldMode = m_pGraphics->GetInterpolationMode();
	if (uiOldMode!=InterpolationModeNearestNeighbor)
		m_pGraphics->SetInterpolationMode(InterpolationModeNearestNeighbor);

	SCMergeAreaWithPattern(this, destRect, dwRop3);

	if (uiOldMode!=InterpolationModeNearestNeighbor)
		m_pGraphics->SetInterpolationMode(uiOldMode);
#else
	SCMergeAreaWithPattern(this, destRect, dwRop3);
#endif
}

///
///	Set the pixel at the specified coordinates to the closest approximation of the specified color.
///
void CSCEMFdcRenderer::SCDrawPixel(POINTL ptlPixel, COLORREF crColor)
{
	ASSERT(m_pGraphics);

	Rect rcDest(ptlPixel.x, ptlPixel.y, 1, 1);
	Color PixelColor;
	PixelColor.SetFromCOLORREF(crColor);
	SolidBrush PixelBrush(PixelColor);

	m_pGraphics->FillRectangle(&PixelBrush, rcDest);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -