author | Jan de Mooij <jdemooij@mozilla.com> |
Wed, 27 Mar 2013 19:51:50 +0100 | |
changeset 127449 | 6cac55064722597d0292f530678fdb0c21adf650 |
parent 127448 | 8a80ce1f0c2201b3267c866943a1095abfba3d23 (current diff) |
parent 126369 | 5dbcbd03d7ba81c4fb364e23a30b0c2f9805da8e (diff) |
child 127450 | 3fc13eee44b5940c9729ac2d648586cfa1b1a4ce |
push id | 24503 |
push user | jandemooij@gmail.com |
push date | Wed, 03 Apr 2013 15:43:00 +0000 |
treeherder | mozilla-central@b5cb88ccd907 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 22.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/.gdbinit +++ b/.gdbinit @@ -83,17 +83,17 @@ end def pa set $atom = $arg0 if (sizeof(*((&*$atom)->mString)) == 2) pu (&*$atom)->mString end end # define a "pxul" command to display the type of a XUL element from -# an nsXULDocument* pointer. +# an nsXULElement* pointer. def pxul set $p = $arg0 print $p->mNodeInfo.mRawPtr->mInner.mName->mStaticAtom->mString end # define a "prefcnt" command to display the refcount of an XPCOM obj def prefcnt set $p = $arg0
--- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -80,16 +80,17 @@ LOCAL_INCLUDES += \ -I$(srcdir)/../generic \ -I$(srcdir)/../html \ -I$(srcdir)/../xpcom \ -I$(srcdir)/../xul \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/style \ -I$(srcdir)/../../../layout/svg \ -I$(srcdir)/../../../layout/xul/base/src \ + -I$(srcdir)/../../../layout/xul/tree/ \ $(NULL) ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) LOCAL_INCLUDES += \ -I$(srcdir)/../atk \ $(NULL) else ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
--- a/accessible/src/base/nsAccUtils.cpp +++ b/accessible/src/base/nsAccUtils.cpp @@ -131,48 +131,47 @@ nsAccUtils::SetLiveContainerAttributes(n nsIContent *aTopContent) { nsAutoString atomic, live, relevant, busy; nsIContent *ancestor = aStartContent; while (ancestor) { // container-relevant attribute if (relevant.IsEmpty() && - nsAccUtils::HasDefinedARIAToken(ancestor, nsGkAtoms::aria_relevant) && + HasDefinedARIAToken(ancestor, nsGkAtoms::aria_relevant) && ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_relevant, relevant)) SetAccAttr(aAttributes, nsGkAtoms::containerRelevant, relevant); // container-live, and container-live-role attributes if (live.IsEmpty()) { nsRoleMapEntry* role = aria::GetRoleMap(ancestor); - if (nsAccUtils::HasDefinedARIAToken(ancestor, - nsGkAtoms::aria_live)) { + if (HasDefinedARIAToken(ancestor, nsGkAtoms::aria_live)) { ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_live, live); } else if (role) { GetLiveAttrValue(role->liveAttRule, live); } if (!live.IsEmpty()) { SetAccAttr(aAttributes, nsGkAtoms::containerLive, live); if (role) { - nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::containerLiveRole, - role->ARIARoleString()); + SetAccAttr(aAttributes, nsGkAtoms::containerLiveRole, + role->ARIARoleString()); } } } // container-atomic attribute if (atomic.IsEmpty() && - nsAccUtils::HasDefinedARIAToken(ancestor, nsGkAtoms::aria_atomic) && + HasDefinedARIAToken(ancestor, nsGkAtoms::aria_atomic) && ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_atomic, atomic)) SetAccAttr(aAttributes, nsGkAtoms::containerAtomic, atomic); // container-busy attribute if (busy.IsEmpty() && - nsAccUtils::HasDefinedARIAToken(ancestor, nsGkAtoms::aria_busy) && + HasDefinedARIAToken(ancestor, nsGkAtoms::aria_busy) && ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_busy, busy)) SetAccAttr(aAttributes, nsGkAtoms::containerBusy, busy); if (ancestor == aTopContent) break; ancestor = ancestor->GetParent(); if (!ancestor) @@ -193,17 +192,17 @@ nsAccUtils::HasDefinedARIAToken(nsIConte return false; } return true; } nsIAtom* nsAccUtils::GetARIAToken(dom::Element* aElement, nsIAtom* aAttr) { - if (!nsAccUtils::HasDefinedARIAToken(aElement, aAttr)) + if (!HasDefinedARIAToken(aElement, aAttr)) return nsGkAtoms::_empty; static nsIContent::AttrValuesArray tokens[] = { &nsGkAtoms::_false, &nsGkAtoms::_true, &nsGkAtoms::mixed, nullptr}; int32_t idx = aElement->FindAttrValueIn(kNameSpaceID_None, aAttr, tokens, eCaseMatters);
--- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -52,16 +52,19 @@ #include "nsIDOMHTMLObjectElement.h" #include "nsIDOMXULElement.h" #include "nsImageFrame.h" #include "nsIObserverService.h" #include "nsLayoutUtils.h" #include "nsNPAPIPluginInstance.h" #include "nsObjectFrame.h" #include "nsSVGPathGeometryFrame.h" +#include "nsTreeBodyFrame.h" +#include "nsTreeColumns.h" +#include "nsTreeUtils.h" #include "mozilla/dom/Element.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" #include "mozilla/Util.h" #include "nsDeckFrame.h" #ifdef MOZ_XUL #include "XULAlertAccessible.h" @@ -1567,37 +1570,38 @@ NS_GetAccessibilityService(nsIAccessibil //////////////////////////////////////////////////////////////////////////////// // nsAccessibilityService private (DON'T put methods here) #ifdef MOZ_XUL already_AddRefed<Accessible> nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent, DocAccessible* aDoc) { - nsCOMPtr<nsITreeBoxObject> treeBoxObj = nsCoreUtils::GetTreeBoxObject(aContent); - if (!treeBoxObj) + nsIContent* child = nsTreeUtils::GetDescendantChild(aContent, + nsGkAtoms::treechildren); + if (!child) return nullptr; - nsCOMPtr<nsITreeColumns> treeColumns; - treeBoxObj->GetColumns(getter_AddRefs(treeColumns)); - if (!treeColumns) + nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame()); + if (!treeFrame) return nullptr; + nsRefPtr<nsTreeColumns> treeCols = treeFrame->Columns(); int32_t count = 0; - treeColumns->GetCount(&count); + treeCols->GetCount(&count); // Outline of list accessible. if (count == 1) { - Accessible* accessible = new XULTreeAccessible(aContent, aDoc); + Accessible* accessible = new XULTreeAccessible(aContent, aDoc, treeFrame); NS_ADDREF(accessible); return accessible; } // Table or tree table accessible. - Accessible* accessible = new XULTreeGridAccessibleWrap(aContent, aDoc); + Accessible* accessible = new XULTreeGridAccessibleWrap(aContent, aDoc, treeFrame); NS_ADDREF(accessible); return accessible; } #endif //////////////////////////////////////////////////////////////////////////////// // Services ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/windows/msaa/XULTreeGridAccessibleWrap.h +++ b/accessible/src/windows/msaa/XULTreeGridAccessibleWrap.h @@ -17,18 +17,19 @@ namespace a11y { /** * IA2 wrapper class for XULTreeGridAccessible class implementing * IAccessibleTable and IAccessibleTable2 interfaces. */ class XULTreeGridAccessibleWrap : public XULTreeGridAccessible, public ia2AccessibleTable { public: - XULTreeGridAccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) : - XULTreeGridAccessible(aContent, aDoc), ia2AccessibleTable(this) {} + XULTreeGridAccessibleWrap(nsIContent* aContent, DocAccessible* aDoc, + nsTreeBodyFrame* aTree) : + XULTreeGridAccessible(aContent, aDoc, aTree), ia2AccessibleTable(this) {} // IUnknown DECL_IUNKNOWN_INHERITED // nsISupports NS_DECL_ISUPPORTS_INHERITED virtual void Shutdown() MOZ_OVERRIDE;
--- a/accessible/src/xul/Makefile.in +++ b/accessible/src/xul/Makefile.in @@ -38,16 +38,17 @@ include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES = \ -I$(srcdir) \ -I$(srcdir)/../base \ -I$(srcdir)/../generic \ -I$(srcdir)/../html \ -I$(srcdir)/../xpcom \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/xul/base/src \ + -I$(srcdir)/../../../layout/xul/tree// \ $(NULL) ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) LOCAL_INCLUDES += \ -I$(srcdir)/../atk \ $(NULL) else ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
--- a/accessible/src/xul/XULTreeAccessible.cpp +++ b/accessible/src/xul/XULTreeAccessible.cpp @@ -22,39 +22,40 @@ #include "nsIAutoCompleteInput.h" #include "nsIAutoCompletePopup.h" #include "nsIDOMXULElement.h" #include "nsIDOMXULMenuListElement.h" #include "nsIDOMXULMultSelectCntrlEl.h" #include "nsIDOMXULTreeElement.h" #include "nsITreeSelection.h" #include "nsIMutableArray.h" +#include "nsTreeBodyFrame.h" +#include "nsTreeColumns.h" +#include "nsTreeUtils.h" using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// // XULTreeAccessible //////////////////////////////////////////////////////////////////////////////// XULTreeAccessible:: - XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc) : + XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc, + nsTreeBodyFrame* aTreeFrame) : AccessibleWrap(aContent, aDoc) { mType = eXULTreeType; mGenericTypes |= eSelect; + nsCOMPtr<nsITreeView> view = aTreeFrame->GetExistingView(); + mTreeView = view; + mTree = nsCoreUtils::GetTreeBoxObject(aContent); NS_ASSERTION(mTree, "Can't get mTree!\n"); - if (mTree) { - nsCOMPtr<nsITreeView> treeView; - mTree->GetView(getter_AddRefs(treeView)); - mTreeView = treeView; - } - nsIContent* parentContent = mContent->GetParent(); if (parentContent) { nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = do_QueryInterface(parentContent); if (autoCompletePopupElm) mGenericTypes |= eAutoCompletePopup; } @@ -154,21 +155,26 @@ XULTreeAccessible::Shutdown() // XULTreeAccessible: Accessible implementation (put methods here) role XULTreeAccessible::NativeRole() { // No primary column means we're in a list. In fact, history and mail turn off // the primary flag when switching to a flat view. - nsCOMPtr<nsITreeColumns> cols; - mTree->GetColumns(getter_AddRefs(cols)); + nsIContent* child = nsTreeUtils::GetDescendantChild(mContent, nsGkAtoms::treechildren); + NS_ASSERTION(child, "tree without treechildren!"); + nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame()); + NS_ASSERTION(treeFrame, "xul tree accessible for tree without a frame!"); + if (!treeFrame) + return roles::LIST; + + nsRefPtr<nsTreeColumns> cols = treeFrame->Columns(); nsCOMPtr<nsITreeColumn> primaryCol; - if (cols) - cols->GetPrimaryColumn(getter_AddRefs(primaryCol)); + cols->GetPrimaryColumn(getter_AddRefs(primaryCol)); return primaryCol ? roles::OUTLINE : roles::LIST; } //////////////////////////////////////////////////////////////////////////////// // XULTreeAccessible: Accessible implementation (DON'T put methods here) Accessible*
--- a/accessible/src/xul/XULTreeAccessible.h +++ b/accessible/src/xul/XULTreeAccessible.h @@ -6,16 +6,18 @@ #ifndef mozilla_a11y_XULTreeAccessible_h__ #define mozilla_a11y_XULTreeAccessible_h__ #include "nsITreeBoxObject.h" #include "nsITreeView.h" #include "nsITreeColumns.h" #include "XULListboxAccessible.h" +class nsTreeBodyFrame; + namespace mozilla { namespace a11y { /* * A class the represents the XUL Tree widget. */ const uint32_t kMaxTreeColumns = 100; const uint32_t kDefaultTreeCacheSize = 256; @@ -24,17 +26,18 @@ const uint32_t kDefaultTreeCacheSize = 2 * Accessible class for XUL tree element. */ class XULTreeAccessible : public AccessibleWrap { public: using Accessible::GetChildAt; - XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc); + XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc, + nsTreeBodyFrame* aTreeframe); // nsISupports and cycle collection NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULTreeAccessible, Accessible) // nsAccessNode virtual void Shutdown();
--- a/accessible/src/xul/XULTreeGridAccessible.cpp +++ b/accessible/src/xul/XULTreeGridAccessible.cpp @@ -16,27 +16,16 @@ #include "nsIMutableArray.h" #include "nsITreeSelection.h" #include "nsComponentManagerUtils.h" using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// -// XULTreeGridAccessible -//////////////////////////////////////////////////////////////////////////////// - -XULTreeGridAccessible:: - XULTreeGridAccessible(nsIContent* aContent, DocAccessible* aDoc) : - XULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this) -{ - mGenericTypes |= eTable; -} - -//////////////////////////////////////////////////////////////////////////////// // XULTreeGridAccessible: nsISupports implementation NS_IMPL_ISUPPORTS_INHERITED1(XULTreeGridAccessible, XULTreeAccessible, nsIAccessibleTable) //////////////////////////////////////////////////////////////////////////////// // XULTreeGridAccessible: nsIAccessibleTable implementation
--- a/accessible/src/xul/XULTreeGridAccessible.h +++ b/accessible/src/xul/XULTreeGridAccessible.h @@ -19,17 +19,20 @@ namespace a11y { * Represents accessible for XUL tree in the case when it has multiple columns. */ class XULTreeGridAccessible : public XULTreeAccessible, public xpcAccessibleTable, public nsIAccessibleTable, public TableAccessible { public: - XULTreeGridAccessible(nsIContent* aContent, DocAccessible* aDoc); + XULTreeGridAccessible(nsIContent* aContent, DocAccessible* aDoc, + nsTreeBodyFrame* aTreeFrame) : + XULTreeAccessible(aContent, aDoc, aTreeFrame), xpcAccessibleTable(this) + { mGenericTypes |= eTable; } // nsISupports NS_DECL_ISUPPORTS_INHERITED // nsIAccessibleTable NS_FORWARD_NSIACCESSIBLETABLE(xpcAccessibleTable::) // TableAccessible
--- a/accessible/tests/mochitest/events/test_focus_autocomplete.xul +++ b/accessible/tests/mochitest/events/test_focus_autocomplete.xul @@ -27,19 +27,16 @@ <script type="application/javascript" src="../events.js" /> <script type="application/javascript" src="../autocomplete.js" /> <script type="application/javascript"> <![CDATA[ - if (!navigator.platform.startsWith("Mac")) { - SimpleTest.expectAssertions(2); - } //////////////////////////////////////////////////////////////////////////// // Hacky stuffs // This is the hack needed for searchbar work outside of browser. function getBrowser() { return { mCurrentBrowser: { engines: new Array() }
--- a/accessible/tests/mochitest/text/test_multiline.html +++ b/accessible/tests/mochitest/text/test_multiline.html @@ -61,19 +61,19 @@ testTextAfterOffset(0, BOUNDARY_WORD_START, "two ", 9, 13, "div", kTodo, kTodo, kTodo, "divbr", kTodo, kTodo, kTodo, "editable", kTodo, kTodo, kTodo, "editablebr", kTodo, kTodo, kTodo, "textarea", kTodo, kTodo, kTodo); testTextAfterOffset(8, BOUNDARY_WORD_START, "two ", 9, 13, "div", kTodo, kTodo, kTodo, - "divbr", kTodo, kTodo, kTodo, + "divbr", kTodo, kTodo, kOk, "editable", kTodo, kTodo, kTodo, - "editablebr", kTodo, kTodo, kTodo, + "editablebr", kTodo, kTodo, kOk, "textarea", kTodo, kTodo, kTodo); testTextAfterOffset(9, BOUNDARY_WORD_START, "words\n", 13, 19, "div", kTodo, kTodo, kTodo, "divbr", kTodo, kTodo, kTodo, "editable", kTodo, kTodo, kTodo, "editablebr", kTodo, kTodo, kTodo, "textarea", kTodo, kTodo, kTodo); @@ -379,22 +379,17 @@ testTextAtOffset(9, BOUNDARY_CHAR, "t", 9, 10, "div", kOk, kOk, kOk, "divbr", kOk, kOk, kOk, "editable", kOk, kOk, kOk, "editablebr", kOk, kOk, kOk, "textarea", kOk, kOk, kOk); // BOUNDARY_WORD_START - testTextAtOffset(0, BOUNDARY_WORD_START, "oneword\n\n", 0, 9, - "div", kTodo, kOk, kTodo, - "divbr", kOk, kOk, kOk, - "editable", kTodo, kOk, kTodo, - "editablebr", kOk, kOk, kOk, - "textarea", kTodo, kOk, kTodo); + testTextAtOffset(0, BOUNDARY_WORD_START, "oneword\n\n", 0, 9, IDs); testTextAtOffset(8, BOUNDARY_WORD_START, "oneword\n\n", 0, 9, "div", kOk, kOk, kOk, "divbr", kTodo, kTodo, kTodo, "editable", kOk, kOk, kOk, "editablebr", kTodo, kTodo, kTodo, "textarea", kOk, kOk, kOk); testTextAtOffset(9, BOUNDARY_WORD_START, "two ", 9, 13, IDs); testTextAtOffset(13, BOUNDARY_WORD_START, "words\n", 13, 19, IDs); @@ -408,27 +403,22 @@ "textarea", kTodo, kOk, kTodo); testTextAtOffset(8, BOUNDARY_WORD_END, "\n\ntwo", 7, 12, "div", kOk, kOk, kOk, "divbr", kTodo, kTodo, kTodo, "editable", kOk, kOk, kOk, "editablebr", kTodo, kTodo, kTodo, "textarea", kOk, kOk, kOk); testTextAtOffset(9, BOUNDARY_WORD_END, "\n\ntwo", 7, 12, - "div", kTodo, kTodo, kOk, + "div", kOk, kOk, kOk, "divbr", kTodo, kTodo, kTodo, - "editable", kTodo, kTodo, kOk, + "editable", kOk, kOk, kOk, "editablebr", kTodo, kTodo, kTodo, - "textarea", kTodo, kTodo, kOk); - testTextAtOffset(12, BOUNDARY_WORD_END, "\n\ntwo", 7, 12, - "div", kTodo, kTodo, kOk, - "divbr", kOk, kOk, kOk, - "editable", kTodo, kTodo, kOk, - "editablebr", kOk, kOk, kOk, - "textarea", kTodo, kTodo, kOk); + "textarea", kOk, kOk, kOk); + testTextAtOffset(12, BOUNDARY_WORD_END, "\n\ntwo", 7, 12, IDs); testTextAtOffset(13, BOUNDARY_WORD_END, " words", 12, 18, "div", kOk, kOk, kOk, "divbr", kOk, kOk, kOk, "editable", kOk, kOk, kOk, "editablebr", kOk, kOk, kOk, "textarea", kOk, kOk, kOk); // BOUNDARY_LINE_START
--- a/accessible/tests/mochitest/tree/test_txtctrl.xul +++ b/accessible/tests/mochitest/tree/test_txtctrl.xul @@ -13,21 +13,16 @@ src="../common.js" /> <script type="application/javascript" src="../role.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> <![CDATA[ - if (navigator.platform.startsWith("Mac")) { - SimpleTest.expectAssertions(0, 1); - } else { - SimpleTest.expectAssertions(1); - } //////////////////////////////////////////////////////////////////////////// // Test function doTest() { //////////////////// // textbox ////////////////////
--- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -49,17 +49,16 @@ #ifndef MOZ_STATIC_JS @BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@ #endif #ifndef MOZ_FOLD_LIBS @BINPATH@/@DLL_PREFIX@plc4@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@ #endif -@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@ #ifdef MOZ_DMD @BINPATH@/@DLL_PREFIX@dmd@DLL_SUFFIX@ #endif #ifdef XP_MACOSX @BINPATH@/XUL #else @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@ @@ -197,16 +196,17 @@ @BINPATH@/components/dom_payment.xpt @BINPATH@/components/dom_json.xpt #ifdef MOZ_B2G_RIL @BINPATH@/components/dom_mms.xpt #endif @BINPATH@/components/dom_browserelement.xpt @BINPATH@/components/dom_messages.xpt @BINPATH@/components/dom_power.xpt +@BINPATH@/components/dom_quota.xpt @BINPATH@/components/dom_range.xpt @BINPATH@/components/dom_settings.xpt @BINPATH@/components/dom_permissionsettings.xpt @BINPATH@/components/dom_sidebar.xpt @BINPATH@/components/dom_mobilemessage.xpt @BINPATH@/components/dom_storage.xpt @BINPATH@/components/dom_stylesheets.xpt @BINPATH@/components/dom_threads.xpt
--- a/b2g/installer/removed-files.in +++ b/b2g/installer/removed-files.in @@ -15,8 +15,9 @@ components/dom_sms.xpt @DLL_PREFIX@nspr4@DLL_SUFFIX@ @DLL_PREFIX@plds4@DLL_SUFFIX@ @DLL_PREFIX@plc4@DLL_SUFFIX@ @DLL_PREFIX@ssl3@DLL_SUFFIX@ @DLL_PREFIX@smime3@DLL_SUFFIX@ @DLL_PREFIX@nssutil3@DLL_SUFFIX@ @DLL_PREFIX@mozsqlite3@DLL_SUFFIX@ #endif +@DLL_PREFIX@xpcom@DLL_SUFFIX@
--- a/browser/base/content/browser-social.js +++ b/browser/base/content/browser-social.js @@ -1,20 +1,31 @@ // 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 "exported" symbols +let SocialUI, + SocialChatBar, + SocialFlyout, + SocialShareButton, + SocialMenu, + SocialToolbar, + SocialSidebar; + +(function() { + // The minimum sizes for the auto-resize panel code. const PANEL_MIN_HEIGHT = 100; const PANEL_MIN_WIDTH = 330; XPCOMUtils.defineLazyModuleGetter(this, "SharedFrame", "resource:///modules/SharedFrame.jsm"); -let SocialUI = { +SocialUI = { // Called on delayed startup to initialize the UI init: function SocialUI_init() { Services.obs.addObserver(this, "social:ambient-notification-changed", false); Services.obs.addObserver(this, "social:profile-changed", false); Services.obs.addObserver(this, "social:recommend-info-changed", false); Services.obs.addObserver(this, "social:frameworker-error", false); Services.obs.addObserver(this, "social:provider-set", false); Services.obs.addObserver(this, "social:providers-changed", false); @@ -335,17 +346,17 @@ let SocialUI = { // Returns whether social is enabled *for this window*. if (this._chromeless || PrivateBrowsingUtils.isWindowPrivate(window)) return false; return !!Social.provider; }, } -let SocialChatBar = { +SocialChatBar = { init: function() { }, get chatbar() { return document.getElementById("pinnedchats"); }, // Whether the chatbar is available for this window. Note that in full-screen // mode chats are available, but not shown. get isAvailable() { @@ -432,17 +443,17 @@ DynamicResizeWatcher.prototype = { // may get "TypeError: can't access dead object" which seems strange, // but doesn't seem to indicate a real problem, so ignore it... } this._mutationObserver = null; } } } -let SocialFlyout = { +SocialFlyout = { get panel() { return document.getElementById("social-flyout-panel"); }, dispatchPanelEvent: function(name) { let doc = this.panel.firstChild.contentDocument; let evt = doc.createEvent("CustomEvent"); evt.initCustomEvent(name, true, true, {}); @@ -564,17 +575,17 @@ let SocialFlyout = { // that the docShell of this frame is created panel.firstChild.clientTop; Social.setErrorListener(iframe, this.setFlyoutErrorMessage.bind(this)) } this.yOffset = yOffset; } } -let SocialShareButton = { +SocialShareButton = { // Called once, after window load, when the Social.provider object is initialized init: function SSB_init() { }, // Called when the Social.provider changes update: function() { this._updateButtonHiddenState(); let profileRow = document.getElementById("unsharePopupHeader"); @@ -707,17 +718,17 @@ let SocialShareButton = { shareButton.removeAttribute("shared"); shareButton.setAttribute("tooltiptext", recommendInfo.messages.shareTooltip); imageURL = recommendInfo.images.share; } shareButton.src = imageURL; } }; -var SocialMenu = { +SocialMenu = { init: function SocialMenu_init() { }, populate: function SocialMenu_populate() { let submenu = document.getElementById("menu_social-statusarea-popup"); let ambientMenuItems = submenu.getElementsByClassName("ambient-menuitem"); while (ambientMenuItems.length) submenu.removeChild(ambientMenuItems.item(0)); @@ -741,17 +752,17 @@ var SocialMenu = { openUILinkIn(icon.menuURL, "tab"); }, false); submenu.insertBefore(menuitem, separator); } } }; // XXX Need to audit that this is being initialized correctly -var SocialToolbar = { +SocialToolbar = { // Called once, after window load, when the Social.provider object is // initialized. init: function SocialToolbar_init() { this._dynamicResizer = new DynamicResizeWatcher(); }, update: function() { this._updateButtonHiddenState(); @@ -1082,17 +1093,17 @@ var SocialToolbar = { menuitem.setAttribute("oncommand", "Social.setProviderByOrigin(this.getAttribute('origin'));"); } menu.insertBefore(menuitem, providerMenuSep); } providerMenuSep.hidden = false; } } -var SocialSidebar = { +SocialSidebar = { // Called once, after window load, when the Social.provider object is initialized init: function SocialSidebar_init() { let sbrowser = document.getElementById("social-sidebar-browser"); Social.setErrorListener(sbrowser, this.setSidebarErrorMessage.bind(this)); // setting isAppTab causes clicks on untargeted links to open new tabs sbrowser.docShell.isAppTab = true; }, @@ -1189,8 +1200,10 @@ var SocialSidebar = { if (Social.provider.errorState == "frameworker-error") { sbrowser.setAttribute("src", "about:socialerror?mode=workerFailure"); } else { let url = encodeURIComponent(Social.provider.sidebarURL); sbrowser.loadURI("about:socialerror?mode=tryAgain&url=" + url, null, null); } } } + +})();
--- a/browser/base/content/newtab/sites.js +++ b/browser/base/content/newtab/sites.js @@ -139,17 +139,17 @@ Site.prototype = { /** * Adds event handlers for the site and its buttons. */ _addEventHandlers: function Site_addEventHandlers() { // Register drag-and-drop event handlers. this._node.addEventListener("dragstart", this, false); this._node.addEventListener("dragend", this, false); - this._node.addEventListener("mouseenter", this, false); + this._node.addEventListener("mouseover", this, false); let controls = this.node.querySelectorAll(".newtab-control"); for (let i = 0; i < controls.length; i++) controls[i].addEventListener("click", this, false); }, /** * Speculatively opens a connection to the current site. @@ -169,17 +169,18 @@ Site.prototype = { aEvent.preventDefault(); if (aEvent.target.classList.contains("newtab-control-block")) this.block(); else if (this.isPinned()) this.unpin(); else this.pin(); break; - case "mouseenter": + case "mouseover": + this._node.removeEventListener("mouseover", this, false); this._speculativeConnect(); break; case "dragstart": gDrag.start(this, aEvent); break; case "drag": gDrag.drag(this, aEvent); break;
--- a/browser/base/content/pageinfo/permissions.js +++ b/browser/base/content/pageinfo/permissions.js @@ -2,21 +2,21 @@ * 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/. */ const UNKNOWN = nsIPermissionManager.UNKNOWN_ACTION; // 0 const ALLOW = nsIPermissionManager.ALLOW_ACTION; // 1 const BLOCK = nsIPermissionManager.DENY_ACTION; // 2 const SESSION = nsICookiePermission.ACCESS_SESSION; // 8 -const nsIIndexedDatabaseManager = - Components.interfaces.nsIIndexedDatabaseManager; +const nsIQuotaManager = Components.interfaces.nsIQuotaManager; var gPermURI; var gPrefs; +var gUsageRequest; var gPermObj = { image: function getImageDefaultPermission() { if (gPrefs.getIntPref("permissions.default.image") == 2) return BLOCK; return ALLOW; }, @@ -111,19 +111,20 @@ function onLoadPermission() } function onUnloadPermission() { var os = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService); os.removeObserver(permissionObserver, "perm-changed"); - var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"] - .getService(nsIIndexedDatabaseManager); - dbManager.cancelGetUsageForURI(gPermURI, onIndexedDBUsageCallback); + if (gUsageRequest) { + gUsageRequest.cancel(); + gUsageRequest = null; + } } function initRow(aPartId) { if (aPartId == "plugins") { initPluginsRow(); return; } @@ -200,33 +201,34 @@ function onRadioClick(aPartId) function setRadioState(aPartId, aValue) { var radio = document.getElementById(aPartId + "#" + aValue); radio.radioGroup.selectedItem = radio; } function initIndexedDBRow() { - var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"] - .getService(nsIIndexedDatabaseManager); - dbManager.getUsageForURI(gPermURI, onIndexedDBUsageCallback); + var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"] + .getService(nsIQuotaManager); + gUsageRequest = + quotaManager.getUsageForURI(gPermURI, onIndexedDBUsageCallback); var status = document.getElementById("indexedDBStatus"); var button = document.getElementById("indexedDBClear"); status.value = ""; status.setAttribute("hidden", "true"); button.setAttribute("hidden", "true"); } function onIndexedDBClear() { - Components.classes["@mozilla.org/dom/indexeddb/manager;1"] - .getService(nsIIndexedDatabaseManager) - .clearDatabasesForURI(gPermURI); + Components.classes["@mozilla.org/dom/quota/manager;1"] + .getService(nsIQuotaManager) + .clearStoragesForURI(gPermURI); var permissionManager = Components.classes[PERMISSION_CONTRACTID] .getService(nsIPermissionManager); permissionManager.remove(gPermURI.host, "indexedDB-unlimited"); initIndexedDBRow(); } function onIndexedDBUsageCallback(uri, usage, fileUsage)
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -443,22 +443,38 @@ delete this.mTabBrowser; }, _callProgressListeners: function () { Array.unshift(arguments, this.mBrowser); return this.mTabBrowser._callProgressListeners.apply(this.mTabBrowser, arguments); }, + _shouldShowProgress: function (aRequest) { + if (this.mBlank) + return false; + + // Don't show progress indicators in tabs for about: URIs + // pointing to local resources. + try { + let channel = aRequest.QueryInterface(Ci.nsIChannel); + if (channel.originalURI.schemeIs("about") && + (channel.URI.schemeIs("jar") || channel.URI.schemeIs("file"))) + return false; + } catch (e) {} + + return true; + }, + onProgressChange: function (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) { this.mTotalProgress = aMaxTotalProgress ? aCurTotalProgress / aMaxTotalProgress : 0; - if (this.mBlank) + if (!this._shouldShowProgress(aRequest)) return; if (this.mTotalProgress) this.mTab.setAttribute("progress", "true"); this._callProgressListeners("onProgressChange", [aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, @@ -505,17 +521,17 @@ // onLocationChange, this counter gets decremented // (so we keep it while switching tabs after failed loads) // We need to add 2 because loadURIWithFlags may have // cancelled a pending load which would have cleared // its anchor scroll detection temporary increment. if (aWebProgress.DOMWindow == this.mBrowser.contentWindow) this.mBrowser.userTypedClear += 2; - if (!this.mBlank) { + if (this._shouldShowProgress(aRequest)) { if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) { this.mTab.setAttribute("busy", "true"); if (!(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_RELOAD)) this.mTabBrowser.setTabTitleLoading(this.mTab); } if (this.mTab.selected) this.mTabBrowser.mIsBusy = true; @@ -689,19 +705,25 @@ aURI = makeURI(aURI); this.mFaviconService.setAndFetchFaviconForPage(browser.currentURI, aURI, false, PrivateBrowsingUtils.isWindowPrivate(window) ? this.mFaviconService.FAVICON_LOAD_PRIVATE : this.mFaviconService.FAVICON_LOAD_NON_PRIVATE); } - if ((browser.mIconURL || "") != aTab.getAttribute("image")) { - if (browser.mIconURL) - aTab.setAttribute("image", browser.mIconURL); + let sizedIconUrl = browser.mIconURL || ""; + if (sizedIconUrl) { + let size = Math.round(16 * window.devicePixelRatio); + sizedIconUrl += (sizedIconUrl.contains("#") ? "&" : "#") + + "-moz-resolution=" + size + "," + size; + } + if (sizedIconUrl != aTab.getAttribute("image")) { + if (sizedIconUrl) + aTab.setAttribute("image", sizedIconUrl); else aTab.removeAttribute("image"); this._tabAttrModified(aTab); } this._callProgressListeners(browser, "onLinkIconAvailable", [browser.mIconURL]); ]]> </body>
--- a/browser/base/content/test/browser_aboutHome.js +++ b/browser/base/content/test/browser_aboutHome.js @@ -26,17 +26,18 @@ let gTests = [ setup: function () { Cc["@mozilla.org/dom/storagemanager;1"] .getService(Ci.nsIObserver) .observe(null, "cookie-changed", "cleared"); }, run: function (aSnippetsMap) { - isnot(aSnippetsMap.get("snippets-last-update"), null); + isnot(aSnippetsMap.get("snippets-last-update"), null, + "snippets-last-update should have a value"); } }, { desc: "Check default snippets are shown", setup: function () { }, run: function () { @@ -111,17 +112,17 @@ let gTests = [ desc: "Check that performing a search records to Firefox Health Report.", setup: function () { }, run: function () { try { let cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); cm.getCategoryEntry("healthreport-js-provider", "SearchesProvider"); } catch (ex) { // Health Report disabled, or no SearchesProvider. - return; + return Promise.resolve(); } let deferred = Promise.defer(); let doc = gBrowser.contentDocument; // We rely on the listener in browser.js being installed and fired before // this one. If this ever changes, we should add an executeSoon() or similar. doc.addEventListener("AboutHomeSearchEvent", function onSearch(e) { @@ -215,19 +216,19 @@ function test() // can't guess the order they will happen. // So, start listening now, but verify the promise is fulfilled only // after the snippets map setup. let promise = promiseBrowserAttributes(tab); // Prepare the snippets map with default values, then run the test setup. let snippetsMap = yield promiseSetupSnippetsMap(tab, test.setup); // Ensure browser has set attributes already, or wait for them. yield promise; - + info("Running test"); yield test.run(snippetsMap); - + info("Cleanup"); gBrowser.removeCurrentTab(); } finish(); }); } /** @@ -238,18 +239,20 @@ function test() * @param aEvent * The load event type to wait for. Defaults to "load". * @return {Promise} resolved when the event is handled. Gets the new tab. */ function promiseNewTabLoadEvent(aUrl, aEventType="load") { let deferred = Promise.defer(); let tab = gBrowser.selectedTab = gBrowser.addTab(aUrl); + info("Wait tab event: " + aEventType); tab.linkedBrowser.addEventListener(aEventType, function load(event) { tab.linkedBrowser.removeEventListener(aEventType, load, true); + info("Tab event received: " + aEventType); deferred.resolve(tab); }, true); return deferred.promise; } /** * Cleans up snippets and ensures that by default we don't try to check for * remote snippets since that may cause network bustage or slowness. @@ -259,17 +262,22 @@ function promiseNewTabLoadEvent(aUrl, aE * @param aSetupFn * The setup function to be run. * @return {Promise} resolved when the snippets are ready. Gets the snippets map. */ function promiseSetupSnippetsMap(aTab, aSetupFn) { let deferred = Promise.defer(); let cw = aTab.linkedBrowser.contentWindow.wrappedJSObject; + info("Waiting for snippets map"); cw.ensureSnippetsMapThen(function (aSnippetsMap) { + info("Got snippets map: " + + "{ last-update: " + aSnippetsMap.get("snippets-last-update") + + ", cached-version: " + aSnippetsMap.get("snippets-cached-version") + + " }"); // Don't try to update. aSnippetsMap.set("snippets-last-update", Date.now()); aSnippetsMap.set("snippets-cached-version", AboutHomeUtils.snippetsVersion); // Clear snippets. aSnippetsMap.delete("snippets"); aSetupFn(aSnippetsMap); // Must be sure to continue after the page snippets map setup. executeSoon(function() deferred.resolve(aSnippetsMap)); @@ -288,26 +296,30 @@ function promiseSetupSnippetsMap(aTab, a function promiseBrowserAttributes(aTab) { let deferred = Promise.defer(); let docElt = aTab.linkedBrowser.contentDocument.documentElement; //docElt.setAttribute("snippetsURL", "nonexistent://test"); let observer = new MutationObserver(function (mutations) { for (let mutation of mutations) { + info("Got attribute mutation: " + mutation.attributeName + + " from " + mutation.oldValue); if (mutation.attributeName == "snippetsURL" && docElt.getAttribute("snippetsURL") != "nonexistent://test") { docElt.setAttribute("snippetsURL", "nonexistent://test"); } // Now we just have to wait for the last attribute. if (mutation.attributeName == "searchEngineURL") { + info("Remove attributes observer"); observer.disconnect(); // Must be sure to continue after the page mutation observer. executeSoon(function() deferred.resolve()); break; } } }); + info("Add attributes observer"); observer.observe(docElt, { attributes: true }); return deferred.promise; }
--- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -1393,17 +1393,17 @@ BrowserGlue.prototype = { else this._dataSource.Unassert(aSource, aProperty, oldTarget); } else { this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true); } // Add the entry to the persisted set for this document if it's not there. - // This code is mostly borrowed from nsXULDocument::Persist. + // This code is mostly borrowed from XULDocument::Persist. let docURL = aSource.ValueUTF8.split("#")[0]; let docResource = this._rdf.GetResource(docURL); let persistResource = this._rdf.GetResource("http://home.netscape.com/NC-rdf#persist"); if (!this._dataSource.HasAssertion(docResource, persistResource, aSource, true)) { this._dataSource.Assert(docResource, persistResource, aSource, true); } } catch(ex) {}
--- a/browser/components/places/tests/browser/browser_toolbar_migration.js +++ b/browser/components/places/tests/browser/browser_toolbar_migration.js @@ -14,17 +14,17 @@ let localStore = { get RDF() Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService), get store() this.RDF.GetDataSource("rdf:local-store"), get toolbar() { delete this.toolbar; let toolbar = this.RDF.GetResource(BROWSER_URL + "#PersonalToolbar"); // Add the entry to the persisted set for this document if it's not there. - // See nsXULDocument::Persist. + // See XULDocument::Persist. let doc = this.RDF.GetResource(BROWSER_URL); let persist = this.RDF.GetResource("http://home.netscape.com/NC-rdf#persist"); if (!this.store.HasAssertion(doc, persist, toolbar, true)) { this.store.Assert(doc, persist, toolbar, true); } return this.toolbar = toolbar; },
--- a/browser/config/tooltool-manifests/linux32/clang.manifest +++ b/browser/config/tooltool-manifests/linux32/clang.manifest @@ -1,17 +1,17 @@ [ { "clang_version": "r170890" -}, +}, { -"size": 47, -"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", -"algorithm": "sha512", -"filename": "setup.sh" -}, +"filename": "setup.sh", +"algorithm": "sha512", +"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", +"size": 47 +}, { -"size": 61878284, -"digest": "a3f924e7a6d8651b3466f3dc4625eaa00f90ee6cc824ddd4da7a27ce26916220615c1aa33e4a286b757b9283c536b8311edddf469d23e9e1306b90dff19ae11f", -"algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"algorithm": "sha512", +"digest": "0bcfc19f05cc0f042befb3823c7ecce9ba411b152921aa29e97e7adc846e0258fd7da521b1620cb1e61a19d2fcac9b60e6d613c922b6c153e01b9b0766651d09", +"size": 62708281 } ]
--- a/browser/config/tooltool-manifests/linux64/clang.manifest +++ b/browser/config/tooltool-manifests/linux64/clang.manifest @@ -1,17 +1,17 @@ [ { "clang_version": "r170890" }, { -"size": 47, +"filename": "setup.sh", +"algorithm": "sha512", "digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", -"algorithm": "sha512", -"filename": "setup.sh" +"size": 47 }, { -"size": 62279506, -"digest": "aa886361161a7d32aad71dfe5fd6b6cdff25610d8e32153a80caea66a8475aa8526d8529d8ac26e8ac26bd32878ee0df6d8dbef95dfd9faacec45b4ab918d52d", +"filename": "clang.tar.bz2", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"digest": "e14ccefd965372a57c540647b2b99e21a4aa82f81a8b9a9e18dac7cba4c3436181bef0dfab8c51bcb5c343f504a693fdcfbe7d609f10291b5dd65ab059979d29", +"size": 63034761 } ]
--- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -64,17 +64,16 @@ #endif #ifndef MOZ_NATIVE_NSPR #ifndef MOZ_FOLD_LIBS @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@plc4@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@ #endif #endif -@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@ #ifdef XP_MACOSX @BINPATH@/XUL #else @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@ #endif #ifdef XP_MACOSX @BINPATH@/@MOZ_CHILD_PROCESS_NAME@.app/ @BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@ @@ -198,16 +197,17 @@ @BINPATH@/components/dom_indexeddb.xpt @BINPATH@/components/dom_offline.xpt @BINPATH@/components/dom_json.xpt #ifdef MOZ_B2G_RIL @BINPATH@/components/dom_mms.xpt #endif @BINPATH@/components/dom_browserelement.xpt @BINPATH@/components/dom_power.xpt +@BINPATH@/components/dom_quota.xpt @BINPATH@/components/dom_range.xpt @BINPATH@/components/dom_settings.xpt @BINPATH@/components/dom_permissionsettings.xpt @BINPATH@/components/dom_sidebar.xpt @BINPATH@/components/dom_mobilemessage.xpt @BINPATH@/components/dom_storage.xpt @BINPATH@/components/dom_stylesheets.xpt @BINPATH@/components/dom_traversal.xpt
--- a/browser/installer/removed-files.in +++ b/browser/installer/removed-files.in @@ -21,16 +21,17 @@ @DLL_PREFIX@nspr4@DLL_SUFFIX@ @DLL_PREFIX@plds4@DLL_SUFFIX@ @DLL_PREFIX@plc4@DLL_SUFFIX@ @DLL_PREFIX@ssl3@DLL_SUFFIX@ @DLL_PREFIX@smime3@DLL_SUFFIX@ @DLL_PREFIX@nssutil3@DLL_SUFFIX@ @DLL_PREFIX@mozsqlite3@DLL_SUFFIX@ #endif +@DLL_PREFIX@xpcom@DLL_SUFFIX@ LICENSE browserconfig.properties chrome/US.jar chrome/app-chrome.manifest chrome/browser.manifest chrome/chrome.rdf chrome/chromelist.txt chrome/classic.jar
--- a/browser/metro/base/content/browser-scripts.js +++ b/browser/metro/base/content/browser-scripts.js @@ -20,16 +20,22 @@ XPCOMUtils.defineLazyModuleGetter(this, "resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PdfJs", "resource://pdf.js/PdfJs.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils", "resource://gre/modules/DownloadUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Promise", + "resource://gre/modules/commonjs/sdk/core/promise.js"); + +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); + /* * Services */ #ifdef XP_WIN XPCOMUtils.defineLazyServiceGetter(this, "MetroUtils", "@mozilla.org/windows-metroutils;1", "nsIWinMetroUtils");
--- a/browser/metro/base/content/browser-ui.js +++ b/browser/metro/base/content/browser-ui.js @@ -273,27 +273,29 @@ var BrowserUI = { // Make sure we're online before attempting to load Util.forceOnline(); BrowserUI.showContent(aURI); content.focus(); this._setURI(aURI); - let postData = {}; - aURI = Browser.getShortcutOrURI(aURI, postData); - Browser.loadURI(aURI, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP, postData: postData }); + Task.spawn(function() { + let postData = {}; + aURI = yield Browser.getShortcutOrURI(aURI, postData); + Browser.loadURI(aURI, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP, postData: postData }); - // Delay doing the fixup so the raw URI is passed to loadURIWithFlags - // and the proper third-party fixup can be done - let fixupFlags = Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP; - let uri = gURIFixup.createFixupURI(aURI, fixupFlags); - gHistSvc.markPageAsTyped(uri); + // Delay doing the fixup so the raw URI is passed to loadURIWithFlags + // and the proper third-party fixup can be done + let fixupFlags = Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP; + let uri = gURIFixup.createFixupURI(aURI, fixupFlags); + gHistSvc.markPageAsTyped(uri); - this._titleChanged(Browser.selectedBrowser); + BrowserUI._titleChanged(Browser.selectedBrowser); + }); }, handleUrlbarEnter: function handleUrlbarEnter(aEvent) { let url = this._edit.value; if (aEvent instanceof KeyEvent) url = this._canonizeURL(url, aEvent); this.goToURI(url); },
--- a/browser/metro/base/content/browser.js +++ b/browser/metro/base/content/browser.js @@ -128,63 +128,16 @@ var Browser = { // If this is an intial window launch the commandline handler passes us the default // page as an argument. commandURL _should_ never be empty, but we protect against it // below. However, we delay trying to get the fallback homepage until we really need it. let commandURL = null; if (window.arguments && window.arguments[0]) commandURL = window.arguments[0]; - // Activation URIs come from protocol activations, secondary tiles, and file activations - let activationURI = this.getShortcutOrURI(MetroUtils.activationURI); - - let self = this; - function loadStartupURI() { - let uri = activationURI || commandURL || Browser.getHomePage(); - if (StartUI.isStartURI(uri)) { - self.addTab(uri, true); - StartUI.show(); // This makes about:start load a lot faster - } else if (activationURI) { - self.addTab(uri, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP }); - } else { - self.addTab(uri, true); - } - } - - // Should we restore the previous session (crash or some other event) - let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - if (ss.shouldRestore() || Services.prefs.getBoolPref("browser.startup.sessionRestore")) { - let bringFront = false; - // First open any commandline URLs, except the homepage - if (activationURI && !StartUI.isStartURI(activationURI)) { - this.addTab(activationURI, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP }); - } else if (commandURL && !StartUI.isStartURI(commandURL)) { - this.addTab(commandURL, true); - } else { - bringFront = true; - // Initial window resizes call functions that assume a tab is in the tab list - // and restored tabs are added too late. We add a dummy to to satisfy the resize - // code and then remove the dummy after the session has been restored. - let dummy = this.addTab("about:blank", true); - let dummyCleanup = { - observe: function(aSubject, aTopic, aData) { - Services.obs.removeObserver(dummyCleanup, "sessionstore-windows-restored"); - if (aData == "fail") - loadStartupURI(); - dummy.chromeTab.ignoreUndo = true; - Browser.closeTab(dummy, { forceClose: true }); - } - }; - Services.obs.addObserver(dummyCleanup, "sessionstore-windows-restored", false); - } - ss.restoreLastSession(bringFront); - } else { - loadStartupURI(); - } - messageManager.addMessageListener("DOMLinkAdded", this); messageManager.addMessageListener("MozScrolledAreaChanged", this); messageManager.addMessageListener("Browser:ViewportMetadata", this); messageManager.addMessageListener("Browser:FormSubmit", this); messageManager.addMessageListener("Browser:ZoomToPoint:Return", this); messageManager.addMessageListener("Browser:CanUnload:Return", this); messageManager.addMessageListener("scroll", this); messageManager.addMessageListener("Browser:CertException", this); @@ -192,20 +145,69 @@ var Browser = { messageManager.addMessageListener("Browser:ErrorPage", this); messageManager.addMessageListener("Browser:TapOnSelection", this); messageManager.addMessageListener("Browser:PluginClickToPlayClicked", this); // Let everyone know what kind of mouse input we are // starting with: InputSourceHelper.fireUpdate(); - // Broadcast a UIReady message so add-ons know we are finished with startup - let event = document.createEvent("Events"); - event.initEvent("UIReady", true, false); - window.dispatchEvent(event); + Task.spawn(function() { + // Activation URIs come from protocol activations, secondary tiles, and file activations + let activationURI = yield this.getShortcutOrURI(MetroUtils.activationURI); + + let self = this; + function loadStartupURI() { + let uri = activationURI || commandURL || Browser.getHomePage(); + if (StartUI.isStartURI(uri)) { + self.addTab(uri, true); + StartUI.show(); // This makes about:start load a lot faster + } else if (activationURI) { + self.addTab(uri, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP }); + } else { + self.addTab(uri, true); + } + } + + // Should we restore the previous session (crash or some other event) + let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); + if (ss.shouldRestore() || Services.prefs.getBoolPref("browser.startup.sessionRestore")) { + let bringFront = false; + // First open any commandline URLs, except the homepage + if (activationURI && !StartUI.isStartURI(activationURI)) { + this.addTab(activationURI, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP }); + } else if (commandURL && !StartUI.isStartURI(commandURL)) { + this.addTab(commandURL, true); + } else { + bringFront = true; + // Initial window resizes call functions that assume a tab is in the tab list + // and restored tabs are added too late. We add a dummy to to satisfy the resize + // code and then remove the dummy after the session has been restored. + let dummy = this.addTab("about:blank", true); + let dummyCleanup = { + observe: function(aSubject, aTopic, aData) { + Services.obs.removeObserver(dummyCleanup, "sessionstore-windows-restored"); + if (aData == "fail") + loadStartupURI(); + dummy.chromeTab.ignoreUndo = true; + Browser.closeTab(dummy, { forceClose: true }); + } + }; + Services.obs.addObserver(dummyCleanup, "sessionstore-windows-restored", false); + } + ss.restoreLastSession(bringFront); + } else { + loadStartupURI(); + } + + // Broadcast a UIReady message so add-ons know we are finished with startup + let event = document.createEvent("Events"); + event.initEvent("UIReady", true, false); + window.dispatchEvent(event); + }.bind(this)); }, quit: function quit() { // NOTE: onclose seems to be called only when using OS chrome to close a window, // so we need to handle the Browser.closing check ourselves. if (this.closing()) { window.QueryInterface(Ci.nsIDOMChromeWindow).minimize(); window.close(); @@ -343,87 +345,90 @@ var Browser = { dump("Error: " + e + "\n"); } }, /** * Determine if the given URL is a shortcut/keyword and, if so, expand it * @param aURL String * @param aPostDataRef Out param contains any required post data for a search - * @returns the expanded shortcut, or the original URL if not a shortcut + * @return {Promise} + * @result the expanded shortcut, or the original URL if not a shortcut */ getShortcutOrURI: function getShortcutOrURI(aURL, aPostDataRef) { - if (!aURL) - return aURL; - - let shortcutURL = null; - let keyword = aURL; - let param = ""; + return Task.spawn(function() { + if (!aURL) + throw new Task.Result(aURL); - let offset = aURL.indexOf(" "); - if (offset > 0) { - keyword = aURL.substr(0, offset); - param = aURL.substr(offset + 1); - } - - if (!aPostDataRef) - aPostDataRef = {}; - - let engine = Services.search.getEngineByAlias(keyword); - if (engine) { - let submission = engine.getSubmission(param); - aPostDataRef.value = submission.postData; - return submission.uri.spec; - } + let shortcutURL = null; + let keyword = aURL; + let param = ""; - try { - [shortcutURL, aPostDataRef.value] = PlacesUtils.getURLAndPostDataForKeyword(keyword); - } catch (e) {} - - if (!shortcutURL) - return aURL; - - let postData = ""; - if (aPostDataRef.value) - postData = unescape(aPostDataRef.value); + let offset = aURL.indexOf(" "); + if (offset > 0) { + keyword = aURL.substr(0, offset); + param = aURL.substr(offset + 1); + } - if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) { - let charset = ""; - const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; - let matches = shortcutURL.match(re); - if (matches) - [, shortcutURL, charset] = matches; - else { - // Try to get the saved character-set. - try { - // makeURI throws if URI is invalid. - // Will return an empty string if character-set is not found. - charset = PlacesUtils.history.getCharsetForURI(Util.makeURI(shortcutURL)); - } catch (e) { dump("--- error " + e + "\n"); } + if (!aPostDataRef) + aPostDataRef = {}; + + let engine = Services.search.getEngineByAlias(keyword); + if (engine) { + let submission = engine.getSubmission(param); + aPostDataRef.value = submission.postData; + throw new Task.Result(submission.uri.spec); } - let encodedParam = ""; - if (charset) - encodedParam = escape(convertFromUnicode(charset, param)); - else // Default charset is UTF-8 - encodedParam = encodeURIComponent(param); + try { + [shortcutURL, aPostDataRef.value] = PlacesUtils.getURLAndPostDataForKeyword(keyword); + } catch (e) {} - shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); + if (!shortcutURL) + throw new Task.Result(aURL); + + let postData = ""; + if (aPostDataRef.value) + postData = unescape(aPostDataRef.value); - if (/%s/i.test(postData)) // POST keyword - aPostDataRef.value = getPostDataStream(postData, param, encodedParam, "application/x-www-form-urlencoded"); - } else if (param) { - // This keyword doesn't take a parameter, but one was provided. Just return - // the original URL. - aPostDataRef.value = null; + if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) { + let charset = ""; + const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; + let matches = shortcutURL.match(re); + if (matches) + [, shortcutURL, charset] = matches; + else { + // Try to get the saved character-set. + try { + // makeURI throws if URI is invalid. + // Will return an empty string if character-set is not found. + charset = yield PlacesUtils.getCharsetForURI(Util.makeURI(shortcutURL)); + } catch (e) { dump("--- error " + e + "\n"); } + } - return aURL; - } + let encodedParam = ""; + if (charset) + encodedParam = escape(convertFromUnicode(charset, param)); + else // Default charset is UTF-8 + encodedParam = encodeURIComponent(param); + + shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); - return shortcutURL; + if (/%s/i.test(postData)) // POST keyword + aPostDataRef.value = getPostDataStream(postData, param, encodedParam, "application/x-www-form-urlencoded"); + } else if (param) { + // This keyword doesn't take a parameter, but one was provided. Just return + // the original URL. + aPostDataRef.value = null; + + throw new Task.Result(aURL); + } + + throw new Task.Result(shortcutURL); + }); }, /** * Return the currently active <browser> object */ get selectedBrowser() { return (this._selectedTab && this._selectedTab.browser); },
--- a/browser/metro/shell/testing/metrotestharness.cpp +++ b/browser/metro/shell/testing/metrotestharness.cpp @@ -23,16 +23,23 @@ #include <strsafe.h> #include <io.h> #include <shellapi.h> static const WCHAR* kFirefoxExe = L"firefox.exe"; static const WCHAR* kDefaultMetroBrowserIDPathKey = L"FirefoxURL"; static const WCHAR* kDemoMetroBrowserIDPathKey = L"Mozilla.Firefox.URL"; +CString sAppParams; +CString sFirefoxPath; + +// The tests file we write out for firefox.exe which contains test +// startup command line paramters. +#define kMetroTestFile "tests.ini" + static void Log(const wchar_t *fmt, ...) { va_list a = NULL; wchar_t szDebugString[1024]; if(!lstrlenW(fmt)) return; va_start(a,fmt); vswprintf(szDebugString, 1024, fmt, a); @@ -129,132 +136,172 @@ static bool GetDefaultBrowserAppModelID( (LPBYTE)aIDBuffer, &len) != ERROR_SUCCESS || !len) { RegCloseKey(key); return false; } RegCloseKey(key); return true; } -CString sAppParams; +// Tests.ini file cleanup helper +class DeleteTestFileHelper +{ + CStringA mTestFile; +public: + DeleteTestFileHelper(CStringA& aTestFile) : + mTestFile(aTestFile) {} + ~DeleteTestFileHelper() { + if (mTestFile.GetLength()) { + Log(L"Deleting %s", CStringW(mTestFile)); + DeleteFileA(mTestFile); + } + } +}; static bool Launch() { Log(L"Launching browser..."); DWORD processID; // The interface that allows us to activate the browser - IApplicationActivationManager* activateMgr = NULL; + CComPtr<IApplicationActivationManager> activateMgr; if (FAILED(CoCreateInstance(CLSID_ApplicationActivationManager, NULL, CLSCTX_LOCAL_SERVER, IID_IApplicationActivationManager, (void**)&activateMgr))) { Fail(L"CoCreateInstance CLSID_ApplicationActivationManager failed."); return false; } HRESULT hr; WCHAR appModelID[256]; // Activation is based on the browser's registered app model id if (!GetDefaultBrowserAppModelID(appModelID, (sizeof(appModelID)/sizeof(WCHAR)))) { Fail(L"GetDefaultBrowserAppModelID failed."); - activateMgr->Release(); return false; } Log(L"App model id='%s'", appModelID); // Hand off focus rights to the out-of-process activation server. Without // this the metro interface won't launch. hr = CoAllowSetForegroundWindow(activateMgr, NULL); if (FAILED(hr)) { Fail(L"CoAllowSetForegroundWindow result %X", hr); - activateMgr->Release(); return false; } Log(L"Harness process id: %d", GetCurrentProcessId()); // Because we can't pass command line args, we store params in a // tests.ini file in dist/bin which the browser picks up on launch. - char path[MAX_PATH]; - if (!GetModuleFileNameA(NULL, path, MAX_PATH)) { - Fail(L"GetModuleFileNameA errorno=%d", GetLastError()); - activateMgr->Release(); - return false; + CStringA testFilePath; + if (sFirefoxPath.GetLength()) { + // Use the firefoxpath passed to us by the test harness + int index = sFirefoxPath.ReverseFind('\\'); + if (index == -1) { + Fail(L"Bad firefoxpath path"); + return false; + } + testFilePath = sFirefoxPath.Mid(0, index); + testFilePath += "\\"; + testFilePath += kMetroTestFile; + } else { + // Use the module path + char path[MAX_PATH]; + if (!GetModuleFileNameA(NULL, path, MAX_PATH)) { + Fail(L"GetModuleFileNameA errorno=%d", GetLastError()); + return false; + } + char* slash = strrchr(path, '\\'); + if (!slash) + return false; + *slash = '\0'; // no trailing slash + testFilePath = path; + testFilePath += "\\"; + testFilePath += kMetroTestFile; } - char* slash = strrchr(path, '\\'); - if (!slash) - return false; - *slash = '\0'; // no trailing slash - CStringA testFilePath = path; - testFilePath += "\\tests.ini"; + Log(L"Writing out tests.ini to: '%s'", CStringW(testFilePath)); HANDLE hTestFile = CreateFileA(testFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hTestFile == INVALID_HANDLE_VALUE) { Fail(L"CreateFileA errorno=%d", GetLastError()); - activateMgr->Release(); return false; } + DeleteTestFileHelper dtf(testFilePath); + CStringA asciiParams = sAppParams; if (!WriteFile(hTestFile, asciiParams, asciiParams.GetLength(), NULL, 0)) { CloseHandle(hTestFile); Fail(L"WriteFile errorno=%d", GetLastError()); - activateMgr->Release(); return false; } FlushFileBuffers(hTestFile); CloseHandle(hTestFile); // Launch firefox hr = activateMgr->ActivateApplication(appModelID, L"", AO_NOERRORUI, &processID); if (FAILED(hr)) { Fail(L"ActivateApplication result %X", hr); - activateMgr->Release(); return false; } Log(L"Activation succeeded. processid=%d", processID); HANDLE child = OpenProcess(SYNCHRONIZE, FALSE, processID); if (!child) { Fail(L"Couldn't find child process. (%d)", GetLastError()); - activateMgr->Release(); return false; } Log(L"Waiting on child process..."); MSG msg; DWORD waitResult = WAIT_TIMEOUT; while ((waitResult = WaitForSingleObject(child, 10)) != WAIT_OBJECT_0) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } Log(L"Exiting."); - activateMgr->Release(); - DeleteFileA(testFilePath); return true; } int wmain(int argc, WCHAR* argv[]) { CoInitialize(NULL); int idx; + bool firefoxParam = false; for (idx = 1; idx < argc; idx++) { + CString param = argv[idx]; + param.Trim(); + + // Pickup the firefox path param and store it, we'll need this + // when we create the tests.ini file. + if (param == "-firefoxpath") { + firefoxParam = true; + continue; + } else if (firefoxParam) { + firefoxParam = false; + sFirefoxPath = param; + continue; + } + sAppParams.Append(argv[idx]); sAppParams.Append(L" "); } sAppParams.Trim(); + if (sFirefoxPath.GetLength()) { + Log(L"firefoxpath: '%s'", sFirefoxPath); + } Log(L"args: '%s'", sAppParams); Launch(); CoUninitialize(); return 0; }
--- a/browser/themes/windows/downloads/allDownloadsViewOverlay.css +++ b/browser/themes/windows/downloads/allDownloadsViewOverlay.css @@ -15,19 +15,19 @@ %endif } .downloadTypeIcon { -moz-margin-end: 8px; %ifdef WINDOWS_AERO -moz-margin-start: 8px; %endif - /* Prevent flickering when changing states. */ - min-height: 32px; - min-width: 32px; + /* explicitly size the icon, so size doesn't vary on hidpi systems */ + height: 32px; + width: 32px; } .blockedIcon { list-style-image: url("chrome://global/skin/icons/Error.png"); } .downloadTarget { margin-bottom: 3px;
--- a/build/autoconf/python-virtualenv.m4 +++ b/build/autoconf/python-virtualenv.m4 @@ -48,17 +48,17 @@ mozilla-central and relaunch configure.] fi if test -z $DONT_POPULATE_VIRTUALENV; then AC_MSG_RESULT([Creating Python environment]) dnl This verifies our Python version is sane and ensures the Python dnl virtualenv is present and up to date. It sanitizes the environment dnl for us, so we don't need to clean anything out. $PYTHON $_virtualenv_populate_path \ - $_virtualenv_topsrcdir $MOZ_BUILD_ROOT/_virtualenv || exit 1 + $_virtualenv_topsrcdir $MOZ_BUILD_ROOT $MOZ_BUILD_ROOT/_virtualenv || exit 1 case "$host_os" in mingw*) PYTHON=`cd $MOZ_BUILD_ROOT && pwd -W`/_virtualenv/Scripts/python.exe ;; *) PYTHON=$MOZ_BUILD_ROOT/_virtualenv/bin/python ;;
--- a/build/automation.py.in +++ b/build/automation.py.in @@ -1134,32 +1134,32 @@ user_pref("camino.use_system_proxy_setti def checkForZombies(self, processLog): """ Look for hung processes """ if not os.path.exists(processLog): self.log.info('Automation Error: PID log not found: %s', processLog) # Whilst no hung process was found, the run should still display as a failure return True foundZombie = False - self.log.info('INFO | automation.py | Reading PID log: %s', processLog) + self.log.info('INFO | zombiecheck | Reading PID log: %s', processLog) processList = [] pidRE = re.compile(r'launched child process (\d+)$') processLogFD = open(processLog) for line in processLogFD: self.log.info(line.rstrip()) m = pidRE.search(line) if m: processList.append(int(m.group(1))) processLogFD.close() for processPID in processList: - self.log.info("INFO | automation.py | Checking for orphan process with PID: %d", processPID) + self.log.info("INFO | zombiecheck | Checking for orphan process with PID: %d", processPID) if self.isPidAlive(processPID): foundZombie = True - self.log.info("TEST-UNEXPECTED-FAIL | automation.py | child process %d still alive after shutdown", processPID) + self.log.info("TEST-UNEXPECTED-FAIL | zombiecheck | child process %d still alive after shutdown", processPID) self.killPid(processPID) return foundZombie def checkForCrashes(self, profileDir, symbolsPath): return mozcrash.check_for_crashes(os.path.join(profileDir, "minidumps"), symbolsPath, test_name=self.lastTestSeen) def runApp(self, testURL, env, app, profileDir, extraArgs, runSSLTunnel = False, utilityPath = None,
--- a/build/mach_bootstrap.py +++ b/build/mach_bootstrap.py @@ -17,16 +17,18 @@ SEARCH_PATHS = [ 'python/psutil', 'python/which', 'build/pymake', 'config', 'other-licenses/ply', 'xpcom/idl-parser', 'testing', 'testing/xpcshell', + 'testing/mozbase/mozcrash', + 'testing/mozbase/mozlog', 'testing/mozbase/mozprocess', 'testing/mozbase/mozfile', 'testing/mozbase/mozinfo', ] # Individual files providing mach commands. MACH_MODULES = [ 'addon-sdk/mach_commands.py',
--- a/build/mobile/b2gautomation.py +++ b/build/mobile/b2gautomation.py @@ -5,16 +5,17 @@ import mozcrash import threading import os import Queue import re import shutil import tempfile import time +import traceback from automation import Automation from devicemanager import NetworkTools from mozprocess import ProcessHandlerMixin class StdOutProc(ProcessHandlerMixin): """Process handler for b2g which puts all output in a Queue. @@ -101,21 +102,24 @@ class B2GRemoteAutomation(Automation): break time_out += 1 time.sleep(1) return active def checkForCrashes(self, directory, symbolsPath): crashed = False remote_dump_dir = self._remoteProfile + '/minidumps' + print "checking for crashes in '%s'" % remote_dump_dir if self._devicemanager.dirExists(remote_dump_dir): local_dump_dir = tempfile.mkdtemp() self._devicemanager.getDirectory(remote_dump_dir, local_dump_dir) try: crashed = mozcrash.check_for_crashes(local_dump_dir, symbolsPath, test_name=self.lastTestSeen) + except: + traceback.print_exc() finally: shutil.rmtree(local_dump_dir) self._devicemanager.removeDir(remote_dump_dir) return crashed def initializeProfile(self, profileDir, extraPrefs=[], useServerLocations=False, initialProfile=None):
--- a/build/unix/build-clang/build-clang.py +++ b/build/unix/build-clang/build-clang.py @@ -106,19 +106,19 @@ def build_one_stage_aux(stage_dir, is_st build_dir = stage_dir + "/build" inst_dir = stage_dir + "/clang" configure_opts = ["--enable-optimized", "--enable-targets=x86,x86_64,arm", "--disable-assertions", "--prefix=%s" % inst_dir, - "--with-gcc-toolchain=/tools/gcc-4.5-0moz3"] + "--with-gcc-toolchain=/tools/gcc-4.7.2-0moz1"] build_package(llvm_source_dir, build_dir, configure_opts, - ["CLANG_IS_PRODUCTION=1"]) + []) if isDarwin: os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7' if not os.path.exists(source_dir): os.makedirs(source_dir) svn_co("http://llvm.org/svn/llvm-project/llvm/branches/release_32", llvm_source_dir, llvm_revision)
new file mode 100644 --- /dev/null +++ b/build/unix/headers/bits/c++config.h @@ -0,0 +1,2 @@ +#include_next <bits/c++config.h> +#undef _GLIBCXX_USE_FLOAT128
--- a/build/virtualenv/packages.txt +++ b/build/virtualenv/packages.txt @@ -10,8 +10,9 @@ which.pth:python/which ply.pth:other-licenses/ply/ codegen.pth:python/codegen/ mock.pth:python/mock-1.0.0 mozilla.pth:build mozilla.pth:config mozilla.pth:xpcom/typelib/xpt/tools copy:build/buildconfig.py packages.txt:testing/mozbase/packages.txt +objdir:build
--- a/build/virtualenv/populate_virtualenv.py +++ b/build/virtualenv/populate_virtualenv.py @@ -17,24 +17,26 @@ import sys # Minimum version of Python required to build. MINIMUM_PYTHON_MAJOR = 2 MINIMUM_PYTHON_MINOR = 7 class VirtualenvManager(object): """Contains logic for managing virtualenvs for building the tree.""" - def __init__(self, topsrcdir, virtualenv_path, log_handle, manifest_path): + def __init__(self, topsrcdir, topobjdir, virtualenv_path, log_handle, + manifest_path): """Create a new manager. Each manager is associated with a source directory, a path where you want the virtualenv to be created, and a handle to write output to. """ assert os.path.isabs(manifest_path), "manifest_path must be an absolute path: %s" % (manifest_path) self.topsrcdir = topsrcdir + self.topobjdir = topobjdir self.virtualenv_root = virtualenv_path self.log_handle = log_handle self.manifest_path = manifest_path @property def virtualenv_script_path(self): """Path to virtualenv's own populator script.""" return os.path.join(self.topsrcdir, 'python', 'virtualenv', @@ -73,16 +75,17 @@ class VirtualenvManager(object): return False # recursively check sub packages.txt files submanifests = [i[1] for i in self.packages() if i[0] == 'packages.txt'] for submanifest in submanifests: submanifest = os.path.join(self.topsrcdir, submanifest) submanager = VirtualenvManager(self.topsrcdir, + self.topobjdir, self.virtualenv_root, self.log_handle, submanifest) if not submanager.up_to_date(): return False return True @@ -146,16 +149,24 @@ class VirtualenvManager(object): is attempted. If it fails, we issue a warning and go on. The initial "optional" field is stripped then the remaining line is processed like normal. e.g. "optional:setup.py:python/foo:built_ext:-i" copy -- Copies the given file in the virtualenv site packages directory. + packages.txt -- Denotes that the specified path is a child manifest. It + will be read and processed as if its contents were concatenated + into the manifest being read. + + objdir -- Denotes a relative path in the object directory to add to the + search path. e.g. "objdir:build" will add $topobjdir/build to the + search path. + Note that the Python interpreter running this function should be the one from the virtualenv. If it is the system Python or if the environment is not configured properly, packages could be installed into the wrong place. This is how virtualenv's work. """ packages = self.packages() @@ -180,16 +191,17 @@ class VirtualenvManager(object): return True if package[0] == 'packages.txt': assert len(package) == 2 src = os.path.join(self.topsrcdir, package[1]) assert os.path.isfile(src), "'%s' does not exist" % src submanager = VirtualenvManager(self.topsrcdir, + self.topobjdir, self.virtualenv_root, self.log_handle, src) submanager.populate() return True if package[0].endswith('.pth'): @@ -207,16 +219,25 @@ class VirtualenvManager(object): handle_package(package[1:]) return True except: print('Error processing command. Ignoring', \ 'because optional. (%s)' % ':'.join(package), file=self.log_handle) return False + if package[0] == 'objdir': + assert len(package) == 2 + path = os.path.join(self.topobjdir, package[1]) + + with open(os.path.join(python_lib, 'objdir.pth'), 'a') as f: + f.write('%s\n' % path) + + return True + raise Exception('Unknown action: %s' % package[0]) # We always target the OS X deployment target that Python itself was # built with, regardless of what's in the current environment. If we # don't do # this, we may run into a Python bug. See # http://bugs.python.org/issue9516 and bug 659881. # # Note that this assumes that nothing compiled in the virtualenv is @@ -288,17 +309,17 @@ class VirtualenvManager(object): """ self.create() # We need to populate the virtualenv using the Python executable in # the virtualenv for paths to be proper. args = [self.python_path, __file__, 'populate', self.topsrcdir, - self.virtualenv_root] + self.topobjdir, self.virtualenv_root] result = subprocess.call(args, stdout=self.log_handle, stderr=subprocess.STDOUT, cwd=self.topsrcdir) if result != 0: raise Exception('Error populating virtualenv.') os.utime(self.activate_path, None) @@ -324,34 +345,37 @@ def verify_python_version(log_handle): log_handle.write('Python %d.%d or greater (but not Python 3) is ' 'required to build. ' % (MINIMUM_PYTHON_MAJOR, MINIMUM_PYTHON_MINOR)) log_handle.write('You are running Python %d.%d.\n' % (major, minor)) sys.exit(1) if __name__ == '__main__': - if len(sys.argv) < 3: - print('Usage: populate_virtualenv.py /path/to/topsrcdir /path/to/virtualenv') + if len(sys.argv) < 4: + print('Usage: populate_virtualenv.py /path/to/topsrcdir /path/to/topobjdir /path/to/virtualenv') sys.exit(1) verify_python_version(sys.stdout) topsrcdir = sys.argv[1] - virtualenv_path = sys.argv[2] + topobjdir = sys.argv[2] + virtualenv_path = sys.argv[3] populate = False # This should only be called internally. if sys.argv[1] == 'populate': populate = True topsrcdir = sys.argv[2] - virtualenv_path = sys.argv[3] + topobjdir = sys.argv[3] + virtualenv_path = sys.argv[4] # path to default packages.txt manifest_path = os.path.join(topsrcdir, 'build', 'virtualenv', 'packages.txt') - manager = VirtualenvManager(topsrcdir, virtualenv_path, sys.stdout, manifest_path) + manager = VirtualenvManager(topsrcdir, topobjdir, virtualenv_path, + sys.stdout, manifest_path) if populate: manager.populate() else: manager.ensure()
--- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -325,17 +325,17 @@ nsScriptSecurityManager::GetChannelPrinc if (owner) { CallQueryInterface(owner, aPrincipal); if (*aPrincipal) { return NS_OK; } } // OK, get the principal from the URI. Make sure this does the same thing - // as nsDocument::Reset and nsXULDocument::StartDocumentLoad. + // as nsDocument::Reset and XULDocument::StartDocumentLoad. nsCOMPtr<nsIURI> uri; nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDocShell> docShell; NS_QueryNotificationCallbacks(aChannel, docShell); if (docShell) {
--- a/configure.in +++ b/configure.in @@ -1014,20 +1014,20 @@ MOZ_JPEG_CFLAGS= MOZ_JPEG_LIBS='$(call EXPAND_LIBNAME_PATH,mozjpeg,$(DEPTH)/media/libjpeg)' MOZ_BZ2_CFLAGS= MOZ_BZ2_LIBS='$(call EXPAND_LIBNAME_PATH,bz2,$(DEPTH)/modules/libbz2/src)' MOZ_PNG_CFLAGS= MOZ_PNG_LIBS='$(call EXPAND_LIBNAME_PATH,mozpng,$(DEPTH)/media/libpng)' MOZ_JS_STATIC_LIBS='$(call EXPAND_LIBNAME_PATH,js_static,$(LIBXUL_DIST)/lib)' MOZ_JS_SHARED_LIBS='$(call EXPAND_LIBNAME_PATH,mozjs,$(LIBXUL_DIST)/lib)' -DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/bin -lxpcom -lxpcom_core -lmozalloc' +DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/bin -lxul -lxpcom_core -lmozalloc' MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib' -XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/bin -lxpcom -lmozalloc' -LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) -lxul' +XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/bin -lxul -lmozalloc' +LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS)' XPCOM_GLUE_LDOPTS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) $(XPCOM_FROZEN_LDOPTS)' XPCOM_STANDALONE_GLUE_LDOPTS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX)' # These are specially defined on Windows only case "$target" in *-mingw*) XPCOM_STATICRUNTIME_GLUE_LDOPTS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue_staticruntime_s.$(LIB_SUFFIX) $(XPCOM_FROZEN_LDOPTS)' XPCOM_STANDALONE_STATICRUNTIME_GLUE_LDOPTS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue_staticruntime.$(LIB_SUFFIX)' @@ -1421,17 +1421,17 @@ if test "$GNU_CC"; then # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives # -Wsign-compare - catches comparison of signed and unsigned types # _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement" MOZ_C_SUPPORTS_WARNING(-W, error=return-type, ac_c_has_werror_return_type) MOZ_C_SUPPORTS_WARNING(-W, type-limits, ac_c_has_wtype_limits) MOZ_C_SUPPORTS_WARNING(-W, empty-body, ac_c_has_wempty_body) MOZ_C_SUPPORTS_WARNING(-W, sign-compare, ac_c_has_sign_compare) - + # Turn off the following warnings that -Wall turns on: # -Wno-unused - lots of violations in third-party code # _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wno-unused" if test -z "$INTEL_CC" -a -z "$CLANG_CC"; then # Don't use -Wcast-align with ICC or clang case "$CPU_ARCH" in @@ -1484,17 +1484,17 @@ if test "$GNU_CXX"; then # -Wtype-limits - catches overflow bugs, few false positives # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives # -Wsign-compare - catches comparison of signed and unsigned types # _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual" MOZ_CXX_SUPPORTS_WARNING(-W, error=return-type, ac_cxx_has_werror_return_type) MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits) MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body) - MOZ_CXX_SUPPORTS_WARNING(-W, sign-compare, ac_c_has_sign_compare) + MOZ_CXX_SUPPORTS_WARNING(-W, sign-compare, ac_cxx_has_sign_compare) # Turn off the following warnings that -Wall turns on: # -Wno-invalid-offsetof - we use offsetof on non-POD types frequently # MOZ_CXX_SUPPORTS_WARNING(-Wno-, invalid-offsetof, ac_cxx_has_wno_invalid_offsetof) if test -z "$INTEL_CXX" -a -z "$CLANG_CXX"; then # Don't use -Wcast-align with ICC or clang @@ -2111,18 +2111,18 @@ ia64*-hpux*) RC='$(WINDRES)' # Use static libgcc and libstdc++ LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++" # Use temp file for windres (bug 213281) RCFLAGS='-O coff --use-temp-file' # mingw doesn't require kernel32, user32, and advapi32 explicitly LIBS="$LIBS -luuid -lgdi32 -lwinmm -lwsock32 -luserenv -lsecur32 -lnetapi32" MOZ_FIX_LINK_PATHS= - DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom -lxpcom_core -lmozalloc' - XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxpcom -lmozalloc' + DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxul -lxpcom_core -lmozalloc' + XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxul -lmozalloc' DLL_PREFIX= IMPORT_LIB_SUFFIX=dll.a # We use mix of both POSIX and Win32 printf format across the tree, so format # warnings are useless on mingw. MOZ_C_SUPPORTS_WARNING(-Wno-, format, ac_c_has_wno_format) MOZ_CXX_SUPPORTS_WARNING(-Wno-, format, ac_cxx_has_wno_format) else @@ -2177,19 +2177,19 @@ ia64*-hpux*) CFLAGS="$CFLAGS -we4553" CXXFLAGS="$CXXFLAGS -we4553" LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib secur32.lib netapi32.lib" MOZ_DEBUG_FLAGS='-Zi' MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV' WARNINGS_AS_ERRORS='-WX' MOZ_OPTIMIZE_FLAGS='-O1' MOZ_FIX_LINK_PATHS= - DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib' - XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/mozalloc.lib' - LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' MOZ_COMPONENT_NSPR_LIBS='$(NSPR_LIBS)' LDFLAGS="$LDFLAGS -LARGEADDRESSAWARE -NXCOMPAT" dnl For profile-guided optimization PROFILE_GEN_CFLAGS="-GL" PROFILE_GEN_LDFLAGS="-LTCG:PGINSTRUMENT" dnl XXX: PGO builds can fail with warnings treated as errors, dnl specifically "no profile data available" appears to be dnl treated as an error sometimes. This might be a consequence @@ -2355,18 +2355,18 @@ ia64*-hpux*) BIN_FLAGS='-Zlinker /ST:0x100000' IMPLIB='emximp -o' FILTER='true' LDFLAGS='-Zmap' WARNINGS_AS_ERRORS='-Werror' MOZ_DEBUG_FLAGS="-g -fno-inline" MOZ_OPTIMIZE_FLAGS="-O2" MOZ_OPTIMIZE_LDFLAGS="-s -Zlinker /EXEPACK:2 -Zlinker /PACKCODE -Zlinker /PACKDATA" - DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib' - LIBXUL_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib' + LIBXUL_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib' TARGET_MD_ARCH=os2 _PLATFORM_DEFAULT_TOOLKIT="cairo-os2" RC=rc.exe MC=mc.exe RCFLAGS='-n' MOZ_USER_DIR="Mozilla" ZIP="$ZIP -X" STRIP=lxlite @@ -2710,19 +2710,30 @@ if test "$GNU_CXX"; then _SAVE_CXXFLAGS=$CXXFLAGS CXXFLAGS="$CXXFLAGS -std=gnu++0x" AC_CACHE_CHECK(for gcc c++0x headers bug without rtti, ac_cv_cxx0x_headers_bug, [AC_TRY_COMPILE([#include <memory>], [], ac_cv_cxx0x_headers_bug="no", ac_cv_cxx0x_headers_bug="yes")]) - CXXFLAGS="$_SAVE_CXXFLAGS" - if test "$ac_cv_cxx0x_headers_bug" = "no"; then - CXXFLAGS="$CXXFLAGS -std=gnu++0x" + + if test "$CLANG_CXX" -a "$ac_cv_cxx0x_headers_bug" = "yes"; then + CXXFLAGS="$CXXFLAGS -I$_topsrcdir/build/unix/headers" + AC_CACHE_CHECK(whether workaround for gcc c++0x headers conflict with clang works, + ac_cv_cxx0x_clang_workaround, + [AC_TRY_COMPILE([#include <memory>], [], + ac_cv_cxx0x_clang_workaround="yes", + ac_cv_cxx0x_clang_workaround="no")]) + + if test "ac_cv_cxx0x_clang_workaround" = "no"; then + CXXFLAGS="$_SAVE_CXXFLAGS" + fi + elif test "$ac_cv_cxx0x_headers_bug" = "yes"; then + CXXFLAGS="$_SAVE_CXXFLAGS" fi fi dnl Check for usable char16_t (2 bytes, unsigned) dnl (we might not need the unsignedness check anymore) AC_CACHE_CHECK(for usable char16_t (2 bytes, unsigned), ac_cv_have_usable_char16_t, [AC_TRY_COMPILE([$configure_static_assert_macros], @@ -4580,32 +4591,34 @@ cairo-os2) cairo-cocoa) MOZ_WIDGET_TOOLKIT=cocoa AC_DEFINE(MOZ_WIDGET_COCOA) LDFLAGS="$LDFLAGS -framework Cocoa -lobjc" TK_LIBS='-framework QuartzCore -framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook -framework OpenGL' TK_CFLAGS="-DNO_X11" CFLAGS="$CFLAGS $TK_CFLAGS" CXXFLAGS="$CXXFLAGS $TK_CFLAGS" - LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL' + DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/bin/XUL -lxpcom_core -lmozalloc' + XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/bin/XUL -lmozalloc' MOZ_USER_DIR="Mozilla" MOZ_FS_LAYOUT=bundle MOZ_WEBGL=1 MOZ_INSTRUMENT_EVENT_LOOP=1 ;; cairo-uikit) MOZ_WIDGET_TOOLKIT=uikit AC_DEFINE(MOZ_WIDGET_UIKIT) LDFLAGS="$LDFLAGS -framework UIKit -lobjc" TK_CFLAGS="-DNO_X11" TK_LIBS='-framework Foundation -framework CoreFoundation -framework CoreGraphics -framework CoreText' CFLAGS="$CFLAGS $TK_CFLAGS" CXXFLAGS="$CXXFLAGS $TK_CFLAGS" - LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL' + DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/bin/XUL -lxpcom_core -lmozalloc' + XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/bin/XUL -lmozalloc' MOZ_USER_DIR="Mozilla" MOZ_FS_LAYOUT=bundle ;; cairo-android) AC_DEFINE(MOZ_WIDGET_ANDROID) MOZ_WIDGET_TOOLKIT=android TK_CFLAGS='$(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS)'
--- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -105,18 +105,18 @@ class UndoManager; template<typename> class Sequence; template<typename, typename> class CallbackObjectHolder; typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder; } // namespace dom } // namespace mozilla #define NS_IDOCUMENT_IID \ -{ 0x45ce048f, 0x5970, 0x411e, \ - { 0xaa, 0x99, 0x12, 0xed, 0x3a, 0x55, 0xc9, 0xc3 } } +{ 0x699e0649, 0x55f2, 0x47f1, \ + { 0x93, 0x38, 0xcd, 0x67, 0xf3, 0x2b, 0x04, 0xe9 } } // Flag for AddStyleSheet(). #define NS_STYLESHEET_FROM_CATALOG (1 << 0) // Enum for requesting a particular type of document when creating a doc enum DocumentFlavor { DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true @@ -1301,17 +1301,19 @@ public: * @param aElement canonical nsIContent pointer of the box object's element */ virtual void ClearBoxObjectFor(nsIContent *aContent) = 0; /** * Get the box object for an element. This is not exposed through a * scriptable interface except for XUL documents. */ - NS_IMETHOD GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) = 0; + virtual already_AddRefed<nsIBoxObject> + GetBoxObjectFor(mozilla::dom::Element* aElement, + mozilla::ErrorResult& aRv) = 0; /** * Get the compatibility mode for this document */ nsCompatibility GetCompatibilityMode() const { return mCompatMode; }
--- a/content/base/src/nsCCUncollectableMarker.cpp +++ b/content/base/src/nsCCUncollectableMarker.cpp @@ -4,17 +4,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsCCUncollectableMarker.h" #include "nsIObserverService.h" #include "nsIDocShell.h" #include "nsServiceManagerUtils.h" #include "nsIContentViewer.h" #include "nsIDocument.h" -#include "nsXULDocument.h" +#include "XULDocument.h" #include "nsIWindowMediator.h" #include "nsPIDOMWindow.h" #include "nsIWebNavigation.h" #include "nsISHistory.h" #include "nsISHEntry.h" #include "nsISHContainer.h" #include "nsIWindowWatcher.h" #include "mozilla/Services.h" @@ -420,17 +420,17 @@ TraceActiveWindowGlobal(const uint64_t& if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) { TraceClosure* closure = static_cast<TraceClosure*>(aClosure); if (JSObject* global = aWindow->FastGetGlobalJSObject()) { JS_CALL_OBJECT_TRACER(closure->mTrc, global, "active window global"); } #ifdef MOZ_XUL nsIDocument* doc = aWindow->GetExtantDoc(); if (doc && doc->IsXUL()) { - nsXULDocument* xulDoc = static_cast<nsXULDocument*>(doc); + XULDocument* xulDoc = static_cast<XULDocument*>(doc); xulDoc->TraceProtos(closure->mTrc, closure->mGCNumber); } #endif } return PL_DHASH_NEXT; } void
--- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -151,17 +151,17 @@ #endif // MOZ_MEDIA #ifdef MOZ_WEBRTC #include "IPeerConnection.h" #endif // MOZ_WEBRTC #include "mozAutoDocUpdate.h" #include "nsGlobalWindow.h" #include "mozilla/dom/EncodingUtils.h" -#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "nsDOMNavigationTiming.h" #include "nsEventStateManager.h" #include "nsSMILAnimationController.h" #include "imgIContainer.h" #include "nsSVGUtils.h" #include "nsRefreshDriver.h" @@ -1940,17 +1940,17 @@ nsIDocument::IsVisibleConsideringAncesto } void nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) { nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIPrincipal> principal; if (aChannel) { - // Note: this code is duplicated in nsXULDocument::StartDocumentLoad and + // Note: this code is duplicated in XULDocument::StartDocumentLoad and // nsScriptSecurityManager::GetChannelPrincipal. // Note: this should match nsDocShell::OnLoadingSite NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); nsIScriptSecurityManager *securityManager = nsContentUtils::GetSecurityManager(); if (securityManager) { securityManager->GetChannelPrincipal(aChannel, @@ -5922,49 +5922,50 @@ nsDocument::DoNotifyPossibleTitleChange( } // Fire a DOM event for the title change. nsContentUtils::DispatchChromeEvent(this, static_cast<nsIDocument*>(this), NS_LITERAL_STRING("DOMTitleChanged"), true, true); } -NS_IMETHODIMP -nsDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) -{ - nsCOMPtr<nsIContent> content(do_QueryInterface(aElement)); - NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED); - - nsIDocument* doc = content->OwnerDoc(); - NS_ENSURE_TRUE(doc == this, NS_ERROR_DOM_WRONG_DOCUMENT_ERR); - - if (!mHasWarnedAboutBoxObjects && !content->IsXUL()) { +already_AddRefed<nsIBoxObject> +nsDocument::GetBoxObjectFor(Element* aElement, ErrorResult& aRv) +{ + if (!aElement) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + + nsIDocument* doc = aElement->OwnerDoc(); + if (doc != this) { + aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR); + return nullptr; + } + + if (!mHasWarnedAboutBoxObjects && !aElement->IsXUL()) { mHasWarnedAboutBoxObjects = true; nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "BoxObjects", this, nsContentUtils::eDOM_PROPERTIES, "UseOfGetBoxObjectForWarning"); } - *aResult = nullptr; - if (!mBoxObjectTable) { mBoxObjectTable = new nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject>; mBoxObjectTable->Init(12); } else { - // Want to use Get(content, aResult); but it's the wrong type - *aResult = mBoxObjectTable->GetWeak(content); - if (*aResult) { - NS_ADDREF(*aResult); - return NS_OK; + nsCOMPtr<nsPIBoxObject> boxObject = mBoxObjectTable->Get(aElement); + if (boxObject) { + return boxObject.forget(); } } int32_t namespaceID; - nsCOMPtr<nsIAtom> tag = BindingManager()->ResolveTag(content, &namespaceID); + nsCOMPtr<nsIAtom> tag = BindingManager()->ResolveTag(aElement, &namespaceID); nsAutoCString contractID("@mozilla.org/layout/xul-boxobject"); if (namespaceID == kNameSpaceID_XUL) { if (tag == nsGkAtoms::browser || tag == nsGkAtoms::editor || tag == nsGkAtoms::iframe) contractID += "-container"; else if (tag == nsGkAtoms::menu) @@ -5979,29 +5980,28 @@ nsDocument::GetBoxObjectFor(nsIDOMElemen else if (tag == nsGkAtoms::listbox) contractID += "-listbox"; else if (tag == nsGkAtoms::scrollbox) contractID += "-scrollbox"; } contractID += ";1"; nsCOMPtr<nsPIBoxObject> boxObject(do_CreateInstance(contractID.get())); - if (!boxObject) - return NS_ERROR_FAILURE; - - boxObject->Init(content); + if (!boxObject) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + boxObject->Init(aElement); if (mBoxObjectTable) { - mBoxObjectTable->Put(content, boxObject.get()); - } - - *aResult = boxObject; - NS_ADDREF(*aResult); - - return NS_OK; + mBoxObjectTable->Put(aElement, boxObject.get()); + } + + return boxObject.forget(); } void nsDocument::ClearBoxObjectFor(nsIContent* aContent) { if (mBoxObjectTable) { nsPIBoxObject *boxObject = mBoxObjectTable->GetWeak(aContent); if (boxObject) { @@ -7633,21 +7633,21 @@ nsDocument::CanSavePresentation(nsIReque printf("document %s has request %s\n", docSpec.get(), requestName.get()); #endif return false; } } } - // Check if we have running IndexedDB transactions - indexedDB::IndexedDatabaseManager* idbManager = - win ? indexedDB::IndexedDatabaseManager::Get() : nullptr; - if (idbManager && idbManager->HasOpenTransactions(win)) { - return false; + // Check if we have running offline storage transactions + quota::QuotaManager* quotaManager = + win ? quota::QuotaManager::Get() : nullptr; + if (quotaManager && quotaManager->HasOpenTransactions(win)) { + return false; } #ifdef MOZ_WEBRTC // Check if we have active PeerConnections nsCOMPtr<IPeerConnectionManager> pcManager = do_GetService(IPEERCONNECTION_MANAGER_CONTRACTID); if (pcManager && win) {
--- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -807,17 +807,18 @@ public: virtual NS_HIDDEN_(void) BlockOnload(); virtual NS_HIDDEN_(void) UnblockOnload(bool aFireSync); virtual NS_HIDDEN_(void) AddStyleRelevantLink(mozilla::dom::Link* aLink); virtual NS_HIDDEN_(void) ForgetLink(mozilla::dom::Link* aLink); NS_HIDDEN_(void) ClearBoxObjectFor(nsIContent* aContent); - NS_IMETHOD GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult); + already_AddRefed<nsIBoxObject> GetBoxObjectFor(mozilla::dom::Element* aElement, + mozilla::ErrorResult& aRv); virtual NS_HIDDEN_(nsresult) GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult); virtual NS_HIDDEN_(nsresult) GetContentListFor(nsIContent* aContent, nsIDOMNodeList** aResult); virtual NS_HIDDEN_(Element*) GetAnonymousElementByAttribute(nsIContent* aElement, nsIAtom* aAttrName,
--- a/content/events/src/nsDOMBeforeUnloadEvent.h +++ b/content/events/src/nsDOMBeforeUnloadEvent.h @@ -3,24 +3,33 @@ * 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 nsDOMBeforeUnloadEvent_h__ #define nsDOMBeforeUnloadEvent_h__ #include "nsIDOMBeforeUnloadEvent.h" #include "nsDOMEvent.h" +#include "mozilla/dom/BeforeUnloadEventBinding.h" class nsDOMBeforeUnloadEvent : public nsDOMEvent, public nsIDOMBeforeUnloadEvent { public: nsDOMBeforeUnloadEvent(mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, nsEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) {} + : nsDOMEvent(aOwner, aPresContext, aEvent) + { + SetIsDOMBinding(); + } + + virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope) + { + return mozilla::dom::BeforeUnloadEventBinding::Wrap(aCx, aScope, this); + } NS_DECL_ISUPPORTS_INHERITED // Forward to nsDOMEvent NS_FORWARD_TO_NSDOMEVENT // nsIDOMBeforeUnloadEvent Interface NS_DECL_NSIDOMBEFOREUNLOADEVENT
--- a/content/events/src/nsDOMCompositionEvent.cpp +++ b/content/events/src/nsDOMCompositionEvent.cpp @@ -25,16 +25,18 @@ nsDOMCompositionEvent::nsDOMCompositionE // XXX compositionstart is cancelable in draft of DOM3 Events. // However, it doesn't make sence for us, we cannot cancel composition // when we sends compositionstart event. mEvent->mFlags.mCancelable = false; } mData = static_cast<nsCompositionEvent*>(mEvent)->data; // TODO: Native event should have locale information. + + SetIsDOMBinding(); } nsDOMCompositionEvent::~nsDOMCompositionEvent() { if (mEventIsInternal) { delete static_cast<nsCompositionEvent*>(mEvent); mEvent = nullptr; }
--- a/content/events/src/nsDOMCompositionEvent.h +++ b/content/events/src/nsDOMCompositionEvent.h @@ -4,28 +4,47 @@ * 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 nsDOMCompositionEvent_h__ #define nsDOMCompositionEvent_h__ #include "nsDOMUIEvent.h" #include "nsIDOMCompositionEvent.h" +#include "mozilla/dom/CompositionEventBinding.h" class nsDOMCompositionEvent : public nsDOMUIEvent, public nsIDOMCompositionEvent { public: nsDOMCompositionEvent(mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, nsCompositionEvent* aEvent); virtual ~nsDOMCompositionEvent(); NS_DECL_ISUPPORTS_INHERITED NS_FORWARD_TO_NSDOMUIEVENT NS_DECL_NSIDOMCOMPOSITIONEVENT + virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope) + { + return mozilla::dom::CompositionEventBinding::Wrap(aCx, aScope, this); + } + + void + InitCompositionEvent(const nsAString& aType, + bool aCanBubble, + bool aCancelable, + nsIDOMWindow* aView, + const nsAString& aData, + const nsAString& aLocale, + mozilla::ErrorResult& aRv) + { + aRv = InitCompositionEvent(aType, aCanBubble, aCancelable, aView, + aData, aLocale); + } + protected: nsString mData; nsString mLocale; }; #endif // nsDOMCompositionEvent_h__
--- a/content/media/webrtc/MediaEngineWebRTC.h +++ b/content/media/webrtc/MediaEngineWebRTC.h @@ -13,16 +13,17 @@ #include "mozilla/Mutex.h" #include "mozilla/Monitor.h" #include "nsCOMPtr.h" #include "nsDOMFile.h" #include "nsThreadUtils.h" #include "DOMMediaStream.h" #include "nsDirectoryServiceDefs.h" #include "nsComponentManagerUtils.h" +#include "nsRefPtrHashtable.h" #include "VideoUtils.h" #include "MediaEngine.h" #include "VideoSegment.h" #include "AudioSegment.h" #include "StreamBuffer.h" #include "MediaStreamGraph.h"
--- a/content/media/wmf/WMFDecoder.cpp +++ b/content/media/wmf/WMFDecoder.cpp @@ -5,16 +5,19 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WMF.h" #include "WMFDecoder.h" #include "WMFReader.h" #include "WMFUtils.h" #include "MediaDecoderStateMachine.h" #include "mozilla/Preferences.h" +#include "WinUtils.h" + +using namespace mozilla::widget; namespace mozilla { MediaDecoderStateMachine* WMFDecoder::CreateStateMachine() { return new MediaDecoderStateMachine(this, new WMFReader(this)); } @@ -81,34 +84,19 @@ WMFDecoder::LoadDLLs() } void WMFDecoder::UnloadDLLs() { wmf::UnloadDLLs(); } -bool IsWindows7OrLater() -{ - OSVERSIONINFO versionInfo; - versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - if (!GetVersionEx(&versionInfo)) { - return false; - } - // Note: Win Vista = 6.0 - // Win 7 = 6.1 - // Win 8 = 6.2 - return versionInfo.dwMajorVersion > 6 || - (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1); -} - /* static */ bool WMFDecoder::IsEnabled() { - // We only use WMF on Windows 7 and up, until we can properly test Vista - // and how it responds with and without the Platform Update installed. - return IsWindows7OrLater() && + // We only use WMF on Windows Vista and up + return WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION && Preferences::GetBool("media.windows-media-foundation.enabled"); } } // namespace mozilla
--- a/content/media/wmf/WMFUtils.cpp +++ b/content/media/wmf/WMFUtils.cpp @@ -4,16 +4,20 @@ * 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 "WMFUtils.h" #include "mozilla/StandardInteger.h" #include "mozilla/RefPtr.h" #include "prlog.h" #include "nsThreadUtils.h" +#include "WinUtils.h" +#include "nsWindowsHelpers.h" + +using namespace mozilla::widget; namespace mozilla { struct GuidToName { GUID guid; const char* name; }; @@ -264,42 +268,42 @@ DisableBlockedDecoders(IMFPluginControl* return hr; } static HRESULT DisableBlockedDecoders() { RefPtr<IMFPluginControl> pluginControl; HRESULT hr = wmf::MFGetPluginControl(byRef(pluginControl)); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + if (SUCCEEDED(hr) && pluginControl) { + hr = DisableBlockedDecoders(pluginControl, + MFT_CATEGORY_VIDEO_DECODER); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - hr = DisableBlockedDecoders(pluginControl, - MFT_CATEGORY_VIDEO_DECODER); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - hr = DisableBlockedDecoders(pluginControl, - MFT_CATEGORY_AUDIO_DECODER); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + hr = DisableBlockedDecoders(pluginControl, + MFT_CATEGORY_AUDIO_DECODER); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + } return S_OK; } static bool sDLLsLoaded = false; static bool sFailedToLoadDlls = false; struct WMFModule { - const char* name; + const wchar_t* name; HMODULE handle; }; static WMFModule sDLLs[] = { - { "mfplat.dll", NULL }, - { "mfreadwrite.dll", NULL }, - { "propsys.dll", NULL }, - { "mf.dll", NULL } + { L"mfplat.dll", NULL }, + { L"mfreadwrite.dll", NULL }, + { L"propsys.dll", NULL }, + { L"mf.dll", NULL } }; HRESULT LoadDLLs() { NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); if (sDLLsLoaded) { @@ -307,17 +311,17 @@ LoadDLLs() } if (sFailedToLoadDlls) { return E_FAIL; } // Try to load all the required DLLs. uint32_t dllLength = NS_ARRAY_LENGTH(sDLLs); for (uint32_t i = 0; i < dllLength; i++) { - sDLLs[i].handle = LoadLibraryA(sDLLs[i].name); + sDLLs[i].handle = LoadLibrarySystem32(sDLLs[i].name); if (!sDLLs[i].handle) { sFailedToLoadDlls = true; NS_WARNING("Failed to load WMF DLLs"); UnloadDLLs(); return E_FAIL; } } @@ -362,19 +366,25 @@ UnloadDLLs() } #define DECL_FUNCTION_PTR(FunctionName, ...) \ typedef HRESULT (STDMETHODCALLTYPE * FunctionName##Ptr_t)(__VA_ARGS__) HRESULT MFStartup() { + const int MF_VISTA_VERSION = (0x0001 << 16 | MF_API_VERSION); + const int MF_WIN7_VERSION = (0x0002 << 16 | MF_API_VERSION); + DECL_FUNCTION_PTR(MFStartup, ULONG, DWORD); ENSURE_FUNCTION_PTR(MFStartup, Mfplat.dll) - return MFStartupPtr(MF_VERSION, MFSTARTUP_FULL); + if (WinUtils::GetWindowsVersion() == WinUtils::VISTA_VERSION) + return MFStartupPtr(MF_VISTA_VERSION, MFSTARTUP_FULL); + else + return MFStartupPtr(MF_WIN7_VERSION, MFSTARTUP_FULL); } HRESULT MFShutdown() { DECL_FUNCTION_PTR(MFShutdown); ENSURE_FUNCTION_PTR(MFShutdown, Mfplat.dll) return (MFShutdownPtr)();
--- a/content/svg/content/src/Makefile.in +++ b/content/svg/content/src/Makefile.in @@ -45,17 +45,16 @@ CPPSRCS = \ nsSVGIntegerPair.cpp \ nsSVGLength2.cpp \ nsSVGNumber2.cpp \ nsSVGNumberPair.cpp \ nsSVGPathDataParser.cpp \ nsSVGPathGeometryElement.cpp \ nsSVGPolyElement.cpp \ nsSVGString.cpp \ - nsSVGRect.cpp \ nsSVGUnknownElement.cpp \ nsSVGViewBox.cpp \ SVGAElement.cpp \ SVGAltGlyphElement.cpp \ SVGAngle.cpp \ SVGAnimatedAngle.cpp \ SVGAnimatedBoolean.cpp \ SVGAnimatedLength.cpp \ @@ -85,21 +84,23 @@ CPPSRCS = \ SVGFEDiffuseLightingElement.cpp \ SVGFEDisplacementMapElement.cpp \ SVGFEDistantLightElement.cpp \ SVGFEFloodElement.cpp \ SVGFEGaussianBlurElement.cpp \ SVGFEImageElement.cpp \ SVGFEMergeElement.cpp \ SVGFEMergeNodeElement.cpp \ + SVGFEMorphologyElement.cpp \ SVGFEOffsetElement.cpp \ SVGFEPointLightElement.cpp \ SVGFESpecularLightingElement.cpp \ SVGFESpotLightElement.cpp \ SVGFETileElement.cpp \ + SVGFETurbulenceElement.cpp \ SVGFilterElement.cpp \ SVGForeignObjectElement.cpp \ SVGFragmentIdentifier.cpp \ SVGGElement.cpp \ SVGGradientElement.cpp \ SVGGraphicsElement.cpp \ SVGImageElement.cpp \ SVGIntegerPairSMILType.cpp \ @@ -125,16 +126,17 @@ CPPSRCS = \ SVGPathSegUtils.cpp \ SVGPathSegListSMILType.cpp \ SVGPatternElement.cpp \ SVGPointList.cpp \ SVGPointListSMILType.cpp \ SVGPolygonElement.cpp \ SVGPolylineElement.cpp \ SVGPreserveAspectRatio.cpp \ + SVGRect.cpp \ SVGRectElement.cpp \ SVGScriptElement.cpp \ SVGSetElement.cpp \ SVGStopElement.cpp \ SVGStringList.cpp \ SVGStyleElement.cpp \ SVGSymbolElement.cpp \ SVGSVGElement.cpp \ @@ -160,17 +162,16 @@ include $(topsrcdir)/config/config.mk # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 EXPORTS = \ nsSVGClass.h \ nsSVGElement.h \ nsSVGFeatures.h \ - nsSVGRect.h \ SVGAttrValueWrapper.h \ SVGStringList.h \ $(NULL) EXPORTS_NAMESPACES = mozilla/dom EXPORTS_mozilla/dom = \ SVGAElement.h \ @@ -197,37 +198,41 @@ EXPORTS_mozilla/dom = \ SVGFEDiffuseLightingElement.h \ SVGFEDisplacementMapElement.h \ SVGFEDistantLightElement.h \ SVGFEFloodElement.h \ SVGFEGaussianBlurElement.h \ SVGFEImageElement.h \ SVGFEMergeElement.h \ SVGFEMergeNodeElement.h \ + SVGFEMorphologyElement.h \ SVGFEOffsetElement.h \ SVGFEPointLightElement.h \ SVGFESpecularLightingElement.h \ SVGFESpotLightElement.h \ SVGFETileElement.h \ + SVGFETurbulenceElement.h \ SVGFilterElement.h \ SVGForeignObjectElement.h \ SVGGElement.h \ SVGGradientElement.h \ SVGGraphicsElement.h \ SVGImageElement.h \ SVGLineElement.h \ SVGMarkerElement.h \ SVGMaskElement.h \ SVGMatrix.h \ SVGMetadataElement.h \ SVGMPathElement.h \ SVGPathElement.h \ SVGPatternElement.h \ SVGPolygonElement.h \ SVGPolylineElement.h \ + SVGRect.h \ + SVGIRect.h \ SVGRectElement.h \ SVGScriptElement.h \ SVGSetElement.h \ SVGStopElement.h \ SVGStyleElement.h \ SVGSymbolElement.h \ SVGSVGElement.h \ SVGSwitchElement.h \
copy from content/svg/content/src/nsSVGFilters.cpp copy to content/svg/content/src/SVGFEMorphologyElement.cpp --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/SVGFEMorphologyElement.cpp @@ -1,1434 +1,172 @@ /* a*- 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 "nsSVGElement.h" -#include "nsGkAtoms.h" -#include "nsSVGNumber2.h" -#include "nsSVGNumberPair.h" -#include "nsSVGInteger.h" -#include "nsSVGIntegerPair.h" -#include "nsSVGBoolean.h" -#include "nsIDOMSVGFilters.h" -#include "nsCOMPtr.h" +#include "mozilla/dom/SVGFEMorphologyElement.h" +#include "mozilla/dom/SVGFEMorphologyElementBinding.h" #include "nsSVGFilterInstance.h" -#include "nsSVGEnum.h" -#include "SVGNumberList.h" -#include "SVGAnimatedNumberList.h" -#include "DOMSVGAnimatedNumberList.h" -#include "nsSVGFilters.h" -#include "nsLayoutUtils.h" -#include "nsSVGUtils.h" -#include "nsStyleContext.h" -#include "nsIFrame.h" -#include "gfxContext.h" -#include "gfxMatrix.h" -#include "imgIContainer.h" -#include "nsNetUtil.h" -#include "mozilla/dom/SVGFilterElement.h" -#include "nsSVGString.h" -#include "gfxUtils.h" -#include "SVGContentUtils.h" -#include <algorithm> -#include "nsContentUtils.h" -#include "mozilla/dom/SVGAnimatedLength.h" -#include "mozilla/dom/SVGComponentTransferFunctionElement.h" -#include "mozilla/dom/SVGFEDistantLightElement.h" -#include "mozilla/dom/SVGFEFuncAElementBinding.h" -#include "mozilla/dom/SVGFEFuncBElementBinding.h" -#include "mozilla/dom/SVGFEFuncGElementBinding.h" -#include "mozilla/dom/SVGFEFuncRElementBinding.h" -#include "mozilla/dom/SVGFEPointLightElement.h" -#include "mozilla/dom/SVGFESpotLightElement.h" - -#if defined(XP_WIN) -// Prevent Windows redefining LoadImage -#undef LoadImage -#endif - -using namespace mozilla; -using namespace mozilla::dom; - -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5; - -void -CopyDataRect(uint8_t *aDest, const uint8_t *aSrc, uint32_t aStride, - const nsIntRect& aDataRect) -{ - for (int32_t y = aDataRect.y; y < aDataRect.YMost(); y++) { - memcpy(aDest + y * aStride + 4 * aDataRect.x, - aSrc + y * aStride + 4 * aDataRect.x, - 4 * aDataRect.width); - } -} - -static void -CopyAndScaleDeviceOffset(const gfxImageSurface *aImage, gfxImageSurface *aResult, - gfxFloat kernelX, gfxFloat kernelY) -{ - gfxPoint deviceOffset = aImage->GetDeviceOffset(); - deviceOffset.x /= kernelX; - deviceOffset.y /= kernelY; - aResult->SetDeviceOffset(deviceOffset); -} - -//--------------------Filter Element Base Class----------------------- - -nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] = -{ - { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, - { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y }, - { &nsGkAtoms::width, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, - { &nsGkAtoms::height, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFE,nsSVGFEBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFE,nsSVGFEBase) - -NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGFE, NS_SVG_FE_CID) - -NS_INTERFACE_MAP_BEGIN(nsSVGFE) - // nsISupports is an ambiguous base of nsSVGFE so we have to work - // around that - if ( aIID.Equals(NS_GET_IID(nsSVGFE)) ) - foundInterface = static_cast<nsISupports*>(static_cast<void*>(this)); - else -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBase) - -//---------------------------------------------------------------------- -// Implementation - -nsSVGFE::ScaleInfo -nsSVGFE::SetupScalingFilter(nsSVGFilterInstance *aInstance, - const Image *aSource, const Image *aTarget, - const nsIntRect& aDataRect, - nsSVGNumberPair *aKernelUnitLength) -{ - ScaleInfo result; - result.mRescaling = aKernelUnitLength->IsExplicitlySet(); - if (!result.mRescaling) { - result.mSource = aSource->mImage; - result.mTarget = aTarget->mImage; - result.mDataRect = aDataRect; - return result; - } - - gfxFloat kernelX = aInstance->GetPrimitiveNumber(SVGContentUtils::X, - aKernelUnitLength, - nsSVGNumberPair::eFirst); - gfxFloat kernelY = aInstance->GetPrimitiveNumber(SVGContentUtils::Y, - aKernelUnitLength, - nsSVGNumberPair::eSecond); - if (kernelX <= 0 || kernelY <= 0) - return result; - - bool overflow = false; - gfxIntSize scaledSize = - nsSVGUtils::ConvertToSurfaceSize(gfxSize(aTarget->mImage->Width() / kernelX, - aTarget->mImage->Height() / kernelY), - &overflow); - // If the requested size based on the kernel unit is too big, we - // need to bail because the effect is pixel size dependent. Also - // need to check if we ended up with a negative size (arithmetic - // overflow) or zero size (large kernel unit) - if (overflow || scaledSize.width <= 0 || scaledSize.height <= 0) - return result; - - gfxRect r(aDataRect.x, aDataRect.y, aDataRect.width, aDataRect.height); - r.Scale(1 / kernelX, 1 / kernelY); - r.RoundOut(); - if (!gfxUtils::GfxRectToIntRect(r, &result.mDataRect)) - return result; - - // Rounding in the code above can mean that result.mDataRect is not contained - // within the bounds of the surfaces that we're about to create. We must - // clamp to these bounds to prevent out-of-bounds reads and writes: - result.mDataRect.IntersectRect(result.mDataRect, - nsIntRect(nsIntPoint(), scaledSize)); - - result.mSource = new gfxImageSurface(scaledSize, - gfxASurface::ImageFormatARGB32); - result.mTarget = new gfxImageSurface(scaledSize, - gfxASurface::ImageFormatARGB32); - if (!result.mSource || result.mSource->CairoStatus() || - !result.mTarget || result.mTarget->CairoStatus()) { - result.mSource = nullptr; - result.mTarget = nullptr; - return result; - } - - CopyAndScaleDeviceOffset(aSource->mImage, result.mSource, kernelX, kernelY); - CopyAndScaleDeviceOffset(aTarget->mImage, result.mTarget, kernelX, kernelY); - - result.mRealTarget = aTarget->mImage; - gfxContext ctx(result.mSource); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.Scale(double(scaledSize.width) / aTarget->mImage->Width(), - double(scaledSize.height) / aTarget->mImage->Height()); - ctx.SetSource(aSource->mImage); - ctx.Paint(); - - // mTarget was already cleared when it was created - - return result; -} - -void -nsSVGFE::FinishScalingFilter(ScaleInfo *aScaleInfo) -{ - if (!aScaleInfo->mRescaling) - return; - - gfxIntSize scaledSize = aScaleInfo->mTarget->GetSize(); - - gfxContext ctx(aScaleInfo->mRealTarget); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.Scale(double(aScaleInfo->mRealTarget->Width()) / scaledSize.width, - double(aScaleInfo->mRealTarget->Height()) / scaledSize.height); - ctx.SetSource(aScaleInfo->mTarget); - ctx.Paint(); -} - -nsIntRect -nsSVGFE::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - nsIntRect r; - for (uint32_t i = 0; i < aSourceBBoxes.Length(); ++i) { - r.UnionRect(r, aSourceBBoxes[i]); - } - return r; -} - -void -nsSVGFE::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - for (uint32_t i = 0; i < aSourceBBoxes.Length(); ++i) { - aSourceBBoxes[i] = aTargetBBox; - } -} - -nsIntRect -nsSVGFE::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - nsIntRect r; - for (uint32_t i = 0; i < aSourceChangeBoxes.Length(); ++i) { - r.UnionRect(r, aSourceChangeBoxes[i]); - } - return r; -} - -void -nsSVGFE::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ -} - -bool -nsSVGFE::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::x || - aAttribute == nsGkAtoms::y || - aAttribute == nsGkAtoms::width || - aAttribute == nsGkAtoms::height || - aAttribute == nsGkAtoms::result); -} - -//---------------------------------------------------------------------- -// nsIDOMSVGFilterPrimitiveStandardAttributes methods - -/* readonly attribute nsIDOMSVGAnimatedLength x; */ -NS_IMETHODIMP nsSVGFE::GetX(nsIDOMSVGAnimatedLength * *aX) -{ - *aX = X().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::X() -{ - return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength y; */ -NS_IMETHODIMP nsSVGFE::GetY(nsIDOMSVGAnimatedLength * *aY) -{ - *aY = Y().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Y() -{ - return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength width; */ -NS_IMETHODIMP nsSVGFE::GetWidth(nsIDOMSVGAnimatedLength * *aWidth) -{ - *aWidth = Width().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Width() -{ - return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength height; */ -NS_IMETHODIMP nsSVGFE::GetHeight(nsIDOMSVGAnimatedLength * *aHeight) -{ - *aHeight = Height().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Height() -{ - return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedString result; */ -NS_IMETHODIMP nsSVGFE::GetResult(nsIDOMSVGAnimatedString * *aResult) -{ - *aResult = Result().get(); - return NS_OK; -} - -already_AddRefed<nsIDOMSVGAnimatedString> -nsSVGFE::Result() -{ - return GetResultImageName().ToDOMAnimatedString(this); -} - -//---------------------------------------------------------------------- -// nsIContent methods - -NS_IMETHODIMP_(bool) -nsSVGFE::IsAttributeMapped(const nsIAtom* name) const -{ - static const MappedAttributeEntry* const map[] = { - sFiltersMap - }; - - return FindAttributeDependence(name, map) || - nsSVGFEBase::IsAttributeMapped(name); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -/* virtual */ bool -nsSVGFE::HasValidDimensions() const -{ - return (!mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() || - mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0) && - (!mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() || - mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0); -} - -nsSVGElement::LengthAttributesInfo -nsSVGFE::GetLengthInfo() -{ - return LengthAttributesInfo(mLengthAttributes, sLengthInfo, - ArrayLength(sLengthInfo)); -} +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEMorphology) namespace mozilla { namespace dom { -nsSVGElement::NumberListInfo SVGComponentTransferFunctionElement::sNumberListInfo[1] = +JSObject* +SVGFEMorphologyElement::WrapNode(JSContext* aCx, JSObject* aScope) { - { &nsGkAtoms::tableValues } + return SVGFEMorphologyElementBinding::Wrap(aCx, aScope, this); +} + +// Morphology Operators +static const unsigned short SVG_OPERATOR_UNKNOWN = 0; +static const unsigned short SVG_OPERATOR_ERODE = 1; +static const unsigned short SVG_OPERATOR_DILATE = 2; + +nsSVGElement::NumberPairInfo SVGFEMorphologyElement::sNumberPairInfo[1] = +{ + { &nsGkAtoms::radius, 0, 0 } }; -nsSVGElement::NumberInfo SVGComponentTransferFunctionElement::sNumberInfo[5] = -{ - { &nsGkAtoms::slope, 1, false }, - { &nsGkAtoms::intercept, 0, false }, - { &nsGkAtoms::amplitude, 1, false }, - { &nsGkAtoms::exponent, 1, false }, - { &nsGkAtoms::offset, 0, false } -}; - -nsSVGEnumMapping SVGComponentTransferFunctionElement::sTypeMap[] = { - {&nsGkAtoms::identity, - SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY}, - {&nsGkAtoms::table, - SVG_FECOMPONENTTRANSFER_TYPE_TABLE}, - {&nsGkAtoms::discrete, - SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE}, - {&nsGkAtoms::linear, - SVG_FECOMPONENTTRANSFER_TYPE_LINEAR}, - {&nsGkAtoms::gamma, - SVG_FECOMPONENTTRANSFER_TYPE_GAMMA}, +nsSVGEnumMapping SVGFEMorphologyElement::sOperatorMap[] = { + {&nsGkAtoms::erode, SVG_OPERATOR_ERODE}, + {&nsGkAtoms::dilate, SVG_OPERATOR_DILATE}, {nullptr, 0} }; -nsSVGElement::EnumInfo SVGComponentTransferFunctionElement::sEnumInfo[1] = +nsSVGElement::EnumInfo SVGFEMorphologyElement::sEnumInfo[1] = { - { &nsGkAtoms::type, - sTypeMap, - SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY + { &nsGkAtoms::_operator, + sOperatorMap, + SVG_OPERATOR_ERODE } }; +nsSVGElement::StringInfo SVGFEMorphologyElement::sStringInfo[2] = +{ + { &nsGkAtoms::result, kNameSpaceID_None, true }, + { &nsGkAtoms::in, kNameSpaceID_None, true } +}; + //---------------------------------------------------------------------- // nsISupports methods -NS_IMPL_ADDREF_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) -NS_IMPL_RELEASE_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) - -NS_DEFINE_STATIC_IID_ACCESSOR(SVGComponentTransferFunctionElement, NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID) - -NS_INTERFACE_MAP_BEGIN(SVGComponentTransferFunctionElement) - // nsISupports is an ambiguous base of nsSVGFE so we have to work - // around that - if ( aIID.Equals(NS_GET_IID(SVGComponentTransferFunctionElement)) ) - foundInterface = static_cast<nsISupports*>(static_cast<void*>(this)); - else -NS_INTERFACE_MAP_END_INHERITING(SVGComponentTransferFunctionElementBase) - - -//---------------------------------------------------------------------- -// nsFEUnstyledElement methods - -bool -SVGComponentTransferFunctionElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::tableValues || - aAttribute == nsGkAtoms::slope || - aAttribute == nsGkAtoms::intercept || - aAttribute == nsGkAtoms::amplitude || - aAttribute == nsGkAtoms::exponent || - aAttribute == nsGkAtoms::offset || - aAttribute == nsGkAtoms::type); -} - -//---------------------------------------------------------------------- - -already_AddRefed<nsIDOMSVGAnimatedEnumeration> -SVGComponentTransferFunctionElement::Type() -{ - return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this); -} - -already_AddRefed<DOMSVGAnimatedNumberList> -SVGComponentTransferFunctionElement::TableValues() -{ - return DOMSVGAnimatedNumberList::GetDOMWrapper( - &mNumberListAttributes[TABLEVALUES], this, TABLEVALUES); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Slope() -{ - return mNumberAttributes[SLOPE].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Intercept() -{ - return mNumberAttributes[INTERCEPT].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Amplitude() -{ - return mNumberAttributes[AMPLITUDE].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Exponent() -{ - return mNumberAttributes[EXPONENT].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Offset() -{ - return mNumberAttributes[OFFSET].ToDOMAnimatedNumber(this); -} - -bool -SVGComponentTransferFunctionElement::GenerateLookupTable(uint8_t *aTable) -{ - uint16_t type = mEnumAttributes[TYPE].GetAnimValue(); - - float slope, intercept, amplitude, exponent, offset; - GetAnimatedNumberValues(&slope, &intercept, &litude, - &exponent, &offset, nullptr); - - const SVGNumberList &tableValues = - mNumberListAttributes[TABLEVALUES].GetAnimValue(); - uint32_t tvLength = tableValues.Length(); - - uint32_t i; - - switch (type) { - case SVG_FECOMPONENTTRANSFER_TYPE_TABLE: - { - if (tableValues.Length() < 2) - return false; - - for (i = 0; i < 256; i++) { - uint32_t k = (i * (tvLength - 1)) / 255; - float v1 = tableValues[k]; - float v2 = tableValues[std::min(k + 1, tvLength - 1)]; - int32_t val = - int32_t(255 * (v1 + (i/255.0f - k/float(tvLength-1))*(tvLength - 1)*(v2 - v1))); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: - { - if (tableValues.Length() < 1) - return false; - - for (i = 0; i < 256; i++) { - uint32_t k = (i * tvLength) / 255; - k = std::min(k, tvLength - 1); - float v = tableValues[k]; - int32_t val = int32_t(255 * v); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: - { - for (i = 0; i < 256; i++) { - int32_t val = int32_t(slope * i + 255 * intercept); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: - { - for (i = 0; i < 256; i++) { - int32_t val = int32_t(255 * (amplitude * pow(i / 255.0f, exponent) + offset)); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: - default: - break; - } - return true; -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberListAttributesInfo -SVGComponentTransferFunctionElement::GetNumberListInfo() -{ - return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, - ArrayLength(sNumberListInfo)); -} - -nsSVGElement::EnumAttributesInfo -SVGComponentTransferFunctionElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::NumberAttributesInfo -SVGComponentTransferFunctionElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncRElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncRElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncRElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncR) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncRElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncGElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncGElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncGElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncG) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncGElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncBElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncBElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncBElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncB) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncBElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncAElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncAElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncAElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncA) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncAElement) - -} // namespace dom -} // namespace mozilla - -//---------------------Turbulence------------------------ - -typedef nsSVGFE nsSVGFETurbulenceElementBase; - -class nsSVGFETurbulenceElement : public nsSVGFETurbulenceElementBase, - public nsIDOMSVGFETurbulenceElement -{ - friend nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFETurbulenceElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFETurbulenceElementBase(aNodeInfo) {} - -public: - virtual bool SubregionIsUnionOfRegions() { return false; } - - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::) - - virtual nsresult Filter(nsSVGFilterInstance* aInstance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& aDataRect); - virtual bool AttributeAffectsRendering( - int32_t aNameSpaceID, nsIAtom* aAttribute) const; - virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; } - virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance); - - // Turbulence - NS_DECL_NSIDOMSVGFETURBULENCEELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::) - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual NumberAttributesInfo GetNumberInfo(); - virtual NumberPairAttributesInfo GetNumberPairInfo(); - virtual IntegerAttributesInfo GetIntegerInfo(); - virtual EnumAttributesInfo GetEnumInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { SEED }; // floating point seed?! - nsSVGNumber2 mNumberAttributes[1]; - static NumberInfo sNumberInfo[1]; - - enum { BASE_FREQ }; - nsSVGNumberPair mNumberPairAttributes[1]; - static NumberPairInfo sNumberPairInfo[1]; - - enum { OCTAVES }; - nsSVGInteger mIntegerAttributes[1]; - static IntegerInfo sIntegerInfo[1]; - - enum { TYPE, STITCHTILES }; - nsSVGEnum mEnumAttributes[2]; - static nsSVGEnumMapping sTypeMap[]; - static nsSVGEnumMapping sStitchTilesMap[]; - static EnumInfo sEnumInfo[2]; - - enum { RESULT }; - nsSVGString mStringAttributes[1]; - static StringInfo sStringInfo[1]; - -private: - - /* The turbulence calculation code is an adapted version of what - appears in the SVG 1.1 specification: - http://www.w3.org/TR/SVG11/filters.html#feTurbulence - */ - - /* Produces results in the range [1, 2**31 - 2]. - Algorithm is: r = (a * r) mod m - where a = 16807 and m = 2**31 - 1 = 2147483647 - See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988 - To test: the algorithm should produce the result 1043618065 - as the 10,000th generated number if the original seed is 1. - */ -#define RAND_M 2147483647 /* 2**31 - 1 */ -#define RAND_A 16807 /* 7**5; primitive root of m */ -#define RAND_Q 127773 /* m / a */ -#define RAND_R 2836 /* m % a */ - - int32_t SetupSeed(int32_t aSeed) { - if (aSeed <= 0) - aSeed = -(aSeed % (RAND_M - 1)) + 1; - if (aSeed > RAND_M - 1) - aSeed = RAND_M - 1; - return aSeed; - } - - uint32_t Random(uint32_t aSeed) { - int32_t result = RAND_A * (aSeed % RAND_Q) - RAND_R * (aSeed / RAND_Q); - if (result <= 0) - result += RAND_M; - return result; - } -#undef RAND_M -#undef RAND_A -#undef RAND_Q -#undef RAND_R - - const static int sBSize = 0x100; - const static int sBM = 0xff; - const static int sPerlinN = 0x1000; - const static int sNP = 12; /* 2^PerlinN */ - const static int sNM = 0xfff; - - int32_t mLatticeSelector[sBSize + sBSize + 2]; - double mGradient[4][sBSize + sBSize + 2][2]; - struct StitchInfo { - int mWidth; // How much to subtract to wrap for stitching. - int mHeight; - int mWrapX; // Minimum value to wrap. - int mWrapY; - }; - - void InitSeed(int32_t aSeed); - double Noise2(int aColorChannel, double aVec[2], StitchInfo *aStitchInfo); - double - Turbulence(int aColorChannel, double *aPoint, double aBaseFreqX, - double aBaseFreqY, int aNumOctaves, bool aFractalSum, - bool aDoStitching, double aTileX, double aTileY, - double aTileWidth, double aTileHeight); -}; - -nsSVGElement::NumberInfo nsSVGFETurbulenceElement::sNumberInfo[1] = -{ - { &nsGkAtoms::seed, 0, false } -}; - -nsSVGElement::NumberPairInfo nsSVGFETurbulenceElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::baseFrequency, 0, 0 } -}; - -nsSVGElement::IntegerInfo nsSVGFETurbulenceElement::sIntegerInfo[1] = -{ - { &nsGkAtoms::numOctaves, 1 } -}; - -nsSVGEnumMapping nsSVGFETurbulenceElement::sTypeMap[] = { - {&nsGkAtoms::fractalNoise, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_FRACTALNOISE}, - {&nsGkAtoms::turbulence, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE}, - {nullptr, 0} -}; - -nsSVGEnumMapping nsSVGFETurbulenceElement::sStitchTilesMap[] = { - {&nsGkAtoms::stitch, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH}, - {&nsGkAtoms::noStitch, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFETurbulenceElement::sEnumInfo[2] = -{ - { &nsGkAtoms::type, - sTypeMap, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE - }, - { &nsGkAtoms::stitchTiles, - sStitchTilesMap, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH - } -}; - -nsSVGElement::StringInfo nsSVGFETurbulenceElement::sStringInfo[1] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase) - -DOMCI_NODE_DATA(SVGFETurbulenceElement, nsSVGFETurbulenceElement) +NS_IMPL_ADDREF_INHERITED(SVGFEMorphologyElement,SVGFEMorphologyElementBase) +NS_IMPL_RELEASE_INHERITED(SVGFEMorphologyElement,SVGFEMorphologyElementBase) -NS_INTERFACE_TABLE_HEAD(nsSVGFETurbulenceElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFETurbulenceElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFETurbulenceElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETurbulenceElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFETurbulenceElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETurbulenceElement) - -//---------------------------------------------------------------------- -// nsIDOMSVGFETurbulenceElement methods - -/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyX(nsIDOMSVGAnimatedNumber * *aX) -{ - return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyY(nsIDOMSVGAnimatedNumber * *aY) -{ - return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this); -} - -/* readonly attribute nsIDOMSVGAnimatedInteger numOctaves; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetNumOctaves(nsIDOMSVGAnimatedInteger * *aNum) -{ - return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(aNum, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber seed; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetSeed(nsIDOMSVGAnimatedNumber * *aSeed) -{ - return mNumberAttributes[SEED].ToDOMAnimatedNumber(aSeed, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetStitchTiles(nsIDOMSVGAnimatedEnumeration * *aStitch) -{ - return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(aStitch, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType) -{ - return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this); -} - -nsresult -nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - uint8_t* targetData = aTarget->mImage->Data(); - uint32_t stride = aTarget->mImage->Stride(); - - nsIntRect filterSubregion(int32_t(aTarget->mFilterPrimitiveSubregion.X()), - int32_t(aTarget->mFilterPrimitiveSubregion.Y()), - int32_t(aTarget->mFilterPrimitiveSubregion.Width()), - int32_t(aTarget->mFilterPrimitiveSubregion.Height())); - - float fX = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eFirst); - float fY = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eSecond); - float seed = mNumberAttributes[OCTAVES].GetAnimValue(); - int32_t octaves = mIntegerAttributes[OCTAVES].GetAnimValue(); - uint16_t type = mEnumAttributes[TYPE].GetAnimValue(); - uint16_t stitch = mEnumAttributes[STITCHTILES].GetAnimValue(); - - InitSeed((int32_t)seed); - - // XXXroc this makes absolutely no sense to me. - float filterX = instance->GetFilterRegion().X(); - float filterY = instance->GetFilterRegion().Y(); - float filterWidth = instance->GetFilterRegion().Width(); - float filterHeight = instance->GetFilterRegion().Height(); - - bool doStitch = false; - if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) { - doStitch = true; - - float lowFreq, hiFreq; - - lowFreq = floor(filterWidth * fX) / filterWidth; - hiFreq = ceil(filterWidth * fX) / filterWidth; - if (fX / lowFreq < hiFreq / fX) - fX = lowFreq; - else - fX = hiFreq; - - lowFreq = floor(filterHeight * fY) / filterHeight; - hiFreq = ceil(filterHeight * fY) / filterHeight; - if (fY / lowFreq < hiFreq / fY) - fY = lowFreq; - else - fY = hiFreq; - } - for (int32_t y = rect.y; y < rect.YMost(); y++) { - for (int32_t x = rect.x; x < rect.XMost(); x++) { - int32_t targIndex = y * stride + x * 4; - double point[2]; - point[0] = filterX + (filterWidth * (x + instance->GetSurfaceRect().x)) / (filterSubregion.width - 1); - point[1] = filterY + (filterHeight * (y + instance->GetSurfaceRect().y)) / (filterSubregion.height - 1); - - float col[4]; - if (type == nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE) { - for (int i = 0; i < 4; i++) - col[i] = Turbulence(i, point, fX, fY, octaves, false, - doStitch, filterX, filterY, filterWidth, filterHeight) * 255; - } else { - for (int i = 0; i < 4; i++) - col[i] = (Turbulence(i, point, fX, fY, octaves, true, - doStitch, filterX, filterY, filterWidth, filterHeight) * 255 + 255) / 2; - } - for (int i = 0; i < 4; i++) { - col[i] = std::min(col[i], 255.f); - col[i] = std::max(col[i], 0.f); - } - - uint8_t r, g, b, a; - a = uint8_t(col[3]); - FAST_DIVIDE_BY_255(r, unsigned(col[0]) * a); - FAST_DIVIDE_BY_255(g, unsigned(col[1]) * a); - FAST_DIVIDE_BY_255(b, unsigned(col[2]) * a); - - targetData[targIndex + GFX_ARGB32_OFFSET_B] = b; - targetData[targIndex + GFX_ARGB32_OFFSET_G] = g; - targetData[targIndex + GFX_ARGB32_OFFSET_R] = r; - targetData[targIndex + GFX_ARGB32_OFFSET_A] = a; - } - } - - return NS_OK; -} - -bool -nsSVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::seed || - aAttribute == nsGkAtoms::baseFrequency || - aAttribute == nsGkAtoms::numOctaves || - aAttribute == nsGkAtoms::type || - aAttribute == nsGkAtoms::stitchTiles)); -} - -void -nsSVGFETurbulenceElement::InitSeed(int32_t aSeed) -{ - double s; - int i, j, k; - aSeed = SetupSeed(aSeed); - for (k = 0; k < 4; k++) { - for (i = 0; i < sBSize; i++) { - mLatticeSelector[i] = i; - for (j = 0; j < 2; j++) { - mGradient[k][i][j] = - (double) (((aSeed = - Random(aSeed)) % (sBSize + sBSize)) - sBSize) / sBSize; - } - s = double (sqrt - (mGradient[k][i][0] * mGradient[k][i][0] + - mGradient[k][i][1] * mGradient[k][i][1])); - mGradient[k][i][0] /= s; - mGradient[k][i][1] /= s; - } - } - while (--i) { - k = mLatticeSelector[i]; - mLatticeSelector[i] = mLatticeSelector[j = - (aSeed = - Random(aSeed)) % sBSize]; - mLatticeSelector[j] = k; - } - for (i = 0; i < sBSize + 2; i++) { - mLatticeSelector[sBSize + i] = mLatticeSelector[i]; - for (k = 0; k < 4; k++) - for (j = 0; j < 2; j++) - mGradient[k][sBSize + i][j] = mGradient[k][i][j]; - } -} - -#define S_CURVE(t) ( t * t * (3. - 2. * t) ) -#define LERP(t, a, b) ( a + t * (b - a) ) -double -nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2], - StitchInfo *aStitchInfo) -{ - int bx0, bx1, by0, by1, b00, b10, b01, b11; - double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v; - register long i, j; - t = aVec[0] + sPerlinN; - bx0 = (int) t; - bx1 = bx0 + 1; - rx0 = t - (int) t; - rx1 = rx0 - 1.0f; - t = aVec[1] + sPerlinN; - by0 = (int) t; - by1 = by0 + 1; - ry0 = t - (int) t; - ry1 = ry0 - 1.0f; - // If stitching, adjust lattice points accordingly. - if (aStitchInfo != NULL) { - if (bx0 >= aStitchInfo->mWrapX) - bx0 -= aStitchInfo->mWidth; - if (bx1 >= aStitchInfo->mWrapX) - bx1 -= aStitchInfo->mWidth; - if (by0 >= aStitchInfo->mWrapY) - by0 -= aStitchInfo->mHeight; - if (by1 >= aStitchInfo->mWrapY) - by1 -= aStitchInfo->mHeight; - } - bx0 &= sBM; - bx1 &= sBM; - by0 &= sBM; - by1 &= sBM; - i = mLatticeSelector[bx0]; - j = mLatticeSelector[bx1]; - b00 = mLatticeSelector[i + by0]; - b10 = mLatticeSelector[j + by0]; - b01 = mLatticeSelector[i + by1]; - b11 = mLatticeSelector[j + by1]; - sx = double (S_CURVE(rx0)); - sy = double (S_CURVE(ry0)); - q = mGradient[aColorChannel][b00]; - u = rx0 * q[0] + ry0 * q[1]; - q = mGradient[aColorChannel][b10]; - v = rx1 * q[0] + ry0 * q[1]; - a = LERP(sx, u, v); - q = mGradient[aColorChannel][b01]; - u = rx0 * q[0] + ry1 * q[1]; - q = mGradient[aColorChannel][b11]; - v = rx1 * q[0] + ry1 * q[1]; - b = LERP(sx, u, v); - return LERP(sy, a, b); -} -#undef S_CURVE -#undef LERP - -double -nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint, - double aBaseFreqX, double aBaseFreqY, - int aNumOctaves, bool aFractalSum, - bool aDoStitching, - double aTileX, double aTileY, - double aTileWidth, double aTileHeight) -{ - StitchInfo stitch; - StitchInfo *stitchInfo = NULL; // Not stitching when NULL. - // Adjust the base frequencies if necessary for stitching. - if (aDoStitching) { - // When stitching tiled turbulence, the frequencies must be adjusted - // so that the tile borders will be continuous. - if (aBaseFreqX != 0.0) { - double loFreq = double (floor(aTileWidth * aBaseFreqX)) / aTileWidth; - double hiFreq = double (ceil(aTileWidth * aBaseFreqX)) / aTileWidth; - if (aBaseFreqX / loFreq < hiFreq / aBaseFreqX) - aBaseFreqX = loFreq; - else - aBaseFreqX = hiFreq; - } - if (aBaseFreqY != 0.0) { - double loFreq = double (floor(aTileHeight * aBaseFreqY)) / aTileHeight; - double hiFreq = double (ceil(aTileHeight * aBaseFreqY)) / aTileHeight; - if (aBaseFreqY / loFreq < hiFreq / aBaseFreqY) - aBaseFreqY = loFreq; - else - aBaseFreqY = hiFreq; - } - // Set up initial stitch values. - stitchInfo = &stitch; - stitch.mWidth = int (aTileWidth * aBaseFreqX + 0.5f); - stitch.mWrapX = int (aTileX * aBaseFreqX + sPerlinN + stitch.mWidth); - stitch.mHeight = int (aTileHeight * aBaseFreqY + 0.5f); - stitch.mWrapY = int (aTileY * aBaseFreqY + sPerlinN + stitch.mHeight); - } - double sum = 0.0f; - double vec[2]; - vec[0] = aPoint[0] * aBaseFreqX; - vec[1] = aPoint[1] * aBaseFreqY; - double ratio = 1; - for (int octave = 0; octave < aNumOctaves; octave++) { - if (aFractalSum) - sum += double (Noise2(aColorChannel, vec, stitchInfo) / ratio); - else - sum += double (fabs(Noise2(aColorChannel, vec, stitchInfo)) / ratio); - vec[0] *= 2; - vec[1] *= 2; - ratio *= 2; - if (stitchInfo != NULL) { - // Update stitch values. Subtracting sPerlinN before the multiplication - // and adding it afterward simplifies to subtracting it once. - stitch.mWidth *= 2; - stitch.mWrapX = 2 * stitch.mWrapX - sPerlinN; - stitch.mHeight *= 2; - stitch.mWrapY = 2 * stitch.mWrapY - sPerlinN; - } - } - return sum; -} - -nsIntRect -nsSVGFETurbulenceElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - return GetMaxRect(); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFETurbulenceElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -nsSVGElement::NumberPairAttributesInfo -nsSVGFETurbulenceElement::GetNumberPairInfo() -{ - return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, - ArrayLength(sNumberPairInfo)); -} - -nsSVGElement::IntegerAttributesInfo -nsSVGFETurbulenceElement::GetIntegerInfo() -{ - return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo, - ArrayLength(sIntegerInfo)); -} - -nsSVGElement::EnumAttributesInfo -nsSVGFETurbulenceElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFETurbulenceElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Morphology------------------------ - -typedef nsSVGFE nsSVGFEMorphologyElementBase; - -class nsSVGFEMorphologyElement : public nsSVGFEMorphologyElementBase, - public nsIDOMSVGFEMorphologyElement -{ - friend nsresult NS_NewSVGFEMorphologyElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEMorphologyElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEMorphologyElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMorphologyElementBase::) - - virtual nsresult Filter(nsSVGFilterInstance* aInstance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& aDataRect); - virtual bool AttributeAffectsRendering( - int32_t aNameSpaceID, nsIAtom* aAttribute) const; - virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; } - virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources); - virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance); - virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance); - virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance); - - // Morphology - NS_DECL_NSIDOMSVGFEMORPHOLOGYELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMorphologyElementBase::) - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - void GetRXY(int32_t *aRX, int32_t *aRY, const nsSVGFilterInstance& aInstance); - nsIntRect InflateRect(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance); - - virtual NumberPairAttributesInfo GetNumberPairInfo(); - virtual EnumAttributesInfo GetEnumInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { RADIUS }; - nsSVGNumberPair mNumberPairAttributes[1]; - static NumberPairInfo sNumberPairInfo[1]; - - enum { OPERATOR }; - nsSVGEnum mEnumAttributes[1]; - static nsSVGEnumMapping sOperatorMap[]; - static EnumInfo sEnumInfo[1]; - - enum { RESULT, IN1 }; - nsSVGString mStringAttributes[2]; - static StringInfo sStringInfo[2]; -}; - -nsSVGElement::NumberPairInfo nsSVGFEMorphologyElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::radius, 0, 0 } -}; - -nsSVGEnumMapping nsSVGFEMorphologyElement::sOperatorMap[] = { - {&nsGkAtoms::erode, nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE}, - {&nsGkAtoms::dilate, nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFEMorphologyElement::sEnumInfo[1] = -{ - { &nsGkAtoms::_operator, - sOperatorMap, - nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE - } -}; - -nsSVGElement::StringInfo nsSVGFEMorphologyElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEMorphology) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase) - -DOMCI_NODE_DATA(SVGFEMorphologyElement, nsSVGFEMorphologyElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEMorphologyElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEMorphologyElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEMorphologyElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMorphologyElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMorphologyElementBase) +NS_INTERFACE_TABLE_HEAD(SVGFEMorphologyElement) + NS_NODE_INTERFACE_TABLE3(SVGFEMorphologyElement, nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement) +NS_INTERFACE_MAP_END_INHERITING(SVGFEMorphologyElementBase) //---------------------------------------------------------------------- // nsIDOMNode methods -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMorphologyElement) +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEMorphologyElement) //---------------------------------------------------------------------- -// nsSVGFEMorphologyElement methods +// SVGFEMorphologyElement methods -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) +already_AddRefed<nsIDOMSVGAnimatedString> +SVGFEMorphologyElement::In1() { - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration operator; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetOperator(nsIDOMSVGAnimatedEnumeration * *aOperator) -{ - return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(aOperator, this); + return mStringAttributes[IN1].ToDOMAnimatedString(this); } -/* readonly attribute nsIDOMSVGAnimatedNumber radiusX; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusX(nsIDOMSVGAnimatedNumber * *aX) +already_AddRefed<nsIDOMSVGAnimatedEnumeration> +SVGFEMorphologyElement::Operator() { - return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this); + return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(this); } -/* readonly attribute nsIDOMSVGAnimatedNumber radiusY; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusY(nsIDOMSVGAnimatedNumber * *aY) +already_AddRefed<nsIDOMSVGAnimatedNumber> +SVGFEMorphologyElement::RadiusX() { - return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this); + return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(nsSVGNumberPair::eFirst, this); } -NS_IMETHODIMP -nsSVGFEMorphologyElement::SetRadius(float rx, float ry) +already_AddRefed<nsIDOMSVGAnimatedNumber> +SVGFEMorphologyElement::RadiusY() { - NS_ENSURE_FINITE2(rx, ry, NS_ERROR_ILLEGAL_VALUE); - mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this); - return NS_OK; + return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(nsSVGNumberPair::eSecond, this); } void -nsSVGFEMorphologyElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) +SVGFEMorphologyElement::SetRadius(float rx, float ry) +{ + mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this); +} + +void +SVGFEMorphologyElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) { aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); } nsIntRect -nsSVGFEMorphologyElement::InflateRect(const nsIntRect& aRect, - const nsSVGFilterInstance& aInstance) +SVGFEMorphologyElement::InflateRect(const nsIntRect& aRect, + const nsSVGFilterInstance& aInstance) { int32_t rx, ry; GetRXY(&rx, &ry, aInstance); nsIntRect result = aRect; result.Inflate(std::max(0, rx), std::max(0, ry)); return result; } nsIntRect -nsSVGFEMorphologyElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, +SVGFEMorphologyElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) { return InflateRect(aSourceBBoxes[0], aInstance); } void -nsSVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, +SVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) { aSourceBBoxes[0] = InflateRect(aTargetBBox, aInstance); } nsIntRect -nsSVGFEMorphologyElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) +SVGFEMorphologyElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, + const nsSVGFilterInstance& aInstance) { return InflateRect(aSourceChangeBoxes[0], aInstance); } #define MORPHOLOGY_EPSILON 0.0001 void -nsSVGFEMorphologyElement::GetRXY(int32_t *aRX, int32_t *aRY, - const nsSVGFilterInstance& aInstance) +SVGFEMorphologyElement::GetRXY(int32_t *aRX, int32_t *aRY, + const nsSVGFilterInstance& aInstance) { // Subtract an epsilon here because we don't want a value that's just // slightly larger than an integer to round up to the next integer; it's // probably meant to be the integer it's close to, modulo machine precision // issues. *aRX = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::X, &mNumberPairAttributes[RADIUS], nsSVGNumberPair::eFirst) - MORPHOLOGY_EPSILON); *aRY = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::Y, &mNumberPairAttributes[RADIUS], nsSVGNumberPair::eSecond) - MORPHOLOGY_EPSILON); } nsresult -nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) +SVGFEMorphologyElement::Filter(nsSVGFilterInstance* instance, + const nsTArray<const Image*>& aSources, + const Image* aTarget, + const nsIntRect& rect) { int32_t rx, ry; GetRXY(&rx, &ry, *instance); if (rx < 0 || ry < 0) { // XXX SVGContentUtils::ReportToConsole() return NS_OK; } @@ -1461,410 +199,62 @@ nsSVGFEMorphologyElement::Filter(nsSVGFi for (int32_t i = 0; i < 4; i++) { extrema[i] = sourceData[targIndex + i]; } for (int32_t y1 = startY; y1 <= endY; y1++) { for (int32_t x1 = startX; x1 <= endX; x1++) { for (int32_t i = 0; i < 4; i++) { uint8_t pixel = sourceData[y1 * stride + 4 * x1 + i]; if ((extrema[i] > pixel && - op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) || + op == SVG_OPERATOR_ERODE) || (extrema[i] < pixel && - op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) { + op == SVG_OPERATOR_DILATE)) { extrema[i] = pixel; } } } } targetData[targIndex ] = extrema[0]; targetData[targIndex+1] = extrema[1]; targetData[targIndex+2] = extrema[2]; targetData[targIndex+3] = extrema[3]; } } return NS_OK; } bool -nsSVGFEMorphologyElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const +SVGFEMorphologyElement::AttributeAffectsRendering(int32_t aNameSpaceID, + nsIAtom* aAttribute) const { - return nsSVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || + return SVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || (aNameSpaceID == kNameSpaceID_None && (aAttribute == nsGkAtoms::in || aAttribute == nsGkAtoms::radius || aAttribute == nsGkAtoms::_operator)); } //---------------------------------------------------------------------- // nsSVGElement methods nsSVGElement::NumberPairAttributesInfo -nsSVGFEMorphologyElement::GetNumberPairInfo() +SVGFEMorphologyElement::GetNumberPairInfo() { return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, ArrayLength(sNumberPairInfo)); } nsSVGElement::EnumAttributesInfo -nsSVGFEMorphologyElement::GetEnumInfo() +SVGFEMorphologyElement::GetEnumInfo() { return EnumAttributesInfo(mEnumAttributes, sEnumInfo, ArrayLength(sEnumInfo)); } nsSVGElement::StringAttributesInfo -nsSVGFEMorphologyElement::GetStringInfo() +SVGFEMorphologyElement::GetStringInfo() { return StringAttributesInfo(mStringAttributes, sStringInfo, ArrayLength(sStringInfo)); } -//-------------------------------------------------------------------- -// -nsSVGElement::NumberInfo nsSVGFELightingElement::sNumberInfo[4] = -{ - { &nsGkAtoms::surfaceScale, 1, false }, - { &nsGkAtoms::diffuseConstant, 1, false }, - { &nsGkAtoms::specularConstant, 1, false }, - { &nsGkAtoms::specularExponent, 1, false } -}; - -nsSVGElement::NumberPairInfo nsSVGFELightingElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::kernelUnitLength, 0, 0 } -}; - -nsSVGElement::StringInfo nsSVGFELightingElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase) - -NS_INTERFACE_MAP_BEGIN(nsSVGFELightingElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFELightingElementBase) - -//---------------------------------------------------------------------- -// Implementation - -NS_IMETHODIMP_(bool) -nsSVGFELightingElement::IsAttributeMapped(const nsIAtom* name) const -{ - static const MappedAttributeEntry* const map[] = { - sLightingEffectsMap - }; - - return FindAttributeDependence(name, map) || - nsSVGFELightingElementBase::IsAttributeMapped(name); -} - -void -nsSVGFELightingElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -void -nsSVGFELightingElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) -{ - // XXX lighting can depend on more than the target area, because - // of the kernels it uses. We could compute something precise here - // but just leave it and assume we use the entire source bounding box. -} - -nsIntRect -nsSVGFELightingElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - // XXX be conservative for now - return GetMaxRect(); -} - -static int32_t -Convolve3x3(const uint8_t *index, int32_t stride, - const int8_t kernel[3][3] -#ifdef DEBUG - , const uint8_t *minData, const uint8_t *maxData -#endif // DEBUG -) -{ - int32_t sum = 0; - for (int32_t y = 0; y < 3; y++) { - for (int32_t x = 0; x < 3; x++) { - int8_t k = kernel[y][x]; - if (k) { - const uint8_t *valPtr = index + (4 * (x - 1) + stride * (y - 1)); - NS_ASSERTION(valPtr >= minData, "out of bounds read (before buffer)"); - NS_ASSERTION(valPtr < maxData, "out of bounds read (after buffer)"); - sum += k * (*valPtr); - } - } - } - return sum; -} - -static void -GenerateNormal(float *N, const uint8_t *data, int32_t stride, - int32_t surfaceWidth, int32_t surfaceHeight, - int32_t x, int32_t y, float surfaceScale) -{ - // See this for source of constants: - // http://www.w3.org/TR/SVG11/filters.html#feDiffuseLightingElement - static const int8_t Kx[3][3][3][3] = - { { { { 0, 0, 0}, { 0, -2, 2}, { 0, -1, 1} }, - { { 0, 0, 0}, {-2, 0, 2}, {-1, 0, 1} }, - { { 0, 0, 0}, {-2, 2, 0}, {-1, 1, 0} } }, - { { { 0, -1, 1}, { 0, -2, 2}, { 0, -1, 1} }, - { { -1, 0, 1}, {-2, 0, 2}, {-1, 0, 1} }, - { { -1, 1, 0}, {-2, 2, 0}, {-1, 1, 0} } }, - { { { 0, -1, 1}, { 0, -2, 2}, { 0, 0, 0} }, - { { -1, 0, 1}, {-2, 0, 2}, { 0, 0, 0} }, - { { -1, 1, 0}, {-2, 2, 0}, { 0, 0, 0} } } }; - static const int8_t Ky[3][3][3][3] = - { { { { 0, 0, 0}, { 0, -2, -1}, { 0, 2, 1} }, - { { 0, 0, 0}, {-1, -2, -1}, { 1, 2, 1} }, - { { 0, 0, 0}, {-1, -2, 1}, { 1, 2, 0} } }, - { { { 0, -2, -1}, { 0, 0, 0}, { 0, 2, 1} }, - { { -1, -2, -1}, { 0, 0, 0}, { 1, 2, 1} }, - { { -1, -2, 0}, { 0, 0, 0}, { 1, 2, 0} } }, - { { { 0, -2, -1}, { 0, 2, 1}, { 0, 0, 0} }, - { { -1, -2, -1}, { 1, 2, 1}, { 0, 0, 0} }, - { { -1, -2, 0}, { 1, 2, 0}, { 0, 0, 0} } } }; - static const float FACTORx[3][3] = - { { 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0 }, - { 1.0 / 2.0, 1.0 / 4.0, 1.0 / 2.0 }, - { 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0 } }; - static const float FACTORy[3][3] = - { { 2.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0 }, - { 1.0 / 3.0, 1.0 / 4.0, 1.0 / 3.0 }, - { 2.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0 } }; - - // degenerate cases - if (surfaceWidth == 1 || surfaceHeight == 1) { - // just return a unit vector pointing towards the viewer - N[0] = 0; - N[1] = 0; - N[2] = 255; - return; - } - - int8_t xflag, yflag; - if (x == 0) { - xflag = 0; - } else if (x == surfaceWidth - 1) { - xflag = 2; - } else { - xflag = 1; - } - if (y == 0) { - yflag = 0; - } else if (y == surfaceHeight - 1) { - yflag = 2; - } else { - yflag = 1; - } - - const uint8_t *index = data + y * stride + 4 * x + GFX_ARGB32_OFFSET_A; - -#ifdef DEBUG - // For sanity-checking, to be sure we're not reading outside source buffer: - const uint8_t* minData = data; - const uint8_t* maxData = minData + (surfaceHeight * surfaceWidth * stride); - - // We'll sanity-check each value we read inside of Convolve3x3, but we - // might as well ensure we're passing it a valid pointer to start with, too: - NS_ASSERTION(index >= minData, "index points before buffer start"); - NS_ASSERTION(index < maxData, "index points after buffer end"); -#endif // DEBUG - - N[0] = -surfaceScale * FACTORx[yflag][xflag] * - Convolve3x3(index, stride, Kx[yflag][xflag] -#ifdef DEBUG - , minData, maxData -#endif // DEBUG - ); - - N[1] = -surfaceScale * FACTORy[yflag][xflag] * - Convolve3x3(index, stride, Ky[yflag][xflag] -#ifdef DEBUG - , minData, maxData -#endif // DEBUG - ); - N[2] = 255; - NORMALIZE(N); -} - -nsresult -nsSVGFELightingElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - ScaleInfo info = SetupScalingFilter(instance, aSources[0], aTarget, rect, - &mNumberPairAttributes[KERNEL_UNIT_LENGTH]); - if (!info.mTarget) - return NS_ERROR_FAILURE; - - SVGFEDistantLightElement* distantLight = nullptr; - SVGFEPointLightElement* pointLight = nullptr; - SVGFESpotLightElement* spotLight = nullptr; - - nsIFrame* frame = GetPrimaryFrame(); - if (!frame) return NS_ERROR_FAILURE; - nsStyleContext* style = frame->StyleContext(); - - nscolor lightColor = style->StyleSVGReset()->mLightingColor; - - // find specified light - for (nsCOMPtr<nsIContent> child = nsINode::GetFirstChild(); - child; - child = child->GetNextSibling()) { - distantLight = child->IsSVG(nsGkAtoms::feDistantLight) ? - static_cast<SVGFEDistantLightElement*>(child.get()) : nullptr; - pointLight = child->IsSVG(nsGkAtoms::fePointLight) ? - static_cast<SVGFEPointLightElement*>(child.get()) : nullptr; - spotLight = child->IsSVG(nsGkAtoms::feSpotLight) ? - static_cast<SVGFESpotLightElement*>(child.get()) : nullptr; - if (distantLight || pointLight || spotLight) - break; - } - - if (!distantLight && !pointLight && !spotLight) - return NS_ERROR_FAILURE; - - const float radPerDeg = M_PI/180.0; - - float L[3]; - if (distantLight) { - float azimuth, elevation; - distantLight->GetAnimatedNumberValues(&azimuth, - &elevation, - nullptr); - L[0] = cos(azimuth * radPerDeg) * cos(elevation * radPerDeg); - L[1] = sin(azimuth * radPerDeg) * cos(elevation * radPerDeg); - L[2] = sin(elevation * radPerDeg); - } - float lightPos[3], pointsAt[3], specularExponent; - float cosConeAngle = 0; - if (pointLight) { - pointLight->GetAnimatedNumberValues(lightPos, - lightPos + 1, - lightPos + 2, - nullptr); - instance->ConvertLocation(lightPos); - } - if (spotLight) { - float limitingConeAngle; - spotLight->GetAnimatedNumberValues(lightPos, - lightPos + 1, - lightPos + 2, - pointsAt, - pointsAt + 1, - pointsAt + 2, - &specularExponent, - &limitingConeAngle, - nullptr); - instance->ConvertLocation(lightPos); - instance->ConvertLocation(pointsAt); - - if (spotLight->mNumberAttributes[SVGFESpotLightElement::LIMITING_CONE_ANGLE]. - IsExplicitlySet()) { - cosConeAngle = std::max<double>(cos(limitingConeAngle * radPerDeg), 0.0); - } - } - - float surfaceScale = mNumberAttributes[SURFACE_SCALE].GetAnimValue(); - - const nsIntRect& dataRect = info.mDataRect; - int32_t stride = info.mSource->Stride(); - uint8_t *sourceData = info.mSource->Data(); - uint8_t *targetData = info.mTarget->Data(); - int32_t surfaceWidth = info.mSource->Width(); - int32_t surfaceHeight = info.mSource->Height(); - - for (int32_t y = dataRect.y; y < dataRect.YMost(); y++) { - for (int32_t x = dataRect.x; x < dataRect.XMost(); x++) { - int32_t index = y * stride + x * 4; - - float N[3]; - GenerateNormal(N, sourceData, stride, surfaceWidth, surfaceHeight, - x, y, surfaceScale); - - if (pointLight || spotLight) { - gfxPoint pt = instance->FilterSpaceToUserSpace( - gfxPoint(x + instance->GetSurfaceRect().x, - y + instance->GetSurfaceRect().y)); - float Z = surfaceScale * sourceData[index + GFX_ARGB32_OFFSET_A] / 255; - - L[0] = lightPos[0] - pt.x; - L[1] = lightPos[1] - pt.y; - L[2] = lightPos[2] - Z; - NORMALIZE(L); - } - - nscolor color; - - if (spotLight) { - float S[3]; - S[0] = pointsAt[0] - lightPos[0]; - S[1] = pointsAt[1] - lightPos[1]; - S[2] = pointsAt[2] - lightPos[2]; - NORMALIZE(S); - float dot = -DOT(L, S); - float tmp = pow(dot, specularExponent); - if (dot < cosConeAngle) tmp = 0; - color = NS_RGB(uint8_t(NS_GET_R(lightColor) * tmp), - uint8_t(NS_GET_G(lightColor) * tmp), - uint8_t(NS_GET_B(lightColor) * tmp)); - } else { - color = lightColor; - } - - LightPixel(N, L, color, targetData + index); - } - } - - FinishScalingFilter(&info); - - return NS_OK; -} - -bool -nsSVGFELightingElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFELightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::surfaceScale || - aAttribute == nsGkAtoms::kernelUnitLength)); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFELightingElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -nsSVGElement::NumberPairAttributesInfo -nsSVGFELightingElement::GetNumberPairInfo() -{ - return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, - ArrayLength(sNumberPairInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFELightingElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} +} // namespace dom +} // namespace mozilla
copy from content/svg/content/src/nsSVGFilters.cpp copy to content/svg/content/src/SVGFEMorphologyElement.h --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/SVGFEMorphologyElement.h @@ -1,1264 +1,77 @@ /* a*- 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 "nsSVGElement.h" -#include "nsGkAtoms.h" -#include "nsSVGNumber2.h" -#include "nsSVGNumberPair.h" -#include "nsSVGInteger.h" -#include "nsSVGIntegerPair.h" -#include "nsSVGBoolean.h" -#include "nsIDOMSVGFilters.h" -#include "nsCOMPtr.h" -#include "nsSVGFilterInstance.h" -#include "nsSVGEnum.h" -#include "SVGNumberList.h" -#include "SVGAnimatedNumberList.h" -#include "DOMSVGAnimatedNumberList.h" -#include "nsSVGFilters.h" -#include "nsLayoutUtils.h" -#include "nsSVGUtils.h" -#include "nsStyleContext.h" -#include "nsIFrame.h" -#include "gfxContext.h" -#include "gfxMatrix.h" -#include "imgIContainer.h" -#include "nsNetUtil.h" -#include "mozilla/dom/SVGFilterElement.h" -#include "nsSVGString.h" -#include "gfxUtils.h" -#include "SVGContentUtils.h" -#include <algorithm> -#include "nsContentUtils.h" -#include "mozilla/dom/SVGAnimatedLength.h" -#include "mozilla/dom/SVGComponentTransferFunctionElement.h" -#include "mozilla/dom/SVGFEDistantLightElement.h" -#include "mozilla/dom/SVGFEFuncAElementBinding.h" -#include "mozilla/dom/SVGFEFuncBElementBinding.h" -#include "mozilla/dom/SVGFEFuncGElementBinding.h" -#include "mozilla/dom/SVGFEFuncRElementBinding.h" -#include "mozilla/dom/SVGFEPointLightElement.h" -#include "mozilla/dom/SVGFESpotLightElement.h" - -#if defined(XP_WIN) -// Prevent Windows redefining LoadImage -#undef LoadImage -#endif - -using namespace mozilla; -using namespace mozilla::dom; - -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5; - -void -CopyDataRect(uint8_t *aDest, const uint8_t *aSrc, uint32_t aStride, - const nsIntRect& aDataRect) -{ - for (int32_t y = aDataRect.y; y < aDataRect.YMost(); y++) { - memcpy(aDest + y * aStride + 4 * aDataRect.x, - aSrc + y * aStride + 4 * aDataRect.x, - 4 * aDataRect.width); - } -} - -static void -CopyAndScaleDeviceOffset(const gfxImageSurface *aImage, gfxImageSurface *aResult, - gfxFloat kernelX, gfxFloat kernelY) -{ - gfxPoint deviceOffset = aImage->GetDeviceOffset(); - deviceOffset.x /= kernelX; - deviceOffset.y /= kernelY; - aResult->SetDeviceOffset(deviceOffset); -} - -//--------------------Filter Element Base Class----------------------- - -nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] = -{ - { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, - { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y }, - { &nsGkAtoms::width, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, - { &nsGkAtoms::height, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFE,nsSVGFEBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFE,nsSVGFEBase) - -NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGFE, NS_SVG_FE_CID) - -NS_INTERFACE_MAP_BEGIN(nsSVGFE) - // nsISupports is an ambiguous base of nsSVGFE so we have to work - // around that - if ( aIID.Equals(NS_GET_IID(nsSVGFE)) ) - foundInterface = static_cast<nsISupports*>(static_cast<void*>(this)); - else -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBase) - -//---------------------------------------------------------------------- -// Implementation - -nsSVGFE::ScaleInfo -nsSVGFE::SetupScalingFilter(nsSVGFilterInstance *aInstance, - const Image *aSource, const Image *aTarget, - const nsIntRect& aDataRect, - nsSVGNumberPair *aKernelUnitLength) -{ - ScaleInfo result; - result.mRescaling = aKernelUnitLength->IsExplicitlySet(); - if (!result.mRescaling) { - result.mSource = aSource->mImage; - result.mTarget = aTarget->mImage; - result.mDataRect = aDataRect; - return result; - } - - gfxFloat kernelX = aInstance->GetPrimitiveNumber(SVGContentUtils::X, - aKernelUnitLength, - nsSVGNumberPair::eFirst); - gfxFloat kernelY = aInstance->GetPrimitiveNumber(SVGContentUtils::Y, - aKernelUnitLength, - nsSVGNumberPair::eSecond); - if (kernelX <= 0 || kernelY <= 0) - return result; - - bool overflow = false; - gfxIntSize scaledSize = - nsSVGUtils::ConvertToSurfaceSize(gfxSize(aTarget->mImage->Width() / kernelX, - aTarget->mImage->Height() / kernelY), - &overflow); - // If the requested size based on the kernel unit is too big, we - // need to bail because the effect is pixel size dependent. Also - // need to check if we ended up with a negative size (arithmetic - // overflow) or zero size (large kernel unit) - if (overflow || scaledSize.width <= 0 || scaledSize.height <= 0) - return result; - - gfxRect r(aDataRect.x, aDataRect.y, aDataRect.width, aDataRect.height); - r.Scale(1 / kernelX, 1 / kernelY); - r.RoundOut(); - if (!gfxUtils::GfxRectToIntRect(r, &result.mDataRect)) - return result; - - // Rounding in the code above can mean that result.mDataRect is not contained - // within the bounds of the surfaces that we're about to create. We must - // clamp to these bounds to prevent out-of-bounds reads and writes: - result.mDataRect.IntersectRect(result.mDataRect, - nsIntRect(nsIntPoint(), scaledSize)); - - result.mSource = new gfxImageSurface(scaledSize, - gfxASurface::ImageFormatARGB32); - result.mTarget = new gfxImageSurface(scaledSize, - gfxASurface::ImageFormatARGB32); - if (!result.mSource || result.mSource->CairoStatus() || - !result.mTarget || result.mTarget->CairoStatus()) { - result.mSource = nullptr; - result.mTarget = nullptr; - return result; - } - - CopyAndScaleDeviceOffset(aSource->mImage, result.mSource, kernelX, kernelY); - CopyAndScaleDeviceOffset(aTarget->mImage, result.mTarget, kernelX, kernelY); - - result.mRealTarget = aTarget->mImage; - - gfxContext ctx(result.mSource); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.Scale(double(scaledSize.width) / aTarget->mImage->Width(), - double(scaledSize.height) / aTarget->mImage->Height()); - ctx.SetSource(aSource->mImage); - ctx.Paint(); - - // mTarget was already cleared when it was created - - return result; -} - -void -nsSVGFE::FinishScalingFilter(ScaleInfo *aScaleInfo) -{ - if (!aScaleInfo->mRescaling) - return; - - gfxIntSize scaledSize = aScaleInfo->mTarget->GetSize(); - - gfxContext ctx(aScaleInfo->mRealTarget); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.Scale(double(aScaleInfo->mRealTarget->Width()) / scaledSize.width, - double(aScaleInfo->mRealTarget->Height()) / scaledSize.height); - ctx.SetSource(aScaleInfo->mTarget); - ctx.Paint(); -} - -nsIntRect -nsSVGFE::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - nsIntRect r; - for (uint32_t i = 0; i < aSourceBBoxes.Length(); ++i) { - r.UnionRect(r, aSourceBBoxes[i]); - } - return r; -} - -void -nsSVGFE::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - for (uint32_t i = 0; i < aSourceBBoxes.Length(); ++i) { - aSourceBBoxes[i] = aTargetBBox; - } -} - -nsIntRect -nsSVGFE::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - nsIntRect r; - for (uint32_t i = 0; i < aSourceChangeBoxes.Length(); ++i) { - r.UnionRect(r, aSourceChangeBoxes[i]); - } - return r; -} - -void -nsSVGFE::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ -} - -bool -nsSVGFE::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::x || - aAttribute == nsGkAtoms::y || - aAttribute == nsGkAtoms::width || - aAttribute == nsGkAtoms::height || - aAttribute == nsGkAtoms::result); -} - -//---------------------------------------------------------------------- -// nsIDOMSVGFilterPrimitiveStandardAttributes methods - -/* readonly attribute nsIDOMSVGAnimatedLength x; */ -NS_IMETHODIMP nsSVGFE::GetX(nsIDOMSVGAnimatedLength * *aX) -{ - *aX = X().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::X() -{ - return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength y; */ -NS_IMETHODIMP nsSVGFE::GetY(nsIDOMSVGAnimatedLength * *aY) -{ - *aY = Y().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Y() -{ - return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength width; */ -NS_IMETHODIMP nsSVGFE::GetWidth(nsIDOMSVGAnimatedLength * *aWidth) -{ - *aWidth = Width().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Width() -{ - return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength height; */ -NS_IMETHODIMP nsSVGFE::GetHeight(nsIDOMSVGAnimatedLength * *aHeight) -{ - *aHeight = Height().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Height() -{ - return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this); -} +#ifndef mozilla_dom_SVGFEMorphologyElement_h +#define mozilla_dom_SVGFEMorphologyElement_h -/* readonly attribute nsIDOMSVGAnimatedString result; */ -NS_IMETHODIMP nsSVGFE::GetResult(nsIDOMSVGAnimatedString * *aResult) -{ - *aResult = Result().get(); - return NS_OK; -} - -already_AddRefed<nsIDOMSVGAnimatedString> -nsSVGFE::Result() -{ - return GetResultImageName().ToDOMAnimatedString(this); -} - -//---------------------------------------------------------------------- -// nsIContent methods - -NS_IMETHODIMP_(bool) -nsSVGFE::IsAttributeMapped(const nsIAtom* name) const -{ - static const MappedAttributeEntry* const map[] = { - sFiltersMap - }; - - return FindAttributeDependence(name, map) || - nsSVGFEBase::IsAttributeMapped(name); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -/* virtual */ bool -nsSVGFE::HasValidDimensions() const -{ - return (!mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() || - mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0) && - (!mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() || - mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0); -} - -nsSVGElement::LengthAttributesInfo -nsSVGFE::GetLengthInfo() -{ - return LengthAttributesInfo(mLengthAttributes, sLengthInfo, - ArrayLength(sLengthInfo)); -} - -namespace mozilla { -namespace dom { - -nsSVGElement::NumberListInfo SVGComponentTransferFunctionElement::sNumberListInfo[1] = -{ - { &nsGkAtoms::tableValues } -}; - -nsSVGElement::NumberInfo SVGComponentTransferFunctionElement::sNumberInfo[5] = -{ - { &nsGkAtoms::slope, 1, false }, - { &nsGkAtoms::intercept, 0, false }, - { &nsGkAtoms::amplitude, 1, false }, - { &nsGkAtoms::exponent, 1, false }, - { &nsGkAtoms::offset, 0, false } -}; - -nsSVGEnumMapping SVGComponentTransferFunctionElement::sTypeMap[] = { - {&nsGkAtoms::identity, - SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY}, - {&nsGkAtoms::table, - SVG_FECOMPONENTTRANSFER_TYPE_TABLE}, - {&nsGkAtoms::discrete, - SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE}, - {&nsGkAtoms::linear, - SVG_FECOMPONENTTRANSFER_TYPE_LINEAR}, - {&nsGkAtoms::gamma, - SVG_FECOMPONENTTRANSFER_TYPE_GAMMA}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo SVGComponentTransferFunctionElement::sEnumInfo[1] = -{ - { &nsGkAtoms::type, - sTypeMap, - SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY - } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) -NS_IMPL_RELEASE_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) - -NS_DEFINE_STATIC_IID_ACCESSOR(SVGComponentTransferFunctionElement, NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID) - -NS_INTERFACE_MAP_BEGIN(SVGComponentTransferFunctionElement) - // nsISupports is an ambiguous base of nsSVGFE so we have to work - // around that - if ( aIID.Equals(NS_GET_IID(SVGComponentTransferFunctionElement)) ) - foundInterface = static_cast<nsISupports*>(static_cast<void*>(this)); - else -NS_INTERFACE_MAP_END_INHERITING(SVGComponentTransferFunctionElementBase) - - -//---------------------------------------------------------------------- -// nsFEUnstyledElement methods - -bool -SVGComponentTransferFunctionElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::tableValues || - aAttribute == nsGkAtoms::slope || - aAttribute == nsGkAtoms::intercept || - aAttribute == nsGkAtoms::amplitude || - aAttribute == nsGkAtoms::exponent || - aAttribute == nsGkAtoms::offset || - aAttribute == nsGkAtoms::type); -} - -//---------------------------------------------------------------------- - -already_AddRefed<nsIDOMSVGAnimatedEnumeration> -SVGComponentTransferFunctionElement::Type() -{ - return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this); -} - -already_AddRefed<DOMSVGAnimatedNumberList> -SVGComponentTransferFunctionElement::TableValues() -{ - return DOMSVGAnimatedNumberList::GetDOMWrapper( - &mNumberListAttributes[TABLEVALUES], this, TABLEVALUES); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Slope() -{ - return mNumberAttributes[SLOPE].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Intercept() -{ - return mNumberAttributes[INTERCEPT].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Amplitude() -{ - return mNumberAttributes[AMPLITUDE].ToDOMAnimatedNumber(this); -} +#include "nsSVGEnum.h" +#include "nsSVGFilters.h" +#include "nsSVGNumberPair.h" +#include "nsSVGString.h" -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Exponent() -{ - return mNumberAttributes[EXPONENT].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Offset() -{ - return mNumberAttributes[OFFSET].ToDOMAnimatedNumber(this); -} - -bool -SVGComponentTransferFunctionElement::GenerateLookupTable(uint8_t *aTable) -{ - uint16_t type = mEnumAttributes[TYPE].GetAnimValue(); - - float slope, intercept, amplitude, exponent, offset; - GetAnimatedNumberValues(&slope, &intercept, &litude, - &exponent, &offset, nullptr); - - const SVGNumberList &tableValues = - mNumberListAttributes[TABLEVALUES].GetAnimValue(); - uint32_t tvLength = tableValues.Length(); - - uint32_t i; - - switch (type) { - case SVG_FECOMPONENTTRANSFER_TYPE_TABLE: - { - if (tableValues.Length() < 2) - return false; - - for (i = 0; i < 256; i++) { - uint32_t k = (i * (tvLength - 1)) / 255; - float v1 = tableValues[k]; - float v2 = tableValues[std::min(k + 1, tvLength - 1)]; - int32_t val = - int32_t(255 * (v1 + (i/255.0f - k/float(tvLength-1))*(tvLength - 1)*(v2 - v1))); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: - { - if (tableValues.Length() < 1) - return false; - - for (i = 0; i < 256; i++) { - uint32_t k = (i * tvLength) / 255; - k = std::min(k, tvLength - 1); - float v = tableValues[k]; - int32_t val = int32_t(255 * v); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: - { - for (i = 0; i < 256; i++) { - int32_t val = int32_t(slope * i + 255 * intercept); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: - { - for (i = 0; i < 256; i++) { - int32_t val = int32_t(255 * (amplitude * pow(i / 255.0f, exponent) + offset)); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: - default: - break; - } - return true; -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberListAttributesInfo -SVGComponentTransferFunctionElement::GetNumberListInfo() -{ - return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, - ArrayLength(sNumberListInfo)); -} - -nsSVGElement::EnumAttributesInfo -SVGComponentTransferFunctionElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::NumberAttributesInfo -SVGComponentTransferFunctionElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncRElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncRElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncRElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncR) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncRElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncGElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncGElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncGElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncG) +nsresult NS_NewSVGFEMorphologyElement(nsIContent **aResult, + already_AddRefed<nsINodeInfo> aNodeInfo); namespace mozilla { namespace dom { -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncGElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncBElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncBElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncBElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncB) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncBElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncAElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncAElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncAElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncA) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncAElement) - -} // namespace dom -} // namespace mozilla - -//---------------------Turbulence------------------------ - -typedef nsSVGFE nsSVGFETurbulenceElementBase; - -class nsSVGFETurbulenceElement : public nsSVGFETurbulenceElementBase, - public nsIDOMSVGFETurbulenceElement -{ - friend nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFETurbulenceElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFETurbulenceElementBase(aNodeInfo) {} - -public: - virtual bool SubregionIsUnionOfRegions() { return false; } - - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::) - - virtual nsresult Filter(nsSVGFilterInstance* aInstance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& aDataRect); - virtual bool AttributeAffectsRendering( - int32_t aNameSpaceID, nsIAtom* aAttribute) const; - virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; } - virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance); - - // Turbulence - NS_DECL_NSIDOMSVGFETURBULENCEELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::) - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual NumberAttributesInfo GetNumberInfo(); - virtual NumberPairAttributesInfo GetNumberPairInfo(); - virtual IntegerAttributesInfo GetIntegerInfo(); - virtual EnumAttributesInfo GetEnumInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { SEED }; // floating point seed?! - nsSVGNumber2 mNumberAttributes[1]; - static NumberInfo sNumberInfo[1]; - - enum { BASE_FREQ }; - nsSVGNumberPair mNumberPairAttributes[1]; - static NumberPairInfo sNumberPairInfo[1]; - - enum { OCTAVES }; - nsSVGInteger mIntegerAttributes[1]; - static IntegerInfo sIntegerInfo[1]; - - enum { TYPE, STITCHTILES }; - nsSVGEnum mEnumAttributes[2]; - static nsSVGEnumMapping sTypeMap[]; - static nsSVGEnumMapping sStitchTilesMap[]; - static EnumInfo sEnumInfo[2]; - - enum { RESULT }; - nsSVGString mStringAttributes[1]; - static StringInfo sStringInfo[1]; - -private: - - /* The turbulence calculation code is an adapted version of what - appears in the SVG 1.1 specification: - http://www.w3.org/TR/SVG11/filters.html#feTurbulence - */ - - /* Produces results in the range [1, 2**31 - 2]. - Algorithm is: r = (a * r) mod m - where a = 16807 and m = 2**31 - 1 = 2147483647 - See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988 - To test: the algorithm should produce the result 1043618065 - as the 10,000th generated number if the original seed is 1. - */ -#define RAND_M 2147483647 /* 2**31 - 1 */ -#define RAND_A 16807 /* 7**5; primitive root of m */ -#define RAND_Q 127773 /* m / a */ -#define RAND_R 2836 /* m % a */ - - int32_t SetupSeed(int32_t aSeed) { - if (aSeed <= 0) - aSeed = -(aSeed % (RAND_M - 1)) + 1; - if (aSeed > RAND_M - 1) - aSeed = RAND_M - 1; - return aSeed; - } - - uint32_t Random(uint32_t aSeed) { - int32_t result = RAND_A * (aSeed % RAND_Q) - RAND_R * (aSeed / RAND_Q); - if (result <= 0) - result += RAND_M; - return result; - } -#undef RAND_M -#undef RAND_A -#undef RAND_Q -#undef RAND_R - - const static int sBSize = 0x100; - const static int sBM = 0xff; - const static int sPerlinN = 0x1000; - const static int sNP = 12; /* 2^PerlinN */ - const static int sNM = 0xfff; - - int32_t mLatticeSelector[sBSize + sBSize + 2]; - double mGradient[4][sBSize + sBSize + 2][2]; - struct StitchInfo { - int mWidth; // How much to subtract to wrap for stitching. - int mHeight; - int mWrapX; // Minimum value to wrap. - int mWrapY; - }; - - void InitSeed(int32_t aSeed); - double Noise2(int aColorChannel, double aVec[2], StitchInfo *aStitchInfo); - double - Turbulence(int aColorChannel, double *aPoint, double aBaseFreqX, - double aBaseFreqY, int aNumOctaves, bool aFractalSum, - bool aDoStitching, double aTileX, double aTileY, - double aTileWidth, double aTileHeight); -}; - -nsSVGElement::NumberInfo nsSVGFETurbulenceElement::sNumberInfo[1] = -{ - { &nsGkAtoms::seed, 0, false } -}; - -nsSVGElement::NumberPairInfo nsSVGFETurbulenceElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::baseFrequency, 0, 0 } -}; - -nsSVGElement::IntegerInfo nsSVGFETurbulenceElement::sIntegerInfo[1] = -{ - { &nsGkAtoms::numOctaves, 1 } -}; - -nsSVGEnumMapping nsSVGFETurbulenceElement::sTypeMap[] = { - {&nsGkAtoms::fractalNoise, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_FRACTALNOISE}, - {&nsGkAtoms::turbulence, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE}, - {nullptr, 0} -}; - -nsSVGEnumMapping nsSVGFETurbulenceElement::sStitchTilesMap[] = { - {&nsGkAtoms::stitch, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH}, - {&nsGkAtoms::noStitch, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFETurbulenceElement::sEnumInfo[2] = -{ - { &nsGkAtoms::type, - sTypeMap, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE - }, - { &nsGkAtoms::stitchTiles, - sStitchTilesMap, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH - } -}; - -nsSVGElement::StringInfo nsSVGFETurbulenceElement::sStringInfo[1] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase) - -DOMCI_NODE_DATA(SVGFETurbulenceElement, nsSVGFETurbulenceElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFETurbulenceElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFETurbulenceElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFETurbulenceElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETurbulenceElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFETurbulenceElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETurbulenceElement) - -//---------------------------------------------------------------------- -// nsIDOMSVGFETurbulenceElement methods - -/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyX(nsIDOMSVGAnimatedNumber * *aX) -{ - return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyY(nsIDOMSVGAnimatedNumber * *aY) -{ - return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this); -} - -/* readonly attribute nsIDOMSVGAnimatedInteger numOctaves; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetNumOctaves(nsIDOMSVGAnimatedInteger * *aNum) -{ - return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(aNum, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber seed; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetSeed(nsIDOMSVGAnimatedNumber * *aSeed) -{ - return mNumberAttributes[SEED].ToDOMAnimatedNumber(aSeed, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetStitchTiles(nsIDOMSVGAnimatedEnumeration * *aStitch) -{ - return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(aStitch, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType) -{ - return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this); -} - -nsresult -nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - uint8_t* targetData = aTarget->mImage->Data(); - uint32_t stride = aTarget->mImage->Stride(); +typedef nsSVGFE SVGFEMorphologyElementBase; - nsIntRect filterSubregion(int32_t(aTarget->mFilterPrimitiveSubregion.X()), - int32_t(aTarget->mFilterPrimitiveSubregion.Y()), - int32_t(aTarget->mFilterPrimitiveSubregion.Width()), - int32_t(aTarget->mFilterPrimitiveSubregion.Height())); - - float fX = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eFirst); - float fY = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eSecond); - float seed = mNumberAttributes[OCTAVES].GetAnimValue(); - int32_t octaves = mIntegerAttributes[OCTAVES].GetAnimValue(); - uint16_t type = mEnumAttributes[TYPE].GetAnimValue(); - uint16_t stitch = mEnumAttributes[STITCHTILES].GetAnimValue(); - - InitSeed((int32_t)seed); - - // XXXroc this makes absolutely no sense to me. - float filterX = instance->GetFilterRegion().X(); - float filterY = instance->GetFilterRegion().Y(); - float filterWidth = instance->GetFilterRegion().Width(); - float filterHeight = instance->GetFilterRegion().Height(); - - bool doStitch = false; - if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) { - doStitch = true; - - float lowFreq, hiFreq; - - lowFreq = floor(filterWidth * fX) / filterWidth; - hiFreq = ceil(filterWidth * fX) / filterWidth; - if (fX / lowFreq < hiFreq / fX) - fX = lowFreq; - else - fX = hiFreq; - - lowFreq = floor(filterHeight * fY) / filterHeight; - hiFreq = ceil(filterHeight * fY) / filterHeight; - if (fY / lowFreq < hiFreq / fY) - fY = lowFreq; - else - fY = hiFreq; - } - for (int32_t y = rect.y; y < rect.YMost(); y++) { - for (int32_t x = rect.x; x < rect.XMost(); x++) { - int32_t targIndex = y * stride + x * 4; - double point[2]; - point[0] = filterX + (filterWidth * (x + instance->GetSurfaceRect().x)) / (filterSubregion.width - 1); - point[1] = filterY + (filterHeight * (y + instance->GetSurfaceRect().y)) / (filterSubregion.height - 1); - - float col[4]; - if (type == nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE) { - for (int i = 0; i < 4; i++) - col[i] = Turbulence(i, point, fX, fY, octaves, false, - doStitch, filterX, filterY, filterWidth, filterHeight) * 255; - } else { - for (int i = 0; i < 4; i++) - col[i] = (Turbulence(i, point, fX, fY, octaves, true, - doStitch, filterX, filterY, filterWidth, filterHeight) * 255 + 255) / 2; - } - for (int i = 0; i < 4; i++) { - col[i] = std::min(col[i], 255.f); - col[i] = std::max(col[i], 0.f); - } - - uint8_t r, g, b, a; - a = uint8_t(col[3]); - FAST_DIVIDE_BY_255(r, unsigned(col[0]) * a); - FAST_DIVIDE_BY_255(g, unsigned(col[1]) * a); - FAST_DIVIDE_BY_255(b, unsigned(col[2]) * a); - - targetData[targIndex + GFX_ARGB32_OFFSET_B] = b; - targetData[targIndex + GFX_ARGB32_OFFSET_G] = g; - targetData[targIndex + GFX_ARGB32_OFFSET_R] = r; - targetData[targIndex + GFX_ARGB32_OFFSET_A] = a; - } - } - - return NS_OK; -} - -bool -nsSVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::seed || - aAttribute == nsGkAtoms::baseFrequency || - aAttribute == nsGkAtoms::numOctaves || - aAttribute == nsGkAtoms::type || - aAttribute == nsGkAtoms::stitchTiles)); -} - -void -nsSVGFETurbulenceElement::InitSeed(int32_t aSeed) -{ - double s; - int i, j, k; - aSeed = SetupSeed(aSeed); - for (k = 0; k < 4; k++) { - for (i = 0; i < sBSize; i++) { - mLatticeSelector[i] = i; - for (j = 0; j < 2; j++) { - mGradient[k][i][j] = - (double) (((aSeed = - Random(aSeed)) % (sBSize + sBSize)) - sBSize) / sBSize; - } - s = double (sqrt - (mGradient[k][i][0] * mGradient[k][i][0] + - mGradient[k][i][1] * mGradient[k][i][1])); - mGradient[k][i][0] /= s; - mGradient[k][i][1] /= s; - } - } - while (--i) { - k = mLatticeSelector[i]; - mLatticeSelector[i] = mLatticeSelector[j = - (aSeed = - Random(aSeed)) % sBSize]; - mLatticeSelector[j] = k; - } - for (i = 0; i < sBSize + 2; i++) { - mLatticeSelector[sBSize + i] = mLatticeSelector[i]; - for (k = 0; k < 4; k++) - for (j = 0; j < 2; j++) - mGradient[k][sBSize + i][j] = mGradient[k][i][j]; - } -} - -#define S_CURVE(t) ( t * t * (3. - 2. * t) ) -#define LERP(t, a, b) ( a + t * (b - a) ) -double -nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2], - StitchInfo *aStitchInfo) +class SVGFEMorphologyElement : public SVGFEMorphologyElementBase, + public nsIDOMSVGElement { - int bx0, bx1, by0, by1, b00, b10, b01, b11; - double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v; - register long i, j; - t = aVec[0] + sPerlinN; - bx0 = (int) t; - bx1 = bx0 + 1; - rx0 = t - (int) t; - rx1 = rx0 - 1.0f; - t = aVec[1] + sPerlinN; - by0 = (int) t; - by1 = by0 + 1; - ry0 = t - (int) t; - ry1 = ry0 - 1.0f; - // If stitching, adjust lattice points accordingly. - if (aStitchInfo != NULL) { - if (bx0 >= aStitchInfo->mWrapX) - bx0 -= aStitchInfo->mWidth; - if (bx1 >= aStitchInfo->mWrapX) - bx1 -= aStitchInfo->mWidth; - if (by0 >= aStitchInfo->mWrapY) - by0 -= aStitchInfo->mHeight; - if (by1 >= aStitchInfo->mWrapY) - by1 -= aStitchInfo->mHeight; + friend nsresult (::NS_NewSVGFEMorphologyElement(nsIContent **aResult, + already_AddRefed<nsINodeInfo> aNodeInfo)); +protected: + SVGFEMorphologyElement(already_AddRefed<nsINodeInfo> aNodeInfo) + : SVGFEMorphologyElementBase(aNodeInfo) + { + SetIsDOMBinding(); } - bx0 &= sBM; - bx1 &= sBM; - by0 &= sBM; - by1 &= sBM; - i = mLatticeSelector[bx0]; - j = mLatticeSelector[bx1]; - b00 = mLatticeSelector[i + by0]; - b10 = mLatticeSelector[j + by0]; - b01 = mLatticeSelector[i + by1]; - b11 = mLatticeSelector[j + by1]; - sx = double (S_CURVE(rx0)); - sy = double (S_CURVE(ry0)); - q = mGradient[aColorChannel][b00]; - u = rx0 * q[0] + ry0 * q[1]; - q = mGradient[aColorChannel][b10]; - v = rx1 * q[0] + ry0 * q[1]; - a = LERP(sx, u, v); - q = mGradient[aColorChannel][b01]; - u = rx0 * q[0] + ry1 * q[1]; - q = mGradient[aColorChannel][b11]; - v = rx1 * q[0] + ry1 * q[1]; - b = LERP(sx, u, v); - return LERP(sy, a, b); -} -#undef S_CURVE -#undef LERP - -double -nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint, - double aBaseFreqX, double aBaseFreqY, - int aNumOctaves, bool aFractalSum, - bool aDoStitching, - double aTileX, double aTileY, - double aTileWidth, double aTileHeight) -{ - StitchInfo stitch; - StitchInfo *stitchInfo = NULL; // Not stitching when NULL. - // Adjust the base frequencies if necessary for stitching. - if (aDoStitching) { - // When stitching tiled turbulence, the frequencies must be adjusted - // so that the tile borders will be continuous. - if (aBaseFreqX != 0.0) { - double loFreq = double (floor(aTileWidth * aBaseFreqX)) / aTileWidth; - double hiFreq = double (ceil(aTileWidth * aBaseFreqX)) / aTileWidth; - if (aBaseFreqX / loFreq < hiFreq / aBaseFreqX) - aBaseFreqX = loFreq; - else - aBaseFreqX = hiFreq; - } - if (aBaseFreqY != 0.0) { - double loFreq = double (floor(aTileHeight * aBaseFreqY)) / aTileHeight; - double hiFreq = double (ceil(aTileHeight * aBaseFreqY)) / aTileHeight; - if (aBaseFreqY / loFreq < hiFreq / aBaseFreqY) - aBaseFreqY = loFreq; - else - aBaseFreqY = hiFreq; - } - // Set up initial stitch values. - stitchInfo = &stitch; - stitch.mWidth = int (aTileWidth * aBaseFreqX + 0.5f); - stitch.mWrapX = int (aTileX * aBaseFreqX + sPerlinN + stitch.mWidth); - stitch.mHeight = int (aTileHeight * aBaseFreqY + 0.5f); - stitch.mWrapY = int (aTileY * aBaseFreqY + sPerlinN + stitch.mHeight); - } - double sum = 0.0f; - double vec[2]; - vec[0] = aPoint[0] * aBaseFreqX; - vec[1] = aPoint[1] * aBaseFreqY; - double ratio = 1; - for (int octave = 0; octave < aNumOctaves; octave++) { - if (aFractalSum) - sum += double (Noise2(aColorChannel, vec, stitchInfo) / ratio); - else - sum += double (fabs(Noise2(aColorChannel, vec, stitchInfo)) / ratio); - vec[0] *= 2; - vec[1] *= 2; - ratio *= 2; - if (stitchInfo != NULL) { - // Update stitch values. Subtracting sPerlinN before the multiplication - // and adding it afterward simplifies to subtracting it once. - stitch.mWidth *= 2; - stitch.mWrapX = 2 * stitch.mWrapX - sPerlinN; - stitch.mHeight *= 2; - stitch.mWrapY = 2 * stitch.mWrapY - sPerlinN; - } - } - return sum; -} - -nsIntRect -nsSVGFETurbulenceElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - return GetMaxRect(); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFETurbulenceElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -nsSVGElement::NumberPairAttributesInfo -nsSVGFETurbulenceElement::GetNumberPairInfo() -{ - return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, - ArrayLength(sNumberPairInfo)); -} - -nsSVGElement::IntegerAttributesInfo -nsSVGFETurbulenceElement::GetIntegerInfo() -{ - return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo, - ArrayLength(sIntegerInfo)); -} - -nsSVGElement::EnumAttributesInfo -nsSVGFETurbulenceElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFETurbulenceElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Morphology------------------------ - -typedef nsSVGFE nsSVGFEMorphologyElementBase; - -class nsSVGFEMorphologyElement : public nsSVGFEMorphologyElementBase, - public nsIDOMSVGFEMorphologyElement -{ - friend nsresult NS_NewSVGFEMorphologyElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEMorphologyElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEMorphologyElementBase(aNodeInfo) {} + virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope) MOZ_OVERRIDE; public: // interfaces: NS_DECL_ISUPPORTS_INHERITED - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMorphologyElementBase::) - virtual nsresult Filter(nsSVGFilterInstance* aInstance, const nsTArray<const Image*>& aSources, const Image* aTarget, const nsIntRect& aDataRect); virtual bool AttributeAffectsRendering( int32_t aNameSpaceID, nsIAtom* aAttribute) const; virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; } virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources); virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance); virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance); virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, const nsSVGFilterInstance& aInstance); - // Morphology - NS_DECL_NSIDOMSVGFEMORPHOLOGYELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMorphologyElementBase::) + NS_FORWARD_NSIDOMSVGELEMENT(SVGFEMorphologyElementBase::) NS_FORWARD_NSIDOMNODE_TO_NSINODE NS_FORWARD_NSIDOMELEMENT_TO_GENERIC virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - virtual nsXPCClassInfo* GetClassInfo(); + virtual nsIDOMNode* AsDOMNode() { return this; } - virtual nsIDOMNode* AsDOMNode() { return this; } + // WebIDL + already_AddRefed<nsIDOMSVGAnimatedString> In1(); + already_AddRefed<nsIDOMSVGAnimatedEnumeration> Operator(); + already_AddRefed<nsIDOMSVGAnimatedNumber> RadiusX(); + already_AddRefed<nsIDOMSVGAnimatedNumber> RadiusY(); + void SetRadius(float rx, float ry); + protected: void GetRXY(int32_t *aRX, int32_t *aRY, const nsSVGFilterInstance& aInstance); nsIntRect InflateRect(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance); virtual NumberPairAttributesInfo GetNumberPairInfo(); virtual EnumAttributesInfo GetEnumInfo(); virtual StringAttributesInfo GetStringInfo(); @@ -1271,600 +84,12 @@ protected: static nsSVGEnumMapping sOperatorMap[]; static EnumInfo sEnumInfo[1]; enum { RESULT, IN1 }; nsSVGString mStringAttributes[2]; static StringInfo sStringInfo[2]; }; -nsSVGElement::NumberPairInfo nsSVGFEMorphologyElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::radius, 0, 0 } -}; - -nsSVGEnumMapping nsSVGFEMorphologyElement::sOperatorMap[] = { - {&nsGkAtoms::erode, nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE}, - {&nsGkAtoms::dilate, nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFEMorphologyElement::sEnumInfo[1] = -{ - { &nsGkAtoms::_operator, - sOperatorMap, - nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE - } -}; - -nsSVGElement::StringInfo nsSVGFEMorphologyElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEMorphology) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase) - -DOMCI_NODE_DATA(SVGFEMorphologyElement, nsSVGFEMorphologyElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEMorphologyElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEMorphologyElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEMorphologyElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMorphologyElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMorphologyElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMorphologyElement) - - -//---------------------------------------------------------------------- -// nsSVGFEMorphologyElement methods - -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration operator; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetOperator(nsIDOMSVGAnimatedEnumeration * *aOperator) -{ - return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(aOperator, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber radiusX; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusX(nsIDOMSVGAnimatedNumber * *aX) -{ - return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber radiusY; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusY(nsIDOMSVGAnimatedNumber * *aY) -{ - return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this); -} - -NS_IMETHODIMP -nsSVGFEMorphologyElement::SetRadius(float rx, float ry) -{ - NS_ENSURE_FINITE2(rx, ry, NS_ERROR_ILLEGAL_VALUE); - mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this); - return NS_OK; -} - -void -nsSVGFEMorphologyElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -nsIntRect -nsSVGFEMorphologyElement::InflateRect(const nsIntRect& aRect, - const nsSVGFilterInstance& aInstance) -{ - int32_t rx, ry; - GetRXY(&rx, &ry, aInstance); - nsIntRect result = aRect; - result.Inflate(std::max(0, rx), std::max(0, ry)); - return result; -} - -nsIntRect -nsSVGFEMorphologyElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - return InflateRect(aSourceBBoxes[0], aInstance); -} - -void -nsSVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) -{ - aSourceBBoxes[0] = InflateRect(aTargetBBox, aInstance); -} - -nsIntRect -nsSVGFEMorphologyElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - return InflateRect(aSourceChangeBoxes[0], aInstance); -} - -#define MORPHOLOGY_EPSILON 0.0001 - -void -nsSVGFEMorphologyElement::GetRXY(int32_t *aRX, int32_t *aRY, - const nsSVGFilterInstance& aInstance) -{ - // Subtract an epsilon here because we don't want a value that's just - // slightly larger than an integer to round up to the next integer; it's - // probably meant to be the integer it's close to, modulo machine precision - // issues. - *aRX = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::X, - &mNumberPairAttributes[RADIUS], - nsSVGNumberPair::eFirst) - - MORPHOLOGY_EPSILON); - *aRY = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::Y, - &mNumberPairAttributes[RADIUS], - nsSVGNumberPair::eSecond) - - MORPHOLOGY_EPSILON); -} - -nsresult -nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - int32_t rx, ry; - GetRXY(&rx, &ry, *instance); - - if (rx < 0 || ry < 0) { - // XXX SVGContentUtils::ReportToConsole() - return NS_OK; - } - if (rx == 0 && ry == 0) { - return NS_OK; - } - - // Clamp radii to prevent completely insane values: - rx = std::min(rx, 100000); - ry = std::min(ry, 100000); - - uint8_t* sourceData = aSources[0]->mImage->Data(); - uint8_t* targetData = aTarget->mImage->Data(); - int32_t stride = aTarget->mImage->Stride(); - uint8_t extrema[4]; // RGBA magnitude of extrema - uint16_t op = mEnumAttributes[OPERATOR].GetAnimValue(); - - // Scan the kernel for each pixel to determine max/min RGBA values. - for (int32_t y = rect.y; y < rect.YMost(); y++) { - int32_t startY = std::max(0, y - ry); - // We need to read pixels not just in 'rect', which is limited to - // the dirty part of our filter primitive subregion, but all pixels in - // the given radii from the source surface, so use the surface size here. - int32_t endY = std::min(y + ry, instance->GetSurfaceHeight() - 1); - for (int32_t x = rect.x; x < rect.XMost(); x++) { - int32_t startX = std::max(0, x - rx); - int32_t endX = std::min(x + rx, instance->GetSurfaceWidth() - 1); - int32_t targIndex = y * stride + 4 * x; - - for (int32_t i = 0; i < 4; i++) { - extrema[i] = sourceData[targIndex + i]; - } - for (int32_t y1 = startY; y1 <= endY; y1++) { - for (int32_t x1 = startX; x1 <= endX; x1++) { - for (int32_t i = 0; i < 4; i++) { - uint8_t pixel = sourceData[y1 * stride + 4 * x1 + i]; - if ((extrema[i] > pixel && - op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) || - (extrema[i] < pixel && - op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) { - extrema[i] = pixel; - } - } - } - } - targetData[targIndex ] = extrema[0]; - targetData[targIndex+1] = extrema[1]; - targetData[targIndex+2] = extrema[2]; - targetData[targIndex+3] = extrema[3]; - } - } - return NS_OK; -} - -bool -nsSVGFEMorphologyElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::radius || - aAttribute == nsGkAtoms::_operator)); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberPairAttributesInfo -nsSVGFEMorphologyElement::GetNumberPairInfo() -{ - return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, - ArrayLength(sNumberPairInfo)); -} - -nsSVGElement::EnumAttributesInfo -nsSVGFEMorphologyElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFEMorphologyElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//-------------------------------------------------------------------- -// -nsSVGElement::NumberInfo nsSVGFELightingElement::sNumberInfo[4] = -{ - { &nsGkAtoms::surfaceScale, 1, false }, - { &nsGkAtoms::diffuseConstant, 1, false }, - { &nsGkAtoms::specularConstant, 1, false }, - { &nsGkAtoms::specularExponent, 1, false } -}; - -nsSVGElement::NumberPairInfo nsSVGFELightingElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::kernelUnitLength, 0, 0 } -}; - -nsSVGElement::StringInfo nsSVGFELightingElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase) - -NS_INTERFACE_MAP_BEGIN(nsSVGFELightingElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFELightingElementBase) - -//---------------------------------------------------------------------- -// Implementation - -NS_IMETHODIMP_(bool) -nsSVGFELightingElement::IsAttributeMapped(const nsIAtom* name) const -{ - static const MappedAttributeEntry* const map[] = { - sLightingEffectsMap - }; - - return FindAttributeDependence(name, map) || - nsSVGFELightingElementBase::IsAttributeMapped(name); -} - -void -nsSVGFELightingElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} +} // namespace dom +} // namespace mozilla -void -nsSVGFELightingElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) -{ - // XXX lighting can depend on more than the target area, because - // of the kernels it uses. We could compute something precise here - // but just leave it and assume we use the entire source bounding box. -} - -nsIntRect -nsSVGFELightingElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - // XXX be conservative for now - return GetMaxRect(); -} - -static int32_t -Convolve3x3(const uint8_t *index, int32_t stride, - const int8_t kernel[3][3] -#ifdef DEBUG - , const uint8_t *minData, const uint8_t *maxData -#endif // DEBUG -) -{ - int32_t sum = 0; - for (int32_t y = 0; y < 3; y++) { - for (int32_t x = 0; x < 3; x++) { - int8_t k = kernel[y][x]; - if (k) { - const uint8_t *valPtr = index + (4 * (x - 1) + stride * (y - 1)); - NS_ASSERTION(valPtr >= minData, "out of bounds read (before buffer)"); - NS_ASSERTION(valPtr < maxData, "out of bounds read (after buffer)"); - sum += k * (*valPtr); - } - } - } - return sum; -} - -static void -GenerateNormal(float *N, const uint8_t *data, int32_t stride, - int32_t surfaceWidth, int32_t surfaceHeight, - int32_t x, int32_t y, float surfaceScale) -{ - // See this for source of constants: - // http://www.w3.org/TR/SVG11/filters.html#feDiffuseLightingElement - static const int8_t Kx[3][3][3][3] = - { { { { 0, 0, 0}, { 0, -2, 2}, { 0, -1, 1} }, - { { 0, 0, 0}, {-2, 0, 2}, {-1, 0, 1} }, - { { 0, 0, 0}, {-2, 2, 0}, {-1, 1, 0} } }, - { { { 0, -1, 1}, { 0, -2, 2}, { 0, -1, 1} }, - { { -1, 0, 1}, {-2, 0, 2}, {-1, 0, 1} }, - { { -1, 1, 0}, {-2, 2, 0}, {-1, 1, 0} } }, - { { { 0, -1, 1}, { 0, -2, 2}, { 0, 0, 0} }, - { { -1, 0, 1}, {-2, 0, 2}, { 0, 0, 0} }, - { { -1, 1, 0}, {-2, 2, 0}, { 0, 0, 0} } } }; - static const int8_t Ky[3][3][3][3] = - { { { { 0, 0, 0}, { 0, -2, -1}, { 0, 2, 1} }, - { { 0, 0, 0}, {-1, -2, -1}, { 1, 2, 1} }, - { { 0, 0, 0}, {-1, -2, 1}, { 1, 2, 0} } }, - { { { 0, -2, -1}, { 0, 0, 0}, { 0, 2, 1} }, - { { -1, -2, -1}, { 0, 0, 0}, { 1, 2, 1} }, - { { -1, -2, 0}, { 0, 0, 0}, { 1, 2, 0} } }, - { { { 0, -2, -1}, { 0, 2, 1}, { 0, 0, 0} }, - { { -1, -2, -1}, { 1, 2, 1}, { 0, 0, 0} }, - { { -1, -2, 0}, { 1, 2, 0}, { 0, 0, 0} } } }; - static const float FACTORx[3][3] = - { { 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0 }, - { 1.0 / 2.0, 1.0 / 4.0, 1.0 / 2.0 }, - { 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0 } }; - static const float FACTORy[3][3] = - { { 2.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0 }, - { 1.0 / 3.0, 1.0 / 4.0, 1.0 / 3.0 }, - { 2.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0 } }; - - // degenerate cases - if (surfaceWidth == 1 || surfaceHeight == 1) { - // just return a unit vector pointing towards the viewer - N[0] = 0; - N[1] = 0; - N[2] = 255; - return; - } - - int8_t xflag, yflag; - if (x == 0) { - xflag = 0; - } else if (x == surfaceWidth - 1) { - xflag = 2; - } else { - xflag = 1; - } - if (y == 0) { - yflag = 0; - } else if (y == surfaceHeight - 1) { - yflag = 2; - } else { - yflag = 1; - } - - const uint8_t *index = data + y * stride + 4 * x + GFX_ARGB32_OFFSET_A; - -#ifdef DEBUG - // For sanity-checking, to be sure we're not reading outside source buffer: - const uint8_t* minData = data; - const uint8_t* maxData = minData + (surfaceHeight * surfaceWidth * stride); - - // We'll sanity-check each value we read inside of Convolve3x3, but we - // might as well ensure we're passing it a valid pointer to start with, too: - NS_ASSERTION(index >= minData, "index points before buffer start"); - NS_ASSERTION(index < maxData, "index points after buffer end"); -#endif // DEBUG - - N[0] = -surfaceScale * FACTORx[yflag][xflag] * - Convolve3x3(index, stride, Kx[yflag][xflag] -#ifdef DEBUG - , minData, maxData -#endif // DEBUG - ); - - N[1] = -surfaceScale * FACTORy[yflag][xflag] * - Convolve3x3(index, stride, Ky[yflag][xflag] -#ifdef DEBUG - , minData, maxData -#endif // DEBUG - ); - N[2] = 255; - NORMALIZE(N); -} - -nsresult -nsSVGFELightingElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - ScaleInfo info = SetupScalingFilter(instance, aSources[0], aTarget, rect, - &mNumberPairAttributes[KERNEL_UNIT_LENGTH]); - if (!info.mTarget) - return NS_ERROR_FAILURE; - - SVGFEDistantLightElement* distantLight = nullptr; - SVGFEPointLightElement* pointLight = nullptr; - SVGFESpotLightElement* spotLight = nullptr; - - nsIFrame* frame = GetPrimaryFrame(); - if (!frame) return NS_ERROR_FAILURE; - nsStyleContext* style = frame->StyleContext(); - - nscolor lightColor = style->StyleSVGReset()->mLightingColor; - - // find specified light - for (nsCOMPtr<nsIContent> child = nsINode::GetFirstChild(); - child; - child = child->GetNextSibling()) { - distantLight = child->IsSVG(nsGkAtoms::feDistantLight) ? - static_cast<SVGFEDistantLightElement*>(child.get()) : nullptr; - pointLight = child->IsSVG(nsGkAtoms::fePointLight) ? - static_cast<SVGFEPointLightElement*>(child.get()) : nullptr; - spotLight = child->IsSVG(nsGkAtoms::feSpotLight) ? - static_cast<SVGFESpotLightElement*>(child.get()) : nullptr; - if (distantLight || pointLight || spotLight) - break; - } - - if (!distantLight && !pointLight && !spotLight) - return NS_ERROR_FAILURE; - - const float radPerDeg = M_PI/180.0; - - float L[3]; - if (distantLight) { - float azimuth, elevation; - distantLight->GetAnimatedNumberValues(&azimuth, - &elevation, - nullptr); - L[0] = cos(azimuth * radPerDeg) * cos(elevation * radPerDeg); - L[1] = sin(azimuth * radPerDeg) * cos(elevation * radPerDeg); - L[2] = sin(elevation * radPerDeg); - } - float lightPos[3], pointsAt[3], specularExponent; - float cosConeAngle = 0; - if (pointLight) { - pointLight->GetAnimatedNumberValues(lightPos, - lightPos + 1, - lightPos + 2, - nullptr); - instance->ConvertLocation(lightPos); - } - if (spotLight) { - float limitingConeAngle; - spotLight->GetAnimatedNumberValues(lightPos, - lightPos + 1, - lightPos + 2, - pointsAt, - pointsAt + 1, - pointsAt + 2, - &specularExponent, - &limitingConeAngle, - nullptr); - instance->ConvertLocation(lightPos); - instance->ConvertLocation(pointsAt); - - if (spotLight->mNumberAttributes[SVGFESpotLightElement::LIMITING_CONE_ANGLE]. - IsExplicitlySet()) { - cosConeAngle = std::max<double>(cos(limitingConeAngle * radPerDeg), 0.0); - } - } - - float surfaceScale = mNumberAttributes[SURFACE_SCALE].GetAnimValue(); - - const nsIntRect& dataRect = info.mDataRect; - int32_t stride = info.mSource->Stride(); - uint8_t *sourceData = info.mSource->Data(); - uint8_t *targetData = info.mTarget->Data(); - int32_t surfaceWidth = info.mSource->Width(); - int32_t surfaceHeight = info.mSource->Height(); - - for (int32_t y = dataRect.y; y < dataRect.YMost(); y++) { - for (int32_t x = dataRect.x; x < dataRect.XMost(); x++) { - int32_t index = y * stride + x * 4; - - float N[3]; - GenerateNormal(N, sourceData, stride, surfaceWidth, surfaceHeight, - x, y, surfaceScale); - - if (pointLight || spotLight) { - gfxPoint pt = instance->FilterSpaceToUserSpace( - gfxPoint(x + instance->GetSurfaceRect().x, - y + instance->GetSurfaceRect().y)); - float Z = surfaceScale * sourceData[index + GFX_ARGB32_OFFSET_A] / 255; - - L[0] = lightPos[0] - pt.x; - L[1] = lightPos[1] - pt.y; - L[2] = lightPos[2] - Z; - NORMALIZE(L); - } - - nscolor color; - - if (spotLight) { - float S[3]; - S[0] = pointsAt[0] - lightPos[0]; - S[1] = pointsAt[1] - lightPos[1]; - S[2] = pointsAt[2] - lightPos[2]; - NORMALIZE(S); - float dot = -DOT(L, S); - float tmp = pow(dot, specularExponent); - if (dot < cosConeAngle) tmp = 0; - color = NS_RGB(uint8_t(NS_GET_R(lightColor) * tmp), - uint8_t(NS_GET_G(lightColor) * tmp), - uint8_t(NS_GET_B(lightColor) * tmp)); - } else { - color = lightColor; - } - - LightPixel(N, L, color, targetData + index); - } - } - - FinishScalingFilter(&info); - - return NS_OK; -} - -bool -nsSVGFELightingElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFELightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::surfaceScale || - aAttribute == nsGkAtoms::kernelUnitLength)); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFELightingElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -nsSVGElement::NumberPairAttributesInfo -nsSVGFELightingElement::GetNumberPairInfo() -{ - return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, - ArrayLength(sNumberPairInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFELightingElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} +#endif // mozilla_dom_SVGFEMorphologyElement_h
copy from content/svg/content/src/nsSVGFilters.cpp copy to content/svg/content/src/SVGFETurbulenceElement.cpp --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/SVGFETurbulenceElement.cpp @@ -1,921 +1,146 @@ /* a*- 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 "nsSVGElement.h" -#include "nsGkAtoms.h" -#include "nsSVGNumber2.h" -#include "nsSVGNumberPair.h" -#include "nsSVGInteger.h" -#include "nsSVGIntegerPair.h" -#include "nsSVGBoolean.h" -#include "nsIDOMSVGFilters.h" -#include "nsCOMPtr.h" +#include "mozilla/dom/SVGFETurbulenceElement.h" +#include "mozilla/dom/SVGFETurbulenceElementBinding.h" #include "nsSVGFilterInstance.h" -#include "nsSVGEnum.h" -#include "SVGNumberList.h" -#include "SVGAnimatedNumberList.h" -#include "DOMSVGAnimatedNumberList.h" -#include "nsSVGFilters.h" -#include "nsLayoutUtils.h" #include "nsSVGUtils.h" -#include "nsStyleContext.h" -#include "nsIFrame.h" -#include "gfxContext.h" -#include "gfxMatrix.h" -#include "imgIContainer.h" -#include "nsNetUtil.h" -#include "mozilla/dom/SVGFilterElement.h" -#include "nsSVGString.h" -#include "gfxUtils.h" -#include "SVGContentUtils.h" -#include <algorithm> -#include "nsContentUtils.h" -#include "mozilla/dom/SVGAnimatedLength.h" -#include "mozilla/dom/SVGComponentTransferFunctionElement.h" -#include "mozilla/dom/SVGFEDistantLightElement.h" -#include "mozilla/dom/SVGFEFuncAElementBinding.h" -#include "mozilla/dom/SVGFEFuncBElementBinding.h" -#include "mozilla/dom/SVGFEFuncGElementBinding.h" -#include "mozilla/dom/SVGFEFuncRElementBinding.h" -#include "mozilla/dom/SVGFEPointLightElement.h" -#include "mozilla/dom/SVGFESpotLightElement.h" - -#if defined(XP_WIN) -// Prevent Windows redefining LoadImage -#undef LoadImage -#endif - -using namespace mozilla; -using namespace mozilla::dom; - -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5; - -void -CopyDataRect(uint8_t *aDest, const uint8_t *aSrc, uint32_t aStride, - const nsIntRect& aDataRect) -{ - for (int32_t y = aDataRect.y; y < aDataRect.YMost(); y++) { - memcpy(aDest + y * aStride + 4 * aDataRect.x, - aSrc + y * aStride + 4 * aDataRect.x, - 4 * aDataRect.width); - } -} - -static void -CopyAndScaleDeviceOffset(const gfxImageSurface *aImage, gfxImageSurface *aResult, - gfxFloat kernelX, gfxFloat kernelY) -{ - gfxPoint deviceOffset = aImage->GetDeviceOffset(); - deviceOffset.x /= kernelX; - deviceOffset.y /= kernelY; - aResult->SetDeviceOffset(deviceOffset); -} - -//--------------------Filter Element Base Class----------------------- - -nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] = -{ - { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, - { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y }, - { &nsGkAtoms::width, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, - { &nsGkAtoms::height, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFE,nsSVGFEBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFE,nsSVGFEBase) - -NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGFE, NS_SVG_FE_CID) - -NS_INTERFACE_MAP_BEGIN(nsSVGFE) - // nsISupports is an ambiguous base of nsSVGFE so we have to work - // around that - if ( aIID.Equals(NS_GET_IID(nsSVGFE)) ) - foundInterface = static_cast<nsISupports*>(static_cast<void*>(this)); - else -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBase) - -//---------------------------------------------------------------------- -// Implementation - -nsSVGFE::ScaleInfo -nsSVGFE::SetupScalingFilter(nsSVGFilterInstance *aInstance, - const Image *aSource, const Image *aTarget, - const nsIntRect& aDataRect, - nsSVGNumberPair *aKernelUnitLength) -{ - ScaleInfo result; - result.mRescaling = aKernelUnitLength->IsExplicitlySet(); - if (!result.mRescaling) { - result.mSource = aSource->mImage; - result.mTarget = aTarget->mImage; - result.mDataRect = aDataRect; - return result; - } - - gfxFloat kernelX = aInstance->GetPrimitiveNumber(SVGContentUtils::X, - aKernelUnitLength, - nsSVGNumberPair::eFirst); - gfxFloat kernelY = aInstance->GetPrimitiveNumber(SVGContentUtils::Y, - aKernelUnitLength, - nsSVGNumberPair::eSecond); - if (kernelX <= 0 || kernelY <= 0) - return result; - - bool overflow = false; - gfxIntSize scaledSize = - nsSVGUtils::ConvertToSurfaceSize(gfxSize(aTarget->mImage->Width() / kernelX, - aTarget->mImage->Height() / kernelY), - &overflow); - // If the requested size based on the kernel unit is too big, we - // need to bail because the effect is pixel size dependent. Also - // need to check if we ended up with a negative size (arithmetic - // overflow) or zero size (large kernel unit) - if (overflow || scaledSize.width <= 0 || scaledSize.height <= 0) - return result; - - gfxRect r(aDataRect.x, aDataRect.y, aDataRect.width, aDataRect.height); - r.Scale(1 / kernelX, 1 / kernelY); - r.RoundOut(); - if (!gfxUtils::GfxRectToIntRect(r, &result.mDataRect)) - return result; - - // Rounding in the code above can mean that result.mDataRect is not contained - // within the bounds of the surfaces that we're about to create. We must - // clamp to these bounds to prevent out-of-bounds reads and writes: - result.mDataRect.IntersectRect(result.mDataRect, - nsIntRect(nsIntPoint(), scaledSize)); - - result.mSource = new gfxImageSurface(scaledSize, - gfxASurface::ImageFormatARGB32); - result.mTarget = new gfxImageSurface(scaledSize, - gfxASurface::ImageFormatARGB32); - if (!result.mSource || result.mSource->CairoStatus() || - !result.mTarget || result.mTarget->CairoStatus()) { - result.mSource = nullptr; - result.mTarget = nullptr; - return result; - } - - CopyAndScaleDeviceOffset(aSource->mImage, result.mSource, kernelX, kernelY); - CopyAndScaleDeviceOffset(aTarget->mImage, result.mTarget, kernelX, kernelY); - - result.mRealTarget = aTarget->mImage; - gfxContext ctx(result.mSource); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.Scale(double(scaledSize.width) / aTarget->mImage->Width(), - double(scaledSize.height) / aTarget->mImage->Height()); - ctx.SetSource(aSource->mImage); - ctx.Paint(); - - // mTarget was already cleared when it was created - - return result; -} - -void -nsSVGFE::FinishScalingFilter(ScaleInfo *aScaleInfo) -{ - if (!aScaleInfo->mRescaling) - return; - - gfxIntSize scaledSize = aScaleInfo->mTarget->GetSize(); - - gfxContext ctx(aScaleInfo->mRealTarget); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.Scale(double(aScaleInfo->mRealTarget->Width()) / scaledSize.width, - double(aScaleInfo->mRealTarget->Height()) / scaledSize.height); - ctx.SetSource(aScaleInfo->mTarget); - ctx.Paint(); -} - -nsIntRect -nsSVGFE::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - nsIntRect r; - for (uint32_t i = 0; i < aSourceBBoxes.Length(); ++i) { - r.UnionRect(r, aSourceBBoxes[i]); - } - return r; -} - -void -nsSVGFE::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - for (uint32_t i = 0; i < aSourceBBoxes.Length(); ++i) { - aSourceBBoxes[i] = aTargetBBox; - } -} - -nsIntRect -nsSVGFE::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - nsIntRect r; - for (uint32_t i = 0; i < aSourceChangeBoxes.Length(); ++i) { - r.UnionRect(r, aSourceChangeBoxes[i]); - } - return r; -} - -void -nsSVGFE::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ -} - -bool -nsSVGFE::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::x || - aAttribute == nsGkAtoms::y || - aAttribute == nsGkAtoms::width || - aAttribute == nsGkAtoms::height || - aAttribute == nsGkAtoms::result); -} - -//---------------------------------------------------------------------- -// nsIDOMSVGFilterPrimitiveStandardAttributes methods - -/* readonly attribute nsIDOMSVGAnimatedLength x; */ -NS_IMETHODIMP nsSVGFE::GetX(nsIDOMSVGAnimatedLength * *aX) -{ - *aX = X().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::X() -{ - return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength y; */ -NS_IMETHODIMP nsSVGFE::GetY(nsIDOMSVGAnimatedLength * *aY) -{ - *aY = Y().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Y() -{ - return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength width; */ -NS_IMETHODIMP nsSVGFE::GetWidth(nsIDOMSVGAnimatedLength * *aWidth) -{ - *aWidth = Width().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Width() -{ - return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength height; */ -NS_IMETHODIMP nsSVGFE::GetHeight(nsIDOMSVGAnimatedLength * *aHeight) -{ - *aHeight = Height().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Height() -{ - return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedString result; */ -NS_IMETHODIMP nsSVGFE::GetResult(nsIDOMSVGAnimatedString * *aResult) -{ - *aResult = Result().get(); - return NS_OK; -} - -already_AddRefed<nsIDOMSVGAnimatedString> -nsSVGFE::Result() -{ - return GetResultImageName().ToDOMAnimatedString(this); -} - -//---------------------------------------------------------------------- -// nsIContent methods - -NS_IMETHODIMP_(bool) -nsSVGFE::IsAttributeMapped(const nsIAtom* name) const -{ - static const MappedAttributeEntry* const map[] = { - sFiltersMap - }; - - return FindAttributeDependence(name, map) || - nsSVGFEBase::IsAttributeMapped(name); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -/* virtual */ bool -nsSVGFE::HasValidDimensions() const -{ - return (!mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() || - mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0) && - (!mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() || - mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0); -} - -nsSVGElement::LengthAttributesInfo -nsSVGFE::GetLengthInfo() -{ - return LengthAttributesInfo(mLengthAttributes, sLengthInfo, - ArrayLength(sLengthInfo)); -} +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FETurbulence) namespace mozilla { namespace dom { -nsSVGElement::NumberListInfo SVGComponentTransferFunctionElement::sNumberListInfo[1] = +// Turbulence Types +static const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN = 0; +static const unsigned short SVG_TURBULENCE_TYPE_FRACTALNOISE = 1; +static const unsigned short SVG_TURBULENCE_TYPE_TURBULENCE = 2; + +// Stitch Options +static const unsigned short SVG_STITCHTYPE_UNKNOWN = 0; +static const unsigned short SVG_STITCHTYPE_STITCH = 1; +static const unsigned short SVG_STITCHTYPE_NOSTITCH = 2; + +JSObject* +SVGFETurbulenceElement::WrapNode(JSContext* aCx, JSObject* aScope) { - { &nsGkAtoms::tableValues } + return SVGFETurbulenceElementBinding::Wrap(aCx, aScope, this); +} + +nsSVGElement::NumberInfo SVGFETurbulenceElement::sNumberInfo[1] = +{ + { &nsGkAtoms::seed, 0, false } }; -nsSVGElement::NumberInfo SVGComponentTransferFunctionElement::sNumberInfo[5] = +nsSVGElement::NumberPairInfo SVGFETurbulenceElement::sNumberPairInfo[1] = { - { &nsGkAtoms::slope, 1, false }, - { &nsGkAtoms::intercept, 0, false }, - { &nsGkAtoms::amplitude, 1, false }, - { &nsGkAtoms::exponent, 1, false }, - { &nsGkAtoms::offset, 0, false } + { &nsGkAtoms::baseFrequency, 0, 0 } }; -nsSVGEnumMapping SVGComponentTransferFunctionElement::sTypeMap[] = { - {&nsGkAtoms::identity, - SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY}, - {&nsGkAtoms::table, - SVG_FECOMPONENTTRANSFER_TYPE_TABLE}, - {&nsGkAtoms::discrete, - SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE}, - {&nsGkAtoms::linear, - SVG_FECOMPONENTTRANSFER_TYPE_LINEAR}, - {&nsGkAtoms::gamma, - SVG_FECOMPONENTTRANSFER_TYPE_GAMMA}, +nsSVGElement::IntegerInfo SVGFETurbulenceElement::sIntegerInfo[1] = +{ + { &nsGkAtoms::numOctaves, 1 } +}; + +nsSVGEnumMapping SVGFETurbulenceElement::sTypeMap[] = { + {&nsGkAtoms::fractalNoise, + SVG_TURBULENCE_TYPE_FRACTALNOISE}, + {&nsGkAtoms::turbulence, + SVG_TURBULENCE_TYPE_TURBULENCE}, {nullptr, 0} }; -nsSVGElement::EnumInfo SVGComponentTransferFunctionElement::sEnumInfo[1] = +nsSVGEnumMapping SVGFETurbulenceElement::sStitchTilesMap[] = { + {&nsGkAtoms::stitch, + SVG_STITCHTYPE_STITCH}, + {&nsGkAtoms::noStitch, + SVG_STITCHTYPE_NOSTITCH}, + {nullptr, 0} +}; + +nsSVGElement::EnumInfo SVGFETurbulenceElement::sEnumInfo[2] = { { &nsGkAtoms::type, sTypeMap, - SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY + SVG_TURBULENCE_TYPE_TURBULENCE + }, + { &nsGkAtoms::stitchTiles, + sStitchTilesMap, + SVG_STITCHTYPE_NOSTITCH } }; +nsSVGElement::StringInfo SVGFETurbulenceElement::sStringInfo[1] = +{ + { &nsGkAtoms::result, kNameSpaceID_None, true } +}; + //---------------------------------------------------------------------- // nsISupports methods -NS_IMPL_ADDREF_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) -NS_IMPL_RELEASE_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) - -NS_DEFINE_STATIC_IID_ACCESSOR(SVGComponentTransferFunctionElement, NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID) +NS_IMPL_ADDREF_INHERITED(SVGFETurbulenceElement,SVGFETurbulenceElementBase) +NS_IMPL_RELEASE_INHERITED(SVGFETurbulenceElement,SVGFETurbulenceElementBase) -NS_INTERFACE_MAP_BEGIN(SVGComponentTransferFunctionElement) - // nsISupports is an ambiguous base of nsSVGFE so we have to work - // around that - if ( aIID.Equals(NS_GET_IID(SVGComponentTransferFunctionElement)) ) - foundInterface = static_cast<nsISupports*>(static_cast<void*>(this)); - else -NS_INTERFACE_MAP_END_INHERITING(SVGComponentTransferFunctionElementBase) - +NS_INTERFACE_TABLE_HEAD(SVGFETurbulenceElement) + NS_NODE_INTERFACE_TABLE3(SVGFETurbulenceElement, nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement) +NS_INTERFACE_MAP_END_INHERITING(SVGFETurbulenceElementBase) //---------------------------------------------------------------------- -// nsFEUnstyledElement methods +// nsIDOMNode methods -bool -SVGComponentTransferFunctionElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::tableValues || - aAttribute == nsGkAtoms::slope || - aAttribute == nsGkAtoms::intercept || - aAttribute == nsGkAtoms::amplitude || - aAttribute == nsGkAtoms::exponent || - aAttribute == nsGkAtoms::offset || - aAttribute == nsGkAtoms::type); -} +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFETurbulenceElement) //---------------------------------------------------------------------- +already_AddRefed<nsIDOMSVGAnimatedNumber> +SVGFETurbulenceElement::BaseFrequencyX() +{ + return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(nsSVGNumberPair::eFirst, this); +} + +already_AddRefed<nsIDOMSVGAnimatedNumber> +SVGFETurbulenceElement::BaseFrequencyY() +{ + return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(nsSVGNumberPair::eSecond, this); +} + +already_AddRefed<nsIDOMSVGAnimatedInteger> +SVGFETurbulenceElement::NumOctaves() +{ + return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(this); +} + +already_AddRefed<nsIDOMSVGAnimatedNumber> +SVGFETurbulenceElement::Seed() +{ + return mNumberAttributes[SEED].ToDOMAnimatedNumber(this); +} + already_AddRefed<nsIDOMSVGAnimatedEnumeration> -SVGComponentTransferFunctionElement::Type() +SVGFETurbulenceElement::StitchTiles() +{ + return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(this); +} + +already_AddRefed<nsIDOMSVGAnimatedEnumeration> +SVGFETurbulenceElement::Type() { return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this); } -already_AddRefed<DOMSVGAnimatedNumberList> -SVGComponentTransferFunctionElement::TableValues() -{ - return DOMSVGAnimatedNumberList::GetDOMWrapper( - &mNumberListAttributes[TABLEVALUES], this, TABLEVALUES); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Slope() -{ - return mNumberAttributes[SLOPE].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Intercept() -{ - return mNumberAttributes[INTERCEPT].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Amplitude() -{ - return mNumberAttributes[AMPLITUDE].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Exponent() -{ - return mNumberAttributes[EXPONENT].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Offset() -{ - return mNumberAttributes[OFFSET].ToDOMAnimatedNumber(this); -} - -bool -SVGComponentTransferFunctionElement::GenerateLookupTable(uint8_t *aTable) -{ - uint16_t type = mEnumAttributes[TYPE].GetAnimValue(); - - float slope, intercept, amplitude, exponent, offset; - GetAnimatedNumberValues(&slope, &intercept, &litude, - &exponent, &offset, nullptr); - - const SVGNumberList &tableValues = - mNumberListAttributes[TABLEVALUES].GetAnimValue(); - uint32_t tvLength = tableValues.Length(); - - uint32_t i; - - switch (type) { - case SVG_FECOMPONENTTRANSFER_TYPE_TABLE: - { - if (tableValues.Length() < 2) - return false; - - for (i = 0; i < 256; i++) { - uint32_t k = (i * (tvLength - 1)) / 255; - float v1 = tableValues[k]; - float v2 = tableValues[std::min(k + 1, tvLength - 1)]; - int32_t val = - int32_t(255 * (v1 + (i/255.0f - k/float(tvLength-1))*(tvLength - 1)*(v2 - v1))); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: - { - if (tableValues.Length() < 1) - return false; - - for (i = 0; i < 256; i++) { - uint32_t k = (i * tvLength) / 255; - k = std::min(k, tvLength - 1); - float v = tableValues[k]; - int32_t val = int32_t(255 * v); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: - { - for (i = 0; i < 256; i++) { - int32_t val = int32_t(slope * i + 255 * intercept); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: - { - for (i = 0; i < 256; i++) { - int32_t val = int32_t(255 * (amplitude * pow(i / 255.0f, exponent) + offset)); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: - default: - break; - } - return true; -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberListAttributesInfo -SVGComponentTransferFunctionElement::GetNumberListInfo() -{ - return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, - ArrayLength(sNumberListInfo)); -} - -nsSVGElement::EnumAttributesInfo -SVGComponentTransferFunctionElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::NumberAttributesInfo -SVGComponentTransferFunctionElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncRElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncRElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncRElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncR) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncRElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncGElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncGElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncGElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncG) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncGElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncBElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncBElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncBElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncB) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncBElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncAElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncAElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncAElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncA) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncAElement) - -} // namespace dom -} // namespace mozilla - -//---------------------Turbulence------------------------ - -typedef nsSVGFE nsSVGFETurbulenceElementBase; - -class nsSVGFETurbulenceElement : public nsSVGFETurbulenceElementBase, - public nsIDOMSVGFETurbulenceElement -{ - friend nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFETurbulenceElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFETurbulenceElementBase(aNodeInfo) {} - -public: - virtual bool SubregionIsUnionOfRegions() { return false; } - - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::) - - virtual nsresult Filter(nsSVGFilterInstance* aInstance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& aDataRect); - virtual bool AttributeAffectsRendering( - int32_t aNameSpaceID, nsIAtom* aAttribute) const; - virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; } - virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance); - - // Turbulence - NS_DECL_NSIDOMSVGFETURBULENCEELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::) - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual NumberAttributesInfo GetNumberInfo(); - virtual NumberPairAttributesInfo GetNumberPairInfo(); - virtual IntegerAttributesInfo GetIntegerInfo(); - virtual EnumAttributesInfo GetEnumInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { SEED }; // floating point seed?! - nsSVGNumber2 mNumberAttributes[1]; - static NumberInfo sNumberInfo[1]; - - enum { BASE_FREQ }; - nsSVGNumberPair mNumberPairAttributes[1]; - static NumberPairInfo sNumberPairInfo[1]; - - enum { OCTAVES }; - nsSVGInteger mIntegerAttributes[1]; - static IntegerInfo sIntegerInfo[1]; - - enum { TYPE, STITCHTILES }; - nsSVGEnum mEnumAttributes[2]; - static nsSVGEnumMapping sTypeMap[]; - static nsSVGEnumMapping sStitchTilesMap[]; - static EnumInfo sEnumInfo[2]; - - enum { RESULT }; - nsSVGString mStringAttributes[1]; - static StringInfo sStringInfo[1]; - -private: - - /* The turbulence calculation code is an adapted version of what - appears in the SVG 1.1 specification: - http://www.w3.org/TR/SVG11/filters.html#feTurbulence - */ - - /* Produces results in the range [1, 2**31 - 2]. - Algorithm is: r = (a * r) mod m - where a = 16807 and m = 2**31 - 1 = 2147483647 - See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988 - To test: the algorithm should produce the result 1043618065 - as the 10,000th generated number if the original seed is 1. - */ -#define RAND_M 2147483647 /* 2**31 - 1 */ -#define RAND_A 16807 /* 7**5; primitive root of m */ -#define RAND_Q 127773 /* m / a */ -#define RAND_R 2836 /* m % a */ - - int32_t SetupSeed(int32_t aSeed) { - if (aSeed <= 0) - aSeed = -(aSeed % (RAND_M - 1)) + 1; - if (aSeed > RAND_M - 1) - aSeed = RAND_M - 1; - return aSeed; - } - - uint32_t Random(uint32_t aSeed) { - int32_t result = RAND_A * (aSeed % RAND_Q) - RAND_R * (aSeed / RAND_Q); - if (result <= 0) - result += RAND_M; - return result; - } -#undef RAND_M -#undef RAND_A -#undef RAND_Q -#undef RAND_R - - const static int sBSize = 0x100; - const static int sBM = 0xff; - const static int sPerlinN = 0x1000; - const static int sNP = 12; /* 2^PerlinN */ - const static int sNM = 0xfff; - - int32_t mLatticeSelector[sBSize + sBSize + 2]; - double mGradient[4][sBSize + sBSize + 2][2]; - struct StitchInfo { - int mWidth; // How much to subtract to wrap for stitching. - int mHeight; - int mWrapX; // Minimum value to wrap. - int mWrapY; - }; - - void InitSeed(int32_t aSeed); - double Noise2(int aColorChannel, double aVec[2], StitchInfo *aStitchInfo); - double - Turbulence(int aColorChannel, double *aPoint, double aBaseFreqX, - double aBaseFreqY, int aNumOctaves, bool aFractalSum, - bool aDoStitching, double aTileX, double aTileY, - double aTileWidth, double aTileHeight); -}; - -nsSVGElement::NumberInfo nsSVGFETurbulenceElement::sNumberInfo[1] = -{ - { &nsGkAtoms::seed, 0, false } -}; - -nsSVGElement::NumberPairInfo nsSVGFETurbulenceElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::baseFrequency, 0, 0 } -}; - -nsSVGElement::IntegerInfo nsSVGFETurbulenceElement::sIntegerInfo[1] = -{ - { &nsGkAtoms::numOctaves, 1 } -}; - -nsSVGEnumMapping nsSVGFETurbulenceElement::sTypeMap[] = { - {&nsGkAtoms::fractalNoise, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_FRACTALNOISE}, - {&nsGkAtoms::turbulence, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE}, - {nullptr, 0} -}; - -nsSVGEnumMapping nsSVGFETurbulenceElement::sStitchTilesMap[] = { - {&nsGkAtoms::stitch, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH}, - {&nsGkAtoms::noStitch, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFETurbulenceElement::sEnumInfo[2] = -{ - { &nsGkAtoms::type, - sTypeMap, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE - }, - { &nsGkAtoms::stitchTiles, - sStitchTilesMap, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH - } -}; - -nsSVGElement::StringInfo nsSVGFETurbulenceElement::sStringInfo[1] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase) - -DOMCI_NODE_DATA(SVGFETurbulenceElement, nsSVGFETurbulenceElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFETurbulenceElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFETurbulenceElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFETurbulenceElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETurbulenceElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFETurbulenceElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETurbulenceElement) - -//---------------------------------------------------------------------- -// nsIDOMSVGFETurbulenceElement methods - -/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyX(nsIDOMSVGAnimatedNumber * *aX) -{ - return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyY(nsIDOMSVGAnimatedNumber * *aY) -{ - return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this); -} - -/* readonly attribute nsIDOMSVGAnimatedInteger numOctaves; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetNumOctaves(nsIDOMSVGAnimatedInteger * *aNum) -{ - return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(aNum, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber seed; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetSeed(nsIDOMSVGAnimatedNumber * *aSeed) -{ - return mNumberAttributes[SEED].ToDOMAnimatedNumber(aSeed, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetStitchTiles(nsIDOMSVGAnimatedEnumeration * *aStitch) -{ - return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(aStitch, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType) -{ - return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this); -} - nsresult -nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) +SVGFETurbulenceElement::Filter(nsSVGFilterInstance* instance, + const nsTArray<const Image*>& aSources, + const Image* aTarget, + const nsIntRect& rect) { uint8_t* targetData = aTarget->mImage->Data(); uint32_t stride = aTarget->mImage->Stride(); nsIntRect filterSubregion(int32_t(aTarget->mFilterPrimitiveSubregion.X()), int32_t(aTarget->mFilterPrimitiveSubregion.Y()), int32_t(aTarget->mFilterPrimitiveSubregion.Width()), int32_t(aTarget->mFilterPrimitiveSubregion.Height())); @@ -931,17 +156,17 @@ nsSVGFETurbulenceElement::Filter(nsSVGFi // XXXroc this makes absolutely no sense to me. float filterX = instance->GetFilterRegion().X(); float filterY = instance->GetFilterRegion().Y(); float filterWidth = instance->GetFilterRegion().Width(); float filterHeight = instance->GetFilterRegion().Height(); bool doStitch = false; - if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) { + if (stitch == SVG_STITCHTYPE_STITCH) { doStitch = true; float lowFreq, hiFreq; lowFreq = floor(filterWidth * fX) / filterWidth; hiFreq = ceil(filterWidth * fX) / filterWidth; if (fX / lowFreq < hiFreq / fX) fX = lowFreq; @@ -958,17 +183,17 @@ nsSVGFETurbulenceElement::Filter(nsSVGFi for (int32_t y = rect.y; y < rect.YMost(); y++) { for (int32_t x = rect.x; x < rect.XMost(); x++) { int32_t targIndex = y * stride + x * 4; double point[2]; point[0] = filterX + (filterWidth * (x + instance->GetSurfaceRect().x)) / (filterSubregion.width - 1); point[1] = filterY + (filterHeight * (y + instance->GetSurfaceRect().y)) / (filterSubregion.height - 1); float col[4]; - if (type == nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE) { + if (type == SVG_TURBULENCE_TYPE_TURBULENCE) { for (int i = 0; i < 4; i++) col[i] = Turbulence(i, point, fX, fY, octaves, false, doStitch, filterX, filterY, filterWidth, filterHeight) * 255; } else { for (int i = 0; i < 4; i++) col[i] = (Turbulence(i, point, fX, fY, octaves, true, doStitch, filterX, filterY, filterWidth, filterHeight) * 255 + 255) / 2; } @@ -989,30 +214,30 @@ nsSVGFETurbulenceElement::Filter(nsSVGFi targetData[targIndex + GFX_ARGB32_OFFSET_A] = a; } } return NS_OK; } bool -nsSVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID, +SVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID, nsIAtom* aAttribute) const { - return nsSVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || + return SVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || (aNameSpaceID == kNameSpaceID_None && (aAttribute == nsGkAtoms::seed || aAttribute == nsGkAtoms::baseFrequency || aAttribute == nsGkAtoms::numOctaves || aAttribute == nsGkAtoms::type || aAttribute == nsGkAtoms::stitchTiles)); } void -nsSVGFETurbulenceElement::InitSeed(int32_t aSeed) +SVGFETurbulenceElement::InitSeed(int32_t aSeed) { double s; int i, j, k; aSeed = SetupSeed(aSeed); for (k = 0; k < 4; k++) { for (i = 0; i < sBSize; i++) { mLatticeSelector[i] = i; for (j = 0; j < 2; j++) { @@ -1040,18 +265,18 @@ nsSVGFETurbulenceElement::InitSeed(int32 for (j = 0; j < 2; j++) mGradient[k][sBSize + i][j] = mGradient[k][i][j]; } } #define S_CURVE(t) ( t * t * (3. - 2. * t) ) #define LERP(t, a, b) ( a + t * (b - a) ) double -nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2], - StitchInfo *aStitchInfo) +SVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2], + StitchInfo *aStitchInfo) { int bx0, bx1, by0, by1, b00, b10, b01, b11; double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v; register long i, j; t = aVec[0] + sPerlinN; bx0 = (int) t; bx1 = bx0 + 1; rx0 = t - (int) t; @@ -1095,22 +320,22 @@ nsSVGFETurbulenceElement::Noise2(int aCo v = rx1 * q[0] + ry1 * q[1]; b = LERP(sx, u, v); return LERP(sy, a, b); } #undef S_CURVE #undef LERP double -nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint, - double aBaseFreqX, double aBaseFreqY, - int aNumOctaves, bool aFractalSum, - bool aDoStitching, - double aTileX, double aTileY, - double aTileWidth, double aTileHeight) +SVGFETurbulenceElement::Turbulence(int aColorChannel, double* aPoint, + double aBaseFreqX, double aBaseFreqY, + int aNumOctaves, bool aFractalSum, + bool aDoStitching, + double aTileX, double aTileY, + double aTileWidth, double aTileHeight) { StitchInfo stitch; StitchInfo *stitchInfo = NULL; // Not stitching when NULL. // Adjust the base frequencies if necessary for stitching. if (aDoStitching) { // When stitching tiled turbulence, the frequencies must be adjusted // so that the tile borders will be continuous. if (aBaseFreqX != 0.0) { @@ -1157,714 +382,54 @@ nsSVGFETurbulenceElement::Turbulence(int stitch.mHeight *= 2; stitch.mWrapY = 2 * stitch.mWrapY - sPerlinN; } } return sum; } nsIntRect -nsSVGFETurbulenceElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, +SVGFETurbulenceElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) { return GetMaxRect(); } //---------------------------------------------------------------------- // nsSVGElement methods nsSVGElement::NumberAttributesInfo -nsSVGFETurbulenceElement::GetNumberInfo() +SVGFETurbulenceElement::GetNumberInfo() { return NumberAttributesInfo(mNumberAttributes, sNumberInfo, ArrayLength(sNumberInfo)); } nsSVGElement::NumberPairAttributesInfo -nsSVGFETurbulenceElement::GetNumberPairInfo() +SVGFETurbulenceElement::GetNumberPairInfo() { return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, ArrayLength(sNumberPairInfo)); } nsSVGElement::IntegerAttributesInfo -nsSVGFETurbulenceElement::GetIntegerInfo() +SVGFETurbulenceElement::GetIntegerInfo() { return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo, ArrayLength(sIntegerInfo)); } nsSVGElement::EnumAttributesInfo -nsSVGFETurbulenceElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFETurbulenceElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Morphology------------------------ - -typedef nsSVGFE nsSVGFEMorphologyElementBase; - -class nsSVGFEMorphologyElement : public nsSVGFEMorphologyElementBase, - public nsIDOMSVGFEMorphologyElement -{ - friend nsresult NS_NewSVGFEMorphologyElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEMorphologyElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEMorphologyElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMorphologyElementBase::) - - virtual nsresult Filter(nsSVGFilterInstance* aInstance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& aDataRect); - virtual bool AttributeAffectsRendering( - int32_t aNameSpaceID, nsIAtom* aAttribute) const; - virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; } - virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources); - virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance); - virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance); - virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance); - - // Morphology - NS_DECL_NSIDOMSVGFEMORPHOLOGYELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMorphologyElementBase::) - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - void GetRXY(int32_t *aRX, int32_t *aRY, const nsSVGFilterInstance& aInstance); - nsIntRect InflateRect(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance); - - virtual NumberPairAttributesInfo GetNumberPairInfo(); - virtual EnumAttributesInfo GetEnumInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { RADIUS }; - nsSVGNumberPair mNumberPairAttributes[1]; - static NumberPairInfo sNumberPairInfo[1]; - - enum { OPERATOR }; - nsSVGEnum mEnumAttributes[1]; - static nsSVGEnumMapping sOperatorMap[]; - static EnumInfo sEnumInfo[1]; - - enum { RESULT, IN1 }; - nsSVGString mStringAttributes[2]; - static StringInfo sStringInfo[2]; -}; - -nsSVGElement::NumberPairInfo nsSVGFEMorphologyElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::radius, 0, 0 } -}; - -nsSVGEnumMapping nsSVGFEMorphologyElement::sOperatorMap[] = { - {&nsGkAtoms::erode, nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE}, - {&nsGkAtoms::dilate, nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFEMorphologyElement::sEnumInfo[1] = -{ - { &nsGkAtoms::_operator, - sOperatorMap, - nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE - } -}; - -nsSVGElement::StringInfo nsSVGFEMorphologyElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEMorphology) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase) - -DOMCI_NODE_DATA(SVGFEMorphologyElement, nsSVGFEMorphologyElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEMorphologyElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEMorphologyElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEMorphologyElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMorphologyElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMorphologyElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMorphologyElement) - - -//---------------------------------------------------------------------- -// nsSVGFEMorphologyElement methods - -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration operator; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetOperator(nsIDOMSVGAnimatedEnumeration * *aOperator) -{ - return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(aOperator, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber radiusX; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusX(nsIDOMSVGAnimatedNumber * *aX) -{ - return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber radiusY; */ -NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusY(nsIDOMSVGAnimatedNumber * *aY) -{ - return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this); -} - -NS_IMETHODIMP -nsSVGFEMorphologyElement::SetRadius(float rx, float ry) -{ - NS_ENSURE_FINITE2(rx, ry, NS_ERROR_ILLEGAL_VALUE); - mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this); - return NS_OK; -} - -void -nsSVGFEMorphologyElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -nsIntRect -nsSVGFEMorphologyElement::InflateRect(const nsIntRect& aRect, - const nsSVGFilterInstance& aInstance) -{ - int32_t rx, ry; - GetRXY(&rx, &ry, aInstance); - nsIntRect result = aRect; - result.Inflate(std::max(0, rx), std::max(0, ry)); - return result; -} - -nsIntRect -nsSVGFEMorphologyElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - return InflateRect(aSourceBBoxes[0], aInstance); -} - -void -nsSVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) -{ - aSourceBBoxes[0] = InflateRect(aTargetBBox, aInstance); -} - -nsIntRect -nsSVGFEMorphologyElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - return InflateRect(aSourceChangeBoxes[0], aInstance); -} - -#define MORPHOLOGY_EPSILON 0.0001 - -void -nsSVGFEMorphologyElement::GetRXY(int32_t *aRX, int32_t *aRY, - const nsSVGFilterInstance& aInstance) -{ - // Subtract an epsilon here because we don't want a value that's just - // slightly larger than an integer to round up to the next integer; it's - // probably meant to be the integer it's close to, modulo machine precision - // issues. - *aRX = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::X, - &mNumberPairAttributes[RADIUS], - nsSVGNumberPair::eFirst) - - MORPHOLOGY_EPSILON); - *aRY = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::Y, - &mNumberPairAttributes[RADIUS], - nsSVGNumberPair::eSecond) - - MORPHOLOGY_EPSILON); -} - -nsresult -nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - int32_t rx, ry; - GetRXY(&rx, &ry, *instance); - - if (rx < 0 || ry < 0) { - // XXX SVGContentUtils::ReportToConsole() - return NS_OK; - } - if (rx == 0 && ry == 0) { - return NS_OK; - } - - // Clamp radii to prevent completely insane values: - rx = std::min(rx, 100000); - ry = std::min(ry, 100000); - - uint8_t* sourceData = aSources[0]->mImage->Data(); - uint8_t* targetData = aTarget->mImage->Data(); - int32_t stride = aTarget->mImage->Stride(); - uint8_t extrema[4]; // RGBA magnitude of extrema - uint16_t op = mEnumAttributes[OPERATOR].GetAnimValue(); - - // Scan the kernel for each pixel to determine max/min RGBA values. - for (int32_t y = rect.y; y < rect.YMost(); y++) { - int32_t startY = std::max(0, y - ry); - // We need to read pixels not just in 'rect', which is limited to - // the dirty part of our filter primitive subregion, but all pixels in - // the given radii from the source surface, so use the surface size here. - int32_t endY = std::min(y + ry, instance->GetSurfaceHeight() - 1); - for (int32_t x = rect.x; x < rect.XMost(); x++) { - int32_t startX = std::max(0, x - rx); - int32_t endX = std::min(x + rx, instance->GetSurfaceWidth() - 1); - int32_t targIndex = y * stride + 4 * x; - - for (int32_t i = 0; i < 4; i++) { - extrema[i] = sourceData[targIndex + i]; - } - for (int32_t y1 = startY; y1 <= endY; y1++) { - for (int32_t x1 = startX; x1 <= endX; x1++) { - for (int32_t i = 0; i < 4; i++) { - uint8_t pixel = sourceData[y1 * stride + 4 * x1 + i]; - if ((extrema[i] > pixel && - op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) || - (extrema[i] < pixel && - op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) { - extrema[i] = pixel; - } - } - } - } - targetData[targIndex ] = extrema[0]; - targetData[targIndex+1] = extrema[1]; - targetData[targIndex+2] = extrema[2]; - targetData[targIndex+3] = extrema[3]; - } - } - return NS_OK; -} - -bool -nsSVGFEMorphologyElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::radius || - aAttribute == nsGkAtoms::_operator)); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberPairAttributesInfo -nsSVGFEMorphologyElement::GetNumberPairInfo() -{ - return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, - ArrayLength(sNumberPairInfo)); -} - -nsSVGElement::EnumAttributesInfo -nsSVGFEMorphologyElement::GetEnumInfo() +SVGFETurbulenceElement::GetEnumInfo() { return EnumAttributesInfo(mEnumAttributes, sEnumInfo, ArrayLength(sEnumInfo)); } nsSVGElement::StringAttributesInfo -nsSVGFEMorphologyElement::GetStringInfo() +SVGFETurbulenceElement::GetStringInfo() { return StringAttributesInfo(mStringAttributes, sStringInfo, ArrayLength(sStringInfo)); } -//-------------------------------------------------------------------- -// -nsSVGElement::NumberInfo nsSVGFELightingElement::sNumberInfo[4] = -{ - { &nsGkAtoms::surfaceScale, 1, false }, - { &nsGkAtoms::diffuseConstant, 1, false }, - { &nsGkAtoms::specularConstant, 1, false }, - { &nsGkAtoms::specularExponent, 1, false } -}; - -nsSVGElement::NumberPairInfo nsSVGFELightingElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::kernelUnitLength, 0, 0 } -}; - -nsSVGElement::StringInfo nsSVGFELightingElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFELightingElement,nsSVGFELightingElementBase) - -NS_INTERFACE_MAP_BEGIN(nsSVGFELightingElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFELightingElementBase) - -//---------------------------------------------------------------------- -// Implementation - -NS_IMETHODIMP_(bool) -nsSVGFELightingElement::IsAttributeMapped(const nsIAtom* name) const -{ - static const MappedAttributeEntry* const map[] = { - sLightingEffectsMap - }; - - return FindAttributeDependence(name, map) || - nsSVGFELightingElementBase::IsAttributeMapped(name); -} - -void -nsSVGFELightingElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -void -nsSVGFELightingElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) -{ - // XXX lighting can depend on more than the target area, because - // of the kernels it uses. We could compute something precise here - // but just leave it and assume we use the entire source bounding box. -} - -nsIntRect -nsSVGFELightingElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - // XXX be conservative for now - return GetMaxRect(); -} - -static int32_t -Convolve3x3(const uint8_t *index, int32_t stride, - const int8_t kernel[3][3] -#ifdef DEBUG - , const uint8_t *minData, const uint8_t *maxData -#endif // DEBUG -) -{ - int32_t sum = 0; - for (int32_t y = 0; y < 3; y++) { - for (int32_t x = 0; x < 3; x++) { - int8_t k = kernel[y][x]; - if (k) { - const uint8_t *valPtr = index + (4 * (x - 1) + stride * (y - 1)); - NS_ASSERTION(valPtr >= minData, "out of bounds read (before buffer)"); - NS_ASSERTION(valPtr < maxData, "out of bounds read (after buffer)"); - sum += k * (*valPtr); - } - } - } - return sum; -} - -static void -GenerateNormal(float *N, const uint8_t *data, int32_t stride, - int32_t surfaceWidth, int32_t surfaceHeight, - int32_t x, int32_t y, float surfaceScale) -{ - // See this for source of constants: - // http://www.w3.org/TR/SVG11/filters.html#feDiffuseLightingElement - static const int8_t Kx[3][3][3][3] = - { { { { 0, 0, 0}, { 0, -2, 2}, { 0, -1, 1} }, - { { 0, 0, 0}, {-2, 0, 2}, {-1, 0, 1} }, - { { 0, 0, 0}, {-2, 2, 0}, {-1, 1, 0} } }, - { { { 0, -1, 1}, { 0, -2, 2}, { 0, -1, 1} }, - { { -1, 0, 1}, {-2, 0, 2}, {-1, 0, 1} }, - { { -1, 1, 0}, {-2, 2, 0}, {-1, 1, 0} } }, - { { { 0, -1, 1}, { 0, -2, 2}, { 0, 0, 0} }, - { { -1, 0, 1}, {-2, 0, 2}, { 0, 0, 0} }, - { { -1, 1, 0}, {-2, 2, 0}, { 0, 0, 0} } } }; - static const int8_t Ky[3][3][3][3] = - { { { { 0, 0, 0}, { 0, -2, -1}, { 0, 2, 1} }, - { { 0, 0, 0}, {-1, -2, -1}, { 1, 2, 1} }, - { { 0, 0, 0}, {-1, -2, 1}, { 1, 2, 0} } }, - { { { 0, -2, -1}, { 0, 0, 0}, { 0, 2, 1} }, - { { -1, -2, -1}, { 0, 0, 0}, { 1, 2, 1} }, - { { -1, -2, 0}, { 0, 0, 0}, { 1, 2, 0} } }, - { { { 0, -2, -1}, { 0, 2, 1}, { 0, 0, 0} }, - { { -1, -2, -1}, { 1, 2, 1}, { 0, 0, 0} }, - { { -1, -2, 0}, { 1, 2, 0}, { 0, 0, 0} } } }; - static const float FACTORx[3][3] = - { { 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0 }, - { 1.0 / 2.0, 1.0 / 4.0, 1.0 / 2.0 }, - { 2.0 / 3.0, 1.0 / 3.0, 2.0 / 3.0 } }; - static const float FACTORy[3][3] = - { { 2.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0 }, - { 1.0 / 3.0, 1.0 / 4.0, 1.0 / 3.0 }, - { 2.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0 } }; - - // degenerate cases - if (surfaceWidth == 1 || surfaceHeight == 1) { - // just return a unit vector pointing towards the viewer - N[0] = 0; - N[1] = 0; - N[2] = 255; - return; - } - - int8_t xflag, yflag; - if (x == 0) { - xflag = 0; - } else if (x == surfaceWidth - 1) { - xflag = 2; - } else { - xflag = 1; - } - if (y == 0) { - yflag = 0; - } else if (y == surfaceHeight - 1) { - yflag = 2; - } else { - yflag = 1; - } - - const uint8_t *index = data + y * stride + 4 * x + GFX_ARGB32_OFFSET_A; - -#ifdef DEBUG - // For sanity-checking, to be sure we're not reading outside source buffer: - const uint8_t* minData = data; - const uint8_t* maxData = minData + (surfaceHeight * surfaceWidth * stride); - - // We'll sanity-check each value we read inside of Convolve3x3, but we - // might as well ensure we're passing it a valid pointer to start with, too: - NS_ASSERTION(index >= minData, "index points before buffer start"); - NS_ASSERTION(index < maxData, "index points after buffer end"); -#endif // DEBUG - - N[0] = -surfaceScale * FACTORx[yflag][xflag] * - Convolve3x3(index, stride, Kx[yflag][xflag] -#ifdef DEBUG - , minData, maxData -#endif // DEBUG - ); - - N[1] = -surfaceScale * FACTORy[yflag][xflag] * - Convolve3x3(index, stride, Ky[yflag][xflag] -#ifdef DEBUG - , minData, maxData -#endif // DEBUG - ); - N[2] = 255; - NORMALIZE(N); -} - -nsresult -nsSVGFELightingElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - ScaleInfo info = SetupScalingFilter(instance, aSources[0], aTarget, rect, - &mNumberPairAttributes[KERNEL_UNIT_LENGTH]); - if (!info.mTarget) - return NS_ERROR_FAILURE; - - SVGFEDistantLightElement* distantLight = nullptr; - SVGFEPointLightElement* pointLight = nullptr; - SVGFESpotLightElement* spotLight = nullptr; - - nsIFrame* frame = GetPrimaryFrame(); - if (!frame) return NS_ERROR_FAILURE; - nsStyleContext* style = frame->StyleContext(); - - nscolor lightColor = style->StyleSVGReset()->mLightingColor; - - // find specified light - for (nsCOMPtr<nsIContent> child = nsINode::GetFirstChild(); - child; - child = child->GetNextSibling()) { - distantLight = child->IsSVG(nsGkAtoms::feDistantLight) ? - static_cast<SVGFEDistantLightElement*>(child.get()) : nullptr; - pointLight = child->IsSVG(nsGkAtoms::fePointLight) ? - static_cast<SVGFEPointLightElement*>(child.get()) : nullptr; - spotLight = child->IsSVG(nsGkAtoms::feSpotLight) ? - static_cast<SVGFESpotLightElement*>(child.get()) : nullptr; - if (distantLight || pointLight || spotLight) - break; - } - - if (!distantLight && !pointLight && !spotLight) - return NS_ERROR_FAILURE; - - const float radPerDeg = M_PI/180.0; - - float L[3]; - if (distantLight) { - float azimuth, elevation; - distantLight->GetAnimatedNumberValues(&azimuth, - &elevation, - nullptr); - L[0] = cos(azimuth * radPerDeg) * cos(elevation * radPerDeg); - L[1] = sin(azimuth * radPerDeg) * cos(elevation * radPerDeg); - L[2] = sin(elevation * radPerDeg); - } - float lightPos[3], pointsAt[3], specularExponent; - float cosConeAngle = 0; - if (pointLight) { - pointLight->GetAnimatedNumberValues(lightPos, - lightPos + 1, - lightPos + 2, - nullptr); - instance->ConvertLocation(lightPos); - } - if (spotLight) { - float limitingConeAngle; - spotLight->GetAnimatedNumberValues(lightPos, - lightPos + 1, - lightPos + 2, - pointsAt, - pointsAt + 1, - pointsAt + 2, - &specularExponent, - &limitingConeAngle, - nullptr); - instance->ConvertLocation(lightPos); - instance->ConvertLocation(pointsAt); - - if (spotLight->mNumberAttributes[SVGFESpotLightElement::LIMITING_CONE_ANGLE]. - IsExplicitlySet()) { - cosConeAngle = std::max<double>(cos(limitingConeAngle * radPerDeg), 0.0); - } - } - - float surfaceScale = mNumberAttributes[SURFACE_SCALE].GetAnimValue(); - - const nsIntRect& dataRect = info.mDataRect; - int32_t stride = info.mSource->Stride(); - uint8_t *sourceData = info.mSource->Data(); - uint8_t *targetData = info.mTarget->Data(); - int32_t surfaceWidth = info.mSource->Width(); - int32_t surfaceHeight = info.mSource->Height(); - - for (int32_t y = dataRect.y; y < dataRect.YMost(); y++) { - for (int32_t x = dataRect.x; x < dataRect.XMost(); x++) { - int32_t index = y * stride + x * 4; - - float N[3]; - GenerateNormal(N, sourceData, stride, surfaceWidth, surfaceHeight, - x, y, surfaceScale); - - if (pointLight || spotLight) { - gfxPoint pt = instance->FilterSpaceToUserSpace( - gfxPoint(x + instance->GetSurfaceRect().x, - y + instance->GetSurfaceRect().y)); - float Z = surfaceScale * sourceData[index + GFX_ARGB32_OFFSET_A] / 255; - - L[0] = lightPos[0] - pt.x; - L[1] = lightPos[1] - pt.y; - L[2] = lightPos[2] - Z; - NORMALIZE(L); - } - - nscolor color; - - if (spotLight) { - float S[3]; - S[0] = pointsAt[0] - lightPos[0]; - S[1] = pointsAt[1] - lightPos[1]; - S[2] = pointsAt[2] - lightPos[2]; - NORMALIZE(S); - float dot = -DOT(L, S); - float tmp = pow(dot, specularExponent); - if (dot < cosConeAngle) tmp = 0; - color = NS_RGB(uint8_t(NS_GET_R(lightColor) * tmp), - uint8_t(NS_GET_G(lightColor) * tmp), - uint8_t(NS_GET_B(lightColor) * tmp)); - } else { - color = lightColor; - } - - LightPixel(N, L, color, targetData + index); - } - } - - FinishScalingFilter(&info); - - return NS_OK; -} - -bool -nsSVGFELightingElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFELightingElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::surfaceScale || - aAttribute == nsGkAtoms::kernelUnitLength)); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFELightingElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -nsSVGElement::NumberPairAttributesInfo -nsSVGFELightingElement::GetNumberPairInfo() -{ - return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, - ArrayLength(sNumberPairInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFELightingElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} +} // namespace dom +} // namespace mozilla
copy from content/svg/content/src/nsSVGFilters.cpp copy to content/svg/content/src/SVGFETurbulenceElement.h --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/SVGFETurbulenceElement.h @@ -1,715 +1,76 @@ /* a*- 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 "nsSVGElement.h" -#include "nsGkAtoms.h" -#include "nsSVGNumber2.h" -#include "nsSVGNumberPair.h" -#include "nsSVGInteger.h" -#include "nsSVGIntegerPair.h" -#include "nsSVGBoolean.h" -#include "nsIDOMSVGFilters.h" -#include "nsCOMPtr.h" -#include "nsSVGFilterInstance.h" -#include "nsSVGEnum.h" -#include "SVGNumberList.h" -#include "SVGAnimatedNumberList.h" -#include "DOMSVGAnimatedNumberList.h" -#include "nsSVGFilters.h" -#include "nsLayoutUtils.h" -#include "nsSVGUtils.h" -#include "nsStyleContext.h" -#include "nsIFrame.h" -#include "gfxContext.h" -#include "gfxMatrix.h" -#include "imgIContainer.h" -#include "nsNetUtil.h" -#include "mozilla/dom/SVGFilterElement.h" -#include "nsSVGString.h" -#include "gfxUtils.h" -#include "SVGContentUtils.h" -#include <algorithm> -#include "nsContentUtils.h" -#include "mozilla/dom/SVGAnimatedLength.h" -#include "mozilla/dom/SVGComponentTransferFunctionElement.h" -#include "mozilla/dom/SVGFEDistantLightElement.h" -#include "mozilla/dom/SVGFEFuncAElementBinding.h" -#include "mozilla/dom/SVGFEFuncBElementBinding.h" -#include "mozilla/dom/SVGFEFuncGElementBinding.h" -#include "mozilla/dom/SVGFEFuncRElementBinding.h" -#include "mozilla/dom/SVGFEPointLightElement.h" -#include "mozilla/dom/SVGFESpotLightElement.h" - -#if defined(XP_WIN) -// Prevent Windows redefining LoadImage -#undef LoadImage -#endif - -using namespace mozilla; -using namespace mozilla::dom; - -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4; -static const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5; - -void -CopyDataRect(uint8_t *aDest, const uint8_t *aSrc, uint32_t aStride, - const nsIntRect& aDataRect) -{ - for (int32_t y = aDataRect.y; y < aDataRect.YMost(); y++) { - memcpy(aDest + y * aStride + 4 * aDataRect.x, - aSrc + y * aStride + 4 * aDataRect.x, - 4 * aDataRect.width); - } -} - -static void -CopyAndScaleDeviceOffset(const gfxImageSurface *aImage, gfxImageSurface *aResult, - gfxFloat kernelX, gfxFloat kernelY) -{ - gfxPoint deviceOffset = aImage->GetDeviceOffset(); - deviceOffset.x /= kernelX; - deviceOffset.y /= kernelY; - aResult->SetDeviceOffset(deviceOffset); -} - -//--------------------Filter Element Base Class----------------------- - -nsSVGElement::LengthInfo nsSVGFE::sLengthInfo[4] = -{ - { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, - { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y }, - { &nsGkAtoms::width, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X }, - { &nsGkAtoms::height, 100, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFE,nsSVGFEBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFE,nsSVGFEBase) - -NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGFE, NS_SVG_FE_CID) - -NS_INTERFACE_MAP_BEGIN(nsSVGFE) - // nsISupports is an ambiguous base of nsSVGFE so we have to work - // around that - if ( aIID.Equals(NS_GET_IID(nsSVGFE)) ) - foundInterface = static_cast<nsISupports*>(static_cast<void*>(this)); - else -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBase) - -//---------------------------------------------------------------------- -// Implementation - -nsSVGFE::ScaleInfo -nsSVGFE::SetupScalingFilter(nsSVGFilterInstance *aInstance, - const Image *aSource, const Image *aTarget, - const nsIntRect& aDataRect, - nsSVGNumberPair *aKernelUnitLength) -{ - ScaleInfo result; - result.mRescaling = aKernelUnitLength->IsExplicitlySet(); - if (!result.mRescaling) { - result.mSource = aSource->mImage; - result.mTarget = aTarget->mImage; - result.mDataRect = aDataRect; - return result; - } - - gfxFloat kernelX = aInstance->GetPrimitiveNumber(SVGContentUtils::X, - aKernelUnitLength, - nsSVGNumberPair::eFirst); - gfxFloat kernelY = aInstance->GetPrimitiveNumber(SVGContentUtils::Y, - aKernelUnitLength, - nsSVGNumberPair::eSecond); - if (kernelX <= 0 || kernelY <= 0) - return result; - - bool overflow = false; - gfxIntSize scaledSize = - nsSVGUtils::ConvertToSurfaceSize(gfxSize(aTarget->mImage->Width() / kernelX, - aTarget->mImage->Height() / kernelY), - &overflow); - // If the requested size based on the kernel unit is too big, we - // need to bail because the effect is pixel size dependent. Also - // need to check if we ended up with a negative size (arithmetic - // overflow) or zero size (large kernel unit) - if (overflow || scaledSize.width <= 0 || scaledSize.height <= 0) - return result; - - gfxRect r(aDataRect.x, aDataRect.y, aDataRect.width, aDataRect.height); - r.Scale(1 / kernelX, 1 / kernelY); - r.RoundOut(); - if (!gfxUtils::GfxRectToIntRect(r, &result.mDataRect)) - return result; - - // Rounding in the code above can mean that result.mDataRect is not contained - // within the bounds of the surfaces that we're about to create. We must - // clamp to these bounds to prevent out-of-bounds reads and writes: - result.mDataRect.IntersectRect(result.mDataRect, - nsIntRect(nsIntPoint(), scaledSize)); - - result.mSource = new gfxImageSurface(scaledSize, - gfxASurface::ImageFormatARGB32); - result.mTarget = new gfxImageSurface(scaledSize, - gfxASurface::ImageFormatARGB32); - if (!result.mSource || result.mSource->CairoStatus() || - !result.mTarget || result.mTarget->CairoStatus()) { - result.mSource = nullptr; - result.mTarget = nullptr; - return result; - } - - CopyAndScaleDeviceOffset(aSource->mImage, result.mSource, kernelX, kernelY); - CopyAndScaleDeviceOffset(aTarget->mImage, result.mTarget, kernelX, kernelY); - - result.mRealTarget = aTarget->mImage; +#ifndef mozilla_dom_SVGFETurbulenceElement_h +#define mozilla_dom_SVGFETurbulenceElement_h - gfxContext ctx(result.mSource); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.Scale(double(scaledSize.width) / aTarget->mImage->Width(), - double(scaledSize.height) / aTarget->mImage->Height()); - ctx.SetSource(aSource->mImage); - ctx.Paint(); - - // mTarget was already cleared when it was created - - return result; -} - -void -nsSVGFE::FinishScalingFilter(ScaleInfo *aScaleInfo) -{ - if (!aScaleInfo->mRescaling) - return; - - gfxIntSize scaledSize = aScaleInfo->mTarget->GetSize(); - - gfxContext ctx(aScaleInfo->mRealTarget); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.Scale(double(aScaleInfo->mRealTarget->Width()) / scaledSize.width, - double(aScaleInfo->mRealTarget->Height()) / scaledSize.height); - ctx.SetSource(aScaleInfo->mTarget); - ctx.Paint(); -} - -nsIntRect -nsSVGFE::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - nsIntRect r; - for (uint32_t i = 0; i < aSourceBBoxes.Length(); ++i) { - r.UnionRect(r, aSourceBBoxes[i]); - } - return r; -} - -void -nsSVGFE::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - for (uint32_t i = 0; i < aSourceBBoxes.Length(); ++i) { - aSourceBBoxes[i] = aTargetBBox; - } -} - -nsIntRect -nsSVGFE::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - nsIntRect r; - for (uint32_t i = 0; i < aSourceChangeBoxes.Length(); ++i) { - r.UnionRect(r, aSourceChangeBoxes[i]); - } - return r; -} - -void -nsSVGFE::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ -} - -bool -nsSVGFE::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::x || - aAttribute == nsGkAtoms::y || - aAttribute == nsGkAtoms::width || - aAttribute == nsGkAtoms::height || - aAttribute == nsGkAtoms::result); -} - -//---------------------------------------------------------------------- -// nsIDOMSVGFilterPrimitiveStandardAttributes methods - -/* readonly attribute nsIDOMSVGAnimatedLength x; */ -NS_IMETHODIMP nsSVGFE::GetX(nsIDOMSVGAnimatedLength * *aX) -{ - *aX = X().get(); - return NS_OK; -} +#include "nsSVGEnum.h" +#include "nsSVGFilters.h" +#include "nsSVGNumber2.h" +#include "nsSVGInteger.h" +#include "nsSVGString.h" -already_AddRefed<SVGAnimatedLength> -nsSVGFE::X() -{ - return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength y; */ -NS_IMETHODIMP nsSVGFE::GetY(nsIDOMSVGAnimatedLength * *aY) -{ - *aY = Y().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Y() -{ - return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength width; */ -NS_IMETHODIMP nsSVGFE::GetWidth(nsIDOMSVGAnimatedLength * *aWidth) -{ - *aWidth = Width().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Width() -{ - return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength height; */ -NS_IMETHODIMP nsSVGFE::GetHeight(nsIDOMSVGAnimatedLength * *aHeight) -{ - *aHeight = Height().get(); - return NS_OK; -} - -already_AddRefed<SVGAnimatedLength> -nsSVGFE::Height() -{ - return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this); -} - -/* readonly attribute nsIDOMSVGAnimatedString result; */ -NS_IMETHODIMP nsSVGFE::GetResult(nsIDOMSVGAnimatedString * *aResult) -{ - *aResult = Result().get(); - return NS_OK; -} - -already_AddRefed<nsIDOMSVGAnimatedString> -nsSVGFE::Result() -{ - return GetResultImageName().ToDOMAnimatedString(this); -} - -//---------------------------------------------------------------------- -// nsIContent methods - -NS_IMETHODIMP_(bool) -nsSVGFE::IsAttributeMapped(const nsIAtom* name) const -{ - static const MappedAttributeEntry* const map[] = { - sFiltersMap - }; - - return FindAttributeDependence(name, map) || - nsSVGFEBase::IsAttributeMapped(name); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -/* virtual */ bool -nsSVGFE::HasValidDimensions() const -{ - return (!mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() || - mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0) && - (!mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() || - mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0); -} - -nsSVGElement::LengthAttributesInfo -nsSVGFE::GetLengthInfo() -{ - return LengthAttributesInfo(mLengthAttributes, sLengthInfo, - ArrayLength(sLengthInfo)); -} +nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult, + already_AddRefed<nsINodeInfo> aNodeInfo); namespace mozilla { namespace dom { -nsSVGElement::NumberListInfo SVGComponentTransferFunctionElement::sNumberListInfo[1] = -{ - { &nsGkAtoms::tableValues } -}; - -nsSVGElement::NumberInfo SVGComponentTransferFunctionElement::sNumberInfo[5] = -{ - { &nsGkAtoms::slope, 1, false }, - { &nsGkAtoms::intercept, 0, false }, - { &nsGkAtoms::amplitude, 1, false }, - { &nsGkAtoms::exponent, 1, false }, - { &nsGkAtoms::offset, 0, false } -}; - -nsSVGEnumMapping SVGComponentTransferFunctionElement::sTypeMap[] = { - {&nsGkAtoms::identity, - SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY}, - {&nsGkAtoms::table, - SVG_FECOMPONENTTRANSFER_TYPE_TABLE}, - {&nsGkAtoms::discrete, - SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE}, - {&nsGkAtoms::linear, - SVG_FECOMPONENTTRANSFER_TYPE_LINEAR}, - {&nsGkAtoms::gamma, - SVG_FECOMPONENTTRANSFER_TYPE_GAMMA}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo SVGComponentTransferFunctionElement::sEnumInfo[1] = -{ - { &nsGkAtoms::type, - sTypeMap, - SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY - } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) -NS_IMPL_RELEASE_INHERITED(SVGComponentTransferFunctionElement,SVGComponentTransferFunctionElementBase) - -NS_DEFINE_STATIC_IID_ACCESSOR(SVGComponentTransferFunctionElement, NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID) - -NS_INTERFACE_MAP_BEGIN(SVGComponentTransferFunctionElement) - // nsISupports is an ambiguous base of nsSVGFE so we have to work - // around that - if ( aIID.Equals(NS_GET_IID(SVGComponentTransferFunctionElement)) ) - foundInterface = static_cast<nsISupports*>(static_cast<void*>(this)); - else -NS_INTERFACE_MAP_END_INHERITING(SVGComponentTransferFunctionElementBase) - - -//---------------------------------------------------------------------- -// nsFEUnstyledElement methods - -bool -SVGComponentTransferFunctionElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::tableValues || - aAttribute == nsGkAtoms::slope || - aAttribute == nsGkAtoms::intercept || - aAttribute == nsGkAtoms::amplitude || - aAttribute == nsGkAtoms::exponent || - aAttribute == nsGkAtoms::offset || - aAttribute == nsGkAtoms::type); -} - -//---------------------------------------------------------------------- - -already_AddRefed<nsIDOMSVGAnimatedEnumeration> -SVGComponentTransferFunctionElement::Type() -{ - return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this); -} - -already_AddRefed<DOMSVGAnimatedNumberList> -SVGComponentTransferFunctionElement::TableValues() -{ - return DOMSVGAnimatedNumberList::GetDOMWrapper( - &mNumberListAttributes[TABLEVALUES], this, TABLEVALUES); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Slope() -{ - return mNumberAttributes[SLOPE].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Intercept() -{ - return mNumberAttributes[INTERCEPT].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Amplitude() -{ - return mNumberAttributes[AMPLITUDE].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Exponent() -{ - return mNumberAttributes[EXPONENT].ToDOMAnimatedNumber(this); -} - -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Offset() -{ - return mNumberAttributes[OFFSET].ToDOMAnimatedNumber(this); -} - -bool -SVGComponentTransferFunctionElement::GenerateLookupTable(uint8_t *aTable) -{ - uint16_t type = mEnumAttributes[TYPE].GetAnimValue(); - - float slope, intercept, amplitude, exponent, offset; - GetAnimatedNumberValues(&slope, &intercept, &litude, - &exponent, &offset, nullptr); - - const SVGNumberList &tableValues = - mNumberListAttributes[TABLEVALUES].GetAnimValue(); - uint32_t tvLength = tableValues.Length(); - - uint32_t i; - - switch (type) { - case SVG_FECOMPONENTTRANSFER_TYPE_TABLE: - { - if (tableValues.Length() < 2) - return false; - - for (i = 0; i < 256; i++) { - uint32_t k = (i * (tvLength - 1)) / 255; - float v1 = tableValues[k]; - float v2 = tableValues[std::min(k + 1, tvLength - 1)]; - int32_t val = - int32_t(255 * (v1 + (i/255.0f - k/float(tvLength-1))*(tvLength - 1)*(v2 - v1))); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: - { - if (tableValues.Length() < 1) - return false; +typedef nsSVGFE SVGFETurbulenceElementBase; - for (i = 0; i < 256; i++) { - uint32_t k = (i * tvLength) / 255; - k = std::min(k, tvLength - 1); - float v = tableValues[k]; - int32_t val = int32_t(255 * v); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: - { - for (i = 0; i < 256; i++) { - int32_t val = int32_t(slope * i + 255 * intercept); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: - { - for (i = 0; i < 256; i++) { - int32_t val = int32_t(255 * (amplitude * pow(i / 255.0f, exponent) + offset)); - val = std::min(255, val); - val = std::max(0, val); - aTable[i] = val; - } - break; - } - - case SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: - default: - break; - } - return true; -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberListAttributesInfo -SVGComponentTransferFunctionElement::GetNumberListInfo() -{ - return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, - ArrayLength(sNumberListInfo)); -} - -nsSVGElement::EnumAttributesInfo -SVGComponentTransferFunctionElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::NumberAttributesInfo -SVGComponentTransferFunctionElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncRElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncRElement::WrapNode(JSContext* aCx, JSObject* aScope) +class SVGFETurbulenceElement : public SVGFETurbulenceElementBase, + public nsIDOMSVGElement { - return SVGFEFuncRElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncR) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncRElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncGElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncGElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncGElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncG) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncGElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncBElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncBElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncBElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncB) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncBElement) - -NS_IMPL_ISUPPORTS_INHERITED3(SVGFEFuncAElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement) - -/* virtual */ JSObject* -SVGFEFuncAElement::WrapNode(JSContext* aCx, JSObject* aScope) -{ - return SVGFEFuncAElementBinding::Wrap(aCx, aScope, this); -} - -} // namespace dom -} // namespace mozilla - -NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEFuncA) - -namespace mozilla { -namespace dom { - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncAElement) - -} // namespace dom -} // namespace mozilla - -//---------------------Turbulence------------------------ - -typedef nsSVGFE nsSVGFETurbulenceElementBase; - -class nsSVGFETurbulenceElement : public nsSVGFETurbulenceElementBase, - public nsIDOMSVGFETurbulenceElement -{ - friend nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); + friend nsresult (::NS_NewSVGFETurbulenceElement(nsIContent **aResult, + already_AddRefed<nsINodeInfo> aNodeInfo)); protected: - nsSVGFETurbulenceElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFETurbulenceElementBase(aNodeInfo) {} + SVGFETurbulenceElement(already_AddRefed<nsINodeInfo> aNodeInfo) + : SVGFETurbulenceElementBase(aNodeInfo) + { + SetIsDOMBinding(); + } + virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope) MOZ_OVERRIDE; public: virtual bool SubregionIsUnionOfRegions() { return false; } // interfaces: NS_DECL_ISUPPORTS_INHERITED - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::) - virtual nsresult Filter(nsSVGFilterInstance* aInstance, const nsTArray<const Image*>& aSources, const Image* aTarget, const nsIntRect& aDataRect); virtual bool AttributeAffectsRendering( int32_t aNameSpaceID, nsIAtom* aAttribute) const; virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; } virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance); - // Turbulence - NS_DECL_NSIDOMSVGFETURBULENCEELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::) + NS_FORWARD_NSIDOMSVGELEMENT(SVGFETurbulenceElementBase::) NS_FORWARD_NSIDOMNODE_TO_NSINODE NS_FORWARD_NSIDOMELEMENT_TO_GENERIC virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - virtual nsXPCClassInfo* GetClassInfo(); + virtual nsIDOMNode* AsDOMNode() { return this; } - virtual nsIDOMNode* AsDOMNode() { return this; } + // WebIDL + already_AddRefed<nsIDOMSVGAnimatedNumber> BaseFrequencyX(); + already_AddRefed<nsIDOMSVGAnimatedNumber> BaseFrequencyY(); + already_AddRefed<nsIDOMSVGAnimatedInteger> NumOctaves(); + already_AddRefed<nsIDOMSVGAnimatedNumber> Seed(); + already_AddRefed<nsIDOMSVGAnimatedEnumeration> StitchTiles(); + already_AddRefed<nsIDOMSVGAnimatedEnumeration> Type(); + protected: virtual NumberAttributesInfo GetNumberInfo(); virtual NumberPairAttributesInfo GetNumberPairInfo(); virtual IntegerAttributesInfo GetIntegerInfo(); virtual EnumAttributesInfo GetEnumInfo(); virtual StringAttributesInfo GetStringInfo(); enum { SEED }; // floating point seed?! @@ -791,1080 +152,12 @@ private: double Noise2(int aColorChannel, double aVec[2], StitchInfo *aStitchInfo); double Turbulence(int aColorChannel, double *aPoint, double aBaseFreqX, double aBaseFreqY, int aNumOctaves, bool aFractalSum, bool aDoStitching, double aTileX, double aTileY, double aTileWidth, double aTileHeight); }; -nsSVGElement::NumberInfo nsSVGFETurbulenceElement::sNumberInfo[1] = -{ - { &nsGkAtoms::seed, 0, false } -}; - -nsSVGElement::NumberPairInfo nsSVGFETurbulenceElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::baseFrequency, 0, 0 } -}; - -nsSVGElement::IntegerInfo nsSVGFETurbulenceElement::sIntegerInfo[1] = -{ - { &nsGkAtoms::numOctaves, 1 } -}; - -nsSVGEnumMapping nsSVGFETurbulenceElement::sTypeMap[] = { - {&nsGkAtoms::fractalNoise, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_FRACTALNOISE}, - {&nsGkAtoms::turbulence, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE}, - {nullptr, 0} -}; - -nsSVGEnumMapping nsSVGFETurbulenceElement::sStitchTilesMap[] = { - {&nsGkAtoms::stitch, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH}, - {&nsGkAtoms::noStitch, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFETurbulenceElement::sEnumInfo[2] = -{ - { &nsGkAtoms::type, - sTypeMap, - nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE - }, - { &nsGkAtoms::stitchTiles, - sStitchTilesMap, - nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH - } -}; - -nsSVGElement::StringInfo nsSVGFETurbulenceElement::sStringInfo[1] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase) - -DOMCI_NODE_DATA(SVGFETurbulenceElement, nsSVGFETurbulenceElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFETurbulenceElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFETurbulenceElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFETurbulenceElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETurbulenceElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFETurbulenceElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETurbulenceElement) - -//---------------------------------------------------------------------- -// nsIDOMSVGFETurbulenceElement methods - -/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyX(nsIDOMSVGAnimatedNumber * *aX) -{ - return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyY(nsIDOMSVGAnimatedNumber * *aY) -{ - return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this); -} - -/* readonly attribute nsIDOMSVGAnimatedInteger numOctaves; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetNumOctaves(nsIDOMSVGAnimatedInteger * *aNum) -{ - return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(aNum, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber seed; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetSeed(nsIDOMSVGAnimatedNumber * *aSeed) -{ - return mNumberAttributes[SEED].ToDOMAnimatedNumber(aSeed, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetStitchTiles(nsIDOMSVGAnimatedEnumeration * *aStitch) -{ - return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(aStitch, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */ -NS_IMETHODIMP nsSVGFETurbulenceElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType) -{ - return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this); -} - -nsresult -nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - uint8_t* targetData = aTarget->mImage->Data(); - uint32_t stride = aTarget->mImage->Stride(); - - nsIntRect filterSubregion(int32_t(aTarget->mFilterPrimitiveSubregion.X()), - int32_t(aTarget->mFilterPrimitiveSubregion.Y()), - int32_t(aTarget->mFilterPrimitiveSubregion.Width()), - int32_t(aTarget->mFilterPrimitiveSubregion.Height())); - - float fX = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eFirst); - float fY = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eSecond); - float seed = mNumberAttributes[OCTAVES].GetAnimValue(); - int32_t octaves = mIntegerAttributes[OCTAVES].GetAnimValue(); - uint16_t type = mEnumAttributes[TYPE].GetAnimValue(); - uint16_t stitch = mEnumAttributes[STITCHTILES].GetAnimValue(); - - InitSeed((int32_t)seed); - - // XXXroc this makes absolutely no sense to me. - float filterX = instance->GetFilterRegion().X(); - float filterY = instance->GetFilterRegion().Y(); - float filterWidth = instance->GetFilterRegion().Width(); - float filterHeight = instance->GetFilterRegion().Height(); - - bool doStitch = false; - if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) { - doStitch = true; - - float lowFreq, hiFreq; - - lowFreq = floor(filterWidth * fX) / filterWidth; - hiFreq = ceil(filterWidth * fX) / filterWidth; - if (fX / lowFreq < hiFreq / fX) - fX = lowFreq; - else - fX = hiFreq; - - lowFreq = floor(filterHeight * fY) / filterHeight; - hiFreq = ceil(filterHeight * fY) / filterHeight; - if (fY / lowFreq < hiFreq / fY) - fY = lowFreq; - else - fY = hiFreq; - } - for (int32_t y = rect.y; y < rect.YMost(); y++) { - for (int32_t x = rect.x; x < rect.XMost(); x++) { - int32_t targIndex = y * stride + x * 4; - double point[2]; - point[0] = filterX + (filterWidth * (x + instance->GetSurfaceRect().x)) / (filterSubregion.width - 1); - point[1] = filterY + (filterHeight * (y + instance->GetSurfaceRect().y)) / (filterSubregion.height - 1); - - float col[4]; - if (type == nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE) { - for (int i = 0; i < 4; i++) - col[i] = Turbulence(i, point, fX, fY, octaves, false, - doStitch, filterX, filterY, filterWidth, filterHeight) * 255; - } else { - for (int i = 0; i < 4; i++) - col[i] = (Turbulence(i, point, fX, fY, octaves, true, - doStitch, filterX, filterY, filterWidth, filterHeight) * 255 + 255) / 2; - } - for (int i = 0; i < 4; i++) { - col[i] = std::min(col[i], 255.f); - col[i] = std::max(col[i], 0.f); - } - - uint8_t r, g, b, a; - a = uint8_t(col[3]); - FAST_DIVIDE_BY_255(r, unsigned(col[0]) * a); - FAST_DIVIDE_BY_255(g, unsigned(col[1]) * a); - FAST_DIVIDE_BY_255(b, unsigned(col[2]) * a); - - targetData[targIndex + GFX_ARGB32_OFFSET_B] = b; - targetData[targIndex + GFX_ARGB32_OFFSET_G] = g; - targetData[targIndex + GFX_ARGB32_OFFSET_R] = r; - targetData[targIndex + GFX_ARGB32_OFFSET_A] = a; - } - } - - return NS_OK; -} - -bool -nsSVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::seed || - aAttribute == nsGkAtoms::baseFrequency || - aAttribute == nsGkAtoms::numOctaves || - aAttribute == nsGkAtoms::type || - aAttribute == nsGkAtoms::stitchTiles)); -} - -void -nsSVGFETurbulenceElement::InitSeed(int32_t aSeed) -{ - double s; - int i, j, k; - aSeed = SetupSeed(aSeed); - for (k = 0; k < 4; k++) { - for (i = 0; i < sBSize; i++) { - mLatticeSelector[i] = i; - for (j = 0; j < 2; j++) { - mGradient[k][i][j] = - (double) (((aSeed = - Random(aSeed)) % (sBSize + sBSize)) - sBSize) / sBSize; - } - s = double (sqrt - (mGradient[k][i][0] * mGradient[k][i][0] + - mGradient[k][i][1] * mGradient[k][i][1])); - mGradient[k][i][0] /= s; - mGradient[k][i][1] /= s; - } - } - while (--i) { - k = mLatticeSelector[i]; - mLatticeSelector[i] = mLatticeSelector[j = - (aSeed = - Random(aSeed)) % sBSize]; - mLatticeSelector[j] = k; - } - for (i = 0; i < sBSize + 2; i++) { - mLatticeSelector[sBSize + i] = mLatticeSelector[i]; - for (k = 0; k < 4; k++) - for (j = 0; j < 2; j++) - mGradient[k][sBSize + i][j] = mGradient[k][i][j]; - } -} - -#define S_CURVE(t) ( t * t * (3. - 2. * t) ) -#define LERP(t, a, b) ( a + t * (b - a) ) -double -nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2], - StitchInfo *aStitchInfo) -{ - int bx0, bx1, by0, by1, b00, b10, b01, b11; - double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v; - register long i, j; - t = aVec[0] + sPerlinN; - bx0 = (int) t; - bx1 = bx0 + 1; - rx0 = t - (int) t; - rx1 = rx0 - 1.0f; - t = aVec[1] + sPerlinN; - by0 = (int) t; - by1 = by0 + 1; - ry0 = t - (int) t; - ry1 = ry0 - 1.0f; - // If stitching, adjust lattice points accordingly. - if (aStitchInfo != NULL) { - if (bx0 >= aStitchInfo->mWrapX) - bx0 -= aStitchInfo->mWidth; - if (bx1 >= aStitchInfo->mWrapX) - bx1 -= aStitchInfo->mWidth; - if (by0 >= aStitchInfo->mWrapY) - by0 -= aStitchInfo->mHeight; - if (by1 >= aStitchInfo->mWrapY) - by1 -= aStitchInfo->mHeight; - } - bx0 &= sBM; - bx1 &= sBM; - by0 &= sBM; - by1 &= sBM; - i = mLatticeSelector[bx0]; - j = mLatticeSelector[bx1]; - b00 = mLatticeSelector[i + by0]; - b10 = mLatticeSelector[j + by0]; - b01 = mLatticeSelector[i + by1]; - b11 = mLatticeSelector[j + by1]; - sx = double (S_CURVE(rx0)); - sy = double (S_CURVE(ry0)); - q = mGradient[aColorChannel][b00]; - u = rx0 * q[0] + ry0 * q[1]; - q = mGradient[aColorChannel][b10]; - v = rx1 * q[0] + ry0 * q[1]; - a = LERP(sx, u, v); - q = mGradient[aColorChannel][b01]; - u = rx0 * q[0] + ry1 * q[1]; - q = mGradient[aColorChannel][b11]; - v = rx1 * q[0] + ry1 * q[1]; - b = LERP(sx, u, v); - return LERP(sy, a, b); -} -#undef S_CURVE -#undef LERP - -double -nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint, - double aBaseFreqX, double aBaseFreqY, - int aNumOctaves, bool aFractalSum, - bool aDoStitching, - double aTileX, double aTileY, - double aTileWidth, double aTileHeight) -{ - StitchInfo stitch; - StitchInfo *stitchInfo = NULL; // Not stitching when NULL. - // Adjust the base frequencies if necessary for stitching. - if (aDoStitching) { - // When stitching tiled turbulence, the frequencies must be adjusted - // so that the tile borders will be continuous. - if (aBaseFreqX != 0.0) { - double loFreq = double (floor(aTileWidth * aBaseFreqX)) / aTileWidth; - double hiFreq = double (ceil(aTileWidth * aBaseFreqX)) / aTileWidth; - if (aBaseFreqX / loFreq < hiFreq / aBaseFreqX) - aBaseFreqX = loFreq; - else - aBaseFreqX = hiFreq; - } - if (aBaseFreqY != 0.0) { - double loFreq = double (floor(aTileHeight * aBaseFreqY)) / aTileHeight; - double hiFreq = double (ceil(aTileHeight * aBaseFreqY)) / aTileHeight; - if (a