Bug 326143 - Implement feFlood and feTurbulence filter elements.

Patch by tor and malex@cs.utexas.edu, r=tor, sr=roc
This commit is contained in:
tor%cs.brown.edu 2007-01-08 16:48:56 +00:00
parent 902b92ceb1
commit 5cce072b38
27 changed files with 859 additions and 38 deletions

View File

@ -901,6 +901,7 @@ GK_ATOM(animateMotion, "animateMotion")
GK_ATOM(animateTransform, "animateTransform")
GK_ATOM(arithmetic, "arithmetic")
GK_ATOM(atop, "atop")
GK_ATOM(baseFrequency, "baseFrequency")
GK_ATOM(baseline_shift, "baseline-shift")
GK_ATOM(clip_path, "clip-path")
GK_ATOM(clip_rule, "clip-rule")
@ -959,6 +960,8 @@ GK_ATOM(fill_rule, "fill-rule")
GK_ATOM(filter, "filter")
GK_ATOM(filterRes, "filterRes")
GK_ATOM(filterUnits, "filterUnits")
GK_ATOM(flood_color, "flood-color")
GK_ATOM(flood_opacity, "flood-opacity")
GK_ATOM(font_face, "font-face")
GK_ATOM(font_face_format, "font-face-format")
GK_ATOM(font_face_name, "font-face-name")
@ -973,6 +976,7 @@ GK_ATOM(font_variant, "font-variant")
#ifdef MOZ_SVG_FOREIGNOBJECT
GK_ATOM(foreignObject, "foreignObject")
#endif
GK_ATOM(fractalNoise, "fractalNoise")
GK_ATOM(fx, "fx")
GK_ATOM(fy, "fy")
GK_ATOM(g, "g")
@ -1016,6 +1020,8 @@ GK_ATOM(metadata, "metadata")
GK_ATOM(missingGlyph, "missingGlyph")
GK_ATOM(mm, "mm")
GK_ATOM(mpath, "mpath")
GK_ATOM(noStitch, "noStitch")
GK_ATOM(numOctaves, "numOctaves")
GK_ATOM(multiply, "multiply")
GK_ATOM(objectBoundingBox, "objectBoundingBox")
GK_ATOM(offset, "offset")
@ -1060,6 +1066,7 @@ GK_ATOM(rx, "rx")
GK_ATOM(ry, "ry")
GK_ATOM(scale, "scale")
GK_ATOM(set, "set")
GK_ATOM(seed, "seed")
GK_ATOM(shape_rendering, "shape-rendering")
GK_ATOM(skewX, "skewX")
GK_ATOM(skewY, "skewY")
@ -1068,6 +1075,8 @@ GK_ATOM(spacing, "spacing")
GK_ATOM(spreadMethod, "spreadMethod")
GK_ATOM(startOffset, "startOffset")
GK_ATOM(stdDeviation, "stdDeviation")
GK_ATOM(stitch, "stitch")
GK_ATOM(stitchTiles, "stitchTiles")
GK_ATOM(stop_color, "stop-color")
GK_ATOM(stop_opacity, "stop-opacity")
GK_ATOM(stroke, "stroke")
@ -1090,6 +1099,7 @@ GK_ATOM(text_rendering, "text-rendering")
GK_ATOM(textPath, "textPath")
GK_ATOM(tref, "tref")
GK_ATOM(tspan, "tspan")
GK_ATOM(turbulence, "turbulence")
GK_ATOM(unicode_bidi, "unicode-bidi")
GK_ATOM(userSpaceOnUse, "userSpaceOnUse")
GK_ATOM(view, "view")

View File

@ -113,7 +113,8 @@ nsSVGDefsElement::IsAttributeMapped(const nsIAtom* name) const
sFontSpecificationMap,
sGradientStopMap,
sMarkersMap,
sViewportsMap
sViewportsMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

View File

@ -496,6 +496,13 @@ nsSVGElement::sColorMap[] = {
{ nsnull }
};
// PresentationAttributes-feFlood
/* static */ const nsGenericElement::MappedAttributeEntry
nsSVGElement::sFEFloodMap[] = {
{ &nsGkAtoms::flood_color },
{ &nsGkAtoms::flood_opacity },
{ nsnull }
};
//----------------------------------------------------------------------
// nsIDOMNode methods

View File

@ -98,6 +98,7 @@ public:
static const MappedAttributeEntry sViewportsMap[];
static const MappedAttributeEntry sMarkersMap[];
static const MappedAttributeEntry sColorMap[];
static const MappedAttributeEntry sFEFloodMap[];
// nsIDOMNode
NS_IMETHOD IsSupported(const nsAString& aFeature, const nsAString& aVersion, PRBool* aReturn);

View File

@ -134,6 +134,10 @@ nsresult
NS_NewSVGPatternElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGMaskElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGFEFloodElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGFETurbulenceElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
@ -232,15 +236,17 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
return NS_NewSVGFEMorphologyElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feOffset)
return NS_NewSVGFEOffsetElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feFlood)
return NS_NewSVGFEFloodElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feTurbulence)
return NS_NewSVGFETurbulenceElement(aResult, aNodeInfo);
if (name == nsGkAtoms::feColorMatrix ||
name == nsGkAtoms::feConvolveMatrix ||
name == nsGkAtoms::feDiffuseLighting ||
name == nsGkAtoms::feDisplacementMap ||
name == nsGkAtoms::feFlood ||
name == nsGkAtoms::feImage ||
name == nsGkAtoms::feSpecularLighting ||
name == nsGkAtoms::feTile ||
name == nsGkAtoms::feTurbulence)
name == nsGkAtoms::feTile)
return NS_NewSVGFEUnimplementedMOZElement(aResult, aNodeInfo);
if (name == nsGkAtoms::pattern)
return NS_NewSVGPatternElement(aResult, aNodeInfo);

