From dcf80e9788e63077527310d945350c0b61df52aa Mon Sep 17 00:00:00 2001 From: "vladimir%pobox.com" Date: Mon, 18 Apr 2005 06:33:23 +0000 Subject: [PATCH] b=288714, html canvas implementation, r=various,a=brendan git-svn-id: svn://10.0.0.236/trunk@172389 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/allmakefiles.sh | 4 + mozilla/content/Makefile.in | 2 +- mozilla/content/base/src/nsDocument.cpp | 4 - mozilla/content/canvas/Makefile.in | 48 + mozilla/content/canvas/public/Makefile.in | 52 + .../content/canvas/public/nsICanvasElement.h | 64 + .../nsICanvasRenderingContextInternal.h | 58 + mozilla/content/canvas/src/Makefile.in | 90 ++ .../canvas/src/nsCanvasRenderingContext2D.cpp | 1363 +++++++++++++++++ mozilla/content/html/content/src/Makefile.in | 1 + .../html/content/src/nsGenericHTMLElement.h | 1 + .../content/html/content/src/nsHTMLAtomList.h | 1 + .../html/content/src/nsHTMLCanvasElement.cpp | 401 +++++ .../html/document/src/nsHTMLContentSink.cpp | 1 - mozilla/dom/public/idl/Makefile.in | 1 + mozilla/dom/public/idl/canvas/Makefile.in | 53 + .../canvas/nsIDOMCanvasRenderingContext2D.idl | 123 ++ mozilla/dom/public/idl/html/Makefile.in | 1 + .../idl/html/nsIDOMHTMLCanvasElement.idl | 60 + mozilla/dom/public/nsIDOMClassInfo.h | 5 + mozilla/dom/src/base/nsDOMClassInfo.cpp | 24 +- mozilla/layout/base/nsCSSFrameConstructor.cpp | 21 +- mozilla/layout/build/Makefile.in | 1 + mozilla/layout/build/nsLayoutCID.h | 6 - mozilla/layout/build/nsLayoutModule.cpp | 42 +- mozilla/layout/generic/Makefile.in | 1 + mozilla/layout/generic/nsHTMLCanvasFrame.cpp | 259 ++++ mozilla/layout/generic/nsHTMLCanvasFrame.h | 99 ++ mozilla/layout/xul/base/public/Makefile.in | 4 - mozilla/layout/xul/base/src/Makefile.in | 8 - .../parser/htmlparser/public/nsHTMLTagList.h | 1 + mozilla/parser/htmlparser/public/nsHTMLTags.h | 2 +- .../parser/htmlparser/src/nsElementTable.cpp | 10 + mozilla/parser/htmlparser/src/nsHTMLTags.cpp | 2 + 34 files changed, 2751 insertions(+), 62 deletions(-) create mode 100644 mozilla/content/canvas/Makefile.in create mode 100644 mozilla/content/canvas/public/Makefile.in create mode 100644 mozilla/content/canvas/public/nsICanvasElement.h create mode 100644 mozilla/content/canvas/public/nsICanvasRenderingContextInternal.h create mode 100644 mozilla/content/canvas/src/Makefile.in create mode 100644 mozilla/content/canvas/src/nsCanvasRenderingContext2D.cpp create mode 100644 mozilla/content/html/content/src/nsHTMLCanvasElement.cpp create mode 100644 mozilla/dom/public/idl/canvas/Makefile.in create mode 100644 mozilla/dom/public/idl/canvas/nsIDOMCanvasRenderingContext2D.idl create mode 100644 mozilla/dom/public/idl/html/nsIDOMHTMLCanvasElement.idl create mode 100644 mozilla/layout/generic/nsHTMLCanvasFrame.cpp create mode 100644 mozilla/layout/generic/nsHTMLCanvasFrame.h diff --git a/mozilla/allmakefiles.sh b/mozilla/allmakefiles.sh index 7d62474b7ac..ffbb24c2b2f 100755 --- a/mozilla/allmakefiles.sh +++ b/mozilla/allmakefiles.sh @@ -108,6 +108,7 @@ dom/public/base/Makefile dom/public/coreEvents/Makefile dom/public/idl/Makefile dom/public/idl/base/Makefile +dom/public/idl/canvas/Makefile dom/public/idl/core/Makefile dom/public/idl/css/Makefile dom/public/idl/events/Makefile @@ -277,6 +278,9 @@ content/Makefile content/base/Makefile content/base/public/Makefile content/base/src/Makefile +content/canvas/Makefile +content/canvas/public/Makefile +content/canvas/src/Makefile content/events/Makefile content/events/public/Makefile content/events/src/Makefile diff --git a/mozilla/content/Makefile.in b/mozilla/content/Makefile.in index 00c0536b331..569bc3d3523 100644 --- a/mozilla/content/Makefile.in +++ b/mozilla/content/Makefile.in @@ -43,7 +43,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = content -DIRS = base html xml xul xbl xsl +DIRS = base canvas html xml xul xbl xsl ifdef MOZ_SVG DIRS += svg diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 99d265ca8e9..354b977f4ba 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -2970,10 +2970,6 @@ nsDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) contractID += "-listbox"; else if (tag == nsXULAtoms::scrollbox) contractID += "-scrollbox"; -#ifdef MOZ_ENABLE_CAIRO - else if (tag == nsXULAtoms::canvas) - contractID += "-canvas"; -#endif } contractID += ";1"; diff --git a/mozilla/content/canvas/Makefile.in b/mozilla/content/canvas/Makefile.in new file mode 100644 index 00000000000..507d59551f7 --- /dev/null +++ b/mozilla/content/canvas/Makefile.in @@ -0,0 +1,48 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Vladimir Vukicevic +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = public src + +include $(topsrcdir)/config/rules.mk + diff --git a/mozilla/content/canvas/public/Makefile.in b/mozilla/content/canvas/public/Makefile.in new file mode 100644 index 00000000000..f63ad9c38a3 --- /dev/null +++ b/mozilla/content/canvas/public/Makefile.in @@ -0,0 +1,52 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Vladimir Vukicevic +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = content + +EXPORTS = \ + nsICanvasRenderingContextInternal.h \ + nsICanvasElement.h \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/content/canvas/public/nsICanvasElement.h b/mozilla/content/canvas/public/nsICanvasElement.h new file mode 100644 index 00000000000..d68d09fda36 --- /dev/null +++ b/mozilla/content/canvas/public/nsICanvasElement.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsICanvasElement_h___ +#define nsICanvasElement_h___ + +#include "nsISupports.h" +#include "imgIContainer.h" + +// {8fd94ec9-d4e0-409b-af8f-828c7d7648f5} +#define NS_ICANVASELEMENT_IID \ + { 0x8fd94ec9, 0xd4e0, 0x409b, { 0xaf, 0x8f, 0x82, 0x8c, 0x7d, 0x76, 0x48, 0xf5 } } + +class nsICanvasElement : public nsISupports { +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICANVASELEMENT_IID) + + /** + * Ask the Canvas Element to return the current image container that + * the frame should render. + */ + NS_IMETHOD GetCanvasImageContainer (imgIContainer **aImageContainer); + + /** + * Ask the canvas Element to return the primary frame, if any + */ + NS_IMETHOD GetPrimaryCanvasFrame (nsIFrame **aFrame); +}; + +#endif /* nsICanvasElement_h___ */ diff --git a/mozilla/content/canvas/public/nsICanvasRenderingContextInternal.h b/mozilla/content/canvas/public/nsICanvasRenderingContextInternal.h new file mode 100644 index 00000000000..5cc3b9cfaea --- /dev/null +++ b/mozilla/content/canvas/public/nsICanvasRenderingContextInternal.h @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsICanvasRenderingContextInternal_h___ +#define nsICanvasRenderingContextInternal_h___ + +#include "nsISupports.h" +#include "nsPresContext.h" +#include "gfxIImageFrame.h" + +// {0be74436-51a3-4be3-8357-ede741750080} +#define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \ + { 0x0be74436, 0x51a3, 0x4be3, { 0x83, 0x57, 0xed, 0xe7, 0x41, 0x75, 0x00, 0x80 } } + +class nsICanvasRenderingContextInternal : public nsISupports { +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID) + + NS_IMETHOD Init(nsIDOMHTMLCanvasElement* aParentCanvas) = 0; + + NS_IMETHOD SetTargetImageFrame(gfxIImageFrame* aImageFrame) = 0; +}; + +#endif /* nsICanvasRenderingContextInternal_h___ */ diff --git a/mozilla/content/canvas/src/Makefile.in b/mozilla/content/canvas/src/Makefile.in new file mode 100644 index 00000000000..ee2a83aacc4 --- /dev/null +++ b/mozilla/content/canvas/src/Makefile.in @@ -0,0 +1,90 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is canvas code. +# +# The Initial Developer of the Original Code is +# Vladimir Vukicevic +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = content +LIBRARY_NAME = gkconcvs_s +LIBXUL_LIBRARY = 1 + +REQUIRES = \ + xpcom \ + string \ + gfx \ + layout \ + widget \ + dom \ + js \ + locale \ + unicharutil \ + webshell \ + uriloader \ + htmlparser \ + necko \ + view \ + pref \ + docshell \ + xpconnect \ + xuldoc \ + caps \ + editor \ + imglib2 \ + mimetype \ + exthandler \ + uconv \ + intl \ + plugin \ + $(NULL) + +CPPSRCS = \ + $(NULL) + +ifdef MOZ_ENABLE_CAIRO +CPPSRCS += nsCanvasRenderingContext2D.cpp +endif + +# we don't want the shared lib, but we want to force the creation of a static lib. +FORCE_STATIC_LIB = 1 + +include $(topsrcdir)/config/rules.mk + +DEFINES += -D_IMPL_NS_LAYOUT diff --git a/mozilla/content/canvas/src/nsCanvasRenderingContext2D.cpp b/mozilla/content/canvas/src/nsCanvasRenderingContext2D.cpp new file mode 100644 index 00000000000..589ecd44cf7 --- /dev/null +++ b/mozilla/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -0,0 +1,1363 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * 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 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIServiceManager.h" + +#include "nsContentUtils.h" + +#include "nsIDOMCanvasRenderingContext2D.h" +#include "nsICanvasRenderingContextInternal.h" +#include "nsPresContext.h" +#include "nsIPresShell.h" +#include "nsIVariant.h" + +#include "imgIRequest.h" +#include "imgIContainer.h" +#include "gfxIImageFrame.h" +#include "nsIDOMHTMLCanvasElement.h" +#include "nsICanvasElement.h" +#include "nsIDOMHTMLImageElement.h" +#include "nsIImageLoadingContent.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIImage.h" +#include "nsIFrame.h" +#include "nsDOMError.h" + +#include "nsICSSParser.h" + +#include "nsPrintfCString.h" + +#include "nsReadableUtils.h" + +#include "nsColor.h" +#include "nsIRenderingContext.h" + +#include "cairo.h" + +class nsCanvasRenderingContext2D : + public nsIDOMCanvasRenderingContext2D, + public nsICanvasRenderingContextInternal +{ +public: + nsCanvasRenderingContext2D(); + virtual ~nsCanvasRenderingContext2D(); + + nsresult Redraw(); + nsresult UpdateImageFrame(); + void SetCairoColor(nscolor c); + + // nsICanvasRenderingContextInternal + NS_IMETHOD Init (nsIDOMHTMLCanvasElement* aParentCanvas); + NS_IMETHOD SetTargetImageFrame(gfxIImageFrame* aImageFrame); + + // nsISupports interface + NS_DECL_ISUPPORTS + + // nsIDOMCanvasRenderingContext2D interface + NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D + +protected: + // destroy cairo/image stuff, in preparation for possibly recreating + void Destroy(); + + nsIFrame *GetCanvasLayoutFrame(); + + // Some helpers. Doesn't modify acolor on failure. + enum { + STYLE_STROKE = 0, + STYLE_FILL, + STYLE_MAX + }; + + PRBool StyleVariantToColor(nsIVariant* aStyle, PRInt32 aWhichStyle); + void StyleColorToString(const nscolor& aColor, nsAString& aStr); + + void DirtyAllStyles(); + void ApplyStyle(PRInt32 aWhichStyle); + + // Member vars + PRInt32 mWidth, mHeight; + + nsCOMPtr mDOMCanvasElement; + nsICanvasElement* mCanvasElement; + + // image bits + nsCOMPtr mImageFrame; + + PRBool mDirty; + + // our CSS parser, for colors and whatnot + nsCOMPtr mCSSParser; + + // yay cairo + cairo_t *mCairo; + cairo_surface_t *mSurface; + char *mSurfaceData; + + // style handling + PRInt32 mLastStyle; + PRPackedBool mDirtyStyle[STYLE_MAX]; + nscolor mColorStyles[STYLE_MAX]; + nsCOMPtr mGradientStyles[STYLE_MAX]; + nsCOMPtr mPatternStyles[STYLE_MAX]; + + // stolen from nsJSUtils + static PRBool ConvertJSValToUint32(PRUint32* aProp, JSContext* aContext, + jsval aValue); + static PRBool ConvertJSValToXPCObject(nsISupports** aSupports, REFNSIID aIID, + JSContext* aContext, jsval aValue); + static PRBool ConvertJSValToDouble(double* aProp, JSContext* aContext, + jsval aValue); + +}; + +NS_IMPL_ADDREF(nsCanvasRenderingContext2D) +NS_IMPL_RELEASE(nsCanvasRenderingContext2D) + +NS_INTERFACE_MAP_BEGIN(nsCanvasRenderingContext2D) + NS_INTERFACE_MAP_ENTRY(nsIDOMCanvasRenderingContext2D) + NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMCanvasRenderingContext2D) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CanvasRenderingContext2D) +NS_INTERFACE_MAP_END + +nsresult +NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult) +{ + nsIDOMCanvasRenderingContext2D* ctx = new nsCanvasRenderingContext2D(); + if (!ctx) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(*aResult = ctx); + return NS_OK; +} + +nsCanvasRenderingContext2D::nsCanvasRenderingContext2D() + : mDirty(PR_TRUE), mCairo(nsnull), mSurface(nsnull), mSurfaceData(nsnull) +{ + mColorStyles[STYLE_STROKE] = NS_RGB(0,0,0); + mColorStyles[STYLE_FILL] = NS_RGB(255,255,255); + + mLastStyle = (PRInt32) -1; + + DirtyAllStyles(); +} + +nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D() +{ + Destroy(); + + mImageFrame = nsnull; +} + +nsIFrame* +nsCanvasRenderingContext2D::GetCanvasLayoutFrame() +{ + if (!mDOMCanvasElement) + return nsnull; + + nsIFrame *fr = nsnull; + mCanvasElement->GetPrimaryCanvasFrame(&fr); + return fr; +} + +void +nsCanvasRenderingContext2D::Destroy() +{ + if (mCairo) { + cairo_destroy(mCairo); + mCairo = nsnull; + } + + if (mSurface) { + cairo_surface_destroy(mSurface); + mSurface = nsnull; + } + + if (mSurfaceData) { + nsMemory::Free(mSurfaceData); + mSurfaceData = nsnull; + } +} + +PRBool +nsCanvasRenderingContext2D::StyleVariantToColor(nsIVariant* aStyle, PRInt32 aWhichStyle) +{ + nsresult rv; + nscolor color; + + PRUint16 paramType; + rv = aStyle->GetDataType(¶mType); + NS_ENSURE_SUCCESS(rv, rv); + + if (paramType == nsIDataType::VTYPE_DOMSTRING) { + nsString str; + rv = aStyle->GetAsDOMString(str); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mCSSParser->ParseColorString(str, nsnull, 0, PR_TRUE, &color); + if (NS_FAILED(rv)) + return PR_FALSE; + + mColorStyles[aWhichStyle] = color; + mPatternStyles[aWhichStyle] = nsnull; + mGradientStyles[aWhichStyle] = nsnull; + + mDirtyStyle[aWhichStyle] = PR_TRUE; + + return PR_TRUE; + } else if (paramType == nsIDataType::VTYPE_WSTRING_SIZE_IS) { + PRUint32 sz; + PRUnichar* str = nsnull; + + rv = aStyle->GetAsWStringWithSize(&sz, &str); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mCSSParser->ParseColorString(nsString(str, sz), nsnull, 0, PR_TRUE, &color); + nsMemory::Free(str); + if (NS_FAILED(rv)) + return PR_FALSE; + + mColorStyles[aWhichStyle] = color; + mPatternStyles[aWhichStyle] = nsnull; + mGradientStyles[aWhichStyle] = nsnull; + + mDirtyStyle[aWhichStyle] = PR_TRUE; + return PR_TRUE; + } else if (paramType == nsIDataType::VTYPE_INTERFACE || + paramType == nsIDataType::VTYPE_INTERFACE_IS) + { + nsID *iid; + nsCOMPtr iface; + rv = aStyle->GetAsInterface(&iid, getter_AddRefs(iface)); + + nsCOMPtr grad (do_QueryInterface(iface)); + if (grad) { + mPatternStyles[aWhichStyle] = nsnull; + mGradientStyles[aWhichStyle] = grad; + mDirtyStyle[aWhichStyle] = PR_TRUE; + } + + nsCOMPtr pattern (do_QueryInterface(iface)); + if (pattern) { + mPatternStyles[aWhichStyle] = pattern; + mGradientStyles[aWhichStyle] = nsnull; + mDirtyStyle[aWhichStyle] = PR_TRUE; + } + } + + return PR_FALSE; +} + +void +nsCanvasRenderingContext2D::StyleColorToString(const nscolor& aColor, nsAString& aStr) +{ + if (NS_GET_A(aColor) == 255) { + CopyUTF8toUTF16(nsPrintfCString(100, "#%02x%02x%02x", + NS_GET_R(aColor), + NS_GET_G(aColor), + NS_GET_B(aColor)), + aStr); + } else { + CopyUTF8toUTF16(nsPrintfCString(100, "rgb(%d,%d,%d,%0.2f)", + NS_GET_R(aColor), + NS_GET_G(aColor), + NS_GET_B(aColor), + NS_GET_A(aColor) / 255.0f), + aStr); + } +} + +void +nsCanvasRenderingContext2D::DirtyAllStyles() +{ + for (int i = 0; i < STYLE_MAX; i++) { + mDirtyStyle[i] = PR_TRUE; + } +} + +void +nsCanvasRenderingContext2D::ApplyStyle(PRInt32 aWhichStyle) +{ + if (mLastStyle == aWhichStyle && + !mDirtyStyle[aWhichStyle]) + { + // nothing to do, this is already the set style + return; + } + + mDirtyStyle[aWhichStyle] = PR_FALSE; + mLastStyle = aWhichStyle; + + if (mPatternStyles[aWhichStyle]) { + } + + if (mGradientStyles[aWhichStyle]) { + } + + SetCairoColor(mColorStyles[aWhichStyle]); +} + +nsresult +nsCanvasRenderingContext2D::Redraw() +{ + mDirty = PR_TRUE; + nsresult rv = UpdateImageFrame(); + if (NS_FAILED(rv)) { + NS_WARNING("Canvas UpdateImageFrame filed"); + return NS_ERROR_FAILURE; + } + + nsIFrame *frame = GetCanvasLayoutFrame(); + if (frame) { + nsRect r = frame->GetRect(); + r.x = r.y = 0; + frame->Invalidate(r, PR_TRUE); + } + + return NS_OK; +} + +void +nsCanvasRenderingContext2D::SetCairoColor(nscolor c) +{ + double r = double(NS_GET_R(c) / 255.0); + double g = double(NS_GET_G(c) / 255.0); + double b = double(NS_GET_B(c) / 255.0); + double a = double(NS_GET_A(c) / 255.0); + + cairo_set_rgb_color (mCairo, r, g, b); + cairo_set_alpha (mCairo, a); +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetTargetImageFrame(gfxIImageFrame* aImageFrame) +{ + // clean up old cairo bits + Destroy(); + + aImageFrame->GetWidth(&mWidth); + aImageFrame->GetHeight(&mHeight); + + mCairo = cairo_create(); + mSurfaceData = (char *) nsMemory::Alloc(mWidth * mHeight * 4); + mSurface = cairo_surface_create_for_image (mSurfaceData, + CAIRO_FORMAT_ARGB32, + mWidth, + mHeight, + mWidth * 4); + cairo_set_target_surface (mCairo, mSurface); + + mImageFrame = aImageFrame; + + return NS_OK; +} + +nsresult +nsCanvasRenderingContext2D::UpdateImageFrame() +{ + nsresult rv; + + if (!mImageFrame) + return NS_OK; + + if (!mSurfaceData) + return NS_ERROR_FAILURE; + + if (mDirty) { + PRUint8 *alphaBits, *rgbBits; + PRUint32 alphaLen, rgbLen; + PRUint32 alphaStride, rgbStride; + + rv = mImageFrame->LockImageData(); + if (NS_FAILED(rv)) { + return rv; + } + + rv = mImageFrame->LockAlphaData(); + if (NS_FAILED(rv)) { + mImageFrame->UnlockImageData(); + return rv; + } + + rv = mImageFrame->GetAlphaBytesPerRow(&alphaStride); + rv |= mImageFrame->GetAlphaData(&alphaBits, &alphaLen); + rv |= mImageFrame->GetImageBytesPerRow(&rgbStride); + rv |= mImageFrame->GetImageData(&rgbBits, &rgbLen); + if (NS_FAILED(rv)) { + mImageFrame->UnlockImageData(); + mImageFrame->UnlockAlphaData(); + return rv; + } + + for (PRUint32 j = 0; j < (PRUint32) mHeight; j++) { + PRUint8 *inrow = (PRUint8*)(mSurfaceData + (mWidth * 4 * j)); +#ifdef XP_WIN + // On windows, RGB_A8 is really "BGR with Y axis flipped" + PRUint8 *outrowrgb = rgbBits + (rgbStride * (mHeight - j - 1)); + PRUint8 *outrowalpha = alphaBits + (alphaStride * (mHeight - j - 1)); +#else + PRUint8 *outrowrgb = rgbBits + (rgbStride * j); + PRUint8 *outrowalpha = alphaBits + (alphaStride * j); +#endif + for (PRUint32 i = 0; i < (PRUint32) mWidth; i++) { + PRUint8 b = *inrow++; + PRUint8 g = *inrow++; + PRUint8 r = *inrow++; + PRUint8 a = *inrow++; + + *outrowalpha++ = a; + + *outrowrgb++ = r; + *outrowrgb++ = g; + *outrowrgb++ = b; +#ifdef XP_MACOSX + // On the mac, RGB_A8 is really RGBX_A8 + *outrowrgb++ = 0; +#endif + } + } + + rv = mImageFrame->UnlockAlphaData(); + rv |= mImageFrame->UnlockImageData(); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr img(do_GetInterface(mImageFrame)); + nsRect r(0, 0, mWidth, mHeight); + img->ImageUpdated(nsnull, nsImageUpdateFlags_kBitsChanged, &r); + + mDirty = PR_FALSE; + } + + return NS_OK; +} + +// +// nsCanvasRenderingContext2D impl +// + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Init(nsIDOMHTMLCanvasElement* aCanvasElement) +{ + mDOMCanvasElement = aCanvasElement; + CallQueryInterface(mDOMCanvasElement, &mCanvasElement); + + // set up our css parser + if (!mCSSParser) { + mCSSParser = do_CreateInstance("@mozilla.org/content/css-parser;1"); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetCanvas(nsIDOMHTMLCanvasElement **canvas) +{ + NS_IF_ADDREF(*canvas = mDOMCanvasElement); + return NS_OK; +} + +// +// state +// + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Save() +{ + cairo_save (mCairo); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Restore() +{ + cairo_restore (mCairo); + return NS_OK; +} + +// +// transformations +// + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Scale(float x, float y) +{ + cairo_scale (mCairo, x, y); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Rotate(float angle) +{ + cairo_rotate (mCairo, angle); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Translate(float x, float y) +{ + cairo_translate (mCairo, x, y); + return NS_OK; +} + +// +// colors +// + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetGlobalAlpha(float globalAlpha) +{ + cairo_set_alpha (mCairo, globalAlpha); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetGlobalAlpha(float *globalAlpha) +{ + double d = cairo_current_alpha(mCairo); + *globalAlpha = (float) d; + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetStrokeStyle(nsIVariant* aStyle) +{ + if (StyleVariantToColor(aStyle, STYLE_STROKE)) + return NS_OK; + + return NS_ERROR_INVALID_ARG; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetStrokeStyle(nsIVariant** aStyle) +{ + nsresult rv; + + nsString styleStr; + StyleColorToString(mColorStyles[STYLE_STROKE], styleStr); + + nsCOMPtr var = do_CreateInstance("@mozilla.org/variant;1"); + if (!var) + return NS_ERROR_FAILURE; + + rv = var->SetWritable(PR_TRUE); + NS_ENSURE_SUCCESS(rv, rv); + + rv = var->SetAsDOMString(styleStr); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ADDREF(*aStyle = var); + + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetFillStyle(nsIVariant* aStyle) +{ + if (StyleVariantToColor(aStyle, STYLE_FILL)) + return NS_OK; + + return NS_ERROR_INVALID_ARG; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetFillStyle(nsIVariant** aStyle) +{ + nsresult rv; + + nsString styleStr; + StyleColorToString(mColorStyles[STYLE_FILL], styleStr); + + nsCOMPtr var = do_CreateInstance("@mozilla.org/variant;1"); + if (!var) + return NS_ERROR_FAILURE; + + rv = var->SetWritable(PR_TRUE); + NS_ENSURE_SUCCESS(rv, rv); + + rv = var->SetAsDOMString(styleStr); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ADDREF(*aStyle = var); + + return NS_OK; +} + +// +// gradients and patterns +// +NS_IMETHODIMP +nsCanvasRenderingContext2D::CreateLinearGradient(float x0, float y0, float x1, float y1, + nsIDOMCanvasGradient **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::CreateRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, + nsIDOMCanvasGradient **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLImageElement *image, + const nsAString& repetition, + nsIDOMCanvasPattern **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +// +// shadows +// +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetShadowOffsetX(float x) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetShadowOffsetX(float *x) +{ + *x = 0.0f; + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetShadowOffsetY(float y) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetShadowOffsetY(float *y) +{ + *y = 0.0f; + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetShadowBlur(float blur) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetShadowBlur(float *blur) +{ + *blur = 0.0f; + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetShadowColor(const nsAString& color) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetShadowColor(nsAString& color) +{ + return NS_OK; +} + +// +// rects +// + +NS_IMETHODIMP +nsCanvasRenderingContext2D::ClearRect(float x, float y, float w, float h) +{ + nsIFrame *fr = GetCanvasLayoutFrame(); + + if (fr) { + if (fr->GetStyleBackground()->IsTransparent()) + cairo_set_rgb_color(mCairo, 0.0f, 0.0f, 0.0f); + else + SetCairoColor(fr->GetStyleBackground()->mBackgroundColor); + } else { + cairo_set_rgb_color(mCairo, 1.0f, 1.0f, 1.0f); + } + + DirtyAllStyles(); + + cairo_set_alpha (mCairo, 0.0); + cairo_new_path (mCairo); + cairo_rectangle (mCairo, x, y, w, h); + cairo_fill (mCairo); + + return Redraw(); +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::FillRect(float x, float y, float w, float h) +{ + ApplyStyle(STYLE_FILL); + + cairo_new_path (mCairo); + cairo_rectangle (mCairo, x, y, w, h); + cairo_fill (mCairo); + + return Redraw(); +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::StrokeRect(float x, float y, float w, float h) +{ + ApplyStyle(STYLE_STROKE); + + cairo_new_path (mCairo); + cairo_rectangle (mCairo, x, y, w, h); + cairo_stroke (mCairo); + + return Redraw(); +} + +// +// path bits +// + +NS_IMETHODIMP +nsCanvasRenderingContext2D::BeginPath() +{ + cairo_new_path(mCairo); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::ClosePath() +{ + cairo_close_path(mCairo); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Fill() +{ + ApplyStyle(STYLE_FILL); + cairo_fill(mCairo); + return Redraw(); +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Stroke() +{ + ApplyStyle(STYLE_STROKE); + cairo_stroke(mCairo); + return Redraw(); +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Clip() +{ + cairo_clip(mCairo); + return Redraw(); +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::MoveTo(float x, float y) +{ + cairo_move_to(mCairo, x, y); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::LineTo(float x, float y) +{ + cairo_line_to(mCairo, x, y); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::QuadraticCurveTo(float cpx, float cpy, float x, float y) +{ + cairo_curve_to(mCairo, cpx, cpy, cpx, cpy, x, y); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::BezierCurveTo(float cp1x, float cp1y, + float cp2x, float cp2y, + float x, float y) +{ + cairo_curve_to(mCairo, cp1x, cp1y, cp2x, cp2y, x, y); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::ArcTo(float x1, float y1, float x2, float y2, float radius) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Arc(float x, float y, float r, float startAngle, float endAngle, int clockwise) +{ + if (clockwise) + cairo_arc (mCairo, x, y, r, startAngle, endAngle); + else + cairo_arc_negative (mCairo, x, y, r, startAngle, endAngle); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::Rect(float x, float y, float w, float h) +{ + cairo_rectangle (mCairo, x, y, w, h); + return NS_OK; +} + + +// +// line caps/joins +// +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetLineWidth(float width) +{ + cairo_set_line_width(mCairo, width); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetLineWidth(float *width) +{ + double d = cairo_current_line_width(mCairo); + *width = (float) d; + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetLineCap(const nsAString& capstyle) +{ + cairo_line_cap_t cap; + + if (capstyle.EqualsLiteral("round")) + cap = CAIRO_LINE_CAP_ROUND; + else if (capstyle.EqualsLiteral("square")) + cap = CAIRO_LINE_CAP_SQUARE; + else + return NS_ERROR_NOT_IMPLEMENTED; + + cairo_set_line_cap (mCairo, cap); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetLineCap(nsAString& capstyle) +{ + cairo_line_cap_t cap = cairo_current_line_cap(mCairo); + + if (cap == CAIRO_LINE_CAP_ROUND) + capstyle.AssignLiteral("round"); + else if (cap == CAIRO_LINE_CAP_SQUARE) + capstyle.AssignLiteral("square"); + else + return NS_ERROR_FAILURE; + + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetLineJoin(const nsAString& joinstyle) +{ + cairo_line_join_t j; + + if (joinstyle.EqualsLiteral("round")) + j = CAIRO_LINE_JOIN_ROUND; + else if (joinstyle.EqualsLiteral("bevel")) + j = CAIRO_LINE_JOIN_BEVEL; + else if (joinstyle.EqualsLiteral("miter")) + j = CAIRO_LINE_JOIN_MITER; + else + return NS_ERROR_NOT_IMPLEMENTED; + + cairo_set_line_join (mCairo, j); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetLineJoin(nsAString& joinstyle) +{ + cairo_line_join_t j = cairo_current_line_join(mCairo); + + if (j == CAIRO_LINE_JOIN_ROUND) + joinstyle.AssignLiteral("round"); + else if (j == CAIRO_LINE_JOIN_BEVEL) + joinstyle.AssignLiteral("bevel"); + else if (j == CAIRO_LINE_JOIN_MITER) + joinstyle.AssignLiteral("miter"); + else + return NS_ERROR_FAILURE; + + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetMiterLimit(float miter) +{ + cairo_set_miter_limit(mCairo, miter); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetMiterLimit(float *miter) +{ + double d = cairo_current_miter_limit(mCairo); + *miter = (float) d; + return NS_OK; +} + +// +// image +// + +// drawImage(in HTMLImageElement image, in float dx, in float dy); +// -- render image from 0,0 at dx,dy top-left coords +// drawImage(in HTMLImageElement image, in float dx, in float dy, in float sw, in float sh); +// -- render image from 0,0 at dx,dy top-left coords clipping it to sw,sh +// drawImage(in HTMLImageElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh); +// -- render the region defined by (sx,sy,sw,wh) in image-local space into the region (dx,dy,dw,dh) on the canvas + +NS_IMETHODIMP +nsCanvasRenderingContext2D::DrawImage() +{ + nsresult rv; + + nsCOMPtr ncc; + rv = nsContentUtils::XPConnect()-> + GetCurrentNativeCallContext(getter_AddRefs(ncc)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!ncc) + return NS_ERROR_FAILURE; + + JSContext *ctx = nsnull; + + rv = ncc->GetJSContext(&ctx); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 argc; + jsval *argv = nsnull; + + ncc->GetArgc(&argc); + ncc->GetArgvPtr(&argv); + + // we always need at least an image and a dx,dy + if (argc < 3) + return NS_ERROR_INVALID_ARG; + + double sx,sy,sw,sh; + double dx,dy,dw,dh; + + nsCOMPtr imgElt; + if (!ConvertJSValToXPCObject(getter_AddRefs(imgElt), + NS_GET_IID(nsIDOMHTMLImageElement), + ctx, argv[0])) + return NS_ERROR_DOM_TYPE_MISMATCH_ERR; + + // before we do anything more, make sure that this image is something + // that we can actually render + nsCOMPtr imageLoader = do_QueryInterface(imgElt); + if (!imageLoader) + return NS_ERROR_NOT_AVAILABLE; + nsCOMPtr imgRequest; + rv = imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, + getter_AddRefs(imgRequest)); + NS_ENSURE_SUCCESS(rv, rv); + if (!imgRequest) + return NS_ERROR_NOT_AVAILABLE; + + nsCOMPtr imgContainer; + rv = imgRequest->GetImage(getter_AddRefs(imgContainer)); + NS_ENSURE_SUCCESS(rv, rv); + if (!imgContainer) + return NS_ERROR_NOT_AVAILABLE; + + nsCOMPtr frame; + rv = imgContainer->GetCurrentFrame(getter_AddRefs(frame)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr img(do_GetInterface(frame)); + + PRInt32 imgWidth, imgHeight; + rv = frame->GetWidth(&imgWidth); + rv |= frame->GetHeight(&imgHeight); + if (NS_FAILED(rv)) + return NS_ERROR_FAILURE; + + // if we're at this point, we have an image container + // and we can actually get at the image data + +#define GET_ARG(dest,whicharg) \ + if (!ConvertJSValToDouble(dest, ctx, whicharg)) return NS_ERROR_INVALID_ARG + + if (argc == 3) { + GET_ARG(&dx, argv[1]); + GET_ARG(&dy, argv[2]); + sx = sy = 0.0; + dw = sw = (double) imgWidth; + dh = sh = (double) imgHeight; + } else if (argc == 5) { + GET_ARG(&dx, argv[1]); + GET_ARG(&dy, argv[2]); + GET_ARG(&sw, argv[3]); + GET_ARG(&sh, argv[4]); + sx = sy = 0.0; + dw = sw; + dh = sh; + } else if (argc == 9) { + GET_ARG(&sx, argv[1]); + GET_ARG(&sy, argv[2]); + GET_ARG(&sw, argv[3]); + GET_ARG(&sh, argv[4]); + GET_ARG(&dx, argv[5]); + GET_ARG(&dy, argv[6]); + GET_ARG(&dw, argv[7]); + GET_ARG(&dh, argv[8]); + } else { + return NS_ERROR_INVALID_ARG; + } +#undef GET_ARG + + // check args + if (sx < 0.0 || sy < 0.0 || + sw < 0.0 || sw > (double) imgWidth || + sh < 0.0 || sh > (double) imgHeight || + dw < 0.0 || dh < 0.0) + { + return NS_ERROR_DOM_INDEX_SIZE_ERR; + } + + + // + // We now need to create a cairo_surface with the same data as + // this image element. + // + + PRUint8 *cairoImgData = (PRUint8 *)nsMemory::Alloc(imgHeight * imgWidth * 4); + PRUint8 *outData = cairoImgData; + + gfx_format format; + rv = frame->GetFormat(&format); + NS_ENSURE_SUCCESS(rv, rv); + + rv = frame->LockImageData(); + if (img->GetHasAlphaMask()) + rv |= frame->LockAlphaData(); + if (NS_FAILED(rv)) + return NS_ERROR_FAILURE; + + PRUint8 *inPixBits, *inAlphaBits = nsnull; + PRUint32 inPixStride, inAlphaStride = 0; + inPixBits = img->GetBits(); + inPixStride = img->GetLineStride(); + if (img->GetHasAlphaMask()) { + inAlphaBits = img->GetAlphaBits(); + inAlphaStride = img->GetAlphaLineStride(); + } + + PRBool topToBottom = img->GetIsRowOrderTopToBottom(); + PRBool useBGR; + + if (format == gfxIFormats::RGB || format == gfxIFormats::BGR) { + useBGR = (format & 1); + + for (PRUint32 j = 0; j < (PRUint32) imgHeight; j++) { + PRUint8 *inrowrgb; + + if (topToBottom) { + inrowrgb = inPixBits + (inPixStride * j); + } else { + inrowrgb = inPixBits + (inPixStride * (imgHeight - j - 1)); + } + + for (PRUint32 i = 0; i < (PRUint32) imgWidth; i++) { + // rgb + if (useBGR) { + *outData++ = *inrowrgb++; + *outData++ = *inrowrgb++; + *outData++ = *inrowrgb++; + } else { + PRUint8 r = *inrowrgb++; + PRUint8 g = *inrowrgb++; + PRUint8 b = *inrowrgb++; + *outData++ = b; + *outData++ = g; + *outData++ = r; + } +#ifdef XP_MACOSX + inrowrgb++; +#endif + + // alpha + *outData++ = 255; + } + } + rv = NS_OK; + } else if (format == gfxIFormats::RGB_A1 || format == gfxIFormats::BGR_A1) { + useBGR = (format & 1); + for (PRUint32 j = 0; j < (PRUint32) imgHeight; j++) { + PRUint8 *inrowrgb; + PRUint8 *inrowalpha; + + if (topToBottom) { + inrowrgb = inPixBits + (inPixStride * j); + inrowalpha = inAlphaBits + (inAlphaStride * j); + } else { + inrowrgb = inPixBits + (inPixStride * (imgHeight - j - 1)); + inrowalpha = inAlphaBits + (inAlphaStride * (imgHeight - j - 1)); + } + + for (PRUint32 i = 0; i < (PRUint32) imgWidth; i++) { + // rgb + if (useBGR) { + *outData++ = *inrowrgb++; + *outData++ = *inrowrgb++; + *outData++ = *inrowrgb++; + } else { + PRUint8 r = *inrowrgb++; + PRUint8 g = *inrowrgb++; + PRUint8 b = *inrowrgb++; + *outData++ = b; + *outData++ = g; + *outData++ = r; + } +#ifdef XP_MACOSX + inrowrgb++; +#endif + + // alpha + PRInt32 bit = i % 8; + PRInt32 byte = i / 8; + + PRUint8 a = (inrowalpha[byte] >> bit) & 1; + if (a) a = 255; + + *outData++ = a; + } + } + rv = NS_OK; + } else if (format == gfxIFormats::RGB_A8 || format == gfxIFormats::RGB_A8) { + useBGR = (format & 1); + for (PRUint32 j = 0; j < (PRUint32) imgHeight; j++) { + PRUint8 *inrowrgb; + PRUint8 *inrowalpha; + + if (topToBottom) { + inrowrgb = inPixBits + (inPixStride * j); + inrowalpha = inAlphaBits + (inAlphaStride * j); + } else { + inrowrgb = inPixBits + (inPixStride * (imgHeight - j - 1)); + inrowalpha = inAlphaBits + (inAlphaStride * (imgHeight - j - 1)); + } + + for (PRUint32 i = 0; i < (PRUint32) imgWidth; i++) { + // rgb + if (useBGR) { + *outData++ = *inrowrgb++; + *outData++ = *inrowrgb++; + *outData++ = *inrowrgb++; + } else { + PRUint8 r = *inrowrgb++; + PRUint8 g = *inrowrgb++; + PRUint8 b = *inrowrgb++; + *outData++ = b; + *outData++ = g; + *outData++ = r; + } +#ifdef XP_MACOSX + inrowrgb++; +#endif + + // alpha + *outData++ = *inrowalpha++; + } + } + rv = NS_OK; + } else { + rv = NS_ERROR_FAILURE; + } + + if (img->GetHasAlphaMask()) + frame->UnlockAlphaData(); + frame->UnlockImageData(); + + if (NS_FAILED(rv)) { + nsMemory::Free(cairoImgData); + return rv; + } + + cairo_surface_t *imgSurf = + cairo_image_surface_create_for_data((char *)cairoImgData, CAIRO_FORMAT_ARGB32, + imgWidth, imgHeight, imgWidth*4); + + cairo_matrix_t *surfMat = cairo_matrix_create(); + + cairo_matrix_translate(surfMat, -sx, -sy); + cairo_matrix_scale(surfMat, sw/dw, sh/dh); + cairo_surface_set_matrix(imgSurf, surfMat); + cairo_matrix_destroy(surfMat); + + cairo_save(mCairo); + cairo_translate(mCairo, dx, dy); + cairo_show_surface(mCairo, imgSurf, (int) dw, (int) dh); + cairo_restore(mCairo); + + nsMemory::Free(cairoImgData); + cairo_surface_destroy(imgSurf); + + return Redraw(); +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op) +{ + cairo_operator_t cairo_op; + +#define CANVAS_OP_TO_CAIRO_OP(cvsop,cairoop) \ + if (op.EqualsLiteral(cvsop)) \ + cairo_op = CAIRO_OPERATOR_##cairoop; + + CANVAS_OP_TO_CAIRO_OP("clear", CLEAR) + else CANVAS_OP_TO_CAIRO_OP("copy", SRC) + else CANVAS_OP_TO_CAIRO_OP("darker", SATURATE) // XXX + else CANVAS_OP_TO_CAIRO_OP("destination-atop", ATOP_REVERSE) + else CANVAS_OP_TO_CAIRO_OP("destination-in", IN_REVERSE) + else CANVAS_OP_TO_CAIRO_OP("destination-out", OUT_REVERSE) + else CANVAS_OP_TO_CAIRO_OP("destination-over", OVER_REVERSE) + else CANVAS_OP_TO_CAIRO_OP("lighter", SATURATE) + else CANVAS_OP_TO_CAIRO_OP("source-atop", ATOP) + else CANVAS_OP_TO_CAIRO_OP("source-in", IN) + else CANVAS_OP_TO_CAIRO_OP("source-out", OUT) + else CANVAS_OP_TO_CAIRO_OP("source-over", OVER) + else CANVAS_OP_TO_CAIRO_OP("xor", XOR) + else CANVAS_OP_TO_CAIRO_OP("over", OVER) + else return NS_ERROR_NOT_IMPLEMENTED; + +#undef CANVAS_OP_TO_CAIRO_OP + + cairo_set_operator(mCairo, cairo_op); + return NS_OK; +} + +NS_IMETHODIMP +nsCanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op) +{ + cairo_operator_t cairo_op = cairo_current_operator(mCairo); + +#define CANVAS_OP_TO_CAIRO_OP(cvsop,cairoop) \ + if (cairo_op == CAIRO_OPERATOR_##cairoop) \ + op.AssignLiteral(cvsop); + + CANVAS_OP_TO_CAIRO_OP("clear", CLEAR) + else CANVAS_OP_TO_CAIRO_OP("copy", SRC) + else CANVAS_OP_TO_CAIRO_OP("darker", SATURATE) // XXX + else CANVAS_OP_TO_CAIRO_OP("destination-atop", ATOP_REVERSE) + else CANVAS_OP_TO_CAIRO_OP("destination-in", IN_REVERSE) + else CANVAS_OP_TO_CAIRO_OP("destination-out", OUT_REVERSE) + else CANVAS_OP_TO_CAIRO_OP("destination-over", OVER_REVERSE) + else CANVAS_OP_TO_CAIRO_OP("lighter", SATURATE) + else CANVAS_OP_TO_CAIRO_OP("source-atop", ATOP) + else CANVAS_OP_TO_CAIRO_OP("source-in", IN) + else CANVAS_OP_TO_CAIRO_OP("source-out", OUT) + else CANVAS_OP_TO_CAIRO_OP("source-over", OVER) + else CANVAS_OP_TO_CAIRO_OP("xor", XOR) + else CANVAS_OP_TO_CAIRO_OP("over", OVER) + else return NS_ERROR_FAILURE; + +#undef CANVAS_OP_TO_CAIRO_OP + + return NS_OK; +} + + +// +// Utils +// +PRBool +nsCanvasRenderingContext2D::ConvertJSValToUint32(PRUint32* aProp, JSContext* aContext, + jsval aValue) +{ + uint32 temp; + if (::JS_ValueToECMAUint32(aContext, aValue, &temp)) { + *aProp = (PRUint32)temp; + } + else { + ::JS_ReportError(aContext, "Parameter must be an integer"); + return JS_FALSE; + } + + return JS_TRUE; +} + +PRBool +nsCanvasRenderingContext2D::ConvertJSValToDouble(double* aProp, JSContext* aContext, + jsval aValue) +{ + jsdouble temp; + if (::JS_ValueToNumber(aContext, aValue, &temp)) { + *aProp = (jsdouble)temp; + } + else { + ::JS_ReportError(aContext, "Parameter must be a number"); + return JS_FALSE; + } + + return JS_TRUE; +} + +PRBool +nsCanvasRenderingContext2D::ConvertJSValToXPCObject(nsISupports** aSupports, REFNSIID aIID, + JSContext* aContext, jsval aValue) +{ + *aSupports = nsnull; + if (JSVAL_IS_NULL(aValue)) { + return JS_TRUE; + } + + if (JSVAL_IS_OBJECT(aValue)) { + // WrapJS does all the work to recycle an existing wrapper and/or do a QI + nsresult rv = nsContentUtils::XPConnect()-> + WrapJS(aContext, JSVAL_TO_OBJECT(aValue), aIID, (void**)aSupports); + + return NS_SUCCEEDED(rv); + } + + return JS_FALSE; +} diff --git a/mozilla/content/html/content/src/Makefile.in b/mozilla/content/html/content/src/Makefile.in index 8cfbc561a6d..4ce12e36282 100644 --- a/mozilla/content/html/content/src/Makefile.in +++ b/mozilla/content/html/content/src/Makefile.in @@ -92,6 +92,7 @@ CPPSRCS = \ nsHTMLBRElement.cpp \ nsHTMLBodyElement.cpp \ nsHTMLButtonElement.cpp \ + nsHTMLCanvasElement.cpp \ nsHTMLDelElement.cpp \ nsHTMLDivElement.cpp \ nsHTMLFieldSetElement.cpp \ diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.h b/mozilla/content/html/content/src/nsGenericHTMLElement.h index f124d4f538b..3805af4c617 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.h +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.h @@ -1104,6 +1104,7 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT(Area) NS_DECLARE_NS_NEW_HTML_ELEMENT(BR) NS_DECLARE_NS_NEW_HTML_ELEMENT(Body) NS_DECLARE_NS_NEW_HTML_ELEMENT(Button) +NS_DECLARE_NS_NEW_HTML_ELEMENT(Canvas) NS_DECLARE_NS_NEW_HTML_ELEMENT(Mod) NS_DECLARE_NS_NEW_HTML_ELEMENT(Div) NS_DECLARE_NS_NEW_HTML_ELEMENT(FieldSet) diff --git a/mozilla/content/html/content/src/nsHTMLAtomList.h b/mozilla/content/html/content/src/nsHTMLAtomList.h index a935cfa0597..8612c5c4698 100644 --- a/mozilla/content/html/content/src/nsHTMLAtomList.h +++ b/mozilla/content/html/content/src/nsHTMLAtomList.h @@ -91,6 +91,7 @@ HTML_ATOM(bottompadding, "bottompadding") HTML_ATOM(br, "br") HTML_ATOM(b, "b") HTML_ATOM(button, "button") +HTML_ATOM(canvas, "canvas") HTML_ATOM(caption, "caption") HTML_ATOM(cellpadding, "cellpadding") HTML_ATOM(cellspacing, "cellspacing") diff --git a/mozilla/content/html/content/src/nsHTMLCanvasElement.cpp b/mozilla/content/html/content/src/nsHTMLCanvasElement.cpp new file mode 100644 index 00000000000..ed34a6f63f2 --- /dev/null +++ b/mozilla/content/html/content/src/nsHTMLCanvasElement.cpp @@ -0,0 +1,401 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIDOMHTMLCanvasElement.h" +#include "nsGenericHTMLElement.h" +#include "nsPresContext.h" +#include "nsIPresShell.h" +#include "nsHTMLAtoms.h" +#include "nsSize.h" +#include "nsIFrame.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsNodeInfoManager.h" + +#include "nsICanvasElement.h" + +#include "gfxIImageFrame.h" +#include "imgIContainer.h" + +#include "nsICanvasRenderingContextInternal.h" + +class nsHTMLCanvasElement : public nsGenericHTMLElement, + public nsIDOMHTMLCanvasElement, + public nsICanvasElement +{ +public: + nsHTMLCanvasElement(nsINodeInfo *aNodeInfo); + virtual ~nsHTMLCanvasElement(); + + // nsISupports + NS_DECL_ISUPPORTS_INHERITED + + // nsIDOMNode + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLElement::) + + // nsIDOMElement + NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::) + + // nsIDOMHTMLElement + NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) + + // nsIDOMHTMLCanvasElement + NS_DECL_NSIDOMHTMLCANVASELEMENT + + // nsICanvasElement + NS_IMETHOD GetCanvasImageContainer (imgIContainer **aImageContainer); + NS_IMETHOD GetPrimaryCanvasFrame (nsIFrame **aFrame); + + NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; + nsMapRuleToAttributesFunc GetAttributeMappingFunction() const; + PRBool ParseAttribute(nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult); + + // SetAttr override. C++ is stupid, so have to override both + // overloaded methods. + NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + const nsAString& aValue, PRBool aNotify) + { + return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify); + } + NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + PRBool aNotify); + + nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, + PRInt32 aModType) const; +protected: + nsSize GetWidthHeight(); + nsresult UpdateImageContainer(); + nsresult UpdateContext(); + + nsString mCurrentContextId; + nsCOMPtr mCurrentContext; + + nsCOMPtr mImageContainer; + nsCOMPtr mImageFrame; +}; + +nsGenericHTMLElement* +NS_NewHTMLCanvasElement(nsINodeInfo *aNodeInfo, PRBool aFromParser) +{ + return new nsHTMLCanvasElement(aNodeInfo); +} + +nsHTMLCanvasElement::nsHTMLCanvasElement(nsINodeInfo *aNodeInfo) + : nsGenericHTMLElement(aNodeInfo) +{ +} + +nsHTMLCanvasElement::~nsHTMLCanvasElement() +{ +} + +NS_IMPL_ADDREF_INHERITED(nsHTMLCanvasElement, nsGenericElement) +NS_IMPL_RELEASE_INHERITED(nsHTMLCanvasElement, nsGenericElement) + +NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLCanvasElement, nsGenericElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLCanvasElement) + NS_INTERFACE_MAP_ENTRY(nsICanvasElement) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLCanvasElement) +NS_HTML_CONTENT_INTERFACE_MAP_END + +NS_IMPL_DOM_CLONENODE(nsHTMLCanvasElement) + +nsSize +nsHTMLCanvasElement::GetWidthHeight() +{ + nsSize size(0,0); + const nsAttrValue* value; + PRInt32 k, rv; + + if ((value = GetParsedAttr(nsHTMLAtoms::width))) { + if (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) { + size.height = value->GetIntegerValue(); + } else if (value->Type() == nsAttrValue::eString) { + k = value->GetStringValue().ToInteger(&rv); + if (NS_SUCCEEDED(rv)) + size.height = k; + } + } + + 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); +} + +nsresult +nsHTMLCanvasElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + PRBool aNotify) +{ + nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, + aNotify); + if (NS_SUCCEEDED(rv) && mCurrentContext && + (aName == nsHTMLAtoms::width || aName == nsHTMLAtoms::height)) + { + rv = UpdateImageContainer(); + NS_ENSURE_SUCCESS(rv, rv); + + rv = UpdateContext(); + NS_ENSURE_SUCCESS(rv, rv); + } + + return rv; +} + +nsChangeHint +nsHTMLCanvasElement::GetAttributeChangeHint(const nsIAtom* aAttribute, + PRInt32 aModType) const +{ + nsChangeHint retval = + nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType); + if (aAttribute == nsHTMLAtoms::width || + aAttribute == nsHTMLAtoms::height) + { + NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE); + } + return retval; +} + +static void +MapAttributesIntoRule(const nsMappedAttributes* aAttributes, + nsRuleData* aData) +{ + nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData); + nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData); + nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData); + nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData); +} + +nsMapRuleToAttributesFunc +nsHTMLCanvasElement::GetAttributeMappingFunction() const +{ + return &MapAttributesIntoRule; +} + +static const nsGenericElement::MappedAttributeEntry +sImageMarginAttributeMap[] = { + { &nsHTMLAtoms::hspace }, + { &nsHTMLAtoms::vspace }, + { nsnull } +}; + +NS_IMETHODIMP_(PRBool) +nsHTMLCanvasElement::IsAttributeMapped(const nsIAtom* aAttribute) const +{ + static const MappedAttributeEntry* const map[] = { + sCommonAttributeMap, + sImageMarginAttributeMap, + sImageBorderAttributeMap, + sImageAlignAttributeMap + }; + + return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map)); +} + +PRBool +nsHTMLCanvasElement::ParseAttribute(nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) +{ + if ((aAttribute == nsHTMLAtoms::width) || + (aAttribute == nsHTMLAtoms::height)) + { + return aResult.ParseIntWithBounds(aValue, 0); + } + + if (ParseImageAttribute(aAttribute, aValue, aResult)) + return PR_TRUE; + + return nsGenericHTMLElement::ParseAttribute(aAttribute, aValue, aResult); +} + +NS_IMETHODIMP +nsHTMLCanvasElement::GetContext(const nsAString& aContextId, + nsISupports **aContext) +{ + if (mCurrentContextId.IsEmpty()) { + nsCString ctxId; + ctxId.Assign(NS_LossyConvertUTF16toASCII(aContextId)); + + // check that ctxId is clamped to A-Za-z0-9_- + for (PRUint32 i = 0; i < ctxId.Length(); i++) { + if ((ctxId[i] < 'A' || ctxId[i] > 'Z') && + (ctxId[i] < 'a' || ctxId[i] > 'z') && + (ctxId[i] < '0' || ctxId[i] > '9') && + (ctxId[i] != '-') && + (ctxId[i] != '_')) + { + return NS_ERROR_INVALID_ARG; + } + } + + nsCString ctxString("@mozilla.org/content/canvas-rendering-context;1?id="); + ctxString.Append(ctxId); + + mCurrentContext = do_CreateInstance(nsPromiseFlatCString(ctxString).get()); + if (!mCurrentContext) + return NS_ERROR_INVALID_ARG; + + nsCOMPtr internalctx(do_QueryInterface(mCurrentContext)); + if (!internalctx) { + mCurrentContext = nsnull; + return NS_ERROR_FAILURE; + } + + nsresult 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)) { + return NS_ERROR_INVALID_ARG; + } + + NS_ADDREF (*aContext = mCurrentContext); + return NS_OK; +} + +nsresult +nsHTMLCanvasElement::UpdateImageContainer() +{ + nsresult rv = NS_OK; + + nsSize sz = GetWidthHeight(); + if (sz.width == 0 || sz.height == 0) + return NS_OK; + + PRInt32 w = 0, h = 0; + + if (mImageFrame) { + mImageFrame->GetWidth(&w); + mImageFrame->GetHeight(&h); + } + + if (sz.width != w || sz.height != h) { + mImageContainer = do_CreateInstance("@mozilla.org/image/container;1"); + mImageContainer->Init(sz.width, sz.height, nsnull); + + mImageFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2"); + if (!mImageFrame) + return NS_ERROR_FAILURE; + +#ifdef XP_WIN + rv = mImageFrame->Init(0, 0, sz.width, sz.height, gfxIFormats::BGR_A8, 24); +#else + rv = mImageFrame->Init(0, 0, sz.width, sz.height, gfxIFormats::RGB_A8, 24); +#endif + NS_ENSURE_SUCCESS(rv, rv); + + mImageContainer->AppendFrame(mImageFrame); + } + + return rv; +} + +nsresult +nsHTMLCanvasElement::UpdateContext() +{ + nsresult rv; + + if (mCurrentContext) { + nsCOMPtr internalctx(do_QueryInterface(mCurrentContext)); + + rv = internalctx->SetTargetImageFrame(mImageFrame); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLCanvasElement::GetCanvasImageContainer (imgIContainer **aImageContainer) +{ + if (!mImageContainer) + UpdateImageContainer(); + + NS_IF_ADDREF(*aImageContainer = mImageContainer); + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLCanvasElement::GetPrimaryCanvasFrame (nsIFrame **aFrame) +{ + *aFrame = GetPrimaryFrame(PR_TRUE); + return NS_OK; +} diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index e37ce917480..9b3b559b458 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -124,7 +124,6 @@ #include "nsNodeInfoManager.h" #include "nsContentCreatorFunctions.h" - //---------------------------------------------------------------------- #ifdef NS_DEBUG diff --git a/mozilla/dom/public/idl/Makefile.in b/mozilla/dom/public/idl/Makefile.in index 45ea8354bbe..330daee367e 100644 --- a/mozilla/dom/public/idl/Makefile.in +++ b/mozilla/dom/public/idl/Makefile.in @@ -44,6 +44,7 @@ include $(DEPTH)/config/autoconf.mk DIRS = \ base \ + canvas \ core \ html \ events \ diff --git a/mozilla/dom/public/idl/canvas/Makefile.in b/mozilla/dom/public/idl/canvas/Makefile.in new file mode 100644 index 00000000000..165f41d85cf --- /dev/null +++ b/mozilla/dom/public/idl/canvas/Makefile.in @@ -0,0 +1,53 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org canvas code. +# +# The Initial Developer of the Original Code is +# Vladimir Vukicevic +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either of the GNU General Public License Version 2 or later (the "GPL"), +# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = dom +XPIDL_MODULE = dom_canvas +GRE_MODULE = 1 + +XPIDLSRCS = \ + nsIDOMCanvasRenderingContext2D.idl \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/mozilla/dom/public/idl/canvas/nsIDOMCanvasRenderingContext2D.idl b/mozilla/dom/public/idl/canvas/nsIDOMCanvasRenderingContext2D.idl new file mode 100644 index 00000000000..5b98c2eca13 --- /dev/null +++ b/mozilla/dom/public/idl/canvas/nsIDOMCanvasRenderingContext2D.idl @@ -0,0 +1,123 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" +#include "nsIVariant.idl" + +interface nsIDOMHTMLImageElement; +interface nsIDOMHTMLCanvasElement; + +[scriptable, uuid(bbb20a59-524e-4662-981e-5e142814b20c)] +interface nsIDOMCanvasGradient : nsISupports +{ + void addColorStop(in float offset, in DOMString color); +}; + +[scriptable, uuid(21dea65c-5c08-4eb1-ac82-81fe95be77b8)] +interface nsIDOMCanvasPattern : nsISupports +{ +}; + +[scriptable, uuid(785c1238-9f86-4da2-a7af-a960a2ce39a1)] +interface nsIDOMCanvasRenderingContext2D : nsISupports +{ + // back-reference to the canvas element for which + // this context was created + readonly attribute nsIDOMHTMLCanvasElement canvas; + + // state + void save(); + void restore(); + + // transformations + void scale(in float x, in float y); + void rotate(in float angle); + void translate(in float x, in float y); + + // compositing + attribute float globalAlpha; /* default 1.0 -- opaque */ + attribute DOMString globalCompositeOperation; /* default "over" */ + + // colors and styles + attribute nsIVariant strokeStyle; + attribute nsIVariant fillStyle; + + nsIDOMCanvasGradient createLinearGradient (in float x0, in float y0, in float x1, in float y1); + nsIDOMCanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1); + nsIDOMCanvasPattern createPattern(in nsIDOMHTMLImageElement image, in DOMString repetition); + + attribute float lineWidth; /* default 1 */ + attribute DOMString lineCap; /* "butt", "round", "square" (default) */ + attribute DOMString lineJoin; /* "round", "bevel", "miter" (default) */ + attribute float miterLimit; /* default 10 */ + + // shadows + attribute float shadowOffsetX; + attribute float shadowOffsetY; + attribute float shadowBlur; + attribute DOMString shadowColor; + + // rects + void clearRect(in float x, in float y, in float w, in float h); + void fillRect(in float x, in float y, in float w, in float h); + void strokeRect(in float x, in float y, in float w, in float h); + + // path API + void beginPath(); + void closePath(); + + void moveTo(in float x, in float y); + void lineTo(in float x, in float y); + void quadraticCurveTo(in float cpx, in float cpy, in float x, in float y); + void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y); + void arcTo(in float x1, in float y1, in float x2, in float y2, in float radius); + void arc(in float x, in float y, in float r, in float startAngle, in float endAngle, in boolean clockwise); + void rect(in float x, in float y, in float w, in float h); + + void fill(); + void stroke(); + void clip(); + + // image api + void drawImage(); +/* + void drawImage(in HTMLImageElement image, in float dx, in float dy); + void drawImage(in HTMLImageElement image, in float dx, in float dy, in float sw, in float sh); + void drawImage(in HTMLImageElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh); +*/ +}; + diff --git a/mozilla/dom/public/idl/html/Makefile.in b/mozilla/dom/public/idl/html/Makefile.in index c87417cb3e7..a6667dbc93c 100644 --- a/mozilla/dom/public/idl/html/Makefile.in +++ b/mozilla/dom/public/idl/html/Makefile.in @@ -107,6 +107,7 @@ SDK_XPIDLSRCS = \ $(NULL) XPIDLSRCS = \ + nsIDOMHTMLCanvasElement.idl \ nsIDOMNSHTMLAnchorElement.idl \ nsIDOMNSHTMLAreaElement.idl \ nsIDOMNSHTMLButtonElement.idl \ diff --git a/mozilla/dom/public/idl/html/nsIDOMHTMLCanvasElement.idl b/mozilla/dom/public/idl/html/nsIDOMHTMLCanvasElement.idl new file mode 100644 index 00000000000..c6b10cd7fb7 --- /dev/null +++ b/mozilla/dom/public/idl/html/nsIDOMHTMLCanvasElement.idl @@ -0,0 +1,60 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsIDOMHTMLElement.idl" + +/** + * The nsIDOMHTMLCanvasElement interface is the interface to a HTML + * element. + * + * For more information on this interface, please see + * http://www.whatwg.org/specs/web-apps/current-work/#graphics + * + * @status UNDER_DEVELOPMENT + */ + +// XXX This should inherit from nsIDOMHTMLImageElement instead, +// and implement that interface as well. +[scriptable, uuid(332dd7d0-97e2-44a0-af5b-1c3bafb0b1f2)] +interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement +{ + attribute long width; + attribute long height; + + nsISupports getContext(in DOMString contextId); +}; + diff --git a/mozilla/dom/public/nsIDOMClassInfo.h b/mozilla/dom/public/nsIDOMClassInfo.h index 202ab88cc6c..cb9e3db5343 100644 --- a/mozilla/dom/public/nsIDOMClassInfo.h +++ b/mozilla/dom/public/nsIDOMClassInfo.h @@ -100,6 +100,7 @@ enum nsDOMClassInfoID { eDOMClassInfo_HTMLBaseFontElement_id, eDOMClassInfo_HTMLBodyElement_id, eDOMClassInfo_HTMLButtonElement_id, + eDOMClassInfo_HTMLCanvasElement_id, eDOMClassInfo_HTMLDListElement_id, eDOMClassInfo_HTMLDelElement_id, eDOMClassInfo_HTMLDirectoryElement_id, @@ -323,6 +324,10 @@ enum nsDOMClassInfoID { eDOMClassInfo_SVGTransform_id, eDOMClassInfo_SVGTransformList_id, #endif // MOZ_SVG + +#ifdef MOZ_ENABLE_CAIRO + eDOMClassInfo_CanvasRenderingContext2D_id, +#endif // This one better be the last one in this list eDOMClassInfoIDCount diff --git a/mozilla/dom/src/base/nsDOMClassInfo.cpp b/mozilla/dom/src/base/nsDOMClassInfo.cpp index 7c77bf1c42c..93b6b5bd87e 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.cpp +++ b/mozilla/dom/src/base/nsDOMClassInfo.cpp @@ -225,6 +225,7 @@ #include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLButtonElement.h" #include "nsIDOMNSHTMLButtonElement.h" +#include "nsIDOMHTMLCanvasElement.h" #include "nsIDOMHTMLDListElement.h" #include "nsIDOMHTMLDirectoryElement.h" #include "nsIDOMHTMLDivElement.h" @@ -370,6 +371,10 @@ #include "nsIDOMSVGZoomAndPan.h" #endif // MOZ_SVG +#ifdef MOZ_ENABLE_CAIRO +#include "nsIDOMCanvasRenderingContext2D.h" +#endif + #include "nsIImageDocument.h" static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID); @@ -582,6 +587,8 @@ static nsDOMClassInfoData sClassInfoData[] = { ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(HTMLButtonElement, nsHTMLElementSH, ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(HTMLCanvasElement, nsHTMLElementSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(HTMLDListElement, nsHTMLElementSH, ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(HTMLDelElement, nsHTMLElementSH, @@ -982,6 +989,11 @@ static nsDOMClassInfoData sClassInfoData[] = { NS_DEFINE_CLASSINFO_DATA(SVGTransformList, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) #endif // MOZ_SVG + +#ifdef MOZ_ENABLE_CAIRO + NS_DEFINE_CLASSINFO_DATA(CanvasRenderingContext2D, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) +#endif // MOZ_ENABLE_CAIRO }; nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull; @@ -1799,6 +1811,11 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(HTMLCanvasElement, nsIDOMHTMLCanvasElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLCanvasElement) + DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(HTMLDListElement, nsIDOMHTMLDListElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDListElement) DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES @@ -2657,9 +2674,14 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGTransformList, nsIDOMSVGTransformList) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTransformList) DOM_CLASSINFO_MAP_END - #endif // MOZ_SVG +#ifdef MOZ_ENABLE_CAIRO + DOM_CLASSINFO_MAP_BEGIN(CanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMCanvasRenderingContext2D) + DOM_CLASSINFO_MAP_END +#endif // MOZ_ENABLE_CAIRO + #ifdef NS_DEBUG { PRUint32 i = sizeof(sClassInfoData) / sizeof(sClassInfoData[0]); diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 0e5cf5ec6b4..d9a40045c81 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -112,9 +112,6 @@ #include "nsXULAtoms.h" #include "nsBoxFrame.h" #include "nsIBoxLayout.h" -#ifdef MOZ_ENABLE_CAIRO -#include "nsCanvasFrame.h" -#endif static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); @@ -159,6 +156,9 @@ NS_NewXTFSVGDisplayFrame(nsIPresShell*, nsIContent*, nsIFrame**); #endif #endif +nsresult +NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsIFrame** aNewFrame); + #ifdef MOZ_SVG #include "nsSVGAtoms.h" #include "nsISVGTextContainerFrame.h" @@ -332,11 +332,6 @@ NS_NewMenuBarFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame ); nsresult NS_NewTreeBodyFrame (nsIPresShell* aPresShell, nsIFrame** aNewFrame); -#ifdef MOZ_ENABLE_CAIRO -nsresult -NS_NewCanvasXULFrame (nsIPresShell* aPresShell, nsIFrame** aNewFrame); -#endif - // grid nsresult NS_NewGridLayout2 ( nsIPresShell* aPresShell, nsIBoxLayout** aNewLayout ); @@ -5375,6 +5370,10 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState, isReplaced = PR_TRUE; rv = NS_NewIsIndexFrame(mPresShell, &newFrame); } + else if (nsHTMLAtoms::canvas == aTag) { + isReplaced = PR_TRUE; + rv = NS_NewHTMLCanvasFrame(mPresShell, &newFrame); + } if (NS_FAILED(rv) || !newFrame) return rv; @@ -5782,12 +5781,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState, processChildren = PR_TRUE; rv = NS_NewTreeColFrame(mPresShell, &newFrame); } -#ifdef MOZ_ENABLE_CAIRO - else if (aTag == nsXULAtoms::canvas) { - isReplaced = PR_TRUE; - rv = NS_NewCanvasXULFrame(mPresShell, &newFrame); - } -#endif // TEXT CONSTRUCTION else if (aTag == nsXULAtoms::text || aTag == nsHTMLAtoms::label || aTag == nsXULAtoms::description) { diff --git a/mozilla/layout/build/Makefile.in b/mozilla/layout/build/Makefile.in index 37f47f6e6f7..bbfb743b059 100644 --- a/mozilla/layout/build/Makefile.in +++ b/mozilla/layout/build/Makefile.in @@ -123,6 +123,7 @@ SHARED_LIBRARY_LIBS = \ $(DIST)/lib/$(LIB_PREFIX)gktable_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkxulbase_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkconbase_s.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)gkconcvs_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkconevents_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkconhtmlcon_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gkconhtmldoc_s.$(LIB_SUFFIX) \ diff --git a/mozilla/layout/build/nsLayoutCID.h b/mozilla/layout/build/nsLayoutCID.h index a920722c718..9c12d85f071 100644 --- a/mozilla/layout/build/nsLayoutCID.h +++ b/mozilla/layout/build/nsLayoutCID.h @@ -225,14 +225,8 @@ #define NS_PLUGINDOCUMENT_CID \ { 0xf96f5ec9, 0x755b, 0x447e, { 0xb1, 0xf3, 0x71, 0x7d, 0x1a, 0x84, 0xbb, 0x41 } } -#ifdef MOZ_ENABLE_CAIRO -// {ba9112c9-10bf-40c7-98b9-315c86e2d99d} -#define NS_CANVASBOXOBJECT_CID \ -{ 0xba9112c9, 0x10bf, 0x40c7, { 0x98, 0xb9, 0x31, 0x5c, 0x86, 0xe2, 0xd9, 0x9d } } - // {a35d1cd4-c505-4d2d-a0f9-aef00b7ce5a5} #define NS_CANVASRENDERINGCONTEXT2D_CID \ { 0xa35d1cd4, 0xc505, 0x4d2d, { 0xa0, 0xf9, 0xae, 0xf0, 0x0b, 0x7c, 0xe5, 0xa5 } } -#endif /* MOZ_ENABLE_CAIRO */ #endif /* nsLayoutCID_h__ */ diff --git a/mozilla/layout/build/nsLayoutModule.cpp b/mozilla/layout/build/nsLayoutModule.cpp index 0aea0a21d47..495f94a4749 100644 --- a/mozilla/layout/build/nsLayoutModule.cpp +++ b/mozilla/layout/build/nsLayoutModule.cpp @@ -147,6 +147,12 @@ #include "nsDOMScriptObjectFactory.h" #include "nsAutoCopyListener.h" +#include "nsHTMLCanvasFrame.h" + +#ifdef MOZ_ENABLE_CAIRO +#include "nsIDOMCanvasRenderingContext2D.h" +#endif + class nsIDocumentLoaderFactory; #define PRODUCT_NAME "Gecko" @@ -176,9 +182,6 @@ static NS_DEFINE_CID(kWindowCommandTableCID, NS_WINDOWCOMMANDTABLE_CID); #include "nsIXULSortService.h" #include "nsXULContentUtils.h" #include "nsXULElement.h" -#ifdef MOZ_ENABLE_CAIRO -#include "nsICanvasRenderingContext2D.h" -#endif NS_IMETHODIMP NS_NewXULContentBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult); @@ -445,10 +448,10 @@ nsresult NS_NewPopupBoxObject(nsIBoxObject** aResult); nsresult NS_NewBrowserBoxObject(nsIBoxObject** aResult); nsresult NS_NewIFrameBoxObject(nsIBoxObject** aResult); nsresult NS_NewTreeBoxObject(nsIBoxObject** aResult); +#endif + #ifdef MOZ_ENABLE_CAIRO -nsresult NS_NewCanvasBoxObject(nsIBoxObject** aResult); -nsresult NS_NewCanvasRenderingContext2D(nsICanvasRenderingContext2D** aResult); -#endif /* MOZ_ENABLE_CAIRO */ +nsresult NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult); #endif nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult); @@ -516,10 +519,6 @@ MAKE_CTOR(CreateNewEditorBoxObject, nsIBoxObject, NS_NewEditorBoxO MAKE_CTOR(CreateNewIFrameBoxObject, nsIBoxObject, NS_NewIFrameBoxObject) MAKE_CTOR(CreateNewScrollBoxObject, nsIBoxObject, NS_NewScrollBoxObject) MAKE_CTOR(CreateNewTreeBoxObject, nsIBoxObject, NS_NewTreeBoxObject) -#ifdef MOZ_ENABLE_CAIRO -MAKE_CTOR(CreateNewCanvasBoxObject, nsIBoxObject, NS_NewCanvasBoxObject) -MAKE_CTOR(CreateNewCanvasRenderingContext2D, nsICanvasRenderingContext2D, NS_NewCanvasRenderingContext2D) -#endif #endif MAKE_CTOR(CreateSelectionImageService, nsISelectionImageService,NS_NewSelectionImageService) #ifdef MOZ_SVG @@ -597,6 +596,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsDataDocumentContentPolicy) MAKE_CTOR(CreateSyncLoadDOMService, nsISyncLoadDOMService, NS_NewSyncLoadDOMService) MAKE_CTOR(CreatePluginDocument, nsIDocument, NS_NewPluginDocument) +#ifdef MOZ_ENABLE_CAIRO +MAKE_CTOR(CreateCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D, NS_NewCanvasRenderingContext2D) +#endif + NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStyleSheetService, Init) // views are not refcounted, so this is the same as @@ -908,18 +911,6 @@ static const nsModuleComponentInfo gComponents[] = { "@mozilla.org/layout/xul-boxobject-tree;1", CreateNewTreeBoxObject }, -#ifdef MOZ_ENABLE_CAIRO - { "XUL Canvas Box Object", - NS_CANVASBOXOBJECT_CID, - "@mozilla.org/layout/xul-boxobject-canvas;1", - CreateNewCanvasBoxObject }, - - { "Canvas 2D Rendering Context", - NS_CANVASRENDERINGCONTEXT2D_CID, - "@mozilla.org/layout/canvas-rendering-context?name=context-2d;1", - CreateNewCanvasRenderingContext2D }, -#endif /* MOZ_ENABLE_CAIRO */ - #endif { "Namespace manager", @@ -1060,6 +1051,13 @@ static const nsModuleComponentInfo gComponents[] = { RegisterHTMLOptionElement, UnregisterHTMLOptionElement }, +#ifdef MOZ_ENABLE_CAIRO + { "Canvas 2D Rendering Context", + NS_CANVASRENDERINGCONTEXT2D_CID, + "@mozilla.org/content/canvas-rendering-context;1?id=2d", + CreateCanvasRenderingContext2D }, +#endif + { "XML document encoder", NS_TEXT_ENCODER_CID, NS_DOC_ENCODER_CONTRACTID_BASE "text/xml", diff --git a/mozilla/layout/generic/Makefile.in b/mozilla/layout/generic/Makefile.in index cd0c11d7cdc..eeb8fd4afb6 100644 --- a/mozilla/layout/generic/Makefile.in +++ b/mozilla/layout/generic/Makefile.in @@ -128,6 +128,7 @@ CPPSRCS = \ nsFrameSetFrame.cpp \ nsFrameUtil.cpp \ nsGfxScrollFrame.cpp \ + nsHTMLCanvasFrame.cpp \ nsHTMLContainerFrame.cpp \ nsHTMLFrame.cpp \ nsHTMLReflowCommand.cpp \ diff --git a/mozilla/layout/generic/nsHTMLCanvasFrame.cpp b/mozilla/layout/generic/nsHTMLCanvasFrame.cpp new file mode 100644 index 00000000000..eac6dfbe7ab --- /dev/null +++ b/mozilla/layout/generic/nsHTMLCanvasFrame.cpp @@ -0,0 +1,259 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsHTMLParts.h" +#include "nsCOMPtr.h" +#include "nsIServiceManager.h" +#include "nsLayoutAtoms.h" + +#include "nsHTMLCanvasFrame.h" +#include "nsICanvasElement.h" + +nsresult +NS_NewHTMLCanvasFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) +{ + nsHTMLCanvasFrame* it = new (aPresShell) nsHTMLCanvasFrame; + if (nsnull == it) { + return NS_ERROR_OUT_OF_MEMORY; + } + *aNewFrame = it; + return NS_OK; +} + +nsHTMLCanvasFrame::nsHTMLCanvasFrame() +{ +} + +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; +} + +NS_IMETHODIMP +nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aMetrics, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + DO_GLOBAL_REFLOW_COUNT("nsHTMLCanvasFrame", aReflowState.reason); + DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); + NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, + ("enter nsHTMLCanvasFrame::Reflow: availSize=%d,%d", + aReflowState.availableWidth, aReflowState.availableHeight)); + + NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow"); + + aStatus = NS_FRAME_COMPLETE; + + float p2t = GetPresContext()->PixelsToTwips(); + + aMetrics.width = NSIntPixelsToTwips(mCanvasSize.width, p2t); + aMetrics.height = NSIntPixelsToTwips(mCanvasSize.height, p2t); + + aMetrics.width += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right; + aMetrics.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; + + if (mPrevInFlow) { + nscoord y = GetContinuationOffset(&aMetrics.width); + aMetrics.height -= y + mBorderPadding.top; + aMetrics.height = PR_MAX(0, aMetrics.height); + } + + aMetrics.ascent = aMetrics.height; + aMetrics.descent = 0; + + if (aMetrics.mComputeMEW) { + aMetrics.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit()); + } + + if (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH) { + aMetrics.mMaximumWidth = aMetrics.width; + } + aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height); + FinishAndStoreOverflow(&aMetrics); + + if (mRect.width != aMetrics.width || mRect.height != aMetrics.height) { + Invalidate(nsRect(0, 0, mRect.width, mRect.height), PR_FALSE); + } + + NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, + ("exit nsHTMLCanvasFrame::Reflow: size=%d,%d", + aMetrics.width, aMetrics.height)); + NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLCanvasFrame::Paint(nsPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer, + PRUint32 aFlags) +{ + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && + isVisible && mRect.width && mRect.height) + { + // If painting is suppressed, we need to stop image painting. + PRBool paintingSuppressed = PR_FALSE; + aPresContext->PresShell()->IsPaintingSuppressed(&paintingSuppressed); + if (paintingSuppressed) { + 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)); + + nsRect dst(0, 0, src.width, src.height); + + if (mImageContainer) { + aRenderingContext.DrawImage(mImageContainer, src, dst); + } else { + aRenderingContext.FillRect(dst); + } + } + } + + return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, nsISelectionDisplay::DISPLAY_IMAGES); +} + +NS_IMETHODIMP +nsHTMLCanvasFrame::CanContinueTextRun(PRBool& aContinueTextRun) const +{ + // stolen from nsImageFrame.cpp + // images really CAN continue text runs, but the textFrame needs to be + // educated before we can indicate that it can. For now, we handle the fixing up + // of max element widths in nsLineLayout::VerticalAlignFrames, but hopefully + // this can be eliminated and the textFrame can be convinced to handle inlines + // that take up space in text runs. + + aContinueTextRun = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLCanvasFrame::GetContentForEvent(nsPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent) +{ + NS_ENSURE_ARG_POINTER(aContent); + *aContent = GetContent(); + NS_IF_ADDREF(*aContent); + return NS_OK; +} + +nsIAtom* +nsHTMLCanvasFrame::GetType() const +{ + return nsLayoutAtoms::canvasFrame; +} + +// get the offset into the content area of the image where aImg starts if it is a continuation. +// from nsImageFrame +nscoord +nsHTMLCanvasFrame::GetContinuationOffset(nscoord* aWidth) const +{ + nscoord offset = 0; + if (aWidth) { + *aWidth = 0; + } + + if (mPrevInFlow) { + for (nsIFrame* prevInFlow = mPrevInFlow ; prevInFlow; prevInFlow = prevInFlow->GetPrevInFlow()) { + nsRect rect = prevInFlow->GetRect(); + if (aWidth) { + *aWidth = rect.width; + } + offset += rect.height; + } + offset -= mBorderPadding.top; + offset = PR_MAX(0, offset); + } + return offset; +} + +#ifdef ACCESSIBILITY +NS_IMETHODIMP +nsHTMLCanvasFrame::GetAccessible(nsIAccessible** aAccessible) +{ + return NS_ERROR_FAILURE; +} +#endif + +#ifdef DEBUG +NS_IMETHODIMP +nsHTMLCanvasFrame::List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent) const +{ + IndentBy(out, aIndent); + ListTag(out); + fputs("\n", out); + return NS_OK; +} +#endif + diff --git a/mozilla/layout/generic/nsHTMLCanvasFrame.h b/mozilla/layout/generic/nsHTMLCanvasFrame.h new file mode 100644 index 00000000000..6140392f939 --- /dev/null +++ b/mozilla/layout/generic/nsHTMLCanvasFrame.h @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Vladimir Vukicevic + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsHTMLCanvasFrame_h___ +#define nsHTMLCanvasFrame_h___ + +#include "nsSplittableFrame.h" +#include "nsString.h" +#include "nsAString.h" +#include "nsPresContext.h" +#include "nsIIOService.h" + +#include "gfxIImageFrame.h" +#include "imgIContainer.h" + +nsresult NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsIFrame** aNewFrame); + +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, + nsFramePaintLayer aWhichLayer, + PRUint32 aFlags = 0); + NS_IMETHOD Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + + NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const; + + + NS_IMETHOD GetContentForEvent(nsPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent); + +#ifdef ACCESSIBILITY + NS_IMETHOD GetAccessible(nsIAccessible** aAccessible); +#endif + + virtual nsIAtom* GetType() const; +#ifdef DEBUG + NS_IMETHOD List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent) const; +#endif + +protected: + virtual ~nsHTMLCanvasFrame(); + + nscoord GetContinuationOffset(nscoord* aWidth = 0) const; + + nsCOMPtr mImageContainer; + + nsMargin mBorderPadding; + nsSize mCanvasSize; +}; + +#endif /* nsHTMLCanvasFrame_h___ */ diff --git a/mozilla/layout/xul/base/public/Makefile.in b/mozilla/layout/xul/base/public/Makefile.in index 0767bcb5abd..95dd7c28261 100644 --- a/mozilla/layout/xul/base/public/Makefile.in +++ b/mozilla/layout/xul/base/public/Makefile.in @@ -66,9 +66,5 @@ XPIDLSRCS= nsIBoxObject.idl \ nsIListBoxObject.idl \ $(NULL) -ifdef MOZ_ENABLE_CAIRO -XPIDLSRCS += nsICanvasBoxObject.idl nsICanvasRenderingContext2D.idl -endif - include $(topsrcdir)/config/rules.mk diff --git a/mozilla/layout/xul/base/src/Makefile.in b/mozilla/layout/xul/base/src/Makefile.in index 48de4abe53a..e421b9c0dff 100644 --- a/mozilla/layout/xul/base/src/Makefile.in +++ b/mozilla/layout/xul/base/src/Makefile.in @@ -132,14 +132,6 @@ CPPSRCS += \ nsListBoxLayout.cpp \ $(NULL) -ifdef MOZ_ENABLE_CAIRO -CPPSRCS += \ - nsCanvasFrame.cpp \ - nsCanvasBoxObject.cpp \ - nsCanvasRenderingContext2D.cpp \ - $(NULL) -endif - endif include $(topsrcdir)/config/config.mk diff --git a/mozilla/parser/htmlparser/public/nsHTMLTagList.h b/mozilla/parser/htmlparser/public/nsHTMLTagList.h index b1c1a97bfa3..230472e2d59 100644 --- a/mozilla/parser/htmlparser/public/nsHTMLTagList.h +++ b/mozilla/parser/htmlparser/public/nsHTMLTagList.h @@ -80,6 +80,7 @@ HTML_TAG(blockquote, Shared) HTML_TAG(body, Body) HTML_TAG(br, BR) HTML_TAG(button, Button) +HTML_TAG(canvas, Canvas) HTML_TAG(caption, TableCaption) HTML_TAG(center, Span) HTML_TAG(cite, Span) diff --git a/mozilla/parser/htmlparser/public/nsHTMLTags.h b/mozilla/parser/htmlparser/public/nsHTMLTags.h index 7bd1d86ff7a..18acee3d0e1 100644 --- a/mozilla/parser/htmlparser/public/nsHTMLTags.h +++ b/mozilla/parser/htmlparser/public/nsHTMLTags.h @@ -63,7 +63,7 @@ enum nsHTMLTag { #undef HTML_TAG #undef HTML_OTHER -// Currently there are 107 HTML tags. eHTMLTag_text = 109. +// All tags before eHTMLTag_text are HTML tags #define NS_HTML_TAG_MAX PRInt32(eHTMLTag_text - 1) class nsHTMLTags { diff --git a/mozilla/parser/htmlparser/src/nsElementTable.cpp b/mozilla/parser/htmlparser/src/nsElementTable.cpp index e688b262bbf..3fc62f94e95 100644 --- a/mozilla/parser/htmlparser/src/nsElementTable.cpp +++ b/mozilla/parser/htmlparser/src/nsElementTable.cpp @@ -369,6 +369,16 @@ const nsHTMLElement gHTMLElements[] = { /*special parents,kids,skip*/ 0,&gButtonKids,eHTMLTag_unknown, /*contain-func*/ 0 }, + { + /*tag*/ eHTMLTag_canvas, + /*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, + /*special parents,kids,skip*/ 0,0,eHTMLTag_unknown, + /*contain-func*/ 0 + }, { /*tag*/ eHTMLTag_caption, /*req-parent excl-parent*/ eHTMLTag_table,eHTMLTag_unknown, diff --git a/mozilla/parser/htmlparser/src/nsHTMLTags.cpp b/mozilla/parser/htmlparser/src/nsHTMLTags.cpp index ff2bcd99bb8..942bebcaf42 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLTags.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLTags.cpp @@ -79,6 +79,8 @@ static const PRUnichar sHTMLTagUnicodeName_br[] = {'b', 'r', '\0'}; static const PRUnichar sHTMLTagUnicodeName_button[] = {'b', 'u', 't', 't', 'o', 'n', '\0'}; +static const PRUnichar sHTMLTagUnicodeName_canvas[] = + {'c', 'a', 'n', 'v', 'a', 's', '\0'}; static const PRUnichar sHTMLTagUnicodeName_caption[] = {'c', 'a', 'p', 't', 'i', 'o', 'n', '\0'}; static const PRUnichar sHTMLTagUnicodeName_center[] =