--- trunk/reactos/lib/uxtheme/draw.c 2005-09-07 16:02:32 UTC (rev 17718)
+++ trunk/reactos/lib/uxtheme/draw.c 2005-09-07 16:22:51 UTC (rev 17719)
@@ -187,12 +187,42 @@
POINT size = {pRect->right-pRect->left, pRect->bottom-pRect->top};
POINT reqsize;
for(i=4; i>=0; i--) {
- if(SUCCEEDED(GetThemePosition(hTheme, iPartId, iStateId, i + TMT_MINSIZE1, &reqsize))) {
- 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);
- return MSSTYLES_FindProperty(hTheme, iPartId, iStateId, TMT_FILENAME, i + TMT_IMAGEFILE1);
+ PTHEME_PROPERTY fileProp =
+ MSSTYLES_FindProperty(hTheme, iPartId, iStateId, TMT_FILENAME, i + TMT_IMAGEFILE1);
+ if (!fileProp) continue;
+ if(FAILED(GetThemePosition(hTheme, iPartId, iStateId, i + TMT_MINSIZE1, &reqsize))) {
+ /* fall back to size of Nth image */
+ WCHAR szPath[MAX_PATH];
+ int imagelayout = IL_HORIZONTAL;
+ int imagecount = 1;
+ int imagenum;
+ BITMAP bmp;
+ HBITMAP hBmp;
+ BOOL hasAlpha;
+
+ lstrcpynW(szPath, fileProp->lpValue,
+ min(fileProp->dwValueLen+1, sizeof(szPath)/sizeof(szPath[0])));
+ hBmp = MSSTYLES_LoadBitmap(hTheme, szPath, &hasAlpha);
+ if(!hBmp) continue;
+
+ 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;
+ reqsize.y = bmp.bmHeight/imagecount;
}
+ else {
+ reqsize.x = bmp.bmWidth/imagecount;
+ reqsize.y = bmp.bmHeight;
+ }
}
+ 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);
+ return fileProp;
+ }
}
/* If an image couldnt be selected, choose the smallest one */
return MSSTYLES_FindProperty(hTheme, iPartId, iStateId, TMT_FILENAME, TMT_IMAGEFILE1);
@@ -206,10 +236,11 @@
* Load image for part/state
*/
static HRESULT UXTHEME_LoadImage(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, BOOL glyph,
- HBITMAP *hBmp, RECT *bmpRect)
+ HBITMAP *hBmp, RECT *bmpRect, BOOL* hasImageAlpha)
{
- int imagelayout = IL_VERTICAL;
+ int imagelayout = IL_HORIZONTAL;
int imagecount = 1;
+ int imagenum;
BITMAP bmp;
WCHAR szPath[MAX_PATH];
PTHEME_PROPERTY tp = UXTHEME_SelectImage(hTheme, hdc, iPartId, iStateId, pRect, glyph);
@@ -218,7 +249,7 @@
return E_PROP_ID_UNSUPPORTED;
}
lstrcpynW(szPath, tp->lpValue, min(tp->dwValueLen+1, sizeof(szPath)/sizeof(szPath[0])));
- *hBmp = MSSTYLES_LoadBitmap(hdc, hTheme, szPath);
+ *hBmp = MSSTYLES_LoadBitmap(hTheme, szPath, hasImageAlpha);
if(!*hBmp) {
TRACE("Failed to load bitmap %s\n", debugstr_w(szPath));
return HRESULT_FROM_WIN32(GetLastError());
@@ -227,17 +258,18 @@
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) {
int height = bmp.bmHeight/imagecount;
bmpRect->left = 0;
bmpRect->right = bmp.bmWidth;
- bmpRect->top = (max(min(imagecount, iStateId), 1)-1) * height;
+ bmpRect->top = imagenum * height;
bmpRect->bottom = bmpRect->top + height;
}
else {
int width = bmp.bmWidth/imagecount;
- bmpRect->left = (max(min(imagecount, iStateId), 1)-1) * width;
+ bmpRect->left = imagenum * width;
bmpRect->right = bmpRect->left + width;
bmpRect->top = 0;
bmpRect->bottom = bmp.bmHeight;
@@ -248,22 +280,35 @@
/***********************************************************************
* UXTHEME_StretchBlt
*
- * Psudo TransparentBlt/StretchBlt
+ * Pseudo TransparentBlt/StretchBlt
*/
static inline BOOL UXTHEME_StretchBlt(HDC hdcDst, int nXOriginDst, int nYOriginDst, int nWidthDst, int nHeightDst,
HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
- BOOL transparent, COLORREF transcolor)
+ INT transparent, COLORREF transcolor)
{
- if(transparent) {
+ static const BLENDFUNCTION blendFunc =
+ {
+ AC_SRC_OVER, /* BlendOp */
+ 0, /* BlendFlag */
+ 255, /* SourceConstantAlpha */
+ AC_SRC_ALPHA /* AlphaFormat */
+ };
+ if (transparent == ALPHABLEND_BINARY) {
/* Ensure we don't pass any negative values to TransparentBlt */
return TransparentBlt(hdcDst, nXOriginDst, nYOriginDst, abs(nWidthDst), abs(nHeightDst),
hdcSrc, nXOriginSrc, nYOriginSrc, abs(nWidthSrc), abs(nHeightSrc),
transcolor);
}
- /* This should be using AlphaBlend */
- return StretchBlt(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
- hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
- SRCCOPY);
+ if ((transparent == ALPHABLEND_NONE) ||
+ !AlphaBlend(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+ hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+ blendFunc))
+ {
+ return StretchBlt(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+ hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+ SRCCOPY);
+ }
+ return TRUE;
}
/***********************************************************************
@@ -273,14 +318,88 @@
*/
static inline BOOL UXTHEME_Blt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
- BOOL transparent, COLORREF transcolor)
+ INT transparent, COLORREF transcolor)
{
return UXTHEME_StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
hdcSrc, nXOriginSrc, nYOriginSrc, nWidthDest, nHeightDest,
transparent, transcolor);
}
+/***********************************************************************
+ * UXTHEME_SizedBlt
+ *
+ * Stretches or tiles, depending on sizingtype.
+ */
+static inline BOOL UXTHEME_SizedBlt (HDC hdcDst, int nXOriginDst, int nYOriginDst,
+ int nWidthDst, int nHeightDst,
+ HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
+ int nWidthSrc, int nHeightSrc,
+ int sizingtype,
+ INT transparent, COLORREF transcolor)
+{
+ if (sizingtype == ST_TILE)
+ {
+ int yOfs = nYOriginDst;
+ int yRemaining = nHeightDst;
+ while (yRemaining > 0)
+ {
+ int bltHeight = min (yRemaining, nHeightSrc);
+ int xOfs = nXOriginDst;
+ int xRemaining = nWidthDst;
+ 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;
+ }
+ yOfs += nHeightSrc;
+ yRemaining -= nHeightSrc;
+ }
+ return TRUE;
+ }
+ else
+ {
+ return UXTHEME_StretchBlt (hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+ hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+ transparent, transcolor);
+ }
+}
+/* Get transparency parameters passed to UXTHEME_StretchBlt() - the parameters
+ * depend on whether the image has full alpha or whether it is
+ * color-transparent or just opaque. */
+static inline void get_transparency (HTHEME hTheme, int iPartId, int iStateId,
+ BOOL hasImageAlpha, INT* transparent,
+ COLORREF* transparentcolor, BOOL glyph)
+{
+ if (hasImageAlpha)
+ {
+ *transparent = ALPHABLEND_FULL;
+ *transparentcolor = RGB (255, 0, 255);
+ }
+ else
+ {
+ BOOL trans = FALSE;
+ GetThemeBool(hTheme, iPartId, iStateId,
+ glyph ? TMT_GLYPHTRANSPARENT : TMT_TRANSPARENT, &trans);
+ if(trans) {
+ *transparent = ALPHABLEND_BINARY;
+ if(FAILED(GetThemeColor(hTheme, iPartId, iStateId,
+ glyph ? TMT_GLYPHTRANSPARENTCOLOR : TMT_TRANSPARENTCOLOR,
+ transparentcolor))) {
+ /* If image is transparent, but no color was specified, use magenta */
+ *transparentcolor = RGB(255, 0, 255);
+ }
+ }
+ else
+ *transparent = ALPHABLEND_NONE;
+ }
+}
+
/***********************************************************************
* UXTHEME_DrawImageGlyph
*
@@ -295,20 +414,21 @@
HDC hdcSrc = NULL;
HGDIOBJ oldSrc = NULL;
RECT rcSrc;
- BOOL transparent = FALSE;
- COLORREF transparentcolor = 0;
+ INT transparent = FALSE;
+ COLORREF transparentcolor;
int valign = VA_CENTER;
int halign = HA_CENTER;
POINT dstSize;
POINT srcSize;
POINT topleft;
+ BOOL hasAlpha;
- hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, TRUE, &bmpSrc, &rcSrc);
+ hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, TRUE,
+ &bmpSrc, &rcSrc, &hasAlpha);
if(FAILED(hr)) return hr;
hdcSrc = CreateCompatibleDC(hdc);
if(!hdcSrc) {
hr = HRESULT_FROM_WIN32(GetLastError());
- DeleteObject(bmpSrc);
return hr;
}
oldSrc = SelectObject(hdcSrc, bmpSrc);
@@ -318,13 +438,8 @@
srcSize.x = rcSrc.right-rcSrc.left;
srcSize.y = rcSrc.bottom-rcSrc.top;
- GetThemeBool(hTheme, iPartId, iStateId, TMT_GLYPHTRANSPARENT, &transparent);
- if(transparent) {
- if(FAILED(GetThemeColor(hTheme, iPartId, iStateId, TMT_GLYPHTRANSPARENTCOLOR, &transparentcolor))) {
- /* If image is transparent, but no color was specified, use magenta */
- transparentcolor = RGB(255, 0, 255);
- }
- }
+ get_transparency (hTheme, iPartId, iStateId, hasAlpha, &transparent,
+ &transparentcolor, TRUE);
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_HALIGN, &halign);
@@ -343,7 +458,6 @@
SelectObject(hdcSrc, oldSrc);
DeleteDC(hdcSrc);
- DeleteObject(bmpSrc);
return hr;
}
@@ -371,6 +485,110 @@
}
/***********************************************************************
+ * get_image_part_size
+ *
+ * Used by GetThemePartSize and UXTHEME_DrawImageBackground
+ */
+static HRESULT get_image_part_size (HTHEME hTheme, HDC hdc, int iPartId,
+ int iStateId, RECT *prc, THEMESIZE eSize,
+ POINT *psz)
+{
+ HRESULT hr = S_OK;
+ HBITMAP bmpSrc;
+ RECT rcSrc;
+ BOOL hasAlpha;
+
+ hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, prc, FALSE,
+ &bmpSrc, &rcSrc, &hasAlpha);
+ if (FAILED(hr)) return hr;
+
+ switch (eSize)
+ {
+ case TS_DRAW:
+ if (prc != NULL)
+ {
+ RECT rcDst;
+ POINT dstSize;
+ POINT srcSize;
+ int sizingtype = ST_STRETCH;
+ BOOL uniformsizing = FALSE;
+
+ CopyRect(&rcDst, prc);
+
+ dstSize.x = rcDst.right-rcDst.left;
+ dstSize.y = rcDst.bottom-rcDst.top;
+ srcSize.x = rcSrc.right-rcSrc.left;
+ srcSize.y = rcSrc.bottom-rcSrc.top;
+
+ GetThemeBool(hTheme, iPartId, iStateId, TMT_UNIFORMSIZING, &uniformsizing);
+ if(uniformsizing) {
+ /* Scale height and width equally */
+ if (dstSize.x*srcSize.y < dstSize.y*srcSize.x)
+ {
+ dstSize.y = MulDiv (srcSize.y, dstSize.x, srcSize.x);
+ rcDst.bottom = rcDst.top + dstSize.y;
+ }
+ else
+ {
+ dstSize.x = MulDiv (srcSize.x, dstSize.y, srcSize.y);
+ rcDst.right = rcDst.left + dstSize.x;
+ }
+ }
+
+ GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_SIZINGTYPE, &sizingtype);
+ if(sizingtype == ST_TRUESIZE) {
+ int truesizestretchmark = 100;
+
+ if(dstSize.x < 0 || dstSize.y < 0) {
+ BOOL mirrorimage = TRUE;
+ GetThemeBool(hTheme, iPartId, iStateId, TMT_MIRRORIMAGE, &mirrorimage);
+ if(mirrorimage) {
+ if(dstSize.x < 0) {
+ rcDst.left += dstSize.x;
+ rcDst.right += dstSize.x;
+ }
+ if(dstSize.y < 0) {
+ rcDst.top += dstSize.y;
+ rcDst.bottom += dstSize.y;
+ }
+ }
+ }
+ /* Whatever TrueSizeStretchMark does - it does not seem to
+ * be what's outlined below. It appears as if native
+ * uxtheme always stretches if dest is smaller than source
+ * (ie as if TrueSizeStretchMark==100 with the code below) */
+#if 0
+ /* Only stretch when target exceeds source by truesizestretchmark percent */
+ GetThemeInt(hTheme, iPartId, iStateId, TMT_TRUESIZESTRETCHMARK, &truesizestretchmark);
+#endif
+ if(dstSize.x < 0 || dstSize.y < 0 ||
+ (MulDiv(srcSize.x, 100, dstSize.x) > truesizestretchmark &&
+ MulDiv(srcSize.y, 100, dstSize.y) > truesizestretchmark)) {
+ memcpy (psz, &dstSize, sizeof (SIZE));
+ }
+ else {
+ memcpy (psz, &srcSize, sizeof (SIZE));
+ }
+ }
+ else
+ {
+ psz->x = abs(dstSize.x);
+ psz->y = abs(dstSize.y);
+ }
+ break;
+ }
+ /* else fall through */
+ case TS_MIN:
+ /* FIXME: couldn't figure how native uxtheme computes min size */
+ case TS_TRUE:
+ psz->x = rcSrc.right - rcSrc.left;
+ psz->y = rcSrc.bottom - rcSrc.top;
+ break;
+ }
+ return hr;
+}
+
+/***********************************************************************
* UXTHEME_DrawImageBackground
*
* Draw an imagefile background
@@ -387,143 +605,101 @@
RECT rcDst;
POINT dstSize;
POINT srcSize;
- int sizingtype = ST_TRUESIZE;
- BOOL uniformsizing = FALSE;
- BOOL transparent = FALSE;
+ POINT drawSize;
+ int sizingtype = ST_STRETCH;
+ INT transparent;
COLORREF transparentcolor = 0;
+ BOOL hasAlpha;
- hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, FALSE, &bmpSrc, &rcSrc);
+ hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, FALSE,
+ &bmpSrc, &rcSrc, &hasAlpha);
if(FAILED(hr)) return hr;
hdcSrc = CreateCompatibleDC(hdc);
if(!hdcSrc) {
hr = HRESULT_FROM_WIN32(GetLastError());
- DeleteObject(bmpSrc);
return hr;
}
oldSrc = SelectObject(hdcSrc, bmpSrc);
CopyRect(&rcDst, pRect);
- GetThemeBool(hTheme, iPartId, iStateId, TMT_TRANSPARENT, &transparent);
- if(transparent) {
- if(FAILED(GetThemeColor(hTheme, iPartId, iStateId, TMT_TRANSPARENTCOLOR, &transparentcolor))) {
- /* If image is transparent, but no color was specified, get the color of the upper left corner */
- transparentcolor = GetPixel(hdcSrc, 0, 0);
- }
- }
+ get_transparency (hTheme, iPartId, iStateId, hasAlpha, &transparent,
+ &transparentcolor, FALSE);
dstSize.x = rcDst.right-rcDst.left;
dstSize.y = rcDst.bottom-rcDst.top;
srcSize.x = rcSrc.right-rcSrc.left;
srcSize.y = rcSrc.bottom-rcSrc.top;
- GetThemeBool(hTheme, iPartId, iStateId, TMT_UNIFORMSIZING, &uniformsizing);
- if(uniformsizing) {
- /* Scale height and width equally */
- int widthDiff = abs(srcSize.x-dstSize.x);
- int heightDiff = abs(srcSize.y-dstSize.x);
- if(widthDiff > heightDiff) {
- dstSize.y -= widthDiff-heightDiff;
- rcDst.bottom = rcDst.top + dstSize.y;
- }
- else if(heightDiff > widthDiff) {
- dstSize.x -= heightDiff-widthDiff;
- rcDst.right = rcDst.left + dstSize.x;
- }
- }
-
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_SIZINGTYPE, &sizingtype);
if(sizingtype == ST_TRUESIZE) {
- int truesizestretchmark = 0;
+ int valign = VA_CENTER, halign = HA_CENTER;
- if(dstSize.x < 0 || dstSize.y < 0) {
- BOOL mirrorimage = TRUE;
- GetThemeBool(hTheme, iPartId, iStateId, TMT_MIRRORIMAGE, &mirrorimage);
- if(mirrorimage) {
- if(dstSize.x < 0) {
- rcDst.left += dstSize.x;
- rcDst.right += dstSize.x;
- }
- if(dstSize.y < 0) {
- rcDst.top += dstSize.y;
- rcDst.bottom += dstSize.y;
- }
- }
- }
- /* Only stretch when target exceeds source by truesizestretchmark percent */
- GetThemeInt(hTheme, iPartId, iStateId, TMT_TRUESIZESTRETCHMARK, &truesizestretchmark);
- if(dstSize.x < 0 || dstSize.y < 0 ||
- MulDiv(srcSize.x, 100, dstSize.x) > truesizestretchmark ||
- MulDiv(srcSize.y, 100, dstSize.y) > truesizestretchmark) {
- if(!UXTHEME_StretchBlt(hdc, rcDst.left, rcDst.top, dstSize.x, dstSize.y,
- hdcSrc, rcSrc.left, rcSrc.top, srcSize.x, srcSize.y,
- transparent, transparentcolor))
- hr = HRESULT_FROM_WIN32(GetLastError());
- }
- else {
- rcDst.left += (dstSize.x/2)-(srcSize.x/2);
- rcDst.top += (dstSize.y/2)-(srcSize.y/2);
- rcDst.right = rcDst.left + srcSize.x;
- rcDst.bottom = rcDst.top + srcSize.y;
- if(!UXTHEME_Blt(hdc, rcDst.left, rcDst.top, srcSize.x, srcSize.y,
- hdcSrc, rcSrc.left, rcSrc.top,
- transparent, transparentcolor))
- hr = HRESULT_FROM_WIN32(GetLastError());
- }
+ get_image_part_size (hTheme, hdc, iPartId, iStateId, pRect, TS_DRAW, &drawSize);
+ GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
+ GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_HALIGN, &halign);
+
+ if (halign == HA_CENTER)
+ rcDst.left += (dstSize.x/2)-(drawSize.x/2);
+ else if (halign == HA_RIGHT)
+ rcDst.left = rcDst.right - drawSize.x;
+ if (valign == VA_CENTER)
+ rcDst.top += (dstSize.y/2)-(drawSize.y/2);
+ else if (valign == VA_BOTTOM)
+ rcDst.top = rcDst.bottom - drawSize.y;
+ rcDst.right = rcDst.left + drawSize.x;
+ rcDst.bottom = rcDst.top + drawSize.y;
+ if(!UXTHEME_StretchBlt(hdc, rcDst.left, rcDst.top, drawSize.x, drawSize.y,
+ hdcSrc, rcSrc.left, rcSrc.top, srcSize.x, srcSize.y,
+ transparent, transparentcolor))
+ hr = HRESULT_FROM_WIN32(GetLastError());
}
else {
HDC hdcDst = NULL;
- HBITMAP bmpDst = NULL;
- HGDIOBJ oldDst = NULL;
MARGINS sm;
+ POINT org;
dstSize.x = abs(dstSize.x);
dstSize.y = abs(dstSize.y);
GetThemeMargins(hTheme, hdc, iPartId, iStateId, TMT_SIZINGMARGINS, NULL, &sm);
- hdcDst = CreateCompatibleDC(hdc);
- if(!hdcDst) {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto draw_error;
- }
- bmpDst = CreateCompatibleBitmap(hdc, dstSize.x, dstSize.y);
- if(!bmpDst) {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto draw_error;
- }
- oldDst = SelectObject(hdcDst, bmpDst);
+ hdcDst = hdc;
+ OffsetViewportOrgEx(hdcDst, rcDst.left, rcDst.top, &org);
/* Upper left corner */
- if(!BitBlt(hdcDst, 0, 0, sm.cxLeftWidth, sm.cyTopHeight,
- hdcSrc, rcSrc.left, rcSrc.top, SRCCOPY)) {
+ if(!UXTHEME_Blt(hdcDst, 0, 0, sm.cxLeftWidth, sm.cyTopHeight,
+ hdcSrc, rcSrc.left, rcSrc.top,
+ transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
/* Upper right corner */
- if(!BitBlt(hdcDst, dstSize.x-sm.cxRightWidth, 0, sm.cxRightWidth, sm.cyTopHeight,
- hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top, SRCCOPY)) {
+ if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, 0,
+ sm.cxRightWidth, sm.cyTopHeight,
+ hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top,
+ transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
/* Lower left corner */
- if(!BitBlt(hdcDst, 0, dstSize.y-sm.cyBottomHeight, sm.cxLeftWidth, sm.cyBottomHeight,
- hdcSrc, rcSrc.left, rcSrc.bottom-sm.cyBottomHeight, SRCCOPY)) {
+ if(!UXTHEME_Blt (hdcDst, 0, dstSize.y-sm.cyBottomHeight,
+ sm.cxLeftWidth, sm.cyBottomHeight,
+ hdcSrc, rcSrc.left, rcSrc.bottom-sm.cyBottomHeight,
+ transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
/* Lower right corner */
- if(!BitBlt(hdcDst, dstSize.x-sm.cxRightWidth, dstSize.y-sm.cyBottomHeight, sm.cxRightWidth, sm.cyBottomHeight,
- hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.bottom-sm.cyBottomHeight, SRCCOPY)) {
+ if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, dstSize.y-sm.cyBottomHeight,
+ sm.cxRightWidth, sm.cyBottomHeight,
+ hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.bottom-sm.cyBottomHeight,
+ transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
- if(sizingtype == ST_TILE) {
- FIXME("Tile\n");
- sizingtype = ST_STRETCH; /* Just use stretch for now */
- }
- if(sizingtype == ST_STRETCH) {
+ if ((sizingtype == ST_STRETCH) || (sizingtype == ST_TILE)) {
int destCenterWidth = dstSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
int srcCenterWidth = srcSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
int destCenterHeight = dstSize.y - (sm.cyTopHeight + sm.cyBottomHeight);
@@ -531,28 +707,41 @@
if(destCenterWidth > 0) {
/* Center top */
- if(!StretchBlt(hdcDst, sm.cxLeftWidth, 0, destCenterWidth, sm.cyTopHeight,
- hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top, srcCenterWidth, sm.cyTopHeight, SRCCOPY)) {
+ if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, 0,
+ destCenterWidth, sm.cyTopHeight,
+ hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top,
+ srcCenterWidth, sm.cyTopHeight,
+ sizingtype, transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
/* Center bottom */
- if(!StretchBlt(hdcDst, sm.cxLeftWidth, dstSize.y-sm.cyBottomHeight, destCenterWidth, sm.cyBottomHeight,
- hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.bottom-sm.cyBottomHeight, srcCenterWidth, sm.cyTopHeight, SRCCOPY)) {
+ if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, dstSize.y-sm.cyBottomHeight,
+ destCenterWidth, sm.cyBottomHeight,
+ hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.bottom-sm.cyBottomHeight,
+ srcCenterWidth, sm.cyBottomHeight,
+ sizingtype, transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
}
if(destCenterHeight > 0) {
/* Left center */
- if(!StretchBlt(hdcDst, 0, sm.cyTopHeight, sm.cxLeftWidth, destCenterHeight,
- hdcSrc, rcSrc.left, rcSrc.top+sm.cyTopHeight, sm.cxLeftWidth, srcCenterHeight, SRCCOPY)) {
+ if(!UXTHEME_SizedBlt (hdcDst, 0, sm.cyTopHeight,
+ sm.cxLeftWidth, destCenterHeight,
+ hdcSrc, rcSrc.left, rcSrc.top+sm.cyTopHeight,
+ sm.cxLeftWidth, srcCenterHeight,
+ sizingtype,
+ transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
/* Right center */
- if(!StretchBlt(hdcDst, dstSize.x-sm.cxRightWidth, sm.cyTopHeight, sm.cxRightWidth, destCenterHeight,
- hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top+sm.cyTopHeight, sm.cxRightWidth, srcCenterHeight, SRCCOPY)) {
+ if(!UXTHEME_SizedBlt (hdcDst, dstSize.x-sm.cxRightWidth, sm.cyTopHeight,
+ sm.cxRightWidth, destCenterHeight,
+ hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top+sm.cyTopHeight,
+ sm.cxRightWidth, srcCenterHeight,
+ sizingtype, transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
@@ -562,8 +751,11 @@
GetThemeBool(hTheme, iPartId, iStateId, TMT_BORDERONLY, &borderonly);
if(!borderonly) {
/* Center */
- if(!StretchBlt(hdcDst, sm.cxLeftWidth, sm.cyTopHeight, destCenterWidth, destCenterHeight,
- hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top+sm.cyTopHeight, srcCenterWidth, srcCenterHeight, SRCCOPY)) {
+ if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, sm.cyTopHeight,
+ destCenterWidth, destCenterHeight,
+ hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top+sm.cyTopHeight,
+ srcCenterWidth, srcCenterHeight,
+ sizingtype, transparent, transparentcolor)) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto draw_error;
}
@@ -571,20 +763,10 @@
}
}
- if(!UXTHEME_Blt(hdc, rcDst.left, rcDst.top, dstSize.x, dstSize.y,
- hdcDst, 0, 0,
- transparent, transparentcolor))
- hr = HRESULT_FROM_WIN32(GetLastError());
-
draw_error:
- if(hdcDst) {
- SelectObject(hdcDst, oldDst);
- DeleteDC(hdcDst);
- }
- if(bmpDst) DeleteObject(bmpDst);
+ SetViewportOrgEx (hdcDst, org.x, org.y, NULL);
}
SelectObject(hdcSrc, oldSrc);
- DeleteObject(bmpSrc);
DeleteDC(hdcSrc);
CopyRect(pRect, &rcDst);
return hr;
@@ -751,6 +933,9 @@
if(!hTheme)
return E_HANDLE;
+ GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
+ if (bgtype == BT_NONE) return S_OK;
+
/* Ensure we have a DTBGOPTS structure available, simplifies some of the code */
opts = pOptions;
if(!opts) opts = &defaultOpts;
@@ -765,7 +950,6 @@
}
CopyRect(&rt, pRect);
- GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
if(bgtype == BT_IMAGEFILE)
hr = UXTHEME_DrawImageBackground(hTheme, hdc, iPartId, iStateId, &rt, opts);
else if(bgtype == BT_BORDERFILL)
@@ -787,19 +971,557 @@
return hr;
}
+/*
+ * DrawThemeEdge() implementation
+ *
+ * Since it basically is DrawEdge() with different colors, I copied its code
+ * from user32's uitools.c.
+ */
+
+enum
+{
+ EDGE_LIGHT,
+ EDGE_HIGHLIGHT,
+ EDGE_SHADOW,
+ EDGE_DARKSHADOW,
+ EDGE_FILL,
+
+ EDGE_WINDOW,
+ EDGE_WINDOWFRAME,
+
+ EDGE_NUMCOLORS
+};
+
+static const struct
+{
+ int themeProp;
+ int sysColor;
+} EdgeColorMap[EDGE_NUMCOLORS] = {
+ {TMT_EDGELIGHTCOLOR, COLOR_3DLIGHT},
+ {TMT_EDGEHIGHLIGHTCOLOR, COLOR_BTNHIGHLIGHT},
+ {TMT_EDGESHADOWCOLOR, COLOR_BTNSHADOW},
+ {TMT_EDGEDKSHADOWCOLOR, COLOR_3DDKSHADOW},
+ {TMT_EDGEFILLCOLOR, COLOR_BTNFACE},
+ {-1, COLOR_WINDOW},
+ {-1, COLOR_WINDOWFRAME}
+};
+
+static const signed char LTInnerNormal[] = {
+ -1, -1, -1, -1,
+ -1, EDGE_HIGHLIGHT, EDGE_HIGHLIGHT, -1,
+ -1, EDGE_DARKSHADOW, EDGE_DARKSHADOW, -1,
+ -1, -1, -1, -1
+};
+
+static const signed char LTOuterNormal[] = {
+ -1, EDGE_LIGHT, EDGE_SHADOW, -1,
+ EDGE_HIGHLIGHT, EDGE_LIGHT, EDGE_SHADOW, -1,
+ EDGE_DARKSHADOW, EDGE_LIGHT, EDGE_SHADOW, -1,
+ -1, EDGE_LIGHT, EDGE_SHADOW, -1
+};
+
+static const signed char RBInnerNormal[] = {
+ -1, -1, -1, -1,
+ -1, EDGE_SHADOW, EDGE_SHADOW, -1,
+ -1, EDGE_LIGHT, EDGE_LIGHT, -1,
+ -1, -1, -1, -1
+};
+
+static const signed char RBOuterNormal[] = {
+ -1, EDGE_DARKSHADOW, EDGE_HIGHLIGHT, -1,
+ EDGE_SHADOW, EDGE_DARKSHADOW, EDGE_HIGHLIGHT, -1,
+ EDGE_LIGHT, EDGE_DARKSHADOW, EDGE_HIGHLIGHT, -1,
+ -1, EDGE_DARKSHADOW, EDGE_HIGHLIGHT, -1
+};
+
+static const signed char LTInnerSoft[] = {
+ -1, -1, -1, -1,
+ -1, EDGE_LIGHT, EDGE_LIGHT, -1,
+ -1, EDGE_SHADOW, EDGE_SHADOW, -1,
+ -1, -1, -1, -1
+};
+
+static const signed char LTOuterSoft[] = {
+ -1, EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
+ EDGE_LIGHT, EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
+ EDGE_SHADOW, EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
+ -1, EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1
+};
+
+#define RBInnerSoft RBInnerNormal /* These are the same */
+#define RBOuterSoft RBOuterNormal
+
+static const signed char LTRBOuterMono[] = {
+ -1, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+ EDGE_WINDOW, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+ EDGE_WINDOW, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+ EDGE_WINDOW, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+};
+
+static const signed char LTRBInnerMono[] = {
+ -1, -1, -1, -1,
+ -1, EDGE_WINDOW, EDGE_WINDOW, EDGE_WINDOW,
+ -1, EDGE_WINDOW, EDGE_WINDOW, EDGE_WINDOW,
+ -1, EDGE_WINDOW, EDGE_WINDOW, EDGE_WINDOW,
+};
+
+static const signed char LTRBOuterFlat[] = {
+ -1, EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+ EDGE_FILL, EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+ EDGE_FILL, EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+ EDGE_FILL, EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+};
+
+static const signed char LTRBInnerFlat[] = {
+ -1, -1, -1, -1,
+ -1, EDGE_FILL, EDGE_FILL, EDGE_FILL,
+ -1, EDGE_FILL, EDGE_FILL, EDGE_FILL,
+ -1, EDGE_FILL, EDGE_FILL, EDGE_FILL,
+};
+
+static COLORREF get_edge_color (int edgeType, HTHEME theme, int part, int state)
+{
+ COLORREF col;
+ if ((EdgeColorMap[edgeType].themeProp == -1)
+ || FAILED (GetThemeColor (theme, part, state,
+ EdgeColorMap[edgeType].themeProp, &col)))
+ col = GetSysColor (EdgeColorMap[edgeType].sysColor);
+ return col;
+}
+
+static inline HPEN get_edge_pen (int edgeType, HTHEME theme, int part, int state)
+{
+ return CreatePen (PS_SOLID, 1, get_edge_color (edgeType, theme, part, state));
+}
+
+static inline HBRUSH get_edge_brush (int edgeType, HTHEME theme, int part, int state)
+{
+ return CreateSolidBrush (get_edge_color (edgeType, theme, part, state));
+}
+
/***********************************************************************
+ * draw_diag_edge
+ *
+ * Same as DrawEdge invoked with BF_DIAGONAL
+ */
+static HRESULT draw_diag_edge (HDC hdc, HTHEME theme, int part, int state,
+ const RECT* rc, UINT uType,
+ UINT uFlags, LPRECT contentsRect)
+{
+ POINT Points[4];
+ signed char InnerI, OuterI;
+ HPEN InnerPen, OuterPen;
+ POINT SavePoint;
+ HPEN SavePen;
+ int spx, spy;
+ int epx, epy;
+ int Width = rc->right - rc->left;
+ int Height= rc->bottom - rc->top;
+ int SmallDiam = Width > Height ? Height : Width;
+ HRESULT retval = (((uType & BDR_INNER) == BDR_INNER
+ || (uType & BDR_OUTER) == BDR_OUTER)
+ && !(uFlags & (BF_FLAT|BF_MONO)) ) ? E_FAIL : S_OK;
+ int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
+ + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
+
+ /* Init some vars */
+ OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN);
+ SavePen = (HPEN)SelectObject(hdc, InnerPen);
+ spx = spy = epx = epy = 0; /* Satisfy the compiler... */
+
+ /* Determine the colors of the edges */
+ if(uFlags & BF_MONO)
+ {
+ InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
+ OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
+ }
+ else if(uFlags & BF_FLAT)
+ {
+ InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
+ OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
+ }
+ else if(uFlags & BF_SOFT)
+ {
+ if(uFlags & BF_BOTTOM)
+ {
+ InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+ OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+ }
+ else
+ {
+ InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+ OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+ }
+ }
+ else
+ {
+ if(uFlags & BF_BOTTOM)
+ {
+ InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+ OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+ }
+ else
+ {
+ InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+ OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+ }
+ }
+
+ if(InnerI != -1) InnerPen = get_edge_pen (InnerI, theme, part, state);
+ if(OuterI != -1) OuterPen = get_edge_pen (OuterI, theme, part, state);
+
+ MoveToEx(hdc, 0, 0, &SavePoint);
+
+ /* Don't ask me why, but this is what is visible... */
+ /* This must be possible to do much simpler, but I fail to */
+ /* see the logic in the MS implementation (sigh...). */
+ /* So, this might look a bit brute force here (and it is), but */
+ /* it gets the job done;) */
+
+ switch(uFlags & BF_RECT)
+ {
+ case 0:
+ case BF_LEFT:
+ case BF_BOTTOM:
+ case BF_BOTTOMLEFT:
+ /* Left bottom endpoint */
+ epx = rc->left-1;
+ spx = epx + SmallDiam;
+ epy = rc->bottom;
+ spy = epy - SmallDiam;
+ break;
+
+ case BF_TOPLEFT:
+ case BF_BOTTOMRIGHT:
+ /* Left top endpoint */
+ epx = rc->left-1;
+ spx = epx + SmallDiam;
+ epy = rc->top-1;
+ spy = epy + SmallDiam;
+ break;
+
+ case BF_TOP:
+ case BF_RIGHT:
+ case BF_TOPRIGHT:
+ case BF_RIGHT|BF_LEFT:
+ case BF_RIGHT|BF_LEFT|BF_TOP:
+ case BF_BOTTOM|BF_TOP:
+ case BF_BOTTOM|BF_TOP|BF_LEFT:
+ case BF_BOTTOMRIGHT|BF_LEFT:
+ case BF_BOTTOMRIGHT|BF_TOP:
+ case BF_RECT:
+ /* Right top endpoint */
+ spx = rc->left;
+ epx = spx + SmallDiam;
+ spy = rc->bottom-1;
+ epy = spy - SmallDiam;
+ break;
+ }
+
+ MoveToEx(hdc, spx, spy, NULL);
+ SelectObject(hdc, OuterPen);
+ LineTo(hdc, epx, epy);
+
+ SelectObject(hdc, InnerPen);
+
+ switch(uFlags & (BF_RECT|BF_DIAGONAL))
+ {
+ case BF_DIAGONAL_ENDBOTTOMLEFT:
+ case (BF_DIAGONAL|BF_BOTTOM):
+ case BF_DIAGONAL:
+ case (BF_DIAGONAL|BF_LEFT):
+ MoveToEx(hdc, spx-1, spy, NULL);
+ LineTo(hdc, epx, epy-1);
+ Points[0].x = spx-add;
+ Points[0].y = spy;
+ Points[1].x = rc->left;
+ Points[1].y = rc->top;
+ Points[2].x = epx+1;
+ Points[2].y = epy-1-add;
+ Points[3] = Points[2];
+ break;
+
+ case BF_DIAGONAL_ENDBOTTOMRIGHT:
+ MoveToEx(hdc, spx-1, spy, NULL);
+ LineTo(hdc, epx, epy+1);
+ Points[0].x = spx-add;
+ Points[0].y = spy;
+ Points[1].x = rc->left;
+ Points[1].y = rc->bottom-1;
+ Points[2].x = epx+1;
+ Points[2].y = epy+1+add;
+ Points[3] = Points[2];
+ break;
+
+ case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP):
[truncated at 1000 lines; 1215 more skipped]