diff --git a/mozilla/content/html/content/src/nsHTMLCanvasElement.cpp b/mozilla/content/html/content/src/nsHTMLCanvasElement.cpp
index f8b988d6065..2d0470e1e80 100644
--- a/mozilla/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/mozilla/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -53,6 +53,9 @@
#include "nsICanvasRenderingContextInternal.h"
+#define DEFAULT_CANVAS_WIDTH 300
+#define DEFAULT_CANVAS_HEIGHT 200
+
class nsHTMLCanvasElement : public nsGenericHTMLElement,
public nsIDOMHTMLCanvasElement,
public nsICanvasElement
@@ -83,6 +86,7 @@ public:
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
PRBool ParseAttribute(nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult);
+ nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, PRInt32 aModType) const;
// SetAttr override. C++ is stupid, so have to override both
// overloaded methods.
@@ -94,11 +98,8 @@ public:
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
-
- nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
- PRInt32 aModType) const;
protected:
- nsSize GetWidthHeight();
+ nsIntSize GetWidthHeight();
nsresult UpdateImageContainer();
nsresult UpdateContext();
@@ -135,63 +136,35 @@ NS_HTML_CONTENT_INTERFACE_MAP_END
NS_IMPL_DOM_CLONENODE(nsHTMLCanvasElement)
-nsSize
+nsIntSize
nsHTMLCanvasElement::GetWidthHeight()
{
- nsSize size(0,0);
+ nsIntSize size(0,0);
const nsAttrValue* value;
PRInt32 k, rv;
- if ((value = GetParsedAttr(nsHTMLAtoms::width))) {
- if (value->Type() == nsAttrValue::eInteger) {
+ if ((value = GetParsedAttr(nsHTMLAtoms::width)) &&
+ value->Type() == nsAttrValue::eInteger)
+ {
size.width = value->GetIntegerValue();
- } else if (value->Type() == nsAttrValue::eString) {
- k = value->GetStringValue().ToInteger(&rv);
- if (NS_SUCCEEDED(rv))
- size.width = k;
- }
}
- if ((value = GetParsedAttr(nsHTMLAtoms::height))) {
- if (value->Type() == nsAttrValue::eInteger) {
+ if ((value = GetParsedAttr(nsHTMLAtoms::height)) &&
+ value->Type() == nsAttrValue::eInteger)
+ {
size.height = value->GetIntegerValue();
- } else if (value->Type() == nsAttrValue::eString) {
- k = value->GetStringValue().ToInteger(&rv);
- if (NS_SUCCEEDED(rv))
- size.height = k;
- }
}
+ if (size.width <= 0)
+ size.width = DEFAULT_CANVAS_WIDTH;
+ if (size.height <= 0)
+ size.height = DEFAULT_CANVAS_HEIGHT;
+
return size;
}
-NS_IMETHODIMP
-nsHTMLCanvasElement::GetHeight(PRInt32* aHeight)
-{
- *aHeight = GetWidthHeight().height;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLCanvasElement::SetHeight(PRInt32 aHeight)
-{
- return nsGenericHTMLElement::SetIntAttr(nsHTMLAtoms::height, aHeight);
-}
-
-NS_IMETHODIMP
-nsHTMLCanvasElement::GetWidth(PRInt32* aWidth)
-{
- *aWidth = GetWidthHeight().width;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLCanvasElement::SetWidth(PRInt32 aWidth)
-{
- return nsGenericHTMLElement::SetIntAttr(nsHTMLAtoms::width, aWidth);
-}
+NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLCanvasElement, Width, width, DEFAULT_CANVAS_WIDTH)
+NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLCanvasElement, Height, height, DEFAULT_CANVAS_HEIGHT)
nsresult
nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
@@ -205,9 +178,6 @@ nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
{
rv = UpdateImageContainer();
NS_ENSURE_SUCCESS(rv, rv);
-
- rv = UpdateContext();
- NS_ENSURE_SUCCESS(rv, rv);
}
return rv;
@@ -222,7 +192,7 @@ nsHTMLCanvasElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
if (aAttribute == nsHTMLAtoms::width ||
aAttribute == nsHTMLAtoms::height)
{
- NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
+ NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
}
return retval;
}
@@ -231,8 +201,6 @@ static void
MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsRuleData* aData)
{
- nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
- nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
}
@@ -255,9 +223,7 @@ nsHTMLCanvasElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
static const MappedAttributeEntry* const map[] = {
sCommonAttributeMap,
- sImageMarginAttributeMap,
- sImageBorderAttributeMap,
- sImageAlignAttributeMap
+ sImageMarginAttributeMap
};
return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
@@ -284,6 +250,8 @@ NS_IMETHODIMP
nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
nsISupports **aContext)
{
+ nsresult rv;
+
if (mCurrentContextId.IsEmpty()) {
nsCString ctxId;
ctxId.Assign(NS_LossyConvertUTF16toASCII(aContextId));
@@ -303,8 +271,10 @@ nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
nsCString ctxString("@mozilla.org/content/canvas-rendering-context;1?id=");
ctxString.Append(ctxId);
- mCurrentContext = do_CreateInstance(nsPromiseFlatCString(ctxString).get());
- if (!mCurrentContext)
+ mCurrentContext = do_CreateInstance(nsPromiseFlatCString(ctxString).get(), &rv);
+ if (rv == NS_ERROR_OUT_OF_MEMORY)
+ return NS_ERROR_OUT_OF_MEMORY;
+ if (NS_FAILED(rv))
return NS_ERROR_INVALID_ARG;
nsCOMPtr internalctx(do_QueryInterface(mCurrentContext));
@@ -313,17 +283,15 @@ nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
return NS_ERROR_FAILURE;
}
- nsresult rv = internalctx->Init(this);
+ rv = internalctx->Init(this);
NS_ENSURE_SUCCESS(rv, rv);
rv = UpdateImageContainer();
NS_ENSURE_SUCCESS(rv, rv);
- rv = UpdateContext();
- NS_ENSURE_SUCCESS(rv, rv);
-
mCurrentContextId.Assign(aContextId);
} else if (!mCurrentContextId.Equals(aContextId)) {
+ //XXX eventually allow for more than one active context on a given canvas
return NS_ERROR_INVALID_ARG;
}
@@ -336,10 +304,7 @@ nsHTMLCanvasElement::UpdateImageContainer()
{
nsresult rv = NS_OK;
- nsSize sz = GetWidthHeight();
- if (sz.width == 0 || sz.height == 0)
- return NS_OK;
-
+ nsIntSize sz = GetWidthHeight();
PRInt32 w = 0, h = 0;
if (mImageFrame) {
@@ -365,7 +330,7 @@ nsHTMLCanvasElement::UpdateImageContainer()
mImageContainer->AppendFrame(mImageFrame);
}
- return rv;
+ return UpdateContext();
}
nsresult
@@ -386,8 +351,12 @@ nsHTMLCanvasElement::UpdateContext()
NS_IMETHODIMP
nsHTMLCanvasElement::GetCanvasImageContainer (imgIContainer **aImageContainer)
{
- if (!mImageContainer)
- UpdateImageContainer();
+ nsresult rv;
+
+ if (!mImageContainer) {
+ rv = UpdateImageContainer();
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
NS_IF_ADDREF(*aImageContainer = mImageContainer);
return NS_OK;
diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp
index db1eb936297..5abea86e072 100644
--- a/mozilla/layout/base/nsCSSFrameConstructor.cpp
+++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp
@@ -5394,6 +5394,9 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
rv = NS_NewIsIndexFrame(mPresShell, &newFrame);
}
else if (nsHTMLAtoms::canvas == aTag) {
+ if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
+ ProcessPseudoFrames(aState, aFrameItems);
+ }
isReplaced = PR_TRUE;
rv = NS_NewHTMLCanvasFrame(mPresShell, &newFrame);
}
@@ -8484,8 +8487,9 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer,
// then don't do any processing now
nsIAtom* frameType = parentFrame->GetType();
if (frameType == nsLayoutAtoms::objectFrame ||
- frameType == nsLayoutAtoms::tableColFrame) {
- // This handles APPLET, EMBED, OBJECT and COL
+ frameType == nsLayoutAtoms::tableColFrame ||
+ frameType == nsLayoutAtoms::canvasFrame) {
+ // This handles APPLET, EMBED, OBJECT, COL, and CANVAS
return NS_OK;
}
// Deal with inner/outer tables, fieldsets
@@ -9071,8 +9075,9 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer,
// then don't do any processing now
nsIAtom* frameType = parentFrame->GetType();
if (frameType == nsLayoutAtoms::objectFrame ||
- frameType == nsLayoutAtoms::tableColFrame) {
- // This handles APPLET, EMBED, OBJECT and COL
+ frameType == nsLayoutAtoms::tableColFrame ||
+ frameType == nsLayoutAtoms::canvasFrame) {
+ // This handles APPLET, EMBED, OBJECT, COL, and CANVAS
return NS_OK;
}
// Deal with inner/outer tables, fieldsets
diff --git a/mozilla/layout/generic/nsHTMLCanvasFrame.cpp b/mozilla/layout/generic/nsHTMLCanvasFrame.cpp
index eac6dfbe7ab..9de265f0e0f 100644
--- a/mozilla/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/mozilla/layout/generic/nsHTMLCanvasFrame.cpp
@@ -63,32 +63,13 @@ nsHTMLCanvasFrame::~nsHTMLCanvasFrame()
{
}
-NS_IMETHODIMP
-nsHTMLCanvasFrame::Init(nsPresContext* aPresContext,
- nsIContent* aContent,
- nsIFrame* aParent,
- nsStyleContext* aContext,
- nsIFrame* aPrevInFlow)
-{
- nsCOMPtr canvas (do_QueryInterface(aContent));
- NS_ENSURE_TRUE(canvas, NS_ERROR_FAILURE);
-
- nsresult rv = canvas->GetCanvasImageContainer(getter_AddRefs(mImageContainer));
- NS_ENSURE_SUCCESS(rv, rv);
-
- if (mImageContainer) {
- PRInt32 w, h;
- mImageContainer->GetWidth(&w);
- mImageContainer->GetHeight(&h);
-
- mCanvasSize.SizeTo(w, h);
- }
-
- rv = nsSplittableFrame::Init(aPresContext, aContent, aParent,
- aContext, aPrevInFlow);
-
- return rv;
-}
+// We really want a PR_MINMAX to go along with PR_MIN/PR_MAX
+#define MINMAX(_value,_min,_max) \
+ ((_value) < (_min) \
+ ? (_min) \
+ : ((_value) > (_max) \
+ ? (_max) \
+ : (_value)))
NS_IMETHODIMP
nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
@@ -106,13 +87,43 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE;
+ nsCOMPtr canvas(do_QueryInterface(GetContent()));
+ NS_ENSURE_TRUE(canvas, NS_ERROR_FAILURE);
+
+ nsresult rv = canvas->GetCanvasImageContainer(getter_AddRefs(mImageContainer));
+ NS_ENSURE_SUCCESS(rv, rv);
+
float p2t = GetPresContext()->PixelsToTwips();
- aMetrics.width = NSIntPixelsToTwips(mCanvasSize.width, p2t);
- aMetrics.height = NSIntPixelsToTwips(mCanvasSize.height, p2t);
+ if (mImageContainer) {
+ PRInt32 w, h;
+ mImageContainer->GetWidth(&w);
+ mImageContainer->GetHeight(&h);
- aMetrics.width += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
- aMetrics.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom;
+ mCanvasSize.SizeTo(NSIntPixelsToTwips(w, p2t), NSIntPixelsToTwips(h, p2t));
+ } else {
+ mCanvasSize.SizeTo(0, 0);
+ }
+
+ if (aReflowState.mComputedWidth == NS_INTRINSICSIZE)
+ aMetrics.width = mCanvasSize.width;
+ else
+ aMetrics.width = aReflowState.mComputedWidth;
+
+ if (aReflowState.mComputedHeight == NS_INTRINSICSIZE)
+ aMetrics.height = mCanvasSize.height;
+ else
+ aMetrics.height = aReflowState.mComputedHeight;
+
+ // clamp
+ aMetrics.height = MINMAX(aMetrics.height, aReflowState.mComputedMinHeight, aReflowState.mComputedMaxHeight);
+ aMetrics.width = MINMAX(aMetrics.width, aReflowState.mComputedMinWidth, aReflowState.mComputedMaxWidth);
+
+ // stash this away so we can compute our inner area later
+ mBorderPadding = aReflowState.mComputedBorderPadding;
+
+ aMetrics.width += mBorderPadding.left + mBorderPadding.right;
+ aMetrics.height += mBorderPadding.top + mBorderPadding.bottom;
if (mPrevInFlow) {
nscoord y = GetContinuationOffset(&aMetrics.width);
@@ -144,6 +155,19 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
return NS_OK;
}
+// FIXME taken from nsImageFrame, but then had splittable frame stuff
+// removed. That needs to be fixed.
+nsRect
+nsHTMLCanvasFrame::GetInnerArea() const
+{
+ nsRect r;
+ r.x = mBorderPadding.left;
+ r.y = mBorderPadding.top;
+ r.width = mRect.width - mBorderPadding.left - mBorderPadding.right;
+ r.height = mRect.height - mBorderPadding.top - mBorderPadding.bottom;
+ return r;
+}
+
NS_IMETHODIMP
nsHTMLCanvasFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@@ -162,21 +186,25 @@ nsHTMLCanvasFrame::Paint(nsPresContext* aPresContext,
return NS_OK;
}
- if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) {
- nsPoint dstpt = GetPosition();
- float p2t = aPresContext->PixelsToTwips();
- nsRect src(0,
- 0,
- NSIntPixelsToTwips(mCanvasSize.width, p2t),
- NSIntPixelsToTwips(mCanvasSize.height, p2t));
+ // from nsImageFrame
+ // First paint background and borders, which should be in the
+ // FOREGROUND or BACKGROUND paint layer if the element is
+ // inline-level or block-level, respectively (bug 36710). (See
+ // CSS2 9.5, which is the rationale for paint layers.)
+ const nsStyleDisplay* display = GetStyleDisplay();
+ nsFramePaintLayer backgroundLayer = display->IsBlockLevel()
+ ? NS_FRAME_PAINT_LAYER_BACKGROUND
+ : NS_FRAME_PAINT_LAYER_FOREGROUND;
- nsRect dst(0, 0, src.width, src.height);
+ if (aWhichLayer == backgroundLayer) {
+ PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
+ }
- if (mImageContainer) {
- aRenderingContext.DrawImage(mImageContainer, src, dst);
- } else {
- aRenderingContext.FillRect(dst);
- }
+ if ((aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) && mImageContainer) {
+ nsRect inner = GetInnerArea();
+ nsRect src(0, 0, mCanvasSize.width, mCanvasSize.height);
+
+ aRenderingContext.DrawImage(mImageContainer, src, inner);
}
}
@@ -247,6 +275,12 @@ nsHTMLCanvasFrame::GetAccessible(nsIAccessible** aAccessible)
#endif
#ifdef DEBUG
+NS_IMETHODIMP
+nsHTMLCanvasFrame::GetFrameName(nsAString& aResult) const
+{
+ return MakeFrameName(NS_LITERAL_STRING("HTMLCanvas"), aResult);
+}
+
NS_IMETHODIMP
nsHTMLCanvasFrame::List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent) const
{
diff --git a/mozilla/layout/generic/nsHTMLCanvasFrame.h b/mozilla/layout/generic/nsHTMLCanvasFrame.h
index 6140392f939..865b85fd183 100644
--- a/mozilla/layout/generic/nsHTMLCanvasFrame.h
+++ b/mozilla/layout/generic/nsHTMLCanvasFrame.h
@@ -53,12 +53,6 @@ class nsHTMLCanvasFrame : public nsSplittableFrame
public:
nsHTMLCanvasFrame();
- // nsISupports
- NS_IMETHOD Init(nsPresContext* aPresContext,
- nsIContent* aContent,
- nsIFrame* aParent,
- nsStyleContext* aContext,
- nsIFrame* aPrevInFlow);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
@@ -76,12 +70,15 @@ public:
nsEvent* aEvent,
nsIContent** aContent);
+ nsRect GetInnerArea() const;
+
#ifdef ACCESSIBILITY
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
#endif
virtual nsIAtom* GetType() const;
#ifdef DEBUG
+ NS_IMETHOD GetFrameName(nsAString& aResult) const;
NS_IMETHOD List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent) const;
#endif
diff --git a/mozilla/layout/style/html.css b/mozilla/layout/style/html.css
index 355b0d1553d..dacb9f4d630 100644
--- a/mozilla/layout/style/html.css
+++ b/mozilla/layout/style/html.css
@@ -424,10 +424,10 @@ spacer {
/* focusable content: anything w/ tabindex >=0 is focusable */
abbr:focus, acronym:focus, address:focus, applet:focus, b:focus,
-base:focus, big:focus, blockquote:focus, br:focus, caption:focus, center:focus,
-cite:focus, code:focus, col:focus, colgroup:focus, dd:focus, del:focus,
-dfn:focus, dir:focus, div:focus, dl:focus, dt:focus, em:focus, fieldset:focus,
-font:focus, form:focus, h1:focus, h2:focus, h3:focus, h4:focus,
+base:focus, big:focus, blockquote:focus, br:focus, canvas:focus, caption:focus,
+center:focus, cite:focus, code:focus, col:focus, colgroup:focus, dd:focus,
+del:focus, dfn:focus, dir:focus, div:focus, dl:focus, dt:focus, em:focus,
+fieldset:focus, font:focus, form:focus, h1:focus, h2:focus, h3:focus, h4:focus,
h5:focus, h6:focus, hr:focus, i:focus, img:focus, ins:focus,
kbd:focus, label:focus, legend:focus, li:focus, link:focus, menu:focus,
object:focus, ol:focus, p:focus, pre:focus, q:focus, s:focus, samp:focus,
diff --git a/mozilla/parser/htmlparser/src/nsElementTable.cpp b/mozilla/parser/htmlparser/src/nsElementTable.cpp
index 3fc62f94e95..b084efdf0c4 100644
--- a/mozilla/parser/htmlparser/src/nsElementTable.cpp
+++ b/mozilla/parser/htmlparser/src/nsElementTable.cpp
@@ -374,8 +374,8 @@ const nsHTMLElement gHTMLElements[] = {
/*req-parent excl-parent*/ eHTMLTag_unknown,eHTMLTag_unknown,
/*rootnodes,endrootnodes*/ &gRootTags,&gRootTags,
/*autoclose starttags and endtags*/ 0,0,0,0,
- /*parent,incl,exclgroups*/ kSpecial, kNone, kNone,
- /*special props, prop-range*/ kNonContainer,kDefaultPropRange,
+ /*parent,incl,exclgroups*/ kSpecial, (kFlowEntity|kSelf), kNone,
+ /*special props, prop-range*/ 0, kDefaultPropRange,
/*special parents,kids,skip*/ 0,0,eHTMLTag_unknown,
/*contain-func*/ 0
},