Skip to content

Instantly share code, notes, and snippets.

@smellman
Created April 4, 2013 06:29
Show Gist options
  • Save smellman/5308299 to your computer and use it in GitHub Desktop.
Save smellman/5308299 to your computer and use it in GitHub Desktop.
svgmap diff
diff --git content/base/src/Makefile.in content/base/src/Makefile.in
index df6231c..2d076ca 100644
--- content/base/src/Makefile.in
+++ content/base/src/Makefile.in
@@ -193,6 +193,7 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/content/events/src \
-I$(topsrcdir)/content/html/content/src \
-I$(topsrcdir)/content/html/document/src \
+ -I$(topsrcdir)/content/svg/content/src \
-I$(topsrcdir)/content/xbl/src \
-I$(topsrcdir)/content/xml/content/src \
-I$(topsrcdir)/content/xml/document/src \
diff --git content/base/src/nsFrameLoader.cpp content/base/src/nsFrameLoader.cpp
index 087feb3..08929f3 100644
--- content/base/src/nsFrameLoader.cpp
+++ content/base/src/nsFrameLoader.cpp
@@ -44,6 +44,7 @@
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsSubDocumentFrame.h"
+#include "nsSVGIFrameFrame.h"
#include "nsError.h"
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
@@ -51,6 +52,7 @@
#include "nsISHistoryInternal.h"
#include "nsIDocShellHistory.h"
#include "nsIDOMHTMLDocument.h"
+#include "nsIDOMSVGDocument.h"
#include "nsIXULWindow.h"
#include "nsIEditor.h"
#include "nsIMozBrowserFrame.h"
@@ -87,6 +89,7 @@
#include "jsapi.h"
#include "mozilla/dom/HTMLIFrameElement.h"
+#include "mozilla/dom/SVGIFrameElement.h"
#include "nsSandboxFlags.h"
#include "mozilla/dom/StructuredCloneUtils.h"
@@ -468,6 +471,22 @@ nsFrameLoader::ReallyStartLoadingInternal()
}
}
+ SVGIFrameElement *svgiframe =
+ SVGIFrameElement::FromContent(mOwnerContent);
+
+ if (svgiframe) {
+ sandboxFlags = svgiframe->GetSandboxFlags();
+
+ uint32_t parentSandboxFlags = svgiframe->OwnerDoc()->GetSandboxFlags();
+
+ if (sandboxFlags || parentSandboxFlags) {
+ // The child can only add restrictions, not remove them.
+ sandboxFlags |= parentSandboxFlags;
+
+ mDocShell->SetSandboxFlags(sandboxFlags);
+ }
+ }
+
// If this is an <iframe> and it's sandboxed with respect to origin
// we will set it up with a null principal later in nsDocShell::DoURILoad.
// We do it there to correctly sandbox content that was loaded into
@@ -881,6 +900,126 @@ nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
return true;
}
+
+/*bool
+nsFrameLoader::ShowSVG(int32_t marginWidth, int32_t marginHeight,
+ int32_t scrollbarPrefX, int32_t scrollbarPrefY,
+ nsSVGIFrameFrame* frame)*/
+bool
+nsFrameLoader::ShowSVG(int32_t marginWidth, int32_t marginHeight,
+ nsSVGIFrameFrame* frame)
+{
+ if (mInShow) {
+ return false;
+ }
+ // Reset mInShow if we exit early.
+ AutoResetInShow resetInShow(this);
+ mInShow = true;
+
+ nsresult rv = MaybeCreateDocShell();
+ if (NS_FAILED(rv)) {
+ return false;
+ }
+
+ if (!mRemoteFrame) {
+ if (!mDocShell)
+ return false;
+
+ mDocShell->SetMarginWidth(marginWidth);
+ mDocShell->SetMarginHeight(marginHeight);
+ /*
+ nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell);
+ if (sc) {
+ sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
+ scrollbarPrefX);
+ sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
+ scrollbarPrefY);
+ }
+ */
+ /*
+ nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
+ if (presShell) {
+ // Ensure root scroll frame is reflowed in case scroll preferences or
+ // margins have changed
+ nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
+ if (rootScrollFrame) {
+ presShell->FrameNeedsReflow(rootScrollFrame, nsIPresShell::eResize,
+ NS_FRAME_IS_DIRTY);
+ }
+ return true;
+ }
+ */
+ }
+
+ nsIntSize size = frame->GetSubdocumentSize();
+ if (mRemoteFrame) {
+ return ShowRemoteFrame(size, frame);
+ }
+
+ nsView* view = frame->EnsureInnerView();
+ if (!view)
+ return false;
+
+ nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mDocShell);
+ NS_ASSERTION(baseWindow, "Found a nsIDocShell that isn't a nsIBaseWindow.");
+ baseWindow->InitWindow(nullptr, view->GetWidget(), 0, 0,
+ size.width, size.height);
+ // This is kinda whacky, this "Create()" call doesn't really
+ // create anything, one starts to wonder why this was named
+ // "Create"...
+ baseWindow->Create();
+ baseWindow->SetVisibility(true);
+
+ // Trigger editor re-initialization if midas is turned on in the
+ // sub-document. This shouldn't be necessary, but given the way our
+ // editor works, it is. See
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=284245
+ nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
+ if (presShell) {
+ nsCOMPtr<nsIDOMSVGDocument> doc =
+ do_QueryInterface(presShell->GetDocument());
+
+ if (doc) {
+ /*
+ nsAutoString designMode;
+ doc->GetDesignMode(designMode);
+
+ if (designMode.EqualsLiteral("on")) {
+ // Hold on to the editor object to let the document reattach to the
+ // same editor object, instead of creating a new one.
+ nsCOMPtr<nsIEditor> editor;
+ nsresult rv = mDocShell->GetEditor(getter_AddRefs(editor));
+ NS_ENSURE_SUCCESS(rv, false);
+
+ doc->SetDesignMode(NS_LITERAL_STRING("off"));
+ doc->SetDesignMode(NS_LITERAL_STRING("on"));
+ } else {
+ // Re-initialize the presentation for contenteditable documents
+ bool editable = false,
+ hasEditingSession = false;
+ mDocShell->GetEditable(&editable);
+ mDocShell->GetHasEditingSession(&hasEditingSession);
+ nsCOMPtr<nsIEditor> editor;
+ mDocShell->GetEditor(getter_AddRefs(editor));
+ if (editable && hasEditingSession && editor) {
+ editor->PostCreate();
+ }
+ }
+ */
+ }
+ }
+
+ mInShow = false;
+ if (mHideCalled) {
+ mHideCalled = false;
+ Hide();
+ return false;
+ }
+ return true;
+}
+
+
+
void
nsFrameLoader::MarginsChanged(uint32_t aMarginWidth,
uint32_t aMarginHeight)
@@ -1563,7 +1702,7 @@ nsFrameLoader::MaybeCreateDocShell()
nsAutoString frameName;
int32_t namespaceID = mOwnerContent->GetNameSpaceID();
- if (namespaceID == kNameSpaceID_XHTML && !mOwnerContent->IsInHTMLDocument()) {
+ if ((namespaceID == kNameSpaceID_XHTML || namespaceID == kNameSpaceID_SVG) && !mOwnerContent->IsInHTMLDocument()) {
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
} else {
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, frameName);
diff --git content/base/src/nsFrameLoader.h content/base/src/nsFrameLoader.h
index 17ebf09..c2e1cf5 100644
--- content/base/src/nsFrameLoader.h
+++ content/base/src/nsFrameLoader.h
@@ -26,6 +26,7 @@
class nsIURI;
class nsSubDocumentFrame;
+class nsSVGIFrameFrame;
class nsView;
class nsIInProcessContentFrameMessageManager;
class AutoResetInShow;
@@ -200,6 +201,10 @@ public:
int32_t scrollbarPrefX, int32_t scrollbarPrefY,
nsSubDocumentFrame* frame);
+ bool ShowSVG(int32_t marginWidth, int32_t marginHeight,
+ nsSVGIFrameFrame* frame);
+
+
/**
* Called when the margin properties of the containing frame are changed.
*/
diff --git content/base/src/nsGkAtomList.h content/base/src/nsGkAtomList.h
index 4b0e389..961f1ab 100644
--- content/base/src/nsGkAtomList.h
+++ content/base/src/nsGkAtomList.h
@@ -388,6 +388,7 @@ GK_ATOM(from, "from")
GK_ATOM(functionAvailable, "function-available")
GK_ATOM(generateId, "generate-id")
GK_ATOM(getter, "getter")
+GK_ATOM(globalCoordinateSystem, "globalCoordinateSystem")
GK_ATOM(glyphchar, "glyphchar")
GK_ATOM(glyphid, "glyphid")
GK_ATOM(grid, "grid")
@@ -995,6 +996,7 @@ GK_ATOM(splitmenu, "splitmenu")
GK_ATOM(splitter, "splitter")
GK_ATOM(spring, "spring")
GK_ATOM(src, "src")
+GK_ATOM(srcdoc, "srcdoc")
GK_ATOM(srclang, "srclang")
GK_ATOM(stack, "stack")
GK_ATOM(standalone, "standalone")
@@ -1833,6 +1835,7 @@ GK_ATOM(svgGenericContainerFrame, "SVGGenericContainerFrame")
GK_ATOM(svgGFrame, "SVGGFrame")
GK_ATOM(svgGlyphFrame, "SVGGlyphFrame")
GK_ATOM(svgGradientFrame, "SVGGradientFrame")
+GK_ATOM(svgIFrameFrame, "SVGIFrameFrame")
GK_ATOM(svgImageFrame, "SVGImageFrame")
GK_ATOM(svgInnerSVGFrame, "SVGInnerSVGFrame")
GK_ATOM(svgLinearGradientFrame, "SVGLinearGradientFrame")
diff --git content/base/src/nsTreeSanitizer.cpp content/base/src/nsTreeSanitizer.cpp
index 78f3af8..48703d9 100644
--- content/base/src/nsTreeSanitizer.cpp
+++ content/base/src/nsTreeSanitizer.cpp
@@ -353,6 +353,7 @@ nsIAtom** const kElementsSVG[] = {
&nsGkAtoms::glyph, // glyph
&nsGkAtoms::glyphRef, // glyphRef
&nsGkAtoms::hkern, // hkern
+ &nsGkAtoms::iframe, // iframe
&nsGkAtoms::image, // image
&nsGkAtoms::line, // line
&nsGkAtoms::linearGradient, // linearGradient
@@ -549,6 +550,7 @@ nsIAtom** const kAttributesSVG[] = {
&nsGkAtoms::specularConstant, // specularConstant
&nsGkAtoms::specularExponent, // specularExponent
&nsGkAtoms::spreadMethod, // spreadMethod
+ &nsGkAtoms::src, // src
&nsGkAtoms::startOffset, // startOffset
&nsGkAtoms::stdDeviation, // stdDeviation
// stemh
diff --git content/events/src/nsEventStateManager.cpp content/events/src/nsEventStateManager.cpp
index a243078..393fa3e 100644
--- content/events/src/nsEventStateManager.cpp
+++ content/events/src/nsEventStateManager.cpp
@@ -1568,6 +1568,11 @@ nsEventStateManager::IsRemoteTarget(nsIContent* target) {
return !!TabParent::GetFrom(target);
}
+ // <iframe> from SVG
+ if (browserFrame && (target->Tag() == nsGkAtoms::iframe) && target->IsSVG()) {
+ return !!TabParent::GetFrom(target);
+ }
+
return false;
}
diff --git content/svg/content/src/GenericSVGFrameElement.cpp content/svg/content/src/GenericSVGFrameElement.cpp
new file mode 100644
index 0000000..f1b15ec
--- /dev/null
+++ content/svg/content/src/GenericSVGFrameElement.cpp
@@ -0,0 +1,425 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=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 "nsSVGElement.h"
+#include "GenericSVGFrameElement.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsContentUtils.h"
+#include "mozilla/Preferences.h"
+#include "nsIAppsService.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIDOMApplicationRegistry.h"
+#include "nsIPermissionManager.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+/*
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GenericSVGFrameElement,
+ nsSVGElement)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_TABLE_HEAD(GenericSVGFrameElement)
+ NS_INTERFACE_TABLE_INHERITED3(GenericSVGFrameElement,
+ nsIFrameLoaderOwner,
+ nsIDOMMozBrowserFrame,
+ nsIMozBrowserFrame)
+ NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(GenericSVGFrameElement)
+NS_INTERFACE_MAP_END_INHERITING(nsSVGElement)
+
+NS_IMPL_BOOL_ATTR(GenericSVGFrameElement, Mozbrowser, mozbrowser)
+*/
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GenericSVGFrameElement,
+ nsSVGElement)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_ISUPPORTS_INHERITED1(GenericSVGFrameElement, GenericSVGFrameElementBase,
+ nsIFrameLoaderOwner)
+ // nsIDOMMozBrowserFrame,
+ //nsIMozBrowserFrame)
+//NS_IMPL_BOOL_ATTR(GenericSVGFrameElement, Mozbrowser, mozbrowser)
+
+
+//int32_t
+//GenericSVGFrameElement::TabIndexDefault()
+//{
+// return 0;
+//}
+
+GenericSVGFrameElement::~GenericSVGFrameElement()
+{
+ if (mFrameLoader) {
+ mFrameLoader->Destroy();
+ }
+}
+
+nsresult
+GenericSVGFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
+{
+ NS_PRECONDITION(aContentDocument, "Null out param");
+ nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(GetContentDocument());
+ document.forget(aContentDocument);
+ return NS_OK;
+}
+
+nsIDocument*
+GenericSVGFrameElement::GetContentDocument()
+{
+ nsCOMPtr<nsPIDOMWindow> win = GetContentWindow();
+ if (!win) {
+ return nullptr;
+ }
+
+ return win->GetDoc();
+}
+
+nsresult
+GenericSVGFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
+{
+ NS_PRECONDITION(aContentWindow, "Null out param");
+ nsCOMPtr<nsPIDOMWindow> window = GetContentWindow();
+ window.forget(aContentWindow);
+ return NS_OK;
+}
+
+already_AddRefed<nsPIDOMWindow>
+GenericSVGFrameElement::GetContentWindow()
+{
+ EnsureFrameLoader();
+
+ if (!mFrameLoader) {
+ return nullptr;
+ }
+
+ bool depthTooGreat = false;
+ mFrameLoader->GetDepthTooGreat(&depthTooGreat);
+ if (depthTooGreat) {
+ // Claim to have no contentWindow
+ return nullptr;
+ }
+
+ nsCOMPtr<nsIDocShell> doc_shell;
+ mFrameLoader->GetDocShell(getter_AddRefs(doc_shell));
+
+ nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(doc_shell);
+
+ if (!win) {
+ return nullptr;
+ }
+
+ NS_ASSERTION(win->IsOuterWindow(),
+ "Uh, this window should always be an outer window!");
+
+ return win.forget();
+}
+
+nsresult
+GenericSVGFrameElement::EnsureFrameLoader()
+{
+ if (!GetParent())
+ NS_WARNING("can't get Parent");
+ if (!IsInDoc())
+ NS_WARNING("is not doc");
+
+ // if (!GetParent() || !IsInDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) {
+ if (mFrameLoader || mFrameLoaderCreationDisallowed) {
+ // If frame loader is there, we just keep it around, cached
+ return NS_OK;
+ }
+
+ mFrameLoader = nsFrameLoader::Create(this, mNetworkCreated);
+ if (!mFrameLoader) {
+ // Strangely enough, this method doesn't actually ensure that the
+ // frameloader exists. It's more of a best-effort kind of thing.
+ return NS_OK;
+ }
+
+ return NS_OK;
+}
+/*
+nsresult
+GenericSVGFrameElement::CreateRemoteFrameLoader(nsITabParent* aTabParent)
+{
+ MOZ_ASSERT(!mFrameLoader);
+ EnsureFrameLoader();
+ NS_ENSURE_STATE(mFrameLoader);
+ mFrameLoader->SetRemoteBrowser(aTabParent);
+ return NS_OK;
+}
+*/
+NS_IMETHODIMP
+GenericSVGFrameElement::GetFrameLoader(nsIFrameLoader **aFrameLoader)
+{
+ NS_IF_ADDREF(*aFrameLoader = mFrameLoader);
+ return NS_OK;
+}
+
+NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
+GenericSVGFrameElement::GetFrameLoader()
+{
+ nsRefPtr<nsFrameLoader> loader = mFrameLoader;
+ return loader.forget();
+}
+
+NS_IMETHODIMP
+GenericSVGFrameElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
+{
+ // We don't support this yet
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+GenericSVGFrameElement::LoadSrc()
+{
+ nsresult rv = EnsureFrameLoader();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!mFrameLoader) {
+ return NS_OK;
+ }
+
+ rv = mFrameLoader->LoadFrame();
+#ifdef DEBUG
+ if (NS_FAILED(rv)) {
+ NS_WARNING("failed to load URL");
+ }
+#endif
+
+ return rv;
+}
+
+nsresult
+GenericSVGFrameElement::BindToTree(nsIDocument* aDocument,
+ nsIContent* aParent,
+ nsIContent* aBindingParent,
+ bool aCompileEventHandlers)
+{
+ nsresult rv = nsSVGElement::BindToTree(aDocument, aParent,
+ aBindingParent,
+ aCompileEventHandlers);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aDocument) {
+ NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
+ "Missing a script blocker!");
+ // We're in a document now. Kick off the frame load.
+ LoadSrc();
+ }
+
+ // We're now in document and scripts may move us, so clear
+ // the mNetworkCreated flag.
+ mNetworkCreated = false;
+ return rv;
+}
+
+void
+GenericSVGFrameElement::UnbindFromTree(bool aDeep, bool aNullParent)
+{
+ if (mFrameLoader) {
+ // This iframe is being taken out of the document, destroy the
+ // iframe's frame loader (doing that will tear down the window in
+ // this iframe).
+ // XXXbz we really want to only partially destroy the frame
+ // loader... we don't want to tear down the docshell. Food for
+ // later bug.
+ mFrameLoader->Destroy();
+ mFrameLoader = nullptr;
+ }
+
+ nsSVGElement::UnbindFromTree(aDeep, aNullParent);
+}
+
+nsresult
+GenericSVGFrameElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ nsIAtom* aPrefix, const nsAString& aValue,
+ bool aNotify)
+{
+ nsresult rv = nsSVGElement::SetAttr(aNameSpaceID, aName, aPrefix,
+ aValue, aNotify);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
+ // Don't propagate error here. The attribute was successfully set, that's
+ // what we should reflect.
+ LoadSrc();
+ }
+
+ return NS_OK;
+}
+
+void
+GenericSVGFrameElement::DestroyContent()
+{
+ if (mFrameLoader) {
+ mFrameLoader->Destroy();
+ mFrameLoader = nullptr;
+ }
+
+ nsSVGElement::DestroyContent();
+}
+
+nsresult
+GenericSVGFrameElement::CopyInnerTo(Element* aDest)
+{
+ nsresult rv = nsSVGElement::CopyInnerTo(aDest);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsIDocument* doc = aDest->OwnerDoc();
+ if (doc->IsStaticDocument() && mFrameLoader) {
+ GenericSVGFrameElement* dest =
+ static_cast<GenericSVGFrameElement*>(aDest);
+ nsFrameLoader* fl = nsFrameLoader::Create(dest, false);
+ NS_ENSURE_STATE(fl);
+ dest->mFrameLoader = fl;
+ static_cast<nsFrameLoader*>(mFrameLoader.get())->CreateStaticClone(fl);
+ }
+
+ return rv;
+}
+
+//bool
+//GenericSVGFrameElement::IsHTMLFocusable(bool aWithMouse,
+// bool *aIsFocusable,
+// int32_t *aTabIndex)
+//{
+// if (nsSVGElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
+// return true;
+// }
+//
+// *aIsFocusable = nsContentUtils::IsSubDocumentTabbable(this);
+//
+// if (!*aIsFocusable && aTabIndex) {
+// *aTabIndex = -1;
+// }
+//
+// return false;
+//}
+
+/**
+ * Return true if this frame element really is a mozbrowser or mozapp. (It
+ * needs to have the right attributes, and its creator must have the right
+ * permissions.)
+ */
+/* [infallible] */
+/*nsresult
+GenericSVGFrameElement::GetReallyIsBrowserOrApp(bool *aOut)
+{
+ *aOut = false;
+
+ // Fail if browser frames are globally disabled.
+ //if (!Preferences::GetBool("dom.mozBrowserFramesEnabled")) {
+ // return NS_OK;
+ //}
+
+ // // Fail if this frame doesn't have the mozbrowser attribute.
+ // bool hasMozbrowser = false;
+ // GetMozbrowser(&hasMozbrowser);
+ // if (!hasMozbrowser) {
+ // return NS_OK;
+ // }
+
+ // Fail if the node principal isn't trusted.
+ nsIPrincipal *principal = NodePrincipal();
+ nsCOMPtr<nsIPermissionManager> permMgr =
+ do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+ NS_ENSURE_TRUE(permMgr, NS_OK);
+
+ uint32_t permission = nsIPermissionManager::DENY_ACTION;
+ nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission);
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+ *aOut = permission == nsIPermissionManager::ALLOW_ACTION;
+ return NS_OK;
+}
+*/
+/* [infallible] */
+/* NS_IMETHODIMP
+GenericSVGFrameElement::GetReallyIsApp(bool *aOut)
+{
+ nsAutoString manifestURL;
+ GetAppManifestURL(manifestURL);
+
+ *aOut = !manifestURL.IsEmpty();
+ return NS_OK;
+ }*/
+
+/* [infallible] */
+/*NS_IMETHODIMP
+GenericSVGFrameElement::GetIsExpectingSystemMessage(bool *aOut)
+{
+ *aOut = false;
+
+ if (!nsIMozBrowserFrame::GetReallyIsApp()) {
+ return NS_OK;
+ }
+
+ *aOut = HasAttr(kNameSpaceID_None, nsGkAtoms::expectingSystemMessage);
+ return NS_OK;
+ }*/
+
+/*
+NS_IMETHODIMP
+GenericSVGFrameElement::GetAppManifestURL(nsAString& aOut)
+{
+ aOut.Truncate();
+
+ // At the moment, you can't be an app without being a browser.
+ if (!nsIMozBrowserFrame::GetReallyIsBrowserOrApp()) {
+ return NS_OK;
+ }
+
+ // Check permission.
+ nsIPrincipal *principal = NodePrincipal();
+ nsCOMPtr<nsIPermissionManager> permMgr =
+ do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+ NS_ENSURE_TRUE(permMgr, NS_OK);
+
+ uint32_t permission = nsIPermissionManager::DENY_ACTION;
+ nsresult rv = permMgr->TestPermissionFromPrincipal(principal,
+ "embed-apps",
+ &permission);
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+ if (permission != nsIPermissionManager::ALLOW_ACTION) {
+ return NS_OK;
+ }
+
+ nsAutoString manifestURL;
+ GetAttr(kNameSpaceID_None, nsGkAtoms::mozapp, manifestURL);
+ if (manifestURL.IsEmpty()) {
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
+ NS_ENSURE_TRUE(appsService, NS_OK);
+
+ nsCOMPtr<mozIDOMApplication> app;
+ appsService->GetAppByManifestURL(manifestURL, getter_AddRefs(app));
+ if (app) {
+ aOut.Assign(manifestURL);
+ }
+
+ return NS_OK;
+ }*/
+/*
+NS_IMETHODIMP
+GenericSVGFrameElement::DisallowCreateFrameLoader()
+{
+ MOZ_ASSERT(!mFrameLoader);
+ MOZ_ASSERT(!mFrameLoaderCreationDisallowed);
+ mFrameLoaderCreationDisallowed = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+GenericSVGFrameElement::AllowCreateFrameLoader()
+{
+ MOZ_ASSERT(!mFrameLoader);
+ MOZ_ASSERT(mFrameLoaderCreationDisallowed);
+ mFrameLoaderCreationDisallowed = false;
+ return NS_OK;
+}
+*/
diff --git content/svg/content/src/GenericSVGFrameElement.h content/svg/content/src/GenericSVGFrameElement.h
new file mode 100644
index 0000000..2ae21e4
--- /dev/null
+++ content/svg/content/src/GenericSVGFrameElement.h
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=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 "nsMappedAttributeElement.h"
+#include "nsSVGElement.h"
+#include "nsIFrameLoader.h"
+//#include "nsIMozBrowserFrame.h"
+#include "nsIDOMEventListener.h"
+
+#include "nsFrameLoader.h"
+
+#include "mozilla/dom/SVGGraphicsElement.h"
+#include "mozilla/dom/FromParser.h"
+
+typedef mozilla::dom::SVGGraphicsElement GenericSVGFrameElementBase;
+
+/**
+ * A helper class for frame elements
+ */
+class GenericSVGFrameElement : public GenericSVGFrameElementBase,
+ public nsIFrameLoaderOwner
+ // public nsIMozBrowserFrame
+{
+public:
+ GenericSVGFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+ mozilla::dom::FromParser aFromParser)
+ : GenericSVGFrameElementBase(aNodeInfo)
+ , mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
+ , mBrowserFrameListenersRegistered(false)
+ , mFrameLoaderCreationDisallowed(false)
+ {
+ }
+
+ virtual ~GenericSVGFrameElement();
+
+ NS_DECL_ISUPPORTS_INHERITED
+ // NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
+ NS_DECL_NSIFRAMELOADEROWNER
+ //NS_DECL_NSIDOMMOZBROWSERFRAME
+ //NS_DECL_NSIMOZBROWSERFRAME
+
+ // nsIContent
+ //virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex);
+ virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+ nsIContent* aBindingParent,
+ bool aCompileEventHandlers);
+ virtual void UnbindFromTree(bool aDeep = true,
+ bool aNullParent = true);
+ nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ const nsAString& aValue, bool aNotify)
+ {
+ return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
+ }
+ virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ nsIAtom* aPrefix, const nsAString& aValue,
+ bool aNotify);
+ virtual void DestroyContent();
+
+ nsresult CopyInnerTo(mozilla::dom::Element* aDest);
+
+ //virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
+
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(GenericSVGFrameElement,
+ nsSVGElement)
+
+protected:
+ /**
+ * Listens to titlechanged events from the document inside the iframe and
+ * forwards them along to the iframe so it can fire a mozbrowsertitlechange
+ * event if appropriate.
+ */
+ class TitleChangedListener MOZ_FINAL : public nsIDOMEventListener
+ {
+ public:
+ TitleChangedListener(GenericSVGFrameElement *aElement,
+ nsIDOMEventTarget *aChromeHandler);
+
+ /* Unregister this listener. */
+ void Unregister();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDOMEVENTLISTENER
+
+ private:
+ nsWeakPtr mElement; /* nsGenericHTMLFrameElement */
+ nsWeakPtr mChromeHandler; /* nsIDOMEventTarget */
+ };
+
+ // This doesn't really ensure a frame loade in all cases, only when
+ // it makes sense.
+ nsresult EnsureFrameLoader();
+ nsresult LoadSrc();
+ nsIDocument* GetContentDocument();
+ nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
+ already_AddRefed<nsPIDOMWindow> GetContentWindow();
+ nsresult GetContentWindow(nsIDOMWindow** aContentWindow);
+
+ nsRefPtr<nsFrameLoader> mFrameLoader;
+
+ // True when the element is created by the parser
+ // using NS_FROM_PARSER_NETWORK flag.
+ // If the element is modified, it may lose the flag.
+ bool mNetworkCreated;
+
+ bool mBrowserFrameListenersRegistered;
+ bool mFrameLoaderCreationDisallowed;
+};
diff --git content/svg/content/src/Makefile.in content/svg/content/src/Makefile.in
index 27cabb9..b77d2a4 100644
--- content/svg/content/src/Makefile.in
+++ content/svg/content/src/Makefile.in
@@ -32,6 +32,7 @@ CPPSRCS = \
DOMSVGStringList.cpp \
DOMSVGTransform.cpp \
DOMSVGTransformList.cpp \
+ GenericSVGFrameElement.cpp \
nsDOMSVGZoomEvent.cpp \
nsDOMSVGEvent.cpp \
nsISVGPoint.cpp \
@@ -83,8 +84,10 @@ CPPSRCS = \
SVGForeignObjectElement.cpp \
SVGFragmentIdentifier.cpp \
SVGGElement.cpp \
+ SVGGlobalCoordinateSystemElement.cpp \
SVGGradientElement.cpp \
SVGGraphicsElement.cpp \
+ SVGIFrameElement.cpp \
SVGImageElement.cpp \
SVGIntegerPairSMILType.cpp \
SVGLength.cpp \
@@ -146,6 +149,7 @@ include $(topsrcdir)/config/config.mk
FORCE_STATIC_LIB = 1
EXPORTS = \
+ GenericSVGFrameElement.h \
nsSVGFeatures.h \
nsSVGRect.h \
SVGAttrValueWrapper.h \
@@ -173,8 +177,10 @@ EXPORTS_mozilla/dom = \
SVGFilterElement.h \
SVGForeignObjectElement.h \
SVGGElement.h \
+ SVGGlobalCoordinateSystemElement.h \
SVGGradientElement.h \
SVGGraphicsElement.h \
+ SVGIFrameElement.h \
SVGImageElement.h \
SVGLineElement.h \
SVGMarkerElement.h \
diff --git content/svg/content/src/SVGContentUtils.cpp content/svg/content/src/SVGContentUtils.cpp
index d94eddf..d1553f6 100644
--- content/svg/content/src/SVGContentUtils.cpp
+++ content/svg/content/src/SVGContentUtils.cpp
@@ -30,7 +30,7 @@ SVGContentUtils::GetOuterSVGElement(nsSVGElement *aSVGElement)
nsIContent *ancestor = aSVGElement->GetFlattenedTreeParent();
while (ancestor && ancestor->IsSVG() &&
- ancestor->Tag() != nsGkAtoms::foreignObject) {
+ (ancestor->Tag() != nsGkAtoms::foreignObject || ancestor->Tag() != nsGkAtoms::iframe)) {
element = ancestor;
ancestor = element->GetFlattenedTreeParent();
}
@@ -157,7 +157,8 @@ SVGContentUtils::EstablishesViewport(nsIContent *aContent)
return aContent && aContent->IsSVG() &&
(aContent->Tag() == nsGkAtoms::svg ||
aContent->Tag() == nsGkAtoms::foreignObject ||
- aContent->Tag() == nsGkAtoms::symbol);
+ aContent->Tag() == nsGkAtoms::symbol ||
+ aContent->Tag() == nsGkAtoms::iframe);
}
nsSVGElement*
@@ -167,7 +168,7 @@ SVGContentUtils::GetNearestViewportElement(nsIContent *aContent)
while (element && element->IsSVG()) {
if (EstablishesViewport(element)) {
- if (element->Tag() == nsGkAtoms::foreignObject) {
+ if ((element->Tag() == nsGkAtoms::foreignObject || element->Tag() == nsGkAtoms::iframe)) {
return nullptr;
}
return static_cast<nsSVGElement*>(element);
@@ -186,7 +187,7 @@ GetCTMInternal(nsSVGElement *aElement, bool aScreenCTM, bool aHaveRecursed)
nsIContent *ancestor = aElement->GetFlattenedTreeParent();
while (ancestor && ancestor->IsSVG() &&
- ancestor->Tag() != nsGkAtoms::foreignObject) {
+ (ancestor->Tag() != nsGkAtoms::foreignObject || ancestor->Tag() != nsGkAtoms::iframe)) {
element = static_cast<nsSVGElement*>(ancestor);
matrix *= element->PrependLocalTransformsTo(gfxMatrix()); // i.e. *A*ppend
if (!aScreenCTM && SVGContentUtils::EstablishesViewport(element)) {
diff --git content/svg/content/src/SVGGlobalCoordinateSystemElement.cpp content/svg/content/src/SVGGlobalCoordinateSystemElement.cpp
new file mode 100644
index 0000000..68e9460
--- /dev/null
+++ content/svg/content/src/SVGGlobalCoordinateSystemElement.cpp
@@ -0,0 +1,109 @@
+/* -*- 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/dom/SVGGlobalCoordinateSystemElement.h"
+
+#include "DOMSVGAnimatedTransformList.h"
+#include "mozilla/dom/SVGGlobalCoordinateSystemElementBinding.h"
+#include "mozilla/Util.h"
+#include "nsCOMPtr.h"
+#include "nsGkAtoms.h"
+#include "nsIURI.h"
+#include "nsIDOMSVGURIReference.h"
+#include "nsSVGElement.h"
+
+NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(GlobalCoordinateSystem)
+
+namespace mozilla {
+namespace dom {
+
+//--------------- GlobalCoordinateSystem ------------------
+
+JSObject*
+SVGGlobalCoordinateSystemElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
+{
+ return SVGGlobalCoordinateSystemElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+nsSVGElement::StringInfo SVGGlobalCoordinateSystemElement::sStringInfo[1] =
+{
+ { &nsGkAtoms::href, kNameSpaceID_XLink, true }
+};
+
+//----------------------------------------------------------------------
+// nsISupports methods
+
+NS_IMPL_ISUPPORTS_INHERITED4(SVGGlobalCoordinateSystemElement, SVGGlobalCoordinateSystemElementBase,
+ nsIDOMNode, nsIDOMElement,
+ nsIDOMSVGElement,
+ nsIDOMSVGURIReference)
+
+//----------------------------------------------------------------------
+// Implementation
+
+SVGGlobalCoordinateSystemElement::SVGGlobalCoordinateSystemElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+ : SVGGlobalCoordinateSystemElementBase(aNodeInfo)
+{
+ SetIsDOMBinding();
+}
+
+//----------------------------------------------------------------------
+// nsIDOMNode methods
+
+NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGGlobalCoordinateSystemElement)
+
+//----------------------------------------------------------------------
+// nsSVGElement methods
+
+nsSVGElement::StringAttributesInfo
+SVGGlobalCoordinateSystemElement::GetStringInfo()
+{
+ return StringAttributesInfo(mStringAttributes, sStringInfo,
+ ArrayLength(sStringInfo));
+}
+
+SVGAnimatedTransformList*
+SVGGlobalCoordinateSystemElement::GetAnimatedTransformList(uint32_t aFlags)
+{
+ if (!mTransform && (aFlags & DO_ALLOCATE)) {
+ mTransform = new SVGAnimatedTransformList();
+ }
+ return mTransform;
+}
+
+//----------------------------------------------------------------------
+
+/* readonly attribute SVGAnimatedTransformList transform; */
+already_AddRefed<DOMSVGAnimatedTransformList>
+SVGGlobalCoordinateSystemElement::Transform()
+{
+ // We're creating a DOM wrapper, so we must tell GetAnimatedTransformList
+ // to allocate the SVGAnimatedTransformList if it hasn't already done so:
+ return DOMSVGAnimatedTransformList::GetDOMWrapper(
+ GetAnimatedTransformList(DO_ALLOCATE), this);
+}
+
+//----------------------------------------------------------------------
+// nsIDOMSVGURIReference methods:
+
+/* readonly attribute nsIDOMSVGAnimatedString href; */
+already_AddRefed<nsIDOMSVGAnimatedString>
+SVGGlobalCoordinateSystemElement::Href()
+{
+ nsCOMPtr<nsIDOMSVGAnimatedString> href;
+ mStringAttributes[HREF].ToDOMAnimatedString(getter_AddRefs(href), this);
+ return href.forget();
+}
+
+NS_IMETHODIMP
+SVGGlobalCoordinateSystemElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
+{
+ *aHref = Href().get();
+ return NS_OK;
+}
+
+} // namespace dom
+} // namespace mozilla
+
diff --git content/svg/content/src/SVGGlobalCoordinateSystemElement.h content/svg/content/src/SVGGlobalCoordinateSystemElement.h
new file mode 100644
index 0000000..e273a08
--- /dev/null
+++ content/svg/content/src/SVGGlobalCoordinateSystemElement.h
@@ -0,0 +1,79 @@
+/* -*- 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/. */
+
+#ifndef mozilla_dom_SVGGlobalCoordinateSystemElement_h
+#define mozilla_dom_SVGGlobalCoordinateSystemElement_h
+
+#include "nsIDOMSVGURIReference.h"
+#include "nsSVGElement.h"
+#include "nsSVGString.h"
+#include "SVGAnimatedTransformList.h"
+
+nsresult
+NS_NewSVGGlobalCoordinateSystemElement(nsIContent **aResult,
+ already_AddRefed<nsINodeInfo> aNodeInfo);
+
+namespace mozilla {
+
+class DOMSVGAnimatedTransformList;
+
+namespace dom {
+
+typedef nsSVGElement SVGGlobalCoordinateSystemElementBase;
+
+class SVGGlobalCoordinateSystemElement : public SVGGlobalCoordinateSystemElementBase,
+ public nsIDOMSVGElement,
+ public nsIDOMSVGURIReference
+{
+protected:
+ SVGGlobalCoordinateSystemElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+ virtual JSObject*
+ WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap) MOZ_OVERRIDE;
+ friend nsresult
+ (::NS_NewSVGGlobalCoordinateSystemElement(nsIContent **aResult,
+ already_AddRefed<nsINodeInfo> aNodeInfo));
+
+public:
+ // interfaces:
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // URI Reference
+ NS_DECL_NSIDOMSVGURIREFERENCE
+
+ // The GlobalCoordinateSystem Element base class implements these
+ NS_FORWARD_NSIDOMSVGELEMENT(SVGGlobalCoordinateSystemElementBase::)
+
+ NS_FORWARD_NSIDOMNODE_TO_NSINODE
+ NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
+
+ virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+ virtual nsIDOMNode* AsDOMNode() { return this; }
+
+ virtual SVGAnimatedTransformList*
+ GetAnimatedTransformList(uint32_t aFlags = 0);
+ virtual nsIAtom* GetTransformListAttrName() const {
+ return nsGkAtoms::transform;
+ }
+
+ // WebIDL
+ already_AddRefed<DOMSVGAnimatedTransformList> Transform();
+ already_AddRefed<nsIDOMSVGAnimatedString> Href();
+
+protected:
+ virtual StringAttributesInfo GetStringInfo();
+
+ enum { HREF };
+ nsSVGString mStringAttributes[1];
+ static StringInfo sStringInfo[1];
+
+ // SVGGlobalCoordinateSystemElement values
+ nsAutoPtr<SVGAnimatedTransformList> mTransform;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_SVGGlobalCoordinateSystemElement_h
diff --git content/svg/content/src/SVGIFrameElement.cpp content/svg/content/src/SVGIFrameElement.cpp
new file mode 100644
index 0000000..bc06c81
--- /dev/null
+++ content/svg/content/src/SVGIFrameElement.cpp
@@ -0,0 +1,517 @@
+/* -*- 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/Util.h"
+
+#include "mozilla/dom/SVGIFrameElement.h"
+#include "nsCOMPtr.h"
+#include "nsGkAtoms.h"
+#include "nsIDOMSVGDocument.h"
+#include "mozilla/dom/SVGIFrameElementBinding.h"
+
+//DOMCI_NODE_DATA(SVGIFrameElement, mozilla::dom::SVGIFrameElement)
+
+NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT_CHECK_PARSER(IFrame)
+
+namespace mozilla {
+namespace dom {
+
+JSObject*
+SVGIFrameElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
+{
+ return SVGIFrameElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+
+//--------------------- IFrame ------------------------
+
+nsSVGElement::LengthInfo SVGIFrameElement::sLengthInfo[4] =
+{
+ { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
+ { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
+ { &nsGkAtoms::width, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
+ { &nsGkAtoms::height, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
+};
+
+nsSVGElement::StringInfo SVGIFrameElement::sStringInfo[5] =
+{
+ { &nsGkAtoms::media, 0, true },
+ { &nsGkAtoms::name, 0, true },
+ { &nsGkAtoms::src, 0, true },
+ { &nsGkAtoms::srcdoc, 0, true },
+ { &nsGkAtoms::sandbox, 0, true },
+};
+
+//----------------------------------------------------------------------
+// nsISupports methods
+
+/*
+NS_IMPL_ADDREF_INHERITED(SVGIFrameElement, nsSVGElement)
+NS_IMPL_RELEASE_INHERITED(SVGIFrameElement, nsSVGElement)
+
+NS_INTERFACE_TABLE_HEAD(SVGIFrameElement)
+ NS_NODE_INTERFACE_TABLE4(SVGIFrameElement, nsIDOMNode, nsIDOMElement,
+ nsIDOMSVGElement,
+ nsIDOMGetSVGDocument)
+ NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGIFrameElement)
+NS_INTERFACE_MAP_END_INHERITING(SVGIFrameElementBase)
+*/
+/*
+NS_IMPL_ADDREF_INHERITED(SVGIFrameElement, nsSVGElement)
+NS_IMPL_RELEASE_INHERITED(SVGIFrameElement, nsSVGElement)
+*/
+NS_IMPL_ISUPPORTS_INHERITED3(SVGIFrameElement, SVGIFrameElementBase,
+ nsIDOMNode, nsIDOMElement,
+ nsIDOMSVGElement)
+
+//----------------------------------------------------------------------
+// Implementation
+
+SVGIFrameElement::SVGIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+ FromParser aFromParser)
+ : SVGIFrameElementBase(aNodeInfo, aFromParser)
+{
+ SetIsDOMBinding();
+}
+
+SVGIFrameElement::~SVGIFrameElement()
+{
+}
+
+//----------------------------------------------------------------------
+// nsSVGElement methods
+
+/* virtual */ gfxMatrix
+SVGIFrameElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+ TransformTypes aWhich) const
+{
+ NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(),
+ "Skipping eUserSpaceToParent transforms makes no sense");
+
+ // 'transform' attribute:
+ gfxMatrix fromUserSpace =
+ SVGGraphicsElement::PrependLocalTransformsTo(aMatrix, aWhich);
+ if (aWhich == eUserSpaceToParent) {
+ return fromUserSpace;
+ }
+ // our 'x' and 'y' attributes:
+ float x, y;
+ const_cast<SVGIFrameElement*>(this)->
+ GetAnimatedLengthValues(&x, &y, nullptr);
+ gfxMatrix toUserSpace = gfxMatrix().Translate(gfxPoint(x, y));
+ if (aWhich == eChildToUserSpace) {
+ return toUserSpace;
+ }
+ NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes");
+ return toUserSpace * fromUserSpace;
+}
+
+
+//----------------------------------------------------------------------
+// nsIDOMNode methods
+
+nsresult
+SVGIFrameElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
+{
+ *aResult = nullptr;
+ nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
+ SVGIFrameElement *it = new SVGIFrameElement(ni.forget(), NOT_FROM_PARSER);
+
+ nsCOMPtr<nsINode> kungFuDeathGrip = it;
+ nsresult rv1 = it->Init();
+ nsresult rv2 = const_cast<SVGIFrameElement*>(this)->CopyInnerTo(it);
+ if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
+ kungFuDeathGrip.swap(*aResult);
+ }
+
+ return NS_FAILED(rv1) ? rv1 : rv2;
+}
+
+//NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGIFrameElement)
+
+//----------------------------------------------------------------------
+// nsSVGElement methods
+
+nsSVGElement::LengthAttributesInfo
+SVGIFrameElement::GetLengthInfo()
+{
+ return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
+ ArrayLength(sLengthInfo));
+}
+
+SVGAnimatedPreserveAspectRatio *
+SVGIFrameElement::GetPreserveAspectRatio()
+{
+ return &mPreserveAspectRatio;
+}
+
+nsSVGElement::StringAttributesInfo
+SVGIFrameElement::GetStringInfo()
+{
+ return StringAttributesInfo(mStringAttributes, sStringInfo,
+ ArrayLength(sStringInfo));
+}
+
+//----------------------------------------------------------------------
+// nsIDOMSVGIFrameElement methods:
+
+/* readonly attribute nsIDOMSVGAnimatedLength x; */
+/*NS_IMETHODIMP SVGIFrameElement::GetX(nsIDOMSVGAnimatedLength * *aX)
+{
+ *aX = X().get();
+ return NS_OK;
+}*/
+
+already_AddRefed<nsIDocument>
+SVGIFrameElement::GetContentDocument()
+{
+ return SVGIFrameElementBase::GetContentDocument();
+}
+
+already_AddRefed<nsIDOMWindow>
+SVGIFrameElement::GetContentWindow()
+{
+ return SVGIFrameElementBase::GetContentWindow();
+}
+
+already_AddRefed<SVGAnimatedLength>
+SVGIFrameElement::X()
+{
+ return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedLength y; */
+/*NS_IMETHODIMP SVGIFrameElement::GetY(nsIDOMSVGAnimatedLength * *aY)
+{
+ *aY = Y().get();
+ return NS_OK;
+}*/
+
+already_AddRefed<SVGAnimatedLength>
+SVGIFrameElement::Y()
+{
+ return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedLength width; */
+/*NS_IMETHODIMP SVGIFrameElement::GetWidth(nsIDOMSVGAnimatedLength * *aWidth)
+{
+ *aWidth = Width().get();
+ return NS_OK;
+}*/
+
+already_AddRefed<SVGAnimatedLength>
+SVGIFrameElement::Width()
+{
+ return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedLength height; */
+/*NS_IMETHODIMP SVGIFrameElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight)
+{
+ *aHeight = Height().get();
+ return NS_OK;
+}*/
+
+already_AddRefed<SVGAnimatedLength>
+SVGIFrameElement::Height()
+{
+ return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this);
+}
+
+/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */
+/*NS_IMETHODIMP
+SVGIFrameElement::GetPreserveAspectRatio(nsISupports
+ **aPreserveAspectRatio)
+{
+ *aPreserveAspectRatio = PreserveAspectRatio().get();
+ return NS_OK;
+ }*/
+
+already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
+SVGIFrameElement::PreserveAspectRatio()
+{
+ nsRefPtr<DOMSVGAnimatedPreserveAspectRatio> ratio;
+ mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(getter_AddRefs(ratio), this);
+ return ratio.forget();
+}
+
+/* readonly attribute nsIDOMSVGAnimatedString media; */
+/*NS_IMETHODIMP
+SVGIFrameElement::GetMedia(nsIDOMSVGAnimatedString * *aMedia)
+{
+ *aMedia = Media().get();
+ return NS_OK;
+}*/
+
+already_AddRefed<nsIDOMSVGAnimatedString>
+SVGIFrameElement::Media()
+{
+ nsCOMPtr<nsIDOMSVGAnimatedString> media;
+ mStringAttributes[MEDIA].ToDOMAnimatedString(getter_AddRefs(media), this);
+ return media.forget();
+}
+
+/* readonly attribute nsIDOMSVGAnimatedString name; */
+/*NS_IMETHODIMP
+SVGIFrameElement::GetName(nsIDOMSVGAnimatedString * *aName)
+{
+ *aName = Name().get();
+ return NS_OK;
+}*/
+
+already_AddRefed<nsIDOMSVGAnimatedString>
+SVGIFrameElement::Name()
+{
+ nsCOMPtr<nsIDOMSVGAnimatedString> name;
+ mStringAttributes[NAME].ToDOMAnimatedString(getter_AddRefs(name), this);
+ return name.forget();
+}
+
+/* readonly attribute nsIDOMSVGAnimatedString src; */
+/*NS_IMETHODIMP
+SVGIFrameElement::GetSrc(nsIDOMSVGAnimatedString * *aSrc)
+{
+ *aSrc = Src().get();
+ return NS_OK;
+}*/
+
+already_AddRefed<nsIDOMSVGAnimatedString>
+SVGIFrameElement::Src()
+{
+ nsCOMPtr<nsIDOMSVGAnimatedString> src;
+ mStringAttributes[SRC].ToDOMAnimatedString(getter_AddRefs(src), this);
+ return src.forget();
+}
+
+/* readonly attribute nsIDOMSVGAnimatedString srcdoc; */
+/*NS_IMETHODIMP
+SVGIFrameElement::GetSrcdoc(nsIDOMSVGAnimatedString * *aSrcdoc)
+{
+ *aSrcdoc = Srcdoc().get();
+ return NS_OK;
+}*/
+
+already_AddRefed<nsIDOMSVGAnimatedString>
+SVGIFrameElement::Srcdoc()
+{
+ nsCOMPtr<nsIDOMSVGAnimatedString> srcdoc;
+ mStringAttributes[SRCDOC].ToDOMAnimatedString(getter_AddRefs(srcdoc), this);
+ return srcdoc.forget();
+}
+
+already_AddRefed<nsIDOMSVGAnimatedString>
+SVGIFrameElement::Sandbox()
+{
+ nsCOMPtr<nsIDOMSVGAnimatedString> sandbox;
+ mStringAttributes[SANDBOX].ToDOMAnimatedString(getter_AddRefs(sandbox), this);
+ return sandbox.forget();
+}
+
+
+/* attribute DOMString sandbox; */
+//NS_IMPL_STRING_ATTR(SVGIFrameElement, Sandbox, sandbox)
+
+void
+SVGIFrameElement::SetSandbox(const nsAString& aSandbox, ErrorResult& rv)
+{
+ rv = SetAttr(kNameSpaceID_None, nsGkAtoms::sandbox, aSandbox, true);
+}
+
+//void
+//SVGIFrameElement::GetItemValueText(nsAString& aValue)
+//{
+// GetSrc(aValue);
+//}
+//
+//void
+//SVGIFrameElement::SetItemValueText(const nsAString& aValue)
+//{
+// SetSrc(aValue);
+//}
+
+/*
+NS_IMETHODIMP
+SVGIFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
+{
+ return GenericSVGFrameElement::GetContentDocument(aContentDocument);
+}
+
+NS_IMETHODIMP
+SVGIFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
+{
+ return GenericSVGFrameElement::GetContentWindow(aContentWindow);
+}
+*/
+NS_IMETHODIMP
+SVGIFrameElement::GetSVGDocument(nsIDOMDocument **aResult)
+{
+ return SVGIFrameElementBase::GetContentDocument(aResult);
+}
+
+//bool
+//SVGIFrameElement::ParseAttribute(int32_t aNamespaceID,
+// nsIAtom* aAttribute,
+// const nsAString& aValue,
+// nsAttrValue& aResult)
+//{
+// if (aNamespaceID == kNameSpaceID_None) {
+// if (aAttribute == nsGkAtoms::marginwidth) {
+// return aResult.ParseSpecialIntValue(aValue);
+// }
+// if (aAttribute == nsGkAtoms::marginheight) {
+// return aResult.ParseSpecialIntValue(aValue);
+// }
+// if (aAttribute == nsGkAtoms::width) {
+// return aResult.ParseSpecialIntValue(aValue);
+// }
+// if (aAttribute == nsGkAtoms::height) {
+// return aResult.ParseSpecialIntValue(aValue);
+// }
+// if (aAttribute == nsGkAtoms::frameborder) {
+// return ParseFrameborderValue(aValue, aResult);
+// }
+// if (aAttribute == nsGkAtoms::scrolling) {
+// return ParseScrollingValue(aValue, aResult);
+// }
+// if (aAttribute == nsGkAtoms::align) {
+// return ParseAlignValue(aValue, aResult);
+// }
+// }
+//
+// return nsGenericSVGFrameElement::ParseAttribute(aNamespaceID, aAttribute,
+// aValue, aResult);
+//}
+
+//static void
+//MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+// nsRuleData* aData)
+//{
+// if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
+// // frameborder: 0 | 1 (| NO | YES in quirks mode)
+// // If frameborder is 0 or No, set border to 0
+// // else leave it as the value set in html.css
+// const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::frameborder);
+// if (value && value->Type() == nsAttrValue::eEnum) {
+// int32_t frameborder = value->GetEnumValue();
+// if (NS_STYLE_FRAME_0 == frameborder ||
+// NS_STYLE_FRAME_NO == frameborder ||
+// NS_STYLE_FRAME_OFF == frameborder) {
+// nsCSSValue* borderLeftWidth = aData->ValueForBorderLeftWidthValue();
+// if (borderLeftWidth->GetUnit() == eCSSUnit_Null)
+// borderLeftWidth->SetFloatValue(0.0f, eCSSUnit_Pixel);
+// nsCSSValue* borderRightWidth = aData->ValueForBorderRightWidthValue();
+// if (borderRightWidth->GetUnit() == eCSSUnit_Null)
+// borderRightWidth->SetFloatValue(0.0f, eCSSUnit_Pixel);
+// nsCSSValue* borderTopWidth = aData->ValueForBorderTopWidth();
+// if (borderTopWidth->GetUnit() == eCSSUnit_Null)
+// borderTopWidth->SetFloatValue(0.0f, eCSSUnit_Pixel);
+// nsCSSValue* borderBottomWidth = aData->ValueForBorderBottomWidth();
+// if (borderBottomWidth->GetUnit() == eCSSUnit_Null)
+// borderBottomWidth->SetFloatValue(0.0f, eCSSUnit_Pixel);
+// }
+// }
+// }
+// if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
+// // width: value
+// nsCSSValue* width = aData->ValueForWidth();
+// if (width->GetUnit() == eCSSUnit_Null) {
+// const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
+// if (value && value->Type() == nsAttrValue::eInteger)
+// width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+// else if (value && value->Type() == nsAttrValue::ePercent)
+// width->SetPercentValue(value->GetPercentValue());
+// }
+//
+// // height: value
+// nsCSSValue* height = aData->ValueForHeight();
+// if (height->GetUnit() == eCSSUnit_Null) {
+// const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
+// if (value && value->Type() == nsAttrValue::eInteger)
+// height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+// else if (value && value->Type() == nsAttrValue::ePercent)
+// height->SetPercentValue(value->GetPercentValue());
+// }
+// }
+//
+// nsSVGElement::MapScrollingAttributeInto(aAttributes, aData);
+// nsSVGElement::MapImageAlignAttributeInto(aAttributes, aData);
+// nsSVGElement::MapCommonAttributesInto(aAttributes, aData);
+//}
+//
+//NS_IMETHODIMP_(bool)
+//SVGIFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
+//{
+// static const MappedAttributeEntry attributes[] = {
+// { &nsGkAtoms::width },
+// { &nsGkAtoms::height },
+// { &nsGkAtoms::frameborder },
+// { nullptr },
+// };
+//
+// static const MappedAttributeEntry* const map[] = {
+// attributes,
+// sScrollingAttributeMap,
+// sImageAlignAttributeMap,
+// sCommonAttributeMap,
+// };
+//
+// return FindAttributeDependence(aAttribute, map);
+//}
+
+
+
+//nsMapRuleToAttributesFunc
+//SVGIFrameElement::GetAttributeMappingFunction() const
+//{
+// return &MapAttributesIntoRule;
+//}
+
+//nsresult
+//nsSVGIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+// const nsAttrValue* aValue,
+// bool aNotify)
+//{
+// if (aName == nsGkAtoms::sandbox && aNameSpaceID == kNameSpaceID_None) {
+// // Parse the new value of the sandbox attribute, and if we have a docshell
+// // set its sandbox flags appropriately.
+// if (mFrameLoader) {
+// nsCOMPtr<nsIDocShell> docshell = mFrameLoader->GetExistingDocShell();
+//
+// if (docshell) {
+// uint32_t newFlags = 0;
+// // If a NULL aValue is passed in, we want to clear the sandbox flags
+// // which we will do by setting them to 0.
+// if (aValue) {
+// nsAutoString strValue;
+// aValue->ToString(strValue);
+// newFlags = nsContentUtils::ParseSandboxAttributeToFlags(
+// strValue);
+// }
+// docshell->SetSandboxFlags(newFlags);
+// }
+// }
+// }
+// return nsSVGElement::AfterSetAttr(aNameSpaceID, aName, aValue,
+// aNotify);
+//
+//}
+
+
+uint32_t
+SVGIFrameElement::GetSandboxFlags()
+{
+ nsAutoString sandboxAttr;
+
+ if (GetAttr(kNameSpaceID_None, nsGkAtoms::sandbox, sandboxAttr)) {
+ return nsContentUtils::ParseSandboxAttributeToFlags(sandboxAttr);
+ }
+
+ // No sandbox attribute, no sandbox flags.
+ return 0;
+}
+
+} // namespace dom
+} // namespace mozilla
diff --git content/svg/content/src/SVGIFrameElement.h content/svg/content/src/SVGIFrameElement.h
new file mode 100644
index 0000000..e2a7e07
--- /dev/null
+++ content/svg/content/src/SVGIFrameElement.h
@@ -0,0 +1,123 @@
+/* -*- 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/. */
+
+#ifndef mozilla_dom_SVGIFrameElement_h
+#define mozilla_dom_SVGIFrameElement_h
+
+#include "GenericSVGFrameElement.h"
+#include "nsIDOMGetSVGDocument.h"
+#include "nsContentUtils.h"
+#include "nsSVGLength2.h"
+#include "nsSVGString.h"
+#include "nsSVGElement.h"
+#include "SVGAnimatedPreserveAspectRatio.h"
+#include "nsIDocument.h"
+
+nsresult NS_NewSVGIFrameElement(nsIContent **aResult,
+ already_AddRefed<nsINodeInfo> aNodeInfo,
+ mozilla::dom::FromParser aFromParser);
+
+typedef GenericSVGFrameElement SVGIFrameElementBase;
+
+class nsSVGIFrameFrame;
+
+namespace mozilla {
+namespace dom {
+class DOMSVGAnimatedPreserveAspectRatio;
+
+class SVGIFrameElement : public SVGIFrameElementBase
+ , public nsIDOMSVGElement
+ , public nsIDOMGetSVGDocument
+{
+ friend class ::nsSVGIFrameFrame;
+
+protected:
+ SVGIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+ mozilla::dom::FromParser aFromParser);
+ virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap) MOZ_OVERRIDE;
+ virtual ~SVGIFrameElement();
+
+ friend nsresult (::NS_NewSVGIFrameElement(nsIContent **aResult,
+ already_AddRefed<nsINodeInfo> aNodeInfo,
+ mozilla::dom::FromParser aFromParser));
+
+public:
+ NS_IMPL_FROMCONTENT_WITH_TAG(SVGIFrameElement, kNameSpaceID_SVG, iframe)
+
+ // nsISupports
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIDOMNode
+ NS_FORWARD_NSIDOMNODE_TO_NSINODE
+
+ // nsIDOMElement
+ NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
+
+ // nsIDOMSVGElement
+ NS_FORWARD_NSIDOMSVGELEMENT(SVGIFrameElementBase::)
+
+ // nsIDOMGetSVGDocument
+ NS_DECL_NSIDOMGETSVGDOCUMENT
+
+
+ // nsSVGElement specializations:
+ virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
+ TransformTypes aWhich = eAllTransforms) const;
+
+ // nsIContent
+ //virtual bool ParseAttribute(int32_t aNamespaceID,
+ // nsIAtom* aAttribute,
+ // const nsAString& aValue,
+ // nsAttrValue& aResult);
+ //NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
+ //virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
+
+ virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+ //virtual nsXPCClassInfo* GetClassInfo();
+ virtual nsIDOMNode* AsDOMNode() { return this; }
+
+ // WebIDL
+ already_AddRefed<SVGAnimatedLength> X();
+ already_AddRefed<SVGAnimatedLength> Y();
+ already_AddRefed<SVGAnimatedLength> Width();
+ already_AddRefed<SVGAnimatedLength> Height();
+ already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
+ already_AddRefed<nsIDOMSVGAnimatedString> Media();
+ already_AddRefed<nsIDOMSVGAnimatedString> Name();
+ already_AddRefed<nsIDOMSVGAnimatedString> Src();
+ already_AddRefed<nsIDOMSVGAnimatedString> Srcdoc();
+ already_AddRefed<nsIDOMSVGAnimatedString> Sandbox();
+ already_AddRefed<nsIDocument> GetContentDocument();
+ already_AddRefed<nsIDOMWindow> GetContentWindow();
+ void SetSandbox(const nsAString & aSandbox, ErrorResult& rv);
+
+ //virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+ // const nsAttrValue* aValue,
+ // bool aNotify);
+
+ uint32_t GetSandboxFlags();
+
+protected:
+ virtual LengthAttributesInfo GetLengthInfo();
+ virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio();
+ virtual StringAttributesInfo GetStringInfo();
+
+ enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
+ nsSVGLength2 mLengthAttributes[4];
+ static LengthInfo sLengthInfo[4];
+
+ SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
+
+ enum { MEDIA, NAME, SRC, SRCDOC, SANDBOX };
+ nsSVGString mStringAttributes[5];
+ static StringInfo sStringInfo[5];
+
+ //virtual void GetItemValueText(nsAString& text);
+ //virtual void SetItemValueText(const nsAString& text);
+};
+
+} // namespace dom
+} // namespace mozilla
+#endif // mozilla_dom_SVGIFrameElement_h
diff --git content/svg/content/src/SVGSVGElement.cpp content/svg/content/src/SVGSVGElement.cpp
index fd89ede..7d26f26 100644
--- content/svg/content/src/SVGSVGElement.cpp
+++ content/svg/content/src/SVGSVGElement.cpp
@@ -805,6 +805,9 @@ SVGSVGElement::WillBeOutermostSVG(nsIContent* aParent,
// SVG in a foreignObject must have its own <svg> (nsSVGOuterSVGFrame).
return false;
}
+ if (tag == nsGkAtoms::iframe) {
+ return false;
+ }
if (tag == nsGkAtoms::svg) {
return false;
}
diff --git content/svg/content/src/SVGSVGElement.h content/svg/content/src/SVGSVGElement.h
index 720682e..0fc0fd8 100644
--- content/svg/content/src/SVGSVGElement.h
+++ content/svg/content/src/SVGSVGElement.h
@@ -299,7 +299,7 @@ private:
bool IsInner() const {
const nsIContent *parent = GetFlattenedTreeParent();
return parent && parent->IsSVG() &&
- parent->Tag() != nsGkAtoms::foreignObject;
+ (parent->Tag() != nsGkAtoms::foreignObject || parent->Tag() != nsGkAtoms::iframe);
}
/*
diff --git content/svg/content/src/SVGTagList.h content/svg/content/src/SVGTagList.h
index c0014ba..3a16c20 100644
--- content/svg/content/src/SVGTagList.h
+++ content/svg/content/src/SVGTagList.h
@@ -64,6 +64,8 @@ SVG_TAG(feTurbulence, FETurbulence)
SVG_TAG(filter, Filter)
SVG_TAG(foreignObject, ForeignObject)
SVG_TAG(g, G)
+SVG_TAG(globalCoordinateSystem, GlobalCoordinateSystem)
+SVG_FROM_PARSER_TAG(iframe, IFrame)
SVG_TAG(image, Image)
SVG_TAG(line, Line)
SVG_TAG(linearGradient, LinearGradient)
diff --git content/svg/content/src/nsSVGElement.cpp content/svg/content/src/nsSVGElement.cpp
index 58ebe88..9c7b628 100644
--- content/svg/content/src/nsSVGElement.cpp
+++ content/svg/content/src/nsSVGElement.cpp
@@ -1560,7 +1560,7 @@ nsSVGElement::GetCtx() const
while (ancestor && ancestor->IsSVG()) {
nsIAtom* tag = ancestor->Tag();
- if (tag == nsGkAtoms::foreignObject) {
+ if ((tag == nsGkAtoms::foreignObject || tag == nsGkAtoms::iframe)) {
return nullptr;
}
if (tag == nsGkAtoms::svg) {
diff --git dom/bindings/Bindings.conf dom/bindings/Bindings.conf
index 1264bba..a867af6 100644
--- dom/bindings/Bindings.conf
+++ dom/bindings/Bindings.conf
@@ -636,6 +636,10 @@ DOMInterfaces = {
'headerFile': 'mozilla/dom/SVGComponentTransferFunctionElement.h',
},
+'SVGGlobalCoordinateSystemElement': {
+ 'headerFile': 'mozilla/dom/SVGGlobalCoordinateSystemElement.h',
+},
+
'SVGGraphicsElement': {
'concrete': False,
'resultNotAddRefed': ['nearestViewportElement', 'farthestViewportElement']
@@ -645,6 +649,10 @@ DOMInterfaces = {
'concrete': False,
},
+'SVGIFrameElement': {
+ 'headerFile': 'mozilla/dom/SVGIFrameElement.h',
+},
+
'SVGLengthList': {
'nativeType': 'mozilla::DOMSVGLengthList',
'headerFile': 'DOMSVGLengthList.h',
diff --git dom/webidl/SVGGlobalCoordinateSystemElement.webidl dom/webidl/SVGGlobalCoordinateSystemElement.webidl
new file mode 100644
index 0000000..9c0f6bd
--- /dev/null
+++ dom/webidl/SVGGlobalCoordinateSystemElement.webidl
@@ -0,0 +1,17 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/Graphics/SVG/WG/wiki/Proposals/IFrame_Like_Syntax#7.13.1_The_.27globalCoordinateSystem.27_element
+ * (Currentry no IDL file)
+ *
+ * Copyright © 2013 KDDI, Inc.
+ */
+
+interface SVGGlobalCoordinateSystemElement : SVGElement {
+ readonly attribute SVGAnimatedTransformList transform;
+};
+
+SVGGlobalCoordinateSystemElement implements SVGURIReference;
diff --git dom/webidl/SVGIFrameElement.webidl dom/webidl/SVGIFrameElement.webidl
new file mode 100644
index 0000000..3426b3d
--- /dev/null
+++ dom/webidl/SVGIFrameElement.webidl
@@ -0,0 +1,48 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/Graphics/SVG/WG/wiki/Proposals/IFrame_Like_Syntax#5.8_The_.27iframe.27_element
+ * but based
+ * http://www.whatwg.org/specs/web-apps/current-work/#the-iframe-element
+ *
+ * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
+ * Opera Software ASA. You are granted a license to use, reproduce
+ * and create derivative works of this document.
+ * Copyright © 2013 KDDI, Inc.
+ */
+
+interface SVGIFrameElement : SVGGraphicsElement {
+ [Constant]
+ readonly attribute SVGAnimatedLength x;
+ [Constant]
+ readonly attribute SVGAnimatedLength y;
+ [Constant]
+ readonly attribute SVGAnimatedLength width;
+ [Constant]
+ readonly attribute SVGAnimatedLength height;
+ [Constant]
+ readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio;
+
+ [Constant]
+ readonly attribute SVGAnimatedString media;
+ [Constant]
+ readonly attribute SVGAnimatedString name;
+ [Constant]
+ readonly attribute SVGAnimatedString src;
+ [Constant]
+ readonly attribute SVGAnimatedString srcdoc; // maybe DOM String
+ // maybe to use DOMSettableTokenList
+ [Constant]
+ readonly attribute SVGAnimatedString sandbox;
+
+ // not implement yet
+ //[Constant]
+ //readonly attribute SVGAnimatedBoolean seamless;
+
+ readonly attribute Document? contentDocument;
+ readonly attribute WindowProxy? contentWindow;
+
+};
diff --git dom/webidl/WebIDL.mk dom/webidl/WebIDL.mk
index 2e7493b..d980acc 100644
--- dom/webidl/WebIDL.mk
+++ dom/webidl/WebIDL.mk
@@ -166,8 +166,10 @@ webidl_files = \
SVGFitToViewBox.webidl \
SVGForeignObjectElement.webidl \
SVGGElement.webidl \
+ SVGGlobalCoordinateSystemElement.webidl \
SVGGradientElement.webidl \
SVGGraphicsElement.webidl \
+ SVGIFrameElement.webidl \
SVGImageElement.webidl \
SVGLengthList.webidl \
SVGLinearGradientElement.webidl \
diff --git layout/base/nsCSSFrameConstructor.cpp layout/base/nsCSSFrameConstructor.cpp
index b2345d6..993ce59 100644
--- layout/base/nsCSSFrameConstructor.cpp
+++ layout/base/nsCSSFrameConstructor.cpp
@@ -204,6 +204,8 @@ nsIFrame*
NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
nsIFrame*
NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+nsIFrame*
+NS_NewSVGIFrameFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
#include "nsIScrollable.h"
#include "nsINodeInfo.h"
@@ -5058,7 +5060,8 @@ nsCSSFrameConstructor::FindSVGData(Element* aElement,
SIMPLE_SVG_CREATE(feOffset, NS_NewSVGFELeafFrame),
SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGFEContainerFrame),
SIMPLE_SVG_CREATE(feTile, NS_NewSVGFELeafFrame),
- SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame)
+ SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame),
+ SIMPLE_SVG_CREATE(iframe, NS_NewSVGIFrameFrame)
};
const FrameConstructionData* data =
diff --git layout/base/nsDocumentViewer.cpp layout/base/nsDocumentViewer.cpp
index c30b4d7b..b56996a 100644
--- layout/base/nsDocumentViewer.cpp
+++ layout/base/nsDocumentViewer.cpp
@@ -2376,7 +2376,7 @@ nsDocumentViewer::FindContainerView()
// constructor can treat a <frame> as an inline in some XBL
// cases. Treat that as display:none, the document is not
// displayed.
- if (subdocFrame->GetType() == nsGkAtoms::subDocumentFrame) {
+ if (subdocFrame && subdocFrame->GetType() == nsGkAtoms::subDocumentFrame) {
NS_ASSERTION(subdocFrame->GetView(), "Subdoc frames must have views");
nsView* innerView =
static_cast<nsSubDocumentFrame*>(subdocFrame)->EnsureInnerView();
diff --git layout/generic/nsFrameIdList.h layout/generic/nsFrameIdList.h
index 958e561..73d253d 100644
--- layout/generic/nsFrameIdList.h
+++ layout/generic/nsFrameIdList.h
@@ -140,6 +140,8 @@ FRAME_ID(nsSVGGeometryFrame)
FRAME_ID(nsSVGGFrame)
FRAME_ID(nsSVGGlyphFrame)
FRAME_ID(nsSVGGradientFrame)
+FRAME_ID(nsSVGIFrameForeignObjectFrame)
+FRAME_ID(nsSVGIFrameFrame)
FRAME_ID(nsSVGImageFrame)
FRAME_ID(nsSVGInnerSVGFrame)
FRAME_ID(nsSVGLinearGradientFrame)
diff --git layout/generic/nsSubDocumentFrame.h layout/generic/nsSubDocumentFrame.h
index 63cc8be..e8789f3 100644
--- layout/generic/nsSubDocumentFrame.h
+++ layout/generic/nsSubDocumentFrame.h
@@ -88,7 +88,7 @@ public:
nsresult BeginSwapDocShells(nsIFrame* aOther);
void EndSwapDocShells(nsIFrame* aOther);
nsView* EnsureInnerView();
- nsIFrame* GetSubdocumentRootFrame();
+ virtual nsIFrame* GetSubdocumentRootFrame();
nsIntSize GetSubdocumentSize();
// nsIReflowCallback
diff --git layout/svg/Makefile.in layout/svg/Makefile.in
index f541947..cd2d83a 100644
--- layout/svg/Makefile.in
+++ layout/svg/Makefile.in
@@ -35,6 +35,7 @@ CPPSRCS = \
nsSVGGeometryFrame.cpp \
nsSVGGlyphFrame.cpp \
nsSVGGradientFrame.cpp \
+ nsSVGIFrameFrame.cpp \
nsSVGImageFrame.cpp \
nsSVGInnerSVGFrame.cpp \
nsSVGIntegrationUtils.cpp \
diff --git layout/svg/nsSVGIFrameFrame.cpp layout/svg/nsSVGIFrameFrame.cpp
new file mode 100644
index 0000000..23fcf48
--- /dev/null
+++ layout/svg/nsSVGIFrameFrame.cpp
@@ -0,0 +1,1223 @@
+/* -*- 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/. */
+
+// Main header first:
+#include "nsSVGIFrameFrame.h"
+
+// Keep others in (case-insensitive) order:
+#include "gfxContext.h"
+#include "gfxMatrix.h"
+#include "nsGkAtoms.h"
+#include "nsINameSpaceManager.h"
+#include "nsLayoutUtils.h"
+#include "nsRegion.h"
+#include "nsRenderingContext.h"
+#include "nsSubDocumentFrame.h"
+#include "nsSVGEffects.h"
+#include "mozilla/dom/SVGIFrameElement.h"
+#include "nsSVGIntegrationUtils.h"
+#include "nsSVGOuterSVGFrame.h"
+#include "nsSVGUtils.h"
+#include "mozilla/AutoRestore.h"
+#include "nsViewManager.h"
+#include "nsIDocShell.h"
+#include "nsIDocShellLoadInfo.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIDocShellTreeNode.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIBaseWindow.h"
+#include "nsIContentViewer.h"
+#include "nsPresContext.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+static nsIDocument*
+GetDocumentFromView(nsView* aView)
+{
+ NS_PRECONDITION(aView, "");
+
+ nsIFrame* f = aView->GetFrame();
+ nsIPresShell* ps = f ? f->PresContext()->PresShell() : nullptr;
+ return ps ? ps->GetDocument() : nullptr;
+}
+
+
+
+class AsyncSVGFrameInit : public nsRunnable
+{
+public:
+ AsyncSVGFrameInit(nsIFrame* aFrame) : mFrame(aFrame) {}
+ NS_IMETHOD Run()
+ {
+ if (mFrame.IsAlive()) {
+ static_cast<nsSVGIFrameFrame*>(mFrame.GetFrame())->ShowViewer();
+ }
+ return NS_OK;
+ }
+private:
+ nsWeakFrame mFrame;
+};
+
+static void
+InsertViewsInReverseOrder(nsView* aSibling, nsView* aParent);
+
+static void
+EndSwapDocShellsForViews(nsView* aView);
+
+
+//----------------------------------------------------------------------
+// Implementation
+
+nsIFrame*
+NS_NewSVGIFrameFrame(nsIPresShell *aPresShell,
+ nsStyleContext *aContext)
+{
+ NS_WARNING("NS_NewSVGIFrameFrame is called");
+ return new (aPresShell) nsSVGIFrameFrame(aContext);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(nsSVGIFrameFrame)
+
+nsSVGIFrameFrame::nsSVGIFrameFrame(nsStyleContext* aContext)
+ : nsSVGIFrameFrameBase(aContext),
+ mInReflow(false)
+{
+ AddStateBits(NS_FRAME_REFLOW_ROOT | NS_FRAME_MAY_BE_TRANSFORMED |
+ NS_FRAME_SVG_LAYOUT);
+}
+
+
+//----------------------------------------------------------------------
+// nsIFrame methods
+
+NS_QUERYFRAME_HEAD(nsSVGIFrameFrame)
+ NS_QUERYFRAME_ENTRY(nsISVGChildFrame)
+NS_QUERYFRAME_TAIL_INHERITING(nsSVGIFrameFrameBase)
+
+NS_IMETHODIMP
+nsSVGIFrameFrame::Init(nsIContent* aContent,
+ nsIFrame* aParent,
+ nsIFrame* aPrevInFlow)
+{
+ NS_ASSERTION(aContent->IsSVG(nsGkAtoms::iframe),
+ "Content is not an SVG iframe!");
+
+ AddStateBits(aParent->GetStateBits() &
+ (NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD));
+ // nsresult rv = nsSVGIFrameFrameBase::Init(aContent, aParent, aPrevInFlow);
+ nsresult rv = nsLeafFrame::Init(aContent, aParent, aPrevInFlow);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // We are going to create an inner view. If we need a view for the
+ // OuterFrame but we wait for the normal view creation path in
+ // nsCSSFrameConstructor, then we will lose because the inner view's
+ // parent will already have been set to some outer view (e.g., the
+ // canvas) when it really needs to have this frame's view as its
+ // parent. So, create this frame's view right away, whether we
+ // really need it or not, and the inner view will get it as the
+ // parent.
+ if (!HasView()) {
+ rv = nsContainerFrame::CreateViewForFrame(this, true);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+ EnsureInnerView();
+
+ // Set the primary frame now so that nsDocumentViewer::FindContainerView
+ // called from within EndSwapDocShellsForViews below can find it if needed.
+ aContent->SetPrimaryFrame(this);
+
+ // If we have a detached subdoc's root view on our frame loader, re-insert
+ // it into the view tree. This happens when we've been reframed, and
+ // ensures the presentation persists across reframes. If the frame element
+ // has changed documents however, we blow away the presentation.
+ nsRefPtr<nsFrameLoader> frameloader = FrameLoader();
+ if (frameloader) {
+ nsCOMPtr<nsIDocument> oldContainerDoc;
+ nsView* detachedViews =
+ frameloader->GetDetachedSubdocView(getter_AddRefs(oldContainerDoc));
+ if (detachedViews) {
+ if (oldContainerDoc == aContent->OwnerDoc()) {
+ // Restore stashed presentation.
+ ::InsertViewsInReverseOrder(detachedViews, mInnerView);
+ ::EndSwapDocShellsForViews(mInnerView->GetFirstChild());
+ } else {
+ // Presentation is for a different document, don't restore it.
+ frameloader->Hide();
+ }
+ }
+ frameloader->SetDetachedSubdocView(nullptr, nullptr);
+ }
+
+ AddStateBits(NS_FRAME_FONT_INFLATION_CONTAINER |
+ NS_FRAME_FONT_INFLATION_FLOW_ROOT);
+ if (NS_SUCCEEDED(rv) &&
+ !(mState & NS_STATE_SVG_NONDISPLAY_CHILD)) {
+ NS_WARNING("to register object");
+ //nsSVGUtils::GetOuterSVGFrame(this)->RegisterForeignObject(this);
+ }
+ nsContentUtils::AddScriptRunner(new AsyncSVGFrameInit(this));
+
+ return rv;
+}
+
+nsIFrame*
+nsSVGIFrameFrame::GetSubdocumentRootFrame()
+{
+ if (!mInnerView)
+ return nullptr;
+ nsView* subdocView = mInnerView->GetFirstChild();
+ return subdocView ? subdocView->GetFrame() : nullptr;
+}
+
+
+
+static void
+InsertViewsInReverseOrder(nsView* aSibling, nsView* aParent)
+{
+ NS_PRECONDITION(aParent, "");
+ NS_PRECONDITION(!aParent->GetFirstChild(), "inserting into non-empty list");
+
+ nsViewManager* vm = aParent->GetViewManager();
+ while (aSibling) {
+ nsView* next = aSibling->GetNextSibling();
+ aSibling->SetNextSibling(nullptr);
+ // true means 'after' in document order which is 'before' in view order,
+ // so this call prepends the child, thus reversing the siblings as we go.
+ vm->InsertChild(aParent, aSibling, nullptr, true);
+ aSibling = next;
+ }
+}
+
+static bool
+EndSwapDocShellsForDocument(nsIDocument* aDocument, void*)
+{
+ NS_PRECONDITION(aDocument, "");
+
+ // Our docshell and view trees have been updated for the new hierarchy.
+ // Now also update all nsDeviceContext::mWidget to that of the
+ // container view in the new hierarchy.
+ nsCOMPtr<nsISupports> container = aDocument->GetContainer();
+ nsCOMPtr<nsIDocShell> ds = do_QueryInterface(container);
+ if (ds) {
+ nsCOMPtr<nsIContentViewer> cv;
+ ds->GetContentViewer(getter_AddRefs(cv));
+ while (cv) {
+ nsCOMPtr<nsPresContext> pc;
+ cv->GetPresContext(getter_AddRefs(pc));
+ nsDeviceContext* dc = pc ? pc->DeviceContext() : nullptr;
+ if (dc) {
+ nsView* v = cv->FindContainerView();
+ dc->Init(v ? v->GetNearestWidget(nullptr) : nullptr);
+ }
+ nsCOMPtr<nsIContentViewer> prev;
+ cv->GetPreviousViewer(getter_AddRefs(prev));
+ cv = prev;
+ }
+ }
+
+ /*aDocument->EnumerateFreezableElements(
+ nsObjectFrame::EndSwapDocShells, nullptr);*/
+ aDocument->EnumerateSubDocuments(EndSwapDocShellsForDocument, nullptr);
+ return true;
+}
+
+static void
+EndSwapDocShellsForViews(nsView* aSibling)
+{
+ for ( ; aSibling; aSibling = aSibling->GetNextSibling()) {
+ nsIDocument* doc = ::GetDocumentFromView(aSibling);
+ if (doc) {
+ ::EndSwapDocShellsForDocument(doc, nullptr);
+ }
+ nsIFrame *frame = aSibling->GetFrame();
+ if (frame) {
+ nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(frame);
+ if (parent->HasAnyStateBits(NS_FRAME_IN_POPUP)) {
+ nsIFrame::AddInPopupStateBitToDescendants(frame);
+ } else {
+ nsIFrame::RemoveInPopupStateBitFromDescendants(frame);
+ }
+ if (frame->HasInvalidFrameInSubtree()) {
+ while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
+ parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
+ parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
+ }
+ }
+ }
+ }
+}
+
+
+
+NS_IMETHODIMP
+nsSVGIFrameFrame::SetInitialChildList(ChildListID aListID,
+ nsFrameList& aChildList)
+{
+ nsresult result;
+ if (mFrames.NotEmpty()) {
+ // We already have child frames which means we've already been
+ // initialized
+ NS_NOTREACHED("unexpected second call to SetInitialChildList");
+ result = NS_ERROR_UNEXPECTED;
+ } else if (aListID != kPrincipalList) {
+ // All we know about is the principal child list.
+ NS_NOTREACHED("unknown frame list");
+ result = NS_ERROR_INVALID_ARG;
+ } else {
+#ifdef DEBUG
+ nsFrame::VerifyDirtyBitSet(aChildList);
+#endif
+ mFrames.SetFrames(aChildList);
+ result = NS_OK;
+ }
+ return result;
+}
+
+NS_IMETHODIMP
+nsSVGIFrameFrame::AppendFrames(ChildListID aListID,
+ nsFrameList& aFrameList)
+{
+ if (aListID != kPrincipalList) {
+#ifdef IBMBIDI
+ if (aListID != kNoReflowPrincipalList)
+#endif
+ {
+ NS_ERROR("unexpected child list");
+ return NS_ERROR_INVALID_ARG;
+ }
+ }
+ if (aFrameList.NotEmpty()) {
+ mFrames.AppendFrames(this, aFrameList);
+
+ // Ask the parent frame to reflow me.
+#ifdef IBMBIDI
+ if (aListID == kPrincipalList)
+#endif
+ {
+ PresContext()->PresShell()->
+ FrameNeedsReflow(this, nsIPresShell::eTreeChange,
+ NS_FRAME_HAS_DIRTY_CHILDREN);
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSVGIFrameFrame::InsertFrames(ChildListID aListID,
+ nsIFrame* aPrevFrame,
+ nsFrameList& aFrameList)
+{
+ NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
+ "inserting after sibling frame with different parent");
+
+ if (aListID != kPrincipalList) {
+#ifdef IBMBIDI
+ if (aListID != kNoReflowPrincipalList)
+#endif
+ {
+ NS_ERROR("unexpected child list");
+ return NS_ERROR_INVALID_ARG;
+ }
+ }
+ if (aFrameList.NotEmpty()) {
+ // Insert frames after aPrevFrame
+ mFrames.InsertFrames(this, aPrevFrame, aFrameList);
+
+#ifdef IBMBIDI
+ if (aListID == kPrincipalList)
+#endif
+ {
+ PresContext()->PresShell()->
+ FrameNeedsReflow(this, nsIPresShell::eTreeChange,
+ NS_FRAME_HAS_DIRTY_CHILDREN);
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSVGIFrameFrame::RemoveFrame(ChildListID aListID,
+ nsIFrame* aOldFrame)
+{
+ if (aListID != kPrincipalList) {
+#ifdef IBMBIDI
+ if (kNoReflowPrincipalList != aListID)
+#endif
+ {
+ NS_ERROR("unexpected child list");
+ return NS_ERROR_INVALID_ARG;
+ }
+ }
+
+ // Loop and destroy aOldFrame and all of its continuations.
+ // Request a reflow on the parent frames involved unless we were explicitly
+ // told not to (kNoReflowPrincipalList).
+ bool generateReflowCommand = true;
+#ifdef IBMBIDI
+ if (kNoReflowPrincipalList == aListID) {
+ generateReflowCommand = false;
+ }
+#endif
+ nsPresContext* pc = PresContext();
+ nsContainerFrame* lastParent = nullptr;
+ while (aOldFrame) {
+ //XXXfr probably should use StealFrame here. I'm not sure if we need to
+ // check the overflow lists atm, but we'll need a prescontext lookup
+ // for overflow containers once we can split abspos elements with
+ // inline containing blocks.
+ nsIFrame* oldFrameNextContinuation = aOldFrame->GetNextContinuation();
+ nsContainerFrame* parent =
+ static_cast<nsContainerFrame*>(aOldFrame->GetParent());
+ parent->StealFrame(pc, aOldFrame, true);
+ aOldFrame->Destroy();
+ aOldFrame = oldFrameNextContinuation;
+ if (parent != lastParent && generateReflowCommand) {
+ pc->PresShell()->
+ FrameNeedsReflow(parent, nsIPresShell::eTreeChange,
+ NS_FRAME_HAS_DIRTY_CHILDREN);
+ lastParent = parent;
+ }
+ }
+ return NS_OK;
+}
+
+
+void nsSVGIFrameFrame::DestroyFrom(nsIFrame* aDestructRoot)
+{
+ // Only unregister if we registered in the first place:
+ if (!(mState & NS_STATE_SVG_NONDISPLAY_CHILD)) {
+ NS_WARNING("to unregister object");
+ //nsSVGUtils::GetOuterSVGFrame((nsSVGForeignObjectFrame *)this)->UnregisterForeignObject(this);
+ }
+ nsSVGIFrameFrameBase::DestroyFrom(aDestructRoot);
+}
+
+
+
+
+nsIAtom *
+nsSVGIFrameFrame::GetType() const
+{
+ return nsGkAtoms::subDocumentFrame;
+}
+
+NS_IMETHODIMP
+nsSVGIFrameFrame::AttributeChanged(int32_t aNameSpaceID,
+ nsIAtom *aAttribute,
+ int32_t aModType)
+{
+ NS_WARNING("Attribute changed");
+
+ if (aNameSpaceID == kNameSpaceID_None) {
+ if (aAttribute == nsGkAtoms::width ||
+ aAttribute == nsGkAtoms::height) {
+ nsSVGUtils::InvalidateBounds(this, false);
+ nsSVGUtils::ScheduleReflowSVG(this);
+ // XXXjwatt: why mark intrinsic widths dirty? can't we just use eResize?
+ RequestReflow(nsIPresShell::eStyleChange);
+ } else if (aAttribute == nsGkAtoms::x ||
+ aAttribute == nsGkAtoms::y ||
+ aAttribute == nsGkAtoms::transform) {
+ // make sure our cached transform matrix gets (lazily) updated
+ mCanvasTM = nullptr;
+ nsSVGUtils::InvalidateBounds(this, false);
+ nsSVGUtils::ScheduleReflowSVG(this);
+ } else if (aAttribute == nsGkAtoms::viewBox ||
+ aAttribute == nsGkAtoms::preserveAspectRatio) {
+ nsSVGUtils::InvalidateBounds(this);
+ } else if (aAttribute == nsGkAtoms::src) {
+ //SVGIFrameElement *element = static_cast<SVGIFrameElement*>(mContent);
+ NS_WARNING("src changed");
+
+ }
+ }
+
+ return NS_OK;
+}
+
+/* virtual */ void
+nsSVGIFrameFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+ nsSVGIFrameFrameBase::DidSetStyleContext(aOldStyleContext);
+
+ // No need to invalidate before first reflow - that will happen elsewhere.
+ // Moreover we haven't been initialised properly yet so we may not have the
+ // right state bits.
+ if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
+ // XXXperf: probably only need a bounds update if 'font-size' changed and
+ // we have em unit width/height. Or, once we map 'transform' into style,
+ // if some transform property changed.
+ nsSVGUtils::InvalidateBounds(this, false);
+ nsSVGUtils::ScheduleReflowSVG(this);
+ }
+}
+
+NS_IMETHODIMP
+nsSVGIFrameFrame::Reflow(nsPresContext* aPresContext,
+ nsHTMLReflowMetrics& aDesiredSize,
+ const nsHTMLReflowState& aReflowState,
+ nsReflowStatus& aStatus)
+{
+ NS_ABORT_IF_FALSE(!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD),
+ "Should not have been called");
+
+ // Only InvalidateAndScheduleBoundsUpdate marks us with NS_FRAME_IS_DIRTY,
+ // so if that bit is still set we still have a resize pending. If we hit
+ // this assertion, then we should get the presShell to skip reflow roots
+ // that have a dirty parent since a reflow is going to come via the
+ // reflow root's parent anyway.
+ NS_ASSERTION(!(GetStateBits() & NS_FRAME_IS_DIRTY),
+ "Reflowing while a resize is pending is wasteful");
+
+ // ReflowSVG makes sure mRect is up to date before we're called.
+
+ NS_ASSERTION(!aReflowState.parentReflowState,
+ "should only get reflow from being reflow root");
+ NS_ASSERTION(aReflowState.ComputedWidth() == GetSize().width &&
+ aReflowState.ComputedHeight() == GetSize().height,
+ "reflow roots should be reflowed at existing size and "
+ "svg.css should ensure we have no padding/border/margin");
+
+ DoReflow();
+
+ aDesiredSize.width = aReflowState.ComputedWidth();
+ aDesiredSize.height = aReflowState.ComputedHeight();
+ aDesiredSize.SetOverflowAreasToDesiredBounds();
+ aStatus = NS_FRAME_COMPLETE;
+
+ return NS_OK;
+}
+
+// void
+// nsSVGIFrameFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
+// const nsRect& aDirtyRect,
+// const nsDisplayListSet& aLists)
+// {
+// if (!static_cast<const nsSVGElement*>(mContent)->HasValidDimensions()) {
+// return;
+// }
+// BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists);
+// }
+
+void
+nsSVGIFrameFrame::BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists,
+ uint32_t aFlags)
+{
+ nsIFrame* kid = mFrames.FirstChild();
+ // Put each child's background directly onto the content list
+ nsDisplayListSet set(aLists, aLists.Content());
+ // The children should be in content order
+ while (kid) {
+ BuildDisplayListForChild(aBuilder, kid, aDirtyRect, set, aFlags);
+ kid = kid->GetNextSibling();
+ }
+}
+
+
+bool
+nsSVGIFrameFrame::IsSVGTransformed(gfxMatrix *aOwnTransform,
+ gfxMatrix *aFromParentTransform) const
+{
+ bool foundTransform = false;
+
+ // Check if our parent has children-only transforms:
+ nsIFrame *parent = GetParent();
+ if (parent &&
+ parent->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer)) {
+ foundTransform = static_cast<nsSVGContainerFrame*>(parent)->
+ HasChildrenOnlyTransform(aFromParentTransform);
+ }
+
+ nsSVGElement *content = static_cast<nsSVGElement*>(mContent);
+ if (content->GetAnimatedTransformList()) {
+ if (aOwnTransform) {
+ *aOwnTransform = content->PrependLocalTransformsTo(gfxMatrix(),
+ nsSVGElement::eUserSpaceToParent);
+ }
+ foundTransform = true;
+ }
+ return foundTransform;
+}
+
+
+/**
+ * Returns the app unit canvas bounds of a userspace rect.
+ *
+ * @param aToCanvas Transform from userspace to canvas device space.
+ */
+static nsRect
+ToCanvasBounds(const gfxRect &aUserspaceRect,
+ const gfxMatrix &aToCanvas,
+ const nsPresContext *presContext)
+{
+ return nsLayoutUtils::RoundGfxRectToAppRect(
+ aToCanvas.TransformBounds(aUserspaceRect),
+ presContext->AppUnitsPerDevPixel());
+}
+
+NS_IMETHODIMP
+nsSVGIFrameFrame::PaintSVG(nsRenderingContext *aContext,
+ const nsIntRect *aDirtyRect)
+{
+ NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
+ (mState & NS_STATE_SVG_NONDISPLAY_CHILD),
+ "If display lists are enabled, only painting of non-display "
+ "SVG should take this code path");
+
+ if (IsDisabled())
+ return NS_OK;
+
+ nsIFrame* kid = GetFirstPrincipalChild();
+ if (!kid)
+ return NS_OK;
+
+ gfxMatrix canvasTM = GetCanvasTM(FOR_PAINTING);
+
+ if (canvasTM.IsSingular()) {
+ NS_WARNING("Can't render foreignObject element!");
+ return NS_ERROR_FAILURE;
+ }
+
+ nsRect kidDirtyRect = kid->GetVisualOverflowRect();
+
+ /* Check if we need to draw anything. */
+ if (aDirtyRect) {
+ NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
+ (mState & NS_STATE_SVG_NONDISPLAY_CHILD),
+ "Display lists handle dirty rect intersection test");
+ // Transform the dirty rect into app units in our userspace.
+ gfxMatrix invmatrix = canvasTM;
+ invmatrix.Invert();
+ NS_ASSERTION(!invmatrix.IsSingular(),
+ "inverse of non-singular matrix should be non-singular");
+
+ gfxRect transDirtyRect = gfxRect(aDirtyRect->x, aDirtyRect->y,
+ aDirtyRect->width, aDirtyRect->height);
+ transDirtyRect = invmatrix.TransformBounds(transDirtyRect);
+
+ kidDirtyRect.IntersectRect(kidDirtyRect,
+ nsLayoutUtils::RoundGfxRectToAppRect(transDirtyRect,
+ PresContext()->AppUnitsPerCSSPixel()));
+
+ // XXX after bug 614732 is fixed, we will compare mRect with aDirtyRect,
+ // not with kidDirtyRect. I.e.
+ // int32_t appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel();
+ // mRect.ToOutsidePixels(appUnitsPerDevPx).Intersects(*aDirtyRect)
+ if (kidDirtyRect.IsEmpty())
+ return NS_OK;
+ }
+
+ gfxContext *gfx = aContext->ThebesContext();
+
+ gfx->Save();
+
+ if (StyleDisplay()->IsScrollableOverflow()) {
+ float x, y, width, height;
+ static_cast<nsSVGElement*>(mContent)->
+ GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
+
+ gfxRect clipRect =
+ nsSVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height);
+ nsSVGUtils::SetClipRect(gfx, canvasTM, clipRect);
+ }
+
+ // SVG paints in CSS px, but normally frames paint in dev pixels. Here we
+ // multiply a CSS-px-to-dev-pixel factor onto canvasTM so our children paint
+ // correctly.
+ float cssPxPerDevPx = PresContext()->
+ AppUnitsToFloatCSSPixels(PresContext()->AppUnitsPerDevPixel());
+ gfxMatrix canvasTMForChildren = canvasTM;
+ canvasTMForChildren.Scale(cssPxPerDevPx, cssPxPerDevPx);
+
+ gfx->Multiply(canvasTMForChildren);
+
+ uint32_t flags = nsLayoutUtils::PAINT_IN_TRANSFORM;
+ if (SVGAutoRenderState::IsPaintingToWindow(aContext)) {
+ flags |= nsLayoutUtils::PAINT_TO_WINDOW;
+ }
+ nsresult rv = nsLayoutUtils::PaintFrame(aContext, kid, nsRegion(kidDirtyRect),
+ NS_RGBA(0,0,0,0), flags);
+
+ gfx->Restore();
+
+ return rv;
+}
+
+NS_IMETHODIMP_(nsIFrame*)
+nsSVGIFrameFrame::GetFrameForPoint(const nsPoint &aPoint)
+{
+ NS_ASSERTION(!NS_SVGDisplayListHitTestingEnabled() ||
+ (mState & NS_STATE_SVG_NONDISPLAY_CHILD),
+ "If display lists are enabled, only hit-testing of a "
+ "clipPath's contents should take this code path");
+
+ if (IsDisabled() || (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD))
+ return nullptr;
+
+ nsIFrame* kid = GetFirstPrincipalChild();
+ if (!kid)
+ return nullptr;
+
+ float x, y, width, height;
+ static_cast<nsSVGElement*>(mContent)->
+ GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
+
+ gfxMatrix tm = GetCanvasTM(FOR_HIT_TESTING).Invert();
+ if (tm.IsSingular())
+ return nullptr;
+
+ // Convert aPoint from app units in canvas space to user space:
+
+ gfxPoint pt = gfxPoint(aPoint.x, aPoint.y) / PresContext()->AppUnitsPerDevPixel();
+ pt = tm.Transform(pt);
+
+ if (!gfxRect(0.0f, 0.0f, width, height).Contains(pt))
+ return nullptr;
+
+ // Convert pt to app units in *local* space:
+
+ pt = pt * nsPresContext::AppUnitsPerCSSPixel();
+ nsPoint point = nsPoint(NSToIntRound(pt.x), NSToIntRound(pt.y));
+
+ nsIFrame *frame = nsLayoutUtils::GetFrameForPoint(kid, point);
+ if (frame && nsSVGUtils::HitTestClip(this, aPoint))
+ return frame;
+
+ return nullptr;
+}
+
+NS_IMETHODIMP_(nsRect)
+nsSVGIFrameFrame::GetCoveredRegion()
+{
+ float x, y, w, h;
+ static_cast<SVGIFrameElement*>(mContent)->
+ GetAnimatedLengthValues(&x, &y, &w, &h, nullptr);
+ if (w < 0.0f) w = 0.0f;
+ if (h < 0.0f) h = 0.0f;
+ // GetCanvasTM includes the x,y translation
+ /*
+ return ToCanvasBounds(gfxRect(0.0, 0.0, w, h), GetCanvasTM(FOR_OUTERSVG_TM),
+ PresContext());
+ */
+ return nsSVGUtils::ToCanvasBounds(gfxRect(0.0, 0.0, w, h), GetCanvasTM(FOR_OUTERSVG_TM),
+ PresContext());
+}
+
+void
+nsSVGIFrameFrame::ReflowSVG()
+{
+ NS_ASSERTION(nsSVGUtils::OuterSVGIsCallingReflowSVG(this),
+ "This call is probably a wasteful mistake");
+
+ NS_ABORT_IF_FALSE(!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD),
+ "ReflowSVG mechanism not designed for this");
+
+ if (!nsSVGUtils::NeedsReflowSVG(this)) {
+ return;
+ }
+
+ // We update mRect before the DoReflow call so that DoReflow uses the
+ // correct dimensions:
+
+ float x, y, w, h;
+ static_cast<SVGIFrameElement*>(mContent)->
+ GetAnimatedLengthValues(&x, &y, &w, &h, nullptr);
+
+ // If mRect's width or height are negative, reflow blows up! We must clamp!
+ if (w < 0.0f) w = 0.0f;
+ if (h < 0.0f) h = 0.0f;
+
+ mRect = nsLayoutUtils::RoundGfxRectToAppRect(
+ gfxRect(x, y, w, h),
+ PresContext()->AppUnitsPerCSSPixel());
+
+ // Fully mark our kid dirty so that it gets resized if necessary
+ // (NS_FRAME_HAS_DIRTY_CHILDREN isn't enough in that case):
+ nsIFrame* kid = GetFirstPrincipalChild();
+ if (kid)
+ kid->AddStateBits(NS_FRAME_IS_DIRTY);
+
+ // Make sure to not allow interrupts if we're not being reflown as a root:
+ nsPresContext::InterruptPreventer noInterrupts(PresContext());
+
+ DoReflow();
+
+ if (mState & NS_FRAME_FIRST_REFLOW) {
+ // Make sure we have our filter property (if any) before calling
+ // FinishAndStoreOverflow (subsequent filter changes are handled off
+ // nsChangeHint_UpdateEffects):
+ nsSVGEffects::UpdateEffects(this);
+ }
+
+ // TODO: once we support |overflow:visible| on foreignObject, then we will
+ // need to take account of our descendants here.
+ nsRect overflow = nsRect(nsPoint(0,0), mRect.Size());
+ nsOverflowAreas overflowAreas(overflow, overflow);
+ FinishAndStoreOverflow(overflowAreas, mRect.Size());
+
+ // Now unset the various reflow bits:
+ mState &= ~(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
+ NS_FRAME_HAS_DIRTY_CHILDREN);
+}
+
+void
+nsSVGIFrameFrame::NotifySVGChanged(uint32_t aFlags)
+{
+ NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED),
+ "Invalidation logic may need adjusting");
+
+ bool needNewBounds = false; // i.e. mRect or visual overflow rect
+ bool needReflow = false;
+ bool needNewCanvasTM = false;
+
+ //if (aFlags & COORD_CONTEXT_CHANGED) {
+ // SVGIFrameElement *fO =
+ // static_cast<SVGIFrameElement*>(mContent);
+ // // Coordinate context changes affect mCanvasTM if we have a
+ // // percentage 'x' or 'y'
+ // if (fO->mLengthAttributes[SVGIFrameElement::ATTR_X].IsPercentage() ||
+ // fO->mLengthAttributes[SVGIFrameElement::ATTR_Y].IsPercentage()) {
+ // needNewBounds = true;
+ // needNewCanvasTM = true;
+ // }
+ // // Our coordinate context's width/height has changed. If we have a
+ // // percentage width/height our dimensions will change so we must reflow.
+ // if (fO->mLengthAttributes[SVGIFrameElement::ATTR_WIDTH].IsPercentage() ||
+ // fO->mLengthAttributes[SVGIFrameElement::ATTR_HEIGHT].IsPercentage()) {
+ // needNewBounds = true;
+ // needReflow = true;
+ // }
+ //}
+
+ if (aFlags & TRANSFORM_CHANGED) {
+ if (mCanvasTM && mCanvasTM->IsSingular()) {
+ needNewBounds = true; // old bounds are bogus
+ }
+ needNewCanvasTM = true;
+ // In an ideal world we would reflow when our CTM changes. This is because
+ // glyph metrics do not necessarily scale uniformly with change in scale
+ // and, as a result, CTM changes may require text to break at different
+ // points. The problem would be how to keep performance acceptable when
+ // e.g. the transform of an ancestor is animated.
+ // We also seem to get some sort of infinite loop post bug 421584 if we
+ // reflow.
+ }
+
+ if (needNewBounds) {
+ // Ancestor changes can't affect how we render from the perspective of
+ // any rendering observers that we may have, so we don't need to
+ // invalidate them. We also don't need to invalidate ourself, since our
+ // changed ancestor will have invalidated its entire area, which includes
+ // our area.
+ nsSVGUtils::ScheduleReflowSVG(this);
+ }
+
+ // If we're called while the PresShell is handling reflow events then we
+ // must have been called as a result of the NotifyViewportChange() call in
+ // our nsSVGOuterSVGFrame's Reflow() method. We must not call RequestReflow
+ // at this point (i.e. during reflow) because it could confuse the
+ // PresShell and prevent it from reflowing us properly in future. Besides
+ // that, nsSVGOuterSVGFrame::DidReflow will take care of reflowing us
+ // synchronously, so there's no need.
+ if (needReflow && !PresContext()->PresShell()->IsReflowLocked()) {
+ RequestReflow(nsIPresShell::eResize);
+ }
+
+ if (needNewCanvasTM) {
+ // Do this after calling InvalidateAndScheduleBoundsUpdate in case we
+ // change the code and it needs to use it.
+ mCanvasTM = nullptr;
+ }
+}
+
+SVGBBox
+nsSVGIFrameFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
+ uint32_t aFlags)
+{
+ SVGIFrameElement *content =
+ static_cast<SVGIFrameElement*>(mContent);
+
+ float x, y, w, h;
+ content->GetAnimatedLengthValues(&x, &y, &w, &h, nullptr);
+
+ if (w < 0.0f) w = 0.0f;
+ if (h < 0.0f) h = 0.0f;
+
+ if (aToBBoxUserspace.IsSingular()) {
+ // XXX ReportToConsole
+ return SVGBBox();
+ }
+ return aToBBoxUserspace.TransformBounds(gfxRect(0.0, 0.0, w, h));
+}
+
+//----------------------------------------------------------------------
+
+gfxMatrix
+nsSVGIFrameFrame::GetCanvasTM(uint32_t aFor)
+{
+ if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
+ if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
+ (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
+ return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
+ }
+ }
+ if (!mCanvasTM) {
+ NS_ASSERTION(mParent, "null parent");
+
+ //nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
+ //SVGForeignObjectElement *content =
+ // static_cast<SVGForeignObjectElement*>(mContent);
+ nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
+ SVGIFrameElement *content = static_cast<SVGIFrameElement*>(mContent);
+
+ gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
+
+ mCanvasTM = new gfxMatrix(tm);
+ }
+ return *mCanvasTM;
+}
+
+//----------------------------------------------------------------------
+// Implementation helpers
+
+void nsSVGIFrameFrame::RequestReflow(nsIPresShell::IntrinsicDirty aType)
+{
+ if (GetStateBits() & NS_FRAME_FIRST_REFLOW)
+ // If we haven't had a ReflowSVG() yet, nothing to do.
+ return;
+
+ nsIFrame* kid = GetFirstPrincipalChild();
+ if (!kid)
+ return;
+
+ PresContext()->PresShell()->FrameNeedsReflow(kid, aType, NS_FRAME_IS_DIRTY);
+}
+
+void
+nsSVGIFrameFrame::DoReflow()
+{
+ // Skip reflow if we're zero-sized, unless this is our first reflow.
+ if (IsDisabled() &&
+ !(GetStateBits() & NS_FRAME_FIRST_REFLOW))
+ return;
+
+ nsPresContext *presContext = PresContext();
+ nsIFrame* kid = GetFirstPrincipalChild();
+ if (!kid)
+ return;
+
+ // initiate a synchronous reflow here and now:
+ nsIPresShell* presShell = presContext->PresShell();
+ NS_ASSERTION(presShell, "null presShell");
+ nsRefPtr<nsRenderingContext> renderingContext =
+ presShell->GetReferenceRenderingContext();
+ if (!renderingContext)
+ return;
+
+ mInReflow = true;
+
+ nsHTMLReflowState reflowState(presContext, kid,
+ renderingContext,
+ nsSize(mRect.width, NS_UNCONSTRAINEDSIZE));
+ nsHTMLReflowMetrics desiredSize;
+ nsReflowStatus status;
+
+ // We don't use mRect.height above because that tells the child to do
+ // page/column breaking at that height.
+ NS_ASSERTION(reflowState.mComputedBorderPadding == nsMargin(0, 0, 0, 0) &&
+ reflowState.mComputedMargin == nsMargin(0, 0, 0, 0),
+ "style system should ensure that :-moz-svg-foreign-content "
+ "does not get styled");
+ NS_ASSERTION(reflowState.ComputedWidth() == mRect.width,
+ "reflow state made child wrong size");
+ reflowState.SetComputedHeight(mRect.height);
+
+ ReflowChild(kid, presContext, desiredSize, reflowState, 0, 0,
+ NS_FRAME_NO_MOVE_FRAME, status);
+ NS_ASSERTION(mRect.width == desiredSize.width &&
+ mRect.height == desiredSize.height, "unexpected size");
+ FinishReflowChild(kid, presContext, &reflowState, desiredSize, 0, 0,
+ NS_FRAME_NO_MOVE_FRAME);
+
+ mInReflow = false;
+}
+
+nsRect
+nsSVGIFrameFrame::GetInvalidRegion()
+{
+ nsIFrame* kid = GetFirstPrincipalChild();
+ if (kid->HasInvalidFrameInSubtree()) {
+ gfxRect r(mRect.x, mRect.y, mRect.width, mRect.height);
+ r.Scale(1.0 / nsPresContext::AppUnitsPerCSSPixel());
+ nsRect rect = ToCanvasBounds(r, GetCanvasTM(FOR_PAINTING), PresContext());
+ rect = nsSVGUtils::GetPostFilterVisualOverflowRect(this, rect);
+ return rect;
+ }
+ return nsRect();
+}
+
+
+/* from nsContainerFrame */
+/**
+ * Invokes the WillReflow() function, positions the frame and its view (if
+ * requested), and then calls Reflow(). If the reflow succeeds and the child
+ * frame is complete, deletes any next-in-flows using DeleteNextInFlowChild()
+ */
+nsresult
+nsSVGIFrameFrame::ReflowChild(nsIFrame* aKidFrame,
+ nsPresContext* aPresContext,
+ nsHTMLReflowMetrics& aDesiredSize,
+ const nsHTMLReflowState& aReflowState,
+ nscoord aX,
+ nscoord aY,
+ uint32_t aFlags,
+ nsReflowStatus& aStatus,
+ nsOverflowContinuationTracker* aTracker)
+{
+ NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state");
+
+ nsresult result;
+
+ // Send the WillReflow() notification, and position the child frame
+ // and its view if requested
+ aKidFrame->WillReflow(aPresContext);
+
+ if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
+ aKidFrame->SetPosition(nsPoint(aX, aY));
+ }
+
+ if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
+ PositionFrameView(aKidFrame);
+ }
+
+ // Reflow the child frame
+ result = aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState,
+ aStatus);
+
+ // If the reflow was successful and the child frame is complete, delete any
+ // next-in-flows
+ if (NS_SUCCEEDED(result) && NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
+ nsIFrame* kidNextInFlow = aKidFrame->GetNextInFlow();
+ if (nullptr != kidNextInFlow) {
+ // Remove all of the childs next-in-flows. Make sure that we ask
+ // the right parent to do the removal (it's possible that the
+ // parent is not this because we are executing pullup code)
+ if (aTracker) aTracker->Finish(aKidFrame);
+ static_cast<nsContainerFrame*>(kidNextInFlow->GetParent())
+ ->DeleteNextInFlowChild(aPresContext, kidNextInFlow, true);
+ }
+ }
+ return result;
+}
+
+
+/**
+ * Position the views of |aFrame|'s descendants. A container frame
+ * should call this method if it moves a frame after |Reflow|.
+ */
+void
+nsSVGIFrameFrame::PositionChildViews(nsIFrame* aFrame)
+{
+ if (!(aFrame->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)) {
+ return;
+ }
+
+ // Recursively walk aFrame's child frames.
+ // Process the additional child lists, but skip the popup list as the
+ // view for popups is managed by the parent. Currently only nsMenuFrame
+ // has a popupList and during layout will call nsMenuPopupFrame::AdjustView.
+ ChildListIterator lists(aFrame);
+ for (; !lists.IsDone(); lists.Next()) {
+ if (lists.CurrentID() == kPopupList) {
+ continue;
+ }
+ nsFrameList::Enumerator childFrames(lists.CurrentList());
+ for (; !childFrames.AtEnd(); childFrames.Next()) {
+ // Position the frame's view (if it has one) otherwise recursively
+ // process its children
+ nsIFrame* childFrame = childFrames.get();
+ if (childFrame->HasView()) {
+ PositionFrameView(childFrame);
+ } else {
+ PositionChildViews(childFrame);
+ }
+ }
+ }
+}
+
+/**
+ * The second half of frame reflow. Does the following:
+ * - sets the frame's bounds
+ * - sizes and positions (if requested) the frame's view. If the frame's final
+ * position differs from the current position and the frame itself does not
+ * have a view, then any child frames with views are positioned so they stay
+ * in sync
+ * - sets the view's visibility, opacity, content transparency, and clip
+ * - invoked the DidReflow() function
+ *
+ * Flags:
+ * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this
+ * case. Also implies NS_FRAME_NO_MOVE_VIEW
+ * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
+ * don't want to automatically sync the frame and view
+ * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view
+ */
+nsresult
+nsSVGIFrameFrame::FinishReflowChild(nsIFrame* aKidFrame,
+ nsPresContext* aPresContext,
+ const nsHTMLReflowState* aReflowState,
+ const nsHTMLReflowMetrics& aDesiredSize,
+ nscoord aX,
+ nscoord aY,
+ uint32_t aFlags)
+{
+ nsPoint curOrigin = aKidFrame->GetPosition();
+ nsRect bounds(aX, aY, aDesiredSize.width, aDesiredSize.height);
+
+ aKidFrame->SetRect(bounds);
+
+ if (aKidFrame->HasView()) {
+ nsView* view = aKidFrame->GetView();
+ // Make sure the frame's view is properly sized and positioned and has
+ // things like opacity correct
+ SyncFrameViewAfterReflow(aPresContext, aKidFrame, view,
+ aDesiredSize.VisualOverflow(), aFlags);
+ }
+
+ if (!(aFlags & NS_FRAME_NO_MOVE_VIEW) &&
+ (curOrigin.x != aX || curOrigin.y != aY)) {
+ if (!aKidFrame->HasView()) {
+ // If the frame has moved, then we need to make sure any child views are
+ // correctly positioned
+ PositionChildViews(aKidFrame);
+ }
+ }
+
+ return aKidFrame->DidReflow(aPresContext, aReflowState, nsDidReflowStatus::FINISHED);
+}
+
+/**
+ * Position the view associated with |aKidFrame|, if there is one. A
+ * container frame should call this method after positioning a frame,
+ * but before |Reflow|.
+ */
+void
+nsSVGIFrameFrame::PositionFrameView(nsIFrame* aKidFrame)
+{
+ nsIFrame* parentFrame = aKidFrame->GetParent();
+ if (!aKidFrame->HasView() || !parentFrame)
+ return;
+
+ nsView* view = aKidFrame->GetView();
+ nsViewManager* vm = view->GetViewManager();
+ nsPoint pt;
+ nsView* ancestorView = parentFrame->GetClosestView(&pt);
+
+ if (ancestorView != view->GetParent()) {
+ NS_ASSERTION(ancestorView == view->GetParent()->GetParent(),
+ "Allowed only one anonymous view between frames");
+ // parentFrame is responsible for positioning aKidFrame's view
+ // explicitly
+ return;
+ }
+
+ pt += aKidFrame->GetPosition();
+ vm->MoveViewTo(view, pt.x, pt.y);
+}
+
+void
+nsSVGIFrameFrame::SyncFrameViewAfterReflow(nsPresContext* aPresContext,
+ nsIFrame* aFrame,
+ nsView* aView,
+ const nsRect& aVisualOverflowArea,
+ uint32_t aFlags)
+{
+ if (!aView) {
+ return;
+ }
+
+ // Make sure the view is sized and positioned correctly
+ if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
+ PositionFrameView(aFrame);
+ }
+
+ if (0 == (aFlags & NS_FRAME_NO_SIZE_VIEW)) {
+ nsViewManager* vm = aView->GetViewManager();
+
+ vm->ResizeView(aView, aVisualOverflowArea, true);
+ }
+}
+
+const nsFrameList&
+nsSVGIFrameFrame::GetChildList(ChildListID aListID) const
+{
+ // We only know about the principal child list and the overflow lists.
+ switch (aListID) {
+ case kPrincipalList:
+ return mFrames;
+ default:
+ return nsSubDocumentFrame::GetChildList(aListID);
+ }
+}
+
+
+void
+nsSVGIFrameFrame::GetChildLists(nsTArray<ChildList>* aLists) const
+{
+ mFrames.AppendIfNonempty(aLists, kPrincipalList);
+ nsSubDocumentFrame::GetChildLists(aLists);
+}
+
+static void AppendIfNonempty(const nsIFrame* aFrame,
+ FramePropertyTable* aPropTable,
+ const FramePropertyDescriptor* aProperty,
+ nsTArray<nsIFrame::ChildList>* aLists,
+ nsIFrame::ChildListID aListID)
+{
+ nsFrameList* list = static_cast<nsFrameList*>(
+ aPropTable->Get(aFrame, aProperty));
+ if (list) {
+ list->AppendIfNonempty(aLists, aListID);
+ }
+}
+
+void
+nsSVGIFrameFrame::ShowViewer()
+{
+ if (mCallingShow) {
+ return;
+ }
+
+ if (!PresContext()->IsDynamic()) {
+ // We let the printing code take care of loading the document; just
+ // create the inner view for it to use.
+ (void) EnsureInnerView();
+ } else {
+ nsRefPtr<nsFrameLoader> frameloader = FrameLoader();
+ if (frameloader) {
+ nsIntSize margin = GetMarginAttributes();
+ const nsStyleDisplay* disp = StyleDisplay();
+ nsWeakFrame weakThis(this);
+ mCallingShow = true;
+ bool didCreateDoc =
+ frameloader->ShowSVG(margin.width, margin.height,
+ this);
+ /* frameloader->ShowSVG(margin.width, margin.height,
+ ConvertOverflow(disp->mOverflowX),
+ ConvertOverflow(disp->mOverflowY),
+ this); */
+ if (!weakThis.IsAlive()) {
+ return;
+ }
+ mCallingShow = false;
+ mDidCreateDoc = didCreateDoc;
+ }
+ }
+}
+
diff --git layout/svg/nsSVGIFrameFrame.h layout/svg/nsSVGIFrameFrame.h
new file mode 100644
index 0000000..88c9f9f
--- /dev/null
+++ layout/svg/nsSVGIFrameFrame.h
@@ -0,0 +1,257 @@
+/* -*- 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/. */
+
+#ifndef NS_SVGIFRAMEFRAME_H
+#define NS_SVGIFRAMEFRAME_H
+
+#include "mozilla/Attributes.h"
+#include "nsIPresShell.h"
+#include "nsISVGChildFrame.h"
+#include "nsRegion.h"
+#include "nsSubDocumentFrame.h"
+#include "nsSVGUtils.h"
+//#include "nsSVGIFrameForeignObjectFrame.h"
+#include "nsContainerFrame.h"
+
+class nsRenderingContext;
+class nsSVGOuterSVGFrame;
+
+typedef nsSubDocumentFrame nsSVGIFrameFrameBase;
+
+class nsSVGIFrameFrame : public nsSVGIFrameFrameBase,
+ public nsISVGChildFrame
+{
+ friend nsIFrame*
+ NS_NewSVGIFrameFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+protected:
+ nsSVGIFrameFrame(nsStyleContext* aContext);
+
+public:
+ NS_DECL_QUERYFRAME
+ NS_DECL_FRAMEARENA_HELPERS
+
+ // nsIFrame methods
+ NS_IMETHOD Init(nsIContent* aContent,
+ nsIFrame* aParent,
+ nsIFrame* aPrevInFlow);
+ NS_IMETHOD SetInitialChildList(ChildListID aListID,
+ nsFrameList& aChildList) MOZ_OVERRIDE;
+ NS_IMETHOD AppendFrames(ChildListID aListID,
+ nsFrameList& aFrameList);
+ NS_IMETHOD InsertFrames(ChildListID aListID,
+ nsIFrame* aPrevFrame,
+ nsFrameList& aFrameList);
+ NS_IMETHOD RemoveFrame(ChildListID aListID,
+ nsIFrame* aOldFrame) MOZ_OVERRIDE;
+
+
+
+ virtual void DestroyFrom(nsIFrame* aDestructRoot);
+
+ NS_IMETHOD AttributeChanged(int32_t aNameSpaceID,
+ nsIAtom* aAttribute,
+ int32_t aModType);
+
+ virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE;
+
+ /*
+ virtual nsIFrame* GetContentInsertionFrame() {
+ nsIFrame *frame = GetFirstPrincipalChild();
+ if (!frame)
+ return nullptr;
+ return frame->GetContentInsertionFrame();
+ }*/
+
+ virtual nsIFrame* GetSubdocumentRootFrame();
+
+ NS_IMETHOD Reflow(nsPresContext* aPresContext,
+ nsHTMLReflowMetrics& aDesiredSize,
+ const nsHTMLReflowState& aReflowState,
+ nsReflowStatus& aStatus);
+
+ // void BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ // const nsRect& aDirtyRect,
+ // const nsDisplayListSet& aLists);
+
+ /**
+ * Get the "type" of the frame
+ *
+ * @see nsGkAtoms::svgIFrameFrame
+ */
+ virtual nsIAtom* GetType() const;
+
+ virtual bool IsFrameOfType(uint32_t aFlags) const
+ {
+ return nsSVGIFrameFrameBase::IsFrameOfType(aFlags &
+ ~(nsIFrame::eSVG | nsIFrame::eSVGForeignObject));
+ }
+
+ virtual bool IsSVGTransformed(gfxMatrix *aOwnTransform,
+ gfxMatrix *aFromParentTransform) const;
+
+ /* from nsContainerFrame */
+ virtual const nsFrameList& GetChildList(ChildListID aList) const MOZ_OVERRIDE;
+ virtual void GetChildLists(nsTArray<ChildList>* aLists) const MOZ_OVERRIDE;
+
+
+ /**
+ * Invokes the WillReflow() function, positions the frame and its view (if
+ * requested), and then calls Reflow(). If the reflow succeeds and the child
+ * frame is complete, deletes any next-in-flows using DeleteNextInFlowChild()
+ *
+ * Flags:
+ * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
+ * don't want to automatically sync the frame and view
+ * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this
+ * case. Also implies NS_FRAME_NO_MOVE_VIEW
+ */
+ nsresult ReflowChild(nsIFrame* aKidFrame,
+ nsPresContext* aPresContext,
+ nsHTMLReflowMetrics& aDesiredSize,
+ const nsHTMLReflowState& aReflowState,
+ nscoord aX,
+ nscoord aY,
+ uint32_t aFlags,
+ nsReflowStatus& aStatus,
+ nsOverflowContinuationTracker* aTracker = nullptr);
+
+ /**
+ * The second half of frame reflow. Does the following:
+ * - sets the frame's bounds
+ * - sizes and positions (if requested) the frame's view. If the frame's final
+ * position differs from the current position and the frame itself does not
+ * have a view, then any child frames with views are positioned so they stay
+ * in sync
+ * - sets the view's visibility, opacity, content transparency, and clip
+ * - invoked the DidReflow() function
+ *
+ * Flags:
+ * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this
+ * case. Also implies NS_FRAME_NO_MOVE_VIEW
+ * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
+ * don't want to automatically sync the frame and view
+ * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view
+ */
+ static nsresult FinishReflowChild(nsIFrame* aKidFrame,
+ nsPresContext* aPresContext,
+ const nsHTMLReflowState* aReflowState,
+ const nsHTMLReflowMetrics& aDesiredSize,
+ nscoord aX,
+ nscoord aY,
+ uint32_t aFlags);
+
+ static void PositionChildViews(nsIFrame* aFrame);
+
+ // Positions the frame's view based on the frame's origin
+ static void PositionFrameView(nsIFrame* aKidFrame);
+
+ // Set the view's size and position after its frame has been reflowed.
+ //
+ // Flags:
+ // NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
+ // don't want to automatically sync the frame and view
+ // NS_FRAME_NO_SIZE_VIEW - don't size the view
+ static void SyncFrameViewAfterReflow(nsPresContext* aPresContext,
+ nsIFrame* aFrame,
+ nsView* aView,
+ const nsRect& aVisualOverflowArea,
+ uint32_t aFlags = 0);
+
+ // ==========================================================================
+ /* Overflow containers are continuation frames that hold overflow. They
+ * are created when the frame runs out of computed height, but still has
+ * too much content to fit in the availableHeight. The parent creates a
+ * continuation as usual, but marks it as NS_FRAME_IS_OVERFLOW_CONTAINER
+ * and adds it to its next-in-flow's overflow container list, either by
+ * adding it directly or by putting it in its own excess overflow containers
+ * list (to be drained by the next-in-flow when it calls
+ * ReflowOverflowContainerChildren). The parent continues reflow as if
+ * the frame was complete once it ran out of computed height, but returns
+ * either an NS_FRAME_NOT_COMPLETE or NS_FRAME_OVERFLOW_INCOMPLETE reflow
+ * status to request a next-in-flow. The parent's next-in-flow is then
+ * responsible for calling ReflowOverflowContainerChildren to (drain and)
+ * reflow these overflow continuations. Overflow containers do not affect
+ * other frames' size or position during reflow (but do affect their
+ * parent's overflow area).
+ *
+ * Overflow container continuations are different from normal continuations
+ * in that
+ * - more than one child of the frame can have its next-in-flow broken
+ * off and pushed into the frame's next-in-flow
+ * - new continuations may need to be spliced into the middle of the list
+ * or deleted continuations slipped out
+ * e.g. A, B, C are all fixed-size containers on one page, all have
+ * overflow beyond availableHeight, and content is dynamically added
+ * and removed from B
+ * As a result, it is not possible to simply prepend the new continuations
+ * to the old list as with the overflowProperty mechanism. To avoid
+ * complicated list splicing, the code assumes only one overflow containers
+ * list exists for a given frame: either its own overflowContainersProperty
+ * or its prev-in-flow's excessOverflowContainersProperty, not both.
+ *
+ * The nsOverflowContinuationTracker helper class should be used for tracking
+ * overflow containers and adding them to the appropriate list.
+ * See nsBlockFrame::Reflow for a sample implementation.
+ */
+
+ friend class nsOverflowContinuationTracker;
+
+
+#ifdef DEBUG
+ NS_IMETHOD GetFrameName(nsAString& aResult) const
+ {
+ return MakeFrameName(NS_LITERAL_STRING("SVGIFrame"), aResult);
+ }
+#endif
+
+ // nsISVGChildFrame interface:
+ NS_IMETHOD PaintSVG(nsRenderingContext *aContext,
+ const nsIntRect *aDirtyRect);
+ NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint) MOZ_OVERRIDE;
+ NS_IMETHOD_(nsRect) GetCoveredRegion() MOZ_OVERRIDE;
+ virtual void ReflowSVG() MOZ_OVERRIDE;
+ virtual void NotifySVGChanged(uint32_t aFlags) MOZ_OVERRIDE;
+ virtual SVGBBox GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
+ uint32_t aFlags) MOZ_OVERRIDE;
+ NS_IMETHOD_(bool) IsDisplayContainer() MOZ_OVERRIDE { return true; }
+
+ gfxMatrix GetCanvasTM(uint32_t aFor);
+
+ nsRect GetInvalidRegion();
+
+protected:
+ friend class AsyncSVGFrameInit;
+
+
+ // implementation helpers:
+ void DoReflow();
+ void RequestReflow(nsIPresShell::IntrinsicDirty aType);
+
+ // If width or height is less than or equal to zero we must disable rendering
+ bool IsDisabled() const { return mRect.width <= 0 || mRect.height <= 0; }
+
+ nsAutoPtr<gfxMatrix> mCanvasTM;
+
+ bool mInReflow;
+
+ // implementation from nsContainerFrame
+ void BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists,
+ uint32_t aFlags = 0);
+
+ nsFrameList mFrames;
+
+ //nsSVGIFrameForeignObjectFrame* mForeignObject;
+
+ // Show our document viewer. The document viewer is hidden via a script
+ // runner, so that we can save and restore the presentation if we're
+ // being reframed.
+ void ShowViewer();
+
+
+};
+
+#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment