зеркало из https://github.com/mozilla/gecko-dev.git
rounding changes in nsNativeThemeGTK::DrawWidgetBackground,
rename aClipRect to aDirtyRect in nsITheme::DrawWidgetBackground. b=444837 r=roc
This commit is contained in:
Родитель
516ed839ce
Коммит
0ed708d923
|
@ -83,7 +83,7 @@ public:
|
|||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect)=0;
|
||||
const nsRect& aDirtyRect)=0;
|
||||
|
||||
/**
|
||||
* Get the computed CSS border for the widget, in pixels.
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect);
|
||||
const nsRect& aDirtyRect);
|
||||
NS_IMETHOD GetWidgetBorder(nsIDeviceContext* aContext,
|
||||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
|
|
|
@ -984,7 +984,7 @@ nsNativeThemeCocoa::GetParentScrollbarFrame(nsIFrame *aFrame)
|
|||
NS_IMETHODIMP
|
||||
nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType, const nsRect& aRect,
|
||||
const nsRect& aClipRect)
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
|
@ -993,16 +993,16 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame
|
|||
aContext->GetDeviceContext(*getter_AddRefs(dctx));
|
||||
PRInt32 p2a = dctx->AppUnitsPerDevPixel();
|
||||
|
||||
gfxRect nativeClipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
|
||||
gfxRect nativeDirtyRect(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
|
||||
gfxRect nativeWidgetRect(aRect.x, aRect.y, aRect.width, aRect.height);
|
||||
nativeWidgetRect.ScaleInverse(gfxFloat(p2a));
|
||||
nativeClipRect.ScaleInverse(gfxFloat(p2a));
|
||||
nativeDirtyRect.ScaleInverse(gfxFloat(p2a));
|
||||
|
||||
nsRefPtr<gfxContext> thebesCtx = aContext->ThebesContext();
|
||||
if (!thebesCtx)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
gfxQuartzNativeDrawing nativeDrawing(thebesCtx, nativeClipRect);
|
||||
gfxQuartzNativeDrawing nativeDrawing(thebesCtx, nativeDirtyRect);
|
||||
|
||||
CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
|
||||
if (cgContext == nsnull) {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
* Brian Ryner <bryner@brianryner.com> (Original Author)
|
||||
* Michael Ventnor <m.ventnor@gmail.com>
|
||||
* Teune van Steeg <t.vansteeg@gmail.com>
|
||||
* Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -662,7 +663,7 @@ ThemeRenderer::NativeDraw(Screen* screen, Drawable drawable, Visual* visual,
|
|||
if (gdkPixmap) {
|
||||
g_object_ref(G_OBJECT(gdkPixmap));
|
||||
} else {
|
||||
// XXX gtk+2.10 has gdk_pixmap_foreign_new_for_screen which would not
|
||||
// XXX gtk+-2.10 has gdk_pixmap_foreign_new_for_screen which would not
|
||||
// use XGetGeometry.
|
||||
gdkPixmap = gdk_pixmap_foreign_new_for_display(gdkDpy, drawable);
|
||||
if (!gdkPixmap)
|
||||
|
@ -729,44 +730,12 @@ GetExtraSizeForWidget(PRUint8 aWidgetType, nsIntMargin* aExtra)
|
|||
}
|
||||
}
|
||||
|
||||
static GdkRectangle
|
||||
ConvertToGdkRect(const nsRect &aRect, PRInt32 aP2A)
|
||||
{
|
||||
GdkRectangle gdk_rect;
|
||||
gdk_rect.x = NSAppUnitsToIntPixels(aRect.x, aP2A);
|
||||
gdk_rect.y = NSAppUnitsToIntPixels(aRect.y, aP2A);
|
||||
gdk_rect.width = NSAppUnitsToIntPixels(aRect.XMost(), aP2A) - gdk_rect.x;
|
||||
gdk_rect.height = NSAppUnitsToIntPixels(aRect.YMost(), aP2A) - gdk_rect.y;
|
||||
return gdk_rect;
|
||||
}
|
||||
|
||||
static GdkRectangle
|
||||
ConvertGfxToGdkRect(const gfxRect &aRect, const gfxPoint &aTranslation)
|
||||
{
|
||||
GdkRectangle gdk_rect;
|
||||
gdk_rect.x = NSToIntRound(aRect.X()) - NSToIntRound(aTranslation.x);
|
||||
gdk_rect.y = NSToIntRound(aRect.Y()) - NSToIntRound(aTranslation.y);
|
||||
gdk_rect.width = NSToIntRound(aRect.Width());
|
||||
gdk_rect.height = NSToIntRound(aRect.Height());
|
||||
return gdk_rect;
|
||||
}
|
||||
|
||||
static gfxRect
|
||||
ConvertToGfxRect(const nsRect &aRect, PRInt32 aP2A)
|
||||
{
|
||||
gfxRect rect(NSAppUnitsToFloatPixels(aRect.x, aP2A),
|
||||
NSAppUnitsToFloatPixels(aRect.y, aP2A),
|
||||
NSAppUnitsToFloatPixels(aRect.width, aP2A),
|
||||
NSAppUnitsToFloatPixels(aRect.height, aP2A));
|
||||
return rect;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNativeThemeGTK::DrawWidgetBackground(nsIRenderingContext* aContext,
|
||||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect)
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
GtkWidgetState state;
|
||||
GtkThemeWidgetType gtkWidgetType;
|
||||
|
@ -776,24 +745,74 @@ nsNativeThemeGTK::DrawWidgetBackground(nsIRenderingContext* aContext,
|
|||
&flags))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDeviceContext> dctx = nsnull;
|
||||
aContext->GetDeviceContext(*getter_AddRefs(dctx));
|
||||
PRInt32 p2a = dctx->AppUnitsPerDevPixel();
|
||||
gfxContext* ctx = aContext->ThebesContext();
|
||||
nsPresContext *presContext = aFrame->PresContext();
|
||||
|
||||
gfxRect rect = presContext->AppUnitsToGfxUnits(aRect);
|
||||
gfxRect dirtyRect = presContext->AppUnitsToGfxUnits(aDirtyRect);
|
||||
|
||||
// Align to device pixels where sensible
|
||||
// to provide crisper and faster drawing.
|
||||
// Don't snap if it's a non-unit scale factor. We're going to have to take
|
||||
// slow paths then in any case.
|
||||
PRBool snapXY = ctx->UserToDevicePixelSnapped(rect);
|
||||
if (snapXY) {
|
||||
// Leave rect in device coords but make dirtyRect consistent.
|
||||
dirtyRect = ctx->UserToDevice(dirtyRect);
|
||||
}
|
||||
|
||||
// Translate the dirty rect so that it is wrt the widget top-left.
|
||||
dirtyRect.MoveBy(-rect.pos);
|
||||
// Round out the dirty rect to gdk pixels to ensure that gtk draws
|
||||
// enough pixels for interpolation to device pixels.
|
||||
dirtyRect.RoundOut();
|
||||
|
||||
// GTK themes can only draw an integer number of pixels
|
||||
// (even when not snapped).
|
||||
nsIntRect widgetRect(0, 0, NS_lround(rect.Width()), NS_lround(rect.Height()));
|
||||
|
||||
// This is the rectangle that will actually be drawn, in gdk pixels
|
||||
nsIntRect drawingRect(PRInt32(dirtyRect.X()),
|
||||
PRInt32(dirtyRect.Y()),
|
||||
PRInt32(dirtyRect.Width()),
|
||||
PRInt32(dirtyRect.Height()));
|
||||
if (!drawingRect.IntersectRect(widgetRect, drawingRect))
|
||||
return NS_OK;
|
||||
|
||||
// This is the rectangle that will actually be drawn, in appunits
|
||||
nsRect drawingRect(aClipRect);
|
||||
nsIntMargin extraSize;
|
||||
GetExtraSizeForWidget(aWidgetType, &extraSize);
|
||||
// inflate drawing rect to account for the overdraw
|
||||
nsMargin extraSizeAppUnits(NSIntPixelsToAppUnits(extraSize.left, p2a),
|
||||
NSIntPixelsToAppUnits(extraSize.top, p2a),
|
||||
NSIntPixelsToAppUnits(extraSize.right, p2a),
|
||||
NSIntPixelsToAppUnits(extraSize.bottom, p2a));
|
||||
drawingRect.Inflate(extraSizeAppUnits);
|
||||
// The margin should be applied to the widget rect rather than the dirty
|
||||
// rect but nsCSSRendering::PaintBackgroundWithSC has already intersected
|
||||
// the dirty rect with the uninflated widget rect.
|
||||
if (GetExtraSizeForWidget(aWidgetType, &extraSize)) {
|
||||
drawingRect.Inflate(extraSize);
|
||||
}
|
||||
|
||||
// gdk rectangles are wrt the drawing rect.
|
||||
|
||||
// The gdk_clip is just advisory here, meanining "you don't
|
||||
// need to draw outside this rect if you don't feel like it!"
|
||||
GdkRectangle gdk_clip = {0, 0, drawingRect.width, drawingRect.height};
|
||||
|
||||
GdkRectangle gdk_rect = {-drawingRect.x, -drawingRect.y,
|
||||
widgetRect.width, widgetRect.height};
|
||||
|
||||
ThemeRenderer renderer(state, gtkWidgetType, flags, direction,
|
||||
gdk_rect, gdk_clip);
|
||||
|
||||
// We require the use of the default screen and visual
|
||||
// because I'm afraid that otherwise the GTK theme may explode.
|
||||
// Some themes (e.g. Clearlooks) just don't clip properly to any
|
||||
// clip rect we provide, so we cannot advertise support for clipping within
|
||||
// the widget bounds.
|
||||
PRUint32 rendererFlags = gfxXlibNativeRenderer::DRAW_SUPPORTS_OFFSET;
|
||||
|
||||
// translate everything so (0,0) is the top left of the drawingRect
|
||||
nsIRenderingContext::AutoPushTranslation
|
||||
autoTranslation(aContext, drawingRect.x, drawingRect.y);
|
||||
gfxContextAutoSaveRestore autoSR(ctx);
|
||||
if (snapXY) {
|
||||
// Rects are in device coords.
|
||||
ctx->IdentityMatrix();
|
||||
}
|
||||
ctx->Translate(rect.pos + gfxPoint(drawingRect.x, drawingRect.y));
|
||||
|
||||
NS_ASSERTION(!IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType),
|
||||
"Trying to render an unsafe widget!");
|
||||
|
@ -805,53 +824,9 @@ nsNativeThemeGTK::DrawWidgetBackground(nsIRenderingContext* aContext,
|
|||
oldHandler = XSetErrorHandler(NativeThemeErrorHandler);
|
||||
}
|
||||
|
||||
gfxContext* ctx = aContext->ThebesContext();
|
||||
gfxMatrix current = ctx->CurrentMatrix();
|
||||
|
||||
// We require the use of the default screen and visual
|
||||
// because I'm afraid that otherwise the GTK theme may explode.
|
||||
// Some themes (e.g. Clearlooks) just don't clip properly to any
|
||||
// clip rect we provide, so we cannot advertise support for clipping within the
|
||||
// widget bounds. The gdk_clip is just advisory here, meanining "you don't
|
||||
// need to draw outside this rect if you don't feel like it!"
|
||||
GdkRectangle gdk_rect, gdk_clip;
|
||||
gfxRect gfx_rect = ConvertToGfxRect(aRect - drawingRect.TopLeft(), p2a);
|
||||
gfxRect gfx_clip = ConvertToGfxRect(drawingRect - drawingRect.TopLeft(), p2a);
|
||||
if (ctx->UserToDevicePixelSnapped(gfx_rect) &&
|
||||
ctx->UserToDevicePixelSnapped(gfx_clip)) {
|
||||
gfxPoint currentTranslation = current.GetTranslation();
|
||||
gdk_rect = ConvertGfxToGdkRect(gfx_rect, currentTranslation);
|
||||
gdk_clip = ConvertGfxToGdkRect(gfx_clip, currentTranslation);
|
||||
}
|
||||
else {
|
||||
gdk_rect = ConvertToGdkRect(aRect - drawingRect.TopLeft(), p2a);
|
||||
gdk_clip = ConvertToGdkRect(drawingRect - drawingRect.TopLeft(), p2a);
|
||||
}
|
||||
ThemeRenderer renderer(state, gtkWidgetType, flags, direction, gdk_rect, gdk_clip);
|
||||
|
||||
// XXXbz do we really want to round here, then snap, then round again?
|
||||
gfxRect rect(0, 0, NSAppUnitsToIntPixels(drawingRect.width, p2a),
|
||||
NSAppUnitsToIntPixels(drawingRect.height, p2a));
|
||||
|
||||
PRUint32 rendererFlags = gfxXlibNativeRenderer::DRAW_SUPPORTS_OFFSET;
|
||||
// Don't snap if it's a non-unit scale factor. We're going to have to take
|
||||
// slow paths then in any case.
|
||||
PRBool snapXY = ctx->UserToDevicePixelSnapped(rect) &&
|
||||
!current.HasNonTranslation();
|
||||
if (snapXY) {
|
||||
gfxMatrix translation;
|
||||
translation.Translate(rect.TopLeft());
|
||||
ctx->SetMatrix(translation);
|
||||
renderer.Draw(gdk_x11_get_default_xdisplay(), ctx,
|
||||
NSToCoordRound(rect.Width()), NSToCoordRound(rect.Height()),
|
||||
drawingRect.width, drawingRect.height,
|
||||
rendererFlags, nsnull);
|
||||
ctx->SetMatrix(current);
|
||||
} else {
|
||||
renderer.Draw(gdk_x11_get_default_xdisplay(), ctx,
|
||||
NSToIntCeil(NSAppUnitsToFloatPixels(drawingRect.width, p2a)),
|
||||
NSToIntCeil(NSAppUnitsToFloatPixels(drawingRect.height, p2a)),
|
||||
rendererFlags, nsnull);
|
||||
}
|
||||
|
||||
if (!safeState) {
|
||||
gdk_flush();
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
NS_IMETHOD DrawWidgetBackground(nsIRenderingContext* aContext,
|
||||
nsIFrame* aFrame, PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect);
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
NS_IMETHOD GetWidgetBorder(nsIDeviceContext* aContext, nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType, nsMargin* aResult);
|
||||
|
|
|
@ -956,11 +956,11 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
|
|||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect)
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
HANDLE theme = GetTheme(aWidgetType);
|
||||
if (!theme)
|
||||
return ClassicDrawWidgetBackground(aContext, aFrame, aWidgetType, aRect, aClipRect);
|
||||
return ClassicDrawWidgetBackground(aContext, aFrame, aWidgetType, aRect, aDirtyRect);
|
||||
|
||||
if (!nsUXThemeData::drawThemeBG)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -976,10 +976,10 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
|
|||
RECT widgetRect;
|
||||
RECT clipRect;
|
||||
gfxRect tr(aRect.x, aRect.y, aRect.width, aRect.height),
|
||||
cr(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
|
||||
dr(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
|
||||
|
||||
tr.ScaleInverse(p2a);
|
||||
cr.ScaleInverse(p2a);
|
||||
dr.ScaleInverse(p2a);
|
||||
|
||||
/* See GetWidgetOverflow */
|
||||
if (aWidgetType == NS_THEME_DROPDOWN_BUTTON &&
|
||||
|
@ -989,14 +989,14 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
|
|||
tr.size.width += 1.0;
|
||||
tr.size.height += 2.0;
|
||||
|
||||
cr.pos.y -= 1.0;
|
||||
cr.size.width += 1.0;
|
||||
cr.size.height += 2.0;
|
||||
dr.pos.y -= 1.0;
|
||||
dr.size.width += 1.0;
|
||||
dr.size.height += 2.0;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxContext> ctx = aContext->ThebesContext();
|
||||
|
||||
gfxWindowsNativeDrawing nativeDrawing(ctx, cr, GetWidgetNativeDrawingFlags(aWidgetType));
|
||||
gfxWindowsNativeDrawing nativeDrawing(ctx, dr, GetWidgetNativeDrawingFlags(aWidgetType));
|
||||
|
||||
RENDER_AGAIN:
|
||||
|
||||
|
@ -1005,13 +1005,13 @@ RENDER_AGAIN:
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
nativeDrawing.TransformToNativeRect(tr, widgetRect);
|
||||
nativeDrawing.TransformToNativeRect(cr, clipRect);
|
||||
nativeDrawing.TransformToNativeRect(dr, clipRect);
|
||||
|
||||
#if 0
|
||||
{
|
||||
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,
|
||||
fprintf (stderr, "tr: [%d %d %d %d]\ndr: [%d %d %d %d]\noff: [%f %f]\n",
|
||||
tr.x, tr.y, tr.width, tr.height, dr.x, dr.y, dr.width, dr.height,
|
||||
offset.x, offset.y);
|
||||
}
|
||||
#endif
|
||||
|
@ -2384,7 +2384,7 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
|
|||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect)
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
PRInt32 part, state;
|
||||
PRBool focused;
|
||||
|
@ -2398,14 +2398,14 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon
|
|||
gfxFloat p2a = gfxFloat(dc->AppUnitsPerDevPixel());
|
||||
RECT widgetRect;
|
||||
gfxRect tr(aRect.x, aRect.y, aRect.width, aRect.height),
|
||||
cr(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
|
||||
dr(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
|
||||
|
||||
tr.ScaleInverse(p2a);
|
||||
cr.ScaleInverse(p2a);
|
||||
dr.ScaleInverse(p2a);
|
||||
|
||||
nsRefPtr<gfxContext> ctx = aContext->ThebesContext();
|
||||
|
||||
gfxWindowsNativeDrawing nativeDrawing(ctx, cr, GetWidgetNativeDrawingFlags(aWidgetType));
|
||||
gfxWindowsNativeDrawing nativeDrawing(ctx, dr, GetWidgetNativeDrawingFlags(aWidgetType));
|
||||
|
||||
RENDER_AGAIN:
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
nsIFrame* aFrame,
|
||||
PRUint8 aWidgetType,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aClipRect);
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
NS_IMETHOD GetWidgetBorder(nsIDeviceContext* aContext,
|
||||
nsIFrame* aFrame,
|
||||
|
|
Загрузка…
Ссылка в новой задаче