Bug 759124 - Implement useCurrentView. r=dholbert
authorRobert Longson <longsonr@gmail.com>
Thu, 31 May 2012 11:39:12 +0100
changeset 97664 f9b479f908489c51a73c4b69ca8cec1606f752c2
parent 97663 ff2ad97929e82809280f5c1423199b5c0cea2448
child 97665 fa3fe2aff1f56fa0320c4bc1dae935833b4af5b5
push idunknown
push userunknown
push dateunknown
reviewersdholbert
bugs759124
milestone15.0a1
Bug 759124 - Implement useCurrentView. r=dholbert
content/svg/content/src/SVGFragmentIdentifier.cpp
content/svg/content/src/nsSVGSVGElement.cpp
content/svg/content/src/nsSVGSVGElement.h
content/svg/content/test/Makefile.in
content/svg/content/test/fragments-helper.svg
content/svg/content/test/test_fragments.html
dom/interfaces/svg/nsIDOMSVGSVGElement.idl
--- a/content/svg/content/src/SVGFragmentIdentifier.cpp
+++ b/content/svg/content/src/SVGFragmentIdentifier.cpp
@@ -65,28 +65,28 @@ SVGFragmentIdentifier::RestoreOldViewBox
     root->mViewBox.SetBaseValue(*oldViewBoxPtr, root);
     root->ClearViewBoxProperty();
   }
 }
 
 void 
 SVGFragmentIdentifier::SaveOldZoomAndPan(nsSVGSVGElement *root)
 {
-  const PRUint16 *oldZoomAndPanPtr = root->GetZoomAndPanProperty();
-  if (!oldZoomAndPanPtr) {
+  PRUint16 oldZoomAndPan = root->GetZoomAndPanProperty();
+  if (oldZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_UNKNOWN) {
     root->SetZoomAndPanProperty(root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].GetBaseValue());
   }
 }
 
 void 
 SVGFragmentIdentifier::RestoreOldZoomAndPan(nsSVGSVGElement *root)
 {
-  const PRUint16 *oldZoomAndPanPtr = root->GetZoomAndPanProperty();
-  if (oldZoomAndPanPtr) {
-    root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(*oldZoomAndPanPtr, root);
+  PRUint16 oldZoomAndPan = root->GetZoomAndPanProperty();
+  if (oldZoomAndPan != nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_UNKNOWN) {
+    root->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(oldZoomAndPan, root);
     root->ClearZoomAndPanProperty();
   }
 }
 
 bool
 SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
                                           nsSVGSVGElement *root)
 {
@@ -103,17 +103,20 @@ SVGFragmentIdentifier::ProcessSVGViewSpe
   const nsAString *preserveAspectRatioParams = nsnull;
   const nsAString *zoomAndPanParams = nsnull;
 
   // Each token is a SVGViewAttribute
   PRInt32 bracketPos = aViewSpec.FindChar('(');
   CharTokenizer<';'>tokenizer(
     Substring(aViewSpec, bracketPos + 1, aViewSpec.Length() - bracketPos - 2));
 
-  while (tokenizer.hasMoreTokens()) {
+  if (!tokenizer.hasMoreTokens()) {
+    return false;
+  }
+  do {
 
     nsAutoString token(tokenizer.nextToken());
 
     bracketPos = token.FindChar('(');
     if (bracketPos < 1 || token.Last() != ')') {
       // invalid SVGViewAttribute syntax
       return false;
     }
@@ -135,17 +138,17 @@ SVGFragmentIdentifier::ProcessSVGViewSpe
       if (zoomAndPanParams) {
         return false;
       }
       zoomAndPanParams = &params;
     } else {
       // We don't support transform or viewTarget currently
       return false;
     }
-  }
+  } while (tokenizer.hasMoreTokens());
 
   if (viewBoxParams) {
     SaveOldViewBox(root);
     root->mViewBox.SetBaseValueString(*viewBoxParams, root);
   } else {
     RestoreOldViewBox(root);
   }
 
@@ -203,19 +206,21 @@ SVGFragmentIdentifier::ProcessFragmentId
     }
     if (viewElement->mEnumAttributes[nsSVGViewElement::ZOOMANDPAN].IsExplicitlySet()) {
       SaveOldZoomAndPan(rootElement);
       rootElement->mEnumAttributes[nsSVGSVGElement::ZOOMANDPAN].SetBaseValue(
         viewElement->mEnumAttributes[nsSVGViewElement::ZOOMANDPAN].GetBaseValue(), rootElement);
     } else {
       RestoreOldZoomAndPan(rootElement);
     }
+    rootElement->mUseCurrentView = true;
     return true;
   }
 
