- Sync uxtheme with Wine head
[reactos.git] / reactos / dll / win32 / uxtheme / draw.c
index 237d409..9e22025 100644 (file)
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include "config.h"
@@ -27,6 +27,7 @@
 #include "winbase.h"
 #include "winuser.h"
 #include "wingdi.h"
+#include "vfwmsgs.h"
 #include "uxtheme.h"
 #include "tmschema.h"
 
@@ -51,19 +52,18 @@ extern ATOM atDialogThemeEnabled;
 HRESULT WINAPI EnableThemeDialogTexture(HWND hwnd, DWORD dwFlags)
 {
     static const WCHAR szTab[] = { 'T','a','b',0 };
-    HRESULT hr;
+    BOOL res;
 
-    TRACE("(%p,0x%08lx\n", hwnd, dwFlags);
-    hr = SetPropW (hwnd, MAKEINTATOMW (atDialogThemeEnabled), 
+    TRACE("(%p,0x%08x\n", hwnd, dwFlags);
+    res = SetPropW (hwnd, (LPCWSTR)MAKEINTATOM(atDialogThemeEnabled), 
         (HANDLE)(dwFlags|0x80000000)); 
         /* 0x80000000 serves as a "flags set" flag */
-    if (FAILED(hr))
-          return hr;
+    if (!res)
+          return HRESULT_FROM_WIN32(GetLastError());
     if (dwFlags & ETDT_USETABTEXTURE)
         return SetWindowTheme (hwnd, NULL, szTab);
     else
         return SetWindowTheme (hwnd, NULL, NULL);
-    return S_OK;
  }
 
 /***********************************************************************
@@ -75,7 +75,7 @@ BOOL WINAPI IsThemeDialogTextureEnabled(HWND hwnd)
     TRACE("(%p)\n", hwnd);
 
     dwDialogTextureFlags = (DWORD)GetPropW (hwnd, 
-        MAKEINTATOMW (atDialogThemeEnabled));
+        (LPCWSTR)MAKEINTATOM(atDialogThemeEnabled));
     if (dwDialogTextureFlags == 0) 
         /* Means EnableThemeDialogTexture wasn't called for this dialog */
         return TRUE;
@@ -100,7 +100,7 @@ HRESULT WINAPI DrawThemeParentBackground(HWND hwnd, HDC hdc, RECT *prc)
         hParent = hwnd;
     if(prc) {
         CopyRect(&rt, prc);
-        MapWindowPoints(hwnd, NULL, (LPPOINT)&rt, 2);
+        MapWindowPoints(hwnd, hParent, (LPPOINT)&rt, 2);
         
         clip = CreateRectRgn(0,0,1,1);
         hasClip = GetClipRgn(hdc, clip);
@@ -110,8 +110,8 @@ HRESULT WINAPI DrawThemeParentBackground(HWND hwnd, HDC hdc, RECT *prc)
             IntersectClipRect(hdc, prc->left, prc->top, prc->right, prc->bottom);
     }
     else {
-        GetClientRect(hParent, &rt);
-        MapWindowPoints(hParent, NULL, (LPPOINT)&rt, 2);
+        GetClientRect(hwnd, &rt);
+        MapWindowPoints(hwnd, hParent, (LPPOINT)&rt, 2);
     }
 
     OffsetViewportOrgEx(hdc, -rt.left, -rt.top, &org);
@@ -195,7 +195,6 @@ static PTHEME_PROPERTY UXTHEME_SelectImage(HTHEME hTheme, HDC hdc, int iPartId,
                 WCHAR szPath[MAX_PATH];
                 int imagelayout = IL_HORIZONTAL;
                 int imagecount = 1;
-                int imagenum;
                 BITMAP bmp;
                 HBITMAP hBmp;
                 BOOL hasAlpha;
@@ -208,7 +207,6 @@ static PTHEME_PROPERTY UXTHEME_SelectImage(HTHEME hTheme, HDC hdc, int iPartId,
                 GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_IMAGELAYOUT, &imagelayout);
                 GetThemeInt(hTheme, iPartId, iStateId, TMT_IMAGECOUNT, &imagecount);
 
-                imagenum = max (min (imagecount, iStateId), 1) - 1;
                 GetObjectW(hBmp, sizeof(bmp), &bmp);
                 if(imagelayout == IL_VERTICAL) {
                     reqsize.x = bmp.bmWidth;
@@ -220,7 +218,7 @@ static PTHEME_PROPERTY UXTHEME_SelectImage(HTHEME hTheme, HDC hdc, int iPartId,
                 }
             }
             if(reqsize.x <= size.x && reqsize.y <= size.y) {
-                TRACE("Using image size %ldx%ld, image %d\n", reqsize.x, reqsize.y, i + TMT_IMAGEFILE1);
+                TRACE("Using image size %dx%d, image %d\n", reqsize.x, reqsize.y, i + TMT_IMAGEFILE1);
                 return fileProp;
             }
         }
@@ -339,27 +337,81 @@ static inline BOOL UXTHEME_SizedBlt (HDC hdcDst, int nXOriginDst, int nYOriginDs
 {
     if (sizingtype == ST_TILE)
     {
-        int yOfs = nYOriginDst;
-        int yRemaining = nHeightDst;
-        while (yRemaining > 0)
+        HDC hdcTemp;
+        BOOL result = FALSE;
+
+        if (!nWidthSrc || !nHeightSrc) return TRUE;
+
+        /* For destination width/height less than or equal to source
+           width/height, do not bother with memory bitmap optimization */
+        if (nWidthSrc >= nWidthDst && nHeightSrc >= nHeightDst)
         {
-            int bltHeight = min (yRemaining, nHeightSrc);
-            int xOfs = nXOriginDst;
-            int xRemaining = nWidthDst;
+            int bltWidth = min (nWidthDst, nWidthSrc);
+            int bltHeight = min (nHeightDst, nHeightSrc);
+
+            return UXTHEME_Blt (hdcDst, nXOriginDst, nYOriginDst, bltWidth, bltHeight,
+                                hdcSrc, nXOriginSrc, nYOriginSrc,
+                                transparent, transcolor);
+        }
+
+        /* Create a DC with a bitmap consisting of a tiling of the source
+           bitmap, with standard GDI functions. This is faster than an
+           iteration with UXTHEME_Blt(). */
+        hdcTemp = CreateCompatibleDC(hdcSrc);
+        if (hdcTemp != 0)
+        {
+            HBITMAP bitmapTemp;
+            HBITMAP bitmapOrig;
+            int nWidthTemp, nHeightTemp;
+            int xOfs, xRemaining;
+            int yOfs, yRemaining;
+            int growSize;
+
+            /* Calculate temp dimensions of integer multiples of source dimensions */
+            nWidthTemp = ((nWidthDst + nWidthSrc - 1) / nWidthSrc) * nWidthSrc;
+            nHeightTemp = ((nHeightDst + nHeightSrc - 1) / nHeightSrc) * nHeightSrc;
+            bitmapTemp = CreateCompatibleBitmap(hdcSrc, nWidthTemp, nHeightTemp);
+            bitmapOrig = SelectObject(hdcTemp, bitmapTemp);
+
+            /* Initial copy of bitmap */
+            BitBlt(hdcTemp, 0, 0, nWidthSrc, nHeightSrc, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
+
+            /* Extend bitmap in the X direction. Growth of width is exponential */
+            xOfs = nWidthSrc;
+            xRemaining = nWidthTemp - nWidthSrc;
+            growSize = nWidthSrc;
             while (xRemaining > 0)
             {
-                int bltWidth = min (xRemaining, nWidthSrc);
-                if (!UXTHEME_Blt (hdcDst, xOfs, yOfs, bltWidth, bltHeight,
-                                  hdcSrc, nXOriginSrc, nYOriginSrc, 
-                                  transparent, transcolor))
-                    return FALSE;
-                xOfs += nWidthSrc;
-                xRemaining -= nWidthSrc;
+                growSize = min(growSize, xRemaining);
+                BitBlt(hdcTemp, xOfs, 0, growSize, nHeightSrc, hdcTemp, 0, 0, SRCCOPY);
+                xOfs += growSize;
+                xRemaining -= growSize;
+                growSize *= 2;
+            }
+
+            /* Extend bitmap in the Y direction. Growth of height is exponential */
+            yOfs = nHeightSrc;
+            yRemaining = nHeightTemp - nHeightSrc;
+            growSize = nHeightSrc;
+            while (yRemaining > 0)
+            {
+                growSize = min(growSize, yRemaining);
+                BitBlt(hdcTemp, 0, yOfs, nWidthTemp, growSize, hdcTemp, 0, 0, SRCCOPY);
+                yOfs += growSize;
+                yRemaining -= growSize;
+                growSize *= 2;
             }
-            yOfs += nHeightSrc;
-            yRemaining -= nHeightSrc;
+
+            /* Use temporary hdc for source */
+            result = UXTHEME_Blt (hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+                          hdcTemp, 0, 0,
+                          transparent, transcolor);
+
+            SelectObject(hdcTemp, bitmapOrig);
+            DeleteObject(bitmapTemp);
         }
-        return TRUE;
+        DeleteDC(hdcTemp);
+        return result;
     }
     else
     {
@@ -831,7 +883,7 @@ static HRESULT UXTHEME_DrawBackgroundFill(HTHEME hTheme, HDC hdc, int iPartId,
     HRESULT hr = S_OK;
     int filltype = FT_SOLID;
 
-    TRACE("(%d,%d,%ld)\n", iPartId, iStateId, pOptions->dwFlags);
+    TRACE("(%d,%d,%d)\n", iPartId, iStateId, pOptions->dwFlags);
 
     if(pOptions->dwFlags & DTBG_OMITCONTENT)
         return S_OK;
@@ -852,7 +904,7 @@ static HRESULT UXTHEME_DrawBackgroundFill(HTHEME hTheme, HDC hdc, int iPartId,
         /* FIXME: This only accounts for 2 gradient colors (out of 5) and ignores
             the gradient ratios (no idea how those work)
             Few themes use this, and the ones I've seen only use 2 colors with
-            a gradient ratio of 0 and 255 respectivly
+            a gradient ratio of 0 and 255 respectively
         */
 
         COLORREF gradient1 = RGB(0,0,0);
@@ -929,7 +981,7 @@ HRESULT WINAPI DrawThemeBackgroundEx(HTHEME hTheme, HDC hdc, int iPartId,
     int bgtype = BT_BORDERFILL;
     RECT rt;
 
-    TRACE("(%p,%p,%d,%d,%ld,%ld)\n", hTheme, hdc, iPartId, iStateId,pRect->left,pRect->top);
+    TRACE("(%p,%p,%d,%d,%d,%d)\n", hTheme, hdc, iPartId, iStateId,pRect->left,pRect->top);
     if(!hTheme)
         return E_HANDLE;
 
@@ -1125,8 +1177,8 @@ static HRESULT draw_diag_edge (HDC hdc, HTHEME theme, int part, int state,
             + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
 
     /* Init some vars */
-    OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN);
-    SavePen = (HPEN)SelectObject(hdc, InnerPen);
+    OuterPen = InnerPen = GetStockObject(NULL_PEN);
+    SavePen = SelectObject(hdc, InnerPen);
     spx = spy = epx = epy = 0; /* Satisfy the compiler... */
 
     /* Determine the colors of the edges */
@@ -1321,8 +1373,8 @@ static HRESULT draw_diag_edge (HDC hdc, HTHEME theme, int part, int state,
         HPEN hpsave;
         HPEN hp = get_edge_pen ((uFlags & BF_MONO) ? EDGE_WINDOW : EDGE_FILL, 
             theme, part, state);
-        hbsave = (HBRUSH)SelectObject(hdc, hb);
-        hpsave = (HPEN)SelectObject(hdc, hp);
+        hbsave = SelectObject(hdc, hb);
+        hpsave = SelectObject(hdc, hp);
         Polygon(hdc, Points, 4);
         SelectObject(hdc, hbsave);
         SelectObject(hdc, hpsave);
@@ -1374,8 +1426,8 @@ static HRESULT draw_rect_edge (HDC hdc, HTHEME theme, int part, int state,
                       && !(uFlags & (BF_FLAT|BF_MONO)) ) ? E_FAIL : S_OK;
 
     /* Init some vars */
-    LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN);
-    SavePen = (HPEN)SelectObject(hdc, LTInnerPen);
+    LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = GetStockObject(NULL_PEN);
+    SavePen = SelectObject(hdc, LTInnerPen);
 
     /* Determine the colors of the edges */
     if(uFlags & BF_MONO)
@@ -1388,7 +1440,7 @@ static HRESULT draw_rect_edge (HDC hdc, HTHEME theme, int part, int state,
         LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
         LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
 
-        if( LTInnerI != -1 ) LTInnerI = RBInnerI = COLOR_BTNFACE;
+        if( LTInnerI != -1 ) LTInnerI = RBInnerI = EDGE_FILL;
     }
     else if(uFlags & BF_SOFT)
     {
@@ -1608,12 +1660,12 @@ HRESULT WINAPI GetThemeBackgroundContentRect(HTHEME hTheme, HDC hdc, int iPartId
     } else {
         /* otherwise, try to determine content rect from the background type and props */
         int bgtype = BT_BORDERFILL;
-        memcpy(pContentRect, pBoundingRect, sizeof(RECT));
+        *pContentRect = *pBoundingRect;
 
         GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
         if(bgtype == BT_BORDERFILL) {
             int bordersize = 1;
-    
+
             GetThemeInt(hTheme, iPartId, iStateId, TMT_BORDERSIZE, &bordersize);
             InflateRect(pContentRect, -bordersize, -bordersize);
         } else if ((bgtype == BT_IMAGEFILE)
@@ -1627,7 +1679,7 @@ HRESULT WINAPI GetThemeBackgroundContentRect(HTHEME hTheme, HDC hdc, int iPartId
         /* If nothing was found, leave unchanged */
     }
 
-    TRACE("left:%ld,top:%ld,right:%ld,bottom:%ld\n", pContentRect->left, pContentRect->top, pContentRect->right, pContentRect->bottom);
+    TRACE("left:%d,top:%d,right:%d,bottom:%d\n", pContentRect->left, pContentRect->top, pContentRect->right, pContentRect->bottom);
 
     return S_OK;
 }
@@ -1656,12 +1708,12 @@ HRESULT WINAPI GetThemeBackgroundExtent(HTHEME hTheme, HDC hdc, int iPartId,
     } else {
         /* otherwise, try to determine content rect from the background type and props */
         int bgtype = BT_BORDERFILL;
-        memcpy(pExtentRect, pContentRect, sizeof(RECT));
+        *pExtentRect = *pContentRect;
 
         GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
         if(bgtype == BT_BORDERFILL) {
             int bordersize = 1;
-    
+
             GetThemeInt(hTheme, iPartId, iStateId, TMT_BORDERSIZE, &bordersize);
             InflateRect(pExtentRect, bordersize, bordersize);
         } else if ((bgtype == BT_IMAGEFILE)
@@ -1675,7 +1727,7 @@ HRESULT WINAPI GetThemeBackgroundExtent(HTHEME hTheme, HDC hdc, int iPartId,
         /* If nothing was found, leave unchanged */
     }
 
-    TRACE("left:%ld,top:%ld,right:%ld,bottom:%ld\n", pExtentRect->left, pExtentRect->top, pExtentRect->right, pExtentRect->bottom);
+    TRACE("left:%d,top:%d,right:%d,bottom:%d\n", pExtentRect->left, pExtentRect->top, pExtentRect->right, pExtentRect->bottom);
 
     return S_OK;
 }
@@ -1718,8 +1770,8 @@ HRESULT WINAPI GetThemeBackgroundRegion(HTHEME hTheme, HDC hdc, int iPartId,
 }
 
 /* compute part size for "borderfill" backgrounds */
-HRESULT get_border_background_size (HTHEME hTheme, int iPartId,
-                                    int iStateId, THEMESIZE eSize, POINT* psz)
+static HRESULT get_border_background_size (HTHEME hTheme, int iPartId,
+                                           int iStateId, THEMESIZE eSize, POINT* psz)
 {
     HRESULT hr = S_OK;
     int bordersize = 1;