Bug 316764 - implement <mask> and fix <clipPath> for multiple
overlapping children. r=scootermorris git-svn-id: svn://10.0.0.236/trunk@187897 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
b5bf49f861
commit
fe2017034e
@ -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")
|
||||
|
||||
@ -102,6 +102,7 @@ CPPSRCS = \
|
||||
nsSVGLengthList.cpp \
|
||||
nsSVGLineElement.cpp \
|
||||
nsSVGMarkerElement.cpp \
|
||||
nsSVGMaskElement.cpp \
|
||||
nsSVGMatrix.cpp \
|
||||
nsSVGMetadataElement.cpp \
|
||||
nsSVGNumber.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);
|
||||
|
||||
@ -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
|
||||
|
||||
258
mozilla/content/svg/content/src/nsSVGMaskElement.cpp
Normal file
258
mozilla/content/svg/content/src/nsSVGMaskElement.cpp
Normal file
@ -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<nsIDOMSVGAnimatedEnumeration> mMaskUnits;
|
||||
nsCOMPtr<nsIDOMSVGAnimatedEnumeration> mMaskContentUnits;
|
||||
nsCOMPtr<nsIDOMSVGAnimatedLength> mX;
|
||||
nsCOMPtr<nsIDOMSVGAnimatedLength> mY;
|
||||
nsCOMPtr<nsIDOMSVGAnimatedLength> mWidth;
|
||||
nsCOMPtr<nsIDOMSVGAnimatedLength> 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<nsISVGEnum> 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<nsISVGEnum> 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<nsISVGLength> 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<nsISVGLength> 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<nsISVGLength> 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<nsISVGLength> 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;
|
||||
}
|
||||
@ -85,6 +85,7 @@ XPIDLSRCS = \
|
||||
nsIDOMSVGLineElement.idl \
|
||||
nsIDOMSVGLocatable.idl \
|
||||
nsIDOMSVGMarkerElement.idl \
|
||||
nsIDOMSVGMaskElement.idl \
|
||||
nsIDOMSVGMatrix.idl \
|
||||
nsIDOMSVGMetadataElement.idl \
|
||||
nsIDOMSVGNumber.idl \
|
||||
|
||||
75
mozilla/dom/public/idl/svg/nsIDOMSVGMaskElement.idl
Normal file
75
mozilla/dom/public/idl/svg/nsIDOMSVGMaskElement.idl
Normal file
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -573,6 +573,7 @@ struct nsCSSSVG : public nsCSSStruct {
|
||||
nsCSSValue mMarkerEnd;
|
||||
nsCSSValue mMarkerMid;
|
||||
nsCSSValue mMarkerStart;
|
||||
nsCSSValue mMask;
|
||||
nsCSSValue mPointerEvents;
|
||||
nsCSSValue mShapeRendering;
|
||||
nsCSSValue mStopColor;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1340,6 +1340,7 @@ struct nsStyleSVGReset : public nsStyleStruct {
|
||||
nsStyleSVGPaint mStopColor; // [reset]
|
||||
nsCOMPtr<nsIURI> mClipPath; // [reset]
|
||||
nsCOMPtr<nsIURI> mFilter; // [reset]
|
||||
nsCOMPtr<nsIURI> mMask; // [reset]
|
||||
|
||||
float mStopOpacity; // [reset]
|
||||
|
||||
|
||||
@ -80,6 +80,7 @@ CPPSRCS = \
|
||||
nsSVGInnerSVGFrame.cpp \
|
||||
nsSVGLineFrame.cpp \
|
||||
nsSVGMarkerFrame.cpp \
|
||||
nsSVGMaskFrame.cpp \
|
||||
nsSVGOuterSVGFrame.cpp \
|
||||
nsSVGPathFrame.cpp \
|
||||
nsSVGPathGeometryFrame.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<nsIDOMSVGMatrix> aMatrix);
|
||||
|
||||
NS_IMETHOD ClipHitTest(nsISVGChildFrame* aParent,
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsIDOMSVGMatrix> mClipParentMatrix;
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
already_AddRefed<nsIDOMSVGMatrix> 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<nsIDOMSVGMatrix> 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
|
||||
{
|
||||
|
||||
@ -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<nsIDOMSVGMatrix> aMatrix);
|
||||
nsCOMPtr<nsIDOMSVGMatrix> aMatrix) = 0;
|
||||
|
||||
NS_IMETHOD ClipHitTest(nsISVGChildFrame* aParent,
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsIDOMSVGMatrix> mClipParentMatrix;
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
already_AddRefed<nsIDOMSVGMatrix> 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
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsSVGFilterFrame.h"
|
||||
#include "nsISVGValueUtils.h"
|
||||
#include <math.h>
|
||||
#include "nsSVGMaskFrame.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
@ -90,8 +90,6 @@ nsSVGGFrame::PaintSVG(nsISVGRendererCanvas* canvas,
|
||||
const nsRect& dirtyRectTwips,
|
||||
PRBool ignoreFilter)
|
||||
{
|
||||
nsCOMPtr<nsISVGRendererSurface> 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<nsISVGRendererSurface> clipMaskSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI) {
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsIDOMSVGMatrix> 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<nsISVGRenderer> 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<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsISVGRendererSurface> 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);
|
||||
|
||||
@ -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<nsISVGRendererSurface> clipMaskSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI) {
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsIDOMSVGMatrix> matrix;
|
||||
GetCanvasTM(getter_AddRefs(matrix));
|
||||
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for mask */
|
||||
|
||||
nsISVGMaskFrame *mask = nsnull;
|
||||
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsIDOMSVGMatrix> 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<nsISVGRendererSurface> 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;
|
||||
|
||||
@ -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<nsISVGRendererSurface> 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<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for mask */
|
||||
|
||||
nsISVGMaskFrame *mask = nsnull;
|
||||
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsISVGRendererSurface> 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
|
||||
|
||||
422
mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp
Normal file
422
mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp
Normal file
@ -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<nsIDOMSVGMatrix> 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<nsIDOMSVGAnimatedEnumeration> mMaskUnits;
|
||||
nsCOMPtr<nsIDOMSVGAnimatedEnumeration> mMaskContentUnits;
|
||||
nsCOMPtr<nsIDOMSVGLength> mX;
|
||||
nsCOMPtr<nsIDOMSVGLength> mY;
|
||||
nsCOMPtr<nsIDOMSVGLength> mWidth;
|
||||
nsCOMPtr<nsIDOMSVGLength> mHeight;
|
||||
|
||||
nsISVGChildFrame *mMaskParent;
|
||||
nsCOMPtr<nsIDOMSVGMatrix> mMaskParentMatrix;
|
||||
|
||||
// nsISVGContainerFrame interface:
|
||||
already_AddRefed<nsIDOMSVGMatrix> 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<nsIDOMSVGMaskElement> mask = do_QueryInterface(mContent);
|
||||
NS_ASSERTION(mask, "wrong content element");
|
||||
|
||||
{
|
||||
nsCOMPtr<nsIDOMSVGAnimatedLength> 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<nsIDOMSVGAnimatedLength> 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<nsIDOMSVGAnimatedLength> 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<nsIDOMSVGAnimatedLength> 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<nsIDOMSVGMatrix> aMatrix,
|
||||
float aOpacity)
|
||||
{
|
||||
nsRect dirty;
|
||||
|
||||
if (NS_FAILED(aCanvas->PushSurface(aSurface)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
{
|
||||
nsIFrame *frame;
|
||||
CallQueryInterface(aParent, &frame);
|
||||
nsCOMPtr<nsIContent> 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<nsIDOMSVGRect> 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<nsIDOMSVGMatrix>
|
||||
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<nsIDOMSVGMatrix> canvasTM = mMaskParentMatrix;
|
||||
|
||||
/* object bounding box? */
|
||||
PRUint16 units;
|
||||
nsCOMPtr<nsIDOMSVGMaskElement> path = do_QueryInterface(mContent);
|
||||
nsCOMPtr<nsIDOMSVGAnimatedEnumeration> aEnum;
|
||||
path->GetMaskContentUnits(getter_AddRefs(aEnum));
|
||||
aEnum->GetAnimVal(&units);
|
||||
|
||||
if (mMaskParent &&
|
||||
units == nsIDOMSVGMaskElement::SVG_MUNITS_OBJECTBOUNDINGBOX) {
|
||||
nsCOMPtr<nsIDOMSVGRect> 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<nsIDOMSVGMatrix> 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;
|
||||
}
|
||||
69
mozilla/layout/svg/base/src/nsSVGMaskFrame.h
Normal file
69
mozilla/layout/svg/base/src/nsSVGMaskFrame.h
Normal file
@ -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<nsIDOMSVGMatrix> 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
|
||||
@ -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<nsISVGRendererSurface> clipMaskSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mClipPath;
|
||||
if (aURI) {
|
||||
NS_GetSVGClipPathFrame(&clip, aURI, mContent);
|
||||
|
||||
if (clip) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsIDOMSVGMatrix> matrix;
|
||||
GetCanvasTM(getter_AddRefs(matrix));
|
||||
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for mask */
|
||||
|
||||
nsISVGMaskFrame *mask = nsnull;
|
||||
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsISVGRendererSurface> 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);
|
||||
|
||||
@ -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<nsISVGRendererSurface> 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<nsIDOMSVGMatrix> matrix = GetCanvasTM();
|
||||
clip->ClipPaint(canvas, clipMaskSurface, this, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for mask */
|
||||
|
||||
nsISVGMaskFrame *mask = nsnull;
|
||||
nsCOMPtr<nsISVGRendererSurface> maskSurface, maskedSurface;
|
||||
|
||||
aURI = GetStyleSVGReset()->mMask;
|
||||
if (aURI) {
|
||||
NS_GetSVGMaskFrame(&mask, aURI, mContent);
|
||||
|
||||
if (mask) {
|
||||
nsSVGUtils::GetSurface(outerSVGFrame, getter_AddRefs(maskSurface));
|
||||
|
||||
if (maskSurface) {
|
||||
nsCOMPtr<nsIDOMSVGMatrix> 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<nsISVGRendererSurface> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 <windows.h>
|
||||
@ -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<nsISVGRenderer> 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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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<nsISVGCairoSurface> cairoSurface = do_QueryInterface(aSurface);
|
||||
nsCOMPtr<nsISVGCairoSurface> 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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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); */
|
||||
|
||||
@ -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); */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user