-  if (ProcessSVGViewSpec(aAnchorName, rootElement)) {
+  rootElement->mUseCurrentView = ProcessSVGViewSpec(aAnchorName, rootElement);
+  if (rootElement->mUseCurrentView) {
     return true;
   }
   RestoreOldViewBox(rootElement);
   RestoreOldPreserveAspectRatio(rootElement);
   RestoreOldZoomAndPan(rootElement);
   return false;
 }
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -1,13 +1,14 @@
 /* -*- 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 "mozilla/StandardInteger.h"
 #include "mozilla/Util.h"
 
 #include "nsGkAtoms.h"
 #include "nsLayoutUtils.h"
 #include "DOMSVGNumber.h"
 #include "DOMSVGLength.h"
 #include "nsSVGAngle.h"
 #include "nsCOMPtr.h"
@@ -166,17 +167,18 @@ nsSVGSVGElement::nsSVGSVGElement(already
     mViewportHeight(0),
     mCurrentTranslate(0.0f, 0.0f),
     mCurrentScale(1.0f),
     mPreviousTranslate(0.0f, 0.0f),
     mPreviousScale(1.0f),
     mStartAnimationOnBindToTree(!aFromParser),
     mImageNeedsTransformInvalidation(false),
     mIsPaintingSVGImageElement(false),
-    mHasChildrenOnlyTransform(false)
+    mHasChildrenOnlyTransform(false),
+    mUseCurrentView(false)
 {
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 // From NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGSVGElement)
 nsresult
@@ -293,24 +295,18 @@ nsSVGSVGElement::GetScreenPixelToMillime
 {
   return GetScreenPixelToMillimeterX(aScreenPixelToMillimeterY);
 }
 
 /* attribute boolean useCurrentView; */
 NS_IMETHODIMP
 nsSVGSVGElement::GetUseCurrentView(bool *aUseCurrentView)
 {
-  NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetUseCurrentView");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-NS_IMETHODIMP
-nsSVGSVGElement::SetUseCurrentView(bool aUseCurrentView)
-{
-  NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetUseCurrentView");
-  return NS_ERROR_NOT_IMPLEMENTED;
+  *aUseCurrentView = mUseCurrentView;
+  return NS_OK;
 }
 
 /* readonly attribute nsIDOMSVGViewSpec currentView; */
 NS_IMETHODIMP
 nsSVGSVGElement::GetCurrentView(nsIDOMSVGViewSpec * *aCurrentView)
 {
   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetCurrentView");
   return NS_ERROR_NOT_IMPLEMENTED;
@@ -1426,24 +1422,24 @@ nsSVGSVGElement::SetZoomAndPanProperty(P
 {
   nsresult rv = SetProperty(nsGkAtoms::zoomAndPan, reinterpret_cast<void*>(aValue));
   NS_ABORT_IF_FALSE(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
                     "Setting override value when it's already set...?"); 
 
   return NS_SUCCEEDED(rv);
 }
 
-const PRUint16*
+PRUint16
 nsSVGSVGElement::GetZoomAndPanProperty() const
 {
   void* valPtr = GetProperty(nsGkAtoms::zoomAndPan);
   if (valPtr) {
-    return reinterpret_cast<PRUint16*>(valPtr);
+    return reinterpret_cast<uintptr_t>(valPtr);
   }
-  return nsnull;
+  return nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_UNKNOWN;
 }
 
 bool
 nsSVGSVGElement::ClearZoomAndPanProperty()
 {
-  return UnsetProperty(nsGkAtoms::viewBox);
+  return UnsetProperty(nsGkAtoms::zoomAndPan);
 }
 
--- a/content/svg/content/src/nsSVGSVGElement.h
+++ b/content/svg/content/src/nsSVGSVGElement.h
@@ -263,17 +263,17 @@ private:
   // Set/Clear properties to hold old or override versions of attributes
   bool SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR);
   const SVGPreserveAspectRatio* GetPreserveAspectRatioProperty() const;
   bool ClearPreserveAspectRatioProperty();
   bool SetViewBoxProperty(const nsSVGViewBoxRect& aViewBox);
   const nsSVGViewBoxRect* GetViewBoxProperty() const;
   bool ClearViewBoxProperty();
   bool SetZoomAndPanProperty(PRUint16 aValue);
-  const PRUint16* GetZoomAndPanProperty() const;
+  PRUint16 GetZoomAndPanProperty() const;
   bool ClearZoomAndPanProperty();
 
   bool IsRoot() const {
     NS_ASSERTION((IsInDoc() && !GetParent()) ==
                  (OwnerDoc() && (OwnerDoc()->GetRootElement() == this)),
                  "Can't determine if we're root");
     return IsInDoc() && !GetParent();
   }
@@ -358,21 +358,21 @@ private:
 
   // zoom and pan
   // IMPORTANT: see the comment in RecordCurrentScaleTranslate before writing
   // code to change any of these!
   nsSVGTranslatePoint               mCurrentTranslate;
   float                             mCurrentScale;
   nsSVGTranslatePoint               mPreviousTranslate;
   float                             mPreviousScale;
-  PRInt32                           mRedrawSuspendCount;
 
   // For outermost <svg> elements created from parsing, animation is started by
   // the onload event in accordance with the SVG spec, but for <svg> elements
   // created by script or promoted from inner <svg> to outermost <svg> we need
   // to manually kick off animation when they are bound to the tree.
   bool                              mStartAnimationOnBindToTree;
   bool                              mImageNeedsTransformInvalidation;
   bool                              mIsPaintingSVGImageElement;
   bool                              mHasChildrenOnlyTransform;
+  bool                              mUseCurrentView;
 };
 
 #endif
--- a/content/svg/content/test/Makefile.in
+++ b/content/svg/content/test/Makefile.in
@@ -31,16 +31,18 @@ include $(topsrcdir)/config/rules.mk
 		test_bbox.xhtml \
 		test_bbox-with-invalid-viewBox.xhtml \
 		test_bounds.html \
 		bbox-helper.svg \
 		bounds-helper.svg \
 		test_dataTypes.html \
 		test_dataTypesModEvents.html \
 		dataTypes-helper.svg \
+		test_fragments.html \
+		fragments-helper.svg \
 		getCTM-helper.svg \
 		test_getCTM.html \
 		test_getElementById.xhtml \
 		test_getSubStringLength.xhtml \
 		getSubStringLength-helper.svg \
 		test_isSupported.xhtml \
 		test_lang.xhtml \
 		test_nonAnimStrings.xhtml \
new file mode 100644
--- /dev/null
+++ b/content/svg/content/test/fragments-helper.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg">
+  <view id="view" viewBox="0 200 100 100" preserveAspectRatio="none"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/content/svg/content/test/test_fragments.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=759124
+-->
+<head>
+  <title>Test for Bug 759124</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=759124">Mozilla Bug 759124</a>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+
+<iframe id="svg" src="fragments-helper.svg"></iframe>
+
+<pre id="test">
+<script class="testbody" type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+function Test(svgFragmentIdentifier, valid) {
+    this.svgFragmentIdentifier = svgFragmentIdentifier;
+    this.valid = valid;
+}
+
+function runTests()
+{
+  var svg = $("svg");
+  var doc = svg.contentWindow.document;
+  
+  var tests = [
+      new Test("view", true),
+      new Test("unknown", false),
+      new Test("svgView(viewBox(0,0,200,200)))", true),
+      new Test("svgView(preserveAspectRatio(xMaxYMin slice))", true),
+      new Test("svgView(viewBox(1,2,3,4);preserveAspectRatio(xMaxYMin))", true),
+      new Test("svgView(zoomAndPan(disable))", true),
+      new Test("svgView", false),
+      new Test("svgView(", false),
+      new Test("svgView()", false)
+  ];
+
+ var src = svg.getAttribute("src");
+ for (var i = 0; i < tests.length; i++) {
+   var test = tests[i];
+   svg.setAttribute("src", src + "#" + test.svgFragmentIdentifier);
+   is(doc.rootElement.useCurrentView, test.valid,
+      "Expected " + test.svgFragmentIdentifier + " to be " +
+      (test.valid ? "valid" : "invalid"));
+ }
+
+  SimpleTest.finish();
+}
+
+window.addEventListener("load", runTests, false);
+</script>
+</pre>
+</body>
+</html>
--- a/dom/interfaces/svg/nsIDOMSVGSVGElement.idl
+++ b/dom/interfaces/svg/nsIDOMSVGSVGElement.idl
@@ -17,17 +17,17 @@ interface nsIDOMSVGTransform;
 
 // undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
 %{C++
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
 %}
 
-[scriptable, uuid(EF862DDA-DE4E-4F1C-9A70-4D3BEBDE5E6E)]
+[scriptable, uuid(BEC06C4F-3EF7-486E-A8F5-F375EE5CB5A8)]
 interface nsIDOMSVGSVGElement
   : nsIDOMSVGElement
 /*
         The SVG DOM makes use of multiple interface inheritance.
         Since XPCOM only supports single interface inheritance,
         the best thing that we can do is to promise that whenever
         an object implements _this_ interface it will also
         implement the following interfaces. (We then have to QI to
@@ -51,18 +51,17 @@ interface nsIDOMSVGSVGElement
       // raises DOMException on setting
   attribute DOMString         contentStyleType;
       // raises DOMException on setting
   readonly attribute nsIDOMSVGRect     viewport;
   readonly attribute float pixelUnitToMillimeterX;
   readonly attribute float pixelUnitToMillimeterY;
   readonly attribute float screenPixelToMillimeterX;
   readonly attribute float screenPixelToMillimeterY;
-  attribute boolean useCurrentView;
-      // raises DOMException on setting
+  readonly attribute boolean useCurrentView;
   readonly attribute nsIDOMSVGViewSpec currentView;
   attribute float currentScale;
       // raises DOMException on setting
   readonly attribute nsIDOMSVGPoint currentTranslate;
 
   unsigned long suspendRedraw(in unsigned long max_wait_milliseconds);
   void          unsuspendRedraw(in unsigned long suspend_handle_id);
       // raises( DOMException );