From 8fa8a2368494ab667a7f0c0cc145f6e5fe37f5a1 Mon Sep 17 00:00:00 2001 From: Mark Harmstone Date: Sun, 15 Mar 2015 16:59:37 +0000 Subject: [PATCH] uxtheme: Support images in GetThemeBackgroundRegion. --- dlls/uxtheme/draw.c | 117 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/dlls/uxtheme/draw.c b/dlls/uxtheme/draw.c index 3ef8d819f40..19df3c89ca1 100644 --- a/dlls/uxtheme/draw.c +++ b/dlls/uxtheme/draw.c @@ -1734,6 +1734,120 @@ HRESULT WINAPI GetThemeBackgroundExtent(HTHEME hTheme, HDC hdc, int iPartId, return S_OK; } +static inline void flush_rgn_data( HRGN rgn, RGNDATA *data ) +{ + HRGN tmp = ExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); + + CombineRgn( rgn, rgn, tmp, RGN_OR ); + DeleteObject( tmp ); + data->rdh.nCount = 0; +} + +static inline void add_row( HRGN rgn, RGNDATA *data, int x, int y, int len ) +{ + RECT *rect = (RECT *)data->Buffer + data->rdh.nCount; + + if (len <= 0) return; + rect->left = x; + rect->top = y; + rect->right = x + len; + rect->bottom = y + 1; + data->rdh.nCount++; + if (data->rdh.nCount * sizeof(RECT) > data->rdh.nRgnSize - sizeof(RECT)) + flush_rgn_data( rgn, data ); +} + +static HRESULT create_image_bg_region(HTHEME theme, int part, int state, const RECT *rect, HRGN *rgn) +{ + RECT r; + HDC dc; + HBITMAP bmp; + HRGN hrgn; + BOOL istrans; + COLORREF transcolour; + HBRUSH transbrush; + unsigned int x, y, start; + BITMAPINFO bitmapinfo; + DWORD *bits; + char buffer[4096]; + RGNDATA *data = (RGNDATA *)buffer; + + if (FAILED(GetThemeBool(theme, part, state, TMT_TRANSPARENT, &istrans)) || !istrans) { + *rgn = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom); + return S_OK; + } + + r = *rect; + OffsetRect(&r, -r.left, -r.top); + + if (FAILED(GetThemeColor(theme, part, state, TMT_TRANSPARENTCOLOR, &transcolour))) + transcolour = RGB(255, 0, 255); /* defaults to magenta */ + + dc = CreateCompatibleDC(NULL); + if (!dc) { + WARN("CreateCompatibleDC failed\n"); + return E_FAIL; + } + + bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapinfo.bmiHeader.biWidth = rect->right - rect->left; + bitmapinfo.bmiHeader.biHeight = -(rect->bottom - rect->top); + bitmapinfo.bmiHeader.biPlanes = 1; + bitmapinfo.bmiHeader.biBitCount = 32; + bitmapinfo.bmiHeader.biCompression = BI_RGB; + bitmapinfo.bmiHeader.biSizeImage = bitmapinfo.bmiHeader.biWidth * bitmapinfo.bmiHeader.biHeight * 4; + bitmapinfo.bmiHeader.biXPelsPerMeter = 0; + bitmapinfo.bmiHeader.biYPelsPerMeter = 0; + bitmapinfo.bmiHeader.biClrUsed = 0; + bitmapinfo.bmiHeader.biClrImportant = 0; + + bmp = CreateDIBSection(dc, &bitmapinfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + if (!bmp) { + WARN("CreateDIBSection failed\n"); + DeleteDC(dc); + return E_FAIL; + } + + SelectObject(dc, bmp); + + transbrush = CreateSolidBrush(transcolour); + FillRect(dc, &r, transbrush); + DeleteObject(transbrush); + + if (FAILED(DrawThemeBackground(theme, dc, part, state, &r, NULL))) { + WARN("DrawThemeBackground failed\n"); + DeleteObject(bmp); + DeleteDC(dc); + return E_FAIL; + } + + data->rdh.dwSize = sizeof(data->rdh); + data->rdh.iType = RDH_RECTANGLES; + data->rdh.nCount = 0; + data->rdh.nRgnSize = sizeof(buffer) - sizeof(data->rdh); + + hrgn = CreateRectRgn(0, 0, 0, 0); + + for (y = 0; y < r.bottom; y++, bits += r.right) { + x = 0; + while (x < r.right) { + while (x < r.right && (bits[x] & 0xffffff) == transcolour) x++; + start = x; + while (x < r.right && !((bits[x] & 0xffffff) == transcolour)) x++; + add_row( hrgn, data, rect->left + start, rect->top + y, x - start ); + } + } + + if (data->rdh.nCount > 0) flush_rgn_data(hrgn, data); + + *rgn = hrgn; + + DeleteObject(bmp); + DeleteDC(dc); + + return S_OK; +} + /*********************************************************************** * GetThemeBackgroundRegion (UXTHEME.@) * @@ -1755,8 +1869,7 @@ HRESULT WINAPI GetThemeBackgroundRegion(HTHEME hTheme, HDC hdc, int iPartId, GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype); if(bgtype == BT_IMAGEFILE) { - FIXME("Images not handled yet\n"); - hr = ERROR_CALL_NOT_IMPLEMENTED; + hr = create_image_bg_region(hTheme, iPartId, iStateId, pRect, pRegion); } else if(bgtype == BT_BORDERFILL) { *pRegion = CreateRectRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);