b=483412; don't overaggressively invalidate on canvas drawWindow; r=roc

This commit is contained in:
Vladimir Vukicevic 2009-04-08 13:27:20 -07:00
Родитель 58d8e271e5
Коммит 914089143b
4 изменённых файлов: 61 добавлений и 29 удалений

Просмотреть файл

@ -39,10 +39,10 @@
#define nsICanvasElement_h___
#include "nsISupports.h"
#include "nsRect.h"
class gfxContext;
class nsIFrame;
struct gfxRect;
// {C234660C-BD06-493e-8583-939A5A158B37}
#define NS_ICANVASELEMENT_IID \
@ -91,9 +91,9 @@ public:
/*
* Ask the canvas frame to invalidate a portion of the frame; damageRect
* is relative to the origin of the canvas frame.
* is relative to the origin of the canvas frame in CSS pixels.
*/
NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect) = 0;
NS_IMETHOD InvalidateFrameSubrect (const gfxRect& damageRect) = 0;
/*
* Get the number of contexts in this canvas, and request a context at

Просмотреть файл

@ -318,6 +318,8 @@ public:
virtual ~nsCanvasRenderingContext2D();
nsresult Redraw();
// this rect is in CSS pixels
nsresult Redraw(const gfxRect& r);
// nsICanvasRenderingContextInternal
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
@ -889,6 +891,20 @@ nsCanvasRenderingContext2D::Redraw()
return NS_OK;
}
nsresult
nsCanvasRenderingContext2D::Redraw(const gfxRect& r)
{
if (!mCanvasElement)
return NS_OK;
if (!mIsFrameInvalid) {
mIsFrameInvalid = PR_TRUE;
return mCanvasElement->InvalidateFrameSubrect(r);
}
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
{
@ -3433,7 +3449,13 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY
mThebes->SetColor(gfxRGBA(1,1,1,1));
DirtyAllStyles();
Redraw();
// note that aX and aY are coordinates in the document that
// we're drawing; aX and aY are drawn to 0,0 in current user
// space.
gfxRect damageRect = mThebes->UserToDevice(gfxRect(0, 0, aW, aH));
damageRect.RoundOut();
Redraw(damageRect);
return rv;
}

Просмотреть файл

@ -92,7 +92,7 @@ public:
virtual PRBool IsWriteOnly();
virtual void SetWriteOnly();
NS_IMETHOD InvalidateFrame ();
NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect);
NS_IMETHOD InvalidateFrameSubrect (const gfxRect& damageRect);
virtual PRInt32 CountContexts();
virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index);
virtual PRBool GetIsOpaque();
@ -555,11 +555,29 @@ nsHTMLCanvasElement::InvalidateFrame()
}
NS_IMETHODIMP
nsHTMLCanvasElement::InvalidateFrameSubrect(const nsRect& damageRect)
nsHTMLCanvasElement::InvalidateFrameSubrect(const gfxRect& damageRect)
{
nsIFrame *frame = GetPrimaryFrame(Flush_Frames);
if (frame) {
frame->Invalidate(damageRect);
nsRect contentArea(frame->GetContentRect());
nsIntSize size = GetWidthHeight();
// damageRect and size are in CSS pixels; contentArea is in appunits
// We want a rect in appunits; so avoid doing pixels-to-appunits and
// vice versa conversion here.
gfxRect realRect(damageRect);
realRect.Scale(contentArea.width / gfxFloat(size.width),
contentArea.height / gfxFloat(size.height));
realRect.RoundOut();
// then make it a nsRect
nsRect invalRect(realRect.X(), realRect.Y(),
realRect.Width(), realRect.Height());
// account for border/padding
invalRect.MoveBy(contentArea.TopLeft() - frame->GetPosition());
frame->Invalidate(invalRect);
}
return NS_OK;

Просмотреть файл

@ -49,6 +49,7 @@
#include "nsTransform2D.h"
#include "gfxContext.h"
class nsDisplayItemCanvas : public nsDisplayItem {
public:
@ -224,6 +225,7 @@ void
nsHTMLCanvasFrame::PaintCanvas(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, nsPoint aPt)
{
nsPresContext *presContext = PresContext();
nsRect inner = GetInnerArea() + aPt;
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
@ -234,34 +236,24 @@ nsHTMLCanvasFrame::PaintCanvas(nsIRenderingContext& aRenderingContext,
if (inner.width == 0 || inner.height == 0)
return;
nsIntSize canvasSize = GetCanvasSize();
nsSize sizeAppUnits(PresContext()->DevPixelsToAppUnits(canvasSize.width),
PresContext()->DevPixelsToAppUnits(canvasSize.height));
nsIntSize sizeCSSPixels = GetCanvasSize();
nsSize sizeAppUnits(nsPresContext::CSSPixelsToAppUnits(sizeCSSPixels.width),
nsPresContext::CSSPixelsToAppUnits(sizeCSSPixels.height));
// XXXvlad clip to aDirtyRect!
gfxContext *ctx = aRenderingContext.ThebesContext();
if (inner.Size() != sizeAppUnits)
{
float sx = inner.width / (float) sizeAppUnits.width;
float sy = inner.height / (float) sizeAppUnits.height;
gfxFloat sx = inner.width / (gfxFloat) sizeAppUnits.width;
gfxFloat sy = inner.height / (gfxFloat) sizeAppUnits.height;
aRenderingContext.PushState();
aRenderingContext.Translate(inner.x, inner.y);
aRenderingContext.Scale(sx, sy);
ctx->Save();
canvas->RenderContexts(aRenderingContext.ThebesContext());
ctx->Translate(gfxPoint(presContext->AppUnitsToGfxUnits(inner.x),
presContext->AppUnitsToGfxUnits(inner.y)));
ctx->Scale(sx, sy);
aRenderingContext.PopState();
} else {
//nsIRenderingContext::AutoPushTranslation(&aRenderingContext, px, py);
canvas->RenderContexts(ctx);
aRenderingContext.PushState();
aRenderingContext.Translate(inner.x, inner.y);
canvas->RenderContexts(aRenderingContext.ThebesContext());
aRenderingContext.PopState();
}
ctx->Restore();
}
NS_IMETHODIMP