View File

@ -270,7 +270,8 @@ nsSVGFilterElement::IsAttributeMapped(const nsIAtom* name) const
sGradientStopMap,
sMarkersMap,
sTextContentElementsMap,
sViewportsMap
sViewportsMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
nsSVGGraphicElementBase::IsAttributeMapped(name);

View File

@ -55,6 +55,10 @@
#include "nsSVGFilters.h"
#include "nsSVGUtils.h"
#include "prdtoa.h"
#include "nsStyleContext.h"
#include "nsIDocument.h"
#include "nsIFrame.h"
#include "nsSVGAnimatedInteger.h"
nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] =
{
@ -232,13 +236,12 @@ nsSVGFE::GetLengthInfo()
//--------------------Filter Resource-----------------------
/**
* nsSVGFilterResource provides functionality for obtaining and releasing
* source and target images. Images are automatically released when the
* Filter Resource is destroyed, but methods to manually release images are
* provided so that multiple source images may be used for a single filter.
* PLEASE NOTE that nsSVGFilterResource should ONLY be used on the stack because
* it has nsAutoString members
*/
* nsSVGFilterResource provides functionality for managing images used by
* filters. PLEASE NOTE that nsSVGFilterResource should ONLY be used on the
* stack because it has nsAutoString member. Also note that ReleaseTarget,
* and thus the deconstructor, depends on AcquireSourceImage having been called
* one or more times before it is executed.
*/
class nsSVGFilterResource
{
@ -247,8 +250,7 @@ public:
~nsSVGFilterResource();
/*
* Acquiring a source image will lock that image
* and prepare its data to be read.
* Acquires a source image for reading
* aIn: the name of the filter primitive to use as the source
* aFilter: the filter that is calling AcquireImage
* aSourceData: out parameter - the image data of the filter primitive
@ -260,10 +262,10 @@ public:
nsSVGFE* aFilter, PRUint8** aSourceData,
cairo_surface_t** aSurface = 0);
/*
* Acquiring a target image will create and lock
* a new surface to be used as the target image.
* aResult: the name by which the resulting filter primitive image will be
* identified
* Acquiring a target image will create a new surface to be used as the
* target image.
* aResult: the name by which the resulting filter primitive image will
* be identified
* aTargetData: out parameter - the resulting filter primitive image data
* aSurface: optional out parameter - the resulting filter primitive image
* surface
@ -298,9 +300,6 @@ public:
}
private:
/*
* If the target image exists then it is unlocked and FixupTarget() is called
*/
void ReleaseTarget();
/*
@ -2479,6 +2478,711 @@ nsSVGFEOffsetElement::GetNumberInfo()
NS_ARRAY_LENGTH(sNumberInfo));
}
//---------------------Flood------------------------
typedef nsSVGFE nsSVGFEFloodElementBase;
class nsSVGFEFloodElement : public nsSVGFEFloodElementBase,
public nsIDOMSVGFEFloodElement,
public nsISVGFilter
{
protected:
friend nsresult NS_NewSVGFEFloodElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGFEFloodElement(nsINodeInfo* aNodeInfo);
nsresult Init();
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
// FE Base
NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEFloodElementBase::)
// nsISVGFilter
NS_IMETHOD Filter(nsSVGFilterInstance *instance);
NS_IMETHOD GetRequirements(PRUint32 *aRequirements);
// Flood
NS_DECL_NSIDOMSVGFEFLOODELEMENT
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEFloodElementBase::)
NS_FORWARD_NSIDOMNODE(nsSVGFEFloodElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGFEFloodElementBase::)
// nsIContent interface
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
nsCOMPtr<nsIDOMSVGAnimatedString> mIn1;
};
NS_IMPL_NS_NEW_SVG_ELEMENT(FEFlood)
//----------------------------------------------------------------------
// nsISupports methods
NS_IMPL_ADDREF_INHERITED(nsSVGFEFloodElement,nsSVGFEFloodElementBase)
NS_IMPL_RELEASE_INHERITED(nsSVGFEFloodElement,nsSVGFEFloodElementBase)
NS_INTERFACE_MAP_BEGIN(nsSVGFEFloodElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFEFloodElement)
NS_INTERFACE_MAP_ENTRY(nsISVGFilter)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFEFloodElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGFEFloodElementBase)
//----------------------------------------------------------------------
// Implementation
nsSVGFEFloodElement::nsSVGFEFloodElement(nsINodeInfo *aNodeInfo)
: nsSVGFEFloodElementBase(aNodeInfo)
{
}
nsresult
nsSVGFEFloodElement::Init()
{
nsresult rv = nsSVGFEFloodElementBase::Init();
NS_ENSURE_SUCCESS(rv,rv);
// DOM property: in1 , #IMPLIED attrib: in
{
rv = NS_NewSVGAnimatedString(getter_AddRefs(mIn1));
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::in, mIn1);
NS_ENSURE_SUCCESS(rv,rv);
}
return rv;
}
//----------------------------------------------------------------------
// nsIDOMNode methods
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEFloodElement)
//----------------------------------------------------------------------
// nsIDOMSVGFEFloodElement methods
/* readonly attribute nsIDOMSVGAnimatedString in1; */
NS_IMETHODIMP nsSVGFEFloodElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
{
*aIn = mIn1;
NS_IF_ADDREF(*aIn);
return NS_OK;
}
NS_IMETHODIMP
nsSVGFEFloodElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
cairo_surface_t *targetSurface;
nsSVGFilterResource fr(instance);
rv = fr.AcquireSourceImage(mIn1, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
rv = fr.AcquireTargetImage(mResult, &targetData, &targetSurface);
NS_ENSURE_SUCCESS(rv, rv);
nsRect rect = fr.GetRect();
nsIDocument* doc = GetCurrentDoc();
if (!doc) return NS_ERROR_FAILURE;
nsIPresShell *presShell = doc->GetShellAt(0);
NS_ASSERTION(presShell, "need presShell to suspend redraw");
if (!presShell) return NS_ERROR_FAILURE;
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
nsStyleContext* style = frame->GetStyleContext();
nscolor floodColor = style->GetStyleSVG()->mFloodColor.mPaint.mColor;
float floodOpacity = style->GetStyleSVG()->mFloodOpacity;
PRUint8 r, g, b, a;
a = PRUint8(floodOpacity * 255);
r = (PRUint32(NS_GET_R(floodColor)) * a) / 255;
g = (PRUint32(NS_GET_G(floodColor)) * a) / 255;
b = (PRUint32(NS_GET_B(floodColor)) * a) / 255;
cairo_t *cr = cairo_create(targetSurface);
if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {
cairo_destroy(cr);
return NS_ERROR_FAILURE;
}
cairo_set_source_rgba(cr, r, g, b, a);
cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height);
cairo_fill(cr);
cairo_destroy(cr);
return NS_OK;
}
NS_IMETHODIMP
nsSVGFEFloodElement::GetRequirements(PRUint32 *aRequirements)
{
*aRequirements = CheckStandardNames(mIn1);
return NS_OK;
}
//----------------------------------------------------------------------
// nsIContent methods
NS_IMETHODIMP_(PRBool)
nsSVGFEFloodElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
nsSVGFEFloodElementBase::IsAttributeMapped(name);
}
//---------------------Turbulence------------------------
typedef nsSVGFE nsSVGFETurbulenceElementBase;
class nsSVGFETurbulenceElement : public nsSVGFETurbulenceElementBase,
public nsIDOMSVGFETurbulenceElement,
public nsISVGFilter
{
protected:
friend nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGFETurbulenceElement(nsINodeInfo* aNodeInfo);
nsresult Init();
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
// FE Base
NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::)
// nsISVGFilter
NS_IMETHOD Filter(nsSVGFilterInstance *instance);
NS_IMETHOD GetRequirements(PRUint32 *aRequirements);
// Turbulence
NS_DECL_NSIDOMSVGFETURBULENCEELEMENT
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::)
NS_FORWARD_NSIDOMNODE(nsSVGFETurbulenceElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGFETurbulenceElementBase::)
virtual PRBool ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
virtual NumberAttributesInfo GetNumberInfo();
enum { BASE_FREQ_X, BASE_FREQ_Y, SEED}; // floating point seed?!
nsSVGNumber2 mNumberAttributes[3];
static NumberInfo sNumberInfo[3];
nsCOMPtr<nsIDOMSVGAnimatedInteger> mNumOctaves;
nsCOMPtr<nsIDOMSVGAnimatedEnumeration> mStitchTiles;
nsCOMPtr<nsIDOMSVGAnimatedEnumeration> mType;
private:
/* The turbulence calculation code is an adapted version of what
appears in the SVG 1.1 specification:
http://www.w3.org/TR/SVG11/filters.html#feTurbulence
*/
/* Produces results in the range [1, 2**31 - 2].
Algorithm is: r = (a * r) mod m
where a = 16807 and m = 2**31 - 1 = 2147483647
See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
To test: the algorithm should produce the result 1043618065
as the 10,000th generated number if the original seed is 1.
*/
#define RAND_M 2147483647 /* 2**31 - 1 */
#define RAND_A 16807 /* 7**5; primitive root of m */
#define RAND_Q 127773 /* m / a */
#define RAND_R 2836 /* m % a */
PRInt32 SetupSeed(PRInt32 aSeed) {
if (aSeed <= 0)
aSeed = -(aSeed % (RAND_M - 1)) + 1;
if (aSeed > RAND_M - 1)
aSeed = RAND_M - 1;
return aSeed;
}
PRUint32 Random(PRUint32 aSeed) {
PRInt32 result = RAND_A * (aSeed % RAND_Q) - RAND_R * (aSeed / RAND_Q);
if (result <= 0)
result += RAND_M;
return result;
}
#undef RAND_M
#undef RAND_A
#undef RAND_Q
#undef RAND_R
const static int sBSize = 0x100;
const static int sBM = 0xff;
const static int sPerlinN = 0x1000;
const static int sNP = 12; /* 2^PerlinN */
const static int sNM = 0xfff;
PRInt32 mLatticeSelector[sBSize + sBSize + 2];
double mGradient[4][sBSize + sBSize + 2][2];
struct StitchInfo {
int mWidth; // How much to subtract to wrap for stitching.
int mHeight;
int mWrapX; // Minimum value to wrap.
int mWrapY;
};
void Init(PRInt32 aSeed);
double Noise2(int aColorChannel, double aVec[2], StitchInfo *aStitchInfo);
double
Turbulence(int aColorChannel, double *aPoint, double aBaseFreqX,
double aBaseFreqY, int aNumOctaves, PRBool aFractalSum,
PRBool aDoStitching, double aTileX, double aTileY,
double aTileWidth, double aTileHeight);
};
nsSVGElement::NumberInfo nsSVGFETurbulenceElement::sNumberInfo[3] =
{
{ &nsGkAtoms::baseFrequency, 0 },
{ &nsGkAtoms::baseFrequency, 0 },
{ &nsGkAtoms::seed, 0 }
};
NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence)
//----------------------------------------------------------------------
// nsISupports methods
NS_IMPL_ADDREF_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
NS_IMPL_RELEASE_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
NS_INTERFACE_MAP_BEGIN(nsSVGFETurbulenceElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFETurbulenceElement)
NS_INTERFACE_MAP_ENTRY(nsISVGFilter)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGFETurbulenceElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGFETurbulenceElementBase)
//----------------------------------------------------------------------
// Implementation
nsSVGFETurbulenceElement::nsSVGFETurbulenceElement(nsINodeInfo *aNodeInfo)
: nsSVGFETurbulenceElementBase(aNodeInfo)
{
}
nsresult
nsSVGFETurbulenceElement::Init()
{
nsresult rv = nsSVGFETurbulenceElementBase::Init();
NS_ENSURE_SUCCESS(rv,rv);
// enumeration mappings
static struct nsSVGEnumMapping gTurbulenceTypes[] = {
{&nsGkAtoms::fractalNoise,
nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_FRACTALNOISE},
{&nsGkAtoms::turbulence,
nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE},
{nsnull, 0}
};
static struct nsSVGEnumMapping gStitchTypes[] = {
{&nsGkAtoms::stitch,
nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH},
{&nsGkAtoms::noStitch,
nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH},
{nsnull, 0}
};
// Create mapped properties:
// DOM property: stitchTiles, #IMPLIED attrib: stitchTiles
{
nsCOMPtr<nsISVGEnum> stitch;
rv = NS_NewSVGEnum(getter_AddRefs(stitch),
nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH,
gStitchTypes);
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mStitchTiles), stitch);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::stitchTiles, mStitchTiles);
NS_ENSURE_SUCCESS(rv,rv);
}
// DOM property: type, #IMPLIED attrib: type
{
nsCOMPtr<nsISVGEnum> types;
rv = NS_NewSVGEnum(getter_AddRefs(types),
nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE,
gTurbulenceTypes);
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mType), types);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::type, mType);
NS_ENSURE_SUCCESS(rv,rv);
}
// DOM property: numOctaves , #IMPLIED attrib: numOctaves
{
rv = NS_NewSVGAnimatedInteger(getter_AddRefs(mNumOctaves), 1);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::numOctaves, mNumOctaves);
NS_ENSURE_SUCCESS(rv,rv);
}
return rv;
}
//----------------------------------------------------------------------
// nsIDOMNode methods
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETurbulenceElement)
//----------------------------------------------------------------------
// nsIDOMSVGFETurbulenceElement methods
/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX; */
NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyX(nsIDOMSVGAnimatedNumber * *aX)
{
return mNumberAttributes[BASE_FREQ_X].ToDOMAnimatedNumber(aX, this);
}
/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY; */
NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyY(nsIDOMSVGAnimatedNumber * *aY)
{
return mNumberAttributes[BASE_FREQ_Y].ToDOMAnimatedNumber(aY, this);
}
/* readonly attribute nsIDOMSVGAnimatedInteger numOctaves; */
NS_IMETHODIMP nsSVGFETurbulenceElement::GetNumOctaves(nsIDOMSVGAnimatedInteger * *aNum)
{
*aNum = mNumOctaves;
NS_IF_ADDREF(*aNum);
return NS_OK;
}
/* readonly attribute nsIDOMSVGAnimatedNumber seed; */
NS_IMETHODIMP nsSVGFETurbulenceElement::GetSeed(nsIDOMSVGAnimatedNumber * *aSeed)
{
return mNumberAttributes[SEED].ToDOMAnimatedNumber(aSeed, this);
}
/* readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles; */
NS_IMETHODIMP nsSVGFETurbulenceElement::GetStitchTiles(nsIDOMSVGAnimatedEnumeration * *aStitch)
{
*aStitch = mStitchTiles;
NS_IF_ADDREF(*aStitch);
return NS_OK;
}
/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
NS_IMETHODIMP nsSVGFETurbulenceElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
{
*aType = mType;
NS_IF_ADDREF(*aType);
return NS_OK;
}
PRBool
nsSVGFETurbulenceElement::ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aName == nsGkAtoms::baseFrequency && aNameSpaceID == kNameSpaceID_None) {
return ScanDualValueAttribute(aValue, nsGkAtoms::baseFrequency,
&mNumberAttributes[BASE_FREQ_X],
&mNumberAttributes[BASE_FREQ_Y],
&sNumberInfo[BASE_FREQ_X],
&sNumberInfo[BASE_FREQ_Y],
aResult);
}
return nsSVGFETurbulenceElementBase::ParseAttribute(aNameSpaceID, aName,
aValue, aResult);
}
NS_IMETHODIMP
nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
nsSVGFilterResource fr(instance);
nsIDOMSVGAnimatedString* sourceGraphic = nsnull;
rv = NS_NewSVGAnimatedString(&sourceGraphic);
NS_ENSURE_SUCCESS(rv, rv);
rv = fr.AcquireSourceImage(sourceGraphic, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
rv = fr.AcquireTargetImage(mResult, &targetData);
NS_ENSURE_SUCCESS(rv, rv);
nsRect rect = fr.GetRect();
#ifdef DEBUG_tor
fprintf(stderr, "FILTER TURBULENCE rect: %d,%d %dx%d\n",
rect.x, rect.y, rect.width, rect.height);
#endif
float fX, fY, seed;
PRInt32 octaves;
PRUint16 type, stitch;
GetAnimatedNumberValues(&fX, &fY, &seed, nsnull);
mNumOctaves->GetAnimVal(&octaves);
mStitchTiles->GetAnimVal(&stitch);
mType->GetAnimVal(&type);
Init((PRInt32)seed);
float filterX, filterY, filterWidth, filterHeight;
instance->GetFilterBox(&filterX, &filterY, &filterWidth, &filterHeight);
PRBool doStitch = PR_FALSE;
if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) {
doStitch = PR_TRUE;
float lowFreq, hiFreq;
lowFreq = floor(filterWidth * fX) / filterWidth;
hiFreq = ceil(filterWidth * fX) / filterWidth;
if (fX / lowFreq < hiFreq / fX)
fX = lowFreq;
else
fX = hiFreq;
lowFreq = floor(filterHeight * fY) / filterHeight;
hiFreq = ceil(filterHeight * fY) / filterHeight;
if (fY / lowFreq < hiFreq / fY)
fY = lowFreq;
else
fY = hiFreq;
}
PRInt32 stride = fr.GetDataStride();
for (PRInt32 y = rect.y; y < rect.y + rect.height; y++) {
for (PRInt32 x = rect.x; x < rect.x + rect.width; x++) {
double point[2];
point[0] = filterX + (filterWidth * x ) / (rect.width - 1);
point[1] = filterY + (filterHeight * y) / (rect.height - 1);
float col[4];
if (type == nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE) {
for (int i = 0; i < 4; i++)
col[i] = Turbulence(i, point, fX, fY, octaves, PR_FALSE,
doStitch, filterX, filterY, filterWidth, filterHeight) * 255;
} else {
for (int i = 0; i < 4; i++)
col[i] = (Turbulence(i, point, fX, fY, octaves, PR_TRUE,
doStitch, filterX, filterY, filterWidth, filterHeight) * 255 + 255) / 2;
}
for (int i = 0; i < 4; i++) {
col[i] = PR_MIN(col[i], 255);
col[i] = PR_MAX(col[i], 0);
}
PRUint8 r, g, b, a;
a = PRUint8(col[3]);
FAST_DIVIDE_BY_255(r, unsigned(col[0]) * a);
FAST_DIVIDE_BY_255(g, unsigned(col[1]) * a);
FAST_DIVIDE_BY_255(b, unsigned(col[2]) * a);
targetData[y * stride + 4 * x ] = b;
targetData[y * stride + 4 * x + 1] = g;
targetData[y * stride + 4 * x + 2] = r;
targetData[y * stride + 4 * x + 3] = a;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsSVGFETurbulenceElement::GetRequirements(PRUint32 *aRequirements)
{
*aRequirements = 0;
return NS_OK;
}
void
nsSVGFETurbulenceElement::Init(PRInt32 aSeed)
{
double s;
int i, j, k;
aSeed = SetupSeed(aSeed);
for (k = 0; k < 4; k++) {
for (i = 0; i < sBSize; i++) {
mLatticeSelector[i] = i;
for (j = 0; j < 2; j++) {
mGradient[k][i][j] =
(double) (((aSeed =
Random(aSeed)) % (sBSize + sBSize)) - sBSize) / sBSize;
}
s = double (sqrt
(mGradient[k][i][0] * mGradient[k][i][0] +
mGradient[k][i][1] * mGradient[k][i][1]));
mGradient[k][i][0] /= s;
mGradient[k][i][1] /= s;
}
}
while (--i) {
k = mLatticeSelector[i];
mLatticeSelector[i] = mLatticeSelector[j =
(aSeed =
Random(aSeed)) % sBSize];
mLatticeSelector[j] = k;
}
for (i = 0; i < sBSize + 2; i++) {
mLatticeSelector[sBSize + i] = mLatticeSelector[i];
for (k = 0; k < 4; k++)
for (j = 0; j < 2; j++)
mGradient[k][sBSize + i][j] = mGradient[k][i][j];
}
}
#define S_CURVE(t) ( t * t * (3. - 2. * t) )
#define LERP(t, a, b) ( a + t * (b - a) )
double
nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2],
StitchInfo *aStitchInfo)
{
int bx0, bx1, by0, by1, b00, b10, b01, b11;
double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
register long i, j;
t = aVec[0] + sPerlinN;
bx0 = (int) t;
bx1 = bx0 + 1;
rx0 = t - (int) t;
rx1 = rx0 - 1.0f;
t = aVec[1] + sPerlinN;
by0 = (int) t;
by1 = by0 + 1;
ry0 = t - (int) t;
ry1 = ry0 - 1.0f;
// If stitching, adjust lattice points accordingly.
if (aStitchInfo != NULL) {
if (bx0 >= aStitchInfo->mWrapX)
bx0 -= aStitchInfo->mWidth;
if (bx1 >= aStitchInfo->mWrapX)
bx1 -= aStitchInfo->mWidth;
if (by0 >= aStitchInfo->mWrapY)
by0 -= aStitchInfo->mHeight;
if (by1 >= aStitchInfo->mWrapY)
by1 -= aStitchInfo->mHeight;
}
bx0 &= sBM;
bx1 &= sBM;
by0 &= sBM;
by1 &= sBM;
i = mLatticeSelector[bx0];
j = mLatticeSelector[bx1];
b00 = mLatticeSelector[i + by0];
b10 = mLatticeSelector[j + by0];
b01 = mLatticeSelector[i + by1];
b11 = mLatticeSelector[j + by1];
sx = double (S_CURVE(rx0));
sy = double (S_CURVE(ry0));
q = mGradient[aColorChannel][b00];
u = rx0 * q[0] + ry0 * q[1];
q = mGradient[aColorChannel][b10];
v = rx1 * q[0] + ry0 * q[1];
a = LERP(sx, u, v);
q = mGradient[aColorChannel][b01];
u = rx0 * q[0] + ry1 * q[1];
q = mGradient[aColorChannel][b11];
v = rx1 * q[0] + ry1 * q[1];
b = LERP(sx, u, v);
return LERP(sy, a, b);
}
#undef S_CURVE
#undef LERP
double
nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint,
double aBaseFreqX, double aBaseFreqY,
int aNumOctaves, PRBool aFractalSum,
PRBool aDoStitching,
double aTileX, double aTileY,
double aTileWidth, double aTileHeight)
{
StitchInfo stitch;
StitchInfo *stitchInfo = NULL; // Not stitching when NULL.
// Adjust the base frequencies if necessary for stitching.
if (aDoStitching) {
// When stitching tiled turbulence, the frequencies must be adjusted
// so that the tile borders will be continuous.
if (aBaseFreqX != 0.0) {
double loFreq = double (floor(aTileWidth * aBaseFreqX)) / aTileWidth;
double hiFreq = double (ceil(aTileWidth * aBaseFreqX)) / aTileWidth;
if (aBaseFreqX / loFreq < hiFreq / aBaseFreqX)
aBaseFreqX = loFreq;
else
aBaseFreqX = hiFreq;
}
if (aBaseFreqY != 0.0) {
double loFreq = double (floor(aTileHeight * aBaseFreqY)) / aTileHeight;
double hiFreq = double (ceil(aTileHeight * aBaseFreqY)) / aTileHeight;
if (aBaseFreqY / loFreq < hiFreq / aBaseFreqY)
aBaseFreqY = loFreq;
else
aBaseFreqY = hiFreq;
}
// Set up initial stitch values.
stitchInfo = &stitch;
stitch.mWidth = int (aTileWidth * aBaseFreqX + 0.5f);
stitch.mWrapX = int (aTileX * aBaseFreqX + sPerlinN + stitch.mWidth);
stitch.mHeight = int (aTileHeight * aBaseFreqY + 0.5f);
stitch.mWrapY = int (aTileY * aBaseFreqY + sPerlinN + stitch.mHeight);
}
double sum = 0.0f;
double vec[2];
vec[0] = aPoint[0] * aBaseFreqX;
vec[1] = aPoint[1] * aBaseFreqY;
double ratio = 1;
for (int octave = 0; octave < aNumOctaves; octave++) {
if (aFractalSum)
sum += double (Noise2(aColorChannel, vec, stitchInfo) / ratio);
else
sum += double (fabs(Noise2(aColorChannel, vec, stitchInfo)) / ratio);
vec[0] *= 2;
vec[1] *= 2;
ratio *= 2;
if (stitchInfo != NULL) {
// Update stitch values. Subtracting sPerlinN before the multiplication
// and adding it afterward simplifies to subtracting it once.
stitch.mWidth *= 2;
stitch.mWrapX = 2 * stitch.mWrapX - sPerlinN;
stitch.mHeight *= 2;
stitch.mWrapY = 2 * stitch.mWrapY - sPerlinN;
}
}
return sum;
}
//----------------------------------------------------------------------
// nsSVGElement methods
nsSVGElement::NumberAttributesInfo
nsSVGFETurbulenceElement::GetNumberInfo()
{
return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
NS_ARRAY_LENGTH(sNumberInfo));
}
//---------------------Morphology------------------------
typedef nsSVGFE nsSVGFEMorphologyElementBase;

