Bug 534028, Patch B: Add "MappedAttrParser" class to simplify parsing values for mapped attributes. r=dbaron
authorDaniel Holbert <dholbert@cs.stanford.edu>
Tue, 16 Mar 2010 16:17:32 -0700
changeset 39487 782e82ce2c29
parent 39486 3b169d4e085c
child 39488 33632ecef69c
push id12227
push userdholbert@mozilla.com
push dateTue, 16 Mar 2010 23:20:42 +0000
treeherdermozilla-central@9e96f8553258 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs534028
milestone1.9.3a4pre
Bug 534028, Patch B: Add "MappedAttrParser" class to simplify parsing values for mapped attributes. r=dbaron
content/svg/content/src/nsSVGElement.cpp
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -1016,16 +1016,111 @@ nsSVGElement::DidModifySVGObservable(nsI
 
 
   nsAttrValue newValue(aObservable);
   return SetAttrAndNotify(attrName->NamespaceID(), attrName->LocalName(),
                           attrName->GetPrefix(), EmptyString(), newValue,
                           data.modType, hasListeners, PR_TRUE, nsnull);
 }
 
+//------------------------------------------------------------------------
+// Helper class: MappedAttrParser, for parsing values of mapped attributes
+class MappedAttrParser {
+public:
+  MappedAttrParser(mozilla::css::Loader* aLoader,
+                   nsIURI* aDocURI,
+                   already_AddRefed<nsIURI> aBaseURI,
+                   nsIPrincipal* aNodePrincipal);
+  ~MappedAttrParser();
+
+  // Parses a mapped attribute value.
+  void ParseMappedAttrValue(nsIAtom* aMappedAttrName,
+                            nsAString& aMappedAttrValue);
+
+  // If we've parsed any values for mapped attributes, this method returns
+  // a new already_AddRefed nsICSSStyleRule that incorporates the parsed
+  // values. Otherwise, this method returns null. 
+  already_AddRefed<nsICSSStyleRule> CreateStyleRule();
+
+private:
+  // MEMBER DATA
+  // -----------
+  nsCSSParser       mParser;
+
+  // Arguments for nsCSSParser::ParseProperty
+  nsIURI*           mDocURI;
+  nsCOMPtr<nsIURI>  mBaseURI;
+  nsIPrincipal*     mNodePrincipal;
+
+  // Declaration for storing parsed values (lazily initialized)
+  nsCSSDeclaration* mDecl;
+};
+
+MappedAttrParser::MappedAttrParser(mozilla::css::Loader* aLoader,
+                                   nsIURI* aDocURI,
+                                   already_AddRefed<nsIURI> aBaseURI,
+                                   nsIPrincipal* aNodePrincipal)
+  : mParser(aLoader), mDocURI(aDocURI), mBaseURI(aBaseURI),
+    mNodePrincipal(aNodePrincipal), mDecl(nsnull)
+{
+  // mParser should successfully construct, now that we have infallible malloc.
+  NS_ABORT_IF_FALSE(mParser, "parser failed to initialize?");
+
+  // 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.
+  mParser.SetSVGMode(PR_TRUE);
+}
+
+MappedAttrParser::~MappedAttrParser()
+{
+  NS_ABORT_IF_FALSE(!mDecl,
+                    "If mDecl was initialized, it should have been converted "
+                    "into a style rule (and had its pointer cleared)");
+}
+
+void
+MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName,
+                                       nsAString& aMappedAttrValue)
+{
+  if (!mDecl) {
+    // Need to do lazy initializion of declaration.
+    mDecl = new nsCSSDeclaration();
+    mDecl->InitializeEmpty();
+  }
+
+  // Get the nsCSSProperty ID for our mapped attribute.
+  nsCSSProperty propertyID =
+    nsCSSProps::LookupProperty(nsAtomString(aMappedAttrName));
+  PRBool changed; // outparam for ParseProperty. (ignored)
+  mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
+                        mNodePrincipal, mDecl, &changed);
+}
+
+already_AddRefed<nsICSSStyleRule>
+MappedAttrParser::CreateStyleRule()
+{
+  if (!mDecl) {
+    return nsnull; // No mapped attributes were parsed
+  }
+
+  nsCOMPtr<nsICSSStyleRule> rule;
+  if (NS_FAILED(NS_NewCSSStyleRule(getter_AddRefs(rule), nsnull, mDecl))) {
+    NS_WARNING("could not create style rule from mapped attributes");
+    mDecl->RuleAbort(); // deletes declaration
+  }
+  mDecl = nsnull; // We no longer own the declaration -- drop our pointer to it
+  return rule.forget();
+}
+
 //----------------------------------------------------------------------
 // Implementation Helpers:
 
 PRBool
 nsSVGElement::IsEventName(nsIAtom* aName)
 {
   return PR_FALSE;
 }
@@ -1042,73 +1137,29 @@ nsSVGElement::UpdateContentStyleRule()
   }
 
   nsIDocument* doc = GetOwnerDoc();
   if (!doc) {
     NS_ERROR("SVG element without owner document");
     return;
   }
 
-  // Try to fetch the CSS Parser from the document.
-  nsCSSParser parser(doc->CSSLoader());
-  if (!parser) {
-    NS_WARNING("failed to get a css parser");
-    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);
-
-  nsCOMPtr<nsIURI> baseURI = GetBaseURI();
-  nsIURI *docURI = doc->GetDocumentURI();
-  nsCSSDeclaration* declaration = nsnull;
+  MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
+                                    GetBaseURI(), NodePrincipal());
 
   for (PRUint32 i = 0; i < attrCount; ++i) {
     const nsAttrName* attrName = mAttrsAndChildren.AttrNameAt(i);
     if (!attrName->IsAtom() || !IsAttributeMapped(attrName->Atom()))
       continue;
 
-    // Create the nsCSSDeclaration if we haven't already.
-    if (!declaration) {
-      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;
-      }
-    }
-
     nsAutoString value;
     mAttrsAndChildren.AttrAt(i)->ToString(value);
-
-    PRBool changed;
-    parser.ParseProperty(
-      nsCSSProps::LookupProperty(nsAtomString(attrName->Atom())), value,
-      docURI, baseURI, NodePrincipal(), declaration, &changed);
+    mappedAttrParser.ParseMappedAttrValue(attrName->Atom(), value);
   }
-
-  if (declaration) {
-    nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(mContentStyleRule),
-                                     nsnull, declaration);
-    if (NS_FAILED(rv)) {
-      NS_WARNING("could not create contentstylerule");
-      declaration->RuleAbort();  // deletes declaration
-    }
-  }
+  mContentStyleRule = mappedAttrParser.CreateStyleRule();
 }
 
 nsISVGValue*
 nsSVGElement::GetMappedAttribute(PRInt32 aNamespaceID, nsIAtom* aName)
 {
   const nsAttrValue* attrVal = mMappedAttributes.GetAttr(aName, aNamespaceID);
   if (!attrVal)
     return nsnull;