From fe2017034edb7b6a2054f596bb22bd453460ffbf Mon Sep 17 00:00:00 2001 From: "tor%cs.brown.edu" Date: Fri, 20 Jan 2006 17:00:43 +0000 Subject: [PATCH] Bug 316764 - implement and fix for multiple overlapping children. r=scootermorris git-svn-id: svn://10.0.0.236/trunk@187897 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsGkAtomList.h | 3 + mozilla/content/svg/content/src/Makefile.in | 1 + .../svg/content/src/nsSVGElementFactory.cpp | 4 + .../svg/content/src/nsSVGFeaturesList.h | 2 +- .../svg/content/src/nsSVGMaskElement.cpp | 258 +++++++++++ mozilla/dom/public/idl/svg/Makefile.in | 1 + .../public/idl/svg/nsIDOMSVGMaskElement.idl | 75 ++++ mozilla/dom/public/nsIDOMClassInfo.h | 1 + mozilla/dom/src/base/nsDOMClassInfo.cpp | 9 + mozilla/layout/base/nsCSSFrameConstructor.cpp | 8 +- mozilla/layout/style/nsCSSParser.cpp | 2 + mozilla/layout/style/nsCSSPropList.h | 1 + mozilla/layout/style/nsCSSStruct.cpp | 2 + mozilla/layout/style/nsCSSStruct.h | 1 + mozilla/layout/style/nsRuleNode.cpp | 10 + mozilla/layout/style/nsStyleContext.cpp | 3 +- mozilla/layout/style/nsStyleStruct.cpp | 3 + mozilla/layout/style/nsStyleStruct.h | 1 + mozilla/layout/svg/base/src/Makefile.in | 1 + .../svg/base/src/nsSVGClipPathFrame.cpp | 117 ++++- .../layout/svg/base/src/nsSVGClipPathFrame.h | 66 ++- mozilla/layout/svg/base/src/nsSVGGFrame.cpp | 98 ++-- .../layout/svg/base/src/nsSVGImageFrame.cpp | 77 +++- .../svg/base/src/nsSVGInnerSVGFrame.cpp | 86 ++++ .../layout/svg/base/src/nsSVGMaskFrame.cpp | 422 ++++++++++++++++++ mozilla/layout/svg/base/src/nsSVGMaskFrame.h | 69 +++ .../svg/base/src/nsSVGPathGeometryFrame.cpp | 87 +++- .../layout/svg/base/src/nsSVGTextFrame.cpp | 95 +++- mozilla/layout/svg/base/src/nsSVGUtils.cpp | 28 ++ mozilla/layout/svg/base/src/nsSVGUtils.h | 6 + .../renderer/public/nsISVGRendererCanvas.idl | 13 +- .../renderer/src/cairo/nsSVGCairoCanvas.cpp | 32 +- .../src/cairo/nsSVGCairoPathGeometry.cpp | 20 +- .../src/gdiplus/nsSVGGDIPlusCanvas.cpp | 13 + .../renderer/src/libart/nsSVGLibartCanvas.cpp | 13 + 35 files changed, 1494 insertions(+), 134 deletions(-) create mode 100644 mozilla/content/svg/content/src/nsSVGMaskElement.cpp create mode 100644 mozilla/dom/public/idl/svg/nsIDOMSVGMaskElement.idl create mode 100644 mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp create mode 100644 mozilla/layout/svg/base/src/nsSVGMaskFrame.h diff --git a/mozilla/content/base/src/nsGkAtomList.h b/mozilla/content/base/src/nsGkAtomList.h index bf65cbaae20..f9674423856 100755 --- a/mozilla/content/base/src/nsGkAtomList.h +++ b/mozilla/content/base/src/nsGkAtomList.h @@ -895,6 +895,8 @@ GK_ATOM(markerHeight, "markerHeight") GK_ATOM(markerUnits, "markerUnits") GK_ATOM(markerWidth, "markerWidth") GK_ATOM(mask, "mask") +GK_ATOM(maskContentUnits, "maskContentUnits") +GK_ATOM(maskUnits, "maskUnits") GK_ATOM(matrix, "matrix") GK_ATOM(metadata, "metadata") GK_ATOM(mm, "mm") @@ -1259,6 +1261,7 @@ GK_ATOM(svgInnerSVGFrame, "SVGInnerSVGFrame") GK_ATOM(svgLinearGradientFrame, "SVGLinearGradientFrame") GK_ATOM(svgLineFrame, "SVGLineFrame") GK_ATOM(svgMarkerFrame, "SVGMarkerFrame") +GK_ATOM(svgMaskFrame, "SVGMaskFrame") GK_ATOM(svgOuterSVGFrame, "SVGOuterSVGFrame") GK_ATOM(svgPathFrame, "SVGPathFrame") GK_ATOM(svgPathGeometryFrame, "SVGPathGeometryFrame") diff --git a/mozilla/content/svg/content/src/Makefile.in b/mozilla/content/svg/content/src/Makefile.in index e47ece375f7..bd65b19b1bb 100644 --- a/mozilla/content/svg/content/src/Makefile.in +++ b/mozilla/content/svg/content/src/Makefile.in @@ -102,6 +102,7 @@ CPPSRCS = \ nsSVGLengthList.cpp \ nsSVGLineElement.cpp \ nsSVGMarkerElement.cpp \ + nsSVGMaskElement.cpp \ nsSVGMatrix.cpp \ nsSVGMetadataElement.cpp \ nsSVGNumber.cpp \ diff --git a/mozilla/content/svg/content/src/nsSVGElementFactory.cpp b/mozilla/content/svg/content/src/nsSVGElementFactory.cpp index d5281e2bbc9..3d208679a78 100644 --- a/mozilla/content/svg/content/src/nsSVGElementFactory.cpp +++ b/mozilla/content/svg/content/src/nsSVGElementFactory.cpp @@ -126,6 +126,8 @@ nsresult NS_NewSVGFEUnimplementedMOZElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsresult NS_NewSVGPatternElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGMaskElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsresult NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo) @@ -233,6 +235,8 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo) return NS_NewSVGFEUnimplementedMOZElement(aResult, aNodeInfo); if (name == nsSVGAtoms::pattern) return NS_NewSVGPatternElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::mask) + return NS_NewSVGMaskElement(aResult, aNodeInfo); // if we don't know what to create, just create a standard xml element: return NS_NewXMLElement(aResult, aNodeInfo); diff --git a/mozilla/content/svg/content/src/nsSVGFeaturesList.h b/mozilla/content/svg/content/src/nsSVGFeaturesList.h index aaf4ea63d8d..076e48f93ca 100644 --- a/mozilla/content/svg/content/src/nsSVGFeaturesList.h +++ b/mozilla/content/svg/content/src/nsSVGFeaturesList.h @@ -56,7 +56,7 @@ SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#ColorProfile") SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Gradient") SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Pattern") SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Clip") -SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Mask") +SVG_SUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Mask") SVG_UNSUPPORTED_FEATURE("http://www.w3.org/TR/SVG11/feature#Filter") // Basic features diff --git a/mozilla/content/svg/content/src/nsSVGMaskElement.cpp b/mozilla/content/svg/content/src/nsSVGMaskElement.cpp new file mode 100644 index 00000000000..e7644449019 --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGMaskElement.cpp @@ -0,0 +1,258 @@ +/* -*- 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 the Mozilla SVG project. + * + * The Initial Developer of the Original Code is IBM Corporation. + * 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 "nsSVGLength.h" +#include "nsSVGAnimatedLength.h" +#include "nsSVGEnum.h" +#include "nsSVGAnimatedEnumeration.h" +#include "nsIDOMSVGAnimatedEnum.h" +#include "nsIDOMSVGMaskElement.h" +#include "nsCOMPtr.h" +#include "nsISVGSVGElement.h" +#include "nsSVGStylableElement.h" +#include "nsSVGAtoms.h" + +//--------------------- Masks ------------------------ + +typedef nsSVGStylableElement nsSVGMaskElementBase; + +class nsSVGMaskElement : public nsSVGMaskElementBase, + public nsIDOMSVGMaskElement +{ +protected: + friend nsresult NS_NewSVGMaskElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGMaskElement(nsINodeInfo* aNodeInfo); + virtual ~nsSVGMaskElement(); + nsresult Init(); + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + + // Mask Element + NS_DECL_NSIDOMSVGMASKELEMENT + + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGElement::) + NS_FORWARD_NSIDOMELEMENT(nsSVGElement::) + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::) + +protected: + + // nsIDOMSVGMaskElement values + nsCOMPtr mMaskUnits; + nsCOMPtr mMaskContentUnits; + nsCOMPtr mX; + nsCOMPtr mY; + nsCOMPtr mWidth; + nsCOMPtr mHeight; +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(Mask) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGMaskElement,nsSVGMaskElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGMaskElement,nsSVGMaskElementBase) + +NS_INTERFACE_MAP_BEGIN(nsSVGMaskElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGMaskElement) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGMaskElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGMaskElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGMaskElement::nsSVGMaskElement(nsINodeInfo* aNodeInfo) + : nsSVGMaskElementBase(aNodeInfo) +{ + +} + +nsSVGMaskElement::~nsSVGMaskElement() +{ +} + + +nsresult +nsSVGMaskElement::Init() +{ + nsresult rv = nsSVGMaskElementBase::Init(); + NS_ENSURE_SUCCESS(rv,rv); + + // Define enumeration mappings + static struct nsSVGEnumMapping pUnitMap[] = { + {&nsSVGAtoms::objectBoundingBox, nsIDOMSVGMaskElement::SVG_MUNITS_OBJECTBOUNDINGBOX}, + {&nsSVGAtoms::userSpaceOnUse, nsIDOMSVGMaskElement::SVG_MUNITS_USERSPACEONUSE}, + {nsnull, 0} + }; + + // Create mapped attributes + + // DOM property: maskUnits , #IMPLIED attrib: maskUnits + { + nsCOMPtr units; + rv = NS_NewSVGEnum(getter_AddRefs(units), + nsIDOMSVGMaskElement::SVG_MUNITS_OBJECTBOUNDINGBOX, pUnitMap); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mMaskUnits), units); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::maskUnits, mMaskUnits); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: maskContentUnits , #IMPLIED attrib: maskContentUnits + { + nsCOMPtr units; + rv = NS_NewSVGEnum(getter_AddRefs(units), + nsIDOMSVGMaskElement::SVG_MUNITS_USERSPACEONUSE, pUnitMap); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mMaskContentUnits), units); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::maskContentUnits, mMaskContentUnits); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: x , #IMPLIED attrib: x + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + -10.0,nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mX), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::x, mX); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: y , #IMPLIED attrib: y + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + -10.0,nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mY), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::y, mY); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: width , #IMPLIED attrib: width + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + 120.0,nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mWidth), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::width, mWidth); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: height , #IMPLIED attrib: height + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), + 120.0,nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mHeight), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::height, mHeight); + NS_ENSURE_SUCCESS(rv,rv); + } + + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsIDOMNode method + +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGMaskElement) + +//---------------------------------------------------------------------- +// nsIDOMSVGMaskElement methods + +/* readonly attribute nsIDOMSVGAnimatedEnumeration maskUnits; */ +NS_IMETHODIMP nsSVGMaskElement::GetMaskUnits(nsIDOMSVGAnimatedEnumeration * *aMaskUnits) +{ + *aMaskUnits = mMaskUnits; + NS_IF_ADDREF(*aMaskUnits); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedEnumeration maskContentUnits; */ +NS_IMETHODIMP nsSVGMaskElement::GetMaskContentUnits(nsIDOMSVGAnimatedEnumeration * *aMaskUnits) +{ + *aMaskUnits = mMaskContentUnits; + NS_IF_ADDREF(*aMaskUnits); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength x; */ +NS_IMETHODIMP nsSVGMaskElement::GetX(nsIDOMSVGAnimatedLength * *aX) +{ + *aX = mX; + NS_IF_ADDREF(*aX); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength y; */ +NS_IMETHODIMP nsSVGMaskElement::GetY(nsIDOMSVGAnimatedLength * *aY) +{ + *aY = mY; + NS_IF_ADDREF(*aY); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength width; */ +NS_IMETHODIMP nsSVGMaskElement::GetWidth(nsIDOMSVGAnimatedLength * *aWidth) +{ + *aWidth = mWidth; + NS_IF_ADDREF(*aWidth); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength height; */ +NS_IMETHODIMP nsSVGMaskElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight) +{ + *aHeight = mHeight; + NS_IF_ADDREF(*aHeight); + return NS_OK; +} diff --git a/mozilla/dom/public/idl/svg/Makefile.in b/mozilla/dom/public/idl/svg/Makefile.in index 2bb9be34f84..94c9d3450ce 100644 --- a/mozilla/dom/public/idl/svg/Makefile.in +++ b/mozilla/dom/public/idl/svg/Makefile.in @@ -85,6 +85,7 @@ XPIDLSRCS = \ nsIDOMSVGLineElement.idl \ nsIDOMSVGLocatable.idl \ nsIDOMSVGMarkerElement.idl \ + nsIDOMSVGMaskElement.idl \ nsIDOMSVGMatrix.idl \ nsIDOMSVGMetadataElement.idl \ nsIDOMSVGNumber.idl \ diff --git a/mozilla/dom/public/idl/svg/nsIDOMSVGMaskElement.idl b/mozilla/dom/public/idl/svg/nsIDOMSVGMaskElement.idl new file mode 100644 index 00000000000..daa684fee80 --- /dev/null +++ b/mozilla/dom/public/idl/svg/nsIDOMSVGMaskElement.idl @@ -0,0 +1,75 @@ +/* -*- 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 the Mozilla SVG project. + * + * The Initial Developer of the Original Code is IBM Corporation. + * 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 "nsIDOMSVGElement.idl" + +interface nsIDOMSVGAnimatedLength; +interface nsIDOMSVGAnimatedEnumeration; + +[scriptable, uuid(fdd7039c-35b6-465a-b7a3-c98a815b583e)] +interface nsIDOMSVGMaskElement + : nsIDOMSVGElement +/* + The SVG DOM makes use of multiple interface inheritance. + Since XPCOM only supports single interface inheritance, + the best thing that we can do is to promise that whenever + an object implements _this_ interface it will also + implement the following interfaces. (We then have to QI to + hop between them.) + + SVGElement, + SVGTests, + SVGLangSpace, + SVGExternalResourcesRequired, + SVGStylable, + SVGUnitTypes { + +*/ +{ + // These constants are taken from SVGUnitTypes + const unsigned short SVG_MUNITS_UNKNOWN = 0; + const unsigned short SVG_MUNITS_OBJECTBOUNDINGBOX = 1; + const unsigned short SVG_MUNITS_USERSPACEONUSE = 2; + + readonly attribute nsIDOMSVGAnimatedEnumeration maskUnits; + readonly attribute nsIDOMSVGAnimatedEnumeration maskContentUnits; + readonly attribute nsIDOMSVGAnimatedLength x; + readonly attribute nsIDOMSVGAnimatedLength y; + readonly attribute nsIDOMSVGAnimatedLength width; + readonly attribute nsIDOMSVGAnimatedLength height; +}; + + diff --git a/mozilla/dom/public/nsIDOMClassInfo.h b/mozilla/dom/public/nsIDOMClassInfo.h index 309d1e8b5aa..a7510e0aa65 100644 --- a/mozilla/dom/public/nsIDOMClassInfo.h +++ b/mozilla/dom/public/nsIDOMClassInfo.h @@ -267,6 +267,7 @@ enum nsDOMClassInfoID { eDOMClassInfo_SVGLinearGradientElement_id, eDOMClassInfo_SVGLineElement_id, eDOMClassInfo_SVGMarkerElement_id, + eDOMClassInfo_SVGMaskElement_id, eDOMClassInfo_SVGMetadataElement_id, eDOMClassInfo_SVGPathElement_id, eDOMClassInfo_SVGPatternElement_id, diff --git a/mozilla/dom/src/base/nsDOMClassInfo.cpp b/mozilla/dom/src/base/nsDOMClassInfo.cpp index 83351d8b7f3..e7a75f19b36 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.cpp +++ b/mozilla/dom/src/base/nsDOMClassInfo.cpp @@ -365,6 +365,7 @@ #include "nsIDOMSVGLineElement.h" #include "nsIDOMSVGLocatable.h" #include "nsIDOMSVGMarkerElement.h" +#include "nsIDOMSVGMaskElement.h" #include "nsIDOMSVGMatrix.h" #include "nsIDOMSVGMetadataElement.h" #include "nsIDOMSVGNumber.h" @@ -931,6 +932,8 @@ static nsDOMClassInfoData sClassInfoData[] = { ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGMarkerElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGMaskElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGMetadataElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGPathElement, nsElementSH, @@ -2620,6 +2623,12 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGMaskElement, nsIDOMSVGMaskElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGMaskElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGMetadataElement, nsIDOMSVGMetadataElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGMetadataElement) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 77df9e53c35..8e8900b3b1f 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -229,6 +229,8 @@ nsIFrame* NS_NewSVGFilterFrame(nsIPresShell *aPresShell, nsIContent *aContent); nsIFrame* NS_NewSVGPatternFrame(nsIPresShell* aPresShell, nsIContent* aContent); +nsIFrame* +NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsIContent* aContent); #endif #include "nsIDocument.h" @@ -3469,7 +3471,8 @@ IsSpecialContent(nsIContent* aContent, aTag == nsSVGAtoms::clipPath || aTag == nsSVGAtoms::textPath || aTag == nsSVGAtoms::filter || - aTag == nsSVGAtoms::pattern; + aTag == nsSVGAtoms::pattern || + aTag == nsSVGAtoms::mask; #endif #ifdef MOZ_MATHML @@ -7800,6 +7803,9 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsFrameConstructorState& aState, else if (aTag == nsSVGAtoms::pattern) { newFrame = NS_NewSVGPatternFrame(mPresShell, aContent); } + else if (aTag == nsSVGAtoms::mask) { + newFrame = NS_NewSVGMaskFrame(mPresShell, aContent); + } if (newFrame == nsnull) { // Either we have an unknown tag, or construction of a frame diff --git a/mozilla/layout/style/nsCSSParser.cpp b/mozilla/layout/style/nsCSSParser.cpp index 12e4d619b83..6be769551d0 100644 --- a/mozilla/layout/style/nsCSSParser.cpp +++ b/mozilla/layout/style/nsCSSParser.cpp @@ -4434,6 +4434,8 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode, case eCSSProperty_marker_mid: case eCSSProperty_marker_start: return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull); + case eCSSProperty_mask: + return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull); case eCSSProperty_pointer_events: return ParseVariant(aErrorCode, aValue, VARIANT_HOK, nsCSSProps::kPointerEventsKTable); diff --git a/mozilla/layout/style/nsCSSPropList.h b/mozilla/layout/style/nsCSSPropList.h index 23514115634..6704d533e8b 100644 --- a/mozilla/layout/style/nsCSSPropList.h +++ b/mozilla/layout/style/nsCSSPropList.h @@ -475,6 +475,7 @@ CSS_PROP_SHORTHAND(marker, marker, Marker) CSS_PROP_SVG(marker-end, marker_end, MarkerEnd, SVG, mMarkerEnd, eCSSType_Value, nsnull) CSS_PROP_SVG(marker-mid, marker_mid, MarkerMid, SVG, mMarkerMid, eCSSType_Value, nsnull) CSS_PROP_SVG(marker-start, marker_start, MarkerStart, SVG, mMarkerStart, eCSSType_Value, nsnull) +CSS_PROP_SVGRESET(mask, mask, Mask, SVG, mMask, eCSSType_Value, nsnull) CSS_PROP_SVG(pointer-events, pointer_events, PointerEvents, SVG, mPointerEvents, eCSSType_Value, kPointerEventsKTable) CSS_PROP_SVG(shape-rendering, shape_rendering, ShapeRendering, SVG, mShapeRendering, eCSSType_Value, kShapeRenderingKTable) CSS_PROP_SVGRESET(stop-color, stop_color, StopColor, SVG, mStopColor, eCSSType_Value, nsnull) diff --git a/mozilla/layout/style/nsCSSStruct.cpp b/mozilla/layout/style/nsCSSStruct.cpp index 638665bedd3..4861cdba949 100644 --- a/mozilla/layout/style/nsCSSStruct.cpp +++ b/mozilla/layout/style/nsCSSStruct.cpp @@ -1163,6 +1163,7 @@ nsCSSSVG::nsCSSSVG(const nsCSSSVG& aCopy) mMarkerEnd(aCopy.mMarkerEnd), mMarkerMid(aCopy.mMarkerMid), mMarkerStart(aCopy.mMarkerStart), + mMask(aCopy.mMask), mPointerEvents(aCopy.mPointerEvents), mShapeRendering(aCopy.mShapeRendering), mStopColor(aCopy.mStopColor), @@ -1205,6 +1206,7 @@ void nsCSSSVG::List(FILE* out, PRInt32 aIndent) const mMarkerEnd.AppendToString(buffer, eCSSProperty_marker_end); mMarkerMid.AppendToString(buffer, eCSSProperty_marker_mid); mMarkerStart.AppendToString(buffer, eCSSProperty_marker_start); + mMask.AppendToString(buffer, eCSSProperty_mask); mPointerEvents.AppendToString(buffer, eCSSProperty_pointer_events); mShapeRendering.AppendToString(buffer, eCSSProperty_shape_rendering); mStopColor.AppendToString(buffer, eCSSProperty_stop_color); diff --git a/mozilla/layout/style/nsCSSStruct.h b/mozilla/layout/style/nsCSSStruct.h index 87e939954fa..cecdde91327 100644 --- a/mozilla/layout/style/nsCSSStruct.h +++ b/mozilla/layout/style/nsCSSStruct.h @@ -573,6 +573,7 @@ struct nsCSSSVG : public nsCSSStruct { nsCSSValue mMarkerEnd; nsCSSValue mMarkerMid; nsCSSValue mMarkerStart; + nsCSSValue mMask; nsCSSValue mPointerEvents; nsCSSValue mShapeRendering; nsCSSValue mStopColor; diff --git a/mozilla/layout/style/nsRuleNode.cpp b/mozilla/layout/style/nsRuleNode.cpp index da7e9d64801..1f69c3a85c4 100644 --- a/mozilla/layout/style/nsRuleNode.cpp +++ b/mozilla/layout/style/nsRuleNode.cpp @@ -5011,6 +5011,16 @@ nsRuleNode::ComputeSVGResetData(nsStyleStruct* aStartStruct, inherited = PR_TRUE; svgReset->mFilter = parentSVGReset->mFilter; } + + // mask: url, none, inherit + if (eCSSUnit_URL == SVGData.mMask.GetUnit()) { + svgReset->mMask = SVGData.mMask.GetURLValue(); + } else if (eCSSUnit_None == SVGData.mMask.GetUnit()) { + svgReset->mMask = nsnull; + } else if (eCSSUnit_Inherit == SVGData.mMask.GetUnit()) { + inherited = PR_TRUE; + svgReset->mMask = parentSVGReset->mMask; + } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the diff --git a/mozilla/layout/style/nsStyleContext.cpp b/mozilla/layout/style/nsStyleContext.cpp index c6afa7e2ed2..d47bd6757bc 100644 --- a/mozilla/layout/style/nsStyleContext.cpp +++ b/mozilla/layout/style/nsStyleContext.cpp @@ -932,9 +932,10 @@ void nsStyleContext::DumpRegressionData(nsPresContext* aPresContext, FILE* out, else fprintf(out, "%ld ", (long)svgReset->mStopColor.mPaint.mColor); - fprintf(out, "%s %s %f %d\" />\n", + fprintf(out, "%s %s %s %f %d\" />\n", URICString(svgReset->mClipPath).get(), URICString(svgReset->mFilter).get(), + URICString(svgReset->mMask).get(), svgReset->mStopOpacity, (int)svgReset->mDominantBaseline); #endif diff --git a/mozilla/layout/style/nsStyleStruct.cpp b/mozilla/layout/style/nsStyleStruct.cpp index c7a2a756449..d316fe945e8 100644 --- a/mozilla/layout/style/nsStyleStruct.cpp +++ b/mozilla/layout/style/nsStyleStruct.cpp @@ -838,6 +838,7 @@ nsStyleSVGReset::nsStyleSVGReset() mStopColor.mPaint.mColor = NS_RGB(0,0,0); mClipPath = nsnull; mFilter = nsnull; + mMask = nsnull; mStopOpacity = 1.0f; mDominantBaseline = NS_STYLE_DOMINANT_BASELINE_AUTO; } @@ -851,6 +852,7 @@ nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource) mStopColor = aSource.mStopColor; mClipPath = aSource.mClipPath; mFilter = aSource.mFilter; + mMask = aSource.mMask; mStopOpacity = aSource.mStopOpacity; mDominantBaseline = aSource.mDominantBaseline; } @@ -860,6 +862,7 @@ nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) cons if (mStopColor != aOther.mStopColor || !EqualURIs(mClipPath, aOther.mClipPath) || !EqualURIs(mFilter, aOther.mFilter) || + !EqualURIs(mMask, aOther.mMask) || mStopOpacity != aOther.mStopOpacity || mDominantBaseline != aOther.mDominantBaseline) return NS_STYLE_HINT_VISUAL; diff --git a/mozilla/layout/style/nsStyleStruct.h b/mozilla/layout/style/nsStyleStruct.h index 5ef8563b292..2784578fe29 100644 --- a/mozilla/layout/style/nsStyleStruct.h +++ b/mozilla/layout/style/nsStyleStruct.h @@ -1340,6 +1340,7 @@ struct nsStyleSVGReset : public nsStyleStruct { nsStyleSVGPaint mStopColor; // [reset] nsCOMPtr mClipPath; // [reset] nsCOMPtr mFilter; // [reset] + nsCOMPtr mMask; // [reset] float mStopOpacity; // [reset] diff --git a/mozilla/layout/svg/base/src/Makefile.in b/mozilla/layout/svg/base/src/Makefile.in index 878515b4531..20aaba94c7e 100644 --- a/mozilla/layout/svg/base/src/Makefile.in +++ b/mozilla/layout/svg/base/src/Makefile.in @@ -80,6 +80,7 @@ CPPSRCS = \ nsSVGInnerSVGFrame.cpp \ nsSVGLineFrame.cpp \ nsSVGMarkerFrame.cpp \ + nsSVGMaskFrame.cpp \ nsSVGOuterSVGFrame.cpp \ nsSVGPathFrame.cpp \ nsSVGPathGeometryFrame.cpp \ diff --git a/mozilla/layout/svg/base/src/nsSVGClipPathFrame.cpp b/mozilla/layout/svg/base/src/nsSVGClipPathFrame.cpp index 98cc6b4ae79..41b43570a94 100644 --- a/mozilla/layout/svg/base/src/nsSVGClipPathFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGClipPathFrame.cpp @@ -44,32 +44,64 @@ #include "nsSVGAnimatedTransformList.h" #include "nsIDOMSVGAnimatedEnum.h" #include "nsSVGUtils.h" +#include "nsISVGRendererSurface.h" +#include "nsSVGDefsFrame.h" +#include "nsSVGAtoms.h" -NS_IMETHODIMP_(nsrefcnt) -nsSVGClipPathFrame::AddRef() -{ - return NS_OK; -} +typedef nsSVGDefsFrame nsSVGClipPathFrameBase; -NS_IMETHODIMP_(nsrefcnt) -nsSVGClipPathFrame::Release() +class nsSVGClipPathFrame : public nsSVGClipPathFrameBase, + public nsISVGClipPathFrame { - return NS_OK; -} + friend nsIFrame* + NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsIContent* aContent); -NS_IMETHODIMP -nsSVGClipPathFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if (nsnull == aInstancePtr) { - return NS_ERROR_NULL_POINTER; + virtual ~nsSVGClipPathFrame(); + NS_IMETHOD InitSVG(); + + public: + // nsISupports interface: + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + + // nsISVGClipPathFrame interface: + NS_IMETHOD ClipPaint(nsISVGRendererCanvas* canvas, + nsISVGRendererSurface* aClipSurface, + nsISVGChildFrame* aParent, + nsCOMPtr aMatrix); + + NS_IMETHOD ClipHitTest(nsISVGChildFrame* aParent, + nsCOMPtr aMatrix, + float aX, float aY, PRBool *aHit); + + NS_IMETHOD IsTrivial(PRBool *aTrivial); + + /** + * Get the "type" of the frame + * + * @see nsLayoutAtoms::svgClipPathFrame + */ + virtual nsIAtom* GetType() const; + +#ifdef DEBUG + NS_IMETHOD GetFrameName(nsAString& aResult) const + { + return MakeFrameName(NS_LITERAL_STRING("SVGClipPath"), aResult); } - if (aIID.Equals(nsSVGClipPathFrame::GetCID())) { - *aInstancePtr = (void*)(nsSVGClipPathFrame*)this; - NS_ADDREF_THIS(); - return NS_OK; - } - return (nsSVGDefsFrame::QueryInterface(aIID, aInstancePtr)); -} +#endif + + private: + nsISVGChildFrame *mClipParent; + nsCOMPtr mClipParentMatrix; + + // nsISVGContainerFrame interface: + already_AddRefed GetCanvasTM(); +}; + +NS_INTERFACE_MAP_BEGIN(nsSVGClipPathFrame) + NS_INTERFACE_MAP_ENTRY(nsISVGClipPathFrame) +NS_INTERFACE_MAP_END_INHERITING(nsSVGClipPathFrameBase) //---------------------------------------------------------------------- // Implementation @@ -89,7 +121,8 @@ NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsIContent* aContent) } nsresult -NS_GetSVGClipPathFrame(nsSVGClipPathFrame **aResult, nsIURI *aURI, nsIContent *aContent) +NS_GetSVGClipPathFrame(nsISVGClipPathFrame **aResult, + nsIURI *aURI, nsIContent *aContent) { *aResult = nsnull; @@ -132,6 +165,7 @@ nsSVGClipPathFrame::InitSVG() NS_IMETHODIMP nsSVGClipPathFrame::ClipPaint(nsISVGRendererCanvas* canvas, + nsISVGRendererSurface* aClipSurface, nsISVGChildFrame* aParent, nsCOMPtr aMatrix) { @@ -143,7 +177,17 @@ nsSVGClipPathFrame::ClipPaint(nsISVGRendererCanvas* canvas, NotifyCanvasTMChanged(PR_TRUE); - rv = canvas->SetRenderMode(nsISVGRendererCanvas::SVG_RENDER_MODE_CLIP); + PRBool isTrivial; + IsTrivial(&isTrivial); + + if (isTrivial) + rv = canvas->SetRenderMode(nsISVGRendererCanvas::SVG_RENDER_MODE_CLIP); + else { + rv = canvas->SetRenderMode(nsISVGRendererCanvas::SVG_RENDER_MODE_CLIP_MASK); + + canvas->PushSurface(aClipSurface); + } + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; @@ -156,6 +200,9 @@ nsSVGClipPathFrame::ClipPaint(nsISVGRendererCanvas* canvas, } } + if (!isTrivial) + canvas->PopSurface(); + canvas->SetRenderMode(nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL); return NS_OK; @@ -193,6 +240,30 @@ nsSVGClipPathFrame::ClipHitTest(nsISVGChildFrame* aParent, return NS_OK; } +NS_IMETHODIMP +nsSVGClipPathFrame::IsTrivial(PRBool *aTrivial) +{ + *aTrivial = PR_TRUE; + PRBool foundOne = PR_FALSE; + + for (nsIFrame* kid = mFrames.FirstChild(); kid; + kid = kid->GetNextSibling()) { + nsISVGChildFrame* SVGFrame = nsnull; + kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); + if (SVGFrame) { + nsIFrame *frame = nsnull; + CallQueryInterface(SVGFrame, &frame); + if (foundOne || frame->GetContent()->Tag() == nsSVGAtoms::g) { + *aTrivial = PR_FALSE; + return NS_OK; + } + foundOne = PR_TRUE; + } + } + + return NS_OK; +} + nsIAtom * nsSVGClipPathFrame::GetType() const { diff --git a/mozilla/layout/svg/base/src/nsSVGClipPathFrame.h b/mozilla/layout/svg/base/src/nsSVGClipPathFrame.h index 2fd5bb07e19..d7e741c0425 100644 --- a/mozilla/layout/svg/base/src/nsSVGClipPathFrame.h +++ b/mozilla/layout/svg/base/src/nsSVGClipPathFrame.h @@ -34,58 +34,46 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsSVGDefsFrame.h" -#include "nsLayoutAtoms.h" +#ifndef __NS_SVGCLIPPATHFRAME_H__ +#define __NS_SVGCLIPPATHFRAME_H__ -#define NS_SVGCLIPPATHFRAME_CID \ -{0xb497bbe2, 0x4434, 0x4d96, {0x9c, 0xe8, 0xf2, 0xad, 0xd1, 0x1f, 0x1d, 0x26}} +#include "nsISupports.h" -typedef nsSVGDefsFrame nsSVGClipPathFrameBase; +class nsISVGRendererCanvas; +class nsISVGRendererSurface; +class nsISVGChildFrame; +class nsIDOMSVGMatrix; +class nsIURI; +class nsIContent; -class nsSVGClipPathFrame : public nsSVGClipPathFrameBase -{ - friend nsIFrame* - NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsIContent* aContent); +#define NS_ISVGCLIPPATHFRAME_IID \ +{0x9309e388, 0xde9b, 0x4848, {0x84, 0xfe, 0x22, 0xc1, 0xd8, 0x0c, 0x89, 0x11}} - virtual ~nsSVGClipPathFrame(); - NS_IMETHOD InitSVG(); - - public: - NS_DECL_ISUPPORTS - - NS_DEFINE_STATIC_CID_ACCESSOR(NS_SVGCLIPPATHFRAME_CID) - NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVGCLIPPATHFRAME_CID) +class nsISVGClipPathFrame : public nsISupports { +public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGCLIPPATHFRAME_IID) NS_IMETHOD ClipPaint(nsISVGRendererCanvas* canvas, + nsISVGRendererSurface* aClipSurface, nsISVGChildFrame* aParent, - nsCOMPtr aMatrix); + nsCOMPtr aMatrix) = 0; NS_IMETHOD ClipHitTest(nsISVGChildFrame* aParent, nsCOMPtr aMatrix, - float aX, float aY, PRBool *aHit); - /** - * Get the "type" of the frame - * - * @see nsLayoutAtoms::svgClipPathFrame - */ - virtual nsIAtom* GetType() const; + float aX, float aY, PRBool *aHit) = 0; -#ifdef DEBUG - NS_IMETHOD GetFrameName(nsAString& aResult) const - { - return MakeFrameName(NS_LITERAL_STRING("SVGClipPath"), aResult); - } -#endif + // Check if this clipPath is made up of more than one geometry object. + // If so, the clipping API in cairo isn't enough and we need to use + // mask based clipping. - private: - nsISVGChildFrame *mClipParent; - nsCOMPtr mClipParentMatrix; - - // nsISVGContainerFrame interface: - already_AddRefed GetCanvasTM(); + NS_IMETHOD IsTrivial(PRBool *aTrivial) = 0; }; -NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGClipPathFrame, NS_SVGCLIPPATHFRAME_CID) +NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGClipPathFrame, NS_ISVGCLIPPATHFRAME_IID) + nsresult -NS_GetSVGClipPathFrame(nsSVGClipPathFrame **aResult, nsIURI *aURI, nsIContent *aContent); +NS_GetSVGClipPathFrame(nsISVGClipPathFrame **aResult, + nsIURI *aURI, nsIContent *aContent); + +#endif diff --git a/mozilla/layout/svg/base/src/nsSVGGFrame.cpp b/mozilla/layout/svg/base/src/nsSVGGFrame.cpp index 1a2802fc828..375fcbcf7cf 100644 --- a/mozilla/layout/svg/base/src/nsSVGGFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGGFrame.cpp @@ -50,7 +50,7 @@ #include "nsSVGUtils.h" #include "nsSVGFilterFrame.h" #include "nsISVGValueUtils.h" -#include +#include "nsSVGMaskFrame.h" //---------------------------------------------------------------------- // Implementation @@ -90,8 +90,6 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips, PRBool ignoreFilter) { - nsCOMPtr surface; - const nsStyleDisplay *display = mStyleContext->GetStyleDisplay(); if (display->mOpacity == 0.0) return NS_OK; @@ -117,42 +115,65 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas, } } - nsSVGClipPathFrame *clip = NULL; + nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame(); + + /* check for a clip path */ + + PRBool trivialClip = PR_TRUE; + nsISVGClipPathFrame *clip = NULL; + nsCOMPtr clipMaskSurface; + aURI = GetStyleSVGReset()->mClipPath; if (aURI) { NS_GetSVGClipPathFrame(&clip, aURI, mContent); if (clip) { - nsCOMPtr matrix = GetCanvasTM(); - canvas->PushClip(); - clip->ClipPaint(canvas, this, matrix); + clip->IsTrivial(&trivialClip); + + if (trivialClip) { + canvas->PushClip(); + } else { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface)); + if (!clipMaskSurface) + clip = nsnull; + } + + if (clip) { + nsCOMPtr matrix = GetCanvasTM(); + clip->ClipPaint(canvas, clipMaskSurface, this, matrix); + } } } - if (display->mOpacity != 1.0) { - nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame(); - if (outerSVGFrame) { - nsIFrame *frame = nsnull; - CallQueryInterface(outerSVGFrame, &frame); + /* check for mask */ - if (frame) { - nsSize size = frame->GetSize(); - float p2t = GetPresContext()->ScaledPixelsToTwips(); - PRUint32 width = (PRUint32)ceil(size.width/p2t); - PRUint32 height = (PRUint32)ceil(size.height/p2t); - - nsCOMPtr renderer; - outerSVGFrame->GetRenderer(getter_AddRefs(renderer)); - if (renderer) - renderer->CreateSurface(width, height, getter_AddRefs(surface)); - if (surface) { - if (NS_FAILED(canvas->PushSurface(surface))) - surface = nsnull; - } + nsISVGMaskFrame *mask = nsnull; + nsCOMPtr maskSurface, maskedSurface; + + aURI = GetStyleSVGReset()->mMask; + if (aURI) { + NS_GetSVGMaskFrame(&mask, aURI, mContent); + + if (mask) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface)); + + if (maskSurface) { + nsCOMPtr matrix = GetCanvasTM(); + if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix, + display->mOpacity))) + maskSurface = nsnull; } } } + if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface)); + if (maskedSurface) { + canvas->PushSurface(maskedSurface); + } else + maskSurface = nsnull; + } + for (nsIFrame* kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) { nsISVGChildFrame* SVGFrame=nsnull; @@ -161,12 +182,29 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas, SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE); } - if (surface) { + if (maskedSurface) canvas->PopSurface(); - canvas->CompositeSurface(surface, 0, 0, display->mOpacity); + + if (clipMaskSurface) { + if (!maskSurface && display->mOpacity == 1.0) { + maskSurface = clipMaskSurface; + } else { + nsCOMPtr clipped; + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped)); + + canvas->PushSurface(clipped); + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface); + canvas->PopSurface(); + maskedSurface = clipped; + } } - if (clip) + if (maskSurface) + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface); + else if (display->mOpacity != 1.0) + canvas->CompositeSurface(maskedSurface, 0, 0, display->mOpacity); + + if (clip && trivialClip) canvas->PopClip(); return NS_OK; @@ -195,7 +233,7 @@ nsSVGGFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit) PRBool clipHit = PR_TRUE;; nsIURI *aURI; - nsSVGClipPathFrame *clip = NULL; + nsISVGClipPathFrame *clip = NULL; aURI = GetStyleSVGReset()->mClipPath; if (aURI) NS_GetSVGClipPathFrame(&clip, aURI, mContent); diff --git a/mozilla/layout/svg/base/src/nsSVGImageFrame.cpp b/mozilla/layout/svg/base/src/nsSVGImageFrame.cpp index 87db380cd1f..27ff7ddde14 100644 --- a/mozilla/layout/svg/base/src/nsSVGImageFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGImageFrame.cpp @@ -57,6 +57,8 @@ #include "nsLayoutAtoms.h" #include "nsISVGValueUtils.h" #include "nsSVGFilterFrame.h" +#include "nsSVGUtils.h" +#include "nsSVGMaskFrame.h" #define NS_GET_BIT(rowptr, x) (rowptr[(x)>>3] & (1<<(7-(x)&0x7))) @@ -354,19 +356,66 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, canvas->PushClip(); + nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame(); + /* check for a clip path */ - nsSVGClipPathFrame *clip = NULL; + + PRBool trivialClip = PR_TRUE; + nsISVGClipPathFrame *clip = NULL; + nsCOMPtr clipMaskSurface; + aURI = GetStyleSVGReset()->mClipPath; if (aURI) { NS_GetSVGClipPathFrame(&clip, aURI, mContent); if (clip) { - nsCOMPtr matrix; - GetCanvasTM(getter_AddRefs(matrix)); - clip->ClipPaint(canvas, this, matrix); + clip->IsTrivial(&trivialClip); + + if (trivialClip) { + canvas->PushClip(); + } else { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface)); + if (!clipMaskSurface) + clip = nsnull; + } + + if (clip) { + nsCOMPtr matrix; + GetCanvasTM(getter_AddRefs(matrix)); + clip->ClipPaint(canvas, clipMaskSurface, this, matrix); + } } } + /* check for mask */ + + nsISVGMaskFrame *mask = nsnull; + nsCOMPtr maskSurface, maskedSurface; + + aURI = GetStyleSVGReset()->mMask; + if (aURI) { + NS_GetSVGMaskFrame(&mask, aURI, mContent); + + if (mask) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface)); + + if (maskSurface) { + nsCOMPtr matrix; + GetCanvasTM(getter_AddRefs(matrix)); + if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix))) + maskSurface = nsnull; + } + } + } + + if (maskSurface || clipMaskSurface) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface)); + if (maskedSurface) { + canvas->PushSurface(maskedSurface); + } else + maskSurface = nsnull; + } + if (mSurface) { nsCOMPtr ctm; GetCanvasTM(getter_AddRefs(ctm)); @@ -465,6 +514,26 @@ nsSVGImageFrame::PaintSVG(nsISVGRendererCanvas* canvas, mStyleContext->GetStyleDisplay()->mOpacity); } + if (maskedSurface) + canvas->PopSurface(); + + if (clipMaskSurface) { + if (!maskSurface) { + maskSurface = clipMaskSurface; + } else { + nsCOMPtr clipped; + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped)); + + canvas->PushSurface(clipped); + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface); + canvas->PopSurface(); + maskedSurface = clipped; + } + } + + if (maskSurface) + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface); + canvas->PopClip(); return NS_OK; diff --git a/mozilla/layout/svg/base/src/nsSVGInnerSVGFrame.cpp b/mozilla/layout/svg/base/src/nsSVGInnerSVGFrame.cpp index e1bc2814e00..ae31a2c840e 100644 --- a/mozilla/layout/svg/base/src/nsSVGInnerSVGFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGInnerSVGFrame.cpp @@ -57,6 +57,9 @@ #include "nsSVGFilterFrame.h" #include "nsISVGValueUtils.h" #include "nsSVGUtils.h" +#include "nsSVGClipPathFrame.h" +#include "nsSVGMaskFrame.h" +#include "nsISVGRendererSurface.h" typedef nsContainerFrame nsSVGInnerSVGFrameBase; @@ -359,6 +362,8 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas, // printf("nsSVGInnerSVG(%p)::Paint\n", this); #endif + const nsStyleDisplay *display = mStyleContext->GetStyleDisplay(); + nsIURI *aURI; /* check for filter */ @@ -411,6 +416,63 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas, canvas->SetClipRect(clipTransform, x, y, width, height); } + nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame(); + + /* check for a clip path */ + + PRBool trivialClip = PR_TRUE; + nsISVGClipPathFrame *clip = NULL; + nsCOMPtr clipMaskSurface; + + aURI = GetStyleSVGReset()->mClipPath; + if (aURI) { + NS_GetSVGClipPathFrame(&clip, aURI, mContent); + + if (clip) { + clip->IsTrivial(&trivialClip); + + if (!trivialClip) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface)); + if (!clipMaskSurface) + clip = nsnull; + } + + if (clip) { + nsCOMPtr matrix = GetCanvasTM(); + clip->ClipPaint(canvas, clipMaskSurface, this, matrix); + } + } + } + + /* check for mask */ + + nsISVGMaskFrame *mask = nsnull; + nsCOMPtr maskSurface, maskedSurface; + + aURI = GetStyleSVGReset()->mMask; + if (aURI) { + NS_GetSVGMaskFrame(&mask, aURI, mContent); + + if (mask) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface)); + + if (maskSurface) { + nsCOMPtr matrix = GetCanvasTM(); + if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix, + display->mOpacity))) + maskSurface = nsnull; + } + } + } + + if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface)); + if (maskedSurface) { + canvas->PushSurface(maskedSurface); + } else + maskSurface = nsnull; + } + for (nsIFrame* kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) { nsISVGChildFrame* SVGFrame=nsnull; @@ -419,6 +481,28 @@ nsSVGInnerSVGFrame::PaintSVG(nsISVGRendererCanvas* canvas, SVGFrame->PaintSVG(canvas, dirtyRectTwips, PR_FALSE); } + if (maskedSurface) + canvas->PopSurface(); + + if (clipMaskSurface) { + if (!maskSurface && display->mOpacity == 1.0) { + maskSurface = clipMaskSurface; + } else { + nsCOMPtr clipped; + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped)); + + canvas->PushSurface(clipped); + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface); + canvas->PopSurface(); + maskedSurface = clipped; + } + } + + if (maskSurface) + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface); + else if (display->mOpacity != 1.0) + canvas->CompositeSurface(maskedSurface, 0, 0, display->mOpacity); + canvas->PopClip(); return NS_OK; @@ -748,6 +832,8 @@ nsSVGInnerSVGFrame::WillModifySVGObservable(nsISVGValue* observable, nsSVGUtils::FindFilterInvalidation(this, getter_AddRefs(region)); outerSVGFrame->InvalidateRegion(region, PR_TRUE); } + + return NS_OK; } NS_IMETHODIMP diff --git a/mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp b/mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp new file mode 100644 index 00000000000..ade814ad0bb --- /dev/null +++ b/mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp @@ -0,0 +1,422 @@ +/* -*- 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 the Mozilla SVG project. + * + * The Initial Developer of the Original Code is IBM Corporation. + * Portions created by the Initial Developer are Copyright (C) 2004 + * 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 "nsIDOMDocument.h" +#include "nsIDocument.h" +#include "nsIDOMSVGMaskElement.h" +#include "nsSVGMaskFrame.h" +#include "nsISVGRendererCanvas.h" +#include "nsIDOMSVGAnimatedEnum.h" +#include "nsSVGUtils.h" +#include "nsISVGValueUtils.h" +#include "nsIDOMSVGAnimatedLength.h" +#include "nsSVGDefsFrame.h" +#include "nsIDOMSVGLength.h" +#include "nsISVGRendererSurface.h" + +typedef nsSVGDefsFrame nsSVGMaskFrameBase; + +class nsSVGMaskFrame : public nsSVGMaskFrameBase, + public nsISVGMaskFrame +{ + friend nsIFrame* + NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsIContent* aContent); + + virtual ~nsSVGMaskFrame(); + NS_IMETHOD InitSVG(); + + public: + // nsISupports interface: + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + + // nsISVGMaskFrame interface: + NS_IMETHOD MaskPaint(nsISVGRendererCanvas* aCanvas, + nsISVGRendererSurface* aSurface, + nsISVGChildFrame* aParent, + nsCOMPtr aMatrix, + float aOpacity = 1.0f); + + /** + * Get the "type" of the frame + * + * @see nsLayoutAtoms::svgMaskFrame + */ + virtual nsIAtom* GetType() const; + +#ifdef DEBUG + NS_IMETHOD GetFrameName(nsAString& aResult) const + { + return MakeFrameName(NS_LITERAL_STRING("SVGMask"), aResult); + } +#endif + + private: + nsCOMPtr mMaskUnits; + nsCOMPtr mMaskContentUnits; + nsCOMPtr mX; + nsCOMPtr mY; + nsCOMPtr mWidth; + nsCOMPtr mHeight; + + nsISVGChildFrame *mMaskParent; + nsCOMPtr mMaskParentMatrix; + + // nsISVGContainerFrame interface: + already_AddRefed GetCanvasTM(); +}; + +NS_INTERFACE_MAP_BEGIN(nsSVGMaskFrame) + NS_INTERFACE_MAP_ENTRY(nsISVGMaskFrame) +NS_INTERFACE_MAP_END_INHERITING(nsSVGMaskFrameBase) + + +//---------------------------------------------------------------------- +// Implementation + +nsIFrame* +NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsIContent* aContent) +{ + return new (aPresShell) nsSVGMaskFrame; +} + +nsresult +NS_GetSVGMaskFrame(nsISVGMaskFrame **aResult, + nsIURI *aURI, nsIContent *aContent) +{ + *aResult = nsnull; + + // Get the PresShell + nsIDocument *myDoc = aContent->GetCurrentDoc(); + if (!myDoc) { + NS_WARNING("No document for this content!"); + return NS_ERROR_FAILURE; + } + nsIPresShell *aPresShell = myDoc->GetShellAt(0); + + // Find the referenced frame + nsIFrame *cpframe; + if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&cpframe, aURI, aContent, aPresShell))) + return NS_ERROR_FAILURE; + + nsIAtom* frameType = cpframe->GetType(); + if (frameType != nsLayoutAtoms::svgMaskFrame) + return NS_ERROR_FAILURE; + + *aResult = (nsSVGMaskFrame *)cpframe; + return NS_OK; +} + +nsSVGMaskFrame::~nsSVGMaskFrame() +{ + NS_REMOVE_SVGVALUE_OBSERVER(mX); + NS_REMOVE_SVGVALUE_OBSERVER(mY); + NS_REMOVE_SVGVALUE_OBSERVER(mWidth); + NS_REMOVE_SVGVALUE_OBSERVER(mHeight); + NS_REMOVE_SVGVALUE_OBSERVER(mMaskUnits); + NS_REMOVE_SVGVALUE_OBSERVER(mMaskContentUnits); +} + +NS_IMETHODIMP +nsSVGMaskFrame::InitSVG() +{ + nsresult rv = nsSVGDefsFrame::InitSVG(); + if (NS_FAILED(rv)) + return rv; + + mMaskParentMatrix = nsnull; + + nsCOMPtr mask = do_QueryInterface(mContent); + NS_ASSERTION(mask, "wrong content element"); + + { + nsCOMPtr length; + mask->GetX(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mX)); + NS_ASSERTION(mX, "no X"); + if (!mX) return NS_ERROR_FAILURE; + NS_ADD_SVGVALUE_OBSERVER(mX); + } + + { + nsCOMPtr length; + mask->GetY(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mY)); + NS_ASSERTION(mY, "no Y"); + if (!mY) return NS_ERROR_FAILURE; + NS_ADD_SVGVALUE_OBSERVER(mY); + } + + { + nsCOMPtr length; + mask->GetWidth(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mWidth)); + NS_ASSERTION(mWidth, "no Width"); + if (!mWidth) return NS_ERROR_FAILURE; + NS_ADD_SVGVALUE_OBSERVER(mWidth); + } + + { + nsCOMPtr length; + mask->GetHeight(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mHeight)); + NS_ASSERTION(mHeight, "no Height"); + if (!mHeight) return NS_ERROR_FAILURE; + NS_ADD_SVGVALUE_OBSERVER(mHeight); + } + + mask->GetMaskUnits(getter_AddRefs(mMaskUnits)); + NS_ADD_SVGVALUE_OBSERVER(mMaskUnits); + + mask->GetMaskContentUnits(getter_AddRefs(mMaskContentUnits)); + NS_ADD_SVGVALUE_OBSERVER(mMaskContentUnits); + + return NS_OK; +} + + +/* sRGB -> linearRGB mapping table */ +static unsigned char rgb2lin[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 6, 6, 6, 6, 7, + 7, 7, 8, 8, 8, 9, 9, 9, + 10, 10, 10, 11, 11, 11, 12, 12, + 13, 13, 13, 14, 14, 15, 15, 16, + 16, 16, 17, 17, 18, 18, 19, 19, + 20, 20, 21, 22, 22, 23, 23, 24, + 24, 25, 26, 26, 27, 27, 28, 29, + 29, 30, 31, 31, 32, 33, 33, 34, + 35, 36, 36, 37, 38, 38, 39, 40, + 41, 42, 42, 43, 44, 45, 46, 47, + 47, 48, 49, 50, 51, 52, 53, 54, + 55, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 70, + 71, 72, 73, 74, 75, 76, 77, 78, + 80, 81, 82, 83, 84, 85, 87, 88, + 89, 90, 92, 93, 94, 95, 97, 98, + 99, 101, 102, 103, 105, 106, 107, 109, +110, 112, 113, 114, 116, 117, 119, 120, +122, 123, 125, 126, 128, 129, 131, 132, +134, 135, 137, 139, 140, 142, 144, 145, +147, 148, 150, 152, 153, 155, 157, 159, +160, 162, 164, 166, 167, 169, 171, 173, +175, 176, 178, 180, 182, 184, 186, 188, +190, 192, 193, 195, 197, 199, 201, 203, +205, 207, 209, 211, 213, 215, 218, 220, +222, 224, 226, 228, 230, 232, 235, 237, +239, 241, 243, 245, 248, 250, 252, 255 +}; + +NS_IMETHODIMP +nsSVGMaskFrame::MaskPaint(nsISVGRendererCanvas* aCanvas, + nsISVGRendererSurface* aSurface, + nsISVGChildFrame* aParent, + nsCOMPtr aMatrix, + float aOpacity) +{ + nsRect dirty; + + if (NS_FAILED(aCanvas->PushSurface(aSurface))) + return NS_ERROR_FAILURE; + + { + nsIFrame *frame; + CallQueryInterface(aParent, &frame); + nsCOMPtr parent = frame->GetContent(); + + float x, y, width, height; + + PRUint16 units; + mMaskUnits->GetAnimVal(&units); + + if (units == nsIDOMSVGMaskElement::SVG_MUNITS_OBJECTBOUNDINGBOX) { + + aParent->SetMatrixPropagation(PR_FALSE); + aParent->NotifyCanvasTMChanged(PR_TRUE); + + nsCOMPtr bbox; + aParent->GetBBox(getter_AddRefs(bbox)); + + aParent->SetMatrixPropagation(PR_TRUE); + aParent->NotifyCanvasTMChanged(PR_TRUE); + + if (!bbox) + return NS_OK; + +#ifdef DEBUG_tor + bbox->GetX(&x); + bbox->GetY(&y); + bbox->GetWidth(&width); + bbox->GetHeight(&height); + + fprintf(stderr, "mask bbox: %f,%f %fx%f\n", x, y, width, height); +#endif + + bbox->GetX(&x); + x += nsSVGUtils::ObjectSpace(bbox, mX, nsSVGUtils::X); + bbox->GetY(&y); + y += nsSVGUtils::ObjectSpace(bbox, mY, nsSVGUtils::Y); + width = nsSVGUtils::ObjectSpace(bbox, mWidth, nsSVGUtils::X); + height = nsSVGUtils::ObjectSpace(bbox, mHeight, nsSVGUtils::Y); + } else { + x = nsSVGUtils::UserSpace(parent, mX, nsSVGUtils::X); + y = nsSVGUtils::UserSpace(parent, mY, nsSVGUtils::Y); + width = nsSVGUtils::UserSpace(parent, mWidth, nsSVGUtils::X); + height = nsSVGUtils::UserSpace(parent, mHeight, nsSVGUtils::Y); + } + +#ifdef DEBUG_tor + fprintf(stderr, "mask clip: %f,%f %fx%f\n", x, y, width, height); +#endif + + aCanvas->SetClipRect(aMatrix, x, y, width, height); + } + + mMaskParent = aParent, + mMaskParentMatrix = aMatrix; + + NotifyCanvasTMChanged(PR_TRUE); + + for (nsIFrame* kid = mFrames.FirstChild(); kid; + kid = kid->GetNextSibling()) { + nsISVGChildFrame* SVGFrame=nsnull; + kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); + if (SVGFrame) { + SVGFrame->PaintSVG(aCanvas, dirty, PR_TRUE); + } + } + + aCanvas->PopSurface(); + + /* Now convert to intensity (sRGB -> linearRGB -> intensity) + and store in alpha channel */ + + PRUint32 width, height, length; + PRUint8 *data; + PRInt32 stride; + + aSurface->Lock(); + aSurface->GetWidth(&width); + aSurface->GetHeight(&height); + aSurface->GetData(&data, &length, &stride); + for (PRUint32 y = 0; y < height; y++) + for (PRUint32 x = 0; x < width; x++) { + PRUint32 a; + float r, g, b, intensity; + + /* un-premultiply and sRGB -> linearRGB conversion */ + a = data[stride * y + 4 * x + 3]; + if (a) { + b = rgb2lin[(255 * (PRUint32)data[stride * y + 4 * x]) / a] / 255.0; + g = rgb2lin[(255 * (PRUint32)data[stride * y + 4 * x + 1]) / a] / 255.0; + r = rgb2lin[(255 * (PRUint32)data[stride * y + 4 * x + 2]) / a] / 255.0; + } else { + b = g = r = 0.0f; + } + + /* linearRGB -> intensity */ + intensity = (r * 0.2125 + g * 0.7154 + b * 0.0721) * (a / 255.0) * aOpacity; + + data[stride * y + 4 * x] = 255; + data[stride * y + 4 * x + 1] = 255; + data[stride * y + 4 * x + 2] = 255; + data[stride * y + 4 * x + 3] = (unsigned char)(intensity * 255); + } + + aSurface->Unlock(); + + return NS_OK; +} + +nsIAtom * +nsSVGMaskFrame::GetType() const +{ + return nsLayoutAtoms::svgMaskFrame; +} + +already_AddRefed +nsSVGMaskFrame::GetCanvasTM() +{ + // startup cycle + if (!mMaskParentMatrix) { + NS_ASSERTION(mParent, "null parent"); + nsISVGContainerFrame *containerFrame; + mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), + (void**)&containerFrame); + if (!containerFrame) { + NS_ERROR("invalid parent"); + return nsnull; + } + mMaskParentMatrix = containerFrame->GetCanvasTM(); + } + + nsCOMPtr canvasTM = mMaskParentMatrix; + + /* object bounding box? */ + PRUint16 units; + nsCOMPtr path = do_QueryInterface(mContent); + nsCOMPtr aEnum; + path->GetMaskContentUnits(getter_AddRefs(aEnum)); + aEnum->GetAnimVal(&units); + + if (mMaskParent && + units == nsIDOMSVGMaskElement::SVG_MUNITS_OBJECTBOUNDINGBOX) { + nsCOMPtr rect; + nsresult rv = mMaskParent->GetBBox(getter_AddRefs(rect)); + + if (NS_SUCCEEDED(rv)) { + float minx, miny, width, height; + rect->GetX(&minx); + rect->GetY(&miny); + rect->GetWidth(&width); + rect->GetHeight(&height); + + nsCOMPtr tmp, fini; + canvasTM->Translate(minx, miny, getter_AddRefs(tmp)); + tmp->ScaleNonUniform(width, height, getter_AddRefs(fini)); + canvasTM = fini; + } + } + + nsIDOMSVGMatrix* retval = canvasTM.get(); + NS_IF_ADDREF(retval); + return retval; +} diff --git a/mozilla/layout/svg/base/src/nsSVGMaskFrame.h b/mozilla/layout/svg/base/src/nsSVGMaskFrame.h new file mode 100644 index 00000000000..cb0299b24af --- /dev/null +++ b/mozilla/layout/svg/base/src/nsSVGMaskFrame.h @@ -0,0 +1,69 @@ +/* -*- 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 the Mozilla SVG project. + * + * The Initial Developer of the Original Code is IBM Corporation. + * 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 __NS_SVGMASKFRAME_H__ +#define __NS_SVGMASKFRAME_H__ + +#include "nsISupports.h" + +class nsISVGRendererCanvas; +class nsISVGRendererSurface; +class nsISVGChildFrame; +class nsIDOMSVGMatrix; +class nsIURI; +class nsIContent; + +#define NS_ISVGMASKFRAME_IID \ +{0x122fe62b, 0xa4cb, 0x49d4, {0xbf, 0xd7, 0x26, 0x67, 0x58, 0x28, 0xff, 0x02}} + +class nsISVGMaskFrame : public nsISupports { +public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGMASKFRAME_IID) + + NS_IMETHOD MaskPaint(nsISVGRendererCanvas* aCanvas, + nsISVGRendererSurface* aSurface, + nsISVGChildFrame* aParent, + nsCOMPtr aMatrix, + float aOpacity = 1.0f) = 0; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsISVGMaskFrame, NS_ISVGMASKFRAME_IID) + +nsresult +NS_GetSVGMaskFrame(nsISVGMaskFrame **aResult, + nsIURI *aURI, nsIContent *aContent); + +#endif diff --git a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp index 15f2b092de4..5b2bb57d495 100644 --- a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp @@ -62,6 +62,8 @@ #include "nsIViewManager.h" #include "nsSVGUtils.h" #include "nsSVGFilterFrame.h" +#include "nsSVGMaskFrame.h" +#include "nsISVGRendererSurface.h" //////////////////////////////////////////////////////////////////////// // nsSVGPathGeometryFrame @@ -258,25 +260,64 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas, } } + nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame(); + /* check for a clip path */ - nsSVGClipPathFrame *clip = nsnull; + PRBool trivialClip = PR_TRUE; + nsISVGClipPathFrame *clip = NULL; + nsCOMPtr clipMaskSurface; + aURI = GetStyleSVGReset()->mClipPath; if (aURI) { NS_GetSVGClipPathFrame(&clip, aURI, mContent); if (clip) { - nsCOMPtr matrix; - GetCanvasTM(getter_AddRefs(matrix)); - canvas->PushClip(); - clip->ClipPaint(canvas, this, matrix); - } + clip->IsTrivial(&trivialClip); -#ifdef DEBUG_tor - nsCAutoString spec; - aURI->GetAsciiSpec(spec); - fprintf(stderr, "CLIPPATH %s %p\n", spec.get(), clip); -#endif + if (trivialClip) { + canvas->PushClip(); + } else { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface)); + if (!clipMaskSurface) + clip = nsnull; + } + + if (clip) { + nsCOMPtr matrix; + GetCanvasTM(getter_AddRefs(matrix)); + clip->ClipPaint(canvas, clipMaskSurface, this, matrix); + } + } + } + + /* check for mask */ + + nsISVGMaskFrame *mask = nsnull; + nsCOMPtr maskSurface, maskedSurface; + + aURI = GetStyleSVGReset()->mMask; + if (aURI) { + NS_GetSVGMaskFrame(&mask, aURI, mContent); + + if (mask) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface)); + + if (maskSurface) { + nsCOMPtr matrix; + GetCanvasTM(getter_AddRefs(matrix)); + if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix))) + maskSurface = nsnull; + } + } + } + + if (maskSurface || clipMaskSurface) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface)); + if (maskedSurface) { + canvas->PushSurface(maskedSurface); + } else + maskSurface = nsnull; } /* render */ @@ -314,7 +355,27 @@ nsSVGPathGeometryFrame::PaintSVG(nsISVGRendererCanvas* canvas, } } - if (clip) + if (maskedSurface) + canvas->PopSurface(); + + if (clipMaskSurface) { + if (!maskSurface) { + maskSurface = clipMaskSurface; + } else { + nsCOMPtr clipped; + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped)); + + canvas->PushSurface(clipped); + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface); + canvas->PopSurface(); + maskedSurface = clipped; + } + } + + if (maskSurface) + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface); + + if (clip && trivialClip) canvas->PopClip(); return NS_OK; @@ -336,7 +397,7 @@ nsSVGPathGeometryFrame::GetFrameForPointSVG(float x, float y, nsIFrame** hit) PRBool clipHit = PR_TRUE;; nsIURI *aURI; - nsSVGClipPathFrame *clip = NULL; + nsISVGClipPathFrame *clip = NULL; aURI = GetStyleSVGReset()->mClipPath; if (aURI) NS_GetSVGClipPathFrame(&clip, aURI, mContent); diff --git a/mozilla/layout/svg/base/src/nsSVGTextFrame.cpp b/mozilla/layout/svg/base/src/nsSVGTextFrame.cpp index 254ca9a1da0..d0487b41d4f 100644 --- a/mozilla/layout/svg/base/src/nsSVGTextFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGTextFrame.cpp @@ -69,6 +69,9 @@ #include "nsSVGFilterFrame.h" #include "nsSVGUtils.h" #include "nsDOMError.h" +#include "nsSVGMaskFrame.h" +#include "nsSVGClipPathFrame.h" +#include "nsISVGRendererSurface.h" typedef nsContainerFrame nsSVGTextFrameBase; @@ -541,11 +544,17 @@ nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas, // printf("nsSVGTextFrame(%p)::Paint\n", this); #endif + const nsStyleDisplay *display = mStyleContext->GetStyleDisplay(); + if (display->mOpacity == 0.0) + return NS_OK; + + nsIURI *aURI; + /* check for filter */ if (!ignoreFilter) { if (!mFilter) { - nsIURI *aURI = GetStyleSVGReset()->mFilter; + aURI = GetStyleSVGReset()->mFilter; if (aURI) NS_GetSVGFilterFrame(&mFilter, aURI, mContent); if (mFilter) @@ -560,6 +569,65 @@ nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas, } } + nsISVGOuterSVGFrame* outerSVGFrame = GetOuterSVGFrame(); + + /* check for a clip path */ + + PRBool trivialClip = PR_TRUE; + nsISVGClipPathFrame *clip = NULL; + nsCOMPtr clipMaskSurface; + + aURI = GetStyleSVGReset()->mClipPath; + if (aURI) { + NS_GetSVGClipPathFrame(&clip, aURI, mContent); + + if (clip) { + clip->IsTrivial(&trivialClip); + + if (trivialClip) { + canvas->PushClip(); + } else { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipMaskSurface)); + if (!clipMaskSurface) + clip = nsnull; + } + + if (clip) { + nsCOMPtr matrix = GetCanvasTM(); + clip->ClipPaint(canvas, clipMaskSurface, this, matrix); + } + } + } + + /* check for mask */ + + nsISVGMaskFrame *mask = nsnull; + nsCOMPtr maskSurface, maskedSurface; + + aURI = GetStyleSVGReset()->mMask; + if (aURI) { + NS_GetSVGMaskFrame(&mask, aURI, mContent); + + if (mask) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface)); + + if (maskSurface) { + nsCOMPtr matrix = GetCanvasTM(); + if (NS_FAILED(mask->MaskPaint(canvas, maskSurface, this, matrix, + display->mOpacity))) + maskSurface = nsnull; + } + } + } + + if (maskSurface || clipMaskSurface || display->mOpacity != 1.0) { + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskedSurface)); + if (maskedSurface) { + canvas->PushSurface(maskedSurface); + } else + maskSurface = nsnull; + } + nsIFrame* kid = mFrames.FirstChild(); while (kid) { nsISVGChildFrame* SVGFrame=0; @@ -569,6 +637,31 @@ nsSVGTextFrame::PaintSVG(nsISVGRendererCanvas* canvas, kid = kid->GetNextSibling(); } + if (maskedSurface) + canvas->PopSurface(); + + if (clipMaskSurface) { + if (!maskSurface && display->mOpacity == 1.0) { + maskSurface = clipMaskSurface; + } else { + nsCOMPtr clipped; + nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(clipped)); + + canvas->PushSurface(clipped); + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, clipMaskSurface); + canvas->PopSurface(); + maskedSurface = clipped; + } + } + + if (maskSurface) + canvas->CompositeSurfaceWithMask(maskedSurface, 0, 0, maskSurface); + else if (display->mOpacity != 1.0) + canvas->CompositeSurface(maskedSurface, 0, 0, display->mOpacity); + + if (clip && trivialClip) + canvas->PopClip(); + return NS_OK; } diff --git a/mozilla/layout/svg/base/src/nsSVGUtils.cpp b/mozilla/layout/svg/base/src/nsSVGUtils.cpp index a9e3fccc544..235ffded6d1 100644 --- a/mozilla/layout/svg/base/src/nsSVGUtils.cpp +++ b/mozilla/layout/svg/base/src/nsSVGUtils.cpp @@ -1,3 +1,4 @@ +/* -*- 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 * @@ -64,6 +65,7 @@ #include "nsIDOMSVGPoint.h" #include "nsSVGPoint.h" #include "nsDOMError.h" +#include "nsISVGOuterSVGFrame.h" #if defined(MOZ_SVG_RENDERER_GDIPLUS) #include @@ -393,6 +395,32 @@ nsSVGUtils::TransformPoint(nsIDOMSVGMatrix *matrix, xfpoint->GetY(y); } +nsresult +nsSVGUtils::GetSurface(nsISVGOuterSVGFrame *aOuterSVGFrame, + nsISVGRendererSurface **aSurface) +{ + if (!aOuterSVGFrame) + return NS_ERROR_FAILURE; + + nsIFrame *frame = nsnull; + CallQueryInterface(aOuterSVGFrame, &frame); + + if (!frame) + return NS_ERROR_FAILURE; + + nsSize size = frame->GetSize(); + float p2t = frame->GetPresContext()->ScaledPixelsToTwips(); + PRUint32 width = (PRUint32)ceil(size.width/p2t); + PRUint32 height = (PRUint32)ceil(size.height/p2t); + + nsCOMPtr renderer; + aOuterSVGFrame->GetRenderer(getter_AddRefs(renderer)); + if (renderer) + return renderer->CreateSurface(width, height, aSurface); + else + return NS_ERROR_FAILURE; +} + nsISVGGlyphFragmentLeaf * nsSVGUtils::GetGlyphFragmentAtCharNum(nsISVGGlyphFragmentNode* node, PRUint32 charnum) diff --git a/mozilla/layout/svg/base/src/nsSVGUtils.h b/mozilla/layout/svg/base/src/nsSVGUtils.h index 97c6dc8d724..8da708a3b96 100644 --- a/mozilla/layout/svg/base/src/nsSVGUtils.h +++ b/mozilla/layout/svg/base/src/nsSVGUtils.h @@ -53,6 +53,8 @@ class nsISVGGlyphFragmentNode; class nsIDOMSVGLength; class nsIDOMSVGMatrix; class nsIURI; +class nsISVGOuterSVGFrame; +class nsISVGRendererSurface; #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -136,6 +138,10 @@ public: static float AngleBisect(float a1, float a2); + /* Generate a new rendering surface the size of the outer svg frame */ + static nsresult GetSurface(nsISVGOuterSVGFrame *aOuterSVGFrame, + nsISVGRendererSurface **aSurface); + private: /* * Returns the glyph fragment containing a particular character diff --git a/mozilla/layout/svg/renderer/public/nsISVGRendererCanvas.idl b/mozilla/layout/svg/renderer/public/nsISVGRendererCanvas.idl index f44cd7f80a6..2e92dd7aa91 100644 --- a/mozilla/layout/svg/renderer/public/nsISVGRendererCanvas.idl +++ b/mozilla/layout/svg/renderer/public/nsISVGRendererCanvas.idl @@ -69,7 +69,7 @@ interface nsISVGRendererSurface; * Mozilla-native rendering object with a call to * nsISVGRenderer::createCanvas(). */ -[scriptable, uuid(2e64a227-de4b-4a69-ab82-5dda1579e90f)] +[scriptable, uuid(9cdf3f86-a511-4948-83f8-e25460f03b83)] interface nsISVGRendererCanvas : nsISupports { /** @@ -108,10 +108,11 @@ interface nsISVGRendererCanvas : nsISupports void flush(); /** - * Set render mode (clipping or normal draw) + * Set render mode (normal, clipping, or clip render to mask) */ - const unsigned short SVG_RENDER_MODE_NORMAL = 0; - const unsigned short SVG_RENDER_MODE_CLIP = 1; + const unsigned short SVG_RENDER_MODE_NORMAL = 0; + const unsigned short SVG_RENDER_MODE_CLIP = 1; + const unsigned short SVG_RENDER_MODE_CLIP_MASK = 2; attribute unsigned short renderMode; /** @@ -139,6 +140,10 @@ interface nsISVGRendererCanvas : nsISupports in unsigned long x, in unsigned long y, in float opacity); + void compositeSurfaceWithMask(in nsISVGRendererSurface surface, + in unsigned long x, in unsigned long y, + in nsISVGRendererSurface mask); + void compositeSurfaceMatrix(in nsISVGRendererSurface surface, in nsIDOMSVGMatrix canvasTM, in float opacity); diff --git a/mozilla/layout/svg/renderer/src/cairo/nsSVGCairoCanvas.cpp b/mozilla/layout/svg/renderer/src/cairo/nsSVGCairoCanvas.cpp index 9192fd10b4c..954f0c476f9 100644 --- a/mozilla/layout/svg/renderer/src/cairo/nsSVGCairoCanvas.cpp +++ b/mozilla/layout/svg/renderer/src/cairo/nsSVGCairoCanvas.cpp @@ -721,10 +721,6 @@ nsSVGCairoCanvas::CompositeSurface(nsISVGRendererSurface *aSurface, cairo_save(mCR); cairo_translate(mCR, aX, aY); - PRUint32 width, height; - aSurface->GetWidth(&width); - aSurface->GetHeight(&height); - cairo_set_source_surface(mCR, cairoSurface->GetSurface(), 0.0, 0.0); cairo_paint_with_alpha(mCR, aOpacity); cairo_restore(mCR); @@ -732,6 +728,30 @@ nsSVGCairoCanvas::CompositeSurface(nsISVGRendererSurface *aSurface, return NS_OK; } +/** Implements void compositeSurfaceWithMask(in nsISVGRendererSurface surface, + in unsigned long x, + in unsigned long y, + in nsISVGRendererSurface mask); */ +NS_IMETHODIMP +nsSVGCairoCanvas::CompositeSurfaceWithMask(nsISVGRendererSurface *aSurface, + PRUint32 aX, PRUint32 aY, + nsISVGRendererSurface *aMask) +{ + nsCOMPtr cairoSurface = do_QueryInterface(aSurface); + nsCOMPtr maskSurface = do_QueryInterface(aMask); + if (!cairoSurface || !maskSurface) + return NS_ERROR_FAILURE; + + cairo_save(mCR); + cairo_translate(mCR, aX, aY); + + cairo_set_source_surface(mCR, cairoSurface->GetSurface(), 0.0, 0.0); + cairo_mask_surface(mCR, maskSurface->GetSurface(), 0.0, 0.0); + cairo_restore(mCR); + + return NS_OK; +} + /** Implements void compositeSurface(in nsISVGRendererSurface surface, in nsIDOMSVGMatrix canvasTM, in float opacity); */ @@ -768,10 +788,6 @@ nsSVGCairoCanvas::CompositeSurfaceMatrix(nsISVGRendererSurface *aSurface, cairo_matrix_t matrix = {m[0], m[1], m[2], m[3], m[4], m[5]}; cairo_transform(mCR, &matrix); - PRUint32 width, height; - aSurface->GetWidth(&width); - aSurface->GetHeight(&height); - cairo_set_source_surface(mCR, cairoSurface->GetSurface(), 0.0, 0.0); cairo_paint_with_alpha(mCR, aOpacity); cairo_restore(mCR); diff --git a/mozilla/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp b/mozilla/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp index 032ce88306c..2f5dbb7197d 100644 --- a/mozilla/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp +++ b/mozilla/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp @@ -277,20 +277,18 @@ nsSVGCairoPathGeometry::Render(nsISVGRendererCanvas *canvas) PRUint16 renderMode; canvas->GetRenderMode(&renderMode); - cairo_matrix_t matrix; - if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL) { - cairo_new_path(ctx); + cairo_new_path(ctx); - /* save/pop the state so we don't screw up the xform */ - cairo_save(ctx); - } else { - cairo_get_matrix(ctx, &matrix); - } + /* save/pop the state so we don't screw up the xform */ + cairo_save(ctx); GeneratePath(ctx, cairoCanvas); if (renderMode != nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL) { + + cairo_restore(ctx); + PRUint16 rule; mSource->GetClipRule(&rule); if (rule == nsISVGGeometrySource::FILL_RULE_EVENODD) @@ -298,7 +296,11 @@ nsSVGCairoPathGeometry::Render(nsISVGRendererCanvas *canvas) else cairo_set_fill_rule(ctx, CAIRO_FILL_RULE_WINDING); - cairo_set_matrix(ctx, &matrix); + if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_CLIP_MASK) { + cairo_set_antialias(ctx, CAIRO_ANTIALIAS_NONE); + cairo_set_source_rgba(ctx, 1.0f, 1.0f, 1.0f, 1.0f); + cairo_fill(ctx); + } return NS_OK; } diff --git a/mozilla/layout/svg/renderer/src/gdiplus/nsSVGGDIPlusCanvas.cpp b/mozilla/layout/svg/renderer/src/gdiplus/nsSVGGDIPlusCanvas.cpp index 5567323f37d..246bea4a7d9 100644 --- a/mozilla/layout/svg/renderer/src/gdiplus/nsSVGGDIPlusCanvas.cpp +++ b/mozilla/layout/svg/renderer/src/gdiplus/nsSVGGDIPlusCanvas.cpp @@ -485,6 +485,19 @@ nsSVGGDIPlusCanvas::CompositeSurface(nsISVGRendererSurface *aSurface, return NS_OK; } +/** Implements void compositeSurfaceWithMask(in nsISVGRendererSurface surface, + in unsigned long x, + in unsigned long y, + in nsISVGRendererSurface mask); */ +NS_IMETHODIMP +nsSVGGDIPlusCanvas::CompositeSurfaceWithMask(nsISVGRendererSurface *aSurface, + PRUint32 aX, PRUint32 aY, + nsISVGRendererSurface *aMask) +{ + // XXX + return NS_ERROR_NOT_IMPLEMENTED; +} + /** Implements void compositeSurface(in nsISVGRendererSurface surface, in nsIDOMSVGMatrix canvasTM, in float opacity); */ diff --git a/mozilla/layout/svg/renderer/src/libart/nsSVGLibartCanvas.cpp b/mozilla/layout/svg/renderer/src/libart/nsSVGLibartCanvas.cpp index 4517873e83a..56b334695c6 100644 --- a/mozilla/layout/svg/renderer/src/libart/nsSVGLibartCanvas.cpp +++ b/mozilla/layout/svg/renderer/src/libart/nsSVGLibartCanvas.cpp @@ -421,6 +421,19 @@ nsSVGLibartCanvas::CompositeSurface(nsISVGRendererSurface *aSurface, return NS_ERROR_NOT_IMPLEMENTED; } +/** Implements void compositeSurfaceWithMask(in nsISVGRendererSurface surface, + in unsigned long x, + in unsigned long y, + in nsISVGRendererSurface mask); */ +NS_IMETHODIMP +nsSVGLibartCanvas::CompositeSurfaceWithMask(nsISVGRendererSurface *aSurface, + PRUint32 aX, PRUint32 aY, + nsISVGRendererSurface *aMask) +{ + // XXX + return NS_ERROR_NOT_IMPLEMENTED; +} + /** Implements void compositeSurface(in nsISVGRendererSurface surface, in nsIDOMSVGMatrix canvasTM, in float opacity); */