You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
8.5 KiB
295 lines
8.5 KiB
/***************************************************************************\
|
|
* Module Name: wmicon.c
|
|
*
|
|
* Icon Drawing Routines
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* 22-Jan-1991 MikeKe from win30
|
|
* 13-Jan-1994 JohnL rewrote from Chicago (m5)
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#define GetCWidth(cxOrg, lrF, cxDes) \
|
|
(cxOrg ? cxOrg : ((lrF & DI_DEFAULTSIZE) ? SYSMET(CXICON) : cxDes))
|
|
|
|
#define GetCHeight(cyOrg, lrF, cyDes) \
|
|
(cyOrg ? cyOrg : ((lrF & DI_DEFAULTSIZE) ? SYSMET(CYICON) : cyDes))
|
|
|
|
/***************************************************************************\
|
|
* BltIcon
|
|
*
|
|
* Note: We use the following DI flags to indicate what bitmap to draw:
|
|
* DI_IMAGE - render the color image bits (also known as XOR image)
|
|
* DI_MASK - render the mask bits (also known and AND image)
|
|
* DI_NORMAL - even though this is normally used to indicate that both the
|
|
* mask and the image pieces of the icon should be rendered, it
|
|
* is used here to indicate that the alpha channel should be
|
|
* rendered. See _DrawIconEx.
|
|
\***************************************************************************/
|
|
BOOL BltIcon(
|
|
HDC hdc,
|
|
int x,
|
|
int y,
|
|
int cx,
|
|
int cy,
|
|
HDC hdcSrc,
|
|
PCURSOR pcur,
|
|
UINT diFlag,
|
|
LONG rop)
|
|
{
|
|
HBITMAP hbmpSave;
|
|
HBITMAP hbmpUse;
|
|
LONG rgbText;
|
|
LONG rgbBk;
|
|
int nMode;
|
|
int yBlt = 0;
|
|
|
|
/*
|
|
* Setup the DC for drawing
|
|
*/
|
|
switch (diFlag) {
|
|
default:
|
|
case DI_IMAGE:
|
|
hbmpUse = pcur->hbmColor;
|
|
|
|
/*
|
|
* If there isn't an explicit color bitmap, it is encoded
|
|
* along with the mask, but in the second half.
|
|
*/
|
|
if (NULL == hbmpUse) {
|
|
hbmpUse = pcur->hbmMask;
|
|
yBlt = pcur->cy / 2;
|
|
}
|
|
break;
|
|
|
|
case DI_MASK:
|
|
hbmpUse = pcur->hbmMask;
|
|
break;
|
|
|
|
case DI_NORMAL:
|
|
UserAssert(pcur->hbmUserAlpha != NULL);
|
|
hbmpUse = pcur->hbmUserAlpha;
|
|
break;
|
|
}
|
|
|
|
rgbBk = GreSetBkColor(hdc, 0x00FFFFFFL);
|
|
rgbText = GreSetTextColor(hdc, 0x00000000L);
|
|
nMode = SetBestStretchMode(hdc, pcur->bpp, FALSE);
|
|
|
|
hbmpSave = GreSelectBitmap(hdcSrc, hbmpUse);
|
|
|
|
if (diFlag == DI_NORMAL) {
|
|
BLENDFUNCTION bf;
|
|
bf.BlendOp = AC_SRC_OVER;
|
|
bf.BlendFlags = AC_MIRRORBITMAP;
|
|
bf.SourceConstantAlpha = 0xFF;
|
|
bf.AlphaFormat = AC_SRC_ALPHA;
|
|
|
|
GreAlphaBlend(hdc,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
hdcSrc,
|
|
0,
|
|
yBlt,
|
|
pcur->cx,
|
|
pcur->cy / 2,
|
|
bf,
|
|
NULL);
|
|
}
|
|
else {
|
|
/*
|
|
* Do the output to the surface. By passing in (-1) as the background
|
|
* color, we are telling GDI to use the background-color already set
|
|
* in the DC.
|
|
*/
|
|
GreStretchBlt(hdc,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
hdcSrc,
|
|
0,
|
|
yBlt,
|
|
pcur->cx,
|
|
pcur->cy / 2,
|
|
rop,
|
|
(COLORREF)-1);
|
|
}
|
|
|
|
GreSetStretchBltMode(hdc, nMode);
|
|
GreSetTextColor(hdc, rgbText);
|
|
GreSetBkColor(hdc, rgbBk);
|
|
|
|
GreSelectBitmap(hdcSrc, hbmpSave);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* DrawIconEx
|
|
*
|
|
* Draws icon in desired size.
|
|
*
|
|
\***************************************************************************/
|
|
BOOL _DrawIconEx(
|
|
HDC hdc,
|
|
int x,
|
|
int y,
|
|
PCURSOR pcur,
|
|
int cx,
|
|
int cy,
|
|
UINT istepIfAniCur,
|
|
HBRUSH hbr,
|
|
UINT diFlags)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
BOOL fAlpha = FALSE;
|
|
LONG rop = (diFlags & DI_NOMIRROR) ? NOMIRRORBITMAP : 0;
|
|
|
|
/*
|
|
* If this is an animated cursor, just grab the ith frame and use it
|
|
* for drawing.
|
|
*/
|
|
if (pcur->CURSORF_flags & CURSORF_ACON) {
|
|
|
|
if ((int)istepIfAniCur >= ((PACON)pcur)->cicur) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "DrawIconEx, icon step out of range.");
|
|
goto Done;
|
|
}
|
|
|
|
pcur = ((PACON)pcur)->aspcur[((PACON)pcur)->aicur[istepIfAniCur]];
|
|
}
|
|
|
|
/*
|
|
* We really want to draw an alpha icon if we can. But we need to
|
|
* respect the user's request to draw only the image or only the
|
|
* mask. We decide if we are, or are not, going to draw the icon
|
|
* with alpha information here.
|
|
*/
|
|
if (pcur->hbmUserAlpha != NULL && ((diFlags & DI_NORMAL) == DI_NORMAL)) {
|
|
fAlpha = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Setup defaults.
|
|
*/
|
|
cx = GetCWidth(cx, diFlags, pcur->cx);
|
|
cy = GetCHeight(cy, diFlags, (pcur->cy / 2));
|
|
|
|
if (hbr) {
|
|
|
|
HBITMAP hbmpT = NULL;
|
|
HDC hdcT;
|
|
HBITMAP hbmpOld;
|
|
POLYPATBLT PolyData;
|
|
|
|
if (hdcT = GreCreateCompatibleDC(hdc)) {
|
|
|
|
if (hbmpT = GreCreateCompatibleBitmap(hdc, cx, cy)) {
|
|
POINT pt;
|
|
BOOL bRet;
|
|
|
|
hbmpOld = GreSelectBitmap(hdcT, hbmpT);
|
|
|
|
/*
|
|
* Set new dc's brush origin in same relative
|
|
* location as passed-in dc's.
|
|
*/
|
|
bRet = GreGetBrushOrg(hdc, &pt);
|
|
/*
|
|
* Bug 292396 - joejo
|
|
* Stop overactive asserts by replacing with RIPMSG.
|
|
*/
|
|
if (bRet != TRUE) {
|
|
RIPMSG0(RIP_WARNING, "DrawIconEx, GreGetBrushOrg failed.");
|
|
}
|
|
|
|
bRet = GreSetBrushOrg(hdcT, pt.x, pt.y, NULL);
|
|
if (bRet != TRUE) {
|
|
RIPMSG0(RIP_WARNING, "DrawIconEx, GreSetBrushOrg failed.");
|
|
}
|
|
|
|
PolyData.x = 0;
|
|
PolyData.y = 0;
|
|
PolyData.cx = cx;
|
|
PolyData.cy = cy;
|
|
PolyData.BrClr.hbr = hbr;
|
|
|
|
bRet = GrePolyPatBlt(hdcT, PATCOPY, &PolyData, 1, PPB_BRUSH);
|
|
if (bRet != TRUE) {
|
|
RIPMSG0(RIP_WARNING, "DrawIconEx, GrePolyPatBlt failed.");
|
|
}
|
|
|
|
/*
|
|
* Output the image to the temporary memoryDC.
|
|
*/
|
|
if (fAlpha) {
|
|
BltIcon(hdcT, 0, 0, cx, cy, ghdcMem, pcur, DI_NORMAL, rop | SRCCOPY);
|
|
}
|
|
else {
|
|
BltIcon(hdcT, 0, 0, cx, cy, ghdcMem, pcur, DI_MASK, rop | SRCAND);
|
|
BltIcon(hdcT, 0, 0, cx, cy, ghdcMem, pcur, DI_IMAGE, rop | SRCINVERT);
|
|
}
|
|
|
|
|
|
/*
|
|
* Blt the bitmap to the original DC.
|
|
*/
|
|
GreBitBlt(hdc, x, y, cx, cy, hdcT, 0, 0, SRCCOPY, (COLORREF)-1);
|
|
|
|
GreSelectBitmap(hdcT, hbmpOld);
|
|
|
|
bRet = GreDeleteObject(hbmpT);
|
|
if (bRet != TRUE) {
|
|
RIPMSG0(RIP_WARNING, "DrawIconEx, GreDeleteObject failed. Possible Leak");
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
}
|
|
|
|
GreDeleteDC(hdcT);
|
|
}
|
|
|
|
} else {
|
|
if (fAlpha) {
|
|
BltIcon(hdc, x, y, cx, cy, ghdcMem, pcur, DI_NORMAL, rop | SRCCOPY);
|
|
} else {
|
|
if (diFlags & DI_MASK) {
|
|
|
|
BltIcon(hdc,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
ghdcMem,
|
|
pcur,
|
|
DI_MASK,
|
|
((diFlags & DI_IMAGE) ? rop | SRCAND : rop | SRCCOPY));
|
|
}
|
|
|
|
if (diFlags & DI_IMAGE) {
|
|
|
|
BltIcon(hdc,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
ghdcMem,
|
|
pcur,
|
|
DI_IMAGE,
|
|
((diFlags & DI_MASK) ? rop | SRCINVERT : rop | SRCCOPY));
|
|
}
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
}
|
|
|
|
Done:
|
|
|
|
return fSuccess;
|
|
}
|