📄 scdcrendimages_i.cpp
字号:
// 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 + -