diff --git a/mozilla/content/svg/content/src/Makefile.in b/mozilla/content/svg/content/src/Makefile.in index 6016e7201d5..2be4df6131c 100644 --- a/mozilla/content/svg/content/src/Makefile.in +++ b/mozilla/content/svg/content/src/Makefile.in @@ -63,6 +63,8 @@ REQUIRES = xpcom \ unicharutil CPPSRCS = \ + nsSVGAngle.cpp \ + nsSVGAnimatedAngle.cpp \ nsSVGAnimatedEnumeration.cpp \ nsSVGAnimatedLength.cpp \ nsSVGAnimatedLengthList.cpp \ @@ -91,6 +93,7 @@ CPPSRCS = \ nsSVGLength.cpp \ nsSVGLengthList.cpp \ nsSVGLineElement.cpp \ + nsSVGMarkerElement.cpp \ nsSVGMatrix.cpp \ nsSVGNumber.cpp \ nsSVGNumberList.cpp \ diff --git a/mozilla/content/svg/content/src/nsISVGAngle.h b/mozilla/content/svg/content/src/nsISVGAngle.h new file mode 100644 index 00000000000..e570ebfabd9 --- /dev/null +++ b/mozilla/content/svg/content/src/nsISVGAngle.h @@ -0,0 +1,56 @@ +/* -*- 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 of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __NS_ISVGANGLE_H__ +#define __NS_ISVGANGLE_H__ + +#include "nsIDOMSVGAngle.h" + +//////////////////////////////////////////////////////////////////////// +// nsISVGAngle: private interface for svg angles + +// {7ac1f558-4460-4e32-98d2-179a666c28d8} +#define NS_ISVGANGLE_IID \ +{ 0x7ac1f558, 0x4460, 0x4e32, { 0x98, 0xd2, 0x17, 0x9a, 0x66, 0x6c, 0x28, 0xd8 } } + +class nsISVGAngle : public nsIDOMSVGAngle +{ +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISVGANGLE_IID) +}; + + +#endif // __NS_ISVGANGLE_H__ diff --git a/mozilla/content/svg/content/src/nsSVGAngle.cpp b/mozilla/content/svg/content/src/nsSVGAngle.cpp new file mode 100644 index 00000000000..04091bf8d87 --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGAngle.cpp @@ -0,0 +1,417 @@ +/* -*- 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 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 "nsSVGAngle.h" +#include "prdtoa.h" +#include "nsSVGAtoms.h" +#include "nsSVGValue.h" +#include "nsReadableUtils.h" +#include "nsTextFormatter.h" +#include "nsCRT.h" +#include "nsIDOMSVGNumber.h" +#include "nsISVGValueUtils.h" +#include "nsWeakReference.h" + +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//////////////////////////////////////////////////////////////////////// +// nsSVGAngle class + +class nsSVGAngle : public nsISVGAngle, + public nsSVGValue, + public nsISVGValueObserver, + public nsSupportsWeakReference +{ +protected: + friend nsresult NS_NewSVGAngle(nsISVGAngle** result, + float value, + PRUint16 unit); + + friend nsresult NS_NewSVGAngle(nsISVGAngle** result, + const nsAString &value); + + nsSVGAngle(float value, PRUint16 unit); + nsSVGAngle(); + virtual ~nsSVGAngle(); + +public: + // nsISupports interface: + NS_DECL_ISUPPORTS + + // nsIDOMSVGAngle interface: + NS_DECL_NSIDOMSVGANGLE + + // nsISVGValue interface: + NS_IMETHOD SetValueString(const nsAString& aValue); + NS_IMETHOD GetValueString(nsAString& aValue); + + // nsISVGValueObserver interface: + NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable); + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable); + + // nsISupportsWeakReference + // implementation inherited from nsSupportsWeakReference + +protected: + // implementation helpers: + void GetUnitString(nsAString& unit); + PRUint16 GetUnitTypeForString(const char* unitStr); + PRBool IsValidUnitType(PRUint16 unit); + + float mValueInSpecifiedUnits; + PRUint16 mSpecifiedUnitType; +}; + + +//---------------------------------------------------------------------- +// Implementation + +nsresult +NS_NewSVGAngle(nsISVGAngle** result, + float value, + PRUint16 unit) +{ + nsSVGAngle *pl = new nsSVGAngle(value, unit); + NS_ENSURE_TRUE(pl, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(pl); + *result = pl; + return NS_OK; +} + +nsresult +NS_NewSVGAngle(nsISVGAngle** result, + const nsAString &value) +{ + *result = nsnull; + nsSVGAngle *pl = new nsSVGAngle(); + NS_ENSURE_TRUE(pl, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(pl); + if (NS_FAILED(pl->SetValueAsString(value))) { + NS_RELEASE(pl); + return NS_ERROR_FAILURE; + } + *result = pl; + return NS_OK; +} + + +nsSVGAngle::nsSVGAngle(float value, + PRUint16 unit) + : mValueInSpecifiedUnits(value), + mSpecifiedUnitType(unit) +{ +} + +nsSVGAngle::nsSVGAngle() +{ +} + +nsSVGAngle::~nsSVGAngle() +{ +} + +//---------------------------------------------------------------------- +// nsISupports methods: + +NS_IMPL_ADDREF(nsSVGAngle) +NS_IMPL_RELEASE(nsSVGAngle) + +NS_INTERFACE_MAP_BEGIN(nsSVGAngle) + NS_INTERFACE_MAP_ENTRY(nsISVGValue) + NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver) + NS_INTERFACE_MAP_ENTRY(nsISVGAngle) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAngle) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue) +NS_INTERFACE_MAP_END + +//---------------------------------------------------------------------- +// nsISVGValue methods: +NS_IMETHODIMP +nsSVGAngle::SetValueString(const nsAString& aValue) +{ + return SetValueAsString(aValue); +} + +NS_IMETHODIMP +nsSVGAngle::GetValueString(nsAString& aValue) +{ + return GetValueAsString(aValue); +} + +//---------------------------------------------------------------------- +// nsISVGValueObserver methods + +NS_IMETHODIMP +nsSVGAngle::WillModifySVGObservable(nsISVGValue* observable) +{ + WillModify(); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGAngle::DidModifySVGObservable(nsISVGValue* observable) +{ + DidModify(); + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsISVGAngle methods: + +/* readonly attribute unsigned short unitType; */ +NS_IMETHODIMP +nsSVGAngle::GetUnitType(PRUint16 *aUnitType) +{ + *aUnitType = mSpecifiedUnitType; + return NS_OK; +} + +/* attribute float value; */ +NS_IMETHODIMP +nsSVGAngle::GetValue(float *aValue) +{ + nsresult rv = NS_OK; + + switch (mSpecifiedUnitType) { + case SVG_ANGLETYPE_UNSPECIFIED: + case SVG_ANGLETYPE_DEG: + *aValue = (mValueInSpecifiedUnits * M_PI) / 180.0; + break; + case SVG_ANGLETYPE_RAD: + *aValue = mValueInSpecifiedUnits; + break; + case SVG_ANGLETYPE_GRAD: + *aValue = (mValueInSpecifiedUnits * M_PI) / 100.0; + break; + default: + rv = NS_ERROR_FAILURE; + break; + } + return rv; +} + +NS_IMETHODIMP +nsSVGAngle::SetValue(float aValue) +{ + nsresult rv = NS_OK; + + WillModify(); + + switch (mSpecifiedUnitType) { + case SVG_ANGLETYPE_UNSPECIFIED: + case SVG_ANGLETYPE_DEG: + mValueInSpecifiedUnits = (aValue * 180.0) / M_PI; + break; + case SVG_ANGLETYPE_RAD: + mValueInSpecifiedUnits = aValue; + break; + case SVG_ANGLETYPE_GRAD: + mValueInSpecifiedUnits = (aValue * 100.0) / M_PI; + break; + default: + rv = NS_ERROR_FAILURE; + break; + } + + DidModify(); + return rv; +} + +/* attribute float valueInSpecifiedUnits; */ +NS_IMETHODIMP +nsSVGAngle::GetValueInSpecifiedUnits(float *aValueInSpecifiedUnits) +{ + *aValueInSpecifiedUnits = mValueInSpecifiedUnits; + return NS_OK; +} + +NS_IMETHODIMP +nsSVGAngle::SetValueInSpecifiedUnits(float aValueInSpecifiedUnits) +{ + WillModify(); + mValueInSpecifiedUnits = aValueInSpecifiedUnits; + DidModify(); + return NS_OK; +} + +/* attribute DOMString valueAsString; */ +NS_IMETHODIMP +nsSVGAngle::GetValueAsString(nsAString & aValueAsString) +{ + aValueAsString.Truncate(); + + PRUnichar buf[24]; + nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar), + NS_LITERAL_STRING("%g").get(), + (double)mValueInSpecifiedUnits); + aValueAsString.Append(buf); + + nsAutoString unitString; + GetUnitString(unitString); + aValueAsString.Append(unitString); + + return NS_OK; +} + +NS_IMETHODIMP +nsSVGAngle::SetValueAsString(const nsAString & aValueAsString) +{ + nsresult rv = NS_OK; + + char *str = ToNewCString(aValueAsString); + + char* number = str; + while (*number && isspace(*number)) + ++number; + + if (*number) { + char *rest; + double value = PR_strtod(number, &rest); + if (rest!=number) { + PRUint16 unitType = GetUnitTypeForString(nsCRT::strtok(rest, "\x20\x9\xD\xA", &rest)); + if (IsValidUnitType(unitType)){ + WillModify(); + mValueInSpecifiedUnits = (float)value; + mSpecifiedUnitType = unitType; + DidModify(); + } + else { // parse error + // not a valid unit type + rv = NS_ERROR_FAILURE; + NS_ERROR("invalid length type"); + } + } + else { // parse error + // no number + rv = NS_ERROR_FAILURE; + } + } + + nsMemory::Free(str); + + return rv; +} + +/* void newValueSpecifiedUnits (in unsigned short unitType, in float valueInSpecifiedUnits); */ +NS_IMETHODIMP +nsSVGAngle::NewValueSpecifiedUnits(PRUint16 unitType, float valueInSpecifiedUnits) +{ + if (!IsValidUnitType(unitType)) return NS_ERROR_FAILURE; + + WillModify(); + mValueInSpecifiedUnits = valueInSpecifiedUnits; + mSpecifiedUnitType = unitType; + DidModify(); + + return NS_OK; +} + +/* void convertToSpecifiedUnits (in unsigned short unitType); */ +NS_IMETHODIMP +nsSVGAngle::ConvertToSpecifiedUnits(PRUint16 unitType) +{ + if (!IsValidUnitType(unitType)) return NS_ERROR_FAILURE; + + WillModify(); + float valueInUserUnits; + GetValue(&valueInUserUnits); + mSpecifiedUnitType = unitType; + SetValue(valueInUserUnits); + DidModify(); + + return NS_OK; +} + + +//---------------------------------------------------------------------- +// Implementation helpers: + + +void nsSVGAngle::GetUnitString(nsAString& unit) +{ + nsIAtom* UnitAtom = nsnull; + + switch (mSpecifiedUnitType) { + case SVG_ANGLETYPE_UNSPECIFIED: + UnitAtom = nsnull; + break; + case SVG_ANGLETYPE_DEG: + UnitAtom = nsSVGAtoms::deg; + break; + case SVG_ANGLETYPE_GRAD: + UnitAtom = nsSVGAtoms::grad; + break; + case SVG_ANGLETYPE_RAD: + UnitAtom = nsSVGAtoms::rad; + break; + default: + NS_ASSERTION(PR_FALSE, "unknown unit"); + break; + } + if (!UnitAtom) return; + + UnitAtom->ToString(unit); +} + +PRUint16 nsSVGAngle::GetUnitTypeForString(const char* unitStr) +{ + if (!unitStr || *unitStr=='\0') return SVG_ANGLETYPE_UNSPECIFIED; + + nsCOMPtr unitAtom = do_GetAtom(unitStr); + + if (unitAtom == nsSVGAtoms::deg) + return SVG_ANGLETYPE_DEG; + else if (unitAtom == nsSVGAtoms::grad) + return SVG_ANGLETYPE_GRAD; + else if (unitAtom == nsSVGAtoms::rad) + return SVG_ANGLETYPE_RAD; + + return SVG_ANGLETYPE_UNKNOWN; +} + +PRBool nsSVGAngle::IsValidUnitType(PRUint16 unit) +{ + if (unit>0 && unit<=4) + return PR_TRUE; + + return PR_FALSE; +} diff --git a/mozilla/content/svg/content/src/nsSVGAngle.h b/mozilla/content/svg/content/src/nsSVGAngle.h new file mode 100644 index 00000000000..ceb2b2cc94e --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGAngle.h @@ -0,0 +1,52 @@ +/* -*- 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 of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __NS_SVGANGLE_H__ +#define __NS_SVGANGLE_H__ + +#include "nsISVGAngle.h" +#include "nsAString.h" + +nsresult +NS_NewSVGAngle(nsISVGAngle** result, + float value=0.0f, + PRUint16 unit=nsIDOMSVGAngle::SVG_ANGLETYPE_UNSPECIFIED); + +nsresult +NS_NewSVGAngle(nsISVGAngle** result, + const nsAString &value); + +#endif //__NS_SVGLENGTH_H__ diff --git a/mozilla/content/svg/content/src/nsSVGAnimatedAngle.cpp b/mozilla/content/svg/content/src/nsSVGAnimatedAngle.cpp new file mode 100644 index 00000000000..c5a0923558d --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGAnimatedAngle.cpp @@ -0,0 +1,197 @@ +/* -*- 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 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 "nsSVGValue.h" +#include "nsWeakReference.h" +#include "nsSVGAnimatedAngle.h" +#include "nsSVGLength.h" + + +//////////////////////////////////////////////////////////////////////// +// nsSVGAnimatedAngle + +class nsSVGAnimatedAngle : public nsIDOMSVGAnimatedAngle, + public nsSVGValue, + public nsISVGValueObserver, + public nsSupportsWeakReference +{ +protected: + friend nsresult NS_NewSVGAnimatedAngle(nsIDOMSVGAnimatedAngle** result, + nsIDOMSVGAngle* baseVal); + nsSVGAnimatedAngle(); + ~nsSVGAnimatedAngle(); + void Init(nsIDOMSVGAngle* baseVal); + +public: + // nsISupports interface: + NS_DECL_ISUPPORTS + + // nsIDOMSVGAnimatedAngle interface: + NS_DECL_NSIDOMSVGANIMATEDANGLE + + // remainder of nsISVGValue interface: + NS_IMETHOD SetValueString(const nsAString& aValue); + NS_IMETHOD GetValueString(nsAString& aValue); + + // nsISVGValueObserver + NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable); + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable); + + // nsISupportsWeakReference + // implementation inherited from nsSupportsWeakReference + +protected: + nsCOMPtr mBaseVal; +}; + + + +//---------------------------------------------------------------------- +// Implementation + +nsSVGAnimatedAngle::nsSVGAnimatedAngle() +{ +} + +nsSVGAnimatedAngle::~nsSVGAnimatedAngle() +{ + if (!mBaseVal) return; + nsCOMPtr val = do_QueryInterface(mBaseVal); + if (!val) return; + val->RemoveObserver(this); +} + +void +nsSVGAnimatedAngle::Init(nsIDOMSVGAngle* baseVal) +{ + mBaseVal = baseVal; + if (!mBaseVal) return; + nsCOMPtr val = do_QueryInterface(mBaseVal); + NS_ASSERTION(val, "baseval needs to implement nsISVGValue interface"); + if (!val) return; + val->AddObserver(this); +} + +//---------------------------------------------------------------------- +// nsISupports methods: + +NS_IMPL_ADDREF(nsSVGAnimatedAngle) +NS_IMPL_RELEASE(nsSVGAnimatedAngle) + + +NS_INTERFACE_MAP_BEGIN(nsSVGAnimatedAngle) + NS_INTERFACE_MAP_ENTRY(nsISVGValue) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedAngle) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedAngle) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue) +NS_INTERFACE_MAP_END + +//---------------------------------------------------------------------- +// nsISVGValue methods: + +NS_IMETHODIMP +nsSVGAnimatedAngle::SetValueString(const nsAString& aValue) +{ + nsCOMPtr value = do_QueryInterface(mBaseVal); + return value->SetValueString(aValue); +} + +NS_IMETHODIMP +nsSVGAnimatedAngle::GetValueString(nsAString& aValue) +{ + nsCOMPtr value = do_QueryInterface(mBaseVal); + return value->GetValueString(aValue); +} + +//---------------------------------------------------------------------- +// nsIDOMSVGAnimatedAngle methods: + +/* readonly attribute nsIDOMSVGAngle baseVal; */ +NS_IMETHODIMP +nsSVGAnimatedAngle::GetBaseVal(nsIDOMSVGAngle * *aBaseVal) +{ + *aBaseVal = mBaseVal; + NS_ADDREF(*aBaseVal); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAngle animVal; */ +NS_IMETHODIMP +nsSVGAnimatedAngle::GetAnimVal(nsIDOMSVGAngle * *aAnimVal) +{ + *aAnimVal = mBaseVal; + NS_ADDREF(*aAnimVal); + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsISVGValueObserver methods + +NS_IMETHODIMP +nsSVGAnimatedAngle::WillModifySVGObservable(nsISVGValue* observable) +{ + WillModify(); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGAnimatedAngle::DidModifySVGObservable (nsISVGValue* observable) +{ + DidModify(); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +// Exported creation functions + +nsresult +NS_NewSVGAnimatedAngle(nsIDOMSVGAnimatedAngle** aResult, + nsIDOMSVGAngle* baseVal) +{ + *aResult = nsnull; + + nsSVGAnimatedAngle* animatedLength = new nsSVGAnimatedAngle(); + if(!animatedLength) return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(animatedLength); + + animatedLength->Init(baseVal); + + *aResult = (nsIDOMSVGAnimatedAngle*) animatedLength; + + return NS_OK; +} diff --git a/mozilla/content/svg/content/src/nsSVGAnimatedAngle.h b/mozilla/content/svg/content/src/nsSVGAnimatedAngle.h new file mode 100644 index 00000000000..b29163cc44f --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGAnimatedAngle.h @@ -0,0 +1,46 @@ +/* -*- 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 of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __NS_SVGANIMATEDANGLE_H__ +#define __NS_SVGANIMATEDANGLE_H__ + +#include "nsIDOMSVGAnimatedAngle.h" +#include "nsIDOMSVGAngle.h" + +nsresult NS_NewSVGAnimatedAngle(nsIDOMSVGAnimatedAngle** result, + nsIDOMSVGAngle* baseVal); + +#endif //__NS_SVGANIMATEDANGLE_H__ diff --git a/mozilla/content/svg/content/src/nsSVGAtomList.h b/mozilla/content/svg/content/src/nsSVGAtomList.h index dc139d7c9c8..272073b8413 100644 --- a/mozilla/content/svg/content/src/nsSVGAtomList.h +++ b/mozilla/content/svg/content/src/nsSVGAtomList.h @@ -64,6 +64,7 @@ SVG_ATOM(generic, "generic") SVG_ATOM(image, "image") SVG_ATOM(line, "line") SVG_ATOM(linearGradient, "linearGradient") +SVG_ATOM(marker, "marker") SVG_ATOM(path, "path") SVG_ATOM(polygon, "polygon") SVG_ATOM(polyline, "polyline") @@ -82,6 +83,7 @@ SVG_ATOM(use, "use") // properties and attributes SVG_ATOM(alignment_baseline, "alignment-baseline") +SVG_ATOM(_auto, "auto") SVG_ATOM(baseline_shift, "baseline-shift") SVG_ATOM(_class, "class") SVG_ATOM(clip, "clip") @@ -118,6 +120,13 @@ SVG_ATOM(id, "id") SVG_ATOM(image_rendering, "image-rendering") SVG_ATOM(kerning, "kerning") SVG_ATOM(letter_spacing, "letter-spacing") +// defined above - SVG_ATOM(marker, "marker") +SVG_ATOM(marker_end, "marker-end") +SVG_ATOM(marker_mid, "marker-mid") +SVG_ATOM(marker_start, "marker-start") +SVG_ATOM(markerHeight, "markerHeight") +SVG_ATOM(markerUnits, "markerUnits") +SVG_ATOM(markerWidth, "markerWidth") SVG_ATOM(mask, "mask") SVG_ATOM(media, "media") SVG_ATOM(offset, "offset") @@ -129,12 +138,15 @@ SVG_ATOM(onmousemove, "onmousemove") SVG_ATOM(onmouseout, "onmouseout") SVG_ATOM(onload, "onload") SVG_ATOM(opacity, "opacity") +SVG_ATOM(orient, "orient") SVG_ATOM(overflow, "overflow") SVG_ATOM(pathLength, "pathLength") SVG_ATOM(pointer_events, "pointer-events") SVG_ATOM(points, "points") SVG_ATOM(preserveAspectRatio, "preserveAspectRatio") SVG_ATOM(r, "r") +SVG_ATOM(refX, "refX") +SVG_ATOM(refY, "refY") SVG_ATOM(requiredExtensions, "requiredExtensions") SVG_ATOM(requiredFeatures, "requiredFeatures") SVG_ATOM(rx, "rx") @@ -152,6 +164,7 @@ SVG_ATOM(stroke_linejoin, "stroke-linejoin") SVG_ATOM(stroke_miterlimit, "stroke-miterlimit") SVG_ATOM(stroke_opacity, "stroke-opacity") SVG_ATOM(stroke_width, "stroke-width") +SVG_ATOM(strokeWidth, "strokeWidth") SVG_ATOM(style, "style") SVG_ATOM(systemLanguage, "systemLanguage") SVG_ATOM(text_anchor, "text-anchor") @@ -197,10 +210,15 @@ SVG_ATOM(pad, "pad") SVG_ATOM(reflect, "reflect") SVG_ATOM(repeat, "repeat") -// Gradient Units +// Gradient/Marker Units SVG_ATOM(userSpaceOnUse, "userSpaceOnUse") SVG_ATOM(objectBoundingBox, "objectBoundingBox") // Zoom and Pan options SVG_ATOM(disable, "disable") SVG_ATOM(magnify, "magnify") + +// angle units +SVG_ATOM(deg, "deg") +SVG_ATOM(grad, "grad") +SVG_ATOM(rad, "rad") diff --git a/mozilla/content/svg/content/src/nsSVGElement.cpp b/mozilla/content/svg/content/src/nsSVGElement.cpp index aa0f229ca8e..c91ea100bf9 100644 --- a/mozilla/content/svg/content/src/nsSVGElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGElement.cpp @@ -424,6 +424,15 @@ nsSVGElement::sViewportsMap[] = { { nsnull } }; +// PresentationAttributes-Makers +/* static */ const nsGenericElement::MappedAttributeEntry +nsSVGElement::sMarkersMap[] = { + { &nsSVGAtoms::marker_end }, + { &nsSVGAtoms::marker_mid }, + { &nsSVGAtoms::marker_start }, + { nsnull } +}; + //---------------------------------------------------------------------- // nsIDOMNode methods diff --git a/mozilla/content/svg/content/src/nsSVGElement.h b/mozilla/content/svg/content/src/nsSVGElement.h index 9dee051ff1d..ad459095f55 100644 --- a/mozilla/content/svg/content/src/nsSVGElement.h +++ b/mozilla/content/svg/content/src/nsSVGElement.h @@ -96,6 +96,7 @@ public: static const MappedAttributeEntry sFontSpecificationMap[]; static const MappedAttributeEntry sGradientStopMap[]; static const MappedAttributeEntry sViewportsMap[]; + static const MappedAttributeEntry sMarkersMap[]; // nsIDOMNode NS_IMETHOD IsSupported(const nsAString& aFeature, const nsAString& aVersion, PRBool* aReturn); diff --git a/mozilla/content/svg/content/src/nsSVGElementFactory.cpp b/mozilla/content/svg/content/src/nsSVGElementFactory.cpp index 60ea12ba671..b2f8a6e105a 100644 --- a/mozilla/content/svg/content/src/nsSVGElementFactory.cpp +++ b/mozilla/content/svg/content/src/nsSVGElementFactory.cpp @@ -85,6 +85,8 @@ nsresult NS_NewSVGUseElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsresult NS_NewSVGSymbolElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult +NS_NewSVGMarkerElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsresult NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo) @@ -133,6 +135,8 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo) return NS_NewSVGUseElement(aResult, aNodeInfo); if (name == nsSVGAtoms::symbol) return NS_NewSVGSymbolElement(aResult, aNodeInfo); + if (name == nsSVGAtoms::marker) + return NS_NewSVGMarkerElement(aResult, aNodeInfo); // if we don't know what to create, just create a standard xml element: return NS_NewXMLElement(aResult, aNodeInfo); diff --git a/mozilla/content/svg/content/src/nsSVGLineElement.cpp b/mozilla/content/svg/content/src/nsSVGLineElement.cpp index c69079873cd..ef499ceb84a 100644 --- a/mozilla/content/svg/content/src/nsSVGLineElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGLineElement.cpp @@ -72,6 +72,9 @@ public: // nsISVGContent specializations: virtual void ParentChainChanged(); + // nsIStyledContent interface + NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const; + protected: nsCOMPtr mX1; @@ -270,3 +273,17 @@ void nsSVGLineElement::ParentChainChanged() // XXX call baseclass version to recurse into children? } + +//---------------------------------------------------------------------- +// nsIStyledContent methods + +NS_IMETHODIMP_(PRBool) +nsSVGLineElement::IsAttributeMapped(const nsIAtom* name) const +{ + static const MappedAttributeEntry* const map[] = { + sMarkersMap, + }; + + return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) || + nsSVGLineElementBase::IsAttributeMapped(name); +} diff --git a/mozilla/content/svg/content/src/nsSVGMarkerElement.cpp b/mozilla/content/svg/content/src/nsSVGMarkerElement.cpp new file mode 100644 index 00000000000..3892584b27e --- /dev/null +++ b/mozilla/content/svg/content/src/nsSVGMarkerElement.cpp @@ -0,0 +1,551 @@ +/* -*- 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 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 "nsIDOMSVGFitToViewBox.h" +#include "nsSVGGraphicElement.h" +#include "nsSVGAtoms.h" +#include "nsSVGAnimatedLength.h" +#include "nsSVGAnimatedAngle.h" +#include "nsSVGAnimatedRect.h" +#include "nsSVGLength.h" +#include "nsSVGEnum.h" +#include "nsSVGAngle.h" +#include "nsSVGRect.h" +#include "nsSVGAnimatedEnumeration.h" +#include "nsIDOMSVGMarkerElement.h" +#include "nsCOMPtr.h" +#include "nsSVGCoordCtxProvider.h" +#include "nsISVGValueUtils.h" +#include "nsSVGAnimatedPreserveAspectRatio.h" +#include "nsSVGPreserveAspectRatio.h" +#include "nsSVGMatrix.h" + +typedef nsSVGGraphicElement nsSVGMarkerElementBase; + +class nsSVGMarkerElement : public nsSVGMarkerElementBase, + public nsIDOMSVGMarkerElement, + public nsIDOMSVGFitToViewBox, + public nsSVGCoordCtxProvider +{ +protected: + friend nsresult NS_NewSVGMarkerElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGMarkerElement(nsINodeInfo* aNodeInfo); + virtual ~nsSVGMarkerElement(); + nsresult Init(); + +public: + // interfaces: + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIDOMSVGMARKERELEMENT + NS_DECL_NSIDOMSVGFITTOVIEWBOX + + // xxx I wish we could use virtual inheritance + NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGElement::) + NS_FORWARD_NSIDOMELEMENT(nsSVGElement::) + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::) + + // nsISVGValueObserver + NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable); + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable); + +protected: + + nsCOMPtr mRefX; + nsCOMPtr mRefY; + nsCOMPtr mMarkerUnits; + nsCOMPtr mMarkerWidth; + nsCOMPtr mMarkerHeight; + nsCOMPtr mOrientType; + nsCOMPtr mOrientAngle; + + nsCOMPtr mViewBox; + nsCOMPtr mPreserveAspectRatio; + nsCOMPtr mViewBoxToViewportTransform; +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(Marker) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGMarkerElement,nsSVGElement) +NS_IMPL_RELEASE_INHERITED(nsSVGMarkerElement,nsSVGElement) + +NS_INTERFACE_MAP_BEGIN(nsSVGMarkerElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMNode) + NS_INTERFACE_MAP_ENTRY(nsIDOMElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGFitToViewBox) + NS_INTERFACE_MAP_ENTRY(nsIDOMSVGMarkerElement) + NS_INTERFACE_MAP_ENTRY(nsSVGCoordCtxProvider) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGMarkerElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGElement) + +//---------------------------------------------------------------------- +// Implementation + + nsSVGMarkerElement::nsSVGMarkerElement(nsINodeInfo *aNodeInfo) + : nsSVGMarkerElementBase(aNodeInfo) +{ +} + +nsSVGMarkerElement::~nsSVGMarkerElement() +{ + if (mPreserveAspectRatio) { + NS_REMOVE_SVGVALUE_OBSERVER(mPreserveAspectRatio); + } + if (mViewBox) { + NS_REMOVE_SVGVALUE_OBSERVER(mViewBox); + } + if (mOrientType) { + NS_REMOVE_SVGVALUE_OBSERVER(mOrientType); + } +} + +nsresult +nsSVGMarkerElement::Init() +{ + nsresult rv = nsSVGMarkerElementBase::Init(); + NS_ENSURE_SUCCESS(rv,rv); + + // enumeration mappings + static struct nsSVGEnumMapping gMarkerUnits[] = { + {&nsSVGAtoms::strokeWidth, SVG_MARKERUNITS_STROKEWIDTH}, + {&nsSVGAtoms::userSpaceOnUse, SVG_MARKERUNITS_USERSPACEONUSE}, + {nsnull, 0} + }; + + static struct nsSVGEnumMapping gOrientType[] = { + {&nsSVGAtoms::_auto, SVG_MARKER_ORIENT_AUTO}, + {nsnull, 0} + }; + + // Create mapped properties: + + // DOM property: refX + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), 0.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mRefX), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::refX, mRefX); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: refY + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), 0.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mRefY), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::refY, mRefY); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: markerWidth + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), 3.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mMarkerWidth), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::markerWidth, mMarkerWidth); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: markerHeight + { + nsCOMPtr length; + rv = NS_NewSVGLength(getter_AddRefs(length), 3.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLength(getter_AddRefs(mMarkerHeight), length); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::markerHeight, mMarkerHeight); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: markerUnits + { + nsCOMPtr units; + rv = NS_NewSVGEnum(getter_AddRefs(units), SVG_MARKERUNITS_STROKEWIDTH, gMarkerUnits); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mMarkerUnits), units); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::markerUnits, mMarkerUnits); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: orient (enum) + { + nsCOMPtr orient; + rv = NS_NewSVGEnum(getter_AddRefs(orient), SVG_MARKER_ORIENT_ANGLE, gOrientType); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedEnumeration(getter_AddRefs(mOrientType), orient); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::orient, mOrientType); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: orient (angle) + { + nsCOMPtr angle; + rv = NS_NewSVGAngle(getter_AddRefs(angle), 0.0f); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedAngle(getter_AddRefs(mOrientAngle), angle); + NS_ENSURE_SUCCESS(rv,rv); + // Can't map two values to the same attribute, so we take care + // of keeping mOrientAngle updated in DidModifySVGObservable + } + + // DOM property: viewBox + { + nsCOMPtr viewbox; + nsCOMPtr animWidth, animHeight; + mMarkerWidth->GetAnimVal(getter_AddRefs(animWidth)); + mMarkerHeight->GetAnimVal(getter_AddRefs(animHeight)); + rv = NS_NewSVGViewBox(getter_AddRefs(viewbox), animWidth, animHeight); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedRect(getter_AddRefs(mViewBox), viewbox); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::viewBox, mViewBox); + NS_ENSURE_SUCCESS(rv,rv); + // initialize coordinate context with viewbox: + SetCoordCtxRect(viewbox); + } + + // DOM property: preserveAspectRatio + { + nsCOMPtr preserveAspectRatio; + rv = NS_NewSVGPreserveAspectRatio(getter_AddRefs(preserveAspectRatio)); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedPreserveAspectRatio( + getter_AddRefs(mPreserveAspectRatio), + preserveAspectRatio); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsSVGAtoms::preserveAspectRatio, + mPreserveAspectRatio); + NS_ENSURE_SUCCESS(rv,rv); + } + + // add observers -------------------------- : + NS_ADD_SVGVALUE_OBSERVER(mViewBox); + NS_ADD_SVGVALUE_OBSERVER(mPreserveAspectRatio); + NS_ADD_SVGVALUE_OBSERVER(mOrientType); + + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + +NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGMarkerElement) + +//---------------------------------------------------------------------- +// nsIDOMSVGFitToViewBox methods + +/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ + NS_IMETHODIMP nsSVGMarkerElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) +{ + *aViewBox = mViewBox; + NS_ADDREF(*aViewBox); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedPreserveAspectRatio preserveAspectRatio; */ +NS_IMETHODIMP +nsSVGMarkerElement::GetPreserveAspectRatio(nsIDOMSVGAnimatedPreserveAspectRatio * *aPreserveAspectRatio) +{ + *aPreserveAspectRatio = mPreserveAspectRatio; + NS_ADDREF(*aPreserveAspectRatio); + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsIDOMSVGMarkerElement methods + +/* readonly attribute nsIDOMSVGAnimatedLength refX; */ +NS_IMETHODIMP nsSVGMarkerElement::GetRefX(nsIDOMSVGAnimatedLength * *aRefX) +{ + *aRefX = mRefX; + NS_IF_ADDREF(*aRefX); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength refY; */ +NS_IMETHODIMP nsSVGMarkerElement::GetRefY(nsIDOMSVGAnimatedLength * *aRefY) +{ + *aRefY = mRefY; + NS_IF_ADDREF(*aRefY); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedEnumeration markerUnits; */ +NS_IMETHODIMP nsSVGMarkerElement::GetMarkerUnits(nsIDOMSVGAnimatedEnumeration * *aMarkerUnits) +{ + *aMarkerUnits = mMarkerUnits; + NS_IF_ADDREF(*aMarkerUnits); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength markerWidth; */ +NS_IMETHODIMP nsSVGMarkerElement::GetMarkerWidth(nsIDOMSVGAnimatedLength * *aMarkerWidth) +{ + *aMarkerWidth = mMarkerWidth; + NS_IF_ADDREF(*aMarkerWidth); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength markerHeight; */ +NS_IMETHODIMP nsSVGMarkerElement::GetMarkerHeight(nsIDOMSVGAnimatedLength * *aMarkerHeight) +{ + *aMarkerHeight = mMarkerHeight; + NS_IF_ADDREF(*aMarkerHeight); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedEnumeration orientType; */ +NS_IMETHODIMP nsSVGMarkerElement::GetOrientType(nsIDOMSVGAnimatedEnumeration * *aOrientType) +{ + *aOrientType = mOrientType; + NS_IF_ADDREF(*aOrientType); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLength orientAngle; */ +NS_IMETHODIMP nsSVGMarkerElement::GetOrientAngle(nsIDOMSVGAnimatedAngle * *aOrientAngle) +{ + *aOrientAngle = mOrientAngle; + NS_IF_ADDREF(*aOrientAngle); + return NS_OK; +} + +/* void setOrientToAuto (); */ +NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAuto() +{ + mOrientType->SetBaseVal(SVG_MARKER_ORIENT_AUTO); + return NS_OK; +} + +/* void setOrientToAngle (in nsIDOMSVGAngle angle); */ +NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAngle(nsIDOMSVGAngle *angle) +{ + mOrientType->SetBaseVal(SVG_MARKER_ORIENT_ANGLE); + + nsIDOMSVGAngle *a; + mOrientAngle->GetBaseVal(&a); + float f; + angle->GetValue(&f); + a->SetValue(f); + return NS_OK; +} + +NS_IMETHODIMP +nsSVGMarkerElement::GetMarkerTransform(float aStrokeWidth, + float aX, float aY, float aAngle, + nsIDOMSVGMatrix **_retval) +{ + float scale = 1.0; + PRUint16 val; + mMarkerUnits->GetAnimVal(&val); + if (val == SVG_MARKERUNITS_STROKEWIDTH) + scale = aStrokeWidth; + + mOrientType->GetAnimVal(&val); + if (val == SVG_MARKER_ORIENT_ANGLE) { + nsCOMPtr a; + mOrientAngle->GetAnimVal(getter_AddRefs(a)); + a->GetValue(&aAngle); + } + + nsCOMPtr matrix; + NS_NewSVGMatrix(getter_AddRefs(matrix), + cos(aAngle) * scale, sin(aAngle) * scale, + -sin(aAngle) * scale, cos(aAngle) * scale, + aX, aY); + + *_retval = matrix; + NS_IF_ADDREF(*_retval); + return NS_OK; +} + + +/* nsIDOMSVGMatrix getViewboxToViewportTransform (); */ +NS_IMETHODIMP +nsSVGMarkerElement::GetViewboxToViewportTransform(nsIDOMSVGMatrix **_retval) +{ + if (!mViewBoxToViewportTransform) { + float viewportWidth; + { + nsCOMPtr l; + mMarkerWidth->GetAnimVal(getter_AddRefs(l)); + l->GetValue(&viewportWidth); + } + float viewportHeight; + { + nsCOMPtr l; + mMarkerHeight->GetAnimVal(getter_AddRefs(l)); + l->GetValue(&viewportHeight); + } + + float viewboxX, viewboxY, viewboxWidth, viewboxHeight; + { + nsCOMPtr vb; + mViewBox->GetAnimVal(getter_AddRefs(vb)); + NS_ASSERTION(vb, "could not get viewbox"); + vb->GetX(&viewboxX); + vb->GetY(&viewboxY); + vb->GetWidth(&viewboxWidth); + vb->GetHeight(&viewboxHeight); + } + if (viewboxWidth==0.0f || viewboxHeight==0.0f) { + NS_ERROR("XXX. We shouldn't get here. Viewbox width/height is set to 0. Need to disable display of element as per specs."); + viewboxWidth = 1.0f; + viewboxHeight = 1.0f; + } + + PRUint16 align, meetOrSlice; + { + nsCOMPtr par; + mPreserveAspectRatio->GetAnimVal(getter_AddRefs(par)); + NS_ASSERTION(par, "could not get preserveAspectRatio"); + par->GetAlign(&align); + par->GetMeetOrSlice(&meetOrSlice); + } + + // default to the defaults + if (align == nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_UNKNOWN) + align = nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID; + if (meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_UNKNOWN) + align = nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_MEET; + + float a, d, e, f; + a = viewportWidth/viewboxWidth; + d = viewportHeight/viewboxHeight; + e = 0.0f; + f = 0.0f; + + if (align != nsIDOMSVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_NONE && + a != d) { + if (meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_MEET && + a < d || + meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE && + d < a) { + d = a; + } + else if ( + meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_MEET && + d < a || + meetOrSlice == nsIDOMSVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE && + a < d) { + a = d; + } + else NS_NOTREACHED("Unknown value for meetOrSlice"); + } + + if (viewboxX) e += -a * viewboxX; + if (viewboxY) f += -d * viewboxY; + + float refX; + { + nsCOMPtr l; + mRefX->GetAnimVal(getter_AddRefs(l)); + l->GetValue(&refX); + } + + float refY; + { + nsCOMPtr l; + mRefY->GetAnimVal(getter_AddRefs(l)); + l->GetValue(&refY); + } + + e -= refX * a; + f -= refY * d; + +#ifdef DEBUG + printf("Marker Viewport=(0?,0?,%f,%f)\n", viewportWidth, viewportHeight); + printf("Marker Viewbox=(%f,%f,%f,%f)\n", viewboxX, viewboxY, viewboxWidth, viewboxHeight); + printf("Marker Viewbox->Viewport xform [a c e] = [%f, 0, %f]\n", a, e); + printf(" [b d f] = [ 0, %f, %f]\n", d, f); +#endif + + NS_NewSVGMatrix(getter_AddRefs(mViewBoxToViewportTransform), + a, 0.0f, + 0.0f, d, + e, f); + } + + *_retval = mViewBoxToViewportTransform; + NS_IF_ADDREF(*_retval); + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsISVGValueObserver methods: + +NS_IMETHODIMP +nsSVGMarkerElement::WillModifySVGObservable(nsISVGValue* observable) +{ +#ifdef DEBUG + printf("markerelement - viewport/viewbox/preserveAspectRatio will be changed\n"); +#endif + return NS_OK; +} + + +NS_IMETHODIMP +nsSVGMarkerElement::DidModifySVGObservable (nsISVGValue* observable) +{ +#ifdef DEBUG + printf("markerelement - viewport/viewbox/preserveAspectRatio have been changed\n"); +#endif + + mViewBoxToViewportTransform = nsnull; + + // need to sync mOrientAngle + nsAutoString value; + nsresult rv = GetAttribute(NS_LITERAL_STRING("orient"), value); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr target = do_QueryInterface(mOrientAngle); + target->SetValueString(value); + } + + return NS_OK; +} diff --git a/mozilla/content/svg/content/src/nsSVGPathElement.cpp b/mozilla/content/svg/content/src/nsSVGPathElement.cpp index 03374ec9f55..7699398e620 100644 --- a/mozilla/content/svg/content/src/nsSVGPathElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGPathElement.cpp @@ -57,7 +57,7 @@ protected: nsSVGPathElement(nsINodeInfo *aNodeInfo); virtual ~nsSVGPathElement(); nsresult Init(); - + public: // interfaces: @@ -69,6 +69,9 @@ public: NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGPathElementBase::) NS_FORWARD_NSIDOMELEMENT(nsSVGPathElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGPathElementBase::) + + // nsIStyledContent interface + NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const; protected: nsCOMPtr mSegments; @@ -326,3 +329,17 @@ NS_IMETHODIMP nsSVGPathElement::GetAnimatedNormalizedPathSegList(nsIDOMSVGPathSe { return NS_ERROR_NOT_IMPLEMENTED; } + +//---------------------------------------------------------------------- +// nsIStyledContent methods + +NS_IMETHODIMP_(PRBool) +nsSVGPathElement::IsAttributeMapped(const nsIAtom* name) const +{ + static const MappedAttributeEntry* const map[] = { + sMarkersMap, + }; + + return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) || + nsSVGPathElementBase::IsAttributeMapped(name); +} diff --git a/mozilla/content/svg/content/src/nsSVGPolygonElement.cpp b/mozilla/content/svg/content/src/nsSVGPolygonElement.cpp index a5583378abb..aae2f073ac2 100644 --- a/mozilla/content/svg/content/src/nsSVGPolygonElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGPolygonElement.cpp @@ -67,6 +67,9 @@ public: NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGPolygonElementBase::) NS_FORWARD_NSIDOMELEMENT(nsSVGPolygonElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGPolygonElementBase::) + + // nsIStyledContent interface + NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const; protected: nsCOMPtr mPoints; @@ -147,3 +150,17 @@ NS_IMETHODIMP nsSVGPolygonElement::GetAnimatedPoints(nsIDOMSVGPointList * *aAnim NS_ADDREF(*aAnimatedPoints); return NS_OK; } + +//---------------------------------------------------------------------- +// nsIStyledContent methods + +NS_IMETHODIMP_(PRBool) +nsSVGPolygonElement::IsAttributeMapped(const nsIAtom* name) const +{ + static const MappedAttributeEntry* const map[] = { + sMarkersMap, + }; + + return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) || + nsSVGPolygonElementBase::IsAttributeMapped(name); +} diff --git a/mozilla/content/svg/content/src/nsSVGPolylineElement.cpp b/mozilla/content/svg/content/src/nsSVGPolylineElement.cpp index f0871e41efb..59c431655da 100644 --- a/mozilla/content/svg/content/src/nsSVGPolylineElement.cpp +++ b/mozilla/content/svg/content/src/nsSVGPolylineElement.cpp @@ -67,6 +67,9 @@ public: NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGPolylineElementBase::) NS_FORWARD_NSIDOMELEMENT(nsSVGPolylineElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGPolylineElementBase::) + + // nsIStyledContent interface + NS_IMETHODIMP_(PRBool) IsAttributeMapped(const nsIAtom* name) const; protected: nsCOMPtr mPoints; @@ -147,3 +150,17 @@ NS_IMETHODIMP nsSVGPolylineElement::GetAnimatedPoints(nsIDOMSVGPointList * *aAni NS_ADDREF(*aAnimatedPoints); return NS_OK; } + +//---------------------------------------------------------------------- +// nsIStyledContent methods + +NS_IMETHODIMP_(PRBool) +nsSVGPolylineElement::IsAttributeMapped(const nsIAtom* name) const +{ + static const MappedAttributeEntry* const map[] = { + sMarkersMap, + }; + + return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) || + nsSVGPolylineElementBase::IsAttributeMapped(name); +} diff --git a/mozilla/dom/public/idl/svg/Makefile.in b/mozilla/dom/public/idl/svg/Makefile.in index cd68001f5b7..1c0a790a653 100644 --- a/mozilla/dom/public/idl/svg/Makefile.in +++ b/mozilla/dom/public/idl/svg/Makefile.in @@ -49,6 +49,8 @@ XPIDL_MODULE = dom_svg XPIDLSRCS = \ + nsIDOMSVGAngle.idl \ + nsIDOMSVGAnimatedAngle.idl \ nsIDOMSVGAnimatedEnum.idl \ nsIDOMSVGAnimatedLength.idl \ nsIDOMSVGAnimatedLengthList.idl \ @@ -75,6 +77,7 @@ XPIDLSRCS = \ nsIDOMSVGLengthList.idl \ nsIDOMSVGLineElement.idl \ nsIDOMSVGLocatable.idl \ + nsIDOMSVGMarkerElement.idl \ nsIDOMSVGMatrix.idl \ nsIDOMSVGNumber.idl \ nsIDOMSVGNumberList.idl \ diff --git a/mozilla/dom/public/idl/svg/nsIDOMSVGAngle.idl b/mozilla/dom/public/idl/svg/nsIDOMSVGAngle.idl new file mode 100644 index 00000000000..813a99dc4b4 --- /dev/null +++ b/mozilla/dom/public/idl/svg/nsIDOMSVGAngle.idl @@ -0,0 +1,68 @@ +/* -*- 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) 2004 + * 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 "domstubs.idl" + +/** + * The nsIDOMSVGAngle interface is the interface to an SVG angle. + * + * For more information on this interface please see + * http://www.w3.org/TR/SVG11/types.html#InterfaceSVGAngle + * + */ + +[scriptable, uuid(58b6190e-37b3-412a-ba02-1d5ad6c6ea7c)] +interface nsIDOMSVGAngle : nsISupports +{ + // Angle Unit Types + const unsigned short SVG_ANGLETYPE_UNKNOWN = 0; + const unsigned short SVG_ANGLETYPE_UNSPECIFIED = 1; + const unsigned short SVG_ANGLETYPE_DEG = 2; + const unsigned short SVG_ANGLETYPE_RAD = 3; + const unsigned short SVG_ANGLETYPE_GRAD = 4; + + readonly attribute unsigned short unitType; + attribute float value; + // raises DOMException on setting + attribute float valueInSpecifiedUnits; + // raises DOMException on setting + attribute DOMString valueAsString; + // raises DOMException on setting + + void newValueSpecifiedUnits(in unsigned short unitType, in float valueInSpecifiedUnits); + void convertToSpecifiedUnits(in unsigned short unitType); +}; + diff --git a/mozilla/dom/public/idl/svg/nsIDOMSVGAnimatedAngle.idl b/mozilla/dom/public/idl/svg/nsIDOMSVGAnimatedAngle.idl new file mode 100644 index 00000000000..baca7cb0186 --- /dev/null +++ b/mozilla/dom/public/idl/svg/nsIDOMSVGAnimatedAngle.idl @@ -0,0 +1,55 @@ +/* -*- 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) 2004 + * 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 "domstubs.idl" + +interface nsIDOMSVGAngle; + +/** + * The nsIDOMSVGAnimatedAngle interface is the interface to an SVG + * animated angle. + * + * For more information on this interface please see + * http://www.w3.org/TR/SVG11/types.html#InterfaceSVGAnimatedAngle + * + */ + +[scriptable, uuid(c6ab8b9e-32db-464a-ae33-8691d44bc60a)] +interface nsIDOMSVGAnimatedAngle : nsISupports +{ + readonly attribute nsIDOMSVGAngle baseVal; + readonly attribute nsIDOMSVGAngle animVal; +}; diff --git a/mozilla/dom/public/idl/svg/nsIDOMSVGMarkerElement.idl b/mozilla/dom/public/idl/svg/nsIDOMSVGMarkerElement.idl new file mode 100644 index 00000000000..411468616da --- /dev/null +++ b/mozilla/dom/public/idl/svg/nsIDOMSVGMarkerElement.idl @@ -0,0 +1,94 @@ +/* -*- 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 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; +interface nsIDOMSVGAngle; +interface nsIDOMSVGAnimatedAngle; +interface nsIDOMSVGAnimatedRect; +interface nsIDOMSVGMatrix; + +/** + * The nsIDOMSVGMarker interface is the interface to an SVG marker element. + * + * For more information on this interface please see + * http://www.w3.org/TR/SVG11/painting.html#InterfaceSVGMarkerElement + * + */ + +[scriptable, uuid(7d89ceb8-f985-4095-8f24-421910704e5e)] +interface nsIDOMSVGMarkerElement + : 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.) + + nsIDOMSVGLangSpace, + nsIDOMSVGExternalResourcesRequired, + nsIDOMSVGStylable, + nsIDOMSVGFitToViewBox +*/ +{ + // Marker Unit Types + const unsigned short SVG_MARKERUNITS_UNKNOWN = 0; + const unsigned short SVG_MARKERUNITS_USERSPACEONUSE = 1; + const unsigned short SVG_MARKERUNITS_STROKEWIDTH = 2; + // Marker Orientation Types + const unsigned short SVG_MARKER_ORIENT_UNKNOWN = 0; + const unsigned short SVG_MARKER_ORIENT_AUTO = 1; + const unsigned short SVG_MARKER_ORIENT_ANGLE = 2; + + readonly attribute nsIDOMSVGAnimatedLength refX; + readonly attribute nsIDOMSVGAnimatedLength refY; + readonly attribute nsIDOMSVGAnimatedEnumeration markerUnits; + readonly attribute nsIDOMSVGAnimatedLength markerWidth; + readonly attribute nsIDOMSVGAnimatedLength markerHeight; + readonly attribute nsIDOMSVGAnimatedEnumeration orientType; + readonly attribute nsIDOMSVGAnimatedAngle orientAngle; + + void setOrientToAuto ( ); + void setOrientToAngle ( in nsIDOMSVGAngle angle ); + + // Mozilla extension, not part of W3 SVG DOM: + [noscript] nsIDOMSVGMatrix getMarkerTransform(in float strokeWidth, in float x, in float y, in float angle); + [noscript] nsIDOMSVGMatrix getViewboxToViewportTransform( ); +}; diff --git a/mozilla/dom/public/nsIDOMClassInfo.h b/mozilla/dom/public/nsIDOMClassInfo.h index d0a3a8f795e..7170da2d670 100644 --- a/mozilla/dom/public/nsIDOMClassInfo.h +++ b/mozilla/dom/public/nsIDOMClassInfo.h @@ -255,6 +255,7 @@ enum nsDOMClassInfoID { eDOMClassInfo_SVGImageElement_id, eDOMClassInfo_SVGLinearGradientElement_id, eDOMClassInfo_SVGLineElement_id, + eDOMClassInfo_SVGMarkerElement_id, eDOMClassInfo_SVGPathElement_id, eDOMClassInfo_SVGPolygonElement_id, eDOMClassInfo_SVGPolylineElement_id, @@ -270,6 +271,8 @@ enum nsDOMClassInfoID { eDOMClassInfo_SVGUseElement_id, // other SVG classes + eDOMClassInfo_SVGAngle_id, + eDOMClassInfo_SVGAnimatedAngle_id, eDOMClassInfo_SVGAnimatedEnumeration_id, eDOMClassInfo_SVGAnimatedLength_id, eDOMClassInfo_SVGAnimatedLengthList_id, diff --git a/mozilla/dom/src/base/nsDOMClassInfo.cpp b/mozilla/dom/src/base/nsDOMClassInfo.cpp index 332cad02b00..ffa05ab1ab0 100644 --- a/mozilla/dom/src/base/nsDOMClassInfo.cpp +++ b/mozilla/dom/src/base/nsDOMClassInfo.cpp @@ -306,6 +306,8 @@ #include "nsIDOMXPathEvaluator.h" #ifdef MOZ_SVG +#include "nsIDOMSVGAngle.h" +#include "nsIDOMSVGAnimatedAngle.h" #include "nsIDOMSVGAnimatedEnum.h" #include "nsIDOMSVGAnimatedLength.h" #include "nsIDOMSVGAnimatedLengthList.h" @@ -332,6 +334,7 @@ #include "nsIDOMSVGLengthList.h" #include "nsIDOMSVGLineElement.h" #include "nsIDOMSVGLocatable.h" +#include "nsIDOMSVGMarkerElement.h" #include "nsIDOMSVGMatrix.h" #include "nsIDOMSVGNumber.h" #include "nsIDOMSVGNumberList.h" @@ -838,6 +841,8 @@ static nsDOMClassInfoData sClassInfoData[] = { ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGLineElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGMarkerElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGPathElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGPolygonElement, nsElementSH, @@ -866,6 +871,10 @@ static nsDOMClassInfoData sClassInfoData[] = { ELEMENT_SCRIPTABLE_FLAGS) // other SVG classes + NS_DEFINE_CLASSINFO_DATA(SVGAngle, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGAnimatedAngle, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGAnimatedEnumeration, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGAnimatedLength, nsDOMGenericSH, @@ -2364,6 +2373,11 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGMarkerElement, nsIDOMSVGMarkerElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGMarkerElement) + DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGPathElement, nsIDOMSVGPathElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGPathElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedPathData) @@ -2447,6 +2461,14 @@ nsDOMClassInfo::Init() // other SVG classes + DOM_CLASSINFO_MAP_BEGIN(SVGAngle, nsIDOMSVGAngle) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAngle) + DOM_CLASSINFO_MAP_END + + DOM_CLASSINFO_MAP_BEGIN(SVGAnimatedAngle, nsIDOMSVGAnimatedAngle) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedAngle) + DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGAnimatedEnumeration, nsIDOMSVGAnimatedEnumeration) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedEnumeration) DOM_CLASSINFO_MAP_END diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 7bc4f6833d4..e07585b5dc5 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -209,6 +209,8 @@ extern nsresult NS_NewSVGRadialGradientFrame(nsIPresShell *aPresShell, nsIContent *aContent, nsIFrame** newFrame); extern nsresult NS_NewSVGStopFrame(nsIPresShell *aPresShell, nsIContent *aContent, nsIFrame *aParentFrame, nsIFrame** newFrame); +nsresult +NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame); #endif #include "nsIDocument.h" @@ -7290,6 +7292,10 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsIPresShell* aPresShell, processChildren = PR_TRUE; rv = NS_NewSVGUseFrame(aPresShell, aContent, &newFrame); } + else if (aTag == nsSVGAtoms::marker) { + processChildren = PR_TRUE; + rv = NS_NewSVGMarkerFrame(aPresShell, aContent, &newFrame); + } if (newFrame == nsnull) { // Either we have an unknown tag, or construction of a frame diff --git a/mozilla/layout/style/nsCSSDeclaration.cpp b/mozilla/layout/style/nsCSSDeclaration.cpp index 4ba6a52b003..f48d9df142f 100644 --- a/mozilla/layout/style/nsCSSDeclaration.cpp +++ b/mozilla/layout/style/nsCSSDeclaration.cpp @@ -645,6 +645,17 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, } break; } +#ifdef MOZ_SVG + case eCSSProperty_marker: { + nsCSSValue endValue, midValue, startValue; + GetValueOrImportantValue(eCSSProperty_marker_end, endValue); + GetValueOrImportantValue(eCSSProperty_marker_mid, midValue); + GetValueOrImportantValue(eCSSProperty_marker_start, startValue); + if (endValue == midValue && midValue == startValue) + AppendValueToString(eCSSProperty_marker_end, aValue); + break; + } +#endif default: NS_NOTREACHED("no other shorthands"); break; @@ -972,6 +983,35 @@ nsCSSDeclaration::TryOverflowShorthand(nsAString & aString, } } +#ifdef MOZ_SVG +void +nsCSSDeclaration::TryMarkerShorthand(nsAString & aString, + PRInt32 & aMarkerEnd, + PRInt32 & aMarkerMid, + PRInt32 & aMarkerStart) const +{ + PRBool isImportant; + if (aMarkerEnd && aMarkerMid && aMarkerEnd && + AllPropertiesSameImportance(aMarkerEnd, aMarkerMid, aMarkerStart, + 0, 0, 0, isImportant)) { + nsCSSValue endValue, midValue, startValue; + GetValueOrImportantValue(eCSSProperty_marker_end, endValue); + GetValueOrImportantValue(eCSSProperty_marker_mid, midValue); + GetValueOrImportantValue(eCSSProperty_marker_start, startValue); + if (endValue == midValue && midValue == startValue) { + AppendASCIItoUTF16(nsCSSProps::GetStringValue(eCSSProperty_marker), + aString); + aString.AppendLiteral(": "); + + AppendCSSValueToString(eCSSProperty_marker_end, endValue, aString); + AppendImportanceToString(isImportant, aString); + aString.AppendLiteral("; "); + aMarkerEnd = aMarkerMid = aMarkerStart = 0; + } + } +} +#endif + #define NS_CASE_OUTPUT_PROPERTY_VALUE(_prop, _index) \ case _prop: \ if (_index) { \ @@ -1018,6 +1058,10 @@ nsCSSDeclaration::ToString(nsAString& aString) const PRInt32 bgPositionX = 0, bgPositionY = 0; PRInt32 overflowX = 0, overflowY = 0; PRUint32 borderPropertiesSet = 0, finalBorderPropertiesToSet = 0; +#ifdef MOZ_SVG + PRInt32 markerEnd = 0, markerMid = 0, markerStart = 0; +#endif + for (index = 0; index < count; index++) { nsCSSProperty property = OrderValueAt(index); switch (property) { @@ -1080,6 +1124,12 @@ nsCSSDeclaration::ToString(nsAString& aString) const case eCSSProperty_overflow_x: overflowX = index+1; break; case eCSSProperty_overflow_y: overflowY = index+1; break; +#ifdef MOZ_SVG + case eCSSProperty_marker_end: markerEnd = index+1; break; + case eCSSProperty_marker_mid: markerMid = index+1; break; + case eCSSProperty_marker_start: markerStart = index+1; break; +#endif + default: break; } } @@ -1149,6 +1199,9 @@ nsCSSDeclaration::ToString(nsAString& aString) const bgColor, bgImage, bgRepeat, bgAttachment, bgPositionX, bgPositionY); TryOverflowShorthand(aString, overflowX, overflowY); +#ifdef MOZ_SVG + TryMarkerShorthand(aString, markerEnd, markerMid, markerStart); +#endif for (index = 0; index < count; index++) { nsCSSProperty property = OrderValueAt(index); @@ -1227,6 +1280,12 @@ nsCSSDeclaration::ToString(nsAString& aString) const NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_overflow_x, overflowX) NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_overflow_y, overflowY) +#ifdef MOZ_SVG + NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_end, markerEnd) + NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_mid, markerMid) + NS_CASE_OUTPUT_PROPERTY_VALUE(eCSSProperty_marker_start, markerStart) +#endif + case eCSSProperty_margin_left_ltr_source: case eCSSProperty_margin_left_rtl_source: case eCSSProperty_margin_right_ltr_source: diff --git a/mozilla/layout/style/nsCSSDeclaration.h b/mozilla/layout/style/nsCSSDeclaration.h index ead908df86a..adc189ca314 100644 --- a/mozilla/layout/style/nsCSSDeclaration.h +++ b/mozilla/layout/style/nsCSSDeclaration.h @@ -192,6 +192,12 @@ private: PRInt32 & aBgPositionY) const; void TryOverflowShorthand(nsAString & aString, PRInt32 & aOverflowX, PRInt32 & aOverflowY) const; +#ifdef MOZ_SVG + void TryMarkerShorthand(nsAString & aString, + PRInt32 & aMarkerEnd, + PRInt32 & aMarkerMid, + PRInt32 & aMarkerStart) const; +#endif PRBool AllPropertiesSameImportance(PRInt32 aFirst, PRInt32 aSecond, PRInt32 aThird, PRInt32 aFourth, diff --git a/mozilla/layout/style/nsCSSParser.cpp b/mozilla/layout/style/nsCSSParser.cpp index 7a12ebd23d8..69c5314c2ed 100644 --- a/mozilla/layout/style/nsCSSParser.cpp +++ b/mozilla/layout/style/nsCSSParser.cpp @@ -301,6 +301,7 @@ protected: #ifdef MOZ_SVG PRBool ParseDasharray(nsresult& aErrorCode); + PRBool ParseMarker(nsresult& aErrorCode); #endif // Reused utility parsing routines @@ -4001,6 +4002,13 @@ PRBool CSSParserImpl::ParseProperty(nsresult& aErrorCode, case eCSSProperty_text_shadow: return ParseTextShadow(aErrorCode); +#ifdef MOZ_SVG + case eCSSProperty_stroke_dasharray: + return ParseDasharray(aErrorCode); + case eCSSProperty_marker: + return ParseMarker(aErrorCode); +#endif + // Strip out properties we use internally. These properties are used // by compound property parsing routines (e.g. "background-position"). case eCSSProperty_background_x_position: @@ -4025,11 +4033,6 @@ PRBool CSSParserImpl::ParseProperty(nsresult& aErrorCode, REPORT_UNEXPECTED(PEInaccessibleProperty); return PR_FALSE; -#ifdef MOZ_SVG - case eCSSProperty_stroke_dasharray: - return ParseDasharray(aErrorCode); -#endif - default: // must be single property { nsCSSValue value; @@ -4121,6 +4124,7 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode, case eCSSProperty_COUNT: #ifdef MOZ_SVG case eCSSProperty_stroke_dasharray: + case eCSSProperty_marker: #endif NS_ERROR("not a single value property"); return PR_FALSE; @@ -4240,6 +4244,10 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode, case eCSSProperty_fill_rule: return ParseVariant(aErrorCode, aValue, VARIANT_HK, nsCSSProps::kFillRuleKTable); + case eCSSProperty_marker_end: + case eCSSProperty_marker_mid: + case eCSSProperty_marker_start: + return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull); case eCSSProperty_pointer_events: return ParseVariant(aErrorCode, aValue, VARIANT_HK, nsCSSProps::kPointerEventsKTable); @@ -5798,4 +5806,19 @@ PRBool CSSParserImpl::ParseDasharray(nsresult& aErrorCode) } return PR_FALSE; } + +PRBool CSSParserImpl::ParseMarker(nsresult& aErrorCode) +{ + nsCSSValue marker; + if (ParseSingleValueProperty(aErrorCode, marker, eCSSProperty_marker_end)) { + if (ExpectEndProperty(aErrorCode, PR_TRUE)) { + AppendValue(eCSSProperty_marker_end, marker); + AppendValue(eCSSProperty_marker_mid, marker); + AppendValue(eCSSProperty_marker_start, marker); + aErrorCode = NS_OK; + return PR_TRUE; + } + } + return PR_FALSE; +} #endif diff --git a/mozilla/layout/style/nsCSSPropList.h b/mozilla/layout/style/nsCSSPropList.h index 464a194e74f..51b433fa3c6 100644 --- a/mozilla/layout/style/nsCSSPropList.h +++ b/mozilla/layout/style/nsCSSPropList.h @@ -477,6 +477,10 @@ CSS_PROP_SVGRESET(dominant-baseline, dominant_baseline, DominantBaseline, SVG, m 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_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_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_SVG(stop-color, stop_color, StopColor, SVG, mStopColor, eCSSType_Value, nsnull) diff --git a/mozilla/layout/style/nsCSSProps.cpp b/mozilla/layout/style/nsCSSProps.cpp index c166d794b57..4193019c1d2 100644 --- a/mozilla/layout/style/nsCSSProps.cpp +++ b/mozilla/layout/style/nsCSSProps.cpp @@ -1405,6 +1405,15 @@ static const nsCSSProperty gPauseSubpropTable[] = { eCSSProperty_UNKNOWN }; +#ifdef MOZ_SVG +static const nsCSSProperty gMarkerSubpropTable[] = { + eCSSProperty_marker_start, + eCSSProperty_marker_mid, + eCSSProperty_marker_end, + eCSSProperty_UNKNOWN +}; +#endif + const nsCSSProperty *const nsCSSProps::kSubpropertyTable[eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands] = { #define CSS_PROP_SHORTHAND(name_, id_, method_) g##method_##SubpropTable, diff --git a/mozilla/layout/style/nsCSSStruct.cpp b/mozilla/layout/style/nsCSSStruct.cpp index c697ae12479..eb1edc563e2 100644 --- a/mozilla/layout/style/nsCSSStruct.cpp +++ b/mozilla/layout/style/nsCSSStruct.cpp @@ -1208,6 +1208,9 @@ nsCSSSVG::nsCSSSVG(const nsCSSSVG& aCopy) mFill(aCopy.mFill), mFillOpacity(aCopy.mFillOpacity), mFillRule(aCopy.mFillRule), + mMarkerEnd(aCopy.mMarkerEnd), + mMarkerMid(aCopy.mMarkerMid), + mMarkerStart(aCopy.mMarkerStart), mPointerEvents(aCopy.mPointerEvents), mShapeRendering(aCopy.mShapeRendering), mStopColor(aCopy.mStopColor), @@ -1244,6 +1247,9 @@ void nsCSSSVG::List(FILE* out, PRInt32 aIndent) const mFill.AppendToString(buffer, eCSSProperty_fill); mFillOpacity.AppendToString(buffer, eCSSProperty_fill_opacity); mFillRule.AppendToString(buffer, eCSSProperty_fill_rule); + mMarkerEnd.AppendToString(buffer, eCSSProperty_marker_end); + mMarkerMid.AppendToString(buffer, eCSSProperty_marker_mid); + mMarkerStart.AppendToString(buffer, eCSSProperty_marker_start); mPointerEvents.AppendToString(buffer, eCSSProperty_pointer_events); mShapeRendering.AppendToString(buffer, eCSSProperty_shape_rendering); mStopColor.AppendToString(buffer, eCSSProperty_stop_color); diff --git a/mozilla/layout/style/nsCSSStruct.h b/mozilla/layout/style/nsCSSStruct.h index 6da403cb462..f5cc072da11 100644 --- a/mozilla/layout/style/nsCSSStruct.h +++ b/mozilla/layout/style/nsCSSStruct.h @@ -578,6 +578,9 @@ struct nsCSSSVG : public nsCSSStruct { nsCSSValue mFill; nsCSSValue mFillOpacity; nsCSSValue mFillRule; + nsCSSValue mMarkerEnd; + nsCSSValue mMarkerMid; + nsCSSValue mMarkerStart; nsCSSValue mPointerEvents; nsCSSValue mShapeRendering; nsCSSValue mStopColor; diff --git a/mozilla/layout/style/nsRuleNode.cpp b/mozilla/layout/style/nsRuleNode.cpp index 42bd55830ad..d44e4dd97ab 100644 --- a/mozilla/layout/style/nsRuleNode.cpp +++ b/mozilla/layout/style/nsRuleNode.cpp @@ -4446,6 +4446,36 @@ nsRuleNode::ComputeSVGData(nsStyleStruct* aStartStruct, inherited = PR_TRUE; svg->mFillRule = parentSVG->mFillRule; } + + // marker-end: url, none, inherit + if (eCSSUnit_URL == SVGData.mMarkerEnd.GetUnit()) { + svg->mMarkerEnd = SVGData.mMarkerEnd.GetURLValue(); + } else if (eCSSUnit_None == SVGData.mMarkerEnd.GetUnit()) { + svg->mMarkerEnd = nsnull; + } else if (eCSSUnit_Inherit == SVGData.mMarkerEnd.GetUnit()) { + inherited = PR_TRUE; + svg->mMarkerEnd = parentSVG->mMarkerEnd; + } + + // marker-mid: url, none, inherit + if (eCSSUnit_URL == SVGData.mMarkerMid.GetUnit()) { + svg->mMarkerMid = SVGData.mMarkerMid.GetURLValue(); + } else if (eCSSUnit_None == SVGData.mMarkerMid.GetUnit()) { + svg->mMarkerMid = nsnull; + } else if (eCSSUnit_Inherit == SVGData.mMarkerMid.GetUnit()) { + inherited = PR_TRUE; + svg->mMarkerMid = parentSVG->mMarkerMid; + } + + // marker-start: url, none, inherit + if (eCSSUnit_URL == SVGData.mMarkerStart.GetUnit()) { + svg->mMarkerStart = SVGData.mMarkerStart.GetURLValue(); + } else if (eCSSUnit_None == SVGData.mMarkerStart.GetUnit()) { + svg->mMarkerStart = nsnull; + } else if (eCSSUnit_Inherit == SVGData.mMarkerStart.GetUnit()) { + inherited = PR_TRUE; + svg->mMarkerStart = parentSVG->mMarkerStart; + } // stop-color: SetSVGPaint(SVGData.mStopColor, parentSVG->mStopColor, mPresContext, svg->mStopColor, inherited); diff --git a/mozilla/layout/style/nsStyleContext.cpp b/mozilla/layout/style/nsStyleContext.cpp index effbb1b2a18..ce617b39524 100644 --- a/mozilla/layout/style/nsStyleContext.cpp +++ b/mozilla/layout/style/nsStyleContext.cpp @@ -864,9 +864,12 @@ void nsStyleContext::DumpRegressionData(nsPresContext* aPresContext, FILE* out, fprintf(out, "%s ", URICString(svg->mFill.mPaint.mPaintServer).get()); else fprintf(out, "%ld ", (long)svg->mFill.mPaint.mColor); - fprintf(out, "%f %d %d %d %d ", + fprintf(out, "%f %d %s %s %s %d %d %d ", svg->mFillOpacity, (int)svg->mFillRule, + URICString(svg->mMarkerEnd).get(), + URICString(svg->mMarkerMid).get(), + URICString(svg->mMarkerStart).get(), (int)svg->mPointerEvents, (int)svg->mShapeRendering, (int)svg->mStroke.mType); diff --git a/mozilla/layout/style/nsStyleStruct.cpp b/mozilla/layout/style/nsStyleStruct.cpp index 029d181b458..ef81f65cdfb 100644 --- a/mozilla/layout/style/nsStyleStruct.cpp +++ b/mozilla/layout/style/nsStyleStruct.cpp @@ -857,6 +857,9 @@ nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource) mFill = aSource.mFill; mFillOpacity = aSource.mFillOpacity; mFillRule = aSource.mFillRule; + mMarkerEnd = aSource.mMarkerEnd; + mMarkerMid = aSource.mMarkerMid; + mMarkerEnd = aSource.mMarkerStart; mPointerEvents = aSource.mPointerEvents; mShapeRendering = aSource.mShapeRendering; mStopColor = aSource.mStopColor; @@ -889,6 +892,9 @@ nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const if ( mFill != aOther.mFill || mFillOpacity != aOther.mFillOpacity || mFillRule != aOther.mFillRule || + !EqualURIs(mMarkerEnd, aOther.mMarkerEnd) || + !EqualURIs(mMarkerMid, aOther.mMarkerMid) || + !EqualURIs(mMarkerStart, aOther.mMarkerStart) || mPointerEvents != aOther.mPointerEvents || mShapeRendering != aOther.mShapeRendering || mStopColor != aOther.mStopColor || diff --git a/mozilla/layout/style/nsStyleStruct.h b/mozilla/layout/style/nsStyleStruct.h index b3e8b04c48f..818a0f38cfe 100644 --- a/mozilla/layout/style/nsStyleStruct.h +++ b/mozilla/layout/style/nsStyleStruct.h @@ -1246,6 +1246,9 @@ struct nsStyleSVG : public nsStyleStruct { nsStyleSVGPaint mFill; // [inherited] float mFillOpacity; // [inherited] PRUint8 mFillRule; // [inherited] see nsStyleConsts.h + nsCOMPtr mMarkerEnd; // [inherited] + nsCOMPtr mMarkerMid; // [inherited] + nsCOMPtr mMarkerStart; // [inherited] PRUint8 mPointerEvents; // [inherited] see nsStyleConsts.h PRUint8 mShapeRendering; // [inherited] see nsStyleConsts.h nsStyleSVGPaint mStopColor; // [inherited] diff --git a/mozilla/layout/svg/base/src/Makefile.in b/mozilla/layout/svg/base/src/Makefile.in index 42c7f92c7b9..81a12c54441 100644 --- a/mozilla/layout/svg/base/src/Makefile.in +++ b/mozilla/layout/svg/base/src/Makefile.in @@ -71,6 +71,7 @@ CPPSRCS = \ nsSVGGradientFrame.cpp \ nsSVGInnerSVGFrame.cpp \ nsSVGLineFrame.cpp \ + nsSVGMarkerFrame.cpp \ nsSVGOuterSVGFrame.cpp \ nsSVGPathFrame.cpp \ nsSVGPathGeometryFrame.cpp \ diff --git a/mozilla/layout/svg/base/src/nsISVGMarkable.h b/mozilla/layout/svg/base/src/nsISVGMarkable.h new file mode 100644 index 00000000000..24bf0adc13a --- /dev/null +++ b/mozilla/layout/svg/base/src/nsISVGMarkable.h @@ -0,0 +1,55 @@ +/* -*- 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 of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __NS_ISVGMARKABLE_H__ +#define __NS_ISVGMARKABLE_H__ + +#define NS_ISVGMARKABLE_IID \ +{0x6c4f9a33, 0x4461, 0x419c, {0x82, 0xf8, 0x6b, 0x78, 0x3b, 0xcf, 0x85, 0x97}} + +struct nsSVGMark { + float x, y, angle; +}; + +class nsISVGMarkable : public nsISupports { +public: + + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISVGMARKABLE_IID) + + virtual void GetMarkPoints(nsVoidArray *aMarks) = 0; +}; + +#endif diff --git a/mozilla/layout/svg/base/src/nsSVGDefsFrame.cpp b/mozilla/layout/svg/base/src/nsSVGDefsFrame.cpp index f5bb91b6f05..28db50b4741 100644 --- a/mozilla/layout/svg/base/src/nsSVGDefsFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGDefsFrame.cpp @@ -55,14 +55,6 @@ NS_NewSVGDefsFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aN { *aNewFrame = nsnull; - nsCOMPtr transformable = do_QueryInterface(aContent); - if (!transformable) { -#ifdef DEBUG - printf("warning: trying to construct an SVGDefsFrame for a content element that doesn't support the right interfaces\n"); -#endif - return NS_ERROR_FAILURE; - } - nsSVGDefsFrame* it = new (aPresShell) nsSVGDefsFrame; if (nsnull == it) return NS_ERROR_OUT_OF_MEMORY; @@ -79,7 +71,9 @@ nsSVGDefsFrame::nsSVGDefsFrame() nsSVGDefsFrame::~nsSVGDefsFrame() { nsCOMPtr transformable = do_QueryInterface(mContent); - NS_ASSERTION(transformable, "wrong content element"); + if (!transformable) + return; + nsCOMPtr transforms; transformable->GetTransform(getter_AddRefs(transforms)); nsCOMPtr value = do_QueryInterface(transforms); @@ -91,7 +85,9 @@ nsSVGDefsFrame::~nsSVGDefsFrame() nsresult nsSVGDefsFrame::Init() { nsCOMPtr transformable = do_QueryInterface(mContent); - NS_ASSERTION(transformable, "wrong content element"); + if (!transformable) + return NS_OK; + nsCOMPtr transforms; transformable->GetTransform(getter_AddRefs(transforms)); nsCOMPtr value = do_QueryInterface(transforms); diff --git a/mozilla/layout/svg/base/src/nsSVGLineFrame.cpp b/mozilla/layout/svg/base/src/nsSVGLineFrame.cpp index 60263dfc76e..9f751819596 100644 --- a/mozilla/layout/svg/base/src/nsSVGLineFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGLineFrame.cpp @@ -45,8 +45,10 @@ #include "nsIDOMSVGElement.h" #include "nsIDOMSVGSVGElement.h" #include "nsISVGRendererPathBuilder.h" +#include "nsISVGMarkable.h" -class nsSVGLineFrame : public nsSVGPathGeometryFrame +class nsSVGLineFrame : public nsSVGPathGeometryFrame, + public nsISVGMarkable { protected: friend nsresult @@ -61,14 +63,27 @@ public: // nsISVGPathGeometrySource interface: NS_IMETHOD ConstructPath(nsISVGRendererPathBuilder *pathBuilder); - + + // nsISVGMarkable interface + void GetMarkPoints(nsVoidArray *aMarks); + + // nsISupports interface: + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + nsCOMPtr mX1; nsCOMPtr mY1; nsCOMPtr mX2; nsCOMPtr mY2; }; +NS_INTERFACE_MAP_BEGIN(nsSVGLineFrame) + NS_INTERFACE_MAP_ENTRY(nsISVGMarkable) +NS_INTERFACE_MAP_END_INHERITING(nsSVGPathGeometryFrame) + //---------------------------------------------------------------------- // Implementation @@ -196,8 +211,28 @@ NS_IMETHODIMP nsSVGLineFrame::ConstructPath(nsISVGRendererPathBuilder* pathBuild return NS_OK; } -// const nsStyleSVG* nsSVGLineFrame::GetStyle() -// { -// // XXX TODO: strip out any fill color as per svg specs -// return nsSVGGraphicFrame::GetStyle(); -// } +//---------------------------------------------------------------------- +// nsISVGMarkable methods: + +void +nsSVGLineFrame::GetMarkPoints(nsVoidArray *aMarks) { + float x1,y1,x2,y2; + + mX1->GetValue(&x1); + mY1->GetValue(&y1); + mX2->GetValue(&x2); + mY2->GetValue(&y2); + + nsSVGMark *m1, *m2; + m1 = new nsSVGMark(); + m2 = new nsSVGMark(); + + m1->x = x1; + m1->y = y1; + m2->x = x2; + m2->y = y2; + m1->angle = m2->angle = atan2(y2-y1, x2-x1); + + aMarks->AppendElement(m1); + aMarks->AppendElement(m2); +} diff --git a/mozilla/layout/svg/base/src/nsSVGMarkerFrame.cpp b/mozilla/layout/svg/base/src/nsSVGMarkerFrame.cpp new file mode 100644 index 00000000000..f84baf07a32 --- /dev/null +++ b/mozilla/layout/svg/base/src/nsSVGMarkerFrame.cpp @@ -0,0 +1,384 @@ +/* -*- 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 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 "nsIDOMSVGFitToViewBox.h" +#include "nsIDOMSVGAnimatedLength.h" +#include "nsIDOMSVGAnimatedEnum.h" +#include "nsIDOMSVGAnimatedAngle.h" +#include "nsIDOMSVGAnimatedRect.h" +#include "nsIDOMSVGAngle.h" +#include "nsIDOMSVGLength.h" +#include "nsIDOMSVGPoint.h" +#include "nsIDOMSVGRect.h" +#include "nsIDOMSVGRectElement.h" +#include "nsIDOMSVGElement.h" +#include "nsIDOMSVGSVGElement.h" +#include "nsISVGRendererPathBuilder.h" +#include "nsSVGDefsFrame.h" +#include "nsISVGValue.h" +#include "nsIDOMSVGMarkerElement.h" +#include "nsIDOMDocument.h" +#include "nsIDocument.h" +#include "nsSVGMarkerFrame.h" +#include "nsSVGPathGeometryFrame.h" + +NS_IMETHODIMP_(nsrefcnt) + nsSVGMarkerFrame::AddRef() +{ + return NS_OK; +} + +NS_IMETHODIMP_(nsrefcnt) + nsSVGMarkerFrame::Release() +{ + return NS_OK; +} + +// Trying to implement a QueryInterfacable class without a nsIFoo class. +// Couldn't find a macro incantation for this situation, so roll by hand. +NS_IMETHODIMP +nsSVGMarkerFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (nsnull == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(nsSVGMarkerFrame::GetCID())) { + *aInstancePtr = (void*)(nsSVGMarkerFrame*)this; + NS_ADDREF_THIS(); + return NS_OK; + } + return (nsSVGDefsFrame::QueryInterface(aIID, aInstancePtr)); +} + +nsresult +NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame) +{ + *aNewFrame = nsnull; + + nsSVGMarkerFrame* it = new (aPresShell) nsSVGMarkerFrame; + if (nsnull == it) + return NS_ERROR_OUT_OF_MEMORY; + + *aNewFrame = it; + + return NS_OK; +} + +nsresult +NS_GetSVGMarkerFrame(nsSVGMarkerFrame **aResult, nsIURI *aURI, nsIContent *aContent) +{ + nsresult rv; + *aResult = nsnull; + + nsCAutoString uriSpec; + aURI->GetSpec(uriSpec); + + // Get ID from spec + PRInt32 pos = uriSpec.FindChar('#'); + if (pos == -1) { + NS_ASSERTION(pos != -1, "URI Spec not a reference"); + return NS_ERROR_FAILURE; + } + + // Strip off hash and get name + nsCAutoString idC; + uriSpec.Right(idC, uriSpec.Length() - (pos + 1)); + + // Convert to unicode + nsAutoString id; + CopyUTF8toUTF16(idC, id); + + // Get document + nsCOMPtr doc = do_QueryInterface(aContent->GetDocument()); + NS_ASSERTION(doc, "Content doesn't reference a dom Document"); + if (!doc) + return NS_ERROR_FAILURE; + + // Get element + nsCOMPtr element; + nsCOMPtr ps = do_QueryInterface(aContent->GetDocument()->GetShellAt(0)); + rv = doc->GetElementById(id, getter_AddRefs(element)); + if (!NS_SUCCEEDED(rv) || element == nsnull) + return rv; + + nsIFrame *frame; + nsCOMPtr content = do_QueryInterface(element); + rv = ps->GetPrimaryFrameFor(content, &frame); + +// see comment preceeding nsSVGMarkerFrame::QueryInterface +// nsCOMPtr marker = do_QueryInterface(frame); + nsSVGMarkerFrame *marker; + CallQueryInterface(frame, &marker); + *aResult = marker; + return rv; +} + +nsSVGMarkerFrame::~nsSVGMarkerFrame() +{ + nsCOMPtr value; + if (mRefX && (value = do_QueryInterface(mRefX))) + value->RemoveObserver(this); + if (mRefY && (value = do_QueryInterface(mRefY))) + value->RemoveObserver(this); + if (mMarkerWidth && (value = do_QueryInterface(mMarkerWidth))) + value->RemoveObserver(this); + if (mMarkerHeight && (value = do_QueryInterface(mMarkerHeight))) + value->RemoveObserver(this); + if (mOrientAngle && (value = do_QueryInterface(mOrientAngle))) + value->RemoveObserver(this); + if (mViewBox && (value = do_QueryInterface(mViewBox))) + value->RemoveObserver(this); +} + +nsresult nsSVGMarkerFrame::Init() +{ + nsresult rv = nsSVGDefsFrame::Init(); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr marker = do_QueryInterface(mContent); + NS_ASSERTION(marker, "wrong content element"); + + { + nsCOMPtr length; + marker->GetRefX(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mRefX)); + NS_ASSERTION(mRefX, "no RefX"); + if (!mRefX) return NS_ERROR_FAILURE; + nsCOMPtr value = do_QueryInterface(mRefX); + if (value) + value->AddObserver(this); + } + + { + nsCOMPtr length; + marker->GetRefY(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mRefY)); + NS_ASSERTION(mRefY, "no RefY"); + if (!mRefY) return NS_ERROR_FAILURE; + nsCOMPtr value = do_QueryInterface(mRefY); + if (value) + value->AddObserver(this); + } + + { + nsCOMPtr length; + marker->GetMarkerWidth(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mMarkerWidth)); + NS_ASSERTION(mMarkerWidth, "no markerWidth"); + if (!mMarkerWidth) return NS_ERROR_FAILURE; + nsCOMPtr value = do_QueryInterface(mMarkerWidth); + if (value) + value->AddObserver(this); + } + + { + nsCOMPtr length; + marker->GetMarkerHeight(getter_AddRefs(length)); + length->GetBaseVal(getter_AddRefs(mMarkerHeight)); + NS_ASSERTION(mMarkerHeight, "no markerHeight"); + if (!mMarkerHeight) return NS_ERROR_FAILURE; + nsCOMPtr value = do_QueryInterface(mMarkerHeight); + if (value) + value->AddObserver(this); + } + + { + nsCOMPtr angle; + marker->GetOrientAngle(getter_AddRefs(angle)); + angle->GetBaseVal(getter_AddRefs(mOrientAngle)); + NS_ASSERTION(mOrientAngle, "no orientAngle"); + if (!mOrientAngle) return NS_ERROR_FAILURE; + nsCOMPtr value = do_QueryInterface(mOrientAngle); + if (value) + value->AddObserver(this); + } + + { + nsCOMPtr rect; + nsCOMPtr box = do_QueryInterface(marker); + box->GetViewBox(getter_AddRefs(rect)); + + if (rect) { + rect->GetBaseVal(getter_AddRefs(mViewBox)); + NS_ASSERTION(mRefY, "no viewBox"); + if (!mRefY) return NS_ERROR_FAILURE; + nsCOMPtr value = do_QueryInterface(mRefY); + if (value) + value->AddObserver(this); + } + } + + marker->GetMarkerUnits(getter_AddRefs(mMarkerUnits)); + marker->GetOrientType(getter_AddRefs(mOrientType)); + + mMarkerParent = NULL; + + return NS_OK; +} + +//---------------------------------------------------------------------- +// nsISVGValueObserver methods: + +NS_IMETHODIMP +nsSVGMarkerFrame::DidModifySVGObservable(nsISVGValue* observable) +{ + return nsSVGDefsFrame::DidModifySVGObservable(observable); +} + +//---------------------------------------------------------------------- +// nsISVGContainerFrame methods: +already_AddRefed +nsSVGMarkerFrame::GetCanvasTM() +{ + // get our parent's tm and append local transform + nsCOMPtr parentTM; + if (mMarkerParent) { + nsISVGGeometrySource *geometrySource; + mMarkerParent->QueryInterface(NS_GET_IID(nsISVGGeometrySource), + (void**)&geometrySource); + if (!geometrySource) { + NS_ERROR("invalid parent"); + return nsnull; + } + geometrySource->GetCanvasTM(getter_AddRefs(parentTM)); + } else { + // + nsISVGContainerFrame *containerFrame; + mParent->QueryInterface(NS_GET_IID(nsISVGContainerFrame), + (void**)&containerFrame); + if (!containerFrame) { + NS_ERROR("invalid parent"); + return nsnull; + } + parentTM = containerFrame->GetCanvasTM(); + } + NS_ASSERTION(parentTM, "null TM"); + + + // get element + nsCOMPtr element = do_QueryInterface(mContent); + + // scale/move marker + nsCOMPtr markerTM; + element->GetMarkerTransform(mStrokeWidth, mX, mY, mAngle, getter_AddRefs(markerTM)); + + // viewport marker + nsCOMPtr viewTM; + element->GetViewboxToViewportTransform(getter_AddRefs(viewTM)); + + nsCOMPtr tmpTM; + nsCOMPtr resultTM; + + parentTM->Multiply(markerTM, getter_AddRefs(tmpTM)); + tmpTM->Multiply(viewTM, getter_AddRefs(resultTM)); + + nsIDOMSVGMatrix *retval = resultTM.get(); + NS_IF_ADDREF(retval); + return retval; +} + + +void +nsSVGMarkerFrame::PaintMark(nsISVGRendererCanvas *aCanvas, + nsSVGPathGeometryFrame *aParent, + nsSVGMark *aMark, float aStrokeWidth) +{ + mStrokeWidth = aStrokeWidth; + mX = aMark->x; + mY = aMark->y; + mAngle = aMark->angle; + mMarkerParent = aParent; + + nsRect dirtyRectTwips; + for (nsIFrame* kid = mFrames.FirstChild(); kid; + kid = kid->GetNextSibling()) { + nsISVGChildFrame* SVGFrame=nsnull; + kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); + if (SVGFrame) { + SVGFrame->NotifyCanvasTMChanged(); + SVGFrame->Paint(aCanvas, dirtyRectTwips); + } + } +} + + +NS_IMETHODIMP_(already_AddRefed) + nsSVGMarkerFrame::RegionMark(nsSVGPathGeometryFrame *aParent, + nsSVGMark *aMark, float aStrokeWidth) +{ + mStrokeWidth = aStrokeWidth; + mX = aMark->x; + mY = aMark->y; + mAngle = aMark->angle; + mMarkerParent = aParent; + + nsISVGRendererRegion *accu_region=nsnull; + + nsIFrame* kid = mFrames.FirstChild(); + while (kid) { + nsISVGChildFrame* SVGFrame=0; + kid->QueryInterface(NS_GET_IID(nsISVGChildFrame),(void**)&SVGFrame); + if (SVGFrame) { + SVGFrame->NotifyCanvasTMChanged(); + + nsCOMPtr dirty_region = SVGFrame->GetCoveredRegion(); + if (dirty_region) { + if (accu_region) { + nsCOMPtr temp = dont_AddRef(accu_region); + dirty_region->Combine(temp, &accu_region); + } + else { + accu_region = dirty_region; + NS_IF_ADDREF(accu_region); + } + } + } + kid = kid->GetNextSibling(); + } + + return accu_region; +} + + +float +nsSVGMarkerFrame::bisect(float a1, float a2) +{ + if (a2 - a1 < M_PI) + return (a1+a2)/2; + else + return M_PI + (a1+a2)/2; +} diff --git a/mozilla/layout/svg/base/src/nsSVGMarkerFrame.h b/mozilla/layout/svg/base/src/nsSVGMarkerFrame.h new file mode 100644 index 00000000000..27193dfb3f8 --- /dev/null +++ b/mozilla/layout/svg/base/src/nsSVGMarkerFrame.h @@ -0,0 +1,110 @@ +/* -*- 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 of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __NS_SVGMARKERFRAME_H__ +#define __NS_SVGMARKERFRAME_H__ + +#include "nsSVGDefsFrame.h" +#include "nsIDOMSVGLength.h" +#include "nsIDOMSVGAngle.h" +#include "nsIDOMSVGRect.h" +#include "nsIDOMSVGAnimatedEnum.h" +#include "nsISVGMarkable.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +class nsSVGPathGeometryFrame; + +#define NS_SVGMARKERFRAME_CID \ +{0x899a645c, 0xf817, 0x4a1a, {0xaa, 0x3d, 0xa9, 0x1a, 0xbf, 0xa2, 0xb2, 0x0a}} + +class nsSVGMarkerFrame : public nsSVGDefsFrame +{ +protected: + friend nsresult + NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, + nsIContent* aContent, + nsIFrame** aNewFrame); + + virtual ~nsSVGMarkerFrame(); + virtual nsresult Init(); + +public: + NS_DECL_ISUPPORTS + + NS_DEFINE_STATIC_CID_ACCESSOR(NS_SVGMARKERFRAME_CID) + NS_DEFINE_STATIC_IID_ACCESSOR(NS_SVGMARKERFRAME_CID) + + // nsISVGValueObserver interface: + NS_IMETHOD DidModifySVGObservable(nsISVGValue* observable); + + void PaintMark(nsISVGRendererCanvas *aCanvas, + nsSVGPathGeometryFrame *aParent, + nsSVGMark *aMark, + float aStrokeWidth); + + NS_IMETHOD_(already_AddRefed) + RegionMark(nsSVGPathGeometryFrame *aParent, + nsSVGMark *aMark, float aStrokeWidth); + + static float bisect(float a1, float a2); + +private: + nsCOMPtr mRefX; + nsCOMPtr mRefY; + nsCOMPtr mMarkerUnits; + nsCOMPtr mMarkerWidth; + nsCOMPtr mMarkerHeight; + nsCOMPtr mOrientType; + nsCOMPtr mOrientAngle; + nsCOMPtr mViewBox; + + // stuff needed for callback + float mStrokeWidth, mX, mY, mAngle; + nsSVGPathGeometryFrame *mMarkerParent; + + // nsISVGContainerFrame interface: + already_AddRefed GetCanvasTM(); +}; + +nsresult +NS_GetSVGMarkerFrame(nsSVGMarkerFrame **aResult, + nsIURI *aURI, + nsIContent *aContent); + +#endif diff --git a/mozilla/layout/svg/base/src/nsSVGPathFrame.cpp b/mozilla/layout/svg/base/src/nsSVGPathFrame.cpp index cc2053633ba..56828505701 100644 --- a/mozilla/layout/svg/base/src/nsSVGPathFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGPathFrame.cpp @@ -45,8 +45,11 @@ #include "nsIDOMSVGPathSeg.h" #include "nsIDOMSVGMatrix.h" #include "nsISVGRendererPathBuilder.h" +#include "nsISVGMarkable.h" +#include "nsISupports.h" -class nsSVGPathFrame : public nsSVGPathGeometryFrame +class nsSVGPathFrame : public nsSVGPathGeometryFrame, + public nsISVGMarkable { protected: friend nsresult @@ -62,10 +65,23 @@ public: // nsISVGPathGeometrySource interface: NS_IMETHOD ConstructPath(nsISVGRendererPathBuilder *pathBuilder); -private: + // nsISVGMarkable interface + void GetMarkPoints(nsVoidArray *aMarks); + + // nsISupports interface: + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + nsCOMPtr mSegments; }; +NS_INTERFACE_MAP_BEGIN(nsSVGPathFrame) + NS_INTERFACE_MAP_ENTRY(nsISVGMarkable) +NS_INTERFACE_MAP_END_INHERITING(nsSVGPathGeometryFrame) + //---------------------------------------------------------------------- // Implementation @@ -476,3 +492,447 @@ NS_IMETHODIMP nsSVGPathFrame::ConstructPath(nsISVGRendererPathBuilder* pathBuild return NS_OK; } + +static float +calcAngle(float ux, float uy, float vx, float vy) +{ + float ta = atan2(uy, ux); + float tb = atan2(vy, vx); + if (tb >= ta) + return tb-ta; + return 2*M_PI - (ta-tb); +} + +//---------------------------------------------------------------------- +// nsISVGMarkable methods: + +void +nsSVGPathFrame::GetMarkPoints(nsVoidArray *aMarks) { + PRUint32 count; + mSegments->GetNumberOfItems(&count); + nsCOMPtr segment; + + float cx = 0.0f; // current point + float cy = 0.0f; + + float cx1 = 0.0f; // last controlpoint (for s,S,t,T) + float cy1 = 0.0f; + + PRUint16 lastSegmentType = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN; + + float px, py; // subpath initial point + float pathAngle, pathIndex; + + float prevAngle = 0, startAngle, endAngle; + + PRBool newSegment = PR_FALSE; + + PRUint32 i; + for (i = 0; i < count; ++i) { + nsCOMPtr segment; + mSegments->GetItem(i, getter_AddRefs(segment)); + + PRUint16 type = nsIDOMSVGPathSeg::PATHSEG_UNKNOWN; + segment->GetPathSegType(&type); + + float x, y; + PRBool absCoords = PR_FALSE; + + switch (type) { + case nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH: + { + x = px; + y = py; + startAngle = endAngle = atan2(y - cy, x - cx); + } + break; + + case nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS: + absCoords = PR_TRUE; + case nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL: + { + if (!absCoords) { + nsCOMPtr moveseg = do_QueryInterface(segment); + NS_ASSERTION(moveseg, "interface not implemented"); + moveseg->GetX(&x); + moveseg->GetY(&y); + x += cx; + y += cy; + } else { + nsCOMPtr moveseg = do_QueryInterface(segment); + NS_ASSERTION(moveseg, "interface not implemented"); + moveseg->GetX(&x); + moveseg->GetY(&y); + } + px = x; + py = y; + startAngle = endAngle = prevAngle; + newSegment = PR_TRUE; + } + break; + + case nsIDOMSVGPathSeg::PATHSEG_LINETO_ABS: + absCoords = PR_TRUE; + case nsIDOMSVGPathSeg::PATHSEG_LINETO_REL: + { + if (!absCoords) { + nsCOMPtr lineseg = do_QueryInterface(segment); + NS_ASSERTION(lineseg, "interface not implemented"); + lineseg->GetX(&x); + lineseg->GetY(&y); + x += cx; + y += cy; + } else { + nsCOMPtr lineseg = do_QueryInterface(segment); + NS_ASSERTION(lineseg, "interface not implemented"); + lineseg->GetX(&x); + lineseg->GetY(&y); + } + startAngle = endAngle = atan2(y - cy, x - cx); + } + break; + + case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS: + absCoords = PR_TRUE; + case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL: + { + float x1, y1, x2, y2; + if (!absCoords) { + nsCOMPtr curveseg = do_QueryInterface(segment); + NS_ASSERTION(curveseg, "interface not implemented"); + curveseg->GetX(&x); + curveseg->GetY(&y); + curveseg->GetX1(&x1); + curveseg->GetY1(&y1); + curveseg->GetX2(&x2); + curveseg->GetY2(&y2); + x += cx; + y += cy; + x1 += cx; + y1 += cy; + x2 += cx; + y2 += cy; + } else { + nsCOMPtr curveseg = do_QueryInterface(segment); + NS_ASSERTION(curveseg, "interface not implemented"); + curveseg->GetX(&x); + curveseg->GetY(&y); + curveseg->GetX1(&x1); + curveseg->GetY1(&y1); + curveseg->GetX2(&x2); + curveseg->GetY2(&y2); + } + + cx1 = x2; + cy1 = y2; + + if (x1 == cx && y1 == cy) { + x1 = x2; + y1 = y2; + } + + if (x2 == x && y2 == y) { + x2 = x1; + y2 = y1; + } + + startAngle = atan2(y1 - cy, x1 - cx); + endAngle = atan2(y - y2, x - x2); + } + break; + + case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS: + absCoords = PR_TRUE; + case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL: + { + float x1, y1; + + if (!absCoords) { + nsCOMPtr curveseg = do_QueryInterface(segment); + NS_ASSERTION(curveseg, "interface not implemented"); + curveseg->GetX(&x); + curveseg->GetY(&y); + curveseg->GetX1(&x1); + curveseg->GetY1(&y1); + x += cx; + y += cy; + x1 += cx; + y1 += cy; + } else { + nsCOMPtr curveseg = do_QueryInterface(segment); + NS_ASSERTION(curveseg, "interface not implemented"); + curveseg->GetX(&x); + curveseg->GetY(&y); + curveseg->GetX1(&x1); + curveseg->GetY1(&y1); + } + + cx1 = x1; + cy1 = y1; + + startAngle = atan2(y1 - cy, x1 - cx); + endAngle = atan2(y - y1, x - x1); + } + break; + + case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS: + absCoords = PR_TRUE; + case nsIDOMSVGPathSeg::PATHSEG_ARC_REL: + { + float r1, r2, angle; + PRBool largeArcFlag, sweepFlag; + + if (!absCoords) { + nsCOMPtr arcseg = do_QueryInterface(segment); + NS_ASSERTION(arcseg, "interface not implemented"); + arcseg->GetX(&x); + arcseg->GetY(&y); + arcseg->GetR1(&r1); + arcseg->GetR2(&r2); + arcseg->GetAngle(&angle); + arcseg->GetLargeArcFlag(&largeArcFlag); + arcseg->GetSweepFlag(&sweepFlag); + + x += cx; + y += cy; + } else { + nsCOMPtr arcseg = do_QueryInterface(segment); + NS_ASSERTION(arcseg, "interface not implemented"); + arcseg->GetX(&x); + arcseg->GetY(&y); + arcseg->GetR1(&r1); + arcseg->GetR2(&r2); + arcseg->GetAngle(&angle); + arcseg->GetLargeArcFlag(&largeArcFlag); + arcseg->GetSweepFlag(&sweepFlag); + } + + /* check for degenerate ellipse */ + if (r1 == 0.0 || r2 == 0.0) { + startAngle = endAngle = atan2(y - cy, x - cx); + break; + } + + r1 = fabs(r1); r2 = fabs(r2); + + float xp, yp, cxp, cyp; + + /* slope fun&games ... see SVG spec, section F.6 */ + angle = angle*M_PI/180.0; + xp = cos(angle)*(cx-x)/2.0 + sin(angle)*(cy-y)/2.0; + yp = -sin(angle)*(cx-x)/2.0 + cos(angle)*(cy-y)/2.0; + + /* make sure radii are large enough */ + float root, numerator = r1*r1*r2*r2 - r1*r1*yp*yp - r2*r2*xp*xp; + if (numerator < 0.0) { + float s = sqrt(1.0 - numerator/(r1*r1*r2*r2)); + r1 *= s; + r2 *= s; + root = 0.0; + } else { + root = sqrt(numerator/(r1*r1*yp*yp + r2*r2*xp*xp)); + if (largeArcFlag != sweepFlag) + root = -root; + } + cxp = root*r1*yp/r2; + cyp = -root*r2*xp/r1; + + float theta, delta; + theta = calcAngle(1.0, 0.0, (xp-cxp)/r1, (yp-cyp)/r2); + delta = calcAngle((xp-cxp)/r1, (yp-cyp)/r2, (-xp-cxp)/r1, (-yp-cyp)/r2); + if (!sweepFlag && delta > 0) + delta -= 2.0*M_PI; + else if (sweepFlag && delta < 0) + delta += 2.0*M_PI; + + float tx1, ty1, tx2, ty2; + tx1 = -cos(angle)*r1*sin(theta) - sin(angle)*r2*cos(theta); + ty1 = -sin(angle)*r1*sin(theta) + cos(angle)*r2*cos(theta); + + tx2 = -cos(angle)*r1*sin(theta+delta) - sin(angle)*r2*cos(theta+delta); + ty2 = -sin(angle)*r1*sin(theta+delta) + cos(angle)*r2*cos(theta+delta); + + startAngle = atan2(ty1, tx1); + endAngle = atan2(ty2, tx2); + } + break; + + case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS: + absCoords = PR_TRUE; + case nsIDOMSVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL: + { + y = cy; + if (!absCoords) { + nsCOMPtr lineseg = do_QueryInterface(segment); + NS_ASSERTION(lineseg, "interface not implemented"); + lineseg->GetX(&x); + x += cx; + } else { + nsCOMPtr lineseg = do_QueryInterface(segment); + NS_ASSERTION(lineseg, "interface not implemented"); + lineseg->GetX(&x); + } + startAngle = endAngle = atan2(0, x - cx); + } + break; + + case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS: + absCoords = PR_TRUE; + case nsIDOMSVGPathSeg::PATHSEG_LINETO_VERTICAL_REL: + { + x = cx; + if (!absCoords) { + nsCOMPtr lineseg = do_QueryInterface(segment); + NS_ASSERTION(lineseg, "interface not implemented"); + lineseg->GetY(&y); + y += cy; + } else { + nsCOMPtr lineseg = do_QueryInterface(segment); + NS_ASSERTION(lineseg, "interface not implemented"); + lineseg->GetY(&y); + } + startAngle = endAngle = atan2(y - cy, 0); + } + break; + + case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: + absCoords = PR_TRUE; + case nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL: + { + float x1, y1, x2, y2; + + if (lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_REL || + lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS || + lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL || + lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS ) { + // the first controlpoint is the reflection of the last one about the current point: + x1 = 2*cx - cx1; + y1 = 2*cy - cy1; + } + else { + // the first controlpoint is equal to the current point: + x1 = cx; + y1 = cy; + } + + if (!absCoords) { + nsCOMPtr curveseg = do_QueryInterface(segment); + NS_ASSERTION(curveseg, "interface not implemented"); + curveseg->GetX(&x); + curveseg->GetY(&y); + curveseg->GetX2(&x2); + curveseg->GetY2(&y2); + x += cx; + y += cy; + x2 += cx; + y2 += cy; + } else { + nsCOMPtr curveseg = do_QueryInterface(segment); + NS_ASSERTION(curveseg, "interface not implemented"); + curveseg->GetX(&x); + curveseg->GetY(&y); + curveseg->GetX2(&x2); + curveseg->GetY2(&y2); + } + + cx1 = x2; + cy1 = y2; + + if (x1 == cx && y1 == cy) { + x1 = x2; + y1 = y2; + } + + if (x2 == x && y2 == y) { + x2 = x1; + y2 = y1; + } + + startAngle = atan2(y1 - cy, x1 - cx); + endAngle = atan2(y - y2, x - x2); + } + break; + + case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: + absCoords = PR_TRUE; + case nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: + { + float x1, y1; + + if (lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL || + lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS || + lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL || + lastSegmentType == nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS ) { + // the first controlpoint is the reflection of the last one about the current point: + x1 = 2*cx - cx1; + y1 = 2*cy - cy1; + } + else { + // the first controlpoint is equal to the current point: + x1 = cx; + y1 = cy; + } + + if (!absCoords) { + nsCOMPtr curveseg = do_QueryInterface(segment); + NS_ASSERTION(curveseg, "interface not implemented"); + curveseg->GetX(&x); + curveseg->GetY(&y); + x += cx; + y += cy; + } else { + nsCOMPtr curveseg = do_QueryInterface(segment); + NS_ASSERTION(curveseg, "interface not implemented"); + curveseg->GetX(&x); + curveseg->GetY(&y); + } + + cx1 = x1; + cy1 = y1; + + startAngle = atan2(y1 - cy, x1 - cx); + endAngle = atan2(y - y1, x - x1); + } + break; + + default: + NS_ASSERTION(1==0, "unknown path segment"); + break; + } + lastSegmentType = type; + + if (newSegment && + type != nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS && + type != nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL) { + pathIndex = aMarks->Count() - 1; + pathAngle = startAngle; + ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = pathAngle; + newSegment = PR_FALSE; + prevAngle = endAngle; + } else if (type == nsIDOMSVGPathSeg::PATHSEG_MOVETO_ABS || + type == nsIDOMSVGPathSeg::PATHSEG_MOVETO_REL) { + if (aMarks->Count()) + ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle; + } else { + ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = + nsSVGMarkerFrame::bisect(prevAngle, startAngle); + prevAngle = endAngle; + } + + nsSVGMark *mark = new nsSVGMark; + mark->x = x; + mark->y = y; + aMarks->AppendElement(mark); + + if (type == nsIDOMSVGPathSeg::PATHSEG_CLOSEPATH) { + prevAngle = nsSVGMarkerFrame::bisect(endAngle, pathAngle); + ((nsSVGMark *)aMarks->ElementAt(pathIndex))->angle = prevAngle; + } + + cx = x; + cy = y; + } + + if (aMarks->Count()) + ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle; +} diff --git a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp index 58b3a74f63f..30511b23161 100644 --- a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.cpp @@ -53,6 +53,9 @@ #include "nsSVGAtoms.h" #include "nsCRT.h" #include "prdtoa.h" +#include "nsSVGMarkerFrame.h" +#include "nsISVGMarkable.h" +#include "nsIViewManager.h" //////////////////////////////////////////////////////////////////////// // nsSVGPathGeometryFrame @@ -154,16 +157,66 @@ nsSVGPathGeometryFrame::DidSetStyleContext(nsPresContext* aPresContext) //---------------------------------------------------------------------- // nsISVGChildFrame methods +// marker helper +void +nsSVGPathGeometryFrame::GetMarkerFrames(nsSVGMarkerFrame **markerStart, + nsSVGMarkerFrame **markerMid, + nsSVGMarkerFrame **markerEnd) +{ + nsIURI *aURI; + + *markerStart = *markerMid = *markerEnd = NULL; + + aURI = GetStyleSVG()->mMarkerEnd; + if (aURI) + NS_GetSVGMarkerFrame(markerEnd, aURI, mContent); + + aURI = GetStyleSVG()->mMarkerMid; + if (aURI) + NS_GetSVGMarkerFrame(markerMid, aURI, mContent); + + aURI = GetStyleSVG()->mMarkerStart; + if (aURI) + NS_GetSVGMarkerFrame(markerStart, aURI, mContent); +} + NS_IMETHODIMP nsSVGPathGeometryFrame::Paint(nsISVGRendererCanvas* canvas, const nsRect& dirtyRectTwips) { -#ifdef DEBUG - //printf("nsSVGPathGeometryFrame(%p)::Paint\n", this); -#endif if (!GetStyleVisibility()->IsVisible()) return NS_OK; GetGeometry()->Render(canvas); + + nsISVGMarkable *markable; + CallQueryInterface(this, &markable); + + if (markable) { + nsSVGMarkerFrame *markerEnd, *markerMid, *markerStart; + GetMarkerFrames(&markerStart, &markerMid, &markerEnd); + + if (!markerEnd && !markerMid && !markerStart) + return NS_OK; + + float strokeWidth; + GetStrokeWidth(&strokeWidth); + + nsVoidArray marks; + markable->GetMarkPoints(&marks); + + PRUint32 num = marks.Count(); + + if (markerStart) + markerStart->PaintMark(canvas, this, (nsSVGMark *)marks[0], strokeWidth); + + if (markerMid) + for (PRUint32 i = 1; i < num - 1; i++) + markerMid->PaintMark(canvas, this, (nsSVGMark *)marks[i], strokeWidth); + + if (markerEnd) + markerEnd->PaintMark(canvas, this, (nsSVGMark *)marks[num-1], strokeWidth); + } + return NS_OK; } @@ -189,6 +242,51 @@ nsSVGPathGeometryFrame::GetCoveredRegion() { nsISVGRendererRegion *region = nsnull; GetGeometry()->GetCoveredRegion(®ion); + + nsISVGMarkable *markable; + CallQueryInterface(this, &markable); + + if (markable) { + nsSVGMarkerFrame *markerEnd, *markerMid, *markerStart; + GetMarkerFrames(&markerStart, &markerMid, &markerEnd); + + if (!markerEnd && !markerMid && !markerStart) + return region; + + float strokeWidth; + GetStrokeWidth(&strokeWidth); + + nsVoidArray marks; + markable->GetMarkPoints(&marks); + + PRUint32 num = marks.Count(); + + if (markerStart) { + nsCOMPtr mark; + mark = markerStart->RegionMark(this, (nsSVGMark *)marks[0], strokeWidth); + + nsCOMPtr tmp = dont_AddRef(region); + mark->Combine(tmp, ®ion); + } + + if (markerMid) + for (PRUint32 i = 1; i < num - 1; i++) { + nsCOMPtr mark; + mark = markerMid->RegionMark(this, (nsSVGMark *)marks[i], strokeWidth); + + nsCOMPtr tmp = dont_AddRef(region); + mark->Combine(tmp, ®ion); + } + + if (markerEnd) { + nsCOMPtr mark; + mark = markerEnd->RegionMark(this, (nsSVGMark *)marks[num-1], strokeWidth); + + nsCOMPtr tmp = dont_AddRef(region); + mark->Combine(tmp, ®ion); + } + } + return region; } @@ -578,8 +676,19 @@ void nsSVGPathGeometryFrame::UpdateGraphic(PRUint32 flags) if (!suspended) { nsCOMPtr dirty_region; GetGeometry()->Update(mUpdateFlags, getter_AddRefs(dirty_region)); - if (dirty_region) - outerSVGFrame->InvalidateRegion(dirty_region, PR_TRUE); + if (dirty_region) { + // if we're painting a marker, this will get called during paint + // when the region already be invalidated as needed + + nsIView *view = GetClosestView(); + if (!view) return; + nsIViewManager *vm = view->GetViewManager(); + PRBool painting; + vm->IsPainting(painting); + + if (!painting) + outerSVGFrame->InvalidateRegion(dirty_region, PR_TRUE); + } mUpdateFlags = 0; } } diff --git a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.h b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.h index b950f735c5d..2c00874b059 100644 --- a/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.h +++ b/mozilla/layout/svg/base/src/nsSVGPathGeometryFrame.h @@ -47,6 +47,7 @@ #include "nsISVGValue.h" #include "nsISVGValueObserver.h" #include "nsISVGOuterSVGFrame.h" +#include "nsSVGMarkerFrame.h" class nsPresContext; class nsIDOMSVGMatrix; @@ -122,6 +123,10 @@ protected: private: nsCOMPtr mGeometry; PRUint32 mUpdateFlags; + + void GetMarkerFrames(nsSVGMarkerFrame **markerStart, + nsSVGMarkerFrame **markerMid, + nsSVGMarkerFrame **markerEnd); }; #endif // __NS_SVGPATHGEOMETRYFRAME_H__ diff --git a/mozilla/layout/svg/base/src/nsSVGPolygonFrame.cpp b/mozilla/layout/svg/base/src/nsSVGPolygonFrame.cpp index f39eb5942f5..abab81ac0fd 100644 --- a/mozilla/layout/svg/base/src/nsSVGPolygonFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGPolygonFrame.cpp @@ -42,8 +42,10 @@ #include "nsIDOMSVGPoint.h" //#include "nsASVGPathBuilder.h" #include "nsISVGRendererPathBuilder.h" +#include "nsISVGMarkable.h" -class nsSVGPolygonFrame : public nsSVGPathGeometryFrame +class nsSVGPolygonFrame : public nsSVGPathGeometryFrame, + public nsISVGMarkable { protected: friend nsresult @@ -61,8 +63,23 @@ public: NS_IMETHOD ConstructPath(nsISVGRendererPathBuilder *pathBuilder); nsCOMPtr mPoints; + + // nsISVGMarkable interface + void GetMarkPoints(nsVoidArray *aMarks); + + // nsISupports interface: + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } }; + +NS_INTERFACE_MAP_BEGIN(nsSVGPolygonFrame) + NS_INTERFACE_MAP_ENTRY(nsISVGMarkable) +NS_INTERFACE_MAP_END_INHERITING(nsSVGPathGeometryFrame) + //---------------------------------------------------------------------- // Implementation @@ -155,3 +172,57 @@ NS_IMETHODIMP nsSVGPolygonFrame::ConstructPath(nsISVGRendererPathBuilder* pathBu return NS_OK; } + +//---------------------------------------------------------------------- +// nsISVGMarkable methods: + +void +nsSVGPolygonFrame::GetMarkPoints(nsVoidArray *aMarks) { + + if (!mPoints) + return; + + PRUint32 count; + mPoints->GetNumberOfItems(&count); + if (count == 0) + return; + + float px = 0.0, py = 0.0, prevAngle, startAngle; + + nsCOMPtr point; + for (PRUint32 i = 0; i < count; ++i) { + mPoints->GetItem(i, getter_AddRefs(point)); + + float x, y; + point->GetX(&x); + point->GetY(&y); + + float angle = atan2(y-py, x-px); + if (i == 1) + startAngle = angle; + else if (i > 1) + ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = + nsSVGMarkerFrame::bisect(prevAngle, angle); + + nsSVGMark *mark; + mark = new nsSVGMark; + mark->x = x; + mark->y = y; + aMarks->AppendElement(mark); + + prevAngle = angle; + px = x; + py = y; + } + + float nx, ny, angle; + mPoints->GetItem(0, getter_AddRefs(point)); + point->GetX(&nx); + point->GetY(&ny); + angle = atan2(ny - py, nx - px); + + ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = + nsSVGMarkerFrame::bisect(prevAngle, angle); + ((nsSVGMark *)aMarks->ElementAt(0))->angle = + nsSVGMarkerFrame::bisect(angle, startAngle); +} diff --git a/mozilla/layout/svg/base/src/nsSVGPolylineFrame.cpp b/mozilla/layout/svg/base/src/nsSVGPolylineFrame.cpp index cb49e62dfc4..9300f896595 100644 --- a/mozilla/layout/svg/base/src/nsSVGPolylineFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGPolylineFrame.cpp @@ -42,8 +42,10 @@ #include "nsIDOMSVGPoint.h" //#include "nsASVGPathBuilder.h" #include "nsISVGRendererPathBuilder.h" +#include "nsISVGMarkable.h" -class nsSVGPolylineFrame : public nsSVGPathGeometryFrame +class nsSVGPolylineFrame : public nsSVGPathGeometryFrame, + public nsISVGMarkable { protected: friend nsresult @@ -62,8 +64,22 @@ public: // virtual void ConstructPath(nsASVGPathBuilder* pathBuilder); nsCOMPtr mPoints; + + // nsISVGMarkable interface + void GetMarkPoints(nsVoidArray *aMarks); + + // nsISupports interface: + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } }; +NS_INTERFACE_MAP_BEGIN(nsSVGPolylineFrame) + NS_INTERFACE_MAP_ENTRY(nsISVGMarkable) +NS_INTERFACE_MAP_END_INHERITING(nsSVGPathGeometryFrame) + //---------------------------------------------------------------------- // Implementation @@ -152,3 +168,48 @@ NS_IMETHODIMP nsSVGPolylineFrame::ConstructPath(nsISVGRendererPathBuilder* pathB return NS_OK; } + +//---------------------------------------------------------------------- +// nsISVGMarkable methods: + +void +nsSVGPolylineFrame::GetMarkPoints(nsVoidArray *aMarks) { + + if (!mPoints) + return; + + PRUint32 count; + mPoints->GetNumberOfItems(&count); + if (count == 0) + return; + + float px = 0.0, py = 0.0, prevAngle; + + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr point; + mPoints->GetItem(i, getter_AddRefs(point)); + + float x, y; + point->GetX(&x); + point->GetY(&y); + + float angle = atan2(y-py, x-px); + if (i == 1) + ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = angle; + else if (i > 1) + ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = + nsSVGMarkerFrame::bisect(prevAngle, angle); + + nsSVGMark *mark; + mark = new nsSVGMark; + mark->x = x; + mark->y = y; + aMarks->AppendElement(mark); + + prevAngle = angle; + px = x; + py = y; + } + + ((nsSVGMark *)aMarks->ElementAt(aMarks->Count()-1))->angle = prevAngle; +}