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
☠☠ backed out by 6f03a11386fb ☠ ☠
authorJonathan Watt <jwatt@jwatt.org>
Tue, 09 Dec 2014 22:32:10 +0000
changeset 220064 6d81c1303dafce97229e6eacca553f8efe0421ab
parent 220063 7cc47794c45d0f334322706bb3138a76c5aa97b8
child 220065 91928ad7ef735af8898d6e00e658cbea62b21a9e
push id53003
push userjwatt@jwatt.org
push dateWed, 17 Dec 2014 10:30:57 +0000
treeherdermozilla-inbound@83d940ea1491 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1086284
milestone37.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,34 @@ SVGSVGElement::GetTransformProperty() co
 }
 
 bool
 SVGSVGElement::ClearTransformProperty()
 {
   return UnsetProperty(nsGkAtoms::transform);
 }
 
+float
+SVGSVGElement::GetIntrinsicWidth() const
+{
+  if (mLengthAttributes[ATTR_WIDTH].IsPercentage()) {
+    return UnspecifiedNaN<float>();
+  }
+  // Context is only needed for percentage resolution. We already know we
+  // don't have a percentage, so no context is needed; hence, nullptr.
+  SVGSVGElement* context = nullptr;
+  return std::max(mLengthAttributes[ATTR_WIDTH].GetAnimValue(context), 0.f);
+}
+
+float
+SVGSVGElement::GetIntrinsicHeight() const
+{
+  if (mLengthAttributes[ATTR_HEIGHT].IsPercentage()) {
+    return UnspecifiedNaN<float>();
+  }
+  // Context is only needed for percentage resolution. We already know we
+  // don't have a percentage, so no context is needed; hence, nullptr.
+  SVGSVGElement* context = nullptr;
+  return std::max(mLengthAttributes[ATTR_HEIGHT].GetAnimValue(context), 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() const;
+  float GetIntrinsicHeight() const;
+
+  /**
    * 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;