View File

@ -117,7 +117,8 @@ nsSVGForeignObjectElement::IsAttributeMapped(const nsIAtom* name) const
sGradientStopMap,
sMarkersMap,
sTextContentElementsMap,
sViewportsMap
sViewportsMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

View File

@ -113,7 +113,8 @@ nsSVGGElement::IsAttributeMapped(const nsIAtom* name) const
static const MappedAttributeEntry* const map[] = {
sTextContentElementsMap,
sFontSpecificationMap,
sColorMap
sColorMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

View File

@ -293,7 +293,8 @@ nsSVGMarkerElement::IsAttributeMapped(const nsIAtom* name) const
sGradientStopMap,
sMarkersMap,
sTextContentElementsMap,
sViewportsMap
sViewportsMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

View File

@ -187,7 +187,8 @@ nsSVGMaskElement::IsAttributeMapped(const nsIAtom* name) const
sGradientStopMap,
sMarkersMap,
sTextContentElementsMap,
sViewportsMap
sViewportsMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

View File

@ -283,7 +283,8 @@ nsSVGPatternElement::IsAttributeMapped(const nsIAtom* name) const
sGradientStopMap,
sMarkersMap,
sTextContentElementsMap,
sViewportsMap
sViewportsMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

View File

@ -1119,7 +1119,8 @@ nsSVGSVGElement::IsAttributeMapped(const nsIAtom* name) const
sGradientStopMap,
sViewportsMap,
sMarkersMap,
sColorMap
sColorMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

View File

@ -177,7 +177,8 @@ nsSVGSymbolElement::IsAttributeMapped(const nsIAtom* name) const
sGradientStopMap,
sMarkersMap,
sTextContentElementsMap,
sViewportsMap
sViewportsMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

View File

@ -581,7 +581,8 @@ nsSVGUseElement::IsAttributeMapped(const nsIAtom* name) const
sGradientStopMap,
sMarkersMap,
sTextContentElementsMap,
sViewportsMap
sViewportsMap,
sFEFloodMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

View File

@ -42,6 +42,7 @@ interface nsIDOMSVGAnimatedString;
interface nsIDOMSVGAnimatedNumber;
interface nsIDOMSVGAnimatedEnumeration;
interface nsIDOMSVGAnimatedNumberList;
interface nsIDOMSVGAnimatedInteger;
[scriptable, uuid(ab68567a-b830-4c46-9f2f-a28513a9e980)]
interface nsIDOMSVGFilterPrimitiveStandardAttributes : nsIDOMSVGElement
@ -167,6 +168,32 @@ interface nsIDOMSVGFEOffsetElement : nsIDOMSVGFilterPrimitiveStandardAttributes
readonly attribute nsIDOMSVGAnimatedNumber dy;
};
[scriptable, uuid(4d507655-08c4-4726-8887-308a18ebbf2b)]
interface nsIDOMSVGFEFloodElement : nsIDOMSVGFilterPrimitiveStandardAttributes
{
readonly attribute nsIDOMSVGAnimatedString in1;
};
[scriptable, uuid(77bc4d70-0d49-4c81-b7a7-7432f0fe3e04)]
interface nsIDOMSVGFETurbulenceElement : nsIDOMSVGFilterPrimitiveStandardAttributes
{
// Turbulence Types
const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN = 0;
const unsigned short SVG_TURBULENCE_TYPE_FRACTALNOISE = 1;
const unsigned short SVG_TURBULENCE_TYPE_TURBULENCE = 2;
// Stitch Options
const unsigned short SVG_STITCHTYPE_UNKNOWN = 0;
const unsigned short SVG_STITCHTYPE_STITCH = 1;
const unsigned short SVG_STITCHTYPE_NOSTITCH = 2;
readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX;
readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY;
readonly attribute nsIDOMSVGAnimatedInteger numOctaves;
readonly attribute nsIDOMSVGAnimatedNumber seed;
readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles;
readonly attribute nsIDOMSVGAnimatedEnumeration type;
};
[scriptable, uuid(16154319-FB5F-4473-B360-5065B6096D33)]
interface nsIDOMSVGFEMorphologyElement : nsIDOMSVGFilterPrimitiveStandardAttributes
{

View File

@ -247,6 +247,7 @@ enum nsDOMClassInfoID {
eDOMClassInfo_SVGFEBlendElement_id,
eDOMClassInfo_SVGFEComponentTransferElement_id,
eDOMClassInfo_SVGFECompositeElement_id,
eDOMClassInfo_SVGFEFloodElement_id,
eDOMClassInfo_SVGFEFuncAElement_id,
eDOMClassInfo_SVGFEFuncBElement_id,
eDOMClassInfo_SVGFEFuncGElement_id,
@ -256,6 +257,7 @@ enum nsDOMClassInfoID {
eDOMClassInfo_SVGFEMergeNodeElement_id,
eDOMClassInfo_SVGFEMorphologyElement_id,
eDOMClassInfo_SVGFEOffsetElement_id,
eDOMClassInfo_SVGFETurbulenceElement_id,
eDOMClassInfo_SVGFEUnimplementedMOZElement_id,
eDOMClassInfo_SVGFilterElement_id,
eDOMClassInfo_SVGGElement_id,

View File

@ -902,6 +902,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFECompositeElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEFloodElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEFuncAElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEFuncBElement, nsElementSH,
@ -920,6 +922,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEOffsetElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFETurbulenceElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFEUnimplementedMOZElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGFilterElement, nsElementSH,
@ -2576,7 +2580,14 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGFEFloodElement, nsIDOMSVGFEFloodElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEFloodElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGFEFuncAElement, nsIDOMSVGFEFuncAElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEFuncAElement)
@ -2631,6 +2642,13 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGFETurbulenceElement, nsIDOMSVGFETurbulenceElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFETurbulenceElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGFEUnimplementedMOZElement, nsIDOMSVGFEUnimplementedMOZElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEUnimplementedMOZElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)

View File

@ -4521,6 +4521,10 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode,
nsCSSProps::kFillRuleKTable);
case eCSSProperty_filter:
return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull);
case eCSSProperty_flood_color:
return ParseVariant(aErrorCode, aValue, VARIANT_HC, nsnull);
case eCSSProperty_flood_opacity:
return ParseVariant(aErrorCode, aValue, VARIANT_HN, nsnull);
case eCSSProperty_marker_end:
case eCSSProperty_marker_mid:
case eCSSProperty_marker_start:

