12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "mozilla/ArrayUtils.h"
- #include "mozilla/DebugOnly.h"
- #include "mozilla/Unused.h"
- #include "nsSVGElement.h"
- #include "mozilla/dom/SVGSVGElement.h"
- #include "mozilla/dom/SVGTests.h"
- #include "nsContentUtils.h"
- #include "nsICSSDeclaration.h"
- #include "nsIDocument.h"
- #include "nsIDOMMutationEvent.h"
- #include "nsSVGPathGeometryElement.h"
- #include "mozilla/InternalMutationEvent.h"
- #include "mozAutoDocUpdate.h"
- #include "nsError.h"
- #include "nsIPresShell.h"
- #include "nsGkAtoms.h"
- #include "mozilla/css/StyleRule.h"
- #include "nsRuleWalker.h"
- #include "mozilla/css/Declaration.h"
- #include "nsCSSProps.h"
- #include "nsCSSParser.h"
- #include "mozilla/EventListenerManager.h"
- #include "nsLayoutUtils.h"
- #include "nsSVGAnimatedTransformList.h"
- #include "nsSVGLength2.h"
- #include "nsSVGNumber2.h"
- #include "nsSVGNumberPair.h"
- #include "nsSVGInteger.h"
- #include "nsSVGIntegerPair.h"
- #include "nsSVGAngle.h"
- #include "nsSVGBoolean.h"
- #include "nsSVGEnum.h"
- #include "nsSVGViewBox.h"
- #include "nsSVGString.h"
- #include "mozilla/dom/SVGAnimatedEnumeration.h"
- #include "SVGAnimatedNumberList.h"
- #include "SVGAnimatedLengthList.h"
- #include "SVGAnimatedPointList.h"
- #include "SVGAnimatedPathSegList.h"
- #include "SVGContentUtils.h"
- #include "nsIFrame.h"
- #include "nsQueryObject.h"
- #include <stdarg.h>
- #include "nsSMILMappedAttribute.h"
- #include "SVGMotionSMILAttr.h"
- #include "nsAttrValueOrString.h"
- #include "nsSMILAnimationController.h"
- #include "mozilla/dom/SVGElementBinding.h"
- #include "mozilla/Unused.h"
- #include "mozilla/RestyleManagerHandle.h"
- #include "mozilla/RestyleManagerHandleInlines.h"
- using namespace mozilla;
- using namespace mozilla::dom;
- // This is needed to ensure correct handling of calls to the
- // vararg-list methods in this file:
- // nsSVGElement::GetAnimated{Length,Number,Integer}Values
- // See bug 547964 for details:
- static_assert(sizeof(void*) == sizeof(nullptr),
- "nullptr should be the correct size");
- nsresult
- NS_NewSVGElement(Element **aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
- {
- RefPtr<nsSVGElement> it = new nsSVGElement(aNodeInfo);
- nsresult rv = it->Init();
- if (NS_FAILED(rv)) {
- return rv;
- }
- it.forget(aResult);
- return rv;
- }
- NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGElement)
- nsSVGEnumMapping nsSVGElement::sSVGUnitTypesMap[] = {
- {&nsGkAtoms::userSpaceOnUse, SVG_UNIT_TYPE_USERSPACEONUSE},
- {&nsGkAtoms::objectBoundingBox, SVG_UNIT_TYPE_OBJECTBOUNDINGBOX},
- {nullptr, 0}
- };
- nsSVGElement::nsSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
- : nsSVGElementBase(aNodeInfo)
- {
- }
- JSObject*
- nsSVGElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
- {
- return SVGElementBinding::Wrap(aCx, this, aGivenProto);
- }
- //----------------------------------------------------------------------
- NS_IMETHODIMP
- nsSVGElement::GetSVGClassName(nsISupports** aClassName)
- {
- *aClassName = ClassName().take();
- return NS_OK;
- }
- NS_IMETHODIMP
- nsSVGElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
- {
- NS_ADDREF(*aStyle = Style());
- return NS_OK;
- }
- //----------------------------------------------------------------------
- // nsSVGElement methods
- void
- nsSVGElement::DidAnimateClass()
- {
- nsAutoString src;
- mClassAttribute.GetAnimValue(src, this);
- if (!mClassAnimAttr) {
- mClassAnimAttr = new nsAttrValue();
- }
- mClassAnimAttr->ParseAtomArray(src);
- nsIPresShell* shell = OwnerDoc()->GetShell();
- if (shell) {
- shell->RestyleForAnimation(this, eRestyle_Self);
- }
- }
- nsresult
- nsSVGElement::Init()
- {
- // Set up length attributes - can't do this in the constructor
- // because we can't do a virtual call at that point
- LengthAttributesInfo lengthInfo = GetLengthInfo();
- uint32_t i;
- for (i = 0; i < lengthInfo.mLengthCount; i++) {
- lengthInfo.Reset(i);
- }
- NumberAttributesInfo numberInfo = GetNumberInfo();
- for (i = 0; i < numberInfo.mNumberCount; i++) {
- numberInfo.Reset(i);
- }
- NumberPairAttributesInfo numberPairInfo = GetNumberPairInfo();
- for (i = 0; i < numberPairInfo.mNumberPairCount; i++) {
- numberPairInfo.Reset(i);
- }
- IntegerAttributesInfo integerInfo = GetIntegerInfo();
- for (i = 0; i < integerInfo.mIntegerCount; i++) {
- integerInfo.Reset(i);
- }
- IntegerPairAttributesInfo integerPairInfo = GetIntegerPairInfo();
- for (i = 0; i < integerPairInfo.mIntegerPairCount; i++) {
- integerPairInfo.Reset(i);
- }
- AngleAttributesInfo angleInfo = GetAngleInfo();
- for (i = 0; i < angleInfo.mAngleCount; i++) {
- angleInfo.Reset(i);
- }
- BooleanAttributesInfo booleanInfo = GetBooleanInfo();
- for (i = 0; i < booleanInfo.mBooleanCount; i++) {
- booleanInfo.Reset(i);
- }
- EnumAttributesInfo enumInfo = GetEnumInfo();
- for (i = 0; i < enumInfo.mEnumCount; i++) {
- enumInfo.Reset(i);
- }
- nsSVGViewBox *viewBox = GetViewBox();
- if (viewBox) {
- viewBox->Init();
- }
- SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
- GetPreserveAspectRatio();
- if (preserveAspectRatio) {
- preserveAspectRatio->Init();
- }
- LengthListAttributesInfo lengthListInfo = GetLengthListInfo();
- for (i = 0; i < lengthListInfo.mLengthListCount; i++) {
- lengthListInfo.Reset(i);
- }
- NumberListAttributesInfo numberListInfo = GetNumberListInfo();
- for (i = 0; i < numberListInfo.mNumberListCount; i++) {
- numberListInfo.Reset(i);
- }
- // No need to reset SVGPointList since the default value is always the same
- // (an empty list).
- // No need to reset SVGPathData since the default value is always the same
- // (an empty list).
- StringAttributesInfo stringInfo = GetStringInfo();
- for (i = 0; i < stringInfo.mStringCount; i++) {
- stringInfo.Reset(i);
- }
- return NS_OK;
- }
- //----------------------------------------------------------------------
- // nsISupports methods
- NS_IMPL_ISUPPORTS_INHERITED(nsSVGElement, nsSVGElementBase,
- nsIDOMNode, nsIDOMElement,
- nsIDOMSVGElement)
- //----------------------------------------------------------------------
- // Implementation
- //----------------------------------------------------------------------
- // nsIContent methods
- nsresult
- nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
- nsIContent* aBindingParent,
- bool aCompileEventHandlers)
- {
- nsresult rv = nsSVGElementBase::BindToTree(aDocument, aParent,
- aBindingParent,
- aCompileEventHandlers);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!MayHaveStyle()) {
- return NS_OK;
- }
- const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
- if (oldVal && oldVal->Type() == nsAttrValue::eCSSDeclaration) {
- // we need to force a reparse because the baseURI of the document
- // may have changed, and in particular because we may be clones of
- // XBL anonymous content now being bound to the document we should
- // render in and due to the hacky way in which we implement the
- // interaction of XBL and SVG resources. Once we have a sane
- // ownerDocument on XBL anonymous content, this can all go away.
- nsAttrValue attrValue;
- nsAutoString stringValue;
- oldVal->ToString(stringValue);
- // Force in data doc, since we already have a style rule
- ParseStyleAttribute(stringValue, attrValue, true);
- // Don't bother going through SetInlineStyleDeclaration; we don't
- // want to fire off mutation events or document notifications anyway
- bool oldValueSet;
- rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue,
- &oldValueSet);
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return NS_OK;
- }
- nsresult
- nsSVGElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue,
- const nsAttrValue* aOldValue, bool aNotify)
- {
- // We don't currently use nsMappedAttributes within SVG. If this changes, we
- // need to be very careful because some nsAttrValues used by SVG point to
- // member data of SVG elements and if an nsAttrValue outlives the SVG element
- // whose data it points to (by virtue of being stored in
- // mAttrsAndChildren->mMappedAttributes, meaning it's shared between
- // elements), the pointer will dangle. See bug 724680.
- MOZ_ASSERT(!mAttrsAndChildren.HasMappedAttrs(),
- "Unexpected use of nsMappedAttributes within SVG");
- // If this is an svg presentation attribute we need to map it into
- // the content stylerule.
- // XXX For some reason incremental mapping doesn't work, so for now
- // just delete the style rule and lazily reconstruct it in
- // GetContentStyleRule()
- if (aNamespaceID == kNameSpaceID_None && IsAttributeMapped(aName)) {
- mContentStyleRule = nullptr;
- }
- if (IsEventAttributeName(aName) && aValue) {
- MOZ_ASSERT(aValue->Type() == nsAttrValue::eString,
- "Expected string value for script body");
- nsresult rv = SetEventHandler(GetEventNameForAttr(aName),
- aValue->GetStringValue());
- NS_ENSURE_SUCCESS(rv, rv);
- }
- return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aOldValue,
- aNotify);
- }
- bool
- nsSVGElement::ParseAttribute(int32_t aNamespaceID,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- nsAttrValue& aResult)
- {
- nsresult rv = NS_OK;
- bool foundMatch = false;
- bool didSetResult = false;
- if (aNamespaceID == kNameSpaceID_None) {
- // Check for nsSVGLength2 attribute
- LengthAttributesInfo lengthInfo = GetLengthInfo();
- uint32_t i;
- for (i = 0; i < lengthInfo.mLengthCount; i++) {
- if (aAttribute == *lengthInfo.mLengthInfo[i].mName) {
- rv = lengthInfo.mLengths[i].SetBaseValueString(aValue, this, false);
- if (NS_FAILED(rv)) {
- lengthInfo.Reset(i);
- } else {
- aResult.SetTo(lengthInfo.mLengths[i], &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- if (!foundMatch) {
- // Check for SVGAnimatedLengthList attribute
- LengthListAttributesInfo lengthListInfo = GetLengthListInfo();
- for (i = 0; i < lengthListInfo.mLengthListCount; i++) {
- if (aAttribute == *lengthListInfo.mLengthListInfo[i].mName) {
- rv = lengthListInfo.mLengthLists[i].SetBaseValueString(aValue);
- if (NS_FAILED(rv)) {
- lengthListInfo.Reset(i);
- } else {
- aResult.SetTo(lengthListInfo.mLengthLists[i].GetBaseValue(),
- &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for SVGAnimatedNumberList attribute
- NumberListAttributesInfo numberListInfo = GetNumberListInfo();
- for (i = 0; i < numberListInfo.mNumberListCount; i++) {
- if (aAttribute == *numberListInfo.mNumberListInfo[i].mName) {
- rv = numberListInfo.mNumberLists[i].SetBaseValueString(aValue);
- if (NS_FAILED(rv)) {
- numberListInfo.Reset(i);
- } else {
- aResult.SetTo(numberListInfo.mNumberLists[i].GetBaseValue(),
- &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for SVGAnimatedPointList attribute
- if (GetPointListAttrName() == aAttribute) {
- SVGAnimatedPointList* pointList = GetAnimatedPointList();
- if (pointList) {
- pointList->SetBaseValueString(aValue);
- // The spec says we parse everything up to the failure, so we DON'T
- // need to check the result of SetBaseValueString or call
- // pointList->ClearBaseValue() if it fails
- aResult.SetTo(pointList->GetBaseValue(), &aValue);
- didSetResult = true;
- foundMatch = true;
- }
- }
- }
- if (!foundMatch) {
- // Check for SVGAnimatedPathSegList attribute
- if (GetPathDataAttrName() == aAttribute) {
- SVGAnimatedPathSegList* segList = GetAnimPathSegList();
- if (segList) {
- segList->SetBaseValueString(aValue);
- // The spec says we parse everything up to the failure, so we DON'T
- // need to check the result of SetBaseValueString or call
- // segList->ClearBaseValue() if it fails
- aResult.SetTo(segList->GetBaseValue(), &aValue);
- didSetResult = true;
- foundMatch = true;
- }
- }
- }
- if (!foundMatch) {
- // Check for nsSVGNumber2 attribute
- NumberAttributesInfo numberInfo = GetNumberInfo();
- for (i = 0; i < numberInfo.mNumberCount; i++) {
- if (aAttribute == *numberInfo.mNumberInfo[i].mName) {
- rv = numberInfo.mNumbers[i].SetBaseValueString(aValue, this);
- if (NS_FAILED(rv)) {
- numberInfo.Reset(i);
- } else {
- aResult.SetTo(numberInfo.mNumbers[i].GetBaseValue(), &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for nsSVGNumberPair attribute
- NumberPairAttributesInfo numberPairInfo = GetNumberPairInfo();
- for (i = 0; i < numberPairInfo.mNumberPairCount; i++) {
- if (aAttribute == *numberPairInfo.mNumberPairInfo[i].mName) {
- rv = numberPairInfo.mNumberPairs[i].SetBaseValueString(aValue, this);
- if (NS_FAILED(rv)) {
- numberPairInfo.Reset(i);
- } else {
- aResult.SetTo(numberPairInfo.mNumberPairs[i], &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for nsSVGInteger attribute
- IntegerAttributesInfo integerInfo = GetIntegerInfo();
- for (i = 0; i < integerInfo.mIntegerCount; i++) {
- if (aAttribute == *integerInfo.mIntegerInfo[i].mName) {
- rv = integerInfo.mIntegers[i].SetBaseValueString(aValue, this);
- if (NS_FAILED(rv)) {
- integerInfo.Reset(i);
- } else {
- aResult.SetTo(integerInfo.mIntegers[i].GetBaseValue(), &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for nsSVGIntegerPair attribute
- IntegerPairAttributesInfo integerPairInfo = GetIntegerPairInfo();
- for (i = 0; i < integerPairInfo.mIntegerPairCount; i++) {
- if (aAttribute == *integerPairInfo.mIntegerPairInfo[i].mName) {
- rv =
- integerPairInfo.mIntegerPairs[i].SetBaseValueString(aValue, this);
- if (NS_FAILED(rv)) {
- integerPairInfo.Reset(i);
- } else {
- aResult.SetTo(integerPairInfo.mIntegerPairs[i], &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for nsSVGAngle attribute
- AngleAttributesInfo angleInfo = GetAngleInfo();
- for (i = 0; i < angleInfo.mAngleCount; i++) {
- if (aAttribute == *angleInfo.mAngleInfo[i].mName) {
- rv = angleInfo.mAngles[i].SetBaseValueString(aValue, this, false);
- if (NS_FAILED(rv)) {
- angleInfo.Reset(i);
- } else {
- aResult.SetTo(angleInfo.mAngles[i], &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for nsSVGBoolean attribute
- BooleanAttributesInfo booleanInfo = GetBooleanInfo();
- for (i = 0; i < booleanInfo.mBooleanCount; i++) {
- if (aAttribute == *booleanInfo.mBooleanInfo[i].mName) {
- nsIAtom *valAtom = NS_GetStaticAtom(aValue);
- rv = valAtom ? booleanInfo.mBooleans[i].SetBaseValueAtom(valAtom, this) :
- NS_ERROR_DOM_SYNTAX_ERR;
- if (NS_FAILED(rv)) {
- booleanInfo.Reset(i);
- } else {
- aResult.SetTo(valAtom);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for nsSVGEnum attribute
- EnumAttributesInfo enumInfo = GetEnumInfo();
- for (i = 0; i < enumInfo.mEnumCount; i++) {
- if (aAttribute == *enumInfo.mEnumInfo[i].mName) {
- nsCOMPtr<nsIAtom> valAtom = NS_Atomize(aValue);
- rv = enumInfo.mEnums[i].SetBaseValueAtom(valAtom, this);
- if (NS_FAILED(rv)) {
- enumInfo.Reset(i);
- } else {
- aResult.SetTo(valAtom);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for conditional processing attributes
- nsCOMPtr<SVGTests> tests = do_QueryObject(this);
- if (tests && tests->ParseConditionalProcessingAttribute(
- aAttribute, aValue, aResult)) {
- foundMatch = true;
- }
- }
- if (!foundMatch) {
- // Check for StringList attribute
- StringListAttributesInfo stringListInfo = GetStringListInfo();
- for (i = 0; i < stringListInfo.mStringListCount; i++) {
- if (aAttribute == *stringListInfo.mStringListInfo[i].mName) {
- rv = stringListInfo.mStringLists[i].SetValue(aValue);
- if (NS_FAILED(rv)) {
- stringListInfo.Reset(i);
- } else {
- aResult.SetTo(stringListInfo.mStringLists[i], &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- break;
- }
- }
- }
- if (!foundMatch) {
- // Check for nsSVGViewBox attribute
- if (aAttribute == nsGkAtoms::viewBox) {
- nsSVGViewBox* viewBox = GetViewBox();
- if (viewBox) {
- rv = viewBox->SetBaseValueString(aValue, this, false);
- if (NS_FAILED(rv)) {
- viewBox->Init();
- } else {
- aResult.SetTo(*viewBox, &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- }
- // Check for SVGAnimatedPreserveAspectRatio attribute
- } else if (aAttribute == nsGkAtoms::preserveAspectRatio) {
- SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
- GetPreserveAspectRatio();
- if (preserveAspectRatio) {
- rv = preserveAspectRatio->SetBaseValueString(aValue, this, false);
- if (NS_FAILED(rv)) {
- preserveAspectRatio->Init();
- } else {
- aResult.SetTo(*preserveAspectRatio, &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- }
- // Check for SVGAnimatedTransformList attribute
- } else if (GetTransformListAttrName() == aAttribute) {
- // The transform attribute is being set, so we must ensure that the
- // nsSVGAnimatedTransformList is/has been allocated:
- nsSVGAnimatedTransformList *transformList =
- GetAnimatedTransformList(DO_ALLOCATE);
- rv = transformList->SetBaseValueString(aValue);
- if (NS_FAILED(rv)) {
- transformList->ClearBaseValue();
- } else {
- aResult.SetTo(transformList->GetBaseValue(), &aValue);
- didSetResult = true;
- }
- foundMatch = true;
- } else if (aAttribute == nsGkAtoms::tabindex) {
- didSetResult = aResult.ParseIntValue(aValue);
- foundMatch = true;
- }
- }
- if (aAttribute == nsGkAtoms::_class) {
- mClassAttribute.SetBaseValue(aValue, this, false);
- aResult.ParseAtomArray(aValue);
- return true;
- }
- }
- if (!foundMatch) {
- // Check for nsSVGString attribute
- StringAttributesInfo stringInfo = GetStringInfo();
- for (uint32_t i = 0; i < stringInfo.mStringCount; i++) {
- if (aNamespaceID == stringInfo.mStringInfo[i].mNamespaceID &&
- aAttribute == *stringInfo.mStringInfo[i].mName) {
- stringInfo.mStrings[i].SetBaseValue(aValue, this, false);
- foundMatch = true;
- break;
- }
- }
- }
- if (foundMatch) {
- if (NS_FAILED(rv)) {
- ReportAttributeParseFailure(OwnerDoc(), aAttribute, aValue);
- return false;
- }
- if (!didSetResult) {
- aResult.SetTo(aValue);
- }
- return true;
- }
- return nsSVGElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
- aResult);
- }
- void
- nsSVGElement::UnsetAttrInternal(int32_t aNamespaceID, nsIAtom* aName,
- bool aNotify)
- {
- // XXXbz there's a bunch of redundancy here with AfterSetAttr.
- // Maybe consolidate?
- if (aNamespaceID == kNameSpaceID_None) {
- // If this is an svg presentation attribute, remove rule to force an update
- if (IsAttributeMapped(aName))
- mContentStyleRule = nullptr;
- if (IsEventAttributeName(aName)) {
- EventListenerManager* manager = GetExistingListenerManager();
- if (manager) {
- nsIAtom* eventName = GetEventNameForAttr(aName);
- manager->RemoveEventHandler(eventName, EmptyString());
- }
- return;
- }
-
- // Check if this is a length attribute going away
- LengthAttributesInfo lenInfo = GetLengthInfo();
- for (uint32_t i = 0; i < lenInfo.mLengthCount; i++) {
- if (aName == *lenInfo.mLengthInfo[i].mName) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- lenInfo.Reset(i);
- return;
- }
- }
- // Check if this is a length list attribute going away
- LengthListAttributesInfo lengthListInfo = GetLengthListInfo();
- for (uint32_t i = 0; i < lengthListInfo.mLengthListCount; i++) {
- if (aName == *lengthListInfo.mLengthListInfo[i].mName) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- lengthListInfo.Reset(i);
- return;
- }
- }
- // Check if this is a number list attribute going away
- NumberListAttributesInfo numberListInfo = GetNumberListInfo();
- for (uint32_t i = 0; i < numberListInfo.mNumberListCount; i++) {
- if (aName == *numberListInfo.mNumberListInfo[i].mName) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- numberListInfo.Reset(i);
- return;
- }
- }
- // Check if this is a point list attribute going away
- if (GetPointListAttrName() == aName) {
- SVGAnimatedPointList *pointList = GetAnimatedPointList();
- if (pointList) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- pointList->ClearBaseValue();
- return;
- }
- }
- // Check if this is a path segment list attribute going away
- if (GetPathDataAttrName() == aName) {
- SVGAnimatedPathSegList *segList = GetAnimPathSegList();
- if (segList) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- segList->ClearBaseValue();
- return;
- }
- }
- // Check if this is a number attribute going away
- NumberAttributesInfo numInfo = GetNumberInfo();
- for (uint32_t i = 0; i < numInfo.mNumberCount; i++) {
- if (aName == *numInfo.mNumberInfo[i].mName) {
- numInfo.Reset(i);
- return;
- }
- }
- // Check if this is a number pair attribute going away
- NumberPairAttributesInfo numPairInfo = GetNumberPairInfo();
- for (uint32_t i = 0; i < numPairInfo.mNumberPairCount; i++) {
- if (aName == *numPairInfo.mNumberPairInfo[i].mName) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- numPairInfo.Reset(i);
- return;
- }
- }
- // Check if this is an integer attribute going away
- IntegerAttributesInfo intInfo = GetIntegerInfo();
- for (uint32_t i = 0; i < intInfo.mIntegerCount; i++) {
- if (aName == *intInfo.mIntegerInfo[i].mName) {
- intInfo.Reset(i);
- return;
- }
- }
- // Check if this is an integer pair attribute going away
- IntegerPairAttributesInfo intPairInfo = GetIntegerPairInfo();
- for (uint32_t i = 0; i < intPairInfo.mIntegerPairCount; i++) {
- if (aName == *intPairInfo.mIntegerPairInfo[i].mName) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- intPairInfo.Reset(i);
- return;
- }
- }
- // Check if this is an angle attribute going away
- AngleAttributesInfo angleInfo = GetAngleInfo();
- for (uint32_t i = 0; i < angleInfo.mAngleCount; i++) {
- if (aName == *angleInfo.mAngleInfo[i].mName) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- angleInfo.Reset(i);
- return;
- }
- }
- // Check if this is a boolean attribute going away
- BooleanAttributesInfo boolInfo = GetBooleanInfo();
- for (uint32_t i = 0; i < boolInfo.mBooleanCount; i++) {
- if (aName == *boolInfo.mBooleanInfo[i].mName) {
- boolInfo.Reset(i);
- return;
- }
- }
- // Check if this is an enum attribute going away
- EnumAttributesInfo enumInfo = GetEnumInfo();
- for (uint32_t i = 0; i < enumInfo.mEnumCount; i++) {
- if (aName == *enumInfo.mEnumInfo[i].mName) {
- enumInfo.Reset(i);
- return;
- }
- }
- // Check if this is a nsViewBox attribute going away
- if (aName == nsGkAtoms::viewBox) {
- nsSVGViewBox* viewBox = GetViewBox();
- if (viewBox) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- viewBox->Init();
- return;
- }
- }
- // Check if this is a preserveAspectRatio attribute going away
- if (aName == nsGkAtoms::preserveAspectRatio) {
- SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
- GetPreserveAspectRatio();
- if (preserveAspectRatio) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- preserveAspectRatio->Init();
- return;
- }
- }
- // Check if this is a transform list attribute going away
- if (GetTransformListAttrName() == aName) {
- nsSVGAnimatedTransformList *transformList = GetAnimatedTransformList();
- if (transformList) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- transformList->ClearBaseValue();
- return;
- }
- }
- // Check for conditional processing attributes
- nsCOMPtr<SVGTests> tests = do_QueryObject(this);
- if (tests && tests->IsConditionalProcessingAttribute(aName)) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- tests->UnsetAttr(aName);
- return;
- }
- // Check if this is a string list attribute going away
- StringListAttributesInfo stringListInfo = GetStringListInfo();
- for (uint32_t i = 0; i < stringListInfo.mStringListCount; i++) {
- if (aName == *stringListInfo.mStringListInfo[i].mName) {
- MaybeSerializeAttrBeforeRemoval(aName, aNotify);
- stringListInfo.Reset(i);
- return;
- }
- }
- if (aName == nsGkAtoms::_class) {
- mClassAttribute.Init();
- return;
- }
- }
- // Check if this is a string attribute going away
- StringAttributesInfo stringInfo = GetStringInfo();
- for (uint32_t i = 0; i < stringInfo.mStringCount; i++) {
- if (aNamespaceID == stringInfo.mStringInfo[i].mNamespaceID &&
- aName == *stringInfo.mStringInfo[i].mName) {
- stringInfo.Reset(i);
- return;
- }
- }
- }
- nsresult
- nsSVGElement::UnsetAttr(int32_t aNamespaceID, nsIAtom* aName,
- bool aNotify)
- {
- UnsetAttrInternal(aNamespaceID, aName, aNotify);
- return nsSVGElementBase::UnsetAttr(aNamespaceID, aName, aNotify);
- }
- nsChangeHint
- nsSVGElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
- int32_t aModType) const
- {
- nsChangeHint retval =
- nsSVGElementBase::GetAttributeChangeHint(aAttribute, aModType);
- nsCOMPtr<SVGTests> tests = do_QueryObject(const_cast<nsSVGElement*>(this));
- if (tests && tests->IsConditionalProcessingAttribute(aAttribute)) {
- // It would be nice to only reconstruct the frame if the value returned by
- // SVGTests::PassesConditionalProcessingTests has changed, but we don't
- // know that
- retval |= nsChangeHint_ReconstructFrame;
- }
- return retval;
- }
- bool
- nsSVGElement::IsNodeOfType(uint32_t aFlags) const
- {
- return !(aFlags & ~eCONTENT);
- }
- NS_IMETHODIMP
- nsSVGElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
- {
- #ifdef DEBUG
- // printf("nsSVGElement(%p)::WalkContentStyleRules()\n", this);
- #endif
- if (!mContentStyleRule)
- UpdateContentStyleRule();
- if (mContentStyleRule) {
- css::Declaration* declaration = mContentStyleRule->GetDeclaration();
- declaration->SetImmutable();
- aRuleWalker->Forward(declaration);
- }
- return NS_OK;
- }
- void
- nsSVGElement::WalkAnimatedContentStyleRules(nsRuleWalker* aRuleWalker)
- {
- // Update & walk the animated content style rule, to include style from
- // animated mapped attributes. But first, get nsPresContext to check
- // whether this is a "no-animation restyle". (This should match the check
- // in nsHTMLCSSStyleSheet::RulesMatching(), where we determine whether to
- // apply the SMILOverrideStyle.)
- RestyleManagerHandle restyleManager =
- aRuleWalker->PresContext()->RestyleManager();
- MOZ_ASSERT(restyleManager->IsGecko(),
- "stylo: Servo-backed style system should not be calling "
- "WalkAnimatedContentStyleRules");
- if (!restyleManager->AsGecko()->SkipAnimationRules()) {
- // update/walk the animated content style rule.
- css::StyleRule* animContentStyleRule = GetAnimatedContentStyleRule();
- if (!animContentStyleRule) {
- UpdateAnimatedContentStyleRule();
- animContentStyleRule = GetAnimatedContentStyleRule();
- }
- if (animContentStyleRule) {
- css::Declaration* declaration = animContentStyleRule->GetDeclaration();
- declaration->SetImmutable();
- aRuleWalker->Forward(declaration);
- }
- }
- }
- NS_IMETHODIMP_(bool)
- nsSVGElement::IsAttributeMapped(const nsIAtom* name) const
- {
- if (name == nsGkAtoms::lang) {
- return true;
- }
- return nsSVGElementBase::IsAttributeMapped(name);
- }
- // PresentationAttributes-FillStroke
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sFillStrokeMap[] = {
- { &nsGkAtoms::fill },
- { &nsGkAtoms::fill_opacity },
- { &nsGkAtoms::fill_rule },
- { &nsGkAtoms::paint_order },
- { &nsGkAtoms::stroke },
- { &nsGkAtoms::stroke_dasharray },
- { &nsGkAtoms::stroke_dashoffset },
- { &nsGkAtoms::stroke_linecap },
- { &nsGkAtoms::stroke_linejoin },
- { &nsGkAtoms::stroke_miterlimit },
- { &nsGkAtoms::stroke_opacity },
- { &nsGkAtoms::stroke_width },
- { &nsGkAtoms::vector_effect },
- { nullptr }
- };
- // PresentationAttributes-Graphics
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sGraphicsMap[] = {
- { &nsGkAtoms::clip_path },
- { &nsGkAtoms::clip_rule },
- { &nsGkAtoms::colorInterpolation },
- { &nsGkAtoms::cursor },
- { &nsGkAtoms::display },
- { &nsGkAtoms::filter },
- { &nsGkAtoms::image_rendering },
- { &nsGkAtoms::mask },
- { &nsGkAtoms::opacity },
- { &nsGkAtoms::pointer_events },
- { &nsGkAtoms::shape_rendering },
- { &nsGkAtoms::text_rendering },
- { &nsGkAtoms::visibility },
- { nullptr }
- };
- // PresentationAttributes-TextContentElements
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sTextContentElementsMap[] = {
- // Properties that we don't support are commented out.
- // { &nsGkAtoms::alignment_baseline },
- // { &nsGkAtoms::baseline_shift },
- { &nsGkAtoms::direction },
- { &nsGkAtoms::dominant_baseline },
- { &nsGkAtoms::letter_spacing },
- { &nsGkAtoms::text_anchor },
- { &nsGkAtoms::text_decoration },
- { &nsGkAtoms::unicode_bidi },
- { &nsGkAtoms::word_spacing },
- { &nsGkAtoms::writing_mode },
- { nullptr }
- };
- // PresentationAttributes-FontSpecification
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sFontSpecificationMap[] = {
- { &nsGkAtoms::font_family },
- { &nsGkAtoms::font_size },
- { &nsGkAtoms::font_size_adjust },
- { &nsGkAtoms::font_stretch },
- { &nsGkAtoms::font_style },
- { &nsGkAtoms::font_variant },
- { &nsGkAtoms::fontWeight },
- { nullptr }
- };
- // PresentationAttributes-GradientStop
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sGradientStopMap[] = {
- { &nsGkAtoms::stop_color },
- { &nsGkAtoms::stop_opacity },
- { nullptr }
- };
- // PresentationAttributes-Viewports
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sViewportsMap[] = {
- { &nsGkAtoms::overflow },
- { &nsGkAtoms::clip },
- { nullptr }
- };
- // PresentationAttributes-Makers
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sMarkersMap[] = {
- { &nsGkAtoms::marker_end },
- { &nsGkAtoms::marker_mid },
- { &nsGkAtoms::marker_start },
- { nullptr }
- };
- // PresentationAttributes-Color
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sColorMap[] = {
- { &nsGkAtoms::color },
- { nullptr }
- };
- // PresentationAttributes-Filters
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sFiltersMap[] = {
- { &nsGkAtoms::colorInterpolationFilters },
- { nullptr }
- };
- // PresentationAttributes-feFlood
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sFEFloodMap[] = {
- { &nsGkAtoms::flood_color },
- { &nsGkAtoms::flood_opacity },
- { nullptr }
- };
- // PresentationAttributes-LightingEffects
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sLightingEffectsMap[] = {
- { &nsGkAtoms::lighting_color },
- { nullptr }
- };
- // PresentationAttributes-mask
- /* static */ const Element::MappedAttributeEntry
- nsSVGElement::sMaskMap[] = {
- { &nsGkAtoms::mask_type },
- { nullptr }
- };
- //----------------------------------------------------------------------
- // nsIDOMElement methods
- // forwarded to Element implementations
- //----------------------------------------------------------------------
- // nsIDOMSVGElement methods
- NS_IMETHODIMP
- nsSVGElement::GetOwnerSVGElement(nsIDOMSVGElement * *aOwnerSVGElement)
- {
- NS_IF_ADDREF(*aOwnerSVGElement = GetOwnerSVGElement());
- return NS_OK;
- }
- SVGSVGElement*
- nsSVGElement::GetOwnerSVGElement()
- {
- return GetCtx(); // this may return nullptr
- }
- NS_IMETHODIMP
- nsSVGElement::GetViewportElement(nsIDOMSVGElement * *aViewportElement)
- {
- nsSVGElement* elem = GetViewportElement();
- NS_ADDREF(*aViewportElement = elem);
- return NS_OK;
- }
- nsSVGElement*
- nsSVGElement::GetViewportElement()
- {
- return SVGContentUtils::GetNearestViewportElement(this);
- }
- already_AddRefed<SVGAnimatedString>
- nsSVGElement::ClassName()
- {
- return mClassAttribute.ToDOMAnimatedString(this);
- }
- bool
- nsSVGElement::IsFocusableInternal(int32_t* aTabIndex, bool)
- {
- int32_t index = TabIndex();
- if (index == -1) {
- return false;
- }
- *aTabIndex = index;
- return true;
- }
- //------------------------------------------------------------------------
- // Helper class: MappedAttrParser, for parsing values of mapped attributes
- namespace {
- class MOZ_STACK_CLASS MappedAttrParser {
- public:
- MappedAttrParser(css::Loader* aLoader,
- nsIURI* aDocURI,
- already_AddRefed<nsIURI> aBaseURI,
- nsSVGElement* aElement);
- ~MappedAttrParser();
- // Parses a mapped attribute value.
- void ParseMappedAttrValue(nsIAtom* aMappedAttrName,
- const nsAString& aMappedAttrValue);
- // If we've parsed any values for mapped attributes, this method returns
- // a new already_AddRefed css::StyleRule that incorporates the parsed
- // values. Otherwise, this method returns null.
- already_AddRefed<css::StyleRule> CreateStyleRule();
- private:
- // MEMBER DATA
- // -----------
- nsCSSParser mParser;
- // Arguments for nsCSSParser::ParseProperty
- nsIURI* mDocURI;
- nsCOMPtr<nsIURI> mBaseURI;
- // Declaration for storing parsed values (lazily initialized)
- css::Declaration* mDecl;
- // For reporting use counters
- nsSVGElement* mElement;
- };
- MappedAttrParser::MappedAttrParser(css::Loader* aLoader,
- nsIURI* aDocURI,
- already_AddRefed<nsIURI> aBaseURI,
- nsSVGElement* aElement)
- : mParser(aLoader), mDocURI(aDocURI), mBaseURI(aBaseURI),
- mDecl(nullptr), mElement(aElement)
- {
- }
- MappedAttrParser::~MappedAttrParser()
- {
- MOZ_ASSERT(!mDecl,
- "If mDecl was initialized, it should have been converted "
- "into a style rule (and had its pointer cleared)");
- }
- void
- MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName,
- const nsAString& aMappedAttrValue)
- {
- if (!mDecl) {
- mDecl = new css::Declaration();
- mDecl->InitializeEmpty();
- }
- // Get the nsCSSPropertyID ID for our mapped attribute.
- nsCSSPropertyID propertyID =
- nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName),
- CSSEnabledState::eForAllContent);
- if (propertyID != eCSSProperty_UNKNOWN) {
- bool changed = false; // outparam for ParseProperty.
- mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
- mElement->NodePrincipal(), mDecl, &changed, false, true);
- if (changed) {
- // The normal reporting of use counters by the nsCSSParser won't happen
- // since it doesn't have a sheet.
- if (nsCSSProps::IsShorthand(propertyID)) {
- CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, propertyID,
- CSSEnabledState::eForAllContent) {
- UseCounter useCounter = nsCSSProps::UseCounterFor(*subprop);
- if (useCounter != eUseCounter_UNKNOWN) {
- mElement->OwnerDoc()->SetDocumentAndPageUseCounter(useCounter);
- }
- }
- } else {
- UseCounter useCounter = nsCSSProps::UseCounterFor(propertyID);
- if (useCounter != eUseCounter_UNKNOWN) {
- mElement->OwnerDoc()->SetDocumentAndPageUseCounter(useCounter);
- }
- }
- }
- return;
- }
- MOZ_ASSERT(aMappedAttrName == nsGkAtoms::lang,
- "Only 'lang' should be unrecognized!");
- // nsCSSParser doesn't know about 'lang', so we need to handle it specially.
- if (aMappedAttrName == nsGkAtoms::lang) {
- propertyID = eCSSProperty__x_lang;
- nsCSSExpandedDataBlock block;
- mDecl->ExpandTo(&block);
- nsCSSValue cssValue(PromiseFlatString(aMappedAttrValue), eCSSUnit_Ident);
- block.AddLonghandProperty(propertyID, cssValue);
- mDecl->ValueAppended(propertyID);
- mDecl->CompressFrom(&block);
- }
- }
- already_AddRefed<css::StyleRule>
- MappedAttrParser::CreateStyleRule()
- {
- if (!mDecl) {
- return nullptr; // No mapped attributes were parsed
- }
- RefPtr<css::StyleRule> rule = new css::StyleRule(nullptr, mDecl, 0, 0);
- mDecl = nullptr; // We no longer own the declaration -- drop our pointer to it
- return rule.forget();
- }
- } // namespace
- //----------------------------------------------------------------------
- // Implementation Helpers:
- void
- nsSVGElement::UpdateContentStyleRule()
- {
- NS_ASSERTION(!mContentStyleRule, "we already have a content style rule");
- uint32_t attrCount = mAttrsAndChildren.AttrCount();
- if (!attrCount) {
- // nothing to do
- return;
- }
- nsIDocument* doc = OwnerDoc();
- MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
- GetBaseURI(), this);
- for (uint32_t i = 0; i < attrCount; ++i) {
- const nsAttrName* attrName = mAttrsAndChildren.AttrNameAt(i);
- if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom()))
- continue;
- if (attrName->NamespaceID() != kNameSpaceID_None &&
- !attrName->Equals(nsGkAtoms::lang, kNameSpaceID_XML)) {
- continue;
- }
- if (attrName->Equals(nsGkAtoms::lang, kNameSpaceID_None) &&
- HasAttr(kNameSpaceID_XML, nsGkAtoms::lang)) {
- continue; // xml:lang has precedence
- }
- nsAutoString value;
- mAttrsAndChildren.AttrAt(i)->ToString(value);
- mappedAttrParser.ParseMappedAttrValue(attrName->Atom(), value);
- }
- mContentStyleRule = mappedAttrParser.CreateStyleRule();
- }
- static void
- ParseMappedAttrAnimValueCallback(void* aObject,
- nsIAtom* aPropertyName,
- void* aPropertyValue,
- void* aData)
- {
- MOZ_ASSERT(aPropertyName != SMIL_MAPPED_ATTR_STYLERULE_ATOM,
- "animated content style rule should have been removed "
- "from properties table already (we're rebuilding it now)");
- MappedAttrParser* mappedAttrParser = static_cast<MappedAttrParser*>(aData);
- MOZ_ASSERT(mappedAttrParser, "parser should be non-null");
- nsStringBuffer* animValBuf = static_cast<nsStringBuffer*>(aPropertyValue);
- MOZ_ASSERT(animValBuf, "animated value should be non-null");
- nsString animValStr;
- nsContentUtils::PopulateStringFromStringBuffer(animValBuf, animValStr);
- mappedAttrParser->ParseMappedAttrValue(aPropertyName, animValStr);
- }
- // Callback for freeing animated content style rule, in property table.
- static void
- ReleaseStyleRule(void* aObject, /* unused */
- nsIAtom* aPropertyName,
- void* aPropertyValue,
- void* aData /* unused */)
- {
- MOZ_ASSERT(aPropertyName == SMIL_MAPPED_ATTR_STYLERULE_ATOM,
- "unexpected property name, for animated content style rule");
- css::StyleRule* styleRule = static_cast<css::StyleRule*>(aPropertyValue);
- MOZ_ASSERT(styleRule, "unexpected null style rule");
- styleRule->Release();
- }
- void
- nsSVGElement::UpdateAnimatedContentStyleRule()
- {
- MOZ_ASSERT(!GetAnimatedContentStyleRule(),
- "Animated content style rule already set");
- nsIDocument* doc = OwnerDoc();
- if (!doc) {
- NS_ERROR("SVG element without owner document");
- return;
- }
- MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
- GetBaseURI(), this);
- doc->PropertyTable(SMIL_MAPPED_ATTR_ANIMVAL)->
- Enumerate(this, ParseMappedAttrAnimValueCallback, &mappedAttrParser);
-
- RefPtr<css::StyleRule>
- animContentStyleRule(mappedAttrParser.CreateStyleRule());
- if (animContentStyleRule) {
- #ifdef DEBUG
- nsresult rv =
- #endif
- SetProperty(SMIL_MAPPED_ATTR_ANIMVAL,
- SMIL_MAPPED_ATTR_STYLERULE_ATOM,
- animContentStyleRule.get(),
- ReleaseStyleRule);
- Unused << animContentStyleRule.forget();
- MOZ_ASSERT(rv == NS_OK,
- "SetProperty failed (or overwrote something)");
- }
- }
- css::StyleRule*
- nsSVGElement::GetAnimatedContentStyleRule()
- {
- return
- static_cast<css::StyleRule*>(GetProperty(SMIL_MAPPED_ATTR_ANIMVAL,
- SMIL_MAPPED_ATTR_STYLERULE_ATOM,
- nullptr));
- }
- /**
- * Helper methods for the type-specific WillChangeXXX methods.
- *
- * This method sends out appropriate pre-change notifications so that selector
- * restyles (e.g. due to changes that cause |elem[attr="val"]| to start/stop
- * matching) work, and it returns an nsAttrValue that _may_ contain the
- * attribute's pre-change value.
- *
- * The nsAttrValue returned by this method depends on whether there are
- * mutation event listeners listening for changes to this element's attributes.
- * If not, then the object returned is empty. If there are, then the
- * nsAttrValue returned contains a serialized copy of the attribute's value
- * prior to the change, and this object should be passed to the corresponding
- * DidChangeXXX method call (assuming a WillChangeXXX call is required for the
- * SVG type - see comment below). This is necessary so that the 'prevValue'
- * property of the mutation event that is dispatched will correctly contain the
- * old value.
- *
- * The reason we need to serialize the old value if there are mutation
- * event listeners is because the underlying nsAttrValue for the attribute
- * points directly to a parsed representation of the attribute (e.g. an
- * SVGAnimatedLengthList*) that is a member of the SVG element. That object
- * will have changed by the time DidChangeXXX has been called, so without the
- * serialization of the old attribute value that we provide, DidChangeXXX
- * would have no way to get the old value to pass to SetAttrAndNotify.
- *
- * We only return the old value when there are mutation event listeners because
- * it's not needed otherwise, and because it's expensive to serialize the old
- * value. This is especially true for list type attributes, which may be built
- * up via the SVG DOM resulting in a large number of Will/DidModifyXXX calls
- * before the script finally finishes setting the attribute.
- *
- * Note that unlike using SetParsedAttr, using Will/DidChangeXXX does NOT check
- * and filter out redundant changes. Before calling WillChangeXXX, the caller
- * should check whether the new and old values are actually the same, and skip
- * calling Will/DidChangeXXX if they are.
- *
- * Also note that not all SVG types use this scheme. For types that can be
- * represented by an nsAttrValue without pointing back to an SVG object (e.g.
- * enums, booleans, integers) we can simply use SetParsedAttr which will do all
- * of the above for us. For such types there is no matching WillChangeXXX
- * method, only DidChangeXXX which calls SetParsedAttr.
- */
- nsAttrValue
- nsSVGElement::WillChangeValue(nsIAtom* aName)
- {
- // We need an empty attr value:
- // a) to pass to BeforeSetAttr when GetParsedAttr returns nullptr
- // b) to store the old value in the case we have mutation listeners
- //
- // We can use the same value for both purposes, because if GetParsedAttr
- // returns non-null its return value is what will get passed to BeforeSetAttr,
- // not matter what our mutation listener situation is.
- //
- // Also, we should be careful to always return this value to benefit from
- // return value optimization.
- nsAttrValue emptyOrOldAttrValue;
- const nsAttrValue* attrValue = GetParsedAttr(aName);
- // We only need to set the old value if we have listeners since otherwise it
- // isn't used.
- if (attrValue &&
- nsContentUtils::HasMutationListeners(this,
- NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
- this)) {
- emptyOrOldAttrValue.SetToSerialized(*attrValue);
- }
- uint8_t modType = attrValue
- ? static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION)
- : static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
- nsNodeUtils::AttributeWillChange(this, kNameSpaceID_None, aName, modType,
- nullptr);
- // This is not strictly correct--the attribute value parameter for
- // BeforeSetAttr should reflect the value that *will* be set but that implies
- // allocating, e.g. an extra nsSVGLength2, and isn't necessary at the moment
- // since no SVG elements overload BeforeSetAttr. For now we just pass the
- // current value.
- nsAttrValueOrString attrStringOrValue(attrValue ? *attrValue
- : emptyOrOldAttrValue);
- DebugOnly<nsresult> rv =
- BeforeSetAttr(kNameSpaceID_None, aName, &attrStringOrValue,
- kNotifyDocumentObservers);
- // SVG elements aren't expected to overload BeforeSetAttr in such a way that
- // it may fail. So long as this is the case we don't need to check and pass on
- // the return value which simplifies the calling code significantly.
- MOZ_ASSERT(NS_SUCCEEDED(rv), "Unexpected failure from BeforeSetAttr");
- return emptyOrOldAttrValue;
- }
- /**
- * Helper methods for the type-specific DidChangeXXX methods.
- *
- * aEmptyOrOldValue will normally be the object returned from the corresponding
- * WillChangeXXX call. This is because:
- * a) WillChangeXXX will ensure the object is set when we have mutation
- * listeners, and
- * b) WillChangeXXX will ensure the object represents a serialized version of
- * the old attribute value so that the value doesn't change when the
- * underlying SVG type is updated.
- *
- * aNewValue is replaced with the old value.
- */
- void
- nsSVGElement::DidChangeValue(nsIAtom* aName,
- const nsAttrValue& aEmptyOrOldValue,
- nsAttrValue& aNewValue)
- {
- bool hasListeners =
- nsContentUtils::HasMutationListeners(this,
- NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
- this);
- uint8_t modType = HasAttr(kNameSpaceID_None, aName)
- ? static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION)
- : static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
- nsIDocument* document = GetComposedDoc();
- mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL,
- kNotifyDocumentObservers);
- // XXX Really, the fourth argument to SetAttrAndNotify should be null if
- // aEmptyOrOldValue does not represent the actual previous value of the
- // attribute, but currently SVG elements do not even use the old attribute
- // value in |AfterSetAttr|, so this should be ok.
- SetAttrAndNotify(kNameSpaceID_None, aName, nullptr, &aEmptyOrOldValue,
- aNewValue, modType, hasListeners, kNotifyDocumentObservers,
- kCallAfterSetAttr, document, updateBatch);
- }
- void
- nsSVGElement::MaybeSerializeAttrBeforeRemoval(nsIAtom* aName, bool aNotify)
- {
- if (!aNotify ||
- !nsContentUtils::HasMutationListeners(this,
- NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
- this)) {
- return;
- }
- const nsAttrValue* attrValue = mAttrsAndChildren.GetAttr(aName);
- if (!attrValue)
- return;
- nsAutoString serializedValue;
- attrValue->ToString(serializedValue);
- nsAttrValue oldAttrValue(serializedValue);
- bool oldValueSet;
- mAttrsAndChildren.SetAndSwapAttr(aName, oldAttrValue, &oldValueSet);
- }
- /* static */
- nsIAtom* nsSVGElement::GetEventNameForAttr(nsIAtom* aAttr)
- {
- if (aAttr == nsGkAtoms::onload)
- return nsGkAtoms::onSVGLoad;
- if (aAttr == nsGkAtoms::onunload)
- return nsGkAtoms::onSVGUnload;
- if (aAttr == nsGkAtoms::onresize)
- return nsGkAtoms::onSVGResize;
- if (aAttr == nsGkAtoms::onscroll)
- return nsGkAtoms::onSVGScroll;
- if (aAttr == nsGkAtoms::onzoom)
- return nsGkAtoms::onSVGZoom;
- if (aAttr == nsGkAtoms::onbegin)
- return nsGkAtoms::onbeginEvent;
- if (aAttr == nsGkAtoms::onrepeat)
- return nsGkAtoms::onrepeatEvent;
- if (aAttr == nsGkAtoms::onend)
- return nsGkAtoms::onendEvent;
- return aAttr;
- }
- SVGSVGElement *
- nsSVGElement::GetCtx() const
- {
- nsIContent* ancestor = GetFlattenedTreeParent();
- while (ancestor && ancestor->IsSVGElement()) {
- if (ancestor->IsSVGElement(nsGkAtoms::foreignObject)) {
- return nullptr;
- }
- if (ancestor->IsSVGElement(nsGkAtoms::svg)) {
- return static_cast<SVGSVGElement*>(ancestor);
- }
- ancestor = ancestor->GetFlattenedTreeParent();
- }
- // we don't have an ancestor <svg> element...
- return nullptr;
- }
- /* virtual */ gfxMatrix
- nsSVGElement::PrependLocalTransformsTo(
- const gfxMatrix &aMatrix, SVGTransformTypes aWhich) const
- {
- return aMatrix;
- }
- nsSVGElement::LengthAttributesInfo
- nsSVGElement::GetLengthInfo()
- {
- return LengthAttributesInfo(nullptr, nullptr, 0);
- }
- void nsSVGElement::LengthAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mLengths[aAttrEnum].Init(mLengthInfo[aAttrEnum].mCtxType,
- aAttrEnum,
- mLengthInfo[aAttrEnum].mDefaultValue,
- mLengthInfo[aAttrEnum].mDefaultUnitType);
- }
- void
- nsSVGElement::SetLength(nsIAtom* aName, const nsSVGLength2 &aLength)
- {
- LengthAttributesInfo lengthInfo = GetLengthInfo();
- for (uint32_t i = 0; i < lengthInfo.mLengthCount; i++) {
- if (aName == *lengthInfo.mLengthInfo[i].mName) {
- lengthInfo.mLengths[i] = aLength;
- DidAnimateLength(i);
- return;
- }
- }
- MOZ_ASSERT(false, "no length found to set");
- }
- nsAttrValue
- nsSVGElement::WillChangeLength(uint8_t aAttrEnum)
- {
- return WillChangeValue(*GetLengthInfo().mLengthInfo[aAttrEnum].mName);
- }
- void
- nsSVGElement::DidChangeLength(uint8_t aAttrEnum,
- const nsAttrValue& aEmptyOrOldValue)
- {
- LengthAttributesInfo info = GetLengthInfo();
- NS_ASSERTION(info.mLengthCount > 0,
- "DidChangeLength on element with no length attribs");
- NS_ASSERTION(aAttrEnum < info.mLengthCount, "aAttrEnum out of range");
- nsAttrValue newValue;
- newValue.SetTo(info.mLengths[aAttrEnum], nullptr);
- DidChangeValue(*info.mLengthInfo[aAttrEnum].mName, aEmptyOrOldValue,
- newValue);
- }
- void
- nsSVGElement::DidAnimateLength(uint8_t aAttrEnum)
- {
- ClearAnyCachedPath();
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- LengthAttributesInfo info = GetLengthInfo();
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mLengthInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsSVGLength2*
- nsSVGElement::GetAnimatedLength(const nsIAtom *aAttrName)
- {
- LengthAttributesInfo lengthInfo = GetLengthInfo();
- for (uint32_t i = 0; i < lengthInfo.mLengthCount; i++) {
- if (aAttrName == *lengthInfo.mLengthInfo[i].mName) {
- return &lengthInfo.mLengths[i];
- }
- }
- MOZ_ASSERT(false, "no matching length found");
- return nullptr;
- }
- void
- nsSVGElement::GetAnimatedLengthValues(float *aFirst, ...)
- {
- LengthAttributesInfo info = GetLengthInfo();
- NS_ASSERTION(info.mLengthCount > 0,
- "GetAnimatedLengthValues on element with no length attribs");
- SVGSVGElement *ctx = nullptr;
- float *f = aFirst;
- uint32_t i = 0;
- va_list args;
- va_start(args, aFirst);
- while (f && i < info.mLengthCount) {
- uint8_t type = info.mLengths[i].GetSpecifiedUnitType();
- if (!ctx) {
- if (type != nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER &&
- type != nsIDOMSVGLength::SVG_LENGTHTYPE_PX)
- ctx = GetCtx();
- }
- if (type == nsIDOMSVGLength::SVG_LENGTHTYPE_EMS ||
- type == nsIDOMSVGLength::SVG_LENGTHTYPE_EXS)
- *f = info.mLengths[i++].GetAnimValue(this);
- else
- *f = info.mLengths[i++].GetAnimValue(ctx);
- f = va_arg(args, float*);
- }
- va_end(args);
- }
- nsSVGElement::LengthListAttributesInfo
- nsSVGElement::GetLengthListInfo()
- {
- return LengthListAttributesInfo(nullptr, nullptr, 0);
- }
- void
- nsSVGElement::LengthListAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mLengthLists[aAttrEnum].ClearBaseValue(aAttrEnum);
- // caller notifies
- }
- nsAttrValue
- nsSVGElement::WillChangeLengthList(uint8_t aAttrEnum)
- {
- return WillChangeValue(*GetLengthListInfo().mLengthListInfo[aAttrEnum].mName);
- }
- void
- nsSVGElement::DidChangeLengthList(uint8_t aAttrEnum,
- const nsAttrValue& aEmptyOrOldValue)
- {
- LengthListAttributesInfo info = GetLengthListInfo();
- NS_ASSERTION(info.mLengthListCount > 0,
- "DidChangeLengthList on element with no length list attribs");
- NS_ASSERTION(aAttrEnum < info.mLengthListCount, "aAttrEnum out of range");
- nsAttrValue newValue;
- newValue.SetTo(info.mLengthLists[aAttrEnum].GetBaseValue(), nullptr);
- DidChangeValue(*info.mLengthListInfo[aAttrEnum].mName, aEmptyOrOldValue,
- newValue);
- }
- void
- nsSVGElement::DidAnimateLengthList(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- LengthListAttributesInfo info = GetLengthListInfo();
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mLengthListInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- void
- nsSVGElement::GetAnimatedLengthListValues(SVGUserUnitList *aFirst, ...)
- {
- LengthListAttributesInfo info = GetLengthListInfo();
- NS_ASSERTION(info.mLengthListCount > 0,
- "GetAnimatedLengthListValues on element with no length list attribs");
- SVGUserUnitList *list = aFirst;
- uint32_t i = 0;
- va_list args;
- va_start(args, aFirst);
- while (list && i < info.mLengthListCount) {
- list->Init(&(info.mLengthLists[i].GetAnimValue()), this, info.mLengthListInfo[i].mAxis);
- ++i;
- list = va_arg(args, SVGUserUnitList*);
- }
- va_end(args);
- }
- SVGAnimatedLengthList*
- nsSVGElement::GetAnimatedLengthList(uint8_t aAttrEnum)
- {
- LengthListAttributesInfo info = GetLengthListInfo();
- if (aAttrEnum < info.mLengthListCount) {
- return &(info.mLengthLists[aAttrEnum]);
- }
- NS_NOTREACHED("Bad attrEnum");
- return nullptr;
- }
- nsSVGElement::NumberListAttributesInfo
- nsSVGElement::GetNumberListInfo()
- {
- return NumberListAttributesInfo(nullptr, nullptr, 0);
- }
- void
- nsSVGElement::NumberListAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- MOZ_ASSERT(aAttrEnum < mNumberListCount, "Bad attr enum");
- mNumberLists[aAttrEnum].ClearBaseValue(aAttrEnum);
- // caller notifies
- }
- nsAttrValue
- nsSVGElement::WillChangeNumberList(uint8_t aAttrEnum)
- {
- return WillChangeValue(*GetNumberListInfo().mNumberListInfo[aAttrEnum].mName);
- }
- void
- nsSVGElement::DidChangeNumberList(uint8_t aAttrEnum,
- const nsAttrValue& aEmptyOrOldValue)
- {
- NumberListAttributesInfo info = GetNumberListInfo();
- MOZ_ASSERT(info.mNumberListCount > 0,
- "DidChangeNumberList on element with no number list attribs");
- MOZ_ASSERT(aAttrEnum < info.mNumberListCount,
- "aAttrEnum out of range");
- nsAttrValue newValue;
- newValue.SetTo(info.mNumberLists[aAttrEnum].GetBaseValue(), nullptr);
- DidChangeValue(*info.mNumberListInfo[aAttrEnum].mName, aEmptyOrOldValue,
- newValue);
- }
- void
- nsSVGElement::DidAnimateNumberList(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- NumberListAttributesInfo info = GetNumberListInfo();
- MOZ_ASSERT(aAttrEnum < info.mNumberListCount, "aAttrEnum out of range");
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mNumberListInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- SVGAnimatedNumberList*
- nsSVGElement::GetAnimatedNumberList(uint8_t aAttrEnum)
- {
- NumberListAttributesInfo info = GetNumberListInfo();
- if (aAttrEnum < info.mNumberListCount) {
- return &(info.mNumberLists[aAttrEnum]);
- }
- MOZ_ASSERT(false, "Bad attrEnum");
- return nullptr;
- }
- SVGAnimatedNumberList*
- nsSVGElement::GetAnimatedNumberList(nsIAtom *aAttrName)
- {
- NumberListAttributesInfo info = GetNumberListInfo();
- for (uint32_t i = 0; i < info.mNumberListCount; i++) {
- if (aAttrName == *info.mNumberListInfo[i].mName) {
- return &info.mNumberLists[i];
- }
- }
- MOZ_ASSERT(false, "Bad caller");
- return nullptr;
- }
- nsAttrValue
- nsSVGElement::WillChangePointList()
- {
- MOZ_ASSERT(GetPointListAttrName(),
- "Changing non-existent point list?");
- return WillChangeValue(GetPointListAttrName());
- }
- void
- nsSVGElement::DidChangePointList(const nsAttrValue& aEmptyOrOldValue)
- {
- MOZ_ASSERT(GetPointListAttrName(),
- "Changing non-existent point list?");
- nsAttrValue newValue;
- newValue.SetTo(GetAnimatedPointList()->GetBaseValue(), nullptr);
- DidChangeValue(GetPointListAttrName(), aEmptyOrOldValue, newValue);
- }
- void
- nsSVGElement::DidAnimatePointList()
- {
- MOZ_ASSERT(GetPointListAttrName(),
- "Animating non-existent path data?");
- ClearAnyCachedPath();
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- frame->AttributeChanged(kNameSpaceID_None,
- GetPointListAttrName(),
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsAttrValue
- nsSVGElement::WillChangePathSegList()
- {
- MOZ_ASSERT(GetPathDataAttrName(),
- "Changing non-existent path seg list?");
- return WillChangeValue(GetPathDataAttrName());
- }
- void
- nsSVGElement::DidChangePathSegList(const nsAttrValue& aEmptyOrOldValue)
- {
- MOZ_ASSERT(GetPathDataAttrName(),
- "Changing non-existent path seg list?");
- nsAttrValue newValue;
- newValue.SetTo(GetAnimPathSegList()->GetBaseValue(), nullptr);
- DidChangeValue(GetPathDataAttrName(), aEmptyOrOldValue, newValue);
- }
- void
- nsSVGElement::DidAnimatePathSegList()
- {
- MOZ_ASSERT(GetPathDataAttrName(),
- "Animating non-existent path data?");
- ClearAnyCachedPath();
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- frame->AttributeChanged(kNameSpaceID_None,
- GetPathDataAttrName(),
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsSVGElement::NumberAttributesInfo
- nsSVGElement::GetNumberInfo()
- {
- return NumberAttributesInfo(nullptr, nullptr, 0);
- }
- void nsSVGElement::NumberAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mNumbers[aAttrEnum].Init(aAttrEnum,
- mNumberInfo[aAttrEnum].mDefaultValue);
- }
- void
- nsSVGElement::DidChangeNumber(uint8_t aAttrEnum)
- {
- NumberAttributesInfo info = GetNumberInfo();
- NS_ASSERTION(info.mNumberCount > 0,
- "DidChangeNumber on element with no number attribs");
- NS_ASSERTION(aAttrEnum < info.mNumberCount, "aAttrEnum out of range");
- nsAttrValue attrValue;
- attrValue.SetTo(info.mNumbers[aAttrEnum].GetBaseValue(), nullptr);
- SetParsedAttr(kNameSpaceID_None, *info.mNumberInfo[aAttrEnum].mName, nullptr,
- attrValue, true);
- }
- void
- nsSVGElement::DidAnimateNumber(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- NumberAttributesInfo info = GetNumberInfo();
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mNumberInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- void
- nsSVGElement::GetAnimatedNumberValues(float *aFirst, ...)
- {
- NumberAttributesInfo info = GetNumberInfo();
- NS_ASSERTION(info.mNumberCount > 0,
- "GetAnimatedNumberValues on element with no number attribs");
- float *f = aFirst;
- uint32_t i = 0;
- va_list args;
- va_start(args, aFirst);
- while (f && i < info.mNumberCount) {
- *f = info.mNumbers[i++].GetAnimValue();
- f = va_arg(args, float*);
- }
- va_end(args);
- }
- nsSVGElement::NumberPairAttributesInfo
- nsSVGElement::GetNumberPairInfo()
- {
- return NumberPairAttributesInfo(nullptr, nullptr, 0);
- }
- void nsSVGElement::NumberPairAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mNumberPairs[aAttrEnum].Init(aAttrEnum,
- mNumberPairInfo[aAttrEnum].mDefaultValue1,
- mNumberPairInfo[aAttrEnum].mDefaultValue2);
- }
- nsAttrValue
- nsSVGElement::WillChangeNumberPair(uint8_t aAttrEnum)
- {
- return WillChangeValue(*GetNumberPairInfo().mNumberPairInfo[aAttrEnum].mName);
- }
- void
- nsSVGElement::DidChangeNumberPair(uint8_t aAttrEnum,
- const nsAttrValue& aEmptyOrOldValue)
- {
- NumberPairAttributesInfo info = GetNumberPairInfo();
- NS_ASSERTION(info.mNumberPairCount > 0,
- "DidChangePairNumber on element with no number pair attribs");
- NS_ASSERTION(aAttrEnum < info.mNumberPairCount, "aAttrEnum out of range");
- nsAttrValue newValue;
- newValue.SetTo(info.mNumberPairs[aAttrEnum], nullptr);
- DidChangeValue(*info.mNumberPairInfo[aAttrEnum].mName, aEmptyOrOldValue,
- newValue);
- }
- void
- nsSVGElement::DidAnimateNumberPair(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- NumberPairAttributesInfo info = GetNumberPairInfo();
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mNumberPairInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsSVGElement::IntegerAttributesInfo
- nsSVGElement::GetIntegerInfo()
- {
- return IntegerAttributesInfo(nullptr, nullptr, 0);
- }
- void nsSVGElement::IntegerAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mIntegers[aAttrEnum].Init(aAttrEnum,
- mIntegerInfo[aAttrEnum].mDefaultValue);
- }
- void
- nsSVGElement::DidChangeInteger(uint8_t aAttrEnum)
- {
- IntegerAttributesInfo info = GetIntegerInfo();
- NS_ASSERTION(info.mIntegerCount > 0,
- "DidChangeInteger on element with no integer attribs");
- NS_ASSERTION(aAttrEnum < info.mIntegerCount, "aAttrEnum out of range");
- nsAttrValue attrValue;
- attrValue.SetTo(info.mIntegers[aAttrEnum].GetBaseValue(), nullptr);
- SetParsedAttr(kNameSpaceID_None, *info.mIntegerInfo[aAttrEnum].mName, nullptr,
- attrValue, true);
- }
- void
- nsSVGElement::DidAnimateInteger(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
-
- if (frame) {
- IntegerAttributesInfo info = GetIntegerInfo();
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mIntegerInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- void
- nsSVGElement::GetAnimatedIntegerValues(int32_t *aFirst, ...)
- {
- IntegerAttributesInfo info = GetIntegerInfo();
- NS_ASSERTION(info.mIntegerCount > 0,
- "GetAnimatedIntegerValues on element with no integer attribs");
- int32_t *n = aFirst;
- uint32_t i = 0;
- va_list args;
- va_start(args, aFirst);
- while (n && i < info.mIntegerCount) {
- *n = info.mIntegers[i++].GetAnimValue();
- n = va_arg(args, int32_t*);
- }
- va_end(args);
- }
- nsSVGElement::IntegerPairAttributesInfo
- nsSVGElement::GetIntegerPairInfo()
- {
- return IntegerPairAttributesInfo(nullptr, nullptr, 0);
- }
- void nsSVGElement::IntegerPairAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mIntegerPairs[aAttrEnum].Init(aAttrEnum,
- mIntegerPairInfo[aAttrEnum].mDefaultValue1,
- mIntegerPairInfo[aAttrEnum].mDefaultValue2);
- }
- nsAttrValue
- nsSVGElement::WillChangeIntegerPair(uint8_t aAttrEnum)
- {
- return WillChangeValue(
- *GetIntegerPairInfo().mIntegerPairInfo[aAttrEnum].mName);
- }
- void
- nsSVGElement::DidChangeIntegerPair(uint8_t aAttrEnum,
- const nsAttrValue& aEmptyOrOldValue)
- {
- IntegerPairAttributesInfo info = GetIntegerPairInfo();
- NS_ASSERTION(info.mIntegerPairCount > 0,
- "DidChangeIntegerPair on element with no integer pair attribs");
- NS_ASSERTION(aAttrEnum < info.mIntegerPairCount, "aAttrEnum out of range");
- nsAttrValue newValue;
- newValue.SetTo(info.mIntegerPairs[aAttrEnum], nullptr);
- DidChangeValue(*info.mIntegerPairInfo[aAttrEnum].mName, aEmptyOrOldValue,
- newValue);
- }
- void
- nsSVGElement::DidAnimateIntegerPair(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
-
- if (frame) {
- IntegerPairAttributesInfo info = GetIntegerPairInfo();
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mIntegerPairInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsSVGElement::AngleAttributesInfo
- nsSVGElement::GetAngleInfo()
- {
- return AngleAttributesInfo(nullptr, nullptr, 0);
- }
- void nsSVGElement::AngleAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mAngles[aAttrEnum].Init(aAttrEnum,
- mAngleInfo[aAttrEnum].mDefaultValue,
- mAngleInfo[aAttrEnum].mDefaultUnitType);
- }
- nsAttrValue
- nsSVGElement::WillChangeAngle(uint8_t aAttrEnum)
- {
- return WillChangeValue(*GetAngleInfo().mAngleInfo[aAttrEnum].mName);
- }
- void
- nsSVGElement::DidChangeAngle(uint8_t aAttrEnum,
- const nsAttrValue& aEmptyOrOldValue)
- {
- AngleAttributesInfo info = GetAngleInfo();
- NS_ASSERTION(info.mAngleCount > 0,
- "DidChangeAngle on element with no angle attribs");
- NS_ASSERTION(aAttrEnum < info.mAngleCount, "aAttrEnum out of range");
- nsAttrValue newValue;
- newValue.SetTo(info.mAngles[aAttrEnum], nullptr);
- DidChangeValue(*info.mAngleInfo[aAttrEnum].mName, aEmptyOrOldValue, newValue);
- }
- void
- nsSVGElement::DidAnimateAngle(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- AngleAttributesInfo info = GetAngleInfo();
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mAngleInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsSVGElement::BooleanAttributesInfo
- nsSVGElement::GetBooleanInfo()
- {
- return BooleanAttributesInfo(nullptr, nullptr, 0);
- }
- void nsSVGElement::BooleanAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mBooleans[aAttrEnum].Init(aAttrEnum,
- mBooleanInfo[aAttrEnum].mDefaultValue);
- }
- void
- nsSVGElement::DidChangeBoolean(uint8_t aAttrEnum)
- {
- BooleanAttributesInfo info = GetBooleanInfo();
- NS_ASSERTION(info.mBooleanCount > 0,
- "DidChangeBoolean on element with no boolean attribs");
- NS_ASSERTION(aAttrEnum < info.mBooleanCount, "aAttrEnum out of range");
- nsAttrValue attrValue(info.mBooleans[aAttrEnum].GetBaseValueAtom());
- SetParsedAttr(kNameSpaceID_None, *info.mBooleanInfo[aAttrEnum].mName, nullptr,
- attrValue, true);
- }
- void
- nsSVGElement::DidAnimateBoolean(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
-
- if (frame) {
- BooleanAttributesInfo info = GetBooleanInfo();
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mBooleanInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsSVGElement::EnumAttributesInfo
- nsSVGElement::GetEnumInfo()
- {
- return EnumAttributesInfo(nullptr, nullptr, 0);
- }
- void nsSVGElement::EnumAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mEnums[aAttrEnum].Init(aAttrEnum,
- mEnumInfo[aAttrEnum].mDefaultValue);
- }
- void
- nsSVGElement::DidChangeEnum(uint8_t aAttrEnum)
- {
- EnumAttributesInfo info = GetEnumInfo();
- NS_ASSERTION(info.mEnumCount > 0,
- "DidChangeEnum on element with no enum attribs");
- NS_ASSERTION(aAttrEnum < info.mEnumCount, "aAttrEnum out of range");
- nsAttrValue attrValue(info.mEnums[aAttrEnum].GetBaseValueAtom(this));
- SetParsedAttr(kNameSpaceID_None, *info.mEnumInfo[aAttrEnum].mName, nullptr,
- attrValue, true);
- }
- void
- nsSVGElement::DidAnimateEnum(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- EnumAttributesInfo info = GetEnumInfo();
- frame->AttributeChanged(kNameSpaceID_None,
- *info.mEnumInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsSVGViewBox *
- nsSVGElement::GetViewBox()
- {
- return nullptr;
- }
- nsAttrValue
- nsSVGElement::WillChangeViewBox()
- {
- return WillChangeValue(nsGkAtoms::viewBox);
- }
- void
- nsSVGElement::DidChangeViewBox(const nsAttrValue& aEmptyOrOldValue)
- {
- nsSVGViewBox *viewBox = GetViewBox();
- NS_ASSERTION(viewBox, "DidChangeViewBox on element with no viewBox attrib");
- nsAttrValue newValue;
- newValue.SetTo(*viewBox, nullptr);
- DidChangeValue(nsGkAtoms::viewBox, aEmptyOrOldValue, newValue);
- }
- void
- nsSVGElement::DidAnimateViewBox()
- {
- nsIFrame* frame = GetPrimaryFrame();
-
- if (frame) {
- frame->AttributeChanged(kNameSpaceID_None,
- nsGkAtoms::viewBox,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- SVGAnimatedPreserveAspectRatio *
- nsSVGElement::GetPreserveAspectRatio()
- {
- return nullptr;
- }
- nsAttrValue
- nsSVGElement::WillChangePreserveAspectRatio()
- {
- return WillChangeValue(nsGkAtoms::preserveAspectRatio);
- }
- void
- nsSVGElement::DidChangePreserveAspectRatio(const nsAttrValue& aEmptyOrOldValue)
- {
- SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
- GetPreserveAspectRatio();
- NS_ASSERTION(preserveAspectRatio,
- "DidChangePreserveAspectRatio on element with no "
- "preserveAspectRatio attrib");
- nsAttrValue newValue;
- newValue.SetTo(*preserveAspectRatio, nullptr);
- DidChangeValue(nsGkAtoms::preserveAspectRatio, aEmptyOrOldValue, newValue);
- }
- void
- nsSVGElement::DidAnimatePreserveAspectRatio()
- {
- nsIFrame* frame = GetPrimaryFrame();
-
- if (frame) {
- frame->AttributeChanged(kNameSpaceID_None,
- nsGkAtoms::preserveAspectRatio,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsAttrValue
- nsSVGElement::WillChangeTransformList()
- {
- return WillChangeValue(GetTransformListAttrName());
- }
- void
- nsSVGElement::DidChangeTransformList(const nsAttrValue& aEmptyOrOldValue)
- {
- MOZ_ASSERT(GetTransformListAttrName(),
- "Changing non-existent transform list?");
- // The transform attribute is being set, so we must ensure that the
- // SVGAnimatedTransformList is/has been allocated:
- nsAttrValue newValue;
- newValue.SetTo(GetAnimatedTransformList(DO_ALLOCATE)->GetBaseValue(), nullptr);
- DidChangeValue(GetTransformListAttrName(), aEmptyOrOldValue, newValue);
- }
- void
- nsSVGElement::DidAnimateTransformList(int32_t aModType)
- {
- MOZ_ASSERT(GetTransformListAttrName(),
- "Animating non-existent transform data?");
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- nsIAtom *transformAttr = GetTransformListAttrName();
- frame->AttributeChanged(kNameSpaceID_None,
- transformAttr,
- aModType);
- // When script changes the 'transform' attribute, Element::SetAttrAndNotify
- // will call nsNodeUtills::AttributeChanged, under which
- // SVGTransformableElement::GetAttributeChangeHint will be called and an
- // appropriate change event posted to update our frame's overflow rects.
- // The SetAttrAndNotify doesn't happen for transform changes caused by
- // 'animateTransform' though (and sending out the mutation events that
- // nsNodeUtills::AttributeChanged dispatches would be inappropriate
- // anyway), so we need to post the change event ourself.
- nsChangeHint changeHint = GetAttributeChangeHint(transformAttr, aModType);
- if (changeHint) {
- nsLayoutUtils::PostRestyleEvent(this, nsRestyleHint(0), changeHint);
- }
- }
- }
- nsSVGElement::StringAttributesInfo
- nsSVGElement::GetStringInfo()
- {
- return StringAttributesInfo(nullptr, nullptr, 0);
- }
- void nsSVGElement::StringAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mStrings[aAttrEnum].Init(aAttrEnum);
- }
- void nsSVGElement::GetStringBaseValue(uint8_t aAttrEnum, nsAString& aResult) const
- {
- nsSVGElement::StringAttributesInfo info = const_cast<nsSVGElement*>(this)->GetStringInfo();
- NS_ASSERTION(info.mStringCount > 0,
- "GetBaseValue on element with no string attribs");
- NS_ASSERTION(aAttrEnum < info.mStringCount, "aAttrEnum out of range");
- GetAttr(info.mStringInfo[aAttrEnum].mNamespaceID,
- *info.mStringInfo[aAttrEnum].mName, aResult);
- }
- void nsSVGElement::SetStringBaseValue(uint8_t aAttrEnum, const nsAString& aValue)
- {
- nsSVGElement::StringAttributesInfo info = GetStringInfo();
- NS_ASSERTION(info.mStringCount > 0,
- "SetBaseValue on element with no string attribs");
- NS_ASSERTION(aAttrEnum < info.mStringCount, "aAttrEnum out of range");
- SetAttr(info.mStringInfo[aAttrEnum].mNamespaceID,
- *info.mStringInfo[aAttrEnum].mName, aValue, true);
- }
- void
- nsSVGElement::DidAnimateString(uint8_t aAttrEnum)
- {
- nsIFrame* frame = GetPrimaryFrame();
- if (frame) {
- StringAttributesInfo info = GetStringInfo();
- frame->AttributeChanged(info.mStringInfo[aAttrEnum].mNamespaceID,
- *info.mStringInfo[aAttrEnum].mName,
- nsIDOMMutationEvent::MODIFICATION);
- }
- }
- nsSVGElement::StringListAttributesInfo
- nsSVGElement::GetStringListInfo()
- {
- return StringListAttributesInfo(nullptr, nullptr, 0);
- }
- nsAttrValue
- nsSVGElement::WillChangeStringList(bool aIsConditionalProcessingAttribute,
- uint8_t aAttrEnum)
- {
- nsIAtom* name;
- if (aIsConditionalProcessingAttribute) {
- nsCOMPtr<SVGTests> tests(do_QueryInterface(static_cast<nsIDOMSVGElement*>(this)));
- name = tests->GetAttrName(aAttrEnum);
- } else {
- name = *GetStringListInfo().mStringListInfo[aAttrEnum].mName;
- }
- return WillChangeValue(name);
- }
- void
- nsSVGElement::DidChangeStringList(bool aIsConditionalProcessingAttribute,
- uint8_t aAttrEnum,
- const nsAttrValue& aEmptyOrOldValue)
- {
- nsIAtom* name;
- nsAttrValue newValue;
- nsCOMPtr<SVGTests> tests;
- if (aIsConditionalProcessingAttribute) {
- tests = do_QueryObject(this);
- name = tests->GetAttrName(aAttrEnum);
- tests->GetAttrValue(aAttrEnum, newValue);
- } else {
- StringListAttributesInfo info = GetStringListInfo();
- NS_ASSERTION(info.mStringListCount > 0,
- "DidChangeStringList on element with no string list attribs");
- NS_ASSERTION(aAttrEnum < info.mStringListCount, "aAttrEnum out of range");
- name = *info.mStringListInfo[aAttrEnum].mName;
- newValue.SetTo(info.mStringLists[aAttrEnum], nullptr);
- }
- DidChangeValue(name, aEmptyOrOldValue, newValue);
- if (aIsConditionalProcessingAttribute) {
- tests->MaybeInvalidate();
- }
- }
- void
- nsSVGElement::StringListAttributesInfo::Reset(uint8_t aAttrEnum)
- {
- mStringLists[aAttrEnum].Clear();
- // caller notifies
- }
- nsresult
- nsSVGElement::ReportAttributeParseFailure(nsIDocument* aDocument,
- nsIAtom* aAttribute,
- const nsAString& aValue)
- {
- const nsAFlatString& attributeValue = PromiseFlatString(aValue);
- const char16_t *strings[] = { aAttribute->GetUTF16String(),
- attributeValue.get() };
- return SVGContentUtils::ReportToConsole(aDocument,
- "AttributeParseWarning",
- strings, ArrayLength(strings));
- }
- void
- nsSVGElement::RecompileScriptEventListeners()
- {
- int32_t i, count = mAttrsAndChildren.AttrCount();
- for (i = 0; i < count; ++i) {
- const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
- // Eventlistenener-attributes are always in the null namespace
- if (!name->IsAtom()) {
- continue;
- }
- nsIAtom *attr = name->Atom();
- if (!IsEventAttributeName(attr)) {
- continue;
- }
- nsAutoString value;
- GetAttr(kNameSpaceID_None, attr, value);
- SetEventHandler(GetEventNameForAttr(attr), value, true);
- }
- }
- nsISMILAttr*
- nsSVGElement::GetAnimatedAttr(int32_t aNamespaceID, nsIAtom* aName)
- {
- if (aNamespaceID == kNameSpaceID_None) {
- // We check mapped-into-style attributes first so that animations
- // targeting width/height on outer-<svg> don't appear to be ignored
- // because we returned a nsISMILAttr for the corresponding
- // SVGAnimatedLength.
- // Mapped attributes:
- if (IsAttributeMapped(aName)) {
- nsCSSPropertyID prop =
- nsCSSProps::LookupProperty(nsDependentAtomString(aName),
- CSSEnabledState::eForAllContent);
- // Check IsPropertyAnimatable to avoid attributes that...
- // - map to explicitly unanimatable properties (e.g. 'direction')
- // - map to unsupported attributes (e.g. 'glyph-orientation-horizontal')
- if (nsSMILCSSProperty::IsPropertyAnimatable(prop)) {
- return new nsSMILMappedAttribute(prop, this);
- }
- }
- // Transforms:
- if (GetTransformListAttrName() == aName) {
- // The transform attribute is being animated, so we must ensure that the
- // SVGAnimatedTransformList is/has been allocated:
- return GetAnimatedTransformList(DO_ALLOCATE)->ToSMILAttr(this);
- }
- // Motion (fake 'attribute' for animateMotion)
- if (aName == nsGkAtoms::mozAnimateMotionDummyAttr) {
- return new SVGMotionSMILAttr(this);
- }
- // Lengths:
- LengthAttributesInfo info = GetLengthInfo();
- for (uint32_t i = 0; i < info.mLengthCount; i++) {
- if (aName == *info.mLengthInfo[i].mName) {
- return info.mLengths[i].ToSMILAttr(this);
- }
- }
- // Numbers:
- {
- NumberAttributesInfo info = GetNumberInfo();
- for (uint32_t i = 0; i < info.mNumberCount; i++) {
- if (aName == *info.mNumberInfo[i].mName) {
- return info.mNumbers[i].ToSMILAttr(this);
- }
- }
- }
- // Number Pairs:
- {
- NumberPairAttributesInfo info = GetNumberPairInfo();
- for (uint32_t i = 0; i < info.mNumberPairCount; i++) {
- if (aName == *info.mNumberPairInfo[i].mName) {
- return info.mNumberPairs[i].ToSMILAttr(this);
- }
- }
- }
- // Integers:
- {
- IntegerAttributesInfo info = GetIntegerInfo();
- for (uint32_t i = 0; i < info.mIntegerCount; i++) {
- if (aName == *info.mIntegerInfo[i].mName) {
- return info.mIntegers[i].ToSMILAttr(this);
- }
- }
- }
- // Integer Pairs:
- {
- IntegerPairAttributesInfo info = GetIntegerPairInfo();
- for (uint32_t i = 0; i < info.mIntegerPairCount; i++) {
- if (aName == *info.mIntegerPairInfo[i].mName) {
- return info.mIntegerPairs[i].ToSMILAttr(this);
- }
- }
- }
- // Enumerations:
- {
- EnumAttributesInfo info = GetEnumInfo();
- for (uint32_t i = 0; i < info.mEnumCount; i++) {
- if (aName == *info.mEnumInfo[i].mName) {
- return info.mEnums[i].ToSMILAttr(this);
- }
- }
- }
- // Booleans:
- {
- BooleanAttributesInfo info = GetBooleanInfo();
- for (uint32_t i = 0; i < info.mBooleanCount; i++) {
- if (aName == *info.mBooleanInfo[i].mName) {
- return info.mBooleans[i].ToSMILAttr(this);
- }
- }
- }
- // Angles:
- {
- AngleAttributesInfo info = GetAngleInfo();
- for (uint32_t i = 0; i < info.mAngleCount; i++) {
- if (aName == *info.mAngleInfo[i].mName) {
- return info.mAngles[i].ToSMILAttr(this);
- }
- }
- }
- // viewBox:
- if (aName == nsGkAtoms::viewBox) {
- nsSVGViewBox *viewBox = GetViewBox();
- return viewBox ? viewBox->ToSMILAttr(this) : nullptr;
- }
- // preserveAspectRatio:
- if (aName == nsGkAtoms::preserveAspectRatio) {
- SVGAnimatedPreserveAspectRatio *preserveAspectRatio =
- GetPreserveAspectRatio();
- return preserveAspectRatio ?
- preserveAspectRatio->ToSMILAttr(this) : nullptr;
- }
- // NumberLists:
- {
- NumberListAttributesInfo info = GetNumberListInfo();
- for (uint32_t i = 0; i < info.mNumberListCount; i++) {
- if (aName == *info.mNumberListInfo[i].mName) {
- MOZ_ASSERT(i <= UCHAR_MAX, "Too many attributes");
- return info.mNumberLists[i].ToSMILAttr(this, uint8_t(i));
- }
- }
- }
- // LengthLists:
- {
- LengthListAttributesInfo info = GetLengthListInfo();
- for (uint32_t i = 0; i < info.mLengthListCount; i++) {
- if (aName == *info.mLengthListInfo[i].mName) {
- MOZ_ASSERT(i <= UCHAR_MAX, "Too many attributes");
- return info.mLengthLists[i].ToSMILAttr(this,
- uint8_t(i),
- info.mLengthListInfo[i].mAxis,
- info.mLengthListInfo[i].mCouldZeroPadList);
- }
- }
- }
- // PointLists:
- {
- if (GetPointListAttrName() == aName) {
- SVGAnimatedPointList *pointList = GetAnimatedPointList();
- if (pointList) {
- return pointList->ToSMILAttr(this);
- }
- }
- }
- // PathSegLists:
- {
- if (GetPathDataAttrName() == aName) {
- SVGAnimatedPathSegList *segList = GetAnimPathSegList();
- if (segList) {
- return segList->ToSMILAttr(this);
- }
- }
- }
- if (aName == nsGkAtoms::_class) {
- return mClassAttribute.ToSMILAttr(this);
- }
- }
- // Strings
- {
- StringAttributesInfo info = GetStringInfo();
- for (uint32_t i = 0; i < info.mStringCount; i++) {
- if (aNamespaceID == info.mStringInfo[i].mNamespaceID &&
- aName == *info.mStringInfo[i].mName) {
- return info.mStrings[i].ToSMILAttr(this);
- }
- }
- }
- return nullptr;
- }
- void
- nsSVGElement::AnimationNeedsResample()
- {
- nsIDocument* doc = GetComposedDoc();
- if (doc && doc->HasAnimationController()) {
- doc->GetAnimationController()->SetResampleNeeded();
- }
- }
- void
- nsSVGElement::FlushAnimations()
- {
- nsIDocument* doc = GetComposedDoc();
- if (doc && doc->HasAnimationController()) {
- doc->GetAnimationController()->FlushResampleRequests();
- }
- }
|