Index: dll/win32/comctl32/imagelist.c =================================================================== --- dll/win32/comctl32/imagelist.c (revision 65811) +++ dll/win32/comctl32/imagelist.c (working copy) @@ -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,95 @@ return ret; } +HDC saturate_image( HIMAGELIST himl, IMAGELISTDRAWPARAMS *pimldp, HDC dest_dc, int dest_x, int dest_y, + int src_x, int src_y, int cx, int cy, COLORREF rgbFg) +{ + // BOOL ret = FALSE; + HDC hdc; + HBITMAP bmp = 0;//, mask = 0; + BITMAPINFO *info; + void *bits; + unsigned int *ptr; + int i; + + BYTE intp_r, + intp_g, + intp_b; + + + 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; + + SelectObject(hdc, bmp ); + + BitBlt(hdc, 0, 0, cx, cy, himl->hdcImage, src_x, src_y, SRCCOPY); + + + + // rgbFg = RGB(255, 0, 0); + + if (rgbFg == CLR_DEFAULT) + { + rgbFg = GetSysColor(COLOR_HIGHLIGHT); + } + else if (rgbFg == CLR_NONE) + { + rgbFg = GetTextColor(pimldp->hdcDst); + } + + intp_r = GetRValue(rgbFg); + intp_g = GetGValue(rgbFg); + intp_b = GetBValue(rgbFg); + + for (i = 0, ptr = bits; i < cx * cy; i++, ptr++) + { + COLORREF orig_color = *ptr; + + // BYTE this_r = GetRValue(orig_color); + // BYTE this_g = GetGValue(orig_color); + // BYTE this_b = GetBValue(orig_color); + + /* calculate the effective luminance using the constants from here, adapted to the human eye: + */ + // float mixed_color = (this_r * .30 + + // this_g * .59 + + // this_b * .11); + + // *ptr = RGBA(mixed_color, // * intp_r, + // mixed_color, // * intp_g, + // mixed_color, // * intp_b, + // GetAValue(orig_color)); + + *ptr = RGBA(intp_r, + intp_g, + intp_b, + GetAValue(orig_color)); + + } + + +done: + + if (bmp) + DeleteObject(bmp); + + HeapFree(GetProcessHeap(), 0, info); + + return hdc; +} + /************************************************************************* * ImageList_DrawIndirect [COMCTL32.@] * @@ -1394,7 +1483,7 @@ goto cleanup; hOldImageBmp = SelectObject(hImageDC, hImageBmp); - + /* * To obtain a transparent look, background color should be set * to white and foreground color to black when blitting the @@ -1402,7 +1491,19 @@ */ oldImageFg = SetTextColor( hImageDC, RGB( 0, 0, 0 ) ); oldImageBk = SetBkColor( hImageDC, RGB( 0xff, 0xff, 0xff ) ); + + + if (fState & ILS_SATURATE) + { + hImageListDC = saturate_image(himl, pimldp, 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, + 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,8 +1524,9 @@ 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 ); + ERR("1\n"); goto end; } colour = pimldp->rgbBk; @@ -1433,9 +1535,10 @@ 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 ); + ERR("2\n"); goto end; } @@ -1452,6 +1555,7 @@ { BitBlt ( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, SRCAND); bResult = TRUE; + ERR("3\n"); goto end; } } else { @@ -1484,6 +1588,62 @@ DeleteObject (SelectObject (hImageDC, hOldBrush)); } + /* + * If the ILS_SATURATE bit is enabled we should multiply the + * RGB colors of the original image by the contents of rgbFg. + */ + if (FALSE)// && fState & ILS_SATURATE) + { + DWORD *bmpBuffer; + UINT x, y; + + COLORREF rgbFg = pimldp->rgbFg; + + HBITMAP hDesaturateBmp = CreateCompatibleBitmap(hImageListDC, cx, cy); + SelectObject(hImageListDC, hDesaturateBmp); + + if (rgbFg == CLR_DEFAULT) + { + rgbFg = GetSysColor(COLOR_HIGHLIGHT); + } + else if (rgbFg == CLR_NONE) + { + rgbFg = GetTextColor(pimldp->hdcDst); + } + + + rgbFg = RGB(255, 0, 0); + + /* allocate a temp surface for editing the bitmap during the desaturation */ + bmpBuffer = HeapAlloc(GetProcessHeap(), 0, (cx * cy) * 4); + + if (bmpBuffer) + { + DWORD ret = GetBitmapBits(hDesaturateBmp, (cx * cy) * 4, bmpBuffer); + ERR("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + ERR("desaturate: ret: %#x cx: %#x cy: %#x rgbFg: %#x\r\n", ret, cx, cy, rgbFg); + /* programmatically desaturate the bitmap used for disabled buttons, which is created from the normal one */ + for (y=0; ynmcd.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,35 @@ 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.rgbFg = GetSysColor (COLOR_3DSHADOW); + 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 */