[UXTHEME] Apply Wine commit 2b650fa by Mark Harmstone: Resize source image if destina...
[reactos.git] / reactos / dll / win32 / uxtheme / draw.c
index f0430e7..f8c4950 100644 (file)
@@ -241,6 +241,9 @@ static HRESULT UXTHEME_LoadImage(HTHEME hTheme, HDC hdc, int iPartId, int iState
 
     imagenum = max (min (imagecount, iStateId), 1) - 1;
     GetObjectW(*hBmp, sizeof(bmp), &bmp);
+
+    if(imagecount < 1) imagecount = 1;
+
     if(imagelayout == IL_VERTICAL) {
         int height = bmp.bmHeight/imagecount;
         bmpRect->left = 0;
@@ -274,22 +277,33 @@ static inline BOOL UXTHEME_StretchBlt(HDC hdcDst, int nXOriginDst, int nYOriginD
       255,         /* SourceConstantAlpha */
       AC_SRC_ALPHA /* AlphaFormat */
     };
+
+    BOOL ret = TRUE;
+    int old_stretch_mode;
+    POINT old_brush_org;
+
+    old_stretch_mode = SetStretchBltMode(hdcDst, HALFTONE);
+    SetBrushOrgEx(hdcDst, nXOriginDst, nYOriginDst, &old_brush_org);
+
     if (transparent == ALPHABLEND_BINARY) {
         /* Ensure we don't pass any negative values to TransparentBlt */
-        return TransparentBlt(hdcDst, nXOriginDst, nYOriginDst, abs(nWidthDst), abs(nHeightDst),
+        ret = TransparentBlt(hdcDst, nXOriginDst, nYOriginDst, abs(nWidthDst), abs(nHeightDst),
                               hdcSrc, nXOriginSrc, nYOriginSrc, abs(nWidthSrc), abs(nHeightSrc),
                               transcolor);
-    }
-    if ((transparent == ALPHABLEND_NONE) ||
+    } else if ((transparent == ALPHABLEND_NONE) ||
         !AlphaBlend(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
                     hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
                     blendFunc))
     {
-        return StretchBlt(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+        ret = StretchBlt(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
                           hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
                           SRCCOPY);
     }
-    return TRUE;
+
+    SetBrushOrgEx(hdcDst, old_brush_org.x, old_brush_org.y, NULL);
+    SetStretchBltMode(hdcDst, old_stretch_mode);
+
+    return ret;
 }
 
 /***********************************************************************
@@ -633,9 +647,9 @@ static HRESULT UXTHEME_DrawImageBackground(HTHEME hTheme, HDC hdc, int iPartId,
                                     const DTBGOPTS *pOptions)
 {
     HRESULT hr = S_OK;
-    HBITMAP bmpSrc;
+    HBITMAP bmpSrc, bmpSrcResized = NULL;
     HGDIOBJ oldSrc;
-    HDC hdcSrc;
+    HDC hdcSrc, hdcOrigSrc = NULL;
     RECT rcSrc;
     RECT rcDst;
     POINT dstSize;
@@ -699,6 +713,34 @@ static HRESULT UXTHEME_DrawImageBackground(HTHEME hTheme, HDC hdc, int iPartId,
 
         GetThemeMargins(hTheme, hdc, iPartId, iStateId, TMT_SIZINGMARGINS, NULL, &sm);
 
+        /* Resize source image if destination smaller than margins */
+        if (sm.cyTopHeight + sm.cyBottomHeight > dstSize.y || sm.cxLeftWidth + sm.cxRightWidth > dstSize.x) {
+            if (sm.cyTopHeight + sm.cyBottomHeight > dstSize.y) {
+                sm.cyTopHeight = MulDiv(sm.cyTopHeight, dstSize.y, srcSize.y);
+                sm.cyBottomHeight = dstSize.y - sm.cyTopHeight;
+                srcSize.y = dstSize.y;
+            }
+
+            if (sm.cxLeftWidth + sm.cxRightWidth > dstSize.x) {
+                sm.cxLeftWidth = MulDiv(sm.cxLeftWidth, dstSize.x, srcSize.x);
+                sm.cxRightWidth = dstSize.x - sm.cxLeftWidth;
+                srcSize.x = dstSize.x;
+            }
+
+            hdcOrigSrc = hdcSrc;
+            hdcSrc = CreateCompatibleDC(NULL);
+            bmpSrcResized = CreateBitmap(srcSize.x, srcSize.y, 1, 32, NULL);
+            SelectObject(hdcSrc, bmpSrcResized);
+
+            UXTHEME_StretchBlt(hdcSrc, 0, 0, srcSize.x, srcSize.y, hdcOrigSrc, rcSrc.left, rcSrc.top,
+                               rcSrc.right - rcSrc.left, rcSrc.bottom - rcSrc.top, transparent, transparentcolor);
+
+            rcSrc.left = 0;
+            rcSrc.top = 0;
+            rcSrc.right = srcSize.x;
+            rcSrc.bottom = srcSize.y;
+        }
+
         hdcDst = hdc;
         OffsetViewportOrgEx(hdcDst, rcDst.left, rcDst.top, &org);
 
@@ -803,6 +845,8 @@ draw_error:
     }
     SelectObject(hdcSrc, oldSrc);
     DeleteDC(hdcSrc);
+    if (bmpSrcResized) DeleteObject(bmpSrcResized);
+    if (hdcOrigSrc) DeleteDC(hdcOrigSrc);
     CopyRect(pRect, &rcDst);
     return hr;
 }
@@ -1755,20 +1799,15 @@ static HBITMAP UXTHEME_DrawThemePartToDib(HTHEME hTheme, HDC hdc, int iPartId, i
 static HRGN UXTHEME_RegionFromDibBits(RGBQUAD* pBuffer, RGBQUAD* pclrTransparent, LPCRECT pRect)
 {
     int x, y, xstart;
-#ifdef EXTCREATEREGION_WORKS
     int cMaxRgnRects, cRgnDataSize, cRgnRects;
     RECT* prcCurrent;
     PRGNDATA prgnData;
-#else
-    HRGN hrgnTemp;
-#endif
     ULONG clrTransparent, *pclrCurrent;
     HRGN hrgnRet;
 
     pclrCurrent = (PULONG)pBuffer;
     clrTransparent = *(PULONG)pclrTransparent;
 
-#ifdef EXTCREATEREGION_WORKS
     /* Create a region and pre-allocate memory enough for 3 spaces in one row*/
     cRgnRects = 0;
     cMaxRgnRects = 4* (pRect->bottom-pRect->top);
@@ -1778,9 +1817,6 @@ static HRGN UXTHEME_RegionFromDibBits(RGBQUAD* pBuffer, RGBQUAD* pclrTransparent
     prgnData = (PRGNDATA)HeapAlloc(GetProcessHeap(), 0, cRgnDataSize);
 
     prcCurrent = (PRECT)prgnData->Buffer;
-#else
-    hrgnRet = CreateRectRgn(0,0,0,0);
-#endif
     
     /* Calculate the region rects */
     y=0;
@@ -1804,7 +1840,6 @@ static HRGN UXTHEME_RegionFromDibBits(RGBQUAD* pBuffer, RGBQUAD* pclrTransparent
                     pclrCurrent++;
                 }
 
-#ifdef EXTCREATEREGION_WORKS
                 /* Add the scaned line to the region */
                 SetRect(prcCurrent, xstart, y,x,y+1);
                 prcCurrent++;
@@ -1821,11 +1856,6 @@ static HRGN UXTHEME_RegionFromDibBits(RGBQUAD* pBuffer, RGBQUAD* pclrTransparent
                                                      cRgnDataSize);
                     prcCurrent = (RECT*)prgnData->Buffer + cRgnRects;
                 }
-#else
-                hrgnTemp = CreateRectRgn(xstart, y,x,y+1);
-                CombineRgn(hrgnRet, hrgnRet, hrgnTemp, RGN_OR );
-                DeleteObject(hrgnTemp);
-#endif
             }
             else
             {
@@ -1836,7 +1866,6 @@ static HRGN UXTHEME_RegionFromDibBits(RGBQUAD* pBuffer, RGBQUAD* pclrTransparent
         y++;
     }
 
-#ifdef EXTCREATEREGION_WORKS
     /* Fill the region data header */
     prgnData->rdh.dwSize = sizeof(prgnData->rdh);
     prgnData->rdh.iType = RDH_RECTANGLES;
@@ -1849,7 +1878,6 @@ static HRGN UXTHEME_RegionFromDibBits(RGBQUAD* pBuffer, RGBQUAD* pclrTransparent
 
     /* Free the region data*/
     HeapFree(GetProcessHeap(),0,prgnData);
-#endif
 
     /* return the region*/
     return hrgnRet;