b=using opacity with windows native widgets causes bogus rendering/lack of rendering; r=stuart

git-svn-id: svn://10.0.0.236/trunk@221253 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
vladimir%pobox.com
2007-03-03 00:18:34 +00:00
parent 9decb54e91
commit 76df446d7a
11 changed files with 887 additions and 145 deletions

View File

@@ -59,11 +59,11 @@
#include "nsWidgetAtoms.h"
#include <malloc.h>
#ifdef MOZ_CAIRO_GFX
#include "gfxContext.h"
#include "gfxMatrix.h"
#include "gfxWindowsSurface.h"
#endif
#include "gfxWindowsNativeDrawing.h"
/*
* The following constants are used to determine how a widget is drawn using
* Windows' Theme API. For more information on theme parts and states see
@@ -821,99 +821,38 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
PRInt32 p2a = dc->AppUnitsPerDevPixel();
RECT widgetRect;
RECT clipRect;
nsRect tr(aRect);
nsRect cr(aClipRect);
gfxRect tr, cr;
#ifdef MOZ_CAIRO_GFX
tr.x = NSAppUnitsToIntPixels(tr.x, p2a);
tr.y = NSAppUnitsToIntPixels(tr.y, p2a);
tr.width = NSAppUnitsToIntPixels(tr.width, p2a);
tr.height = NSAppUnitsToIntPixels(tr.height, p2a);
tr.pos.x = NSAppUnitsToIntPixels(aRect.x, p2a);
tr.pos.y = NSAppUnitsToIntPixels(aRect.y, p2a);
tr.size.width = NSAppUnitsToIntPixels(aRect.width, p2a);
tr.size.height = NSAppUnitsToIntPixels(aRect.height, p2a);
cr.x = NSAppUnitsToIntPixels(cr.x, p2a);
cr.y = NSAppUnitsToIntPixels(cr.y, p2a);
cr.width = NSAppUnitsToIntPixels(cr.width, p2a);
cr.height = NSAppUnitsToIntPixels(cr.height, p2a);
cr.pos.x = NSAppUnitsToIntPixels(aClipRect.x, p2a);
cr.pos.y = NSAppUnitsToIntPixels(aClipRect.y, p2a);
cr.size.width = NSAppUnitsToIntPixels(aClipRect.width, p2a);
cr.size.height = NSAppUnitsToIntPixels(aClipRect.height, p2a);
nsRefPtr<gfxContext> ctx = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
gfxPoint offset;
nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&offset.x, &offset.y);
gfxWindowsNativeDrawing nativeDrawing(ctx, cr, GetWidgetNativeDrawingFlags(aWidgetType));
HDC hdc = NS_STATIC_CAST(gfxWindowsSurface*, NS_STATIC_CAST(gfxASurface*, surf.get()))->GetDC();
RENDER_AGAIN:
/* Need to force the clip to be set */
ctx->UpdateSurfaceClip();
HDC hdc = nativeDrawing.BeginNativeDrawing();
/* Covert the current transform to a world transform */
XFORM oldWorldTransform;
gfxMatrix m = ctx->CurrentMatrix();
if (m.HasNonTranslation()) {
GetWorldTransform(hdc, &oldWorldTransform);
SetGraphicsMode(hdc, GM_ADVANCED);
XFORM xform;
xform.eM11 = (FLOAT) m.xx;
xform.eM12 = (FLOAT) m.yx;
xform.eM21 = (FLOAT) m.xy;
xform.eM22 = (FLOAT) m.yy;
xform.eDx = (FLOAT) m.x0;
xform.eDy = (FLOAT) m.y0;
SetWorldTransform (hdc, &xform);
} else {
gfxPoint pos(m.GetTranslation());
tr.x += NSToCoordRound(pos.x);
tr.y += NSToCoordRound(pos.y);
cr.x += NSToCoordRound(pos.x);
cr.y += NSToCoordRound(pos.y);
}
nativeDrawing.TransformToNativeRect(tr, widgetRect);
nativeDrawing.TransformToNativeRect(cr, clipRect);
#if 0
{
double dm[6];
m.ToValues(&dm[0], &dm[1], &dm[2], &dm[3], &dm[4], &dm[5]);
fprintf (stderr, "xform: %f %f %f %f [%f %f]\n", dm[0], dm[1], dm[2], dm[3], dm[4], dm[5]);
fprintf (stderr, "tr: [%d %d %d %d]\ncr: [%d %d %d %d]\noff: [%f %f]\n",
tr.x, tr.y, tr.width, tr.height, cr.x, cr.y, cr.width, cr.height,
offset.x, offset.y);
fflush (stderr);
fprintf (stderr, "xform: %f %f %f %f [%f %f]\n", m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);
fprintf (stderr, "tr: [%d %d %d %d]\ncr: [%d %d %d %d]\noff: [%f %f]\n",
tr.x, tr.y, tr.width, tr.height, cr.x, cr.y, cr.width, cr.height,
offset.x, offset.y);
}
#endif
/* Set the device offsets as appropriate */
POINT origViewportOrigin, origBrushOrigin;
GetViewportOrgEx(hdc, &origViewportOrigin);
SetViewportOrgEx(hdc, origViewportOrigin.x + (int)offset.x, origViewportOrigin.y + (int)offset.y, NULL);
#else /* non-MOZ_CAIRO_GFX */
nsTransform2D* transformMatrix;
aContext->GetCurrentTransform(transformMatrix);
transformMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height);
transformMatrix->TransformCoord(&cr.x,&cr.y,&cr.width,&cr.height);
HDC hdc = (HDC)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
if (!hdc)
return NS_ERROR_FAILURE;
#ifndef WINCE
SetGraphicsMode(hdc, GM_ADVANCED);
#endif
#endif /* MOZ_CAIRO_GFX */
GetNativeRect(tr, widgetRect);
GetNativeRect(cr, clipRect);
#if 0
fprintf (stderr, "widget: [%d %d %d %d]\nclip: [%d %d %d %d]\n",
widgetRect.left, widgetRect.top, widgetRect.right, widgetRect.bottom,
clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
fflush (stderr);
#endif
// For left edge and right edge tabs, we need to adjust the widget
// rects and clip rects so that the edges don't get drawn.
if (aWidgetType == NS_THEME_TAB_LEFT_EDGE || aWidgetType == NS_THEME_TAB_RIGHT_EDGE) {
@@ -1003,14 +942,12 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
}
}
#ifdef MOZ_CAIRO_GFX
SetViewportOrgEx(hdc, origViewportOrigin.x, origViewportOrigin.y, NULL);
nativeDrawing.EndNativeDrawing();
if (m.HasNonTranslation())
SetWorldTransform(hdc, &oldWorldTransform);
if (nativeDrawing.ShouldRenderAgain())
goto RENDER_AGAIN;
surf->MarkDirty();
#endif
nativeDrawing.PaintToContext();
return NS_OK;
}
@@ -2000,7 +1937,7 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
PRUint8 aWidgetType,
const nsRect& aRect,
const nsRect& aClipRect)
{
{
PRInt32 part, state;
PRBool focused;
nsresult rv;
@@ -2012,61 +1949,27 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
aContext->GetDeviceContext(*getter_AddRefs(dc));
PRInt32 p2a = dc->AppUnitsPerDevPixel();
RECT widgetRect;
nsRect tr(aRect);
gfxRect tr, cr;
#ifdef MOZ_CAIRO_GFX
tr.x = NSAppUnitsToIntPixels(tr.x, p2a);
tr.y = NSAppUnitsToIntPixels(tr.y, p2a);
tr.width = NSAppUnitsToIntPixels(tr.width, p2a);
tr.height = NSAppUnitsToIntPixels(tr.height, p2a);
tr.pos.x = NSAppUnitsToIntPixels(aRect.x, p2a);
tr.pos.y = NSAppUnitsToIntPixels(aRect.y, p2a);
tr.size.width = NSAppUnitsToIntPixels(aRect.width, p2a);
tr.size.height = NSAppUnitsToIntPixels(aRect.height, p2a);
cr.pos.x = NSAppUnitsToIntPixels(aClipRect.x, p2a);
cr.pos.y = NSAppUnitsToIntPixels(aClipRect.y, p2a);
cr.size.width = NSAppUnitsToIntPixels(aClipRect.width, p2a);
cr.size.height = NSAppUnitsToIntPixels(aClipRect.height, p2a);
nsRefPtr<gfxContext> ctx = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
gfxPoint offset;
nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&offset.x, &offset.y);
HDC hdc = NS_STATIC_CAST(gfxWindowsSurface*, NS_STATIC_CAST(gfxASurface*, surf.get()))->GetDC();
gfxWindowsNativeDrawing nativeDrawing(ctx, cr, GetWidgetNativeDrawingFlags(aWidgetType));
/* Need to force the clip to be set */
ctx->UpdateSurfaceClip();
RENDER_AGAIN:
/* Covert the current transform to a world transform */
XFORM oldWorldTransform;
gfxMatrix m = ctx->CurrentMatrix();
if (m.HasNonTranslation()) {
GetWorldTransform(hdc, &oldWorldTransform);
HDC hdc = nativeDrawing.BeginNativeDrawing();
SetGraphicsMode(hdc, GM_ADVANCED);
XFORM xform;
xform.eM11 = (FLOAT) m.xx;
xform.eM12 = (FLOAT) m.yx;
xform.eM21 = (FLOAT) m.xy;
xform.eM22 = (FLOAT) m.yy;
xform.eDx = (FLOAT) m.x0;
xform.eDy = (FLOAT) m.y0;
SetWorldTransform (hdc, &xform);
} else {
gfxPoint pos(m.GetTranslation());
tr.x += NSToCoordRound(pos.x);
tr.y += NSToCoordRound(pos.y);
}
/* Set the device offsets as appropriate */
POINT origViewportOrigin;
GetViewportOrgEx(hdc, &origViewportOrigin);
SetViewportOrgEx(hdc, origViewportOrigin.x + (int)offset.x, origViewportOrigin.y + (int)offset.y, NULL);
#else /* non-MOZ_CAIRO_GFX */
nsTransform2D* transformMatrix;
aContext->GetCurrentTransform(transformMatrix);
transformMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height);
HDC hdc = (HDC)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
#endif /* MOZ_CAIRO_GFX */
GetNativeRect(tr, widgetRect);
nativeDrawing.TransformToNativeRect(tr, widgetRect);
rv = NS_OK;
switch (aWidgetType) {
@@ -2336,18 +2239,89 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
break;
}
#ifdef MOZ_CAIRO_GFX
SetViewportOrgEx(hdc, origViewportOrigin.x, origViewportOrigin.y, NULL);
nativeDrawing.EndNativeDrawing();
if (m.HasNonTranslation())
SetWorldTransform(hdc, &oldWorldTransform);
if (NS_FAILED(rv))
return rv;
surf->MarkDirty();
#endif
if (nativeDrawing.ShouldRenderAgain())
goto RENDER_AGAIN;
nativeDrawing.PaintToContext();
return rv;
}
PRUint32
nsNativeThemeWin::GetWidgetNativeDrawingFlags(PRUint8 aWidgetType)
{
switch (aWidgetType) {
case NS_THEME_BUTTON:
case NS_THEME_TEXTFIELD:
case NS_THEME_DROPDOWN:
case NS_THEME_DROPDOWN_TEXTFIELD:
return
gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA |
gfxWindowsNativeDrawing::CAN_AXIS_ALIGNED_SCALE |
gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM;
// need to check these others
case NS_THEME_SCROLLBAR_BUTTON_UP:
case NS_THEME_SCROLLBAR_BUTTON_DOWN:
case NS_THEME_SCROLLBAR_BUTTON_LEFT:
case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
case NS_THEME_SCALE_HORIZONTAL:
case NS_THEME_SCALE_VERTICAL:
case NS_THEME_SCALE_THUMB_HORIZONTAL:
case NS_THEME_SCALE_THUMB_VERTICAL:
case NS_THEME_SPINNER_UP_BUTTON:
case NS_THEME_SPINNER_DOWN_BUTTON:
case NS_THEME_LISTBOX:
case NS_THEME_TREEVIEW:
case NS_THEME_TOOLTIP:
case NS_THEME_STATUSBAR:
case NS_THEME_STATUSBAR_PANEL:
case NS_THEME_STATUSBAR_RESIZER_PANEL:
case NS_THEME_RESIZER:
case NS_THEME_PROGRESSBAR:
case NS_THEME_PROGRESSBAR_VERTICAL:
case NS_THEME_PROGRESSBAR_CHUNK:
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
case NS_THEME_TAB:
case NS_THEME_TAB_LEFT_EDGE:
case NS_THEME_TAB_RIGHT_EDGE:
case NS_THEME_TAB_PANEL:
case NS_THEME_TAB_PANELS:
case NS_THEME_MENUBAR:
case NS_THEME_MENUPOPUP:
case NS_THEME_MENUITEM:
break;
// the dropdown button /almost/ renders correctly with scaling,
// except that the graphic in the dropdown button (the downward arrow)
// doesn't get scaled up.
case NS_THEME_DROPDOWN_BUTTON:
// these are definitely no; they're all graphics that don't get scaled up
case NS_THEME_CHECKBOX:
case NS_THEME_RADIO:
case NS_THEME_CHECKMENUITEM:
case NS_THEME_RADIOMENUITEM:
return
gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA |
gfxWindowsNativeDrawing::CANNOT_AXIS_ALIGNED_SCALE |
gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM;
}
return
gfxWindowsNativeDrawing::CANNOT_DRAW_TO_COLOR_ALPHA |
gfxWindowsNativeDrawing::CANNOT_AXIS_ALIGNED_SCALE |
gfxWindowsNativeDrawing::CANNOT_COMPLEX_TRANSFORM;
}
///////////////////////////////////////////
// Creation Routine

View File

@@ -116,6 +116,8 @@ protected:
void DrawCheckedRect(HDC hdc, const RECT& rc, PRInt32 fore, PRInt32 back,
HBRUSH defaultBack);
PRUint32 GetWidgetNativeDrawingFlags(PRUint8 aWidgetType);
private:
HMODULE mThemeDLL;
HANDLE mButtonTheme;