Bug 1086284 - Avoid using refcounting when determining an SVG-as-an-image's intrinsic size so that the image doesn't end up in the CC graph. r=dholbert
authorJonathan Watt <jwatt@jwatt.org>
Tue, 20 Jan 2015 14:27:16 +0000
changeset 224919 24dbc85426023355b60ee651fcd52c216d7a5c1a
parent 224918 594b535e44c8e1dc6890268c49e0204e16188a0b
child 224920 6390ede276aeb4f498d9f76ee377b5d1ef5989c0
push id54381
push userjwatt@jwatt.org
push dateWed, 21 Jan 2015 16:24:41 +0000
treeherdermozilla-inbound@bc86325c518b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1086284
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1086284 - Avoid using refcounting when determining an SVG-as-an-image's intrinsic size so that the image doesn't end up in the CC graph. r=dholbert
dom/svg/SVGSVGElement.cpp
dom/svg/SVGSVGElement.h
image/src/SVGDocumentWrapper.cpp
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -2,16 +2,17 @@
 /* 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 <stdint.h>
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
+#include "mozilla/FloatingPoint.h"
 #include "mozilla/Likely.h"
 
 #include "nsGkAtoms.h"
 #include "nsLayoutUtils.h"
 #include "nsLayoutStylesheetCache.h"
 #include "DOMSVGNumber.h"
 #include "DOMSVGLength.h"
 #include "nsSVGAngle.h"
@@ -1242,10 +1243,36 @@ SVGSVGElement::GetTransformProperty() co
 }
 
 bool
 SVGSVGElement::ClearTransformProperty()
 {
   return UnsetProperty(nsGkAtoms::transform);
 }
 
+float
+SVGSVGElement::GetIntrinsicWidth()
+{
+  if (mLengthAttributes[ATTR_WIDTH].IsPercentage()) {
+    return UnspecifiedNaN<float>();
+  }
+  // Passing |this| as a SVGSVGElement* invokes the variant of GetAnimValue
+  // that uses the passed argument as the context, but that's fine since we
+  // know the length isn't a percentage so the context won't be used (and we
+  // need to pass the element to be able to resolve em/ex units).
+  return std::max(mLengthAttributes[ATTR_WIDTH].GetAnimValue(this), 0.f);
+}
+
+float
+SVGSVGElement::GetIntrinsicHeight()
+{
+  if (mLengthAttributes[ATTR_HEIGHT].IsPercentage()) {
+    return UnspecifiedNaN<float>();
+  }
+  // Passing |this| as a SVGSVGElement* invokes the variant of GetAnimValue
+  // that uses the passed argument as the context, but that's fine since we
+  // know the length isn't a percentage so the context won't be used (and we
+  // need to pass the element to be able to resolve em/ex units).
+  return std::max(mLengthAttributes[ATTR_HEIGHT].GetAnimValue(this), 0.f);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -143,16 +143,24 @@ public:
   virtual bool HasValidDimensions() const MOZ_OVERRIDE;
 
   // SVGSVGElement methods:
   float GetLength(uint8_t mCtxType);
 
   // public helpers:
 
   /**
+   * Returns the user-unit width/height if those dimensions are not specified
+   * as percentage values. If they are specified as percentage values then this
+   * element does not have intrinsic width/height and these methods return NaN.
+   */
+  float GetIntrinsicWidth();
+  float GetIntrinsicHeight();
+
+  /**
    * Returns true if this element has a base/anim value for its "viewBox"
    * attribute that defines a viewBox rectangle with finite values, or
    * if there is a view element overriding this element's viewBox and it
    * has a valid viewBox.
    *
    * Note that this does not check whether we need to synthesize a viewBox,
    * so you must call ShouldSynthesizeViewBox() if you need to check that too.
    *
--- a/image/src/SVGDocumentWrapper.cpp
+++ b/image/src/SVGDocumentWrapper.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; 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 "SVGDocumentWrapper.h"
 
 #include "mozilla/dom/Element.h"
+#include "mozilla/FloatingPoint.h"
 #include "nsICategoryManager.h"
 #include "nsIChannel.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
 #include "nsIDocumentLoaderFactory.h"
 #include "nsIDOMSVGLength.h"
 #include "nsIHttpChannel.h"
 #include "nsIObserverService.h"
@@ -71,44 +72,24 @@ SVGDocumentWrapper::DestroyViewer()
 bool
 SVGDocumentWrapper::GetWidthOrHeight(Dimension aDimension,
                                      int32_t& aResult)
 {
   SVGSVGElement* rootElem = GetRootSVGElem();
   NS_ABORT_IF_FALSE(rootElem, "root elem missing or of wrong type");
 
   // Get the width or height SVG object
-  nsRefPtr<SVGAnimatedLength> domAnimLength;
-  if (aDimension == eWidth) {
-    domAnimLength = rootElem->Width();
-  } else {
-    NS_ABORT_IF_FALSE(aDimension == eHeight, "invalid dimension");
-    domAnimLength = rootElem->Height();
-  }
-  NS_ENSURE_TRUE(domAnimLength, false);
+  float length = (aDimension == eWidth) ? rootElem->GetIntrinsicWidth()
+                                        : rootElem->GetIntrinsicHeight();
 
-  // Get the animated value from the object
-  nsRefPtr<DOMSVGLength> domLength = domAnimLength->AnimVal();
-  NS_ENSURE_TRUE(domLength, false);
-
-  // Check if it's a percent value (and fail if so)
-  uint16_t unitType;
-  nsresult rv = domLength->GetUnitType(&unitType);
-  NS_ENSURE_SUCCESS(rv, false);
-  if (unitType == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) {
-    return false;
+  if (!IsFinite(length)) {
+    return false; // Percentage size
   }
 
-  // Non-percent value - woot! Grab it & return it.
-  float floatLength;
-  rv = domLength->GetValue(&floatLength);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  aResult = nsSVGUtils::ClampToInt(floatLength);
-
+  aResult = nsSVGUtils::ClampToInt(length);
   return true;
 }
 
 nsIFrame*
 SVGDocumentWrapper::GetRootLayoutFrame()
 {
   Element* rootElem = GetRootSVGElem();
   return rootElem ? rootElem->GetPrimaryFrame() : nullptr;