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___ #define nsICanvasElement_h___
#include "nsISupports.h" #include "nsISupports.h"
#include "nsRect.h"
class gfxContext; class gfxContext;
class nsIFrame; class nsIFrame;
struct gfxRect;
// {C234660C-BD06-493e-8583-939A5A158B37} // {C234660C-BD06-493e-8583-939A5A158B37}
#define NS_ICANVASELEMENT_IID \ #define NS_ICANVASELEMENT_IID \
@ -91,9 +91,9 @@ public:
/* /*
* Ask the canvas frame to invalidate a portion of the frame; damageRect * 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 * Get the number of contexts in this canvas, and request a context at

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

@ -318,6 +318,8 @@ public:
virtual ~nsCanvasRenderingContext2D(); virtual ~nsCanvasRenderingContext2D();
nsresult Redraw(); nsresult Redraw();
// this rect is in CSS pixels
nsresult Redraw(const gfxRect& r);
// nsICanvasRenderingContextInternal // nsICanvasRenderingContextInternal
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas); NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
@ -889,6 +891,20 @@ nsCanvasRenderingContext2D::Redraw()
return NS_OK; 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 NS_IMETHODIMP
nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height) 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)); mThebes->SetColor(gfxRGBA(1,1,1,1));
DirtyAllStyles(); 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; return rv;
} }

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

@ -92,7 +92,7 @@ public:
virtual PRBool IsWriteOnly(); virtual PRBool IsWriteOnly();
virtual void SetWriteOnly(); virtual void SetWriteOnly();
NS_IMETHOD InvalidateFrame (); NS_IMETHOD InvalidateFrame ();
NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect); NS_IMETHOD InvalidateFrameSubrect (const gfxRect& damageRect);
virtual PRInt32 CountContexts(); virtual PRInt32 CountContexts();
virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index); virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index);
virtual PRBool GetIsOpaque(); virtual PRBool GetIsOpaque();
@ -555,11 +555,29 @@ nsHTMLCanvasElement::InvalidateFrame()
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLCanvasElement::InvalidateFrameSubrect(const nsRect& damageRect) nsHTMLCanvasElement::InvalidateFrameSubrect(const gfxRect& damageRect)
{ {
nsIFrame *frame = GetPrimaryFrame(Flush_Frames); nsIFrame *frame = GetPrimaryFrame(Flush_Frames);
if (frame) { 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; return NS_OK;

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

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