bug 480233. Make the display list item that canvas uses for painting know about the opacity of the canvas. r/sr=roc
authorStuart Parmenter <pavlov@pavlov.net>
Thu, 05 Mar 2009 05:43:45 -0800
changeset 25788 88074ea4c2880e8cf79d0708d17bbddde8489f45
parent 25787 8b812a0cff6069c0b3054a50edf4fcfdba67caa2
child 25789 d132b09831a138af2757217dc27b26f8c9615c6c
push idunknown
push userunknown
push dateunknown
bugs480233
milestone1.9.2a1pre
bug 480233. Make the display list item that canvas uses for painting know about the opacity of the canvas. r/sr=roc
content/canvas/public/nsICanvasElement.h
content/html/content/src/nsHTMLCanvasElement.cpp
layout/generic/nsHTMLCanvasFrame.cpp
--- a/content/canvas/public/nsICanvasElement.h
+++ b/content/canvas/public/nsICanvasElement.h
@@ -96,13 +96,16 @@ public:
   NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect) = 0;
 
   /*
    * Get the number of contexts in this canvas, and request a context at
    * an index.
    */
   virtual PRInt32 CountContexts () = 0;
   virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index) = 0;
+
+  virtual PRBool GetIsOpaque() = 0;
+
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasElement, NS_ICANVASELEMENT_IID)
 
 #endif /* nsICanvasElement_h___ */
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -90,16 +90,17 @@ public:
   NS_IMETHOD GetSize(PRUint32 *width, PRUint32 *height);
   NS_IMETHOD RenderContexts(gfxContext *ctx);
   virtual PRBool IsWriteOnly();
   virtual void SetWriteOnly();
   NS_IMETHOD InvalidateFrame ();
   NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect);
   virtual PRInt32 CountContexts();
   virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index);
+  virtual PRBool GetIsOpaque();
 
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, PRInt32 aModType) const;
@@ -113,17 +114,16 @@ public:
   }
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            PRBool aNotify);
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
   nsIntSize GetWidthHeight();
-  PRBool GetIsOpaque();
 
   nsresult UpdateContext();
   nsresult ToDataURLImpl(const nsAString& aMimeType,
                          const nsAString& aEncoderOptions,
                          nsAString& aDataURL);
 
   nsString mCurrentContextId;
   nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
@@ -190,22 +190,16 @@ nsHTMLCanvasElement::GetWidthHeight()
   if (size.width <= 0)
     size.width = DEFAULT_CANVAS_WIDTH;
   if (size.height <= 0)
     size.height = DEFAULT_CANVAS_HEIGHT;
 
   return size;
 }
 
-PRBool
-nsHTMLCanvasElement::GetIsOpaque()
-{
-  return HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque);
-}
-
 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLCanvasElement, Width, width, DEFAULT_CANVAS_WIDTH)
 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLCanvasElement, Height, height, DEFAULT_CANVAS_HEIGHT)
 NS_IMPL_BOOL_ATTR(nsHTMLCanvasElement, MozOpaque, moz_opaque)
 
 nsresult
 nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                              nsIAtom* aPrefix, const nsAString& aValue,
                              PRBool aNotify)
@@ -583,8 +577,14 @@ nsHTMLCanvasElement::CountContexts()
 nsICanvasRenderingContextInternal *
 nsHTMLCanvasElement::GetContextAtIndex (PRInt32 index)
 {
   if (mCurrentContext && index == 0)
     return mCurrentContext.get();
 
   return NULL;
 }
+
+PRBool
+nsHTMLCanvasElement::GetIsOpaque()
+{
+  return HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque);
+}
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -44,16 +44,51 @@
 #include "nsGkAtoms.h"
 
 #include "nsHTMLCanvasFrame.h"
 #include "nsICanvasElement.h"
 #include "nsDisplayList.h"
 
 #include "nsTransform2D.h"
 
+
+class nsDisplayItemCanvas : public nsDisplayItem {
+public:
+  nsDisplayItemCanvas(nsIFrame* aFrame)
+    : nsDisplayItem(aFrame)
+  {
+    MOZ_COUNT_CTOR(nsDisplayItemCanvas);
+  }
+#ifdef NS_BUILD_REFCNT_LOGGING
+  virtual ~nsDisplayItemCanvas() {
+    MOZ_COUNT_DTOR(nsDisplayItemCanvas);
+  }
+#endif
+
+  NS_DISPLAY_DECL_NAME("nsDisplayItemCanvas")
+  
+  virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
+                     const nsRect& aDirtyRect) {
+    nsHTMLCanvasFrame* f = static_cast<nsHTMLCanvasFrame*>(GetUnderlyingFrame());
+    f->PaintCanvas(*aCtx, aDirtyRect, aBuilder->ToReferenceFrame(f));
+  }
+
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) {
+    nsIFrame* f = GetUnderlyingFrame();
+    nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(f->GetContent()));
+    return canvas->GetIsOpaque();
+  }
+
+  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
+    nsHTMLCanvasFrame* f = static_cast<nsHTMLCanvasFrame*>(GetUnderlyingFrame());
+    return f->GetInnerArea() + aBuilder->ToReferenceFrame(f);
+  }
+};
+
+
 nsIFrame*
 NS_NewHTMLCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsHTMLCanvasFrame(aContext);
 }
 
 nsHTMLCanvasFrame::~nsHTMLCanvasFrame()
 {
@@ -224,35 +259,29 @@ nsHTMLCanvasFrame::PaintCanvas(nsIRender
     aRenderingContext.Translate(inner.x, inner.y);
 
     canvas->RenderContexts(aRenderingContext.ThebesContext());
 
     aRenderingContext.PopState();
   }
 }
 
-static void PaintCanvas(nsIFrame* aFrame, nsIRenderingContext* aCtx,
-                        const nsRect& aDirtyRect, nsPoint aPt)
-{
-  static_cast<nsHTMLCanvasFrame*>(aFrame)->PaintCanvas(*aCtx, aDirtyRect, aPt);
-}
-
 NS_IMETHODIMP
 nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
     return NS_OK;
 
   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aLists.Content()->AppendNewToTop(new (aBuilder)
-         nsDisplayGeneric(this, ::PaintCanvas, "Canvas"));
+         nsDisplayItemCanvas(this));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return DisplaySelectionOverlay(aBuilder, aLists,
                                  nsISelectionDisplay::DISPLAY_IMAGES);
 }
 
 NS_IMETHODIMP  
 nsHTMLCanvasFrame::GetContentForEvent(nsPresContext* aPresContext,