nsresult nsSVGElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, const nsAString* aValue, PRBool aNotify) { // 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 = nsnull; } if (IsEventName(aName) && aValue) { nsresult rv = AddScriptEventListener(GetEventNameForAttr(aName), *aValue); NS_ENSURE_SUCCESS(rv, rv); } if (aNamespaceID == kNameSpaceID_None && (aName == nsGkAtoms::requiredFeatures || aName == nsGkAtoms::requiredExtensions || aName == nsGkAtoms::systemLanguage)) { nsIContent* parent = nsSVGUtils::GetParentElement(this); if (parent && parent->NodeInfo()->Equals(nsGkAtoms::svgSwitch, kNameSpaceID_SVG)) { static_cast<nsSVGSwitchElement*>(parent)->MaybeInvalidate(); } } return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify); }
nsresult HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAttrValue* aValue, const nsAttrValue* aOldValue, nsIPrincipal* aSubjectPrincipal, bool aNotify) { nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify); NS_ENSURE_SUCCESS(rv, rv); // if the last mapped attribute was removed, don't clear the // nsMappedAttributes, our style can still depend on the containing frame element if (!aValue && IsAttributeMapped(aName)) { nsresult rv = mAttrs.ForceMapped(this, OwnerDoc()); NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; }
nsresult nsSVGElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName, PRBool aNotify) { PRBool foundMatch = PR_FALSE; if (aNamespaceID == kNameSpaceID_None) { // If this is an svg presentation attribute, remove rule to force an update if (IsAttributeMapped(aName)) mContentStyleRule = nsnull; if (IsEventName(aName)) { nsIEventListenerManager* manager = GetListenerManager(PR_FALSE); if (manager) { nsIAtom* eventName = GetEventNameForAttr(aName); manager->RemoveScriptEventListener(eventName); } foundMatch = PR_TRUE; } if (!foundMatch) { // Check if this is a length attribute going away LengthAttributesInfo lenInfo = GetLengthInfo(); for (PRUint32 i = 0; i < lenInfo.mLengthCount; i++) { if (aName == *lenInfo.mLengthInfo[i].mName) { lenInfo.Reset(i); DidChangeLength(i, PR_FALSE); foundMatch = PR_TRUE; break; } } } if (!foundMatch) { // Check if this is a number attribute going away NumberAttributesInfo numInfo = GetNumberInfo(); for (PRUint32 i = 0; i < numInfo.mNumberCount; i++) { if (aName == *numInfo.mNumberInfo[i].mName) { if (i + 1 < numInfo.mNumberCount && aName == *numInfo.mNumberInfo[i + 1].mName) { // found a number-optional-number numInfo.Reset(i + 1); DidChangeNumber(i + 1, PR_FALSE); } numInfo.Reset(i); DidChangeNumber(i, PR_FALSE); foundMatch = PR_TRUE; break; } } } if (!foundMatch) { // Check if this is an integer attribute going away IntegerAttributesInfo intInfo = GetIntegerInfo(); for (PRUint32 i = 0; i < intInfo.mIntegerCount; i++) { if (aName == *intInfo.mIntegerInfo[i].mName) { if (i + 1 < intInfo.mIntegerCount && aName == *intInfo.mIntegerInfo[i + 1].mName) { // found a number-optional-number intInfo.Reset(i + 1); DidChangeNumber(i + 1, PR_FALSE); } intInfo.Reset(i); DidChangeInteger(i, PR_FALSE); foundMatch = PR_TRUE; break; } } } if (!foundMatch) { // Check if this is an angle attribute going away AngleAttributesInfo angleInfo = GetAngleInfo(); for (PRUint32 i = 0; i < angleInfo.mAngleCount; i++) { if (aName == *angleInfo.mAngleInfo[i].mName) { angleInfo.Reset(i); DidChangeAngle(i, PR_FALSE); foundMatch = PR_TRUE; break; } } } if (!foundMatch) { // Check if this is a boolean attribute going away BooleanAttributesInfo boolInfo = GetBooleanInfo(); for (PRUint32 i = 0; i < boolInfo.mBooleanCount; i++) { if (aName == *boolInfo.mBooleanInfo[i].mName) { boolInfo.Reset(i); DidChangeBoolean(i, PR_FALSE); foundMatch = PR_TRUE; } } } if (!foundMatch) { // Check if this is an enum attribute going away EnumAttributesInfo enumInfo = GetEnumInfo(); for (PRUint32 i = 0; i < enumInfo.mEnumCount; i++) { if (aName == *enumInfo.mEnumInfo[i].mName) { enumInfo.Reset(i); DidChangeEnum(i, PR_FALSE); foundMatch = PR_TRUE; break; } } } if (!foundMatch) { // Check if this is a nsViewBox attribute going away if (aName == nsGkAtoms::viewBox) { nsSVGViewBox* viewBox = GetViewBox(); if (viewBox) { viewBox->Init(); DidChangeViewBox(PR_FALSE); foundMatch = PR_TRUE; } // Check if this is a preserveAspectRatio attribute going away } else if (aName == nsGkAtoms::preserveAspectRatio) { nsSVGPreserveAspectRatio *preserveAspectRatio = GetPreserveAspectRatio(); if (preserveAspectRatio) { preserveAspectRatio->Init(); DidChangePreserveAspectRatio(PR_FALSE); foundMatch = PR_TRUE; } } } } if (!foundMatch) { // Check if this is a string attribute going away StringAttributesInfo stringInfo = GetStringInfo(); for (PRUint32 i = 0; i < stringInfo.mStringCount; i++) { if (aNamespaceID == stringInfo.mStringInfo[i].mNamespaceID && aName == *stringInfo.mStringInfo[i].mName) { stringInfo.Reset(i); DidChangeString(i); foundMatch = PR_TRUE; break; } } } if (!foundMatch) { // Now check for one of the old style basetypes going away nsCOMPtr<nsISVGValue> svg_value = GetMappedAttribute(aNamespaceID, aName); if (svg_value) { mSuppressNotification = PR_TRUE; ResetOldStyleBaseType(svg_value); mSuppressNotification = PR_FALSE; } } return nsSVGElementBase::UnsetAttr(aNamespaceID, aName, aNotify); }
void nsSVGElement::UpdateContentStyleRule() { NS_ASSERTION(!mContentStyleRule, "we already have a content style rule"); nsIDocument* doc = GetOwnerDoc(); if (!doc) { NS_ERROR("SVG element without owner document"); return; } nsCOMPtr<nsIURI> baseURI = GetBaseURI(); nsIURI *docURI = doc->GetDocumentURI(); nsICSSLoader* cssLoader = doc->CSSLoader(); nsCSSDeclaration* declaration = nsnull; nsCOMPtr<nsICSSParser> parser; nsresult rv = NS_OK; PRUint32 attrCount = mAttrsAndChildren.AttrCount(); for (PRUint32 i = 0; i < attrCount; ++i) { const nsAttrName* attrName = mAttrsAndChildren.AttrNameAt(i); if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom())) continue; if (!declaration) { // Create the nsCSSDeclaration. declaration = new nsCSSDeclaration(); if (!declaration) { NS_WARNING("Failed to allocate nsCSSDeclaration"); return; } if (!declaration->InitializeEmpty()) { NS_WARNING("could not initialize nsCSSDeclaration"); declaration->RuleAbort(); // deletes declaration return; } // Try to fetch the CSS Parser from the document. rv = cssLoader->GetParserFor(nsnull, getter_AddRefs(parser)); if (NS_FAILED(rv)) { NS_WARNING("failed to get a css parser"); declaration->RuleAbort(); // deletes declaration return; } // SVG and CSS differ slightly in their interpretation of some of // the attributes. SVG allows attributes of the form: font-size="5" // (style="font-size: 5" if using a style attribute) // where CSS requires units: font-size="5pt" (style="font-size: 5pt") // Set a flag to pass information to the parser so that we can use // the CSS parser to parse the font-size attribute. Note that this // does *not* affect the use of CSS stylesheets, which will still // require units. parser->SetSVGMode(PR_TRUE); } nsAutoString name; attrName->Atom()->ToString(name); nsAutoString value; mAttrsAndChildren.AttrAt(i)->ToString(value); PRBool changed; parser->ParseProperty(nsCSSProps::LookupProperty(name), value, docURI, baseURI, NodePrincipal(), declaration, &changed); } if (declaration) { rv = NS_NewCSSStyleRule(getter_AddRefs(mContentStyleRule), nsnull, declaration); if (NS_FAILED(rv)) { NS_WARNING("could not create contentstylerule"); declaration->RuleAbort(); // deletes declaration } // Recycle the parser parser->SetSVGMode(PR_FALSE); cssLoader->RecycleParser(parser); } }