View File

@ -476,6 +476,8 @@ CSS_PROP_SVG(fill, fill, Fill, SVG, mFill, eCSSType_Value, nsnull)
CSS_PROP_SVG(fill-opacity, fill_opacity, FillOpacity, SVG, mFillOpacity, eCSSType_Value, nsnull)
CSS_PROP_SVG(fill-rule, fill_rule, FillRule, SVG, mFillRule, eCSSType_Value, kFillRuleKTable)
CSS_PROP_SVGRESET(filter, filter, Filter, SVG, mFilter, eCSSType_Value, nsnull)
CSS_PROP_SVG(flood-color, flood_color, FloodColor, SVG, mFloodColor, eCSSType_Value, nsnull)
CSS_PROP_SVG(flood-opacity, flood_opacity, FloodOpacity, SVG, mFloodOpacity, eCSSType_Value, nsnull)
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)

View File

@ -667,6 +667,8 @@ nsCSSSVG::nsCSSSVG(const nsCSSSVG& aCopy)
mFillOpacity(aCopy.mFillOpacity),
mFillRule(aCopy.mFillRule),
mFilter(aCopy.mFilter),
mFloodColor(aCopy.mFloodColor),
mFloodOpacity(aCopy.mFloodOpacity),
mMarkerEnd(aCopy.mMarkerEnd),
mMarkerMid(aCopy.mMarkerMid),
mMarkerStart(aCopy.mMarkerStart),

