📄 gdi.c
字号:
// 功能描述:
// 将设备相关的颜色值转化为设备无关的颜色值
// 引用:
//
// ************************************************
DWORD _Gdi_UnrealizeColor( DWORD dwRealizeColor, LPCDWORD lpPal, UINT uiPalNum, UINT uiSrcColorType )
{
DWORD dwRetv;
if( uiSrcColorType == PAL_INDEX )
dwRetv = lpPal[dwRealizeColor]; // 颜色类型为基于色板的索引值
else if( uiSrcColorType == PAL_BITFIELD )
{ //颜色类型bit位组合, lpPal里保存有三个 r g b 的 mask值
int leftShift, rightShift;
DWORD dwColorMask;
dwRetv = 0;
for( rightShift = 24; rightShift >= 0 && uiPalNum; rightShift -= 8, uiPalNum--, lpPal++ )
{
dwColorMask = *lpPal;
//得到 需要移位的值
for( leftShift = 32; dwColorMask; leftShift-- )
dwColorMask >>= 1;
dwRetv |= ( ( dwRealizeColor & *lpPal ) << leftShift ) >> rightShift;
}
}
else
dwRetv = 0;
return dwRetv;
}
// **************************************************
// 声明:static DWORD _Gdi_RealizeColor( COLORREF clRgbColor, DWORD * lpPal, UINT uiPalNum, UINT uiDestColorType )
// 参数:
// IN clRgbColor - 设备无关的颜色值
// IN uiDestColorType - 颜色类型
// IN lpPal - 色板指针
// IN uiPalNum - 色板项目数
// 返回值:
// 假如成功,返回设备相关的颜色值;否则,返回0
// 功能描述:
// 将设备无关的颜色值转化为设备相关的颜色值
// 引用:
//
// ************************************************
// return dest format
DWORD _Gdi_RealizeColor( COLORREF clRgbColor, LPCDWORD lpPal, UINT uiPalNum, UINT uiDestColorType )
{
DWORD dwRetv;
if( uiDestColorType == PAL_INDEX )
{ // 颜色类型为基于色板的索引值
long minDiff, curDiff;
UINT uiPalCount = uiPalNum;
minDiff = 0x7fffffffl;
dwRetv = uiPalNum;
for( ; uiPalCount; uiPalCount--, lpPal++ )
{
if( clRgbColor == *lpPal )
{
dwRetv = uiPalCount;
break;
}
else
{ //得到距离
LPBYTE lpbSrc = (LPBYTE)&clRgbColor;
LPBYTE lpbDest = (LPBYTE)lpPal;
long lDiff;
curDiff = *lpbSrc++ - *lpbDest++;
curDiff *= curDiff;
lDiff = *lpbSrc++ - *lpbDest++;
curDiff += lDiff * lDiff;
lDiff = *lpbSrc - *lpbDest;
curDiff += lDiff * lDiff;
}
if( curDiff < minDiff )
{ //得到最短距离
minDiff = curDiff;
dwRetv = uiPalCount;
}
}
dwRetv = uiPalNum - dwRetv;
}
else if( uiDestColorType == PAL_BITFIELD )
{ //颜色类型bit位组合, lpPal里保存有三个 r g b 的 mask值
int leftShift, rightShift;
DWORD dwColorMask;
dwRetv = 0;
for( leftShift = 24; leftShift >= 0 && uiPalNum; leftShift -= 8, uiPalNum--, lpPal++ )
{
dwColorMask = *lpPal;
//得到 需要移位的值
for( rightShift = 32; dwColorMask; rightShift-- )
dwColorMask >>= 1;
dwRetv |= ( ( clRgbColor << leftShift ) >> rightShift ) & *lpPal;
}
}
else
dwRetv = 0;
return dwRetv;
}
// **************************************************
// 声明:BOOL PixelTransfer(
// _LPGDCDATA lpdcDest,//_LPCDISPLAYDRV lpDestDispDrv,
// _LPPIXELDATA lpPixDest,
// LPRECT lprcDest,
// _LPGDCDATA lpdcSrc,//_LPCDISPLAYDRV lpSrcDispDrv,
// _LPPIXELDATA lpPixSrc,
// LPRECT lprcSrc,
// _LPPIXELDATA lpPixMask, // if bltmask , it is valid
// UINT uiMaskRopSrc, // if bltmask , it is valid
// UINT uiMaskRopDest // if bltmask , it is valid
// DWORD clrTransparent // if == -1 , menau not transparent option invalid
// )
// 参数:
// IN lpdcDest - 目标DC对象 //lpDestDispDrv - 目标驱动程序接口
// IN lpPixDest - 目标点结构指针
// IN lprcDest - 目标矩形
// IN lpdcSrc - 源DC对象 //lpSrcDispDrv - 源驱动程序接口
// IN lpPixSrc - 源点结构指针
// IN lprcSrc - 源矩形
// IN lpPixMask - 屏蔽点(假如有屏蔽位传送功能) // if bltmask , it is valid
// IN uiMaskRopSrc - 对源的屏蔽操作(假如有屏蔽位传送功能) // if bltmask , it is valid
// IN uiMaskRopDest - 对目标屏蔽操作 (假如有屏蔽位传送功能) // if bltmask , it is valid
// IN clrTransparent - 透明颜色,用于透明传输(如果为-1,非透明) // if == -1 , not transparent option
// 假如 (clTransparent & 0x80000000) != 0,
// 则说明 clTransparent 是表示一个在源位图的设备相关的颜色值,否则,是一个RGB值
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 在两个不同的位图格式之间传送位图
// 引用:
//
// ************************************************
#define DEBUG_PIXEL_TRANSFER 0
static BOOL PixelTransfer( _LPGDCDATA lpdcDest,//_LPCDISPLAYDRV lpDestDispDrv,
_LPPIXELDATA lpPixDest,
LPRECT lprcDest,
_LPGDCDATA lpdcSrc,//_LPCDISPLAYDRV lpSrcDispDrv,
_LPPIXELDATA lpPixSrc,
LPRECT lprcSrc,
_LPPIXELDATA lpPixMask, // if bltmask , it is valid
UINT uiMaskRopSrc, // if bltmask , it is valid
UINT uiMaskRopDest, // if bltmask , it is valid
DWORD clrTransparent // if not -1 , invalid
)
{
_LPCDISPLAYDRV lpDestDispDrv = lpdcDest->lpDispDrv;
_LPCDISPLAYDRV lpSrcDispDrv = lpdcSrc->lpDispDrv;
int x, y;
int width, height;
int xSrcOffset, ySrcOffset, xDestOffset, yDestOffset;
COLORREF clrPrev = -1;
COLORREF clrCur, clrRgb = 0;
_LPBITMAP_DIB lpSrcDIB = (_LPBITMAP_DIB)lpPixSrc->lpDestImage;
WORD bmType = lpSrcDIB->bitmap.bmFlags & BF_DIB;
DWORD * lpPal;
UINT uiPalNum;
int yDir = 1;
UINT clrRealTransparent = -1; //设备相关的颜色值
if( bmType )
{ //源位图为DIB格式
lpPal = (DWORD*)&lpSrcDIB->palEntry[0];
uiPalNum = lpSrcDIB->biClrUsed;
yDir = lpSrcDIB->biDir;
//颜色值为指向调色板的索引值
if( lpSrcDIB->biCompression == BI_RGB )
bmType = PAL_INDEX;
else if( lpSrcDIB->biCompression == BI_BITFIELDS )
bmType = PAL_BITFIELD; //颜色值为位图域
else
return FALSE;
}
//目标宽度和高度
width = lprcDest->right - lprcDest->left;
height = lprcDest->bottom - lprcDest->top;
//RETAILMSG( 1, ( "PixelTransfer.\r\n" ) );
//源起始位置在位图中的偏移
xSrcOffset = lprcSrc->left;
ySrcOffset = lprcSrc->top;
//目标起始位置在位图中的偏移
xDestOffset = lprcDest->left;
yDestOffset = lprcDest->top;
if( clrTransparent != -1 )
{ //需要透明传输
if( clrTransparent & TB_DEV_COLOR )
{ //clrTransparent 是设备相关的值
clrRealTransparent = clrTransparent & (~TB_DEV_COLOR);
}
else
{ // clrTransparent是RGB值,将其转到设备相关的值
if( bmType && uiPalNum )
{
clrRealTransparent = _Gdi_RealizeColor( clrTransparent, lpPal, uiPalNum, bmType );
}
else //get default
clrRealTransparent = lpSrcDispDrv->lpRealizeColor( clrTransparent, NULL, 0, 0 );
}
}
for( y = 0; y < height; y++ )
{ // 每一行
for( x = 0; x < width; x++ )
{ // 每一列
//2004.07-01 - remove, 多判断
//if( bmType && yDir < 0 )
if( yDir < 0 )
//
{
lpPixSrc->y = lpSrcDIB->bitmap.bmHeight - (y + ySrcOffset) - 1;
}
else
{
lpPixSrc->y = y + ySrcOffset;
}
lpPixSrc->x = x + xSrcOffset;
//得到源点设备相关颜色值
clrCur = lpSrcDispDrv->lpGetPixel( lpPixSrc );
if( clrCur != clrRealTransparent )
{ //如果非透明色,则画之
if( clrCur != clrPrev )
{ //与之前的颜色值相同吗,如果不相同,则将其转化为
//设备无关的值
if( bmType && uiPalNum )
{
clrRgb = _Gdi_UnrealizeColor( clrCur, lpPal, uiPalNum, bmType );
}
else
clrRgb = lpSrcDispDrv->lpUnrealizeColor( clrCur, NULL, 0, 0 );
}
lpPixDest->x = x + xDestOffset;
lpPixDest->y = y + yDestOffset;
if( clrCur != clrPrev )
{ //得到目标相关的值
lpPixDest->color = lpDestDispDrv->lpRealizeColor( clrRgb, lpdcDest->lpdwPal, lpdcDest->wPalNumber, lpdcDest->wPalFormat );
}
//如果需要屏蔽操作,得到对应x,y坐标的屏蔽位
if( lpPixMask )
{
lpPixMask->x = lpPixSrc->x;
lpPixMask->y = lpPixSrc->y;
if( _drvDisplay1BPP.lpGetPixel( lpPixMask ) )
lpPixMask->rop = uiMaskRopSrc;
else
lpPixMask->rop = uiMaskRopDest;
}
//写点到目标位图
lpDestDispDrv->lpPutPixel( lpPixDest );
//缓存当前的颜色值
clrPrev = clrCur;
}
}
}
return TRUE;
}
// **************************************************
// 声明:BOOL WINAPI WinGdi_BitBlt(
// HDC hdcDest - 目标DC
// int xDest - 目标x坐标
// int yDest - 目标x坐标
// int width,
// int height,
// HDC hdcSrc,
// int xSrc,
// int ySrc,
// DWORD dwRop )
// 参数:
// IN hdcDest - 目标DC
// IN xDest - 目标矩形左上角X坐标
// IN yDest - 目标矩形左上角Y坐标
// IN width - 目标矩形宽度
// IN height - 目标矩形高度
// IN hdcSrc - 源DC
// IN xSrc - 源矩形左上角X坐标
// IN ySrc - 源矩形左上角Y坐标
// IN dwRop - 光栅操作码,包括:
// SRCCOPY-拷贝源矩形到目标矩形
// SRCAND--源数据与目标数据做与运算(AND)
// SRCINVERT-源数据与目标数据做异或运算(XOR)
// SRCPAINT-源数据与目标数据做或运算(OR)
// PATCOPY-拷贝模板到目标矩形
// BLACKNESS-用黑色填充目标矩形
// WHITENESS-用白色填充目标矩形
// PATINVERT-模板颜色与目标颜色做异或运算(XOR)
// DSTINVERT-反转目标颜色
// NOTSRCCOPY-拷贝反转的源颜色到目标矩形
// 返回值:
// 假入成功,返回TRUE;否则,返回FALSE
// 功能描述:
// 从源DC向目标DC进行位图传送
// 引用:
// 系统API
// ************************************************
BOOL WINAPI WinGdi_BitBlt(HDC hdcDest, int xDest, int yDest, int width, int height,
HDC hdcSrc, int xSrc, int ySrc, DWORD dwRop )
{
_LPGDCDATA lpdcDest = _GetSafeDrawPtr( hdcDest );//得到目标DC对象指针
_LPGDCDATA lpdcSrc = _GetSafeDrawPtr( hdcSrc );//得到源DC对象指针
_LPRGNDATA lprgn;
_LPRECTNODE lprnNode;
_BLKBITBLT blt;
RECT rcSrc, rcTemp, rcClip, rcDest;
int xoff, yoff, xSrcOff, ySrcOff;
if( lpdcDest && lpdcSrc && lpdcDest->lpDispDrv )
{
_LPCDISPLAYDRV lpDispDrv = lpdcDest->lpDispDrv; //目标DC驱动程序
lprgn = _GetHRGNPtr( lpdcDest->hrgn );
//源/目标位图数据结构
blt.lpDestImage = _GetHBITMAPPtr( lpdcDest->hBitmap );
blt.lpSrcImage = _GetHBITMAPPtr( lpdcSrc->hBitmap );
//当前刷子
blt.lpBrush = &lpdcSrc->brushAttrib;
if( !(lprgn && blt.lpDestImage && blt.lpSrcImage && blt.lpBrush) )
goto _ERROR;
blt.lprcSrc = &rcSrc;
blt.lprcDest = &rcDest;
blt.dwRop = dwRop;
// in bitblt, mono bitmap , 1 mean backcolor, 0 mean textcolor
blt.solidColor = lpdcDest->backColor;
blt.solidBkColor = lpdcDest->textColor;
blt.backMode = lpdcDest->backMode;
//当前源DC在显示设备上的偏移
xSrcOff = XOFFSET( lpdcSrc );
ySrcOff = YOFFSET( lpdcSrc );
//转换源坐标到设备坐标
rcTemp.left = xSrc;
rcTemp.top = ySrc;
rcTemp.right = rcTemp.left + width;
rcTemp.bottom = rcTemp.top + height;
OffsetRect( &rcTemp, xSrcOff, ySrcOff );
//当前目标DC在显示设备上的偏移
xoff = XOFFSET( lpdcDest );
yoff = YOFFSET( lpdcDest );
//转换目标坐标到设备坐标
rcClip.left = xDest;
rcClip.top = yDest;
rcClip.right = rcClip.left + width;
rcClip.bottom = rcClip.top + height;
OffsetRect( &rcClip, xoff, yoff );
//得到源和目标的共同区域
if( rcTemp.left < 0 )
{
rcClip.left -= rcTemp.left;
}
if( rcTemp.top < 0 )
{
rcClip.top -= rcTemp.top;
}
if( rcTemp.right > blt.lpSrcImage->bmWidth )
{
rcClip.right -= rcTemp.right - blt.lpSrcImage->bmWidth;
}
if( rcTemp.bottom > blt.lpSrcImage->bmHeight )
{
rcClip.bottom -= rcTemp.bottom - blt.lpSrcImage->bmHeight;
}
//源坐标在目标上的投射点相对偏移
xoff = xSrc + XOFFSET( lpdcSrc ) - xDest - xoff;
yoff = ySrc + YOFFSET( lpdcSrc ) - yDest - yoff;
//目标裁剪域
lprnNode = lprgn->lpNodeFirst;
if( blt.lpDestImage->bmBits == blt.lpSrcImage->bmBits )
{ //相同的显示面
//遍历每一个裁剪域,如果可显示则绘制
while( lprnNode )
{ //得到内交区域
if( IntersectRect( &rcDest, &rcClip, &lprnNode->rect ) )
{
rcSrc = rcDest;
OffsetRect( &rcSrc, xoff, yoff );
//设置绘制方向为从左到右,从上到下
blt.yPositive = 1;
blt.xPositive = 1;
//
if( IntersectRect( &rcTemp, &rcSrc, &rcDest ) )
{ //因为是相同的显示面,所以必须确定正确的拷贝顺序
//这里表示目标矩形与源矩形有重叠并且必须反向拷贝
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -