Author: gadamopoulos Date: Sun Feb 22 20:59:08 2015 New Revision: 66418
URL: http://svn.reactos.org/svn/reactos?rev=66418&view=rev Log: [COMCTL32] - Implement ILS_SATURATE in our image list implementation - Use ILS_SATURATE when showing icons of disabled buttons in the toolbar
Patch Ismael Ferreras Morezuelas aka swyter CORE-8916
Modified: trunk/reactos/dll/win32/comctl32/imagelist.c trunk/reactos/dll/win32/comctl32/toolbar.c trunk/reactos/include/psdk/wingdi.h
Modified: trunk/reactos/dll/win32/comctl32/imagelist.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/comctl32/imagelis... ============================================================================== --- trunk/reactos/dll/win32/comctl32/imagelist.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/comctl32/imagelist.c [iso-8859-1] Sun Feb 22 20:59:08 2015 @@ -33,7 +33,7 @@ * * TODO: * - Add support for ILD_PRESERVEALPHA, ILD_SCALE, ILD_DPISCALE - * - Add support for ILS_GLOW, ILS_SHADOW, ILS_SATURATE + * - Add support for ILS_GLOW, ILS_SHADOW * - Thread-safe locking */
@@ -1227,7 +1227,7 @@ }
-static BOOL alpha_blend_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int dest_y, +static BOOL alpha_blend_image( HIMAGELIST himl, HDC srce_dc, HDC dest_dc, int dest_x, int dest_y, int src_x, int src_y, int cx, int cy, BLENDFUNCTION func, UINT style, COLORREF blend_col ) { @@ -1252,9 +1252,9 @@ info->bmiHeader.biYPelsPerMeter = 0; info->bmiHeader.biClrUsed = 0; info->bmiHeader.biClrImportant = 0; - if (!(bmp = CreateDIBSection( himl->hdcImage, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done; + if (!(bmp = CreateDIBSection( srce_dc, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done; SelectObject( hdc, bmp ); - BitBlt( hdc, 0, 0, cx, cy, himl->hdcImage, src_x, src_y, SRCCOPY ); + BitBlt( hdc, 0, 0, cx, cy, srce_dc, src_x, src_y, SRCCOPY );
if (blend_col != CLR_NONE) { @@ -1327,6 +1327,66 @@ return ret; }
+HDC saturate_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int dest_y, + int src_x, int src_y, int cx, int cy, COLORREF rgbFg) +{ + HDC hdc = NULL; + HBITMAP bmp = 0; + BITMAPINFO *info; + + unsigned int *ptr; + void *bits; + int i; + + /* create a dc and its device independent bitmap for doing the work, + shamelessly copied from the alpha-blending function above */ + if (!(hdc = CreateCompatibleDC( 0 ))) return FALSE; + if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done; + info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + info->bmiHeader.biWidth = cx; + info->bmiHeader.biHeight = cy; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = 32; + info->bmiHeader.biCompression = BI_RGB; + info->bmiHeader.biSizeImage = cx * cy * 4; + info->bmiHeader.biXPelsPerMeter = 0; + info->bmiHeader.biYPelsPerMeter = 0; + info->bmiHeader.biClrUsed = 0; + info->bmiHeader.biClrImportant = 0; + if (!(bmp = CreateDIBSection(himl->hdcImage, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done; + + /* bind both surfaces */ + SelectObject(hdc, bmp); + + /* copy into our dc the section that covers just the icon we we're asked for */ + BitBlt(hdc, 0, 0, cx, cy, himl->hdcImage, src_x, src_y, SRCCOPY); + + /* loop every pixel of the bitmap */ + for (i = 0, ptr = bits; i < cx * cy; i++, ptr++) + { + COLORREF orig_color = *ptr; + + /* calculate the effective luminance using the constants from here, adapted to the human eye: + http://bobpowell.net/grayscale.aspx */ + float mixed_color = (GetRValue(orig_color) * .30 + + GetGValue(orig_color) * .59 + + GetBValue(orig_color) * .11); + + *ptr = RGBA(mixed_color, mixed_color, mixed_color, GetAValue(orig_color)); + } + +done: + + if (bmp) + DeleteObject(bmp); + + if (info) + HeapFree(GetProcessHeap(), 0, info); + + /* return the handle to our desaturated dc, that will substitute its original counterpart in the next calls */ + return hdc; +} + /************************************************************************* * ImageList_DrawIndirect [COMCTL32.@] * @@ -1403,6 +1463,21 @@ oldImageFg = SetTextColor( hImageDC, RGB( 0, 0, 0 ) ); oldImageBk = SetBkColor( hImageDC, RGB( 0xff, 0xff, 0xff ) );
+ /* + * If the ILS_SATURATE bit is enabled we should multiply the + * RGB colors of the original image by the contents of rgbFg. + */ + if (fState & ILS_SATURATE) + { + hImageListDC = saturate_image(himl, pimldp->hdcDst, pimldp->x, pimldp->y, + pt.x, pt.y, cx, cy, pimldp->rgbFg); + + /* shitty way of getting subroutines to blit at the right place (top left corner), + as our modified imagelist only contains a single image for performance reasons */ + pt.x = 0; + pt.y = 0; + } + has_alpha = (himl->has_alpha && himl->has_alpha[pimldp->i]); if (!bMask && (has_alpha || (fState & ILS_ALPHA))) { @@ -1423,7 +1498,7 @@
if (bIsTransparent) { - bResult = alpha_blend_image( himl, pimldp->hdcDst, pimldp->x, pimldp->y, + bResult = alpha_blend_image( himl, hImageListDC, pimldp->hdcDst, pimldp->x, pimldp->y, pt.x, pt.y, cx, cy, func, fStyle, blend_col ); goto end; } @@ -1433,7 +1508,7 @@
hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour)); PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY ); - alpha_blend_image( himl, hImageDC, 0, 0, pt.x, pt.y, cx, cy, func, fStyle, blend_col ); + alpha_blend_image( himl, hImageListDC, hImageDC, 0, 0, pt.x, pt.y, cx, cy, func, fStyle, blend_col ); DeleteObject (SelectObject (hImageDC, hOldBrush)); bResult = BitBlt( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, SRCCOPY ); goto end; @@ -1527,7 +1602,6 @@ } }
- if (fState & ILS_SATURATE) FIXME("ILS_SATURATE: unimplemented!\n"); if (fState & ILS_GLOW) FIXME("ILS_GLOW: unimplemented!\n"); if (fState & ILS_SHADOW) FIXME("ILS_SHADOW: unimplemented!\n");
Modified: trunk/reactos/dll/win32/comctl32/toolbar.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/comctl32/toolbar.... ============================================================================== --- trunk/reactos/dll/win32/comctl32/toolbar.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/comctl32/toolbar.c [iso-8859-1] Sun Feb 22 20:59:08 2015 @@ -696,10 +696,12 @@ const NMTBCUSTOMDRAW *tbcd, DWORD dwItemCDFlag) { HIMAGELIST himl = NULL; - BOOL draw_masked = FALSE; + BOOL draw_masked = FALSE, draw_desaturated = FALSE; INT index; INT offset = 0; UINT draw_flags = ILD_TRANSPARENT; + IMAGEINFO info = {0}; + BITMAP bm = {0};
if (tbcd->nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE)) { @@ -707,7 +709,18 @@ if (!himl) { himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DEFAULT, &index); - draw_masked = TRUE; + + ImageList_GetImageInfo(himl, index, &info); + GetObjectW(info.hbmImage, sizeof(bm), &bm); + + if (bm.bmBitsPixel == 32) + { + draw_desaturated = TRUE; + } + else + { + draw_masked = TRUE; + } } } else if (tbcd->nmcd.uItemState & CDIS_CHECKED || @@ -738,9 +751,34 @@ index, himl, left, top, offset);
if (draw_masked) + { + /* code path for drawing flat disabled icons without alpha channel */ TOOLBAR_DrawMasked (himl, index, tbcd->nmcd.hdc, left + offset, top + offset, draw_flags); + } + else if (draw_desaturated) + { + /* code path for drawing disabled, alpha-blended (32bpp) icons */ + IMAGELISTDRAWPARAMS imldp = {0}; + + imldp.cbSize = sizeof(imldp); + imldp.himl = himl; + imldp.i = index; + imldp.hdcDst = tbcd->nmcd.hdc, + imldp.x = offset + left; + imldp.y = offset + top; + imldp.rgbBk = CLR_NONE; + imldp.rgbFg = CLR_DEFAULT; + imldp.fStyle = ILD_TRANSPARENT; + imldp.fState = ILS_ALPHA | ILS_SATURATE; + imldp.Frame = 192; + + ImageList_DrawIndirect (&imldp); + } else + { + /* code path for drawing standard icons as-is */ ImageList_Draw (himl, index, tbcd->nmcd.hdc, left + offset, top + offset, draw_flags); + } }
/* draws a blank frame for a toolbar button */
Modified: trunk/reactos/include/psdk/wingdi.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/wingdi.h?rev=6... ============================================================================== --- trunk/reactos/include/psdk/wingdi.h [iso-8859-1] (original) +++ trunk/reactos/include/psdk/wingdi.h [iso-8859-1] Sun Feb 22 20:59:08 2015 @@ -2902,8 +2902,10 @@ #define GetRValue(rgb) ((BYTE)(rgb)) #define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8)) #define GetBValue(rgb) ((BYTE)((rgb)>>16)) +#define GetAValue(rgb) ((BYTE)((rgb)>>24))
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) +#define RGBA(r,g,b,a) ((COLORREF)((((DWORD)(BYTE)(a))<<24) | RGB(r,g,b))) #define PALETTERGB(r,g,b) (0x02000000 | RGB(r,g,b)) #define PALETTEINDEX(i) ((COLORREF)(0x01000000 | (DWORD)(WORD)(i)))