View File

@ -501,6 +501,8 @@ struct nsCSSSVG : public nsCSSStruct {
nsCSSValue mFillOpacity;
nsCSSValue mFillRule;
nsCSSValue mFilter;
nsCSSValue mFloodColor;
nsCSSValue mFloodOpacity;
nsCSSValue mMarkerEnd;
nsCSSValue mMarkerMid;
nsCSSValue mMarkerStart;

View File

@ -4072,6 +4072,14 @@ nsRuleNode::ComputeSVGData(nsStyleStruct* aStartStruct,
inherited = PR_TRUE;
svg->mFillRule = parentSVG->mFillRule;
}
// flood-color:
SetSVGPaint(SVGData.mFloodColor, parentSVG->mFloodColor,
mPresContext, aContext, svg->mFloodColor, inherited);
// flood-opacity:
SetSVGOpacity(SVGData.mFloodOpacity, parentSVG->mFloodOpacity,
svg->mFloodOpacity, inherited);
// marker-end: url, none, inherit
if (eCSSUnit_URL == SVGData.mMarkerEnd.GetUnit()) {

View File

@ -863,6 +863,8 @@ void nsStyleContext::DumpRegressionData(nsPresContext* aPresContext, FILE* out,
else
fprintf(out, "%ld ", (long)svg->mStroke.mPaint.mColor);
fprintf(out, "%ld ", (long)svg->mFloodColor.mPaint.mColor);
fprintf(out, "%s %s %s ",
URICString(svg->mMarkerEnd).get(),
URICString(svg->mMarkerMid).get(),
@ -877,11 +879,12 @@ void nsStyleContext::DumpRegressionData(nsPresContext* aPresContext, FILE* out,
}
svg->mStrokeDashoffset.ToString(str);
fprintf(out, "%f %s %f %f ",
fprintf(out, "%f %s %f %f %f ",
svg->mFillOpacity,
NS_ConvertUTF16toUTF8(str).get(),
svg->mStrokeMiterlimit,
svg->mStrokeOpacity);
svg->mStrokeOpacity,
svg->mFloodOpacity);
svg->mStrokeWidth.ToString(str);
fprintf(out, "%s %d %d %d %d %d %d %d %d %d\" />\n",
NS_ConvertUTF16toUTF8(str).get(),

View File

@ -636,11 +636,13 @@ nsChangeHint nsStyleColumn::MaxDifference()
//
nsStyleSVG::nsStyleSVG()
{
mFill.mType = eStyleSVGPaintType_Color;
mFill.mPaint.mColor = NS_RGB(0,0,0);
mStroke.mType = eStyleSVGPaintType_None;
mStroke.mPaint.mColor = NS_RGB(0,0,0);
mStrokeDasharray = nsnull;
mFill.mType = eStyleSVGPaintType_Color;
mFill.mPaint.mColor = NS_RGB(0,0,0);
mStroke.mType = eStyleSVGPaintType_None;
mStroke.mPaint.mColor = NS_RGB(0,0,0);
mFloodColor.mType = eStyleSVGPaintType_Color;
mFloodColor.mPaint.mColor = NS_RGB(0,0,0);
mStrokeDasharray = nsnull;
mStrokeDashoffset.SetFactorValue(0.0f);
mStrokeWidth.SetFactorValue(1.0f);
@ -648,6 +650,7 @@ nsStyleSVG::nsStyleSVG()
mFillOpacity = 1.0f;
mStrokeMiterlimit = 4.0f;
mStrokeOpacity = 1.0f;
mFloodOpacity = 1.0f;
mStrokeDasharrayLength = 0;
mClipRule = NS_STYLE_FILL_RULE_NONZERO;
@ -671,6 +674,7 @@ nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
mFill = aSource.mFill;
mStroke = aSource.mStroke;
mFloodColor = aSource.mFloodColor;
mMarkerEnd = aSource.mMarkerEnd;
mMarkerMid = aSource.mMarkerMid;
@ -695,6 +699,7 @@ nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
mFillOpacity = aSource.mFillOpacity;
mStrokeMiterlimit = aSource.mStrokeMiterlimit;
mStrokeOpacity = aSource.mStrokeOpacity;
mFloodOpacity = aSource.mFloodOpacity;
mClipRule = aSource.mClipRule;
mFillRule = aSource.mFillRule;
@ -709,8 +714,9 @@ nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
{
if ( mFill != aOther.mFill ||
mStroke != aOther.mStroke ||
mFloodColor != aOther.mFloodColor ||
!EqualURIs(mMarkerEnd, aOther.mMarkerEnd) ||
!EqualURIs(mMarkerMid, aOther.mMarkerMid) ||
!EqualURIs(mMarkerStart, aOther.mMarkerStart) ||
@ -721,6 +727,7 @@ nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
mFillOpacity != aOther.mFillOpacity ||
mStrokeMiterlimit != aOther.mStrokeMiterlimit ||
mStrokeOpacity != aOther.mStrokeOpacity ||
mFloodOpacity != aOther.mFloodOpacity ||
mClipRule != aOther.mClipRule ||
mFillRule != aOther.mFillRule ||

View File

@ -1241,6 +1241,7 @@ struct nsStyleSVG : public nsStyleStruct {
nsStyleSVGPaint mFill; // [inherited]
nsStyleSVGPaint mStroke; // [inherited]
nsStyleSVGPaint mFloodColor; // [inherited]
nsCOMPtr<nsIURI> mMarkerEnd; // [inherited]
nsCOMPtr<nsIURI> mMarkerMid; // [inherited]
nsCOMPtr<nsIURI> mMarkerStart; // [inherited]
@ -1252,6 +1253,7 @@ struct nsStyleSVG : public nsStyleStruct {
float mFillOpacity; // [inherited]
float mStrokeMiterlimit; // [inherited]
float mStrokeOpacity; // [inherited]
float mFloodOpacity; // [inherited]
PRUint32 mStrokeDasharrayLength;
PRUint8 mClipRule; // [inherited]

View File

@ -66,6 +66,12 @@ public:
cairo_surface_t **aImage, nsRect *aRegion);
void DefineImage(const nsAString &aName,
cairo_surface_t *aImage, nsRect aRegion);
void GetFilterBox(float *x, float *y, float *width, float *height) {
*x = mFilterX;
*y = mFilterY;
*width = mFilterWidth;
*height = mFilterHeight;
}
nsSVGFilterInstance(nsSVGElement *aTarget,
nsIDOMSVGRect *aTargetBBox,