author | Ryan VanderMeulen <ryanvm@gmail.com> |
Thu, 07 Mar 2013 17:39:11 -0500 | |
changeset 124248 | 4ada9533c6d5fc52aa33cda967bcb0ec486ab375 |
parent 124247 | da4d6e7cbb2b03311010edb57c34bf831845f5b0 (current diff) |
parent 124160 | 0e7639e3bdfbe56b5e788f234cafb3c5074954cc (diff) |
child 124249 | 7952fadd1732442445aef29332d74e8ab0a5ecaa |
push id | 24315 |
push user | ryanvm@gmail.com |
push date | Fri, 08 Mar 2013 19:30:04 +0000 |
treeherder | mozilla-inbound@b4bfc1c0829c [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/accessible/public/Makefile.in +++ b/accessible/public/Makefile.in @@ -6,17 +6,16 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = accessibility -XPIDL_MODULE= accessibility GRE_MODULE = 1 XPIDLSRCS = \ nsIAccessibleTypes.idl \ nsIAccessibleRetrieval.idl \ nsIAccessible.idl \ nsIAccessibleApplication.idl \ nsIAccessibleRelation.idl \
--- a/accessible/src/base/FocusManager.cpp +++ b/accessible/src/base/FocusManager.cpp @@ -122,21 +122,18 @@ FocusManager::NotifyOfDOMFocus(nsISuppor mActiveItem = nullptr; nsCOMPtr<nsINode> targetNode(do_QueryInterface(aTarget)); if (targetNode) { DocAccessible* document = GetAccService()->GetDocAccessible(targetNode->OwnerDoc()); if (document) { // Set selection listener for focused element. - if (targetNode->IsElement()) { - RootAccessible* root = document->RootAccessible(); - nsCaretAccessible* caretAcc = root->GetCaretAccessible(); - caretAcc->SetControlSelectionListener(targetNode->AsElement()); - } + if (targetNode->IsElement()) + SelectionMgr()->SetControlSelectionListener(targetNode->AsElement()); document->HandleNotification<FocusManager, nsINode> (this, &FocusManager::ProcessDOMFocus, targetNode); } } } void
--- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -27,19 +27,19 @@ CPPSRCS = \ NotificationController.cpp \ nsAccessNode.cpp \ nsARIAMap.cpp \ nsCoreUtils.cpp \ nsAccUtils.cpp \ nsAccessibilityService.cpp \ nsAccessiblePivot.cpp \ nsEventShell.cpp \ - nsCaretAccessible.cpp \ nsTextEquivUtils.cpp \ RoleAsserts.cpp \ + SelectionManager.cpp \ StyleInfo.cpp \ TextAttrs.cpp \ TextUpdater.cpp \ TreeWalker.cpp \ $(NULL) ifneq ($(A11Y_LOG),0) CPPSRCS += \ @@ -56,16 +56,17 @@ EXPORTS = \ EXPORTS_NAMESPACES = mozilla/a11y EXPORTS_mozilla/a11y = \ DocManager.h \ FocusManager.h \ AccTypes.h \ Platform.h \ States.h \ + SelectionManager.h \ Role.h \ $(NULL) ifdef MOZ_DEBUG EXPORTS_mozilla/a11y += \ Logging.h \ $(NULL) endif
rename from accessible/src/base/nsCaretAccessible.cpp rename to accessible/src/base/SelectionManager.cpp --- a/accessible/src/base/nsCaretAccessible.cpp +++ b/accessible/src/base/SelectionManager.cpp @@ -1,223 +1,180 @@ /* -*- Mode: C++; tab-width: 4; 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 "nsCaretAccessible.h" +#include "mozilla/a11y/SelectionManager.h" #include "DocAccessible-inl.h" #include "nsAccessibilityService.h" #include "nsAccUtils.h" #include "nsCoreUtils.h" #include "nsIAccessibleEvent.h" #include "RootAccessible.h" #include "nsCaret.h" #include "nsIDOMDocument.h" #include "nsIDOMHTMLAnchorElement.h" #include "nsIDOMHTMLTextAreaElement.h" #include "nsIFrame.h" #include "nsIPresShell.h" #include "nsISelectionPrivate.h" #include "nsServiceManagerUtils.h" +#include "mozilla/Selection.h" -class nsIWidget; - +using namespace mozilla; using namespace mozilla::a11y; -NS_IMPL_ISUPPORTS1(nsCaretAccessible, nsISelectionListener) - -nsCaretAccessible::nsCaretAccessible(RootAccessible* aRootAccessible) : -mLastCaretOffset(-1), mRootAccessible(aRootAccessible) +void +SelectionManager::Shutdown() { -} - -nsCaretAccessible::~nsCaretAccessible() -{ + ClearControlSelectionListener(); + mLastTextAccessible = nullptr; + mLastUsedSelection = nullptr; } -void nsCaretAccessible::Shutdown() +void +SelectionManager::ClearControlSelectionListener() { - // The caret accessible isn't shut down until the RootAccessible owning it is shut down - // Each DocAccessible, including the RootAccessible, is responsible for clearing the - // doc selection listeners they registered in this nsCaretAccessible + if (!mCurrentControl) + return; - ClearControlSelectionListener(); // Clear the selection listener for the currently focused control - mLastTextAccessible = nullptr; - mLastUsedSelection = nullptr; - mRootAccessible = nullptr; -} - -nsresult nsCaretAccessible::ClearControlSelectionListener() -{ - nsCOMPtr<nsISelectionController> controller = - GetSelectionControllerForNode(mCurrentControl); + nsIFrame* frame = mCurrentControl->GetPrimaryFrame(); + if (!frame) + return; mCurrentControl = nullptr; - if (!controller) - return NS_OK; + const nsFrameSelection* frameSel = frame->GetConstFrameSelection(); + NS_ASSERTION(frameSel, "No frame selection for the element!"); + if (!frameSel) + return; // Remove 'this' registered as selection listener for the normal selection. - nsCOMPtr<nsISelection> normalSel; - controller->GetSelection(nsISelectionController::SELECTION_NORMAL, - getter_AddRefs(normalSel)); - nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(normalSel)); - NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE); - - nsresult rv = selPrivate->RemoveSelectionListener(this); - NS_ENSURE_SUCCESS(rv, rv); + Selection* normalSel = + frameSel->GetSelection(nsISelectionController::SELECTION_NORMAL); + normalSel->RemoveSelectionListener(this); // Remove 'this' registered as selection listener for the spellcheck // selection. - nsCOMPtr<nsISelection> spellcheckSel; - controller->GetSelection(nsISelectionController::SELECTION_SPELLCHECK, - getter_AddRefs(spellcheckSel)); - selPrivate = do_QueryInterface(spellcheckSel); - NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE); - - return selPrivate->RemoveSelectionListener(this); + Selection* spellSel = + frameSel->GetSelection(nsISelectionController::SELECTION_SPELLCHECK); + spellSel->RemoveSelectionListener(this); } -nsresult -nsCaretAccessible::SetControlSelectionListener(nsIContent *aCurrentNode) +void +SelectionManager::SetControlSelectionListener(dom::Element* aFocusedElm) { - NS_ENSURE_TRUE(mRootAccessible, NS_ERROR_FAILURE); - - ClearControlSelectionListener(); - - mCurrentControl = aCurrentNode; - mLastTextAccessible = nullptr; - // When focus moves such that the caret is part of a new frame selection // this removes the old selection listener and attaches a new one for // the current focus. + ClearControlSelectionListener(); - nsCOMPtr<nsISelectionController> controller = - GetSelectionControllerForNode(mCurrentControl); - NS_ASSERTION(controller || aCurrentNode->IsNodeOfType(nsINode::eDOCUMENT), - "No selection controller for non document node!"); - if (!controller) - return NS_OK; + mCurrentControl = aFocusedElm; + mLastTextAccessible = nullptr; + + nsIFrame* frame = aFocusedElm->GetPrimaryFrame(); + if (!frame) + return; + + const nsFrameSelection* frameSel = frame->GetConstFrameSelection(); + NS_ASSERTION(frameSel, "No frame selection for focused element!"); + if (!frameSel) + return; // Register 'this' as selection listener for the normal selection. - nsCOMPtr<nsISelection> normalSel; - controller->GetSelection(nsISelectionController::SELECTION_NORMAL, - getter_AddRefs(normalSel)); - nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(normalSel)); - NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE); - - nsresult rv = selPrivate->AddSelectionListener(this); - NS_ENSURE_SUCCESS(rv, rv); + Selection* normalSel = + frameSel->GetSelection(nsISelectionController::SELECTION_NORMAL); + normalSel->AddSelectionListener(this); - // Register 'this' as selection listener for the spellcheck selection. - nsCOMPtr<nsISelection> spellcheckSel; - controller->GetSelection(nsISelectionController::SELECTION_SPELLCHECK, - getter_AddRefs(spellcheckSel)); - selPrivate = do_QueryInterface(spellcheckSel); - NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE); - - return selPrivate->AddSelectionListener(this); + // Register 'this' as selection listener for the spell check selection. + Selection* spellSel = + frameSel->GetSelection(nsISelectionController::SELECTION_SPELLCHECK); + spellSel->AddSelectionListener(this); } -nsresult -nsCaretAccessible::AddDocSelectionListener(nsIPresShell *aShell) +void +SelectionManager::AddDocSelectionListener(nsIPresShell* aPresShell) { - NS_ENSURE_TRUE(mRootAccessible, NS_ERROR_FAILURE); - - nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(aShell); - NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE); + const nsFrameSelection* frameSel = aPresShell->ConstFrameSelection(); - nsCOMPtr<nsISelection> domSel; - selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel)); - nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(domSel); - NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE); - - nsresult rv = selPrivate->AddSelectionListener(this); - NS_ENSURE_SUCCESS(rv, rv); + // Register 'this' as selection listener for the normal selection. + Selection* normalSel = + frameSel->GetSelection(nsISelectionController::SELECTION_NORMAL); + normalSel->AddSelectionListener(this); - nsCOMPtr<nsISelection> spellcheckSel; - selCon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK, - getter_AddRefs(spellcheckSel)); - selPrivate = do_QueryInterface(spellcheckSel); - NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE); - - return selPrivate->AddSelectionListener(this); + // Register 'this' as selection listener for the spell check selection. + Selection* spellSel = + frameSel->GetSelection(nsISelectionController::SELECTION_SPELLCHECK); + spellSel->AddSelectionListener(this); } -nsresult -nsCaretAccessible::RemoveDocSelectionListener(nsIPresShell *aShell) +void +SelectionManager::RemoveDocSelectionListener(nsIPresShell* aPresShell) { - nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(aShell); - NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE); + const nsFrameSelection* frameSel = aPresShell->ConstFrameSelection(); - nsCOMPtr<nsISelection> domSel; - selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel)); - nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(domSel); - NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE); - - selPrivate->RemoveSelectionListener(this); + // Remove 'this' registered as selection listener for the normal selection. + Selection* normalSel = + frameSel->GetSelection(nsISelectionController::SELECTION_NORMAL); + normalSel->RemoveSelectionListener(this); - nsCOMPtr<nsISelection> spellcheckSel; - selCon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK, - getter_AddRefs(spellcheckSel)); - selPrivate = do_QueryInterface(spellcheckSel); - NS_ENSURE_TRUE(selPrivate, NS_ERROR_FAILURE); - - return selPrivate->RemoveSelectionListener(this); + // Remove 'this' registered as selection listener for the spellcheck + // selection. + Selection* spellSel = + frameSel->GetSelection(nsISelectionController::SELECTION_SPELLCHECK); + spellSel->RemoveSelectionListener(this); } NS_IMETHODIMP -nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument* aDOMDocument, - nsISelection* aSelection, - int16_t aReason) +SelectionManager::NotifySelectionChanged(nsIDOMDocument* aDOMDocument, + nsISelection* aSelection, + int16_t aReason) { NS_ENSURE_ARG(aDOMDocument); - NS_ENSURE_STATE(mRootAccessible); nsCOMPtr<nsIDocument> documentNode(do_QueryInterface(aDOMDocument)); DocAccessible* document = GetAccService()->GetDocAccessible(documentNode); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eSelection)) logging::SelChange(aSelection, document); #endif // Don't fire events until document is loaded. if (document && document->IsContentLoaded()) { - // The caret accessible has the same lifetime as the root accessible, and - // this outlives all its descendant document accessibles, so that we are - // guaranteed that the notification is processed before the caret accessible - // is destroyed. - document->HandleNotification<nsCaretAccessible, nsISelection> - (this, &nsCaretAccessible::ProcessSelectionChanged, aSelection); + // Selection manager has longer lifetime than any document accessible, + // so that we are guaranteed that the notification is processed before + // the selection manager is destroyed. + document->HandleNotification<SelectionManager, nsISelection> + (this, &SelectionManager::ProcessSelectionChanged, aSelection); } return NS_OK; } void -nsCaretAccessible::ProcessSelectionChanged(nsISelection* aSelection) +SelectionManager::ProcessSelectionChanged(nsISelection* aSelection) { nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(aSelection)); int16_t type = 0; privSel->GetType(&type); if (type == nsISelectionController::SELECTION_NORMAL) NormalSelectionChanged(aSelection); else if (type == nsISelectionController::SELECTION_SPELLCHECK) SpellcheckSelectionChanged(aSelection); } void -nsCaretAccessible::NormalSelectionChanged(nsISelection* aSelection) +SelectionManager::NormalSelectionChanged(nsISelection* aSelection) { mLastUsedSelection = do_GetWeakReference(aSelection); int32_t rangeCount = 0; aSelection->GetRangeCount(&rangeCount); if (rangeCount == 0) { mLastTextAccessible = nullptr; return; // No selection @@ -243,17 +200,17 @@ nsCaretAccessible::NormalSelectionChange mLastCaretOffset = caretOffset; mLastTextAccessible = textAcc; nsRefPtr<AccEvent> event = new AccCaretMoveEvent(mLastTextAccessible); mLastTextAccessible->Document()->FireDelayedEvent(event); } void -nsCaretAccessible::SpellcheckSelectionChanged(nsISelection* aSelection) +SelectionManager::SpellcheckSelectionChanged(nsISelection* aSelection) { // XXX: fire an event for accessible of focus node of the selection. If // spellchecking is enabled then we will fire the number of events for // the same accessible for newly appended range of the selection (for every // misspelled word). If spellchecking is disabled (for example, // @spellcheck="false" on html:body) then we won't fire any event. HyperTextAccessible* hyperText = @@ -261,22 +218,21 @@ nsCaretAccessible::SpellcheckSelectionCh if (hyperText) { hyperText->Document()-> FireDelayedEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED, hyperText); } } nsIntRect -nsCaretAccessible::GetCaretRect(nsIWidget **aOutWidget) +SelectionManager::GetCaretRect(nsIWidget** aWidget) { nsIntRect caretRect; - NS_ENSURE_TRUE(aOutWidget, caretRect); - *aOutWidget = nullptr; - NS_ENSURE_TRUE(mRootAccessible, caretRect); + NS_ENSURE_TRUE(aWidget, caretRect); + *aWidget = nullptr; if (!mLastTextAccessible) { return caretRect; // Return empty rect } nsINode *lastNodeWithCaret = mLastTextAccessible->GetNode(); NS_ENSURE_TRUE(lastNodeWithCaret, caretRect); @@ -299,53 +255,29 @@ nsCaretAccessible::GetCaretRect(nsIWidge nsIFrame* frame = caret->GetGeometry(caretSelection, &rect); if (!frame || rect.IsEmpty()) { return nsIntRect(); // Return empty rect } nsPoint offset; // Offset from widget origin to the frame origin, which includes chrome // on the widget. - *aOutWidget = frame->GetNearestWidget(offset); - NS_ENSURE_TRUE(*aOutWidget, nsIntRect()); + *aWidget = frame->GetNearestWidget(offset); + NS_ENSURE_TRUE(*aWidget, nsIntRect()); rect.MoveBy(offset); caretRect = rect.ToOutsidePixels(frame->PresContext()->AppUnitsPerDevPixel()); // ((content screen origin) - (content offset in the widget)) = widget origin on the screen - caretRect.MoveBy((*aOutWidget)->WidgetToScreenOffset() - (*aOutWidget)->GetClientOffset()); + caretRect.MoveBy((*aWidget)->WidgetToScreenOffset() - (*aWidget)->GetClientOffset()); // Correct for character size, so that caret always matches the size of the character // This is important for font size transitions, and is necessary because the Gecko caret uses the // previous character's size as the user moves forward in the text by character. int32_t charX, charY, charWidth, charHeight; if (NS_SUCCEEDED(mLastTextAccessible->GetCharacterExtents(mLastCaretOffset, &charX, &charY, &charWidth, &charHeight, nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE))) { caretRect.height -= charY - caretRect.y; caretRect.y = charY; } return caretRect; } - -already_AddRefed<nsISelectionController> -nsCaretAccessible::GetSelectionControllerForNode(nsIContent *aContent) -{ - if (!aContent) - return nullptr; - - nsIPresShell *presShell = aContent->OwnerDoc()->GetShell(); - if (!presShell) - return nullptr; - - nsIFrame *frame = aContent->GetPrimaryFrame(); - if (!frame) - return nullptr; - - nsPresContext *presContext = presShell->GetPresContext(); - if (!presContext) - return nullptr; - - nsISelectionController *controller = nullptr; - frame->GetSelectionController(presContext, &controller); - return controller; -} -
rename from accessible/src/base/nsCaretAccessible.h rename to accessible/src/base/SelectionManager.h --- a/accessible/src/base/nsCaretAccessible.h +++ b/accessible/src/base/SelectionManager.h @@ -1,90 +1,91 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef __nsCaretAccessible_h__ -#define __nsCaretAccessible_h__ +#ifndef mozilla_a11y_SelectionManager_h__ +#define mozilla_a11y_SelectionManager_h__ -#include "HyperTextAccessible.h" - +#include "nsAutoPtr.h" #include "nsISelectionListener.h" -/* - * This special accessibility class is for the caret, which is really the currently focused selection. - * There is only 1 visible caret per top level window (RootAccessible), - * However, there may be several visible selections. - * - * The important selections are the one owned by each document, and the one in the currently focused control. +class nsIContent; +class nsIntRect; +class nsIPresShell; +class nsIWeakReference; +class nsIWidget; + +namespace mozilla { + +namespace dom { +class Element; +} + +namespace a11y { + +class HyperTextAccessible; + +/** + * This special accessibility class is for the caret and selection management. + * There is only 1 visible caret per top level window. However, there may be + * several visible selections. * - * The caret accessible is no longer an accessible object in its own right. - * On Windows it is used to move an invisible system caret that shadows the Mozilla caret. Windows will - * also automatically map this to the MSAA caret accessible object (via OBJID_CARET). - * (as opposed to the root accessible tree for a window which is retrieved with OBJID_CLIENT) - * For ATK and Iaccessible2, the caret accessible is used to fire - * caret move and selection change events. + * The important selections are the one owned by each document, and the one in + * the currently focused control. * - * The caret accessible is owned by the RootAccessible for the top level window that it's in. - * The RootAccessible needs to tell the nsCaretAccessible about focus changes via - * setControlSelectionListener(). - * Each DocAccessible needs to tell the nsCaretAccessible owned by the root to - * listen for selection events via addDocSelectionListener() and then needs to remove the - * selection listener when the doc goes away via removeDocSelectionListener(). + * On Windows this class is used to move an invisible system caret that + * shadows the Mozilla caret. Windows will also automatically map this to + * the MSAA caret accessible object (via OBJID_CARET) (as opposed to the root + * accessible tree for a window which is retrieved with OBJID_CLIENT). + * + * For ATK and IAccessible2, this class is used to fire caret move and + * selection change events. */ -class nsCaretAccessible : public nsISelectionListener +class SelectionManager : public nsISelectionListener { public: - NS_DECL_ISUPPORTS + // nsISupports + // implemented by derived nsAccessibilityService - nsCaretAccessible(mozilla::a11y::RootAccessible* aRootAccessible); - virtual ~nsCaretAccessible(); + // nsISelectionListener + NS_DECL_NSISELECTIONLISTENER + + // SelectionManager void Shutdown(); - /* ----- nsISelectionListener ---- */ - NS_DECL_NSISELECTIONLISTENER - /** * Listen to selection events on the focused control. - * Only one control's selection events are listened to at a time, per top-level window. - * This will remove the previous control's selection listener. - * It will fail if aFocusedNode is a document node -- document selection must be listened - * to via AddDocSelectionListener(). - * @param aFocusedNode The node for the focused control + * + * Note: only one control's selection events are listened to at a time. This + * will remove the previous control's selection listener. */ - nsresult SetControlSelectionListener(nsIContent *aCurrentNode); + void SetControlSelectionListener(dom::Element* aFocusedElm); /** - * Stop listening to selection events for any control. - * This does not have to be called explicitly in Shutdown() procedures, - * because the nsCaretAccessible implementation guarantees that. + * Stop listening to selection events on the control. */ - nsresult ClearControlSelectionListener(); + void ClearControlSelectionListener(); /** - * Start listening to selection events for a given document - * More than one document's selection events can be listened to - * at the same time, by a given nsCaretAccessible - * @param aShell PresShell for document to listen to selection events from. + * Listen to selection events on the document. */ - nsresult AddDocSelectionListener(nsIPresShell *aShell); + void AddDocSelectionListener(nsIPresShell* aPresShell); /** * Stop listening to selection events for a given document - * If the document goes away, this method needs to be called for - * that document by the owner of the caret. We use presShell because - * instead of document because it is more direct than getting it from - * the document, and in any case it is unavailable from the doc after a pagehide. - * @param aShell PresShell for document to no longer listen to selection events from. */ - nsresult RemoveDocSelectionListener(nsIPresShell *aShell); + void RemoveDocSelectionListener(nsIPresShell* aShell); - nsIntRect GetCaretRect(nsIWidget **aOutWidget); + /** + * Return the caret rect and the widget containing the caret. + */ + nsIntRect GetCaretRect(nsIWidget** aWidget); protected: /** * Process DOM selection change. Fire selection and caret move events. */ void ProcessSelectionChanged(nsISelection* aSelection); /** @@ -93,34 +94,24 @@ protected: void NormalSelectionChanged(nsISelection* aSelection); /** * Process spellcheck selection change and fire text attribute changed event * for invalid text attribute. */ void SpellcheckSelectionChanged(nsISelection* aSelection); - /** - * Return selection controller for the given node. - */ - already_AddRefed<nsISelectionController> - GetSelectionControllerForNode(nsIContent *aNode); - private: - // The currently focused control -- never a document. - // We listen to selection for one control at a time (the focused one) - // Document selection is handled separately via additional listeners on all active documents - // The current control is set via SetControlSelectionListener() - // Currently focused control. nsCOMPtr<nsIContent> mCurrentControl; // Info for the the last selection event. // If it was on a control, then its control's selection. Otherwise, it's for // a document where the selection changed. nsCOMPtr<nsIWeakReference> mLastUsedSelection; // Weak ref to nsISelection - nsRefPtr<mozilla::a11y::HyperTextAccessible> mLastTextAccessible; + nsRefPtr<HyperTextAccessible> mLastTextAccessible; int32_t mLastCaretOffset; - - mozilla::a11y::RootAccessible* mRootAccessible; }; +} // namespace a11y +} // namespace mozilla + #endif
--- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -136,21 +136,22 @@ nsAccessibilityService::~nsAccessibility { NS_ASSERTION(gIsShutdown, "Accessibility wasn't shutdown!"); gAccessibilityService = nullptr; } //////////////////////////////////////////////////////////////////////////////// // nsISupports -NS_IMPL_ISUPPORTS_INHERITED3(nsAccessibilityService, +NS_IMPL_ISUPPORTS_INHERITED4(nsAccessibilityService, DocManager, nsIAccessibilityService, nsIAccessibleRetrieval, - nsIObserver) + nsIObserver, + nsISelectionListener) // from SelectionManager //////////////////////////////////////////////////////////////////////////////// // nsIObserver NS_IMETHODIMP nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { @@ -1019,16 +1020,18 @@ nsAccessibilityService::Shutdown() static const PRUnichar kShutdownIndicator[] = { '0', 0 }; observerService->NotifyObservers(nullptr, "a11y-init-or-shutdown", kShutdownIndicator); } // Stop accessible document loader. DocManager::Shutdown(); + SelectionManager::Shutdown(); + // Application is going to be closed, shutdown accessibility and mark // accessibility service as shutdown to prevent calls of its methods. // Don't null accessibility service static member at this point to be safe // if someone will try to operate with it. NS_ASSERTION(!gIsShutdown, "Accessibility was shutdown already"); gIsShutdown = true; @@ -1603,16 +1606,22 @@ namespace mozilla { namespace a11y { FocusManager* FocusMgr() { return nsAccessibilityService::gAccessibilityService; } +SelectionManager* +SelectionMgr() +{ + return nsAccessibilityService::gAccessibilityService; +} + ApplicationAccessible* ApplicationAcc() { return nsAccessibilityService::gApplicationAccessible; } EPlatformDisabledState PlatformDisabledState()
--- a/accessible/src/base/nsAccessibilityService.h +++ b/accessible/src/base/nsAccessibilityService.h @@ -5,16 +5,17 @@ #ifndef __nsAccessibilityService_h__ #define __nsAccessibilityService_h__ #include "nsIAccessibilityService.h" #include "mozilla/a11y/DocManager.h" #include "mozilla/a11y/FocusManager.h" +#include "mozilla/a11y/SelectionManager.h" #include "nsIObserver.h" class nsImageFrame; class nsObjectFrame; class nsITreeView; namespace mozilla { @@ -23,25 +24,31 @@ namespace a11y { class ApplicationAccessible; /** * Return focus manager. */ FocusManager* FocusMgr(); /** + * Return selection manager. + */ +SelectionManager* SelectionMgr(); + +/** * Returns the application accessible. */ ApplicationAccessible* ApplicationAcc(); } // namespace a11y } // namespace mozilla class nsAccessibilityService : public mozilla::a11y::DocManager, public mozilla::a11y::FocusManager, + public mozilla::a11y::SelectionManager, public nsIAccessibilityService, public nsIObserver { public: typedef mozilla::a11y::Accessible Accessible; typedef mozilla::a11y::DocAccessible DocAccessible; virtual ~nsAccessibilityService(); @@ -206,16 +213,17 @@ private: /** * Indicates whether accessibility service was shutdown. */ static bool gIsShutdown; friend nsAccessibilityService* GetAccService(); friend mozilla::a11y::FocusManager* mozilla::a11y::FocusMgr(); + friend mozilla::a11y::SelectionManager* mozilla::a11y::SelectionMgr(); friend mozilla::a11y::ApplicationAccessible* mozilla::a11y::ApplicationAcc(); friend nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult); }; /** * Return the accessibility service instance. (Handy global function) */
--- a/accessible/src/generic/DocAccessible.cpp +++ b/accessible/src/generic/DocAccessible.cpp @@ -700,21 +700,17 @@ DocAccessible::AddEventListeners() int32_t itemType; docShellTreeItem->GetItemType(&itemType); if (itemType == nsIDocShellTreeItem::typeContent) { nsCOMPtr<nsICommandManager> commandManager = do_GetInterface(docShellTreeItem); if (commandManager) commandManager->AddCommandObserver(this, "obs_documentCreated"); } - a11y::RootAccessible* rootAccessible = RootAccessible(); - NS_ENSURE_TRUE(rootAccessible, NS_ERROR_FAILURE); - nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible(); - if (caretAccessible) - caretAccessible->AddDocSelectionListener(mPresShell); + SelectionMgr()->AddDocSelectionListener(mPresShell); // Add document observer. mDocumentNode->AddObserver(this); return NS_OK; } // DocAccessible protected member nsresult @@ -746,23 +742,17 @@ DocAccessible::RemoveEventListeners() } if (mScrollWatchTimer) { mScrollWatchTimer->Cancel(); mScrollWatchTimer = nullptr; NS_RELEASE_THIS(); // Kung fu death grip } - a11y::RootAccessible* rootAccessible = RootAccessible(); - if (rootAccessible) { - nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible(); - if (caretAccessible) - caretAccessible->RemoveDocSelectionListener(mPresShell); - } - + SelectionMgr()->RemoveDocSelectionListener(mPresShell); return NS_OK; } void DocAccessible::ScrollTimerCallback(nsITimer* aTimer, void* aClosure) { DocAccessible* docAcc = reinterpret_cast<DocAccessible*>(aClosure);
--- a/accessible/src/generic/RootAccessible.cpp +++ b/accessible/src/generic/RootAccessible.cpp @@ -192,20 +192,16 @@ RootAccessible::AddEventListeners() * const* e_end = ArrayEnd(kEventTypes); e < e_end; ++e) { nsresult rv = nstarget->AddEventListener(NS_ConvertASCIItoUTF16(*e), this, true, true, 2); NS_ENSURE_SUCCESS(rv, rv); } } - if (!mCaretAccessible) { - mCaretAccessible = new nsCaretAccessible(this); - } - return DocAccessible::AddEventListeners(); } nsresult RootAccessible::RemoveEventListeners() { nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocumentNode)); if (target) { @@ -215,34 +211,22 @@ RootAccessible::RemoveEventListeners() nsresult rv = target->RemoveEventListener(NS_ConvertASCIItoUTF16(*e), this, true); NS_ENSURE_SUCCESS(rv, rv); } } // Do this before removing clearing caret accessible, so that it can use // shutdown the caret accessible's selection listener DocAccessible::RemoveEventListeners(); - - if (mCaretAccessible) { - mCaretAccessible->Shutdown(); - mCaretAccessible = nullptr; - } - return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // public -nsCaretAccessible* -RootAccessible::GetCaretAccessible() -{ - return mCaretAccessible; -} - void RootAccessible::DocumentActivated(DocAccessible* aDocument) { } //////////////////////////////////////////////////////////////////////////////// // nsIDOMEventListener
--- a/accessible/src/generic/RootAccessible.h +++ b/accessible/src/generic/RootAccessible.h @@ -1,21 +1,20 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_a11y_RootAccessible_h__ #define mozilla_a11y_RootAccessible_h__ -#include "nsCaretAccessible.h" +#include "HyperTextAccessible.h" #include "DocAccessibleWrap.h" #include "nsHashtable.h" -#include "nsCaretAccessible.h" #include "nsIDocument.h" #include "nsIDOMEventListener.h" namespace mozilla { namespace a11y { class RootAccessible : public DocAccessibleWrap, public nsIDOMEventListener @@ -35,17 +34,16 @@ public: // Accessible virtual mozilla::a11y::ENameValueFlag Name(nsString& aName); virtual Relation RelationByType(uint32_t aType); virtual mozilla::a11y::role NativeRole(); virtual uint64_t NativeState(); // RootAccessible - nsCaretAccessible* GetCaretAccessible(); /** * Notify that the sub document presshell was activated. */ virtual void DocumentActivated(DocAccessible* aDocument); protected: @@ -73,18 +71,16 @@ protected: #ifdef MOZ_XUL void HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent, XULTreeAccessible* aAccessible); void HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent, XULTreeAccessible* aAccessible); uint32_t GetChromeFlags(); #endif - - nsRefPtr<nsCaretAccessible> mCaretAccessible; }; inline RootAccessible* Accessible::AsRoot() { return IsRoot() ? static_cast<mozilla::a11y::RootAccessible*>(this) : nullptr; }
--- a/accessible/src/windows/msaa/AccessibleWrap.cpp +++ b/accessible/src/windows/msaa/AccessibleWrap.cpp @@ -1775,23 +1775,18 @@ AccessibleWrap::UpdateSystemCaret() // off-screen model can follow the caret ::DestroyCaret(); a11y::RootAccessible* rootAccessible = RootAccessible(); if (!rootAccessible) { return; } - nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible(); - if (!caretAccessible) { - return; - } - - nsIWidget *widget; - nsIntRect caretRect = caretAccessible->GetCaretRect(&widget); + nsIWidget* widget = nullptr; + nsIntRect caretRect = SelectionMgr()->GetCaretRect(&widget); HWND caretWnd; if (caretRect.IsEmpty() || !(caretWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW))) { return; } // Create invisible bitmap for caret, otherwise its appearance interferes // with Gecko caret HBITMAP caretBitMap = CreateBitmap(1, caretRect.height, 1, 1, NULL);
--- a/accessible/tests/mochitest/focus/test_takeFocus.html +++ b/accessible/tests/mochitest/focus/test_takeFocus.html @@ -37,38 +37,41 @@ { return "takeFocus for " + prettyName(aID); } } //////////////////////////////////////////////////////////////////////////// // Test - gA11yEventDumpToConsole = true; // debug stuff + //gA11yEventDumpToConsole = true; // debug stuff var gQueue = null; function doTest() { - enableLogging("tree"); gQueue = new eventQueue(); gQueue.push(new takeFocusInvoker("aria-link")); gQueue.push(new takeFocusInvoker("aria-link2")); gQueue.push(new takeFocusInvoker("link")); gQueue.push(new takeFocusInvoker("item2")); gQueue.push(new takeFocusInvoker("plugin")); gQueue.push(new takeFocusInvoker(document)); gQueue.push(new takeFocusInvoker("lb_item2")); - gQueue.onFinish = function() { disableLogging(); } gQueue.invoke(); // Will call SimpleTest.finish(); } + function waitForPlugin() + { + window.setTimeout((isAccessible("plugin") ? doTest : waitForPlugin), 0); + } + SimpleTest.waitForExplicitFinish(); - addA11yLoadEvent(doTest); + addA11yLoadEvent(waitForPlugin); </script> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=429547" title="Support aria-activedescendant usage in nsIAccesible::TakeFocus()"> @@ -92,17 +95,17 @@ <p id="display"></p> <div id="content" style="display: none"></div> <pre id="test"> </pre> <span id="aria-link" role="link" tabindex="0">link</span> <span id="aria-link2" role="link" tabindex="0">link</span> - <a id="link" href="">link</span> + <a id="link" href="">link</a> <div role="listbox" aria-activedescendant="item1" id="container" tabindex="1"> <div role="option" id="item1">item1</div> <div role="option" id="item2">item2</div> <div role="option" id="item3">item3</div> </div> <embed id="plugin" type="application/x-test" width="200" height="200" wmode="window"></embed>
--- a/accessible/tests/mochitest/focus/test_takeFocus.xul +++ b/accessible/tests/mochitest/focus/test_takeFocus.xul @@ -54,18 +54,16 @@ // Tests //gA11yEventDumpID = "eventdump"; // debug stuff //gA11yEventDumpToConsole = true; // debug stuff var gQueue = null; function doTests() { - disableLogging(); // from test_takeFocus.html - // Test focus events. gQueue = new eventQueue(); gQueue.push(new takeFocusInvoker("tree", getLastChild)); gQueue.push(new takeFocusInvoker("listitem2")); gQueue.invoke(); // Will call SimpleTest.finish(); }
--- a/accessible/tests/mochitest/states/test_tree.xul +++ b/accessible/tests/mochitest/states/test_tree.xul @@ -30,21 +30,23 @@ /** * Event queue invoker object to test accessible states for XUL tree * accessible. */ function statesChecker(aTreeID, aView) { this.DOMNode = getNode(aTreeID); - this.invoke = function invoke() + + this.invoke = function statesChecker_invoke() { this.DOMNode.treeBoxObject.view = aView; } - this.check = function check() + + this.check = function statesChecker_check() { var tree = getAccessible(this.DOMNode); // tree states testStates(tree, STATE_READONLY); if (this.DOMNode.getAttribute("seltype") != "single") testStates(tree, STATE_MULTISELECTABLE); @@ -67,19 +69,20 @@ var cell = cells.queryElementAt(idx, nsIAccessible); testStates(cell, STATE_SELECTABLE); } var checkboxCell = cells.queryElementAt(3, nsIAccessible); testStates(checkboxCell, STATE_CHECKABLE | STATE_CHECKED); } } - this.getID = function getID() + + this.getID = function statesChecker_getID() { - "tree processor for " + prettyName(aTreeID); + return "tree processor for " + prettyName(aTreeID); } } gA11yEventDumpToConsole = true; // debug stuff var gQueue = null; function doTest()
--- a/addon-sdk/Makefile.in +++ b/addon-sdk/Makefile.in @@ -4,16 +4,18 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(topsrcdir)/config/config.mk +export PYMAKE = $(.PYMAKE) + libs:: $(PYTHON) $(srcdir)/copy_source.py $(topsrcdir) $(srcdir)/source/lib $(FINAL_TARGET)/modules/commonjs >copy_source.mk $(MAKE) -f copy_source.mk libs include $(topsrcdir)/config/rules.mk TEST_FILES = \ source/app-extension \
--- a/addon-sdk/copy_source.py +++ b/addon-sdk/copy_source.py @@ -1,21 +1,38 @@ # 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/. import os +import posixpath import sys + +def normpath(path): + """Ensure UNIX style paths are used with GNU make on Windows. + + This can be removed once we no longer support GNU make on Windows (bug + 828317). + """ + if os.environ.get('PYMAKE') or os.name not in ('nt', 'ce'): + return path + + if len(path) > 2 and path[1] == ':': + path = '/' + path[0] + path[2:] + + return posixpath.normpath(path) + + if len(sys.argv) != 4: print >> sys.stderr, "Usage: copy_source.py " \ "<topsrcdir> <source directory> <target directory>" sys.exit(1) -topsrcdir = sys.argv[1] +topsrcdir = normpath(sys.argv[1]) source_dir = sys.argv[2] target_dir = sys.argv[3] print """ DEPTH = .. topsrcdir = %(topsrcdir)s srcdir = %(topsrcdir)s/addon-sdk VPATH = %(topsrcdir)s/addon-sdk
--- a/b2g/chrome/content/forms.js +++ b/b2g/chrome/content/forms.js @@ -259,19 +259,24 @@ let FormAssistant = { this.showKeyboard(this.getTopLevelEditable(target)); break; } if (this.isFocusableElement(target)) this.showKeyboard(target); break; + case "pagehide": + // We are only interested to the pagehide event from the root document. + if (target && target != content.document) { + break; + } + // fall through case "blur": case "submit": - case "pagehide": if (this.focusedElement) this.hideKeyboard(); break; case 'mousedown': // We only listen for this event on the currently focused element. // When the mouse goes down, note the cursor/selection position range = getSelectionRange(this.focusedElement);
--- a/b2g/components/Makefile.in +++ b/b2g/components/Makefile.in @@ -5,17 +5,16 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = B2GComponents -XPIDL_MODULE = B2GComponents XPIDLSRCS = \ b2g.idl \ $(NULL) EXTRA_PP_COMPONENTS = \ ActivitiesGlue.js \ AlertsService.js \
--- a/b2g/config/otoro/releng-otoro.tt +++ b/b2g/config/otoro/releng-otoro.tt @@ -1,12 +1,12 @@ [ { -"size": 896038748, -"digest": "a153b55e13938c608d0d449073142322470aaf6c77375165df83dc845d9c357d0cf4754db3b058d4707442cd6252fe3076e81a22c32cb34bd3df6432ad5b99f1", +"size": 896095824, +"digest": "c19f6ab2af72a3156c60daf061c6845ab1ae2071cf04fadcfaa9dddb15f9f58d4a67022f8ec8a978ddf7f6f08e1bb86fdc35d5b5a935bb90dec983280d2878e2", "algorithm": "sha512", "filename": "gonk.tar.xz" }, { "size": 4139008, "digest": "6f65553e882316582b944e46c659915a1b907c4a326104cb31d81356330dddacba757e3eafbd282063da0e670c3c5d6b9a0905ab88da84b47848d810c37571cb", "algorithm": "sha512", "filename": "boot.img"
--- a/b2g/config/otoro/sources.xml +++ b/b2g/config/otoro/sources.xml @@ -11,86 +11,86 @@ <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="43434d6cdbf702e6197e0791f19406860284edf6"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <!-- Information: fake-dalvik is tagged with B2G_1_0_0_20130125190500 --><project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c6fc2e70b2586fe45db4b676567be2aa94cf420e"/> + <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8e68d41728675fc72502dc572dec523c2c8abb8a"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="f634b3d50effdd42828cc757c01fdbf74e562a36"/> <!-- Information: librecovery is tagged with B2G_1_0_0_20130125190500 --><project name="librecovery" path="librecovery" remote="b2g" revision="601fc18b28c9d7cf6954b281ddd3b705c74a9215"/> <project name="moztt" path="external/moztt" remote="b2g" revision="62f94a26d34c1f1e1846efd58d34363c051e8c66"/> <!-- Stock Android things --> - <!-- Information: platform/abi/cpp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/> + <!-- Information: platform/abi/cpp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/> <!-- Information: platform/bionic is tagged with M8960AAAAANLYA100715A --><project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/> <!-- Information: platform/bootable/recovery is tagged with M8960AAAAANLYA100715A --><project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/> <!-- Information: platform/development is tagged with M8960AAAAANLYA100715A --><project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/> <!-- Information: device/common is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/> <!-- Information: device/sample is tagged with M8960AAAAANLYA100715A --><project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/> <project name="platform_external_apriori" path="external/apriori" remote="b2ggithub" revision="2c3a7113299eb789a076be23449d868b3bfa07fd"/> <!-- Information: platform/external/bluetooth/bluez is tagged with M76XXUSNEKNLYA2040 --><project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="1023c91c66e9c3bd1132480051993bf7827770f6"/> - <!-- Information: platform/external/bluetooth/glib is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="c6b49241cc1a8950723a5f74f8f4b4f4c3fa970e"/> + <!-- Information: platform/external/bluetooth/glib is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="c6b49241cc1a8950723a5f74f8f4b4f4c3fa970e"/> <!-- Information: platform/external/bluetooth/hcidump is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/bluetooth/hcidump" path="external/bluetooth/hcidump" revision="02b1eb24fbb3d0135a81edb4a2175b1397308d7d"/> - <!-- Information: platform/external/bsdiff is tagged with A8064AAAAANLYA102313 --><project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/> - <!-- Information: platform/external/bzip2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/> + <!-- Information: platform/external/bsdiff is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/> + <!-- Information: platform/external/bzip2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/> <!-- Information: platform/external/dbus is tagged with M8960AAAAANLYA100715A --><project name="platform/external/dbus" path="external/dbus" revision="c7517b6195dc6926728352113e6cc335da3f9c9e"/> <!-- Information: platform/external/dhcpcd is tagged with M8960AAAAANLYA100715A --><project name="platform/external/dhcpcd" path="external/dhcpcd" revision="1e00fb67022d0921af0fead263f81762781b9ffa"/> - <!-- Information: platform/external/dnsmasq is tagged with A8064AAAAANLYA102313 --><project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/> + <!-- Information: platform/external/dnsmasq is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/> <project name="platform_external_elfcopy" path="external/elfcopy" remote="b2ggithub" revision="62c1bed1c4505369cac2e72fbe30452a598fb690"/> <project name="platform_external_elfutils" path="external/elfutils" remote="b2ggithub" revision="72940dec691fa3255e13df01f8c53b620e446066"/> - <!-- Information: platform/external/e2fsprogs is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/e2fsprogs" path="external/e2fsprogs" revision="d5f550bb2f556c5d287f7c8d2b77223654bcec37"/> - <!-- Information: platform/external/expat is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/> - <!-- Information: platform/external/fdlibm is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/> - <!-- Information: platform/external/flac is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/> - <!-- Information: platform/external/freetype is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/> - <!-- Information: platform/external/giflib is tagged with A8064AAAAANLYA102313 --><project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/> + <!-- Information: platform/external/e2fsprogs is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/e2fsprogs" path="external/e2fsprogs" revision="d5f550bb2f556c5d287f7c8d2b77223654bcec37"/> + <!-- Information: platform/external/expat is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/> + <!-- Information: platform/external/fdlibm is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/> + <!-- Information: platform/external/flac is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/> + <!-- Information: platform/external/freetype is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/> + <!-- Information: platform/external/giflib is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/> <project name="platform/external/gtest" path="external/gtest" remote="linaro" revision="8c212ebe53bb2baab3575f03069016f1fb11e449"/> - <!-- Information: platform/external/harfbuzz is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/harfbuzz" path="external/harfbuzz" revision="116610d63a859521dacf00fb6818ee9ab2e666f6"/> - <!-- Information: platform/external/icu4c is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/> - <!-- Information: platform/external/iptables is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/> + <!-- Information: platform/external/harfbuzz is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/harfbuzz" path="external/harfbuzz" revision="116610d63a859521dacf00fb6818ee9ab2e666f6"/> + <!-- Information: platform/external/icu4c is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/> + <!-- Information: platform/external/iptables is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/> <!-- Information: platform/external/jpeg is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/jpeg" path="external/jpeg" revision="a62e464d672a4623233180e4023034bf825f066e"/> - <!-- Information: platform/external/libgsm is tagged with A8064AAAAANLYA102313 --><project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/> - <!-- Information: platform/external/liblzf is tagged with AU_LINUX_ANDROID_JB_MR1.04.02.02.49.134 --><project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/> - <!-- Information: platform/external/libnfc-nxp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="3a912b065a31a72c63ad56ac224cfeaa933423b6"/> - <!-- Information: platform/external/libnl-headers is tagged with AU_LINUX_ANDROID_JB_MR1.04.02.02.49.134 --><project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/> + <!-- Information: platform/external/libgsm is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/> + <!-- Information: platform/external/liblzf is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/> + <!-- Information: platform/external/libnfc-nxp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="3a912b065a31a72c63ad56ac224cfeaa933423b6"/> + <!-- Information: platform/external/libnl-headers is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/> <!-- Information: platform/external/libpng is tagged with M8960AAAAANLYA100715A --><project name="platform/external/libpng" path="external/libpng" revision="9c3730f0efa69f580f03463c237cd928f3196404"/> <!-- Information: platform/external/libvpx is tagged with M8960AAAAANLYA1519349 --><project name="platform/external/libvpx" path="external/libvpx" revision="3a40da0d96da5c520e7707aa14f48a80956e20d7"/> <!-- Information: platform/external/llvm is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/llvm" path="external/llvm" revision="bff5923831940309f7d8ddbff5826ca6ed2dc050"/> <!-- Information: platform/external/mksh is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/mksh" path="external/mksh" revision="ec646e8f5e7dac9a77d1de549c6ed92c04d0cd4b"/> <!-- Information: platform_external_opensans is tagged with B2G_1_0_0_20130125190500 --><project name="platform_external_opensans" path="external/opensans" remote="b2g" revision="b5b4c226ca1d71e936153cf679dda6d3d60e2354"/> <!-- Information: platform/external/openssl is tagged with AU_LINUX_ANDROID_ICS.04.00.04.00.110 --><project name="platform/external/openssl" path="external/openssl" revision="27d333cce9a31c806b4bfa042925f045c727aecd"/> - <!-- Information: platform/external/protobuf is tagged with A8064AAAAANLYA102313 --><project name="platform/external/protobuf" path="external/protobuf" revision="e217977611c52bccde7f7c78e1d3c790c6357431"/> - <!-- Information: platform/external/safe-iop is tagged with A8064AAAAANLYA102313 --><project name="platform/external/safe-iop" path="external/safe-iop" revision="07073634e2e3aa4f518e36ed5dec3aabc549d5fb"/> + <!-- Information: platform/external/protobuf is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/protobuf" path="external/protobuf" revision="e217977611c52bccde7f7c78e1d3c790c6357431"/> + <!-- Information: platform/external/safe-iop is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/safe-iop" path="external/safe-iop" revision="07073634e2e3aa4f518e36ed5dec3aabc549d5fb"/> <!-- Information: screencap-gonk is tagged with B2G_1_0_0_20130125190500 --><project name="screencap-gonk" path="external/screencap-gonk" remote="b2g" revision="e6403c71e9eca8cb943739d5a0a192deac60fc51"/> <!-- Information: platform/external/skia is tagged with M8960AAAAANLYA100715A --><project name="platform/external/skia" path="external/skia" revision="7d90c85f2c0e3b747f7c7eff8bc9253b0063b439"/> <!-- Information: platform/external/sonivox is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/sonivox" path="external/sonivox" revision="7c967779dfc61ac1f346e972de91d4bfce7dccbb"/> - <!-- Information: platform/external/speex is tagged with A8064AAAAANLYA102313 --><project name="platform/external/speex" path="external/speex" revision="ebe6230a7f7c69f5a4389f2b09b7b19ef9e94f32"/> + <!-- Information: platform/external/speex is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/speex" path="external/speex" revision="ebe6230a7f7c69f5a4389f2b09b7b19ef9e94f32"/> <project name="platform/external/sqlite" path="external/sqlite" revision="fb30e613139b8836fdc8e81e166cf3a76e5fa17f"/> - <!-- Information: platform/external/stlport is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/> - <!-- Information: platform/external/strace is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/> - <!-- Information: platform/external/tagsoup is tagged with AU_LINUX_ANDROID_JB_MR1.04.02.02.49.134 --><project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/> + <!-- Information: platform/external/stlport is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/> + <!-- Information: platform/external/strace is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/> + <!-- Information: platform/external/tagsoup is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/> <!-- Information: platform/external/tinyalsa is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/tinyalsa" path="external/tinyalsa" revision="06cc244ee512c1352215e543615738bc8ac82814"/> - <!-- Information: platform/external/tremolo is tagged with A8064AAAAANLYA102313 --><project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/> + <!-- Information: platform/external/tremolo is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/> <!-- Information: unbootimg is tagged with B2G_1_0_0_20130125190500 --><project name="unbootimg" path="external/unbootimg" remote="b2g" revision="9464623d92eb8668544916dc5a8f4f6337d0bc08"/> - <!-- Information: platform/external/webp is tagged with A8064AAAAANLYA102313 --><project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/> - <!-- Information: platform/external/webrtc is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/webrtc" path="external/webrtc" revision="137024dc8a2e9251a471e20518a9c3ae06f81f23"/> - <!-- Information: platform/external/wpa_supplicant is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/wpa_supplicant" path="external/wpa_supplicant" revision="a01d37870bbf9892d43e792e5de0683ca41c5497"/> + <!-- Information: platform/external/webp is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/> + <!-- Information: platform/external/webrtc is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/webrtc" path="external/webrtc" revision="137024dc8a2e9251a471e20518a9c3ae06f81f23"/> + <!-- Information: platform/external/wpa_supplicant is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/wpa_supplicant" path="external/wpa_supplicant" revision="a01d37870bbf9892d43e792e5de0683ca41c5497"/> <!-- Information: platform/external/hostap is tagged with M8960AAAAANLYA1047 --><project name="platform/external/hostap" path="external/hostap" revision="bf04b0faadbdeb4b7943f2e2c4c5aa59df872bb1"/> <!-- Information: platform/external/zlib is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.01.19.008 --><project name="platform/external/zlib" path="external/zlib" revision="f96a1d1ebfdf1cd582210fd09c23d8f59e0ae094"/> - <!-- Information: platform/external/yaffs2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/yaffs2" path="external/yaffs2" revision="0afa916204c664b3114429637b63af1321a0aeca"/> + <!-- Information: platform/external/yaffs2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/yaffs2" path="external/yaffs2" revision="0afa916204c664b3114429637b63af1321a0aeca"/> <!-- Information: platform/frameworks/base is tagged with M76XXUSNEKNLYA2040 --><project name="platform/frameworks/base" path="frameworks/base" revision="eb2bc75803ca179353c24c364a9c8a8ce23e8b78"/> - <!-- Information: platform/frameworks/opt/emoji is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="a95d8db002770469d72dfaf59ff37ac96db29a87"/> + <!-- Information: platform/frameworks/opt/emoji is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="a95d8db002770469d72dfaf59ff37ac96db29a87"/> <!-- Information: platform/frameworks/support is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/frameworks/support" path="frameworks/support" revision="27208692b001981f1806f4f396434f4eac78b909"/> <!-- Information: platform/hardware/libhardware is tagged with M8960AAAAANLYA1049B --><project name="platform/hardware/libhardware" path="hardware/libhardware" revision="4a619901847621f8a7305edf42dd07347a140484"/> <!-- Information: platform/hardware/libhardware_legacy is tagged with M8960AAAAANLYA153611 --><project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="87b4d7afa8f854b445e2d0d95091f6f6069f2b30"/> <!-- Information: platform/libcore is tagged with M8960AAAAANLYA100715A --><project name="platform/libcore" path="libcore" revision="30841f9fba9ccd5c54f4f079f495994db97f283e"/> - <!-- Information: platform/ndk is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/ndk" path="ndk" revision="9f555971e1481854d5b4dc11b3e6af9fff4f241f"/> + <!-- Information: platform/ndk is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/ndk" path="ndk" revision="9f555971e1481854d5b4dc11b3e6af9fff4f241f"/> <!-- Information: platform/prebuilt is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/prebuilt" path="prebuilt" revision="447ea790fcc957dde59730ecc2a65ca263bdc733"/> <!-- Information: platform/system/bluetooth is tagged with M8960AAAAANLYA100703 --><project name="platform/system/bluetooth" path="system/bluetooth" revision="7772cad4823f1f427ce1d4df84a55982386d6d18"/> <!-- Information: platform/system/core is tagged with M76XXUSNEKNLYA2040 --><project name="platform/system/core" path="system/core" revision="bf1970408676ce570b8f4dc3efa038e47552137f"/> <!-- Information: platform/system/extras is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/system/extras" path="system/extras" revision="01db6c1254e1407740a543f24317fc540fc4c049"/> <!-- Information: platform/system/media is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/system/media" path="system/media" revision="7f71c7fd362bbd992ff2e0e80f7af5859ad116ad"/> <!-- Information: platform/system/netd is tagged with M8960AAAAANLYA1049 --><project name="platform/system/netd" path="system/netd" revision="306e765248e3900041bf2737e9f57b1b5694a4ce"/> <!-- Information: platform/system/vold is tagged with M8960AAAAANLYA100715A --><project name="platform/system/vold" path="system/vold" revision="99fff257d53cc045d1460841edca5d901dacfcf5"/>
--- a/b2g/config/unagi/releng-unagi.tt +++ b/b2g/config/unagi/releng-unagi.tt @@ -1,12 +1,12 @@ [ { -"size": 832866776, -"digest": "27b9e0754de94537d664d12f5e3a2767582ceedb4ee96eb06abe405e6e9b8a0937d56ffd84cb6ce4d197c25168124296806b1ad638175b004a11ab5293b99f08", +"size": 832974796, +"digest": "0d400c33d769af9573299628c8cc33516ffd21558e4625b4e4d4ce79c23293ea10a62dbd5a6056d2df3ca059bb5950309a667a64d08f35f896c2f30ae63285f6", "algorithm": "sha512", "filename": "gonk.tar.xz" }, { "size": 8622080, "digest": "36681be904b20a52dbebf38b86466026430d59adb0e72428ae7557a442d037eb378d278aab181b04a753821ff0a99b6228380d59f86ddd5fbf291284fe54932b", "algorithm": "sha512", "filename": "boot.img"
--- a/b2g/config/unagi/sources.xml +++ b/b2g/config/unagi/sources.xml @@ -11,86 +11,86 @@ <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="43434d6cdbf702e6197e0791f19406860284edf6"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <!-- Information: fake-dalvik is tagged with B2G_1_0_0_20130125190500 --><project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8f016ce56fc7d7ef0aa7428ed509f6fb7cbde5b7"/> + <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="8e68d41728675fc72502dc572dec523c2c8abb8a"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="f634b3d50effdd42828cc757c01fdbf74e562a36"/> <!-- Information: librecovery is tagged with B2G_1_0_0_20130125190500 --><project name="librecovery" path="librecovery" remote="b2g" revision="601fc18b28c9d7cf6954b281ddd3b705c74a9215"/> <project name="moztt" path="external/moztt" remote="b2g" revision="62f94a26d34c1f1e1846efd58d34363c051e8c66"/> <!-- Stock Android things --> - <!-- Information: platform/abi/cpp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/> + <!-- Information: platform/abi/cpp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/> <!-- Information: platform/bionic is tagged with M8960AAAAANLYA100715A --><project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/> <!-- Information: platform/bootable/recovery is tagged with M8960AAAAANLYA100715A --><project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/> <!-- Information: platform/development is tagged with M8960AAAAANLYA100715A --><project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/> <!-- Information: device/common is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/> <!-- Information: device/sample is tagged with M8960AAAAANLYA100715A --><project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/> <project name="platform_external_apriori" path="external/apriori" remote="b2ggithub" revision="2c3a7113299eb789a076be23449d868b3bfa07fd"/> <!-- Information: platform/external/bluetooth/bluez is tagged with M76XXUSNEKNLYA2040 --><project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="1023c91c66e9c3bd1132480051993bf7827770f6"/> - <!-- Information: platform/external/bluetooth/glib is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="c6b49241cc1a8950723a5f74f8f4b4f4c3fa970e"/> + <!-- Information: platform/external/bluetooth/glib is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="c6b49241cc1a8950723a5f74f8f4b4f4c3fa970e"/> <!-- Information: platform/external/bluetooth/hcidump is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/bluetooth/hcidump" path="external/bluetooth/hcidump" revision="02b1eb24fbb3d0135a81edb4a2175b1397308d7d"/> - <!-- Information: platform/external/bsdiff is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/> - <!-- Information: platform/external/bzip2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/> + <!-- Information: platform/external/bsdiff is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/> + <!-- Information: platform/external/bzip2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/> <!-- Information: platform/external/dbus is tagged with M8960AAAAANLYA100715A --><project name="platform/external/dbus" path="external/dbus" revision="c7517b6195dc6926728352113e6cc335da3f9c9e"/> <!-- Information: platform/external/dhcpcd is tagged with M8960AAAAANLYA100715A --><project name="platform/external/dhcpcd" path="external/dhcpcd" revision="1e00fb67022d0921af0fead263f81762781b9ffa"/> - <!-- Information: platform/external/dnsmasq is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/> + <!-- Information: platform/external/dnsmasq is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/> <project name="platform_external_elfcopy" path="external/elfcopy" remote="b2ggithub" revision="62c1bed1c4505369cac2e72fbe30452a598fb690"/> <project name="platform_external_elfutils" path="external/elfutils" remote="b2ggithub" revision="72940dec691fa3255e13df01f8c53b620e446066"/> - <!-- Information: platform/external/e2fsprogs is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/e2fsprogs" path="external/e2fsprogs" revision="d5f550bb2f556c5d287f7c8d2b77223654bcec37"/> - <!-- Information: platform/external/expat is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/> - <!-- Information: platform/external/fdlibm is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/> - <!-- Information: platform/external/flac is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/> - <!-- Information: platform/external/freetype is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/> - <!-- Information: platform/external/giflib is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/> + <!-- Information: platform/external/e2fsprogs is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/e2fsprogs" path="external/e2fsprogs" revision="d5f550bb2f556c5d287f7c8d2b77223654bcec37"/> + <!-- Information: platform/external/expat is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/> + <!-- Information: platform/external/fdlibm is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/> + <!-- Information: platform/external/flac is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/> + <!-- Information: platform/external/freetype is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/> + <!-- Information: platform/external/giflib is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/> <project name="platform/external/gtest" path="external/gtest" remote="linaro" revision="8c212ebe53bb2baab3575f03069016f1fb11e449"/> - <!-- Information: platform/external/harfbuzz is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/harfbuzz" path="external/harfbuzz" revision="116610d63a859521dacf00fb6818ee9ab2e666f6"/> - <!-- Information: platform/external/icu4c is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/> - <!-- Information: platform/external/iptables is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/> + <!-- Information: platform/external/harfbuzz is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/harfbuzz" path="external/harfbuzz" revision="116610d63a859521dacf00fb6818ee9ab2e666f6"/> + <!-- Information: platform/external/icu4c is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/> + <!-- Information: platform/external/iptables is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/> <!-- Information: platform/external/jpeg is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/jpeg" path="external/jpeg" revision="a62e464d672a4623233180e4023034bf825f066e"/> - <!-- Information: platform/external/libgsm is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/> - <!-- Information: platform/external/liblzf is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/> - <!-- Information: platform/external/libnfc-nxp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="3a912b065a31a72c63ad56ac224cfeaa933423b6"/> - <!-- Information: platform/external/libnl-headers is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/> + <!-- Information: platform/external/libgsm is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/> + <!-- Information: platform/external/liblzf is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/> + <!-- Information: platform/external/libnfc-nxp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="3a912b065a31a72c63ad56ac224cfeaa933423b6"/> + <!-- Information: platform/external/libnl-headers is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/> <!-- Information: platform/external/libpng is tagged with M8960AAAAANLYA100715A --><project name="platform/external/libpng" path="external/libpng" revision="9c3730f0efa69f580f03463c237cd928f3196404"/> <!-- Information: platform/external/libvpx is tagged with M8960AAAAANLYA1519349 --><project name="platform/external/libvpx" path="external/libvpx" revision="3a40da0d96da5c520e7707aa14f48a80956e20d7"/> <!-- Information: platform/external/llvm is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/llvm" path="external/llvm" revision="bff5923831940309f7d8ddbff5826ca6ed2dc050"/> <!-- Information: platform/external/mksh is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/mksh" path="external/mksh" revision="ec646e8f5e7dac9a77d1de549c6ed92c04d0cd4b"/> <!-- Information: platform_external_opensans is tagged with B2G_1_0_0_20130125190500 --><project name="platform_external_opensans" path="external/opensans" remote="b2g" revision="b5b4c226ca1d71e936153cf679dda6d3d60e2354"/> <!-- Information: platform/external/openssl is tagged with AU_LINUX_ANDROID_ICS.04.00.04.00.110 --><project name="platform/external/openssl" path="external/openssl" revision="27d333cce9a31c806b4bfa042925f045c727aecd"/> - <!-- Information: platform/external/protobuf is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/protobuf" path="external/protobuf" revision="e217977611c52bccde7f7c78e1d3c790c6357431"/> - <!-- Information: platform/external/safe-iop is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/safe-iop" path="external/safe-iop" revision="07073634e2e3aa4f518e36ed5dec3aabc549d5fb"/> + <!-- Information: platform/external/protobuf is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/protobuf" path="external/protobuf" revision="e217977611c52bccde7f7c78e1d3c790c6357431"/> + <!-- Information: platform/external/safe-iop is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/safe-iop" path="external/safe-iop" revision="07073634e2e3aa4f518e36ed5dec3aabc549d5fb"/> <!-- Information: screencap-gonk is tagged with B2G_1_0_0_20130125190500 --><project name="screencap-gonk" path="external/screencap-gonk" remote="b2g" revision="e6403c71e9eca8cb943739d5a0a192deac60fc51"/> <!-- Information: platform/external/skia is tagged with M8960AAAAANLYA100715A --><project name="platform/external/skia" path="external/skia" revision="7d90c85f2c0e3b747f7c7eff8bc9253b0063b439"/> <!-- Information: platform/external/sonivox is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/sonivox" path="external/sonivox" revision="7c967779dfc61ac1f346e972de91d4bfce7dccbb"/> - <!-- Information: platform/external/speex is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/speex" path="external/speex" revision="ebe6230a7f7c69f5a4389f2b09b7b19ef9e94f32"/> + <!-- Information: platform/external/speex is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/speex" path="external/speex" revision="ebe6230a7f7c69f5a4389f2b09b7b19ef9e94f32"/> <project name="platform/external/sqlite" path="external/sqlite" revision="fb30e613139b8836fdc8e81e166cf3a76e5fa17f"/> - <!-- Information: platform/external/stlport is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/> - <!-- Information: platform/external/strace is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/> - <!-- Information: platform/external/tagsoup is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/> + <!-- Information: platform/external/stlport is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/> + <!-- Information: platform/external/strace is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/> + <!-- Information: platform/external/tagsoup is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/> <!-- Information: platform/external/tinyalsa is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/external/tinyalsa" path="external/tinyalsa" revision="06cc244ee512c1352215e543615738bc8ac82814"/> - <!-- Information: platform/external/tremolo is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/> + <!-- Information: platform/external/tremolo is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/> <!-- Information: unbootimg is tagged with B2G_1_0_0_20130125190500 --><project name="unbootimg" path="external/unbootimg" remote="b2g" revision="9464623d92eb8668544916dc5a8f4f6337d0bc08"/> - <!-- Information: platform/external/webp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/> - <!-- Information: platform/external/webrtc is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/webrtc" path="external/webrtc" revision="137024dc8a2e9251a471e20518a9c3ae06f81f23"/> - <!-- Information: platform/external/wpa_supplicant is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/wpa_supplicant" path="external/wpa_supplicant" revision="a01d37870bbf9892d43e792e5de0683ca41c5497"/> + <!-- Information: platform/external/webp is tagged with M8930AAAAANLYA2217182 --><project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/> + <!-- Information: platform/external/webrtc is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/webrtc" path="external/webrtc" revision="137024dc8a2e9251a471e20518a9c3ae06f81f23"/> + <!-- Information: platform/external/wpa_supplicant is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/wpa_supplicant" path="external/wpa_supplicant" revision="a01d37870bbf9892d43e792e5de0683ca41c5497"/> <!-- Information: platform/external/hostap is tagged with M8960AAAAANLYA1047 --><project name="platform/external/hostap" path="external/hostap" revision="bf04b0faadbdeb4b7943f2e2c4c5aa59df872bb1"/> <!-- Information: platform/external/zlib is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.01.19.008 --><project name="platform/external/zlib" path="external/zlib" revision="f96a1d1ebfdf1cd582210fd09c23d8f59e0ae094"/> - <!-- Information: platform/external/yaffs2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/external/yaffs2" path="external/yaffs2" revision="0afa916204c664b3114429637b63af1321a0aeca"/> + <!-- Information: platform/external/yaffs2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/external/yaffs2" path="external/yaffs2" revision="0afa916204c664b3114429637b63af1321a0aeca"/> <!-- Information: platform/frameworks/base is tagged with M76XXUSNEKNLYA2040 --><project name="platform/frameworks/base" path="frameworks/base" revision="eb2bc75803ca179353c24c364a9c8a8ce23e8b78"/> - <!-- Information: platform/frameworks/opt/emoji is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="a95d8db002770469d72dfaf59ff37ac96db29a87"/> + <!-- Information: platform/frameworks/opt/emoji is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="a95d8db002770469d72dfaf59ff37ac96db29a87"/> <!-- Information: platform/frameworks/support is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/frameworks/support" path="frameworks/support" revision="27208692b001981f1806f4f396434f4eac78b909"/> <!-- Information: platform/hardware/libhardware is tagged with M8960AAAAANLYA1049B --><project name="platform/hardware/libhardware" path="hardware/libhardware" revision="4a619901847621f8a7305edf42dd07347a140484"/> <!-- Information: platform/hardware/libhardware_legacy is tagged with M8960AAAAANLYA153611 --><project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="87b4d7afa8f854b445e2d0d95091f6f6069f2b30"/> <!-- Information: platform/libcore is tagged with M8960AAAAANLYA100715A --><project name="platform/libcore" path="libcore" revision="30841f9fba9ccd5c54f4f079f495994db97f283e"/> - <!-- Information: platform/ndk is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.013 --><project name="platform/ndk" path="ndk" revision="9f555971e1481854d5b4dc11b3e6af9fff4f241f"/> + <!-- Information: platform/ndk is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY_V1.01.00.01.19.032 --><project name="platform/ndk" path="ndk" revision="9f555971e1481854d5b4dc11b3e6af9fff4f241f"/> <!-- Information: platform/prebuilt is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/prebuilt" path="prebuilt" revision="447ea790fcc957dde59730ecc2a65ca263bdc733"/> <!-- Information: platform/system/bluetooth is tagged with M8960AAAAANLYA100703 --><project name="platform/system/bluetooth" path="system/bluetooth" revision="7772cad4823f1f427ce1d4df84a55982386d6d18"/> <!-- Information: platform/system/core is tagged with M76XXUSNEKNLYA2040 --><project name="platform/system/core" path="system/core" revision="bf1970408676ce570b8f4dc3efa038e47552137f"/> <!-- Information: platform/system/extras is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/system/extras" path="system/extras" revision="01db6c1254e1407740a543f24317fc540fc4c049"/> <!-- Information: platform/system/media is tagged with AU_LINUX_ANDROID_ICS_CHOCOLATE.04.00.04.05.324 --><project name="platform/system/media" path="system/media" revision="7f71c7fd362bbd992ff2e0e80f7af5859ad116ad"/> <!-- Information: platform/system/netd is tagged with M8960AAAAANLYA1049 --><project name="platform/system/netd" path="system/netd" revision="306e765248e3900041bf2737e9f57b1b5694a4ce"/> <!-- Information: platform/system/vold is tagged with M8960AAAAANLYA100715A --><project name="platform/system/vold" path="system/vold" revision="99fff257d53cc045d1460841edca5d901dacfcf5"/>
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1214,8 +1214,11 @@ pref("social.directories", "https://addo // necessary. This does not affect whitelisted and directory installs. pref("social.remote-install.enabled", true); pref("social.sidebar.open", true); pref("social.sidebar.unload_timeout_ms", 10000); pref("social.toast-notifications.enabled", true); pref("dom.identity.enabled", false); + +// Override the Gecko-default value of false for Firefox. +pref("plain_text.wrap_long_lines", true);
--- a/browser/base/content/aboutDialog.js +++ b/browser/base/content/aboutDialog.js @@ -40,20 +40,22 @@ function init(aEvent) document.getElementById("version").textContent += " (" + buildDate + ")"; document.getElementById("experimental").hidden = false; document.getElementById("communityDesc").hidden = true; } #ifdef MOZ_UPDATER gAppUpdater = new appUpdater(); +#if MOZ_UPDATE_CHANNEL != release let defaults = Services.prefs.getDefaultBranch(""); let channelLabel = document.getElementById("currentChannel"); channelLabel.value = defaults.getCharPref("app.update.channel"); #endif +#endif #ifdef XP_MACOSX // it may not be sized at this point, and we need its width to calculate its position window.sizeToContent(); window.moveTo((screen.availWidth / 2) - (window.outerWidth / 2), screen.availHeight / 5); #endif }
--- a/browser/base/content/aboutDialog.xul +++ b/browser/base/content/aboutDialog.xul @@ -78,21 +78,23 @@ </hbox> <hbox id="manualUpdate" align="center"> <label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label> </hbox> </deck> #endif </vbox> +#if MOZ_UPDATE_CHANNEL != release #ifdef MOZ_UPDATER <description class="text-blurb" id="currentChannelText"> &channel.description.start;<label id="currentChannel"/>&channel.description.end; </description> #endif +#endif <vbox id="experimental" hidden="true"> <description class="text-blurb" id="warningDesc"> &warningDesc.version; #ifdef MOZ_TELEMETRY_ON_BY_DEFAULT &warningDesc.telemetryDesc; #endif </description> <description class="text-blurb" id="communityExperimentalDesc">
--- a/browser/base/content/abouthealthreport/abouthealth.js +++ b/browser/base/content/abouthealthreport/abouthealth.js @@ -55,17 +55,17 @@ function updateView(state="default") { function refreshDataView(data) { let noData = document.getElementById("data-no-data"); let dataEl = document.getElementById("raw-data"); noData.style.display = data ? "none" : "inline"; dataEl.style.display = data ? "block" : "none"; if (data) { - dataEl.innerHTML = JSON.stringify(data, null, 2); + dataEl.textContent = JSON.stringify(data, null, 2); } } /** * Ensure the page has the latest version of the uploaded JSON payload. */ function refreshJSONPayload() { reporter.getLastPayload().then(refreshDataView);
--- a/browser/base/content/browser-social.js +++ b/browser/base/content/browser-social.js @@ -7,17 +7,16 @@ const PANEL_MIN_HEIGHT = 100; const PANEL_MIN_WIDTH = 330; XPCOMUtils.defineLazyModuleGetter(this, "SharedFrame", "resource:///modules/SharedFrame.jsm"); let SocialUI = { // Called on delayed startup to initialize the UI init: function SocialUI_init() { - Services.obs.addObserver(this, "social:pref-changed", false); 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); Services.prefs.addObserver("social.sidebar.open", this, false); @@ -32,99 +31,78 @@ let SocialUI = { }); SocialChatBar.init(); SocialShareButton.init(); SocialMenu.init(); SocialToolbar.init(); SocialSidebar.init(); - Social.init(); - // If social was previously initialized it isn't going to notify observers - // about the provider being set or the list of providers changing, so - // handle those now. - if (Social.provider) { - this.observe(null, "social:provider-set", Social.provider.origin); + if (!Social.initialized) { + Social.init(); + } else { + // social was previously initialized, so it's not going to notify us of + // anything, so handle that now. this.observe(null, "social:providers-changed", null); + this.observe(null, "social:provider-set", Social.provider ? Social.provider.origin : null); } }, // Called on window unload uninit: function SocialUI_uninit() { - Services.obs.removeObserver(this, "social:pref-changed"); Services.obs.removeObserver(this, "social:ambient-notification-changed"); Services.obs.removeObserver(this, "social:profile-changed"); Services.obs.removeObserver(this, "social:recommend-info-changed"); Services.obs.removeObserver(this, "social:frameworker-error"); Services.obs.removeObserver(this, "social:provider-set"); Services.obs.removeObserver(this, "social:providers-changed"); Services.prefs.removeObserver("social.sidebar.open", this); Services.prefs.removeObserver("social.toast-notifications.enabled", this); }, - // Social.provider has changed, update any state that depends on it. - // Note: this method is not called when Social.provider is first set, during - // the first window load. - _updateProvider: function () { - // XXX audit for handling nullness of social.provider - this._updateActiveUI(); - this._updateMenuItems(); - - SocialChatBar.update(); - SocialShareButton.updateProvider(); - SocialMenu.populate(); - SocialToolbar.updateProvider(); - SocialSidebar.update(); - }, - - // The entire feature is being turned on/off. - _updateEnabledState: function () { - this._updateActiveUI(); - SocialChatBar.update(); - SocialSidebar.update(); - SocialShareButton.updateButtonHiddenState(); - SocialMenu.populate(); - SocialToolbar.updateButtonHiddenState(); - SocialToolbar.populateProviderMenus(); - }, - _matchesCurrentProvider: function (origin) { return Social.provider && Social.provider.origin == origin; }, observe: function SocialUI_observe(subject, topic, data) { // Exceptions here sometimes don't get reported properly, report them // manually :( try { switch (topic) { case "social:provider-set": - this._updateProvider(); + // Social.provider has changed (possibly to null), update any state + // which depends on it. + this._updateActiveUI(); + this._updateMenuItems(); + + SocialChatBar.update(); + SocialSidebar.update(); + SocialShareButton.update(); + SocialToolbar.update(); + SocialMenu.populate(); break; case "social:providers-changed": // the list of providers changed - this may impact the "active" UI. this._updateActiveUI(); // and the multi-provider menu SocialToolbar.populateProviderMenus(); break; - case "social:pref-changed": - this._updateEnabledState(); - break; // Provider-specific notifications case "social:ambient-notification-changed": if (this._matchesCurrentProvider(data)) { SocialToolbar.updateButton(); SocialMenu.populate(); } break; case "social:profile-changed": if (this._matchesCurrentProvider(data)) { SocialToolbar.updateProfile(); - SocialShareButton.updateProfileInfo(); + SocialShareButton.update(); SocialChatBar.update(); } break; case "social:recommend-info-changed": if (this._matchesCurrentProvider(data)) { SocialShareButton.updateShareState(); } break; @@ -590,41 +568,32 @@ let SocialFlyout = { } let SocialShareButton = { // Called once, after window load, when the Social.provider object is initialized init: function SSB_init() { }, // Called when the Social.provider changes - updateProvider: function () { - this.updateButtonHiddenState(); - if (!Social.provider) - return; - this.updateProfileInfo(); - }, - - // Called when the provider's profile info changes (or when the provider - // changes, via updateProvider) - updateProfileInfo: function SSB_updateProfileInfo() { + update: function() { + this._updateButtonHiddenState(); let profileRow = document.getElementById("unsharePopupHeader"); let profile = SocialUI.enabled ? Social.provider.profile : null; if (profile && profile.displayName) { profileRow.hidden = false; let portrait = document.getElementById("socialUserPortrait"); if (profile.portrait) { portrait.setAttribute("src", profile.portrait); } else { portrait.removeAttribute("src"); } let displayName = document.getElementById("socialUserDisplayName"); displayName.setAttribute("label", profile.displayName); } else { profileRow.hidden = true; - this.updateButtonHiddenState(); } }, get shareButton() { return document.getElementById("share-button"); }, get unsharePopup() { return document.getElementById("unsharePopup"); @@ -634,17 +603,17 @@ let SocialShareButton = { this.unsharePopup.hidePopup(); }, canSharePage: function SSB_canSharePage(aURI) { // We only allow sharing of http or https return aURI && (aURI.schemeIs('http') || aURI.schemeIs('https')); }, - updateButtonHiddenState: function SSB_updateButtonHiddenState() { + _updateButtonHiddenState: function SSB_updateButtonHiddenState() { let shareButton = this.shareButton; if (shareButton) shareButton.hidden = !SocialUI.enabled || Social.provider.recommendInfo == null || !Social.haveLoggedInUser() || !this.canSharePage(gBrowser.currentURI); // also update the relevent command's disabled state so the keyboard // shortcut only works when available. @@ -698,17 +667,17 @@ let SocialShareButton = { unsharePage: function SSB_unsharePage() { Social.unsharePage(gBrowser.currentURI); this.updateShareState(); this.dismissUnsharePopup(); }, updateShareState: function SSB_updateShareState() { - this.updateButtonHiddenState(); + this._updateButtonHiddenState(); let shareButton = this.shareButton; let currentPageShared = shareButton && !shareButton.hidden && Social.isPageShared(gBrowser.currentURI); let recommendInfo = SocialUI.enabled ? Social.provider.recommendInfo : null; // Provide a11y-friendly notification of share. let status = document.getElementById("share-button-status"); if (status) { @@ -777,56 +746,63 @@ var SocialMenu = { // XXX Need to audit that this is being initialized correctly var 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(); + this.updateProvider(); + this.populateProviderMenus(); + }, + // Called when the Social.provider changes updateProvider: function () { let provider = Social.provider || Social.defaultProvider; if (provider) { this.button.setAttribute("label", provider.name); this.button.setAttribute("tooltiptext", provider.name); this.button.style.listStyleImage = "url(" + provider.iconURL + ")"; this.updateProfile(); } this.updateButton(); - this.populateProviderMenus(); }, get button() { return document.getElementById("social-provider-button"); }, // Note: this doesn't actually handle hiding the toolbar button, // socialActiveBroadcaster is responsible for that. - updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() { - let tbi = document.getElementById("social-toolbar-item"); + _updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() { let socialEnabled = SocialUI.enabled; for (let className of ["social-statusarea-separator", "social-statusarea-user"]) { for (let element of document.getElementsByClassName(className)) element.hidden = !socialEnabled; } let toggleNotificationsCommand = document.getElementById("Social:ToggleNotifications"); toggleNotificationsCommand.setAttribute("hidden", !socialEnabled); if (!Social.haveLoggedInUser() || !socialEnabled) { let parent = document.getElementById("social-notification-panel"); while (parent.hasChildNodes()) { let frame = parent.firstChild; SharedFrame.forgetGroup(frame.id); parent.removeChild(frame); } - while (tbi.lastChild != tbi.firstChild) - tbi.removeChild(tbi.lastChild); + let tbi = document.getElementById("social-toolbar-item"); + if (tbi) { + while (tbi.lastChild != tbi.firstChild) + tbi.removeChild(tbi.lastChild); + } } }, updateProfile: function SocialToolbar_updateProfile() { // Profile may not have been initialized yet, since it depends on a worker // response. In that case we'll be called again when it's available, via // social:profile-changed if (!Social.provider) @@ -849,17 +825,17 @@ var SocialToolbar = { } userDetailsBroadcaster.setAttribute("value", loggedInStatusValue); userDetailsBroadcaster.setAttribute("label", loggedInStatusValue); }, // XXX doesn't this need to be called for profile changes, given its use of provider.profile? updateButton: function SocialToolbar_updateButton() { - this.updateButtonHiddenState(); + this._updateButtonHiddenState(); let panel = document.getElementById("social-notification-panel"); panel.hidden = !SocialUI.enabled; let command = document.getElementById("Social:ToggleNotifications"); command.setAttribute("checked", Services.prefs.getBoolPref("social.toast-notifications.enabled")); const CACHE_PREF_NAME = "social.cached.ambientNotificationIcons"; // provider.profile == undefined means no response yet from the provider
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -6398,45 +6398,46 @@ function warnAboutClosingWindow() { // Popups aren't considered full browser windows. let isPBWindow = PrivateBrowsingUtils.isWindowPrivate(window); if (!isPBWindow && !toolbar.visible) return gBrowser.warnAboutClosingTabs(true); // Figure out if there's at least one other browser window around. let e = Services.wm.getEnumerator("navigator:browser"); let otherPBWindowExists = false; - let warnAboutClosingTabs = false; + let nonPopupPresent = false; while (e.hasMoreElements()) { let win = e.getNext(); if (win != window) { if (isPBWindow && PrivateBrowsingUtils.isWindowPrivate(win)) otherPBWindowExists = true; if (win.toolbar.visible) - warnAboutClosingTabs = true; + nonPopupPresent = true; // If the current window is not in private browsing mode we don't need to // look for other pb windows, we can leave the loop when finding the // first non-popup window. If however the current window is in private // browsing mode then we need at least one other pb and one non-popup // window to break out early. - if ((!isPBWindow || otherPBWindowExists) && warnAboutClosingTabs) + if ((!isPBWindow || otherPBWindowExists) && nonPopupPresent) break; } } if (isPBWindow && !otherPBWindowExists) { let exitingCanceled = Cc["@mozilla.org/supports-PRBool;1"]. createInstance(Ci.nsISupportsPRBool); exitingCanceled.data = false; Services.obs.notifyObservers(exitingCanceled, "last-pb-context-exiting", null); if (exitingCanceled.data) return false; } - if (warnAboutClosingTabs) + + if (!isPBWindow && nonPopupPresent) return gBrowser.warnAboutClosingTabs(true); let os = Services.obs; let closingCanceled = Cc["@mozilla.org/supports-PRBool;1"]. createInstance(Ci.nsISupportsPRBool); os.notifyObservers(closingCanceled, "browser-lastwindow-close-requested", null); @@ -6444,17 +6445,17 @@ function warnAboutClosingWindow() { return false; os.notifyObservers(null, "browser-lastwindow-close-granted", null); #ifdef XP_MACOSX // OS X doesn't quit the application when the last window is closed, but keeps // the session alive. Hence don't prompt users to save tabs, but warn about // closing multiple tabs. - return gBrowser.warnAboutClosingTabs(true); + return isPBWindow || gBrowser.warnAboutClosingTabs(true); #else return true; #endif } var MailIntegration = { sendLinkForWindow: function (aWindow) { this.sendMessage(aWindow.location.href,
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -778,17 +778,20 @@ <method name="getWindowTitleForBrowser"> <parameter name="aBrowser"/> <body> <![CDATA[ var newTitle = ""; var docElement = this.ownerDocument.documentElement; var sep = docElement.getAttribute("titlemenuseparator"); - var docTitle = aBrowser.contentTitle; + // Strip out any null bytes in the content title, since the + // underlying widget implementations of nsWindow::SetTitle pass + // null-terminated strings to system APIs. + var docTitle = aBrowser.contentTitle.replace("\0", ""); if (!docTitle) docTitle = docElement.getAttribute("titledefault"); var modifier = docElement.getAttribute("titlemodifier"); if (docTitle) { newTitle += docElement.getAttribute("titlepreface"); newTitle += docTitle; @@ -1253,39 +1256,24 @@ t.setAttribute("onerror", "this.removeAttribute('image');"); t.className = "tabbrowser-tab"; this.tabContainer._unlockTabSizing(); // When overflowing, new tabs are scrolled into view smoothly, which // doesn't go well together with the width transition. So we skip the // transition in that case. - if (aSkipAnimation || - this.tabContainer.getAttribute("overflow") == "true" || - !Services.prefs.getBoolPref("browser.tabs.animate")) { + let animate = !aSkipAnimation && + this.tabContainer.getAttribute("overflow") != "true" && + Services.prefs.getBoolPref("browser.tabs.animate"); + if (!animate) { t.setAttribute("fadein", "true"); setTimeout(function (tabContainer) { tabContainer._handleNewTab(t); }, 0, this.tabContainer); - } else { - setTimeout(function (tabContainer) { - if (t.pinned) - tabContainer._handleNewTab(t); - else { - tabContainer._handleTabTelemetryStart(tabContainer, t, aURI); - - t.setAttribute("fadein", "true"); - - // This call to adjustTabstrip is redundant but needed so that - // when opening a second tab, the first tab's close buttons - // appears immediately rather than when the transition ends. - if (tabContainer.childNodes.length == 2) - tabContainer.adjustTabstrip(); - } - }, 0, this.tabContainer); } // invalidate caches this._browsers = null; this._visibleTabs = null; this.tabContainer.appendChild(t); @@ -1438,16 +1426,30 @@ if (this._lastRelatedTab) this._lastRelatedTab.owner = null; else t.owner = this.selectedTab; this.moveTabTo(t, newTabPos); this._lastRelatedTab = t; } + if (animate) { + this.tabContainer._handleTabTelemetryStart(this.tabContainer, t, aURI); + + // kick the animation off + t.clientTop; + t.setAttribute("fadein", "true"); + + // This call to adjustTabstrip is redundant but needed so that + // when opening a second tab, the first tab's close buttons + // appears immediately rather than when the transition ends. + if (this.tabContainer.childNodes.length == 2) + this.tabContainer.adjustTabstrip(); + } + return t; ]]> </body> </method> <method name="warnAboutClosingTabs"> <parameter name="aAll"/> <body>
--- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -308,16 +308,17 @@ endif download_page.html \ browser_URLBarSetURI.js \ browser_bookmark_titles.js \ browser_pageInfo_plugins.js \ browser_pageInfo.js \ feed_tab.html \ browser_pluginCrashCommentAndURL.js \ pluginCrashCommentAndURL.html \ + browser_private_no_prompt.js \ $(NULL) # Disable test on Windows due to frequent failures (bug 841341) ifneq (windows,$(MOZ_WIDGET_TOOLKIT)) _BROWSER_FILES += \ browser_popupNotification.js \ $(NULL) endif
--- a/browser/base/content/test/browser_bug585785.js +++ b/browser/base/content/test/browser_bug585785.js @@ -1,26 +1,21 @@ var tab; function test() { waitForExplicitFinish(); tab = gBrowser.addTab(); - isnot(tab.getAttribute("fadein"), "true", "newly opened tab is yet to fade in"); + is(tab.getAttribute("fadein"), "true", "tab opening animation initiated"); // Try to remove the tab right before the opening animation's first frame window.mozRequestAnimationFrame(checkAnimationState); } function checkAnimationState() { - if (tab.getAttribute("fadein") != "true") { - window.mozRequestAnimationFrame(checkAnimationState); - return; - } - info(window.getComputedStyle(tab).maxWidth); gBrowser.removeTab(tab, { animate: true }); if (!tab.parentNode) { ok(true, "tab removed synchronously since the opening animation hasn't moved yet"); finish(); return; }
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/browser_private_no_prompt.js @@ -0,0 +1,13 @@ +function test() { + waitForExplicitFinish(); + var privateWin = OpenBrowserWindow({private: true}); + privateWin.addEventListener("load", function onload() { + privateWin.removeEventListener("load", onload, false); + ok(true, "Load listener called"); + + privateWin.BrowserOpenTab(); + privateWin.BrowserTryToCloseWindow(); + ok(true, "didn't prompt"); + finish(); + }, false); +} \ No newline at end of file
--- a/browser/base/content/test/social/Makefile.in +++ b/browser/base/content/test/social/Makefile.in @@ -23,16 +23,17 @@ include $(DEPTH)/config/autoconf.mk browser_social_sidebar.js \ browser_social_flyout.js \ browser_social_mozSocial_API.js \ browser_social_isVisible.js \ browser_social_chatwindow.js \ browser_social_chatwindowfocus.js \ browser_social_multiprovider.js \ browser_social_errorPage.js \ + browser_social_window.js \ social_activate.html \ social_activate_iframe.html \ social_panel.html \ social_share_image.png \ social_sidebar.html \ social_chat.html \ social_flyout.html \ social_window.html \
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/social/browser_social_window.js @@ -0,0 +1,145 @@ +// 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/. + +// Test the top-level window UI for social. + +// This function should "reset" Social such that the next time Social.init() +// is called (eg, when a new window is opened), it re-performs all +// initialization. +function resetSocial() { + Social.initialized = false; + Social._provider = null; + Social.providers = []; + // *sob* - listeners keep getting added... + let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService; + SocialService._providerListeners.clear(); +} + +let createdWindows = []; + +function openWindowAndWaitForInit(callback) { + // this notification tells us SocialUI.init() has been run... + let topic = "browser-delayed-startup-finished"; + let w = OpenBrowserWindow(); + createdWindows.push(w); + Services.obs.addObserver(function providerSet(subject, topic, data) { + Services.obs.removeObserver(providerSet, topic); + info(topic + " observer was notified - continuing test"); + // executeSoon to let the browser UI observers run first + executeSoon(function() {callback(w)}); + }, topic, false); +} + +function postTestCleanup(cb) { + for (let w of createdWindows) + w.close(); + createdWindows = []; + Services.prefs.clearUserPref("social.enabled"); + cb(); +} + +let manifest = { // normal provider + name: "provider 1", + origin: "https://example.com", + sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html", + workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js", + iconURL: "https://example.com/browser/browser/base/content/test/social/moz.png" +}; + +function test() { + waitForExplicitFinish(); + runSocialTests(tests, undefined, postTestCleanup); +} + +let tests = { + // check when social is totally disabled at startup (ie, no providers) + testInactiveStartup: function(cbnext) { + is(Social.providers.length, 0, "needs zero providers to start this test."); + resetSocial(); + openWindowAndWaitForInit(function(w1) { + checkSocialUI(w1); + // Now social is (re-)initialized, open a secondary window and check that. + openWindowAndWaitForInit(function(w2) { + checkSocialUI(w2); + checkSocialUI(w1); + cbnext(); + }); + }); + }, + + // Check when providers exist and social is turned on at startup. + testEnabledStartup: function(cbnext) { + runSocialTestWithProvider(manifest, function (finishcb) { + resetSocial(); + openWindowAndWaitForInit(function(w1) { + ok(Social.enabled, "social is enabled"); + checkSocialUI(w1); + // now init is complete, open a second window + openWindowAndWaitForInit(function(w2) { + checkSocialUI(w2); + checkSocialUI(w1); + // disable social and re-check + Services.prefs.setBoolPref("social.enabled", false); + executeSoon(function() { // let all the UI observers run... + ok(!Social.enabled, "social is disabled"); + checkSocialUI(w2); + checkSocialUI(w1); + finishcb(); + }); + }); + }); + }, cbnext); + }, + + // Check when providers exist but social is turned off at startup. + testDisabledStartup: function(cbnext) { + runSocialTestWithProvider(manifest, function (finishcb) { + Services.prefs.setBoolPref("social.enabled", false); + resetSocial(); + openWindowAndWaitForInit(function(w1) { + ok(!Social.enabled, "social is disabled"); + checkSocialUI(w1); + // now init is complete, open a second window + openWindowAndWaitForInit(function(w2) { + checkSocialUI(w2); + checkSocialUI(w1); + // enable social and re-check + Services.prefs.setBoolPref("social.enabled", true); + executeSoon(function() { // let all the UI observers run... + ok(Social.enabled, "social is enabled"); + checkSocialUI(w2); + checkSocialUI(w1); + finishcb(); + }); + }); + }); + }, cbnext); + }, + + // Check when the last provider is removed. + testRemoveProvider: function(cbnext) { + runSocialTestWithProvider(manifest, function (finishcb) { + openWindowAndWaitForInit(function(w1) { + checkSocialUI(w1); + // now init is complete, open a second window + openWindowAndWaitForInit(function(w2) { + checkSocialUI(w2); + // remove the current provider. + let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService; + SocialService.removeProvider(manifest.origin, function() { + ok(!Social.enabled, "social is disabled"); + is(Social.providers.length, 0, "no providers"); + checkSocialUI(w2); + checkSocialUI(w1); + // *sob* - runSocialTestWithProvider's cleanup fails when it can't + // remove the provider, so re-add it. + SocialService.addProvider(manifest, function() { + finishcb(); + }); + }); + }); + }); + }, cbnext); + }, +}
--- a/browser/base/content/test/social/head.js +++ b/browser/base/content/test/social/head.js @@ -35,17 +35,17 @@ function promiseSocialUrlNotRemembered(u ok(!aIsVisited, "social URL " + url + " should not be in global history"); deferred.resolve(); }); return deferred.promise; } let gURLsNotRemembered = []; -function runSocialTestWithProvider(manifest, callback) { +function runSocialTestWithProvider(manifest, callback, finishcallback) { let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService; let manifests = Array.isArray(manifest) ? manifest : [manifest]; // Check that none of the provider's content ends up in history. function finishCleanUp() { for (let i = 0; i < manifests.length; i++) { let m = manifests[i]; @@ -62,17 +62,17 @@ function runSocialTestWithProvider(manif } info("runSocialTestWithProvider: " + manifests.toSource()); let finishCount = 0; function finishIfDone(callFinish) { finishCount++; if (finishCount == manifests.length) - Task.spawn(finishCleanUp).then(finish); + Task.spawn(finishCleanUp).then(finishcallback || finish); } function removeAddedProviders(cleanup) { manifests.forEach(function (m) { // If we're "cleaning up", don't call finish when done. let callback = cleanup ? function () {} : finishIfDone; // Similarly, if we're cleaning up, catch exceptions from removeProvider let removeProvider = SocialService.removeProvider.bind(SocialService); if (cleanup) { @@ -168,38 +168,48 @@ function runSocialTests(tests, cbPreTest // A fairly large hammer which checks all aspects of the SocialUI for // internal consistency. function checkSocialUI(win) { let win = win || window; let doc = win.document; let provider = Social.provider; let enabled = win.SocialUI.enabled; + let active = Social.providers.length > 0 && !win.SocialUI._chromeless && + !PrivateBrowsingUtils.isWindowPrivate(win); + function isbool(a, b, msg) { is(!!a, !!b, msg); } isbool(win.SocialSidebar.canShow, enabled, "social sidebar active?"); if (enabled) isbool(win.SocialSidebar.opened, enabled, "social sidebar open?"); isbool(win.SocialChatBar.isAvailable, enabled && Social.haveLoggedInUser(), "chatbar available?"); isbool(!win.SocialChatBar.chatbar.hidden, enabled && Social.haveLoggedInUser(), "chatbar visible?"); - isbool(!win.SocialShareButton.shareButton.hidden, enabled && Social.haveLoggedInUser() && provider.recommendInfo, "share button visible?"); - isbool(!doc.getElementById("social-toolbar-item").hidden, enabled, "toolbar items visible?"); - if (enabled) - is(win.SocialToolbar.button.style.listStyleImage, 'url("' + provider.iconURL + '")', "toolbar button has provider icon"); + + let canShare = enabled && provider.recommendInfo && Social.haveLoggedInUser() && win.SocialShareButton.canSharePage(win.gBrowser.currentURI) + isbool(!win.SocialShareButton.shareButton.hidden, canShare, "share button visible?"); + isbool(!doc.getElementById("social-toolbar-item").hidden, active, "toolbar items visible?"); + if (active) + is(win.SocialToolbar.button.style.listStyleImage, 'url("' + Social.defaultProvider.iconURL + '")', "toolbar button has provider icon"); + // the menus should always have the provider name + if (provider) { + for (let id of ["menu_socialSidebar", "menu_socialAmbientMenu"]) + is(document.getElementById(id).getAttribute("label"), Social.provider.name, "element has the provider name"); + } // and for good measure, check all the social commands. - isbool(!doc.getElementById("Social:Toggle").hidden, enabled, "Social:Toggle visible?"); + isbool(!doc.getElementById("Social:Toggle").hidden, active, "Social:Toggle visible?"); isbool(!doc.getElementById("Social:ToggleNotifications").hidden, enabled, "Social:ToggleNotifications visible?"); isbool(!doc.getElementById("Social:FocusChat").hidden, enabled && Social.haveLoggedInUser(), "Social:FocusChat visible?"); isbool(doc.getElementById("Social:FocusChat").getAttribute("disabled"), enabled ? "false" : "true", "Social:FocusChat disabled?"); - is(doc.getElementById("Social:SharePage").getAttribute("disabled"), enabled && Social.haveLoggedInUser() && provider.recommendInfo ? "false" : "true", "Social:SharePage visible?"); + is(doc.getElementById("Social:SharePage").getAttribute("disabled"), canShare ? "false" : "true", "Social:SharePage visible?"); // broadcasters. - isbool(!doc.getElementById("socialActiveBroadcaster").hidden, enabled, "socialActiveBroadcaster hidden?"); + isbool(!doc.getElementById("socialActiveBroadcaster").hidden, active, "socialActiveBroadcaster hidden?"); } // blocklist testing function updateBlocklist(aCallback) { var blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"] .getService(Ci.nsITimerCallback); var observer = function() { Services.obs.removeObserver(observer, "blocklist-updated");
--- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -526,17 +526,17 @@ function openHealthReport() } #endif /** * Opens the feedback page for this version of the application. */ function openFeedbackPage() { - openUILinkIn("http://input.mozilla.com/feedback", "tab"); + openUILinkIn("https://input.mozilla.org/feedback", "tab"); } function buildHelpMenu() { // Enable/disable the "Report Web Forgery" menu item. if (typeof gSafeBrowsing != "undefined") gSafeBrowsing.setReportPhishingMenu(); }
--- a/browser/components/feeds/public/Makefile.in +++ b/browser/components/feeds/public/Makefile.in @@ -6,13 +6,12 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = browser-feeds -XPIDL_MODULE = browser-feeds XPIDLSRCS = nsIFeedResultService.idl nsIWebContentConverterRegistrar.idl nsIFeedWriter.idl include $(topsrcdir)/config/rules.mk
--- a/browser/components/migration/public/Makefile.in +++ b/browser/components/migration/public/Makefile.in @@ -5,14 +5,13 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = migration -XPIDL_MODULE = migration XPIDLSRCS = nsIBrowserProfileMigrator.idl include $(topsrcdir)/config/rules.mk
--- a/browser/components/preferences/in-content/privacy.js +++ b/browser/components/preferences/in-content/privacy.js @@ -19,19 +19,17 @@ var gPrivacyPane = { * label of the "Clear Now..." button. */ init: function () { this._updateSanitizeSettingsButton(); this.initializeHistoryMode(); this.updateHistoryModePane(); this.updatePrivacyMicroControls(); - this.initAutoStartPrivateBrowsingObserver(); - - window.addEventListener("unload", this.removeASPBObserver.bind(this), false); + this.initAutoStartPrivateBrowsingReverter(); }, // HISTORY MODE /** * The list of preferences which affect the initial history mode settings. * If the auto start private browsing mode pref is active, the initial * history mode would be set to "Don't remember anything". @@ -227,88 +225,82 @@ var gPrivacyPane = { this._updateSanitizeSettingsButton(); } } }, // PRIVATE BROWSING /** - * Install the observer for the auto-start private browsing mode pref. + * Initialize the starting state for the auto-start private browsing mode pref reverter. */ - initAutoStartPrivateBrowsingObserver: function PPP_initAutoStartPrivateBrowsingObserver() + initAutoStartPrivateBrowsingReverter: function PPP_initAutoStartPrivateBrowsingReverter() { - let prefService = document.getElementById("privacyPreferences") - .service - .QueryInterface(Components.interfaces.nsIPrefBranch); - prefService.addObserver("browser.privatebrowsing.autostart", - this.autoStartPrivateBrowsingObserver, - false); + let mode = document.getElementById("historyMode"); + let autoStart = document.getElementById("privateBrowsingAutoStart"); + this._lastMode = mode.selectedIndex; + this._lastCheckState = autoStart.hasAttribute('checked'); }, - /** - * Install the observer for the auto-start private browsing mode pref. - */ - removeASPBObserver: function PPP_removeASPBObserver() - { - let prefService = document.getElementById("privacyPreferences") - .service - .QueryInterface(Components.interfaces.nsIPrefBranch); - prefService.removeObserver("browser.privatebrowsing.autostart", - this.autoStartPrivateBrowsingObserver); - }, + _lastMode: null, + _lasCheckState: null, + updateAutostart: function PPP_updateAutostart() { + let mode = document.getElementById("historyMode"); + let autoStart = document.getElementById("privateBrowsingAutoStart"); + let pref = document.getElementById("browser.privatebrowsing.autostart"); + if ((mode.value == "custom" && this._lastCheckState == autoStart.checked) || + (mode.value == "remember" && !this._lastCheckState) || + (mode.value == "dontremember" && this._lastCheckState)) { + // These are all no-op changes, so we don't need to prompt. + this._lastMode = mode.selectedIndex; + this._lastCheckState = autoStart.hasAttribute('checked'); + return; + } - autoStartPrivateBrowsingObserver: - { - QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]), - - observe: function PPP_observe(aSubject, aTopic, aData) - { - if (!gPrivacyPane._shouldPromptForRestart) { + if (!this._shouldPromptForRestart) { // We're performing a revert. Just let it happen. - gPrivacyPane._shouldPromptForRestart = true; return; } const Cc = Components.classes, Ci = Components.interfaces; - let pref = document.getElementById("browser.privatebrowsing.autostart"); let brandName = document.getElementById("bundleBrand").getString("brandShortName"); let bundle = document.getElementById("bundlePreferences"); let msg = bundle.getFormattedString(pref.value ? "featureEnableRequiresRestart" : "featureDisableRequiresRestart", [brandName]); let title = bundle.getFormattedString("shouldRestartTitle", [brandName]); let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService); let shouldProceed = prompts.confirm(window, title, msg) if (shouldProceed) { let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"] .createInstance(Ci.nsISupportsPRBool); Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart"); shouldProceed = !cancelQuit.data; if (shouldProceed) { + document.documentElement.acceptDialog(); let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"] .getService(Ci.nsIAppStartup); appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); return; } } - gPrivacyPane._shouldPromptForRestart = false; - pref.value = !pref.value; + + this._shouldPromptForRestart = false; - let mode = document.getElementById("historyMode"); - if (mode.value != "custom") { - mode.selectedIndex = pref.value ? 1 : 0; - mode.doCommand(); + if (this._lastCheckState) { + autoStart.checked = "checked"; } else { - let rememberHistoryCheckbox = document.getElementById("rememberHistory"); - rememberHistory.checked = pref.value; + autoStart.removeAttribute('checked'); } - } + mode.selectedIndex = this._lastMode; + mode.doCommand(); + + this._shouldPromptForRestart = true; }, // HISTORY /** * Read the location bar enabled and suggestion prefs * @return Int value for suggestion menulist */
--- a/browser/components/preferences/in-content/privacy.xul +++ b/browser/components/preferences/in-content/privacy.xul @@ -56,17 +56,16 @@ type="bool"/> <preference id="privacy.sanitize.timeSpan" name="privacy.sanitize.timeSpan" type="int"/> <!-- Private Browsing --> <preference id="browser.privatebrowsing.autostart" name="browser.privatebrowsing.autostart" onchange="gPrivacyPane.updatePrivacyMicroControls();" - instantApply="true" type="bool"/> </preferences> <hbox class="heading" data-category="panePrivacy" hidden="true"> <image class="preference-icon" type="privacy"/> <html:h1>&panePrivacy.title;</html:h1> </hbox> @@ -96,17 +95,18 @@ <hbox align="center"> <label id="historyModeLabel" control="historyMode" accesskey="&historyHeader.pre.accesskey;">&historyHeader.pre.label; </label> <menulist id="historyMode" oncommand="gPrivacyPane.updateHistoryModePane(); gPrivacyPane.updateHistoryModePrefs(); - gPrivacyPane.updatePrivacyMicroControls();"> + gPrivacyPane.updatePrivacyMicroControls(); + gPrivacyPane.updateAutostart();"> <menupopup> <menuitem label="&historyHeader.remember.label;" value="remember"/> <menuitem label="&historyHeader.dontremember.label;" value="dontremember"/> <menuitem label="&historyHeader.custom.label;" value="custom"/> </menupopup> </menulist> <label>&historyHeader.post.label;</label> </hbox> @@ -143,17 +143,18 @@ </hbox> </vbox> <vbox id="historyCustomPane"> <separator class="thin"/> <vbox class="indent"> <checkbox id="privateBrowsingAutoStart" label="&privateBrowsingPermanent2.label;" accesskey="&privateBrowsingPermanent2.accesskey;" - preference="browser.privatebrowsing.autostart"/> + preference="browser.privatebrowsing.autostart" + oncommand="gPrivacyPane.updateAutostart()"/> <vbox class="indent"> <checkbox id="rememberHistory" label="&rememberHistory2.label;" accesskey="&rememberHistory2.accesskey;" preference="places.history.enabled"/> <checkbox id="rememberForms" label="&rememberSearchForm.label;"
--- a/browser/components/preferences/privacy.js +++ b/browser/components/preferences/privacy.js @@ -22,19 +22,17 @@ var gPrivacyPane = { * label of the "Clear Now..." button. */ init: function () { this._updateSanitizeSettingsButton(); this.initializeHistoryMode(); this.updateHistoryModePane(); this.updatePrivacyMicroControls(); - this.initAutoStartPrivateBrowsingObserver(); - - window.addEventListener("unload", this.removeASPBObserver.bind(this), false); + this.initAutoStartPrivateBrowsingReverter(); }, // HISTORY MODE /** * The list of preferences which affect the initial history mode settings. * If the auto start private browsing mode pref is active, the initial * history mode would be set to "Don't remember anything". @@ -230,88 +228,82 @@ var gPrivacyPane = { this._updateSanitizeSettingsButton(); } } }, // PRIVATE BROWSING /** - * Install the observer for the auto-start private browsing mode pref. + * Initialize the starting state for the auto-start private browsing mode pref reverter. */ - initAutoStartPrivateBrowsingObserver: function PPP_initAutoStartPrivateBrowsingObserver() + initAutoStartPrivateBrowsingReverter: function PPP_initAutoStartPrivateBrowsingReverter() { - let prefService = document.getElementById("privacyPreferences") - .service - .QueryInterface(Components.interfaces.nsIPrefBranch); - prefService.addObserver("browser.privatebrowsing.autostart", - this.autoStartPrivateBrowsingObserver, - false); + let mode = document.getElementById("historyMode"); + let autoStart = document.getElementById("privateBrowsingAutoStart"); + this._lastMode = mode.selectedIndex; + this._lastCheckState = autoStart.hasAttribute('checked'); }, - /** - * Install the observer for the auto-start private browsing mode pref. - */ - removeASPBObserver: function PPP_removeASPBObserver() - { - let prefService = document.getElementById("privacyPreferences") - .service - .QueryInterface(Components.interfaces.nsIPrefBranch); - prefService.removeObserver("browser.privatebrowsing.autostart", - this.autoStartPrivateBrowsingObserver); - }, + _lastMode: null, + _lasCheckState: null, + updateAutostart: function PPP_updateAutostart() { + let mode = document.getElementById("historyMode"); + let autoStart = document.getElementById("privateBrowsingAutoStart"); + let pref = document.getElementById("browser.privatebrowsing.autostart"); + if ((mode.value == "custom" && this._lastCheckState == autoStart.checked) || + (mode.value == "remember" && !this._lastCheckState) || + (mode.value == "dontremember" && this._lastCheckState)) { + // These are all no-op changes, so we don't need to prompt. + this._lastMode = mode.selectedIndex; + this._lastCheckState = autoStart.hasAttribute('checked'); + return; + } - autoStartPrivateBrowsingObserver: - { - QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]), - - observe: function PPP_observe(aSubject, aTopic, aData) - { - if (!gPrivacyPane._shouldPromptForRestart) { + if (!this._shouldPromptForRestart) { // We're performing a revert. Just let it happen. - gPrivacyPane._shouldPromptForRestart = true; return; } const Cc = Components.classes, Ci = Components.interfaces; - let pref = document.getElementById("browser.privatebrowsing.autostart"); let brandName = document.getElementById("bundleBrand").getString("brandShortName"); let bundle = document.getElementById("bundlePreferences"); let msg = bundle.getFormattedString(pref.value ? "featureEnableRequiresRestart" : "featureDisableRequiresRestart", [brandName]); let title = bundle.getFormattedString("shouldRestartTitle", [brandName]); let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService); let shouldProceed = prompts.confirm(window, title, msg) if (shouldProceed) { let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"] .createInstance(Ci.nsISupportsPRBool); Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart"); shouldProceed = !cancelQuit.data; if (shouldProceed) { + document.documentElement.acceptDialog(); let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"] .getService(Ci.nsIAppStartup); appStartup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); return; } } - gPrivacyPane._shouldPromptForRestart = false; - pref.value = !pref.value; + + this._shouldPromptForRestart = false; - let mode = document.getElementById("historyMode"); - if (mode.value != "custom") { - mode.selectedIndex = pref.value ? 1 : 0; - mode.doCommand(); + if (this._lastCheckState) { + autoStart.checked = "checked"; } else { - let rememberHistoryCheckbox = document.getElementById("rememberHistory"); - rememberHistory.checked = pref.value; + autoStart.removeAttribute('checked'); } - } + mode.selectedIndex = this._lastMode; + mode.doCommand(); + + this._shouldPromptForRestart = true; }, // HISTORY /** * Read the location bar enabled and suggestion prefs * @return Int value for suggestion menulist */
--- a/browser/components/preferences/privacy.xul +++ b/browser/components/preferences/privacy.xul @@ -68,17 +68,16 @@ <preference id="privacy.sanitize.timeSpan" name="privacy.sanitize.timeSpan" type="int"/> <!-- Private Browsing --> <preference id="browser.privatebrowsing.autostart" name="browser.privatebrowsing.autostart" onchange="gPrivacyPane.updatePrivacyMicroControls();" - instantApply="true" type="bool"/> </preferences> <stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences/preferences.properties"/> <script type="application/javascript" src="chrome://browser/content/preferences/privacy.js"/> @@ -108,17 +107,18 @@ <hbox align="center"> <label id="historyModeLabel" control="historyMode" accesskey="&historyHeader.pre.accesskey;">&historyHeader.pre.label;</label> <menulist id="historyMode" oncommand="gPrivacyPane.updateHistoryModePane(); gPrivacyPane.updateHistoryModePrefs(); - gPrivacyPane.updatePrivacyMicroControls();"> + gPrivacyPane.updatePrivacyMicroControls(); + gPrivacyPane.updateAutostart();"> <menupopup> <menuitem label="&historyHeader.remember.label;" value="remember"/> <menuitem label="&historyHeader.dontremember.label;" value="dontremember"/> <menuitem label="&historyHeader.custom.label;" value="custom"/> </menupopup> </menulist> <label>&historyHeader.post.label;</label> </hbox> @@ -155,17 +155,18 @@ <spacer flex="1" class="indent"/> </hbox> </vbox> <vbox id="historyCustomPane"> <separator class="thin"/> <checkbox id="privateBrowsingAutoStart" class="indent" label="&privateBrowsingPermanent2.label;" accesskey="&privateBrowsingPermanent2.accesskey;" - preference="browser.privatebrowsing.autostart"/> + preference="browser.privatebrowsing.autostart" + oncommand="gPrivacyPane.updateAutostart()"/> <vbox class="indent"> <vbox class="indent"> <checkbox id="rememberHistory" label="&rememberHistory2.label;" accesskey="&rememberHistory2.accesskey;" preference="places.history.enabled"/> <checkbox id="rememberForms"
--- a/browser/components/sessionstore/Makefile.in +++ b/browser/components/sessionstore/Makefile.in @@ -6,16 +6,15 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = sessionstore -XPIDL_MODULE = sessionstore XPIDLSRCS = \ nsISessionStartup.idl \ nsISessionStore.idl \ $(NULL) include $(topsrcdir)/config/rules.mk
--- a/browser/components/shell/public/Makefile.in +++ b/browser/components/shell/public/Makefile.in @@ -6,17 +6,16 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = shellservice -XPIDL_MODULE = shellservice XPIDLSRCS = nsIShellService.idl ifeq ($(OS_ARCH),WINNT) XPIDLSRCS += nsIWindowsShellService.idl endif ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
--- a/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js +++ b/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js @@ -268,19 +268,28 @@ function test() executeSoon(function() { info("remove the second breakpoint using the mouse"); gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveSecond); let iframe = gEditor.editorElement; let testWin = iframe.ownerDocument.defaultView; + // flush the layout for the iframe info("rect " + iframe.contentDocument.documentElement.getBoundingClientRect()); - EventUtils.synthesizeMouse(iframe, 10, 70, {}, testWin); + + let utils = testWin.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + + let rect = iframe.getBoundingClientRect(); + let left = rect.left + 10; + let top = rect.top + 70; + utils.sendMouseEventToWindow("mousedown", left, top, 0, 1, 0, false, 0, 0); + utils.sendMouseEventToWindow("mouseup", left, top, 0, 1, 0, false, 0, 0); }); } function onEditorBreakpointRemoveSecond(aEvent) { gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveSecond);
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595350_multiple_windows_and_tabs.js @@ -94,16 +94,17 @@ function closeConsoles() { openTabs = win1 = win2 = null; function onTimeout() { Services.obs.removeObserver(onWebConsoleClose, "web-console-destroyed"); executeSoon(finishTest); } waitForSuccess({ + timeout: 10000, name: "4 web consoles closed", validatorFn: function() { return consolesClosed == 4; }, successFn: onTimeout, failureFn: onTimeout, });
--- a/browser/fuel/public/Makefile.in +++ b/browser/fuel/public/Makefile.in @@ -5,13 +5,12 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = fuel -XPIDL_MODULE = fuel XPIDLSRCS = fuelIApplication.idl include $(topsrcdir)/config/rules.mk
--- a/browser/metro/base/content/Util.js +++ b/browser/metro/base/content/Util.js @@ -32,16 +32,54 @@ let Util = { }, // Put the Mozilla networking code into a state that will kick the // auto-connection process. forceOnline: function forceOnline() { Services.io.offline = false; }, + // Pass several objects in and it will combine them all into the first object and return it. + // NOTE: Deep copy is not supported + extend: function extend() { + // copy reference to target object + let target = arguments[0] || {}; + let length = arguments.length; + + if (length === 1) { + return target; + } + + // Handle case when target is a string or something + if (typeof target != "object" && typeof target != "function") { + target = {}; + } + + for (let i = 1; i < length; i++) { + // Only deal with non-null/undefined values + let options = arguments[i]; + if (options != null) { + // Extend the base object + for (let name in options) { + let copy = options[name]; + + // Prevent never-ending loop + if (target === copy) + continue; + + if (copy !== undefined) + target[name] = copy; + } + } + } + + // Return the modified object + return target; + }, + /* * Timing utilties */ // Executes aFunc after other events have been processed. executeSoon: function executeSoon(aFunc) { Services.tm.mainThread.dispatch({ run: function() {
--- a/browser/metro/base/content/contenthandlers/Content.js +++ b/browser/metro/base/content/contenthandlers/Content.js @@ -380,16 +380,17 @@ let Content = { let manifestURI = Services.io.newURI(json.manifest, json.charset, currentURI); let updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"] .getService(Ci.nsIOfflineCacheUpdateService); updateService.scheduleUpdate(manifestURI, currentURI, content); break; } case "Browser:SetCharset": { + docShell.gatherCharsetMenuTelemetry(); docShell.charset = json.charset; let webNav = docShell.QueryInterface(Ci.nsIWebNavigation); webNav.reload(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE); break; } case "Browser:PanBegin":
--- a/browser/metro/base/content/helperui/MenuUI.js +++ b/browser/metro/base/content/helperui/MenuUI.js @@ -70,16 +70,23 @@ var AutofillMenuUI = { hide: function hide () { this._menuPopup.hide(); } }; var ContextMenuUI = { _popupState: null, __menuPopup: null, + _defaultPositionOptions: { + forcePosition: true, + bottomAligned: true, + rightAligned: false, + centerHorizontally: true, + moveBelowToFit: true + }, get _panel() { return document.getElementById("context-container"); }, get _popup() { return document.getElementById("context-popup"); }, get _commands() { return this._popup.childNodes[0]; }, get _menuPopup() { if (!this.__menuPopup) this.__menuPopup = new MenuPopup(this._panel, this._popup); @@ -177,17 +184,21 @@ var ContextMenuUI = { } } if (!optionsAvailable) { this._popupState = null; return false; } - this._menuPopup.show(this._popupState); + this._menuPopup.show(Util.extend({}, this._defaultPositionOptions, { + xPos: aMessage.json.xPos, + yPos: aMessage.json.yPos, + source: aMessage.json.source + })); return true; }, hide: function hide () { this._menuPopup.hide(); this._popupState = null; }, @@ -374,33 +385,33 @@ MenuPopup.prototype = { this._panel.removeAttribute("showing"); }, _position: function _position(aPositionOptions) { let aX = aPositionOptions.xPos; let aY = aPositionOptions.yPos; let aSource = aPositionOptions.source; - let forcePosition = aPositionOptions.forcePosition || false; - let isRightAligned = aPositionOptions.rightAligned || false; - let isBottomAligned = aPositionOptions.bottomAligned || false; let width = this._popup.boxObject.width; let height = this._popup.boxObject.height; let halfWidth = width / 2; let halfHeight = height / 2; let screenWidth = ContentAreaObserver.width; let screenHeight = ContentAreaObserver.height; - if (forcePosition) { - if (isRightAligned) + if (aPositionOptions.forcePosition) { + if (aPositionOptions.rightAligned) aX -= width; - if (isBottomAligned) + if (aPositionOptions.bottomAligned) aY -= height; + + if (aPositionOptions.centerHorizontally) + aX -= halfWidth; } else { let leftHand = MetroUtils.handPreference == MetroUtils.handPreferenceLeft; // Add padding on the side of the menu per the user's hand preference if (aSource && aSource == Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH) { if (leftHand) { this._commands.setAttribute("left-hand", true); this._commands.removeAttribute("right-hand"); @@ -441,18 +452,22 @@ MenuPopup.prototype = { } else { dump('None, left hand: ' + leftHand + '!\n'); } } if (aX < 0) aX = 0; - if (aY < 0) + if (aY < 0 && aPositionOptions.moveBelowToFit) { + // show context menu below when it doesn't fit. + aY = aPositionOptions.yPos; + } else if (aY < 0) { aY = 0; + } this._panel.left = aX; this._panel.top = aY; let excessY = (aY + height + kPositionPadding - screenHeight); this._popup.style.maxHeight = (excessY > 0) ? (height - excessY) + "px" : "none"; let excessX = (aX + width + kPositionPadding - screenWidth);
--- a/browser/metro/base/tests/Makefile.in +++ b/browser/metro/base/tests/Makefile.in @@ -4,17 +4,16 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ relativesrcdir = @relativesrcdir@ include $(DEPTH)/config/autoconf.mk -include $(topsrcdir)/config/rules.mk BROWSER_TESTS = \ head.js \ browser_test.js \ browser_canonizeURL.js \ browser_context_ui.js \ browser_onscreen_keyboard.js \ browser_onscreen_keyboard.html \ @@ -29,13 +28,26 @@ BROWSER_TESTS = \ browser_context_menu_tests_03.html \ text-block.html \ $(NULL) BROWSER_TEST_RESOURCES = \ res/image01.png \ $(NULL) +XPCSHELL_TESTS = unit + +# For now we're copying the actual Util code. +# We should make this into a jsm module. See bug 848137 +XPCSHELL_RESOURCES = \ + $(DEPTH)/browser/metro/base/content/Util.js \ + $(NULL) + libs:: $(BROWSER_TESTS) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/metro/ libs:: $(BROWSER_TEST_RESOURCES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/metro/res + +libs:: $(XPCSHELL_RESOURCES) + $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/ + +include $(topsrcdir)/config/rules.mk
--- a/browser/metro/base/tests/browser_context_menu_tests.js +++ b/browser/metro/base/tests/browser_context_menu_tests.js @@ -1,9 +1,9 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*- /* vim: set ts=2 et sw=2 tw=80: */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; function debugClipFlavors(aClip) { @@ -21,16 +21,24 @@ function debugClipFlavors(aClip) } // XXX won't work with out of process content function emptyClipboard() { Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard) .emptyClipboard(Ci.nsIClipboard.kGlobalClipboard); } +function checkContextMenuPositionRange(aElement, aMinLeft, aMaxLeft, aMinTop, aMaxTop) { + ok(aElement.left > aMinLeft && aElement.left < aMaxLeft, + "Left position is " + aElement.left + ", expected between " + aMinLeft + " and " + aMaxLeft); + + ok(aElement.top > aMinTop && aElement.top < aMaxTop, + "Top position is " + aElement.top + ", expected between " + aMinTop + " and " + aMaxTop); +} + gTests.push({ desc: "text context menu", run: function test() { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); info(chromeRoot + "browser_context_menu_tests_02.html"); yield addTab(chromeRoot + "browser_context_menu_tests_02.html"); @@ -419,72 +427,68 @@ gTests.push({ let promise = waitForEvent(document, "popupshown"); sendContextMenuClickToElement(frame1.contentDocument.defaultView, link1, 85, 10); yield promise; ok(promise && !(promise instanceof Error), "promise error"); // should be visible ok(ContextMenuUI._menuPopup._visible, "is visible"); - ok(ContextMenuUI._panel.left > 375 && ContextMenuUI._panel.left < 390, "position"); - ok(ContextMenuUI._panel.top > 235 && ContextMenuUI._panel.top < 245, "position"); + checkContextMenuPositionRange(ContextMenuUI._panel, 560, 570, 175, 190); promise = waitForEvent(document, "popuphidden"); ContextMenuUI.hide(); yield promise; ok(promise && !(promise instanceof Error), "promise error"); frame1.contentDocument.defaultView.scrollBy(0, 200); promise = waitForEvent(document, "popupshown"); sendContextMenuClickToElement(frame1.contentDocument.defaultView, link1, 85, 10); yield promise; ok(promise && !(promise instanceof Error), "promise error"); // should be visible ok(ContextMenuUI._menuPopup._visible, "is visible"); - ok(ContextMenuUI._panel.left > 375 && ContextMenuUI._panel.left < 390, "position"); - ok(ContextMenuUI._panel.top > 35 && ContextMenuUI._panel.top < 45, "position"); + checkContextMenuPositionRange(ContextMenuUI._panel, 560, 570, 95, 110); promise = waitForEvent(document, "popuphidden"); ContextMenuUI.hide(); yield promise; ok(promise && !(promise instanceof Error), "promise error"); let rlink1 = win.document.getElementById("rlink1"); promise = waitForEvent(document, "popupshown"); sendContextMenuClickToElement(win, rlink1, 40, 10); yield promise; ok(promise && !(promise instanceof Error), "promise error"); // should be visible ok(ContextMenuUI._menuPopup._visible, "is visible"); - ok(ContextMenuUI._panel.left > 730 && ContextMenuUI._panel.left < 745, "position"); - ok(ContextMenuUI._panel.top > 600 && ContextMenuUI._panel.top < 610, "position"); + checkContextMenuPositionRange(ContextMenuUI._panel, 910, 925, 540, 555); promise = waitForEvent(document, "popuphidden"); ContextMenuUI.hide(); yield promise; ok(promise && !(promise instanceof Error), "promise error"); win.scrollBy(0, 200); promise = waitForEvent(document, "popupshown"); sendContextMenuClickToElement(win, rlink1, 40, 10); yield promise; ok(promise && !(promise instanceof Error), "promise error"); // should be visible ok(ContextMenuUI._menuPopup._visible, "is visible"); - ok(ContextMenuUI._panel.left > 730 && ContextMenuUI._panel.left < 745, "position"); - ok(ContextMenuUI._panel.top > 400 && ContextMenuUI._panel.top < 410, "position"); + checkContextMenuPositionRange(ContextMenuUI._panel, 910, 925, 340, 355); promise = waitForEvent(document, "popuphidden"); ContextMenuUI.hide(); yield promise; ok(promise && !(promise instanceof Error), "promise error"); let link2 = frame1.contentDocument.getElementById("link2"); @@ -494,18 +498,17 @@ gTests.push({ ok(promise && !(promise instanceof Error), "promise error"); // should be visible ok(ContextMenuUI._menuPopup._visible, "is visible"); info(ContextMenuUI._panel.left); info(ContextMenuUI._panel.top); - ok(ContextMenuUI._panel.left > 380 && ContextMenuUI._panel.left < 390, "position"); - ok(ContextMenuUI._panel.top > 170 && ContextMenuUI._panel.top < 185, "position"); + checkContextMenuPositionRange(ContextMenuUI._panel, 560, 570, 110, 125); promise = waitForEvent(document, "popuphidden"); ContextMenuUI.hide(); yield promise; ok(promise && !(promise instanceof Error), "promise error"); } });
new file mode 100644 --- /dev/null +++ b/browser/metro/base/tests/unit/test_util_extend.js @@ -0,0 +1,38 @@ +load('Util.js'); + +function run_test() { + do_print("Testing Util.extend"); + + do_print("Check if function is defined"); + do_check_true(!!Util.extend); + + do_print("No parameter or null should return a new object"); + let noArgRes = Util.extend(); + do_check_true(noArgRes && typeof noArgRes == "object"); + + let nullRes = Util.extend(null); + do_check_true(nullRes && typeof nullRes == "object"); + + do_print("Simple extend"); + let simpleExtend = {a: 1, b: 2}; + let simpleExtendResult = Util.extend(simpleExtend, {b: 3, c: 4}); + + do_check_true(simpleExtend.a === 1 && simpleExtend.b === 3 && simpleExtend.c === 4); + do_check_true(simpleExtendResult === simpleExtend); + + do_print("Cloning"); + let cloneExtend = {a: 1, b: 2}; + let cloned = Util.extend({}, cloneExtend); + + do_check_true(cloneExtend.a === cloned.a && cloneExtend.b === cloned.b); + do_check_true(cloneExtend !== cloned); + + do_print("Multiple extend"); + let multiExtend1 = {a: 1, b: 2}; + let multiExtend2 = {c: 3, d: 4}; + let multiExtend3 = {b: 5, e: 6}; + let multiExtend4 = {e: 7, a: 8}; + let multiResult = Util.extend({}, multiExtend1, multiExtend2, multiExtend3, multiExtend4); + + do_check_true(multiResult.a === 8 && multiResult.b === 5 && multiResult.c === 3 && multiResult.d === 4 && multiResult.e === 7); +}
new file mode 100644 --- /dev/null +++ b/browser/metro/base/tests/unit/xpcshell.ini @@ -0,0 +1,5 @@ +[DEFAULT] +head = +tail = + +[test_util_extend.js]
--- a/browser/metro/components/Makefile.in +++ b/browser/metro/components/Makefile.in @@ -7,17 +7,16 @@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk # metro/components.manifest MODULE = components -XPIDL_MODULE = components XPIDLSRCS = \ SessionStore.idl \ LoginManagerPrompter.idl \ $(NULL) EXTRA_PP_COMPONENTS = \ components.manifest \
--- a/browser/modules/Social.jsm +++ b/browser/modules/Social.jsm @@ -28,16 +28,17 @@ function prefObserver(subject, topic, da Services.prefs.addObserver("social.enabled", prefObserver, false); Services.obs.addObserver(function xpcomShutdown() { Services.obs.removeObserver(xpcomShutdown, "xpcom-shutdown"); Services.prefs.removeObserver("social.enabled", prefObserver); }, "xpcom-shutdown", false); this.Social = { + initialized: false, lastEventReceived: 0, providers: null, _disabledForSafeMode: false, get _currentProviderPref() { try { return Services.prefs.getComplexValue("social.provider.current", Ci.nsISupportsString).data; @@ -92,19 +93,20 @@ this.Social = { return null; let provider = this._getProviderFromOrigin(this._currentProviderPref); return provider || this.providers[0]; }, init: function Social_init() { this._disabledForSafeMode = Services.appinfo.inSafeMode && this.enabled; - if (this.providers) { + if (this.initialized) { return; } + this.initialized = true; // Retrieve the current set of providers, and set the current provider. SocialService.getProviderList(function (providers) { this._updateProviderCache(providers); }.bind(this)); // Register an observer for changes to the provider list SocialService.registerProviderListener(function providerListener(topic, data) { @@ -115,19 +117,22 @@ this.Social = { } }.bind(this)); }, // Called to update our cache of providers and set the current provider _updateProviderCache: function (providers) { this.providers = providers; - // If social is currently disabled there's nothing else to do. - if (!SocialService.enabled) + // If social is currently disabled there's nothing else to do other than + // to notify about the lack of a provider. + if (!SocialService.enabled) { + Services.obs.notifyObservers(null, "social:provider-set", null); return; + } // Otherwise set the provider. this._setProvider(this.defaultProvider); }, set enabled(val) { // Setting .enabled is just a shortcut for setting the provider to either // the default provider or null... if (val) {
--- a/build/mach_bootstrap.py +++ b/build/mach_bootstrap.py @@ -1,9 +1,8 @@ -#!/usr/bin/env python # 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/. from __future__ import print_function, unicode_literals import os import platform @@ -36,27 +35,30 @@ MACH_MODULES = [ 'python/mozbuild/mozbuild/config.py', 'python/mozbuild/mozbuild/mach_commands.py', 'python/mozbuild/mozbuild/frontend/mach_commands.py', 'testing/mochitest/mach_commands.py', 'testing/xpcshell/mach_commands.py', 'tools/mach_commands.py', ] -def bootstrap(topsrcdir): +def bootstrap(topsrcdir, mozilla_dir=None): + if mozilla_dir is None: + mozilla_dir = topsrcdir + # Ensure we are running Python 2.7+. We put this check here so we generate a # user-friendly error message rather than a cryptic stack trace on module # import. if sys.version_info[0] != 2 or sys.version_info[1] < 7: print('Python 2.7 or above (but not Python 3) is required to run mach.') print('You are running Python', platform.python_version()) sys.exit(1) try: import mach.main except ImportError: - sys.path[0:0] = [os.path.join(topsrcdir, path) for path in SEARCH_PATHS] + sys.path[0:0] = [os.path.join(mozilla_dir, path) for path in SEARCH_PATHS] import mach.main mach = mach.main.Mach(topsrcdir) for path in MACH_MODULES: - mach.load_commands_from_file(os.path.join(topsrcdir, path)) + mach.load_commands_from_file(os.path.join(mozilla_dir, path)) return mach
--- a/build/mobile/b2gautomation.py +++ b/build/mobile/b2gautomation.py @@ -235,17 +235,17 @@ class B2GRemoteAutomation(Automation): raise Exception("network did not come up, please configure the network" + " prior to running before running the automation framework") # stop b2g self._devicemanager._runCmd(['shell', 'stop', 'b2g']) time.sleep(5) # relaunch b2g inside b2g instance - instance = self.B2GInstance(self._devicemanager) + instance = self.B2GInstance(self._devicemanager, env=env) time.sleep(5) # Set up port forwarding again for Marionette, since any that # existed previously got wiped out by the reboot. if not self._is_emulator: self._devicemanager._checkCmd(['forward', 'tcp:%s' % self.marionette.port, @@ -293,29 +293,32 @@ class B2GRemoteAutomation(Automation): # be careful here as this inner class doesn't have access to outer class members class B2GInstance(object): """Represents a B2G instance running on a device, and exposes some process-like methods/properties that are expected by the automation. """ - def __init__(self, dm): + def __init__(self, dm, env=None): self.dm = dm + self.env = env or {} self.stdout_proc = None self.queue = Queue.Queue() # Launch b2g in a separate thread, and dump all output lines # into a queue. The lines in this queue are # retrieved and returned by accessing the stdout property of # this class. cmd = [self.dm._adbPath] if self.dm._deviceSerial: cmd.extend(['-s', self.dm._deviceSerial]) cmd.append('shell') + for k, v in self.env.iteritems(): + cmd.append("%s=%s" % (k, v)) cmd.append('/system/bin/b2g.sh') proc = threading.Thread(target=self._save_stdout_proc, args=(cmd, self.queue)) proc.daemon = True proc.start() def _save_stdout_proc(self, cmd, queue): self.stdout_proc = StdOutProc(cmd, queue) self.stdout_proc.run()
--- a/build/unix/stdc++compat/stdc++compat.cpp +++ b/build/unix/stdc++compat/stdc++compat.cpp @@ -29,16 +29,17 @@ namespace std { template ostream& ostream::_M_insert(bool); template ostream& ostream::_M_insert(const void*); template ostream& __ostream_insert(ostream&, const char*, streamsize); template istream& istream::_M_extract(double&); template istream& istream::_M_extract(float&); template istream& istream::_M_extract(unsigned int&); template istream& istream::_M_extract(unsigned long&); template istream& istream::_M_extract(unsigned short&); + template istream& istream::_M_extract(unsigned long long&); #endif #if MOZ_LIBSTDCXX_VERSION >= GLIBCXX_VERSION(3, 4, 14) /* Instantiate these templates to avoid GLIBCXX_3.4.14 symbol versions * depending on optimization level */ template char *string::_S_construct_aux_2(size_type, char, allocator<char> const&); #ifdef _GLIBCXX_USE_WCHAR_T template wchar_t *wstring::_S_construct_aux_2(size_type, wchar_t, allocator<wchar_t> const&); #endif /* _GLIBCXX_USE_WCHAR_T */
--- a/configure.in +++ b/configure.in @@ -5976,19 +5976,22 @@ if test -n "$MOZ_CRASHREPORTER"; then AC_SUBST(MOZ_GTHREAD_CFLAGS) AC_SUBST(MOZ_GTHREAD_LIBS) fi if test "$OS_ARCH" != "$HOST_OS_ARCH"; then AC_MSG_ERROR([Breakpad tools do not support compiling on $HOST_OS_ARCH while targeting $OS_ARCH. Use --disable-crashreporter.]) fi - if test "$OS_ARCH" = "WINNT" -a -z "$HAVE_64BIT_OS"; then - MOZ_CRASHREPORTER_INJECTOR=1 - AC_DEFINE(MOZ_CRASHREPORTER_INJECTOR) + if test "$OS_ARCH" = "WINNT"; then + AC_DEFINE_UNQUOTED(BREAKPAD_CUSTOM_STDINT_H, "mozilla/StandardInteger.h") + if test -z "$HAVE_64BIT_OS"; then + MOZ_CRASHREPORTER_INJECTOR=1 + AC_DEFINE(MOZ_CRASHREPORTER_INJECTOR) + fi fi fi MOZ_ARG_WITH_STRING(crashreporter-enable-percent, [ --with-crashreporter-enable-percent=NN Enable sending crash reports by default on NN% of users. (default=100)], [ val=`echo $withval | sed 's/[^0-9]//g'` MOZ_CRASHREPORTER_ENABLE_PERCENT="$val"])
--- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -358,17 +358,19 @@ public: /** document fragments */ eDOCUMENT_FRAGMENT = 1 << 7, /** data nodes (comments, PIs, text). Nodes of this type always returns a non-null value for nsIContent::GetText() */ eDATA_NODE = 1 << 8, /** nsHTMLMediaElement */ eMEDIA = 1 << 9, /** animation elements */ - eANIMATION = 1 << 10 + eANIMATION = 1 << 10, + /** filter elements that implement SVGFilterPrimitiveStandardAttributes */ + eFILTER = 1 << 11 }; /** * API for doing a quick check if a content is of a given * type, such as Text, Document, Comment ... Use this when you can instead of * checking the tag. * * @param aFlags what types you want to test for (see above)
--- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -7614,17 +7614,17 @@ nsDocument::CanSavePresentation(nsIReque #endif return false; } } } // Check if we have running IndexedDB transactions indexedDB::IndexedDatabaseManager* idbManager = - indexedDB::IndexedDatabaseManager::Get(); + win ? indexedDB::IndexedDatabaseManager::Get() : nullptr; if (idbManager && idbManager->HasOpenTransactions(win)) { return false; } #ifdef MOZ_WEBRTC // Check if we have active PeerConnections nsCOMPtr<IPeerConnectionManager> pcManager = do_GetService(IPEERCONNECTION_MANAGER_CONTRACTID);
--- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -78,16 +78,17 @@ nsImageLoadingContent::nsImageLoadingCon mImageBlockingStatus(nsIContentPolicy::ACCEPT), mLoadingEnabled(true), mIsImageStateForced(false), mLoading(false), // mBroken starts out true, since an image without a URI is broken.... mBroken(true), mUserDisabled(false), mSuppressed(false), + mFireEventsOnDecode(false), mNewRequestsWillNeedAnimationReset(false), mStateChangerDepth(0), mCurrentRequestRegistered(false), mPendingRequestRegistered(false), mVisibleCount(0) { if (!nsContentUtils::GetImgLoaderForChannel(nullptr)) { mLoadingEnabled = false; @@ -156,16 +157,30 @@ nsImageLoadingContent::Notify(imgIReques if (aType == imgINotificationObserver::LOAD_COMPLETE) { uint32_t reqStatus; aRequest->GetImageStatus(&reqStatus); nsresult status = reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK; return OnStopRequest(aRequest, status); } + if (aType == imgINotificationObserver::DECODE_COMPLETE && mFireEventsOnDecode) { + mFireEventsOnDecode = false; + + uint32_t reqStatus; + aRequest->GetImageStatus(&reqStatus); + if (reqStatus & imgIRequest::STATUS_ERROR) { + FireEvent(NS_LITERAL_STRING("error")); + } else { + FireEvent(NS_LITERAL_STRING("load")); + } + + UpdateImageState(true); + } + return NS_OK; } nsresult nsImageLoadingContent::OnStopRequest(imgIRequest* aRequest, nsresult aStatus) { uint32_t oldStatus; @@ -208,29 +223,44 @@ nsImageLoadingContent::OnStopRequest(img // (*) IsPaintingSuppressed returns false if we haven't gotten the initial // reflow yet, so we have to test !DidInitialize || IsPaintingSuppressed. // It's possible for painting to be suppressed for reasons other than the // initial paint delay (for example, being in the bfcache), but we probably // aren't loading images in those situations. // XXXkhuey should this be GetOurCurrentDoc? Decoding if we're not in // the document seems silly. + bool startedDecoding = false; nsIDocument* doc = GetOurOwnerDoc(); nsIPresShell* shell = doc ? doc->GetShell() : nullptr; if (shell && shell->IsVisible() && (!shell->DidInitialize() || shell->IsPaintingSuppressed())) { - mCurrentRequest->StartDecoding(); + if (NS_SUCCEEDED(mCurrentRequest->StartDecoding())) { + startedDecoding = true; + } } - // Fire the appropriate DOM event. - if (NS_SUCCEEDED(aStatus)) { - FireEvent(NS_LITERAL_STRING("load")); + // We want to give the decoder a chance to find errors. If we haven't found + // an error yet and we've started decoding, either from the above + // StartDecoding or from some other place, we must only fire these events + // after we finish decoding. + uint32_t reqStatus; + aRequest->GetImageStatus(&reqStatus); + if (NS_SUCCEEDED(aStatus) && !(reqStatus & imgIRequest::STATUS_ERROR) && + (reqStatus & imgIRequest::STATUS_DECODE_STARTED || + (startedDecoding && !(reqStatus & imgIRequest::STATUS_DECODE_COMPLETE)))) { + mFireEventsOnDecode = true; } else { - FireEvent(NS_LITERAL_STRING("error")); + // Fire the appropriate DOM event. + if (NS_SUCCEEDED(aStatus)) { + FireEvent(NS_LITERAL_STRING("load")); + } else { + FireEvent(NS_LITERAL_STRING("error")); + } } nsCOMPtr<nsINode> thisNode = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); nsSVGEffects::InvalidateDirectRenderingObservers(thisNode->AsElement()); return NS_OK; }
--- a/content/base/src/nsImageLoadingContent.h +++ b/content/base/src/nsImageLoadingContent.h @@ -392,16 +392,17 @@ private: /** * The state we had the last time we checked whether we needed to notify the * document of a state change. These are maintained by UpdateImageState. */ bool mLoading : 1; bool mBroken : 1; bool mUserDisabled : 1; bool mSuppressed : 1; + bool mFireEventsOnDecode : 1; protected: /** * A hack to get animations to reset, see bug 594771. On requests * that originate from setting .src, we mark them for needing their animation * reset when they are ready. mNewRequestsWillNeedAnimationReset is set to * true while preparing such requests (as a hack around needing to change an * interface), and the other two booleans store which of the current
--- a/content/base/src/nsNodeInfo.cpp +++ b/content/base/src/nsNodeInfo.cpp @@ -19,17 +19,16 @@ #include "nsCOMPtr.h" #include "nsString.h" #include "nsIAtom.h" #include "nsDOMString.h" #include "nsCRT.h" #include "nsContentUtils.h" #include "nsReadableUtils.h" #include "nsAutoPtr.h" -#include NEW_H #include "prprf.h" #include "nsIDocument.h" #include "nsGkAtoms.h" #include "nsCCUncollectableMarker.h" using namespace mozilla; nsNodeInfo::~nsNodeInfo()
--- a/content/events/src/nsEventDispatcher.cpp +++ b/content/events/src/nsEventDispatcher.cpp @@ -1,82 +1,101 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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 "nsEventDispatcher.h" #include "nsDOMEvent.h" #include "nsIDOMEventTarget.h" #include "nsPresContext.h" #include "nsEventListenerManager.h" #include "nsContentUtils.h" #include "nsError.h" #include "nsMutationEvent.h" #include NEW_H -#include "nsFixedSizeAllocator.h" #include "nsINode.h" #include "nsPIDOMWindow.h" #include "nsFrameLoader.h" #include "nsDOMTouchEvent.h" #include "nsDOMStorage.h" #include "sampler.h" #include "GeneratedEvents.h" using namespace mozilla; #define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0) #define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1) #define NS_TARGET_CHAIN_MAY_HAVE_MANAGER (1 << 2) -static nsEventTargetChainItem* gCachedETCI = nullptr; - // nsEventTargetChainItem represents a single item in the event target chain. class nsEventTargetChainItem { private: nsEventTargetChainItem(nsIDOMEventTarget* aTarget, nsEventTargetChainItem* aChild = nullptr); + // This is the ETCI recycle pool, which is used to avoid some malloc/free + // churn. It's implemented as a linked list. + static nsEventTargetChainItem* sEtciRecyclePool; + static uint32_t sNumRecycledEtcis; + static const uint32_t kMaxNumRecycledEtcis = 128; + public: - static nsEventTargetChainItem* Create(nsFixedSizeAllocator* aAllocator, - nsIDOMEventTarget* aTarget, + static nsEventTargetChainItem* Create(nsIDOMEventTarget* aTarget, nsEventTargetChainItem* aChild = nullptr) { + // Allocate from the ETCI recycle pool if possible. void* place = nullptr; - if (gCachedETCI) { - place = gCachedETCI; - gCachedETCI = gCachedETCI->mNext; + if (sNumRecycledEtcis > 0) { + MOZ_ASSERT(sEtciRecyclePool); + place = sEtciRecyclePool; + sEtciRecyclePool = sEtciRecyclePool->mNext; + --sNumRecycledEtcis; } else { - place = aAllocator->Alloc(sizeof(nsEventTargetChainItem)); + place = malloc(sizeof(nsEventTargetChainItem)); } return place ? ::new (place) nsEventTargetChainItem(aTarget, aChild) : nullptr; } - static void Destroy(nsFixedSizeAllocator* aAllocator, - nsEventTargetChainItem* aItem) + static void Destroy(nsEventTargetChainItem* aItem) { // ::Destroy deletes ancestor chain. nsEventTargetChainItem* item = aItem; if (item->mChild) { item->mChild->mParent = nullptr; item->mChild = nullptr; } + // Put destroyed ETCIs into the recycle pool if it's not already full. while (item) { nsEventTargetChainItem* parent = item->mParent; item->~nsEventTargetChainItem(); - item->mNext = gCachedETCI; - gCachedETCI = item; - --sCurrentEtciCount; + if (sNumRecycledEtcis < kMaxNumRecycledEtcis) { + item->mNext = sEtciRecyclePool; + sEtciRecyclePool = item; + ++sNumRecycledEtcis; + } else { + free(item); + } item = parent; } } + static void ShutdownRecyclePool() + { + while (sEtciRecyclePool) { + nsEventTargetChainItem* tmp = sEtciRecyclePool; + sEtciRecyclePool = sEtciRecyclePool->mNext; + free(tmp); + } + } + bool IsValid() { NS_WARN_IF_FALSE(!!(mTarget), "Event target is not valid!"); return !!(mTarget); } nsIDOMEventTarget* GetNewTarget() { @@ -200,46 +219,42 @@ public: MOZ_ASSERT(!sCurrentEtciCount, "Wrong time to call ResetMaxEtciCount()!"); sMaxEtciCount = 0; } nsCOMPtr<nsIDOMEventTarget> mTarget; nsEventTargetChainItem* mChild; union { nsEventTargetChainItem* mParent; - // This is used only when caching ETCI objects. + // This is used only when recycling ETCIs. nsEventTargetChainItem* mNext; }; uint16_t mFlags; uint16_t mItemFlags; nsCOMPtr<nsISupports> mItemData; // Event retargeting must happen whenever mNewTarget is non-null. nsCOMPtr<nsIDOMEventTarget> mNewTarget; // Cache mTarget's event listener manager. nsRefPtr<nsEventListenerManager> mManager; static uint32_t sMaxEtciCount; static uint32_t sCurrentEtciCount; }; -uint32_t nsEventTargetChainItem::sMaxEtciCount = 0; -uint32_t nsEventTargetChainItem::sCurrentEtciCount = 0; +nsEventTargetChainItem* nsEventTargetChainItem::sEtciRecyclePool = nullptr; +uint32_t nsEventTargetChainItem::sNumRecycledEtcis = 0; nsEventTargetChainItem::nsEventTargetChainItem(nsIDOMEventTarget* aTarget, nsEventTargetChainItem* aChild) : mTarget(aTarget), mChild(aChild), mParent(nullptr), mFlags(0), mItemFlags(0) { MOZ_ASSERT(!aTarget || mTarget == aTarget->GetTargetForEventTargetChain()); if (mChild) { mChild->mParent = this; } - - if (++sCurrentEtciCount > sMaxEtciCount) { - sMaxEtciCount = sCurrentEtciCount; - } } nsresult nsEventTargetChainItem::PreHandleEvent(nsEventChainPreVisitor& aVisitor) { aVisitor.Reset(); nsresult rv = mTarget->PreHandleEvent(aVisitor); SetForceContentDispatch(aVisitor.mForceContentDispatch); @@ -373,95 +388,38 @@ nsEventTargetChainItem::HandleEventTarge // system group listeners don't affect to the event. aVisitor.mEvent->mFlags.mPropagationStopped = false; aVisitor.mEvent->mFlags.mImmediatePropagationStopped = false; } return NS_OK; } -#define NS_CHAIN_POOL_SIZE 128 - -class ChainItemPool { -public: - ChainItemPool() { - if (!sEtciPool) { - sEtciPool = new nsFixedSizeAllocator(); - if (sEtciPool) { - static const size_t kBucketSizes[] = { sizeof(nsEventTargetChainItem) }; - static const int32_t kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t); - static const int32_t kInitialPoolSize = - sizeof(nsEventTargetChainItem) * NS_CHAIN_POOL_SIZE; - nsresult rv = sEtciPool->Init("EventTargetChainItem Pool", kBucketSizes, - kNumBuckets, kInitialPoolSize); - if (NS_FAILED(rv)) { - delete sEtciPool; - sEtciPool = nullptr; - } - } - } - if (sEtciPool) { - ++sEtciPoolUsers; - } - } - - ~ChainItemPool() { - if (sEtciPool) { - --sEtciPoolUsers; - } - if (!sEtciPoolUsers) { - if (nsEventTargetChainItem::MaxEtciCount() > NS_CHAIN_POOL_SIZE) { - gCachedETCI = nullptr; - delete sEtciPool; - sEtciPool = nullptr; - nsEventTargetChainItem::ResetMaxEtciCount(); - } - } - } - - static void Shutdown() - { - if (!sEtciPoolUsers) { - gCachedETCI = nullptr; - delete sEtciPool; - sEtciPool = nullptr; - nsEventTargetChainItem::ResetMaxEtciCount(); - } - } - - nsFixedSizeAllocator* GetPool() { return sEtciPool; } - - static nsFixedSizeAllocator* sEtciPool; - static int32_t sEtciPoolUsers; -}; - -nsFixedSizeAllocator* ChainItemPool::sEtciPool = nullptr; -int32_t ChainItemPool::sEtciPoolUsers = 0; - -void NS_ShutdownChainItemPool() { ChainItemPool::Shutdown(); } +void NS_ShutdownEventTargetChainItemRecyclePool() +{ + nsEventTargetChainItem::ShutdownRecyclePool(); +} nsEventTargetChainItem* -EventTargetChainItemForChromeTarget(ChainItemPool& aPool, - nsINode* aNode, +EventTargetChainItemForChromeTarget(nsINode* aNode, nsEventTargetChainItem* aChild = nullptr) { if (!aNode->IsInDoc()) { return nullptr; } nsPIDOMWindow* win = aNode->OwnerDoc()->GetInnerWindow(); nsIDOMEventTarget* piTarget = win ? win->GetParentTarget() : nullptr; NS_ENSURE_TRUE(piTarget, nullptr); nsEventTargetChainItem* etci = - nsEventTargetChainItem::Create(aPool.GetPool(), - piTarget->GetTargetForEventTargetChain(), + nsEventTargetChainItem::Create(piTarget->GetTargetForEventTargetChain(), aChild); NS_ENSURE_TRUE(etci, nullptr); if (!etci->IsValid()) { - nsEventTargetChainItem::Destroy(aPool.GetPool(), etci); + nsEventTargetChainItem::Destroy(etci); return nullptr; } return etci; } /* static */ nsresult nsEventDispatcher::Dispatch(nsISupports* aTarget, nsPresContext* aPresContext, @@ -546,26 +504,23 @@ nsEventDispatcher::Dispatch(nsISupports* #endif nsresult rv = NS_OK; bool externalDOMEvent = !!(aDOMEvent); // If we have a PresContext, make sure it doesn't die before // event dispatching is finished. nsRefPtr<nsPresContext> kungFuDeathGrip(aPresContext); - ChainItemPool pool; - NS_ENSURE_TRUE(pool.GetPool(), NS_ERROR_OUT_OF_MEMORY); // Create the event target chain item for the event target. nsEventTargetChainItem* targetEtci = - nsEventTargetChainItem::Create(pool.GetPool(), - target->GetTargetForEventTargetChain()); + nsEventTargetChainItem::Create(target->GetTargetForEventTargetChain()); NS_ENSURE_TRUE(targetEtci, NS_ERROR_OUT_OF_MEMORY); if (!targetEtci->IsValid()) { - nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci); + nsEventTargetChainItem::Destroy(targetEtci); return NS_ERROR_FAILURE; } // Make sure that nsIDOMEvent::target and nsIDOMEvent::originalTarget // point to the last item in the chain. if (!aEvent->target) { // Note, CurrentTarget() points always to the object returned by // GetTargetForEventTargetChain(). @@ -598,32 +553,31 @@ nsEventDispatcher::Dispatch(nsISupports* // PreHandleEvent for the original target. nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore; nsEventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status, isInAnon); targetEtci->PreHandleEvent(preVisitor); if (!preVisitor.mCanHandle && preVisitor.mAutomaticChromeDispatch && content) { // Event target couldn't handle the event. Try to propagate to chrome. - nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci); - targetEtci = EventTargetChainItemForChromeTarget(pool, content); + nsEventTargetChainItem::Destroy(targetEtci); + targetEtci = EventTargetChainItemForChromeTarget(content); NS_ENSURE_STATE(targetEtci); targetEtci->PreHandleEvent(preVisitor); } if (preVisitor.mCanHandle) { // At least the original target can handle the event. // Setting the retarget to the |target| simplifies retargeting code. nsCOMPtr<nsIDOMEventTarget> t = aEvent->target; targetEtci->SetNewTarget(t); nsEventTargetChainItem* topEtci = targetEtci; while (preVisitor.mParentTarget) { nsIDOMEventTarget* parentTarget = preVisitor.mParentTarget; nsEventTargetChainItem* parentEtci = - nsEventTargetChainItem::Create(pool.GetPool(), preVisitor.mParentTarget, - topEtci); + nsEventTargetChainItem::Create(preVisitor.mParentTarget, topEtci); if (!parentEtci) { rv = NS_ERROR_OUT_OF_MEMORY; break; } if (!parentEtci->IsValid()) { rv = NS_ERROR_FAILURE; break; } @@ -635,25 +589,24 @@ nsEventDispatcher::Dispatch(nsISupports* preVisitor.mEvent->target = preVisitor.mEventTargetAtParent; parentEtci->SetNewTarget(preVisitor.mEventTargetAtParent); } parentEtci->PreHandleEvent(preVisitor); if (preVisitor.mCanHandle) { topEtci = parentEtci; } else { - nsEventTargetChainItem::Destroy(pool.GetPool(), parentEtci); + nsEventTargetChainItem::Destroy(parentEtci); parentEtci = nullptr; if (preVisitor.mAutomaticChromeDispatch && content) { // Even if the current target can't handle the event, try to // propagate to chrome. nsCOMPtr<nsINode> disabledTarget = do_QueryInterface(parentTarget); if (disabledTarget) { - parentEtci = EventTargetChainItemForChromeTarget(pool, - disabledTarget, + parentEtci = EventTargetChainItemForChromeTarget(disabledTarget, topEtci); if (parentEtci) { parentEtci->PreHandleEvent(preVisitor); if (preVisitor.mCanHandle) { targetEtci->SetNewTarget(parentTarget); topEtci = parentEtci; continue; } @@ -674,27 +627,27 @@ nsEventDispatcher::Dispatch(nsISupports* } else { // Event target chain is created. Handle the chain. nsEventChainPostVisitor postVisitor(preVisitor); nsCxPusher pusher; rv = topEtci->HandleEventTargetChain(postVisitor, aCallback, false, &pusher); - + preVisitor.mEventStatus = postVisitor.mEventStatus; // If the DOM event was created during event flow. if (!preVisitor.mDOMEvent && postVisitor.mDOMEvent) { preVisitor.mDOMEvent = postVisitor.mDOMEvent; } } } } - nsEventTargetChainItem::Destroy(pool.GetPool(), targetEtci); + nsEventTargetChainItem::Destroy(targetEtci); targetEtci = nullptr; aEvent->mFlags.mIsBeingDispatched = false; aEvent->mFlags.mDispatchedAtLeastOnce = true; if (!externalDOMEvent && preVisitor.mDOMEvent) { // An nsDOMEvent was created while dispatching the event. // Duplicate private data if someone holds a pointer to it.
--- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -4148,42 +4148,53 @@ nsEventStateManager::NotifyMouseOver(nsG // Turn recursion protection back off mFirstMouseOverEventElement = nullptr; } // Returns the center point of the window's inner content area. // This is in widget coordinates, i.e. relative to the widget's top // left corner, not in screen coordinates, the same units that // nsDOMUIEvent::refPoint is in. +// +// XXX Hack alert: XXX +// However, we do the computation in integer CSS pixels, NOT device pix, +// in order to fudge around the one-pixel error in innerHeight in fullscreen +// mode (see bug 799523 comment 35, and bug 729011). Using integer CSS pix +// makes us throw away the fractional error that results, rather than having +// it manifest as a potential one-device-pix discrepancy. static nsIntPoint GetWindowInnerRectCenter(nsPIDOMWindow* aWindow, nsIWidget* aWidget, nsPresContext* aContext) { NS_ENSURE_TRUE(aWindow && aWidget && aContext, nsIntPoint(0,0)); float cssInnerX = 0.0; aWindow->GetMozInnerScreenX(&cssInnerX); - int32_t innerX = int32_t(NS_round(aContext->CSSPixelsToDevPixels(cssInnerX))); + int32_t innerX = int32_t(NS_round(cssInnerX)); float cssInnerY = 0.0; aWindow->GetMozInnerScreenY(&cssInnerY); - int32_t innerY = int32_t(NS_round(aContext->CSSPixelsToDevPixels(cssInnerY))); + int32_t innerY = int32_t(NS_round(cssInnerY)); int32_t innerWidth = 0; aWindow->GetInnerWidth(&innerWidth); int32_t innerHeight = 0; aWindow->GetInnerHeight(&innerHeight); - + nsIntRect screen; aWidget->GetScreenBounds(screen); - return nsIntPoint(innerX - screen.x + innerWidth / 2, - innerY - screen.y + innerHeight / 2); + int32_t cssScreenX = aContext->DevPixelsToIntCSSPixels(screen.x); + int32_t cssScreenY = aContext->DevPixelsToIntCSSPixels(screen.y); + + return nsIntPoint( + aContext->CSSPixelsToDevPixels(innerX - cssScreenX + innerWidth / 2), + aContext->CSSPixelsToDevPixels(innerY - cssScreenY + innerHeight / 2)); } void nsEventStateManager::GenerateMouseEnterExit(nsGUIEvent* aEvent) { EnsureDocument(mPresContext); if (!mDocument) return;
--- a/content/svg/content/src/Makefile.in +++ b/content/svg/content/src/Makefile.in @@ -74,16 +74,21 @@ CPPSRCS = \ SVGAttrValueWrapper.cpp \ SVGClipPathElement.cpp \ SVGCircleElement.cpp \ SVGContentUtils.cpp \ SVGDefsElement.cpp \ SVGDescElement.cpp \ SVGElementFactory.cpp \ SVGEllipseElement.cpp \ + SVGFEBlendElement.cpp \ + SVGFEFloodElement.cpp \ + SVGFEImageElement.cpp \ + SVGFEMergeElement.cpp \ + SVGFEMergeNodeElement.cpp \ SVGFilterElement.cpp \ SVGForeignObjectElement.cpp \ SVGFragmentIdentifier.cpp \ SVGGElement.cpp \ SVGGradientElement.cpp \ SVGGraphicsElement.cpp \ SVGImageElement.cpp \ SVGIntegerPairSMILType.cpp \ @@ -165,16 +170,21 @@ EXPORTS_mozilla/dom = \ SVGAnimateMotionElement.h \ SVGAnimationElement.h \ SVGClipPathElement.h \ SVGCircleElement.h \ SVGComponentTransferFunctionElement.h \ SVGDefsElement.h \ SVGDescElement.h \ SVGEllipseElement.h \ + SVGFEBlendElement.h \ + SVGFEFloodElement.h \ + SVGFEImageElement.h \ + SVGFEMergeElement.h \ + SVGFEMergeNodeElement.h \ SVGFilterElement.h \ SVGForeignObjectElement.h \ SVGGElement.h \ SVGGradientElement.h \ SVGGraphicsElement.h \ SVGImageElement.h \ SVGLineElement.h \ SVGMarkerElement.h \
copy from content/svg/content/src/nsSVGFilters.cpp copy to content/svg/content/src/SVGFEBlendElement.cpp --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/SVGFEBlendElement.cpp @@ -1,947 +1,89 @@ /* -*- 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 "mozilla/dom/SVGFEBlendElement.h" +#include "mozilla/dom/SVGFEBlendElementBinding.h" #include "nsSVGUtils.h" -#include "nsStyleContext.h" -#include "nsIDocument.h" -#include "nsIFrame.h" -#include "gfxContext.h" -#include "gfxMatrix.h" -#include "imgIContainer.h" -#include "nsNetUtil.h" -#include "nsIInterfaceRequestorUtils.h" -#include "mozilla/dom/SVGFilterElement.h" -#include "nsSVGString.h" -#include "nsSVGEffects.h" -#include "gfxUtils.h" -#include "SVGContentUtils.h" -#include <algorithm> -#include "nsContentUtils.h" -#include "mozilla/dom/SVGComponentTransferFunctionElement.h" -#include "mozilla/dom/SVGFEFuncAElementBinding.h" -#include "mozilla/dom/SVGFEFuncBElementBinding.h" -#include "mozilla/dom/SVGFEFuncGElementBinding.h" -#include "mozilla/dom/SVGFEFuncRElementBinding.h" - -#if defined(XP_WIN) -// Prevent Windows redefining LoadImage -#undef LoadImage -#endif - -#define NUM_ENTRIES_IN_4x5_MATRIX 20 - -using namespace mozilla; -using namespace mozilla::dom; - -static 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 -CopyRect(const nsSVGFE::Image* aDest, const nsSVGFE::Image* aSrc, const nsIntRect& aDataRect) -{ - NS_ASSERTION(aDest->mImage->Stride() == aSrc->mImage->Stride(), "stride mismatch"); - NS_ASSERTION(aDest->mImage->GetSize() == aSrc->mImage->GetSize(), "size mismatch"); - NS_ASSERTION(nsIntRect(0, 0, aDest->mImage->Width(), aDest->mImage->Height()).Contains(aDataRect), - "aDataRect out of bounds"); - - CopyDataRect(aDest->mImage->Data(), aSrc->mImage->Data(), - aSrc->mImage->Stride(), aDataRect); -} - -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; -} +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEBlend) -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) -{ - return mLengthAttributes[X].ToDOMAnimatedLength(aX, this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength y; */ -NS_IMETHODIMP nsSVGFE::GetY(nsIDOMSVGAnimatedLength * *aY) -{ - return mLengthAttributes[Y].ToDOMAnimatedLength(aY, this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength width; */ -NS_IMETHODIMP nsSVGFE::GetWidth(nsIDOMSVGAnimatedLength * *aWidth) -{ - return mLengthAttributes[WIDTH].ToDOMAnimatedLength(aWidth, this); -} - -/* readonly attribute nsIDOMSVGAnimatedLength height; */ -NS_IMETHODIMP nsSVGFE::GetHeight(nsIDOMSVGAnimatedLength * *aHeight) -{ - return mLengthAttributes[HEIGHT].ToDOMAnimatedLength(aHeight, this); -} - -/* readonly attribute nsIDOMSVGAnimatedString result; */ -NS_IMETHODIMP nsSVGFE::GetResult(nsIDOMSVGAnimatedString * *aResult) -{ - return GetResultImageName().ToDOMAnimatedString(aResult, 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[WIDTH].IsExplicitlySet() || - mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0) && - (!mLengthAttributes[HEIGHT].IsExplicitlySet() || - mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0); -} - -nsSVGElement::LengthAttributesInfo -nsSVGFE::GetLengthInfo() -{ - return LengthAttributesInfo(mLengthAttributes, sLengthInfo, - ArrayLength(sLengthInfo)); -} - -//---------------------Gaussian Blur------------------------ - -typedef nsSVGFE nsSVGFEGaussianBlurElementBase; +namespace mozilla { +namespace dom { -class nsSVGFEGaussianBlurElement : public nsSVGFEGaussianBlurElementBase, - public nsIDOMSVGFEGaussianBlurElement +JSObject* +SVGFEBlendElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap) { - friend nsresult NS_NewSVGFEGaussianBlurElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEGaussianBlurElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEGaussianBlurElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEGaussianBlurElementBase::) - - 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); - - // Gaussian - NS_DECL_NSIDOMSVGFEGAUSSIANBLURELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEGaussianBlurElementBase::) - - 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 NumberPairAttributesInfo GetNumberPairInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { STD_DEV }; - nsSVGNumberPair mNumberPairAttributes[1]; - static NumberPairInfo sNumberPairInfo[1]; - - enum { RESULT, IN1 }; - nsSVGString mStringAttributes[2]; - static StringInfo sStringInfo[2]; - -private: - nsresult GetDXY(uint32_t *aDX, uint32_t *aDY, const nsSVGFilterInstance& aInstance); - nsIntRect InflateRectForBlur(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance); - - void GaussianBlur(const Image *aSource, const Image *aTarget, - const nsIntRect& aDataRect, - uint32_t aDX, uint32_t aDY); -}; - -nsSVGElement::NumberPairInfo nsSVGFEGaussianBlurElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::stdDeviation, 0, 0 } -}; - -nsSVGElement::StringInfo nsSVGFEGaussianBlurElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEGaussianBlur) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEGaussianBlurElement,nsSVGFEGaussianBlurElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEGaussianBlurElement,nsSVGFEGaussianBlurElementBase) - -DOMCI_NODE_DATA(SVGFEGaussianBlurElement, nsSVGFEGaussianBlurElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEGaussianBlurElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEGaussianBlurElement, nsIDOMNode, - nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEGaussianBlurElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEGaussianBlurElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEGaussianBlurElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEGaussianBlurElement) - - -//---------------------------------------------------------------------- -// nsIDOMSVGFEGaussianBlurElement methods - -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFEGaussianBlurElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); + return SVGFEBlendElementBinding::Wrap(aCx, aScope, this, aTriedToWrap); } -/* readonly attribute nsIDOMSVGAnimatedNumber stdDeviationX; */ -NS_IMETHODIMP nsSVGFEGaussianBlurElement::GetStdDeviationX(nsIDOMSVGAnimatedNumber * *aX) -{ - return mNumberPairAttributes[STD_DEV].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber stdDeviationY; */ -NS_IMETHODIMP nsSVGFEGaussianBlurElement::GetStdDeviationY(nsIDOMSVGAnimatedNumber * *aY) -{ - return mNumberPairAttributes[STD_DEV].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this); -} - -NS_IMETHODIMP -nsSVGFEGaussianBlurElement::SetStdDeviation(float stdDeviationX, float stdDeviationY) -{ - NS_ENSURE_FINITE2(stdDeviationX, stdDeviationY, NS_ERROR_ILLEGAL_VALUE); - mNumberPairAttributes[STD_DEV].SetBaseValues(stdDeviationX, stdDeviationY, this); - return NS_OK; -} - -/** - * We want to speed up 1/N integer divisions --- integer division is - * often rather slow. - * We know that our input numerators V are constrained to be <= 255*N, - * so the result of dividing by N always fits in 8 bits. - * So we can try approximating the division V/N as V*K/(2^24) (integer - * division, 32-bit multiply). Dividing by 2^24 is a simple shift so it's - * fast. The main problem is choosing a value for K; this function returns - * K's value. - * - * If the result is correct for the extrema, V=0 and V=255*N, then we'll - * be in good shape since both the original function and our approximation - * are linear. V=0 always gives 0 in both cases, no problem there. - * For V=255*N, let's choose the largest K that doesn't cause overflow - * and ensure that it gives the right answer. The constraints are - * (1) 255*N*K < 2^32 - * and (2) 255*N*K >= 255*(2^24) - * - * From (1) we find the best value of K is floor((2^32 - 1)/(255*N)). - * (2) tells us when this will be valid: - * N*floor((2^32 - 1)/(255*N)) >= 2^24 - * Now, floor(X) > X - 1, so (2) holds if - * N*((2^32 - 1)/(255*N) - 1) >= 2^24 - * (2^32 - 1)/255 - 2^24 >= N - * N <= 65793 - * - * If all that math confuses you, this should convince you: - * > perl -e 'for($N=1;(255*$N*int(0xFFFFFFFF/(255*$N)))>>24==255;++$N){}print"$N\n"' - * 66052 - * - * So this is fine for all reasonable values of N. For larger values of N - * we may as well just use the same approximation and accept the fact that - * the output channel values will be a little low. - */ -static uint32_t ComputeScaledDivisor(uint32_t aDivisor) -{ - return UINT32_MAX/(255*aDivisor); -} - -static void -BoxBlur(const uint8_t *aInput, uint8_t *aOutput, - int32_t aStrideMinor, int32_t aStartMinor, int32_t aEndMinor, - int32_t aLeftLobe, int32_t aRightLobe, bool aAlphaOnly) -{ - int32_t boxSize = aLeftLobe + aRightLobe + 1; - int32_t scaledDivisor = ComputeScaledDivisor(boxSize); - int32_t sums[4] = {0, 0, 0, 0}; - - for (int32_t i=0; i < boxSize; i++) { - int32_t pos = aStartMinor - aLeftLobe + i; - pos = std::max(pos, aStartMinor); - pos = std::min(pos, aEndMinor - 1); -#define SUM(j) sums[j] += aInput[aStrideMinor*pos + j]; - SUM(0); SUM(1); SUM(2); SUM(3); -#undef SUM - } - - aOutput += aStrideMinor*aStartMinor; - if (aStartMinor + int32_t(boxSize) <= aEndMinor) { - const uint8_t *lastInput = aInput + aStartMinor*aStrideMinor; - const uint8_t *nextInput = aInput + (aStartMinor + aRightLobe + 1)*aStrideMinor; -#define OUTPUT(j) aOutput[j] = (sums[j]*scaledDivisor) >> 24; -#define SUM(j) sums[j] += nextInput[j] - lastInput[j]; - // process pixels in B, G, R, A order because that's 0, 1, 2, 3 for x86 -#define OUTPUT_PIXEL() \ - if (!aAlphaOnly) { OUTPUT(GFX_ARGB32_OFFSET_B); \ - OUTPUT(GFX_ARGB32_OFFSET_G); \ - OUTPUT(GFX_ARGB32_OFFSET_R); } \ - OUTPUT(GFX_ARGB32_OFFSET_A); -#define SUM_PIXEL() \ - if (!aAlphaOnly) { SUM(GFX_ARGB32_OFFSET_B); \ - SUM(GFX_ARGB32_OFFSET_G); \ - SUM(GFX_ARGB32_OFFSET_R); } \ - SUM(GFX_ARGB32_OFFSET_A); - for (int32_t minor = aStartMinor; - minor < aStartMinor + aLeftLobe; - minor++) { - OUTPUT_PIXEL(); - SUM_PIXEL(); - nextInput += aStrideMinor; - aOutput += aStrideMinor; - } - for (int32_t minor = aStartMinor + aLeftLobe; - minor < aEndMinor - aRightLobe - 1; - minor++) { - OUTPUT_PIXEL(); - SUM_PIXEL(); - lastInput += aStrideMinor; - nextInput += aStrideMinor; - aOutput += aStrideMinor; - } - // nextInput is now aInput + aEndMinor*aStrideMinor. Set it back to - // aInput + (aEndMinor - 1)*aStrideMinor so we read the last pixel in every - // iteration of the next loop. - nextInput -= aStrideMinor; - for (int32_t minor = aEndMinor - aRightLobe - 1; minor < aEndMinor; minor++) { - OUTPUT_PIXEL(); - SUM_PIXEL(); - lastInput += aStrideMinor; - aOutput += aStrideMinor; -#undef SUM_PIXEL -#undef SUM - } - } else { - for (int32_t minor = aStartMinor; minor < aEndMinor; minor++) { - int32_t tmp = minor - aLeftLobe; - int32_t last = std::max(tmp, aStartMinor); - int32_t next = std::min(tmp + int32_t(boxSize), aEndMinor - 1); - - OUTPUT_PIXEL(); -#define SUM(j) sums[j] += aInput[aStrideMinor*next + j] - \ - aInput[aStrideMinor*last + j]; - if (!aAlphaOnly) { SUM(GFX_ARGB32_OFFSET_B); - SUM(GFX_ARGB32_OFFSET_G); - SUM(GFX_ARGB32_OFFSET_R); } - SUM(GFX_ARGB32_OFFSET_A); - aOutput += aStrideMinor; -#undef SUM -#undef OUTPUT_PIXEL -#undef OUTPUT - } - } -} - -static uint32_t -GetBlurBoxSize(double aStdDev) -{ - NS_ASSERTION(aStdDev >= 0, "Negative standard deviations not allowed"); - - double size = aStdDev*3*sqrt(2*M_PI)/4; - // Doing super-large blurs accurately isn't very important. - uint32_t max = 1024; - if (size > max) - return max; - return uint32_t(floor(size + 0.5)); -} - -nsresult -nsSVGFEGaussianBlurElement::GetDXY(uint32_t *aDX, uint32_t *aDY, - const nsSVGFilterInstance& aInstance) -{ - float stdX = aInstance.GetPrimitiveNumber(SVGContentUtils::X, - &mNumberPairAttributes[STD_DEV], - nsSVGNumberPair::eFirst); - float stdY = aInstance.GetPrimitiveNumber(SVGContentUtils::Y, - &mNumberPairAttributes[STD_DEV], - nsSVGNumberPair::eSecond); - if (stdX < 0 || stdY < 0) - return NS_ERROR_FAILURE; - - // If the box size is greater than twice the temporary surface size - // in an axis, then each pixel will be set to the average of all the - // other pixel values. - *aDX = GetBlurBoxSize(stdX); - *aDY = GetBlurBoxSize(stdY); - return NS_OK; -} - -static bool -AreAllColorChannelsZero(const nsSVGFE::Image* aTarget) -{ - return aTarget->mConstantColorChannels && - aTarget->mImage->GetDataSize() >= 4 && - (*reinterpret_cast<uint32_t*>(aTarget->mImage->Data()) & 0x00FFFFFF) == 0; -} - -void -nsSVGFEGaussianBlurElement::GaussianBlur(const Image *aSource, - const Image *aTarget, - const nsIntRect& aDataRect, - uint32_t aDX, uint32_t aDY) -{ - NS_ASSERTION(nsIntRect(0, 0, aTarget->mImage->Width(), aTarget->mImage->Height()).Contains(aDataRect), - "aDataRect out of bounds"); - - nsAutoArrayPtr<uint8_t> tmp(new uint8_t[aTarget->mImage->GetDataSize()]); - if (!tmp) - return; - memset(tmp, 0, aTarget->mImage->GetDataSize()); - - bool alphaOnly = AreAllColorChannelsZero(aTarget); - - const uint8_t* sourceData = aSource->mImage->Data(); - uint8_t* targetData = aTarget->mImage->Data(); - uint32_t stride = aTarget->mImage->Stride(); - - if (aDX == 0) { - CopyDataRect(tmp, sourceData, stride, aDataRect); - } else { - int32_t longLobe = aDX/2; - int32_t shortLobe = (aDX & 1) ? longLobe : longLobe - 1; - for (int32_t major = aDataRect.y; major < aDataRect.YMost(); ++major) { - int32_t ms = major*stride; - BoxBlur(sourceData + ms, tmp + ms, 4, aDataRect.x, aDataRect.XMost(), longLobe, shortLobe, alphaOnly); - BoxBlur(tmp + ms, targetData + ms, 4, aDataRect.x, aDataRect.XMost(), shortLobe, longLobe, alphaOnly); - BoxBlur(targetData + ms, tmp + ms, 4, aDataRect.x, aDataRect.XMost(), longLobe, longLobe, alphaOnly); - } - } - - if (aDY == 0) { - CopyDataRect(targetData, tmp, stride, aDataRect); - } else { - int32_t longLobe = aDY/2; - int32_t shortLobe = (aDY & 1) ? longLobe : longLobe - 1; - for (int32_t major = aDataRect.x; major < aDataRect.XMost(); ++major) { - int32_t ms = major*4; - BoxBlur(tmp + ms, targetData + ms, stride, aDataRect.y, aDataRect.YMost(), longLobe, shortLobe, alphaOnly); - BoxBlur(targetData + ms, tmp + ms, stride, aDataRect.y, aDataRect.YMost(), shortLobe, longLobe, alphaOnly); - BoxBlur(tmp + ms, targetData + ms, stride, aDataRect.y, aDataRect.YMost(), longLobe, longLobe, alphaOnly); - } - } -} - -static void -InflateRectForBlurDXY(nsIntRect* aRect, uint32_t aDX, uint32_t aDY) -{ - aRect->Inflate(3*(aDX/2), 3*(aDY/2)); -} - -static void -ClearRect(gfxImageSurface* aSurface, int32_t aX, int32_t aY, - int32_t aXMost, int32_t aYMost) -{ - NS_ASSERTION(aX <= aXMost && aY <= aYMost, "Invalid rectangle"); - NS_ASSERTION(aX >= 0 && aY >= 0 && aXMost <= aSurface->Width() && aYMost <= aSurface->Height(), - "Rectangle out of bounds"); - - if (aX == aXMost || aY == aYMost) - return; - for (int32_t y = aY; y < aYMost; ++y) { - memset(aSurface->Data() + aSurface->Stride()*y + aX*4, 0, (aXMost - aX)*4); - } -} - -// Clip aTarget's image to its filter primitive subregion. -// aModifiedRect contains all the pixels which might not be RGBA(0,0,0,0), -// it's relative to the surface data. -static void -ClipTarget(nsSVGFilterInstance* aInstance, const nsSVGFE::Image* aTarget, - const nsIntRect& aModifiedRect) -{ - nsIntPoint surfaceTopLeft = aInstance->GetSurfaceRect().TopLeft(); - - NS_ASSERTION(aInstance->GetSurfaceRect().Contains(aModifiedRect + surfaceTopLeft), - "Modified data area overflows the surface?"); - - nsIntRect clip = aModifiedRect; - nsSVGUtils::ClipToGfxRect(&clip, - aTarget->mFilterPrimitiveSubregion - gfxPoint(surfaceTopLeft.x, surfaceTopLeft.y)); - - ClearRect(aTarget->mImage, aModifiedRect.x, aModifiedRect.y, aModifiedRect.XMost(), clip.y); - ClearRect(aTarget->mImage, aModifiedRect.x, clip.y, clip.x, clip.YMost()); - ClearRect(aTarget->mImage, clip.XMost(), clip.y, aModifiedRect.XMost(), clip.YMost()); - ClearRect(aTarget->mImage, aModifiedRect.x, clip.YMost(), aModifiedRect.XMost(), aModifiedRect.YMost()); -} - -static void -ClipComputationRectToSurface(nsSVGFilterInstance* aInstance, - nsIntRect* aDataRect) -{ - aDataRect->IntersectRect(*aDataRect, - nsIntRect(nsIntPoint(0, 0), aInstance->GetSurfaceRect().Size())); -} - -nsresult -nsSVGFEGaussianBlurElement::Filter(nsSVGFilterInstance* aInstance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - uint32_t dx, dy; - nsresult rv = GetDXY(&dx, &dy, *aInstance); - if (NS_FAILED(rv)) - return rv; - - nsIntRect computationRect = rect; - InflateRectForBlurDXY(&computationRect, dx, dy); - ClipComputationRectToSurface(aInstance, &computationRect); - GaussianBlur(aSources[0], aTarget, computationRect, dx, dy); - ClipTarget(aInstance, aTarget, computationRect); - return NS_OK; -} - -bool -nsSVGFEGaussianBlurElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFEGaussianBlurElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::stdDeviation)); -} - -void -nsSVGFEGaussianBlurElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -nsIntRect -nsSVGFEGaussianBlurElement::InflateRectForBlur(const nsIntRect& aRect, - const nsSVGFilterInstance& aInstance) -{ - uint32_t dX, dY; - nsresult rv = GetDXY(&dX, &dY, aInstance); - nsIntRect result = aRect; - if (NS_SUCCEEDED(rv)) { - InflateRectForBlurDXY(&result, dX, dY); - } - return result; -} - -nsIntRect -nsSVGFEGaussianBlurElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - return InflateRectForBlur(aSourceBBoxes[0], aInstance); -} - -void -nsSVGFEGaussianBlurElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) -{ - aSourceBBoxes[0] = InflateRectForBlur(aTargetBBox, aInstance); -} - -nsIntRect -nsSVGFEGaussianBlurElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - return InflateRectForBlur(aSourceChangeBoxes[0], aInstance); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberPairAttributesInfo -nsSVGFEGaussianBlurElement::GetNumberPairInfo() -{ - return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, - ArrayLength(sNumberPairInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFEGaussianBlurElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Blend------------------------ - -typedef nsSVGFE nsSVGFEBlendElementBase; - -class nsSVGFEBlendElement : public nsSVGFEBlendElementBase, - public nsIDOMSVGFEBlendElement -{ - friend nsresult NS_NewSVGFEBlendElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEBlendElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEBlendElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEBlendElementBase::) - - 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); - - // Blend - NS_DECL_NSIDOMSVGFEBLENDELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEBlendElementBase::) - - 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 EnumAttributesInfo GetEnumInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { MODE }; - nsSVGEnum mEnumAttributes[1]; - static nsSVGEnumMapping sModeMap[]; - static EnumInfo sEnumInfo[1]; - - enum { RESULT, IN1, IN2 }; - nsSVGString mStringAttributes[3]; - static StringInfo sStringInfo[3]; -}; - -nsSVGEnumMapping nsSVGFEBlendElement::sModeMap[] = { - {&nsGkAtoms::normal, nsSVGFEBlendElement::SVG_MODE_NORMAL}, - {&nsGkAtoms::multiply, nsSVGFEBlendElement::SVG_MODE_MULTIPLY}, - {&nsGkAtoms::screen, nsSVGFEBlendElement::SVG_MODE_SCREEN}, - {&nsGkAtoms::darken, nsSVGFEBlendElement::SVG_MODE_DARKEN}, - {&nsGkAtoms::lighten, nsSVGFEBlendElement::SVG_MODE_LIGHTEN}, +nsSVGEnumMapping SVGFEBlendElement::sModeMap[] = { + {&nsGkAtoms::normal, SVG_FEBLEND_MODE_NORMAL}, + {&nsGkAtoms::multiply, SVG_FEBLEND_MODE_MULTIPLY}, + {&nsGkAtoms::screen, SVG_FEBLEND_MODE_SCREEN}, + {&nsGkAtoms::darken, SVG_FEBLEND_MODE_DARKEN}, + {&nsGkAtoms::lighten, SVG_FEBLEND_MODE_LIGHTEN}, {nullptr, 0} }; -nsSVGElement::EnumInfo nsSVGFEBlendElement::sEnumInfo[1] = +nsSVGElement::EnumInfo SVGFEBlendElement::sEnumInfo[1] = { { &nsGkAtoms::mode, sModeMap, - nsSVGFEBlendElement::SVG_MODE_NORMAL + SVG_FEBLEND_MODE_NORMAL } }; -nsSVGElement::StringInfo nsSVGFEBlendElement::sStringInfo[3] = +nsSVGElement::StringInfo SVGFEBlendElement::sStringInfo[3] = { { &nsGkAtoms::result, kNameSpaceID_None, true }, { &nsGkAtoms::in, kNameSpaceID_None, true }, { &nsGkAtoms::in2, kNameSpaceID_None, true } }; -NS_IMPL_NS_NEW_SVG_ELEMENT(FEBlend) - //---------------------------------------------------------------------- // nsISupports methods -NS_IMPL_ADDREF_INHERITED(nsSVGFEBlendElement,nsSVGFEBlendElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEBlendElement,nsSVGFEBlendElementBase) - -DOMCI_NODE_DATA(SVGFEBlendElement, nsSVGFEBlendElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEBlendElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEBlendElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEBlendElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEBlendElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEBlendElementBase) - +NS_IMPL_ISUPPORTS_INHERITED3(SVGFEBlendElement, SVGFEBlendElementBase, + nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement) //---------------------------------------------------------------------- // nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEBlendElement) +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEBlendElement) //---------------------------------------------------------------------- // nsIDOMSVGFEBlendElement methods -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFEBlendElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) +already_AddRefed<nsIDOMSVGAnimatedString> +SVGFEBlendElement::In1() { - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); + return mStringAttributes[IN1].ToDOMAnimatedString(this); } -/* readonly attribute nsIDOMSVGAnimatedString in2; */ -NS_IMETHODIMP nsSVGFEBlendElement::GetIn2(nsIDOMSVGAnimatedString * *aIn) +already_AddRefed<nsIDOMSVGAnimatedString> +SVGFEBlendElement::In2() { - return mStringAttributes[IN2].ToDOMAnimatedString(aIn, this); + return mStringAttributes[IN2].ToDOMAnimatedString(this); } -/* readonly attribute nsIDOMSVGAnimatedEnumeration mode; */ -NS_IMETHODIMP nsSVGFEBlendElement::GetMode(nsIDOMSVGAnimatedEnumeration * *aMode) +already_AddRefed<nsIDOMSVGAnimatedEnumeration> +SVGFEBlendElement::Mode() { - return mEnumAttributes[MODE].ToDOMAnimatedEnum(aMode, this); + return mEnumAttributes[MODE].ToDOMAnimatedEnum(this); } nsresult -nsSVGFEBlendElement::Filter(nsSVGFilterInstance* aInstance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) +SVGFEBlendElement::Filter(nsSVGFilterInstance* aInstance, + const nsTArray<const Image*>& aSources, + const Image* aTarget, + const nsIntRect& rect) { CopyRect(aTarget, aSources[0], rect); uint8_t* sourceData = aSources[1]->mImage->Data(); uint8_t* targetData = aTarget->mImage->Data(); uint32_t stride = aTarget->mImage->Stride(); uint16_t mode = mEnumAttributes[MODE].GetAnimValue(); @@ -952,30 +94,30 @@ nsSVGFEBlendElement::Filter(nsSVGFilterI uint32_t qa = targetData[targIndex + GFX_ARGB32_OFFSET_A]; uint32_t qb = sourceData[targIndex + GFX_ARGB32_OFFSET_A]; for (int32_t i = std::min(GFX_ARGB32_OFFSET_B, GFX_ARGB32_OFFSET_R); i <= std::max(GFX_ARGB32_OFFSET_B, GFX_ARGB32_OFFSET_R); i++) { uint32_t ca = targetData[targIndex + i]; uint32_t cb = sourceData[targIndex + i]; uint32_t val; switch (mode) { - case nsSVGFEBlendElement::SVG_MODE_NORMAL: + case SVG_FEBLEND_MODE_NORMAL: val = (255 - qa) * cb + 255 * ca; break; - case nsSVGFEBlendElement::SVG_MODE_MULTIPLY: + case SVG_FEBLEND_MODE_MULTIPLY: val = ((255 - qa) * cb + (255 - qb + cb) * ca); break; - case nsSVGFEBlendElement::SVG_MODE_SCREEN: + case SVG_FEBLEND_MODE_SCREEN: val = 255 * (cb + ca) - ca * cb; break; - case nsSVGFEBlendElement::SVG_MODE_DARKEN: + case SVG_FEBLEND_MODE_DARKEN: val = std::min((255 - qa) * cb + 255 * ca, (255 - qb) * ca + 255 * cb); break; - case nsSVGFEBlendElement::SVG_MODE_LIGHTEN: + case SVG_FEBLEND_MODE_LIGHTEN: val = std::max((255 - qa) * cb + 255 * ca, (255 - qb) * ca + 255 * cb); break; default: return NS_ERROR_FAILURE; break; } val = std::min(val / 255, 255U); @@ -984,5355 +126,44 @@ nsSVGFEBlendElement::Filter(nsSVGFilterI uint32_t alpha = 255 * 255 - (255 - qa) * (255 - qb); FAST_DIVIDE_BY_255(targetData[targIndex + GFX_ARGB32_OFFSET_A], alpha); } } return NS_OK; } bool -nsSVGFEBlendElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const +SVGFEBlendElement::AttributeAffectsRendering(int32_t aNameSpaceID, + nsIAtom* aAttribute) const { - return nsSVGFEBlendElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || + return SVGFEBlendElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || (aNameSpaceID == kNameSpaceID_None && (aAttribute == nsGkAtoms::in || aAttribute == nsGkAtoms::in2 || aAttribute == nsGkAtoms::mode)); } void -nsSVGFEBlendElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) +SVGFEBlendElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) { aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN2], this)); } //---------------------------------------------------------------------- // nsSVGElement methods nsSVGElement::EnumAttributesInfo -nsSVGFEBlendElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFEBlendElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Color Matrix------------------------ - -typedef nsSVGFE nsSVGFEColorMatrixElementBase; - -class nsSVGFEColorMatrixElement : public nsSVGFEColorMatrixElementBase, - public nsIDOMSVGFEColorMatrixElement -{ - friend nsresult NS_NewSVGFEColorMatrixElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEColorMatrixElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEColorMatrixElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEColorMatrixElementBase::) - - 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); - - // Color Matrix - NS_DECL_NSIDOMSVGFECOLORMATRIXELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEColorMatrixElementBase::) - - 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 bool OperatesOnPremultipledAlpha(int32_t) { return false; } - - virtual EnumAttributesInfo GetEnumInfo(); - virtual StringAttributesInfo GetStringInfo(); - virtual NumberListAttributesInfo GetNumberListInfo(); - - enum { TYPE }; - nsSVGEnum mEnumAttributes[1]; - static nsSVGEnumMapping sTypeMap[]; - static EnumInfo sEnumInfo[1]; - - enum { RESULT, IN1 }; - nsSVGString mStringAttributes[2]; - static StringInfo sStringInfo[2]; - - enum { VALUES }; - SVGAnimatedNumberList mNumberListAttributes[1]; - static NumberListInfo sNumberListInfo[1]; -}; - -nsSVGEnumMapping nsSVGFEColorMatrixElement::sTypeMap[] = { - {&nsGkAtoms::matrix, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX}, - {&nsGkAtoms::saturate, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE}, - {&nsGkAtoms::hueRotate, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE}, - {&nsGkAtoms::luminanceToAlpha, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFEColorMatrixElement::sEnumInfo[1] = -{ - { &nsGkAtoms::type, - sTypeMap, - nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX - } -}; - -nsSVGElement::StringInfo nsSVGFEColorMatrixElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -nsSVGElement::NumberListInfo nsSVGFEColorMatrixElement::sNumberListInfo[1] = -{ - { &nsGkAtoms::values } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEColorMatrix) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEColorMatrixElement,nsSVGFEColorMatrixElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEColorMatrixElement,nsSVGFEColorMatrixElementBase) - -DOMCI_NODE_DATA(SVGFEColorMatrixElement, nsSVGFEColorMatrixElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEColorMatrixElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEColorMatrixElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEColorMatrixElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEColorMatrixElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEColorMatrixElementBase) - - -//---------------------------------------------------------------------- -// nsIDOMNode methods - - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEColorMatrixElement) - - -//---------------------------------------------------------------------- -// nsSVGFEColorMatrixElement methods - -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFEColorMatrixElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */ -NS_IMETHODIMP nsSVGFEColorMatrixElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType) -{ - return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this); -} - -/* readonly attribute DOMSVGAnimatedNumberList values; */ -NS_IMETHODIMP nsSVGFEColorMatrixElement::GetValues(nsISupports * *aValues) -{ - *aValues = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[VALUES], - this, VALUES).get(); - return NS_OK; -} - -void -nsSVGFEColorMatrixElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -nsresult -nsSVGFEColorMatrixElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - uint8_t* sourceData = aSources[0]->mImage->Data(); - uint8_t* targetData = aTarget->mImage->Data(); - uint32_t stride = aTarget->mImage->Stride(); - - uint16_t type = mEnumAttributes[TYPE].GetAnimValue(); - const SVGNumberList &values = mNumberListAttributes[VALUES].GetAnimValue(); - - if (!mNumberListAttributes[VALUES].IsExplicitlySet() && - (type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX || - type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE || - type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE)) { - // identity matrix filter - CopyRect(aTarget, aSources[0], rect); - return NS_OK; - } - - static const float identityMatrix[] = - { 1, 0, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 0, 1, 0 }; - - static const float luminanceToAlphaMatrix[] = - { 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0.2125f, 0.7154f, 0.0721f, 0, 0 }; - - float colorMatrix[NUM_ENTRIES_IN_4x5_MATRIX]; - float s, c; - - switch (type) { - case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX: - - if (values.Length() != NUM_ENTRIES_IN_4x5_MATRIX) - return NS_ERROR_FAILURE; - - for(uint32_t j = 0; j < values.Length(); j++) { - colorMatrix[j] = values[j]; - } - break; - case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE: - - if (values.Length() != 1) - return NS_ERROR_FAILURE; - - s = values[0]; - - if (s > 1 || s < 0) - return NS_ERROR_FAILURE; - - memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix)); - - colorMatrix[0] = 0.213f + 0.787f * s; - colorMatrix[1] = 0.715f - 0.715f * s; - colorMatrix[2] = 0.072f - 0.072f * s; - - colorMatrix[5] = 0.213f - 0.213f * s; - colorMatrix[6] = 0.715f + 0.285f * s; - colorMatrix[7] = 0.072f - 0.072f * s; - - colorMatrix[10] = 0.213f - 0.213f * s; - colorMatrix[11] = 0.715f - 0.715f * s; - colorMatrix[12] = 0.072f + 0.928f * s; - - break; - - case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE: - { - memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix)); - - if (values.Length() != 1) - return NS_ERROR_FAILURE; - - float hueRotateValue = values[0]; - - c = static_cast<float>(cos(hueRotateValue * M_PI / 180)); - s = static_cast<float>(sin(hueRotateValue * M_PI / 180)); - - memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix)); - - colorMatrix[0] = 0.213f + 0.787f * c - 0.213f * s; - colorMatrix[1] = 0.715f - 0.715f * c - 0.715f * s; - colorMatrix[2] = 0.072f - 0.072f * c + 0.928f * s; - - colorMatrix[5] = 0.213f - 0.213f * c + 0.143f * s; - colorMatrix[6] = 0.715f + 0.285f * c + 0.140f * s; - colorMatrix[7] = 0.072f - 0.072f * c - 0.283f * s; - - colorMatrix[10] = 0.213f - 0.213f * c - 0.787f * s; - colorMatrix[11] = 0.715f - 0.715f * c + 0.715f * s; - colorMatrix[12] = 0.072f + 0.928f * c + 0.072f * s; - - break; - } - - case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA: - - memcpy(colorMatrix, luminanceToAlphaMatrix, sizeof(colorMatrix)); - break; - - default: - return NS_ERROR_FAILURE; - } - - for (int32_t x = rect.x; x < rect.XMost(); x++) { - for (int32_t y = rect.y; y < rect.YMost(); y++) { - uint32_t targIndex = y * stride + 4 * x; - - float col[4]; - for (int i = 0, row = 0; i < 4; i++, row += 5) { - col[i] = - sourceData[targIndex + GFX_ARGB32_OFFSET_R] * colorMatrix[row + 0] + - sourceData[targIndex + GFX_ARGB32_OFFSET_G] * colorMatrix[row + 1] + - sourceData[targIndex + GFX_ARGB32_OFFSET_B] * colorMatrix[row + 2] + - sourceData[targIndex + GFX_ARGB32_OFFSET_A] * colorMatrix[row + 3] + - 255 * colorMatrix[row + 4]; - col[i] = clamped(col[i], 0.f, 255.f); - } - targetData[targIndex + GFX_ARGB32_OFFSET_R] = - static_cast<uint8_t>(col[0]); - targetData[targIndex + GFX_ARGB32_OFFSET_G] = - static_cast<uint8_t>(col[1]); - targetData[targIndex + GFX_ARGB32_OFFSET_B] = - static_cast<uint8_t>(col[2]); - targetData[targIndex + GFX_ARGB32_OFFSET_A] = - static_cast<uint8_t>(col[3]); - } - } - return NS_OK; -} - -bool -nsSVGFEColorMatrixElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFEColorMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::type || - aAttribute == nsGkAtoms::values)); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::EnumAttributesInfo -nsSVGFEColorMatrixElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFEColorMatrixElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -nsSVGElement::NumberListAttributesInfo -nsSVGFEColorMatrixElement::GetNumberListInfo() -{ - return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, - ArrayLength(sNumberListInfo)); -} - -//---------------------Composite------------------------ - -typedef nsSVGFE nsSVGFECompositeElementBase; - -class nsSVGFECompositeElement : public nsSVGFECompositeElementBase, - public nsIDOMSVGFECompositeElement -{ - friend nsresult NS_NewSVGFECompositeElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFECompositeElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFECompositeElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFECompositeElementBase::) - - 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); - - // Composite - NS_DECL_NSIDOMSVGFECOMPOSITEELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFECompositeElementBase::) - - 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 EnumAttributesInfo GetEnumInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { K1, K2, K3, K4 }; - nsSVGNumber2 mNumberAttributes[4]; - static NumberInfo sNumberInfo[4]; - - enum { OPERATOR }; - nsSVGEnum mEnumAttributes[1]; - static nsSVGEnumMapping sOperatorMap[]; - static EnumInfo sEnumInfo[1]; - - enum { RESULT, IN1, IN2 }; - nsSVGString mStringAttributes[3]; - static StringInfo sStringInfo[3]; -}; - -nsSVGElement::NumberInfo nsSVGFECompositeElement::sNumberInfo[4] = -{ - { &nsGkAtoms::k1, 0, false }, - { &nsGkAtoms::k2, 0, false }, - { &nsGkAtoms::k3, 0, false }, - { &nsGkAtoms::k4, 0, false } -}; - -nsSVGEnumMapping nsSVGFECompositeElement::sOperatorMap[] = { - {&nsGkAtoms::over, nsSVGFECompositeElement::SVG_OPERATOR_OVER}, - {&nsGkAtoms::in, nsSVGFECompositeElement::SVG_OPERATOR_IN}, - {&nsGkAtoms::out, nsSVGFECompositeElement::SVG_OPERATOR_OUT}, - {&nsGkAtoms::atop, nsSVGFECompositeElement::SVG_OPERATOR_ATOP}, - {&nsGkAtoms::xor_, nsSVGFECompositeElement::SVG_OPERATOR_XOR}, - {&nsGkAtoms::arithmetic, nsSVGFECompositeElement::SVG_OPERATOR_ARITHMETIC}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFECompositeElement::sEnumInfo[1] = -{ - { &nsGkAtoms::_operator, - sOperatorMap, - nsIDOMSVGFECompositeElement::SVG_OPERATOR_OVER - } -}; - -nsSVGElement::StringInfo nsSVGFECompositeElement::sStringInfo[3] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true }, - { &nsGkAtoms::in2, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEComposite) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFECompositeElement,nsSVGFECompositeElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFECompositeElement,nsSVGFECompositeElementBase) - -DOMCI_NODE_DATA(SVGFECompositeElement, nsSVGFECompositeElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFECompositeElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFECompositeElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFECompositeElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFECompositeElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFECompositeElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFECompositeElement) - -//---------------------------------------------------------------------- -// nsSVGFECompositeElement methods - -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFECompositeElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -/* readonly attribute nsIDOMSVGAnimatedString in2; */ -NS_IMETHODIMP nsSVGFECompositeElement::GetIn2(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN2].ToDOMAnimatedString(aIn, this); -} - - -/* readonly attribute nsIDOMSVGAnimatedEnumeration operator; */ -NS_IMETHODIMP nsSVGFECompositeElement::GetOperator(nsIDOMSVGAnimatedEnumeration * *aOperator) -{ - return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(aOperator, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber K1; */ -NS_IMETHODIMP nsSVGFECompositeElement::GetK1(nsIDOMSVGAnimatedNumber * *aK1) -{ - return mNumberAttributes[K1].ToDOMAnimatedNumber(aK1, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber K2; */ -NS_IMETHODIMP nsSVGFECompositeElement::GetK2(nsIDOMSVGAnimatedNumber * *aK2) -{ - return mNumberAttributes[K2].ToDOMAnimatedNumber(aK2, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber K3; */ -NS_IMETHODIMP nsSVGFECompositeElement::GetK3(nsIDOMSVGAnimatedNumber * *aK3) -{ - return mNumberAttributes[K3].ToDOMAnimatedNumber(aK3, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber K4; */ -NS_IMETHODIMP nsSVGFECompositeElement::GetK4(nsIDOMSVGAnimatedNumber * *aK4) -{ - return mNumberAttributes[K4].ToDOMAnimatedNumber(aK4, this); -} - -NS_IMETHODIMP -nsSVGFECompositeElement::SetK(float k1, float k2, float k3, float k4) -{ - NS_ENSURE_FINITE4(k1, k2, k3, k4, NS_ERROR_ILLEGAL_VALUE); - mNumberAttributes[K1].SetBaseValue(k1, this); - mNumberAttributes[K2].SetBaseValue(k2, this); - mNumberAttributes[K3].SetBaseValue(k3, this); - mNumberAttributes[K4].SetBaseValue(k4, this); - return NS_OK; -} - -nsresult -nsSVGFECompositeElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - uint16_t op = mEnumAttributes[OPERATOR].GetAnimValue(); - - // Cairo does not support arithmetic operator - if (op == nsSVGFECompositeElement::SVG_OPERATOR_ARITHMETIC) { - float k1, k2, k3, k4; - GetAnimatedNumberValues(&k1, &k2, &k3, &k4, nullptr); - - // Copy the first source image - CopyRect(aTarget, aSources[0], rect); - - uint8_t* sourceData = aSources[1]->mImage->Data(); - uint8_t* targetData = aTarget->mImage->Data(); - uint32_t stride = aTarget->mImage->Stride(); - - // Blend in the second source image - float k1Scaled = k1 / 255.0f; - float k4Scaled = k4*255.0f; - for (int32_t x = rect.x; x < rect.XMost(); x++) { - for (int32_t y = rect.y; y < rect.YMost(); y++) { - uint32_t targIndex = y * stride + 4 * x; - for (int32_t i = 0; i < 4; i++) { - uint8_t i1 = targetData[targIndex + i]; - uint8_t i2 = sourceData[targIndex + i]; - float result = k1Scaled*i1*i2 + k2*i1 + k3*i2 + k4Scaled; - targetData[targIndex + i] = - static_cast<uint8_t>(clamped(result, 0.f, 255.f)); - } - } - } - return NS_OK; - } - - // Cairo supports the operation we are trying to perform - - gfxContext ctx(aTarget->mImage); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.SetSource(aSources[1]->mImage); - // Ensure rendering is limited to the filter primitive subregion - ctx.Clip(aTarget->mFilterPrimitiveSubregion); - ctx.Paint(); - - if (op < SVG_OPERATOR_OVER || op > SVG_OPERATOR_XOR) { - return NS_ERROR_FAILURE; - } - static const gfxContext::GraphicsOperator opMap[] = { - gfxContext::OPERATOR_DEST, - gfxContext::OPERATOR_OVER, - gfxContext::OPERATOR_IN, - gfxContext::OPERATOR_OUT, - gfxContext::OPERATOR_ATOP, - gfxContext::OPERATOR_XOR }; - ctx.SetOperator(opMap[op]); - ctx.SetSource(aSources[0]->mImage); - ctx.Paint(); - return NS_OK; -} - -bool -nsSVGFECompositeElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFECompositeElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::in2 || - aAttribute == nsGkAtoms::k1 || - aAttribute == nsGkAtoms::k2 || - aAttribute == nsGkAtoms::k3 || - aAttribute == nsGkAtoms::k4 || - aAttribute == nsGkAtoms::_operator)); -} - -void -nsSVGFECompositeElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN2], this)); -} - -nsIntRect -nsSVGFECompositeElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - uint16_t op = mEnumAttributes[OPERATOR].GetAnimValue(); - - if (op == nsSVGFECompositeElement::SVG_OPERATOR_ARITHMETIC) { - // "arithmetic" operator can produce non-zero alpha values even where - // all input alphas are zero, so we can actually render outside the - // union of the source bboxes. - // XXX we could also check that k4 is nonzero and check for other - // cases like k1/k2 or k1/k3 zero. - return GetMaxRect(); - } - - if (op == nsSVGFECompositeElement::SVG_OPERATOR_IN || - op == nsSVGFECompositeElement::SVG_OPERATOR_ATOP) { - // We will only draw where in2 has nonzero alpha, so it's a good - // bounding box for us - return aSourceBBoxes[1]; - } - - // The regular Porter-Duff operators always compute zero alpha values - // where all sources have zero alpha, so the union of their bounding - // boxes is also a bounding box for our rendering - return nsSVGFECompositeElementBase::ComputeTargetBBox(aSourceBBoxes, aInstance); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFECompositeElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -nsSVGElement::EnumAttributesInfo -nsSVGFECompositeElement::GetEnumInfo() +SVGFEBlendElement::GetEnumInfo() { return EnumAttributesInfo(mEnumAttributes, sEnumInfo, ArrayLength(sEnumInfo)); } nsSVGElement::StringAttributesInfo -nsSVGFECompositeElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Component Transfer------------------------ - -typedef nsSVGFE nsSVGFEComponentTransferElementBase; - -class nsSVGFEComponentTransferElement : public nsSVGFEComponentTransferElementBase, - public nsIDOMSVGFEComponentTransferElement -{ - friend nsresult NS_NewSVGFEComponentTransferElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEComponentTransferElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEComponentTransferElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEComponentTransferElementBase::) - - 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); - - // Component Transfer - NS_DECL_NSIDOMSVGFECOMPONENTTRANSFERELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEComponentTransferElementBase::) - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - // nsIContent - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual bool OperatesOnPremultipledAlpha(int32_t) { return false; } - - virtual StringAttributesInfo GetStringInfo(); - - enum { RESULT, IN1 }; - nsSVGString mStringAttributes[2]; - static StringInfo sStringInfo[2]; -}; - -nsSVGElement::StringInfo nsSVGFEComponentTransferElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEComponentTransfer) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEComponentTransferElement,nsSVGFEComponentTransferElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEComponentTransferElement,nsSVGFEComponentTransferElementBase) - -DOMCI_NODE_DATA(SVGFEComponentTransferElement, nsSVGFEComponentTransferElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEComponentTransferElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEComponentTransferElement, nsIDOMNode, - nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEComponentTransferElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEComponentTransferElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEComponentTransferElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEComponentTransferElement) - -//---------------------------------------------------------------------- -// nsIDOMSVGFEComponentTransferElement methods - -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP -nsSVGFEComponentTransferElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::StringAttributesInfo -nsSVGFEComponentTransferElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//-------------------------------------------- - -nsresult -nsSVGFEComponentTransferElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - uint8_t* sourceData = aSources[0]->mImage->Data(); - uint8_t* targetData = aTarget->mImage->Data(); - uint32_t stride = aTarget->mImage->Stride(); - - uint8_t tableR[256], tableG[256], tableB[256], tableA[256]; - for (int i=0; i<256; i++) - tableR[i] = tableG[i] = tableB[i] = tableA[i] = i; - uint8_t* tables[] = { tableR, tableG, tableB, tableA }; - for (nsIContent* childContent = nsINode::GetFirstChild(); - childContent; - childContent = childContent->GetNextSibling()) { - - nsRefPtr<SVGComponentTransferFunctionElement> child; - CallQueryInterface(childContent, - (SVGComponentTransferFunctionElement**)getter_AddRefs(child)); - if (child) { - if (!child->GenerateLookupTable(tables[child->GetChannel()])) { - return NS_ERROR_FAILURE; - } - } - } - - 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; - targetData[targIndex + GFX_ARGB32_OFFSET_B] = - tableB[sourceData[targIndex + GFX_ARGB32_OFFSET_B]]; - targetData[targIndex + GFX_ARGB32_OFFSET_G] = - tableG[sourceData[targIndex + GFX_ARGB32_OFFSET_G]]; - targetData[targIndex + GFX_ARGB32_OFFSET_R] = - tableR[sourceData[targIndex + GFX_ARGB32_OFFSET_R]]; - targetData[targIndex + GFX_ARGB32_OFFSET_A] = - tableA[sourceData[targIndex + GFX_ARGB32_OFFSET_A]]; - } - } - return NS_OK; -} - -bool -nsSVGFEComponentTransferElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFEComponentTransferElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - aAttribute == nsGkAtoms::in); -} - -void -nsSVGFEComponentTransferElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -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, - nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY}, - {&nsGkAtoms::table, - nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_TABLE}, - {&nsGkAtoms::discrete, - nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE}, - {&nsGkAtoms::linear, - nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_LINEAR}, - {&nsGkAtoms::gamma, - nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_GAMMA}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo SVGComponentTransferFunctionElement::sEnumInfo[1] = -{ - { &nsGkAtoms::type, - sTypeMap, - nsIDOMSVGComponentTransferFunctionElement::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); -} - -//---------------------------------------------------------------------- -// nsIDOMSVGComponentTransferFunctionElement methods - -/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */ -already_AddRefed<nsIDOMSVGAnimatedEnumeration> -SVGComponentTransferFunctionElement::Type() -{ - return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this); -} -NS_IMETHODIMP SVGComponentTransferFunctionElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType) -{ - *aType = Type().get(); - return NS_OK; -} - -/* readonly attribute DOMSVGAnimatedNumberList tableValues; */ -already_AddRefed<DOMSVGAnimatedNumberList> -SVGComponentTransferFunctionElement::TableValues() -{ - return DOMSVGAnimatedNumberList::GetDOMWrapper( - &mNumberListAttributes[TABLEVALUES], this, TABLEVALUES); -} -NS_IMETHODIMP SVGComponentTransferFunctionElement::GetTableValues(nsISupports * *aTableValues) -{ - *aTableValues = TableValues().get(); - return NS_OK; -} - -/* readonly attribute nsIDOMSVGAnimatedNumber slope; */ -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Slope() -{ - return mNumberAttributes[SLOPE].ToDOMAnimatedNumber(this); -} -NS_IMETHODIMP SVGComponentTransferFunctionElement::GetSlope(nsIDOMSVGAnimatedNumber * *aSlope) -{ - *aSlope = Slope().get(); - return NS_OK; -} - -/* readonly attribute nsIDOMSVGAnimatedNumber intercept; */ -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Intercept() -{ - return mNumberAttributes[INTERCEPT].ToDOMAnimatedNumber(this); -} -NS_IMETHODIMP SVGComponentTransferFunctionElement::GetIntercept(nsIDOMSVGAnimatedNumber * *aIntercept) -{ - *aIntercept = Intercept().get(); - return NS_OK; -} - -/* readonly attribute nsIDOMSVGAnimatedNumber amplitude; */ -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Amplitude() -{ - return mNumberAttributes[AMPLITUDE].ToDOMAnimatedNumber(this); -} -NS_IMETHODIMP SVGComponentTransferFunctionElement::GetAmplitude(nsIDOMSVGAnimatedNumber * *aAmplitude) -{ - *aAmplitude = Amplitude().get(); - return NS_OK; -} - -/* readonly attribute nsIDOMSVGAnimatedNumber exponent; */ -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Exponent() -{ - return mNumberAttributes[EXPONENT].ToDOMAnimatedNumber(this); -} -NS_IMETHODIMP SVGComponentTransferFunctionElement::GetExponent(nsIDOMSVGAnimatedNumber * *aExponent) -{ - *aExponent = Exponent().get(); - return NS_OK; -} - -/* readonly attribute nsIDOMSVGAnimatedNumber offset; */ -already_AddRefed<nsIDOMSVGAnimatedNumber> -SVGComponentTransferFunctionElement::Offset() -{ - return mNumberAttributes[OFFSET].ToDOMAnimatedNumber(this); -} -NS_IMETHODIMP SVGComponentTransferFunctionElement::GetOffset(nsIDOMSVGAnimatedNumber * *aOffset) -{ - *aOffset = Offset().get(); - return NS_OK; -} - -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 nsIDOMSVGComponentTransferFunctionElement::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 nsIDOMSVGComponentTransferFunctionElement::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 nsIDOMSVGComponentTransferFunctionElement::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 nsIDOMSVGComponentTransferFunctionElement::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 nsIDOMSVGComponentTransferFunctionElement::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_INHERITED5(SVGFEFuncRElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGComponentTransferFunctionElement, - nsIDOMSVGFEFuncRElement) - -/* virtual */ JSObject* -SVGFEFuncRElement::WrapNode(JSContext* aCx, JSObject* aScope, - bool* aTriedToWrap) -{ - return SVGFEFuncRElementBinding::Wrap(aCx, aScope, this, aTriedToWrap); -} - -} // 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_INHERITED5(SVGFEFuncGElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGComponentTransferFunctionElement, - nsIDOMSVGFEFuncGElement) - -/* virtual */ JSObject* -SVGFEFuncGElement::WrapNode(JSContext* aCx, JSObject* aScope, - bool* aTriedToWrap) -{ - return SVGFEFuncGElementBinding::Wrap(aCx, aScope, this, aTriedToWrap); -} - -} // 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_INHERITED5(SVGFEFuncBElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGComponentTransferFunctionElement, - nsIDOMSVGFEFuncBElement) - -/* virtual */ JSObject* -SVGFEFuncBElement::WrapNode(JSContext* aCx, JSObject* aScope, - bool* aTriedToWrap) -{ - return SVGFEFuncBElementBinding::Wrap(aCx, aScope, this, aTriedToWrap); -} - -} // 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_INHERITED5(SVGFEFuncAElement, - SVGComponentTransferFunctionElement, - nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGComponentTransferFunctionElement, - nsIDOMSVGFEFuncAElement) - -/* virtual */ JSObject* -SVGFEFuncAElement::WrapNode(JSContext* aCx, JSObject* aScope, - bool* aTriedToWrap) -{ - return SVGFEFuncAElementBinding::Wrap(aCx, aScope, this, aTriedToWrap); -} - -} // 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 - -//---------------------Merge------------------------ - -typedef nsSVGFE nsSVGFEMergeElementBase; - -class nsSVGFEMergeElement : public nsSVGFEMergeElementBase, - public nsIDOMSVGFEMergeElement -{ - friend nsresult NS_NewSVGFEMergeElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEMergeElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEMergeElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMergeElementBase::) - - virtual nsresult Filter(nsSVGFilterInstance* aInstance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& aDataRect); - virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; } - virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources); - - // Merge - NS_DECL_NSIDOMSVGFEMERGEELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMergeElementBase::) - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - // nsIContent - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual StringAttributesInfo GetStringInfo(); - - enum { RESULT }; - nsSVGString mStringAttributes[1]; - static StringInfo sStringInfo[1]; -}; - -typedef SVGFEUnstyledElement nsSVGFEMergeNodeElementBase; - -#define NS_SVG_FE_MERGE_NODE_CID \ - { 0x413687ec, 0x77fd, 0x4077, \ - { 0x9d, 0x7a, 0x97, 0x51, 0xa8, 0x4b, 0x7b, 0x40 } } - -class nsSVGFEMergeNodeElement : public nsSVGFEMergeNodeElementBase, - public nsIDOMSVGFEMergeNodeElement -{ - friend nsresult NS_NewSVGFEMergeNodeElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEMergeNodeElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEMergeNodeElementBase(aNodeInfo) {} - -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVG_FE_MERGE_NODE_CID) - - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - NS_DECL_NSIDOMSVGFEMERGENODEELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMergeNodeElementBase::) - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual bool AttributeAffectsRendering( - int32_t aNameSpaceID, nsIAtom* aAttribute) const; - - const nsSVGString* In1() { return &mStringAttributes[IN1]; } - - operator nsISupports*() { return static_cast<nsIContent*>(this); } - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual StringAttributesInfo GetStringInfo(); - - enum { IN1 }; - nsSVGString mStringAttributes[1]; - static StringInfo sStringInfo[1]; -}; - -nsSVGElement::StringInfo nsSVGFEMergeElement::sStringInfo[1] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEMerge) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEMergeElement,nsSVGFEMergeElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEMergeElement,nsSVGFEMergeElementBase) - -DOMCI_NODE_DATA(SVGFEMergeElement, nsSVGFEMergeElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEMergeElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEMergeElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEMergeElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMergeElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMergeElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMergeElement) - -nsresult -nsSVGFEMergeElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - gfxContext ctx(aTarget->mImage); - ctx.Clip(aTarget->mFilterPrimitiveSubregion); - - for (uint32_t i = 0; i < aSources.Length(); i++) { - ctx.SetSource(aSources[i]->mImage); - ctx.Paint(); - } - return NS_OK; -} - -void -nsSVGFEMergeElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - for (nsIContent* child = nsINode::GetFirstChild(); - child; - child = child->GetNextSibling()) { - nsRefPtr<nsSVGFEMergeNodeElement> node; - CallQueryInterface(child, (nsSVGFEMergeNodeElement**)getter_AddRefs(node)); - if (node) { - aSources.AppendElement(nsSVGStringInfo(node->In1(), node)); - } - } -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::StringAttributesInfo -nsSVGFEMergeElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Merge Node------------------------ - -NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGFEMergeNodeElement, NS_SVG_FE_MERGE_NODE_CID) - -nsSVGElement::StringInfo nsSVGFEMergeNodeElement::sStringInfo[1] = -{ - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEMergeNode) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEMergeNodeElement,nsSVGFEMergeNodeElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEMergeNodeElement,nsSVGFEMergeNodeElementBase) - -DOMCI_NODE_DATA(SVGFEMergeNodeElement, nsSVGFEMergeNodeElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEMergeNodeElement) - NS_NODE_INTERFACE_TABLE4(nsSVGFEMergeNodeElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, nsIDOMSVGFEMergeNodeElement) - // nsISupports is an ambiguous base of nsSVGFE so we have to work - // around that - if ( aIID.Equals(NS_GET_IID(nsSVGFEMergeNodeElement)) ) - foundInterface = static_cast<nsISupports*>(static_cast<void*>(this)); - else - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMergeNodeElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMergeNodeElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMergeNodeElement) - -//---------------------------------------------------------------------- -// nsFEUnstyledElement methods - -bool -nsSVGFEMergeNodeElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::in; -} - -//---------------------------------------------------------------------- -// nsIDOMSVGFEMergeNodeElement methods - -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFEMergeNodeElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::StringAttributesInfo -nsSVGFEMergeNodeElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Offset------------------------ - -typedef nsSVGFE nsSVGFEOffsetElementBase; - -class nsSVGFEOffsetElement : public nsSVGFEOffsetElementBase, - public nsIDOMSVGFEOffsetElement -{ - friend nsresult NS_NewSVGFEOffsetElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEOffsetElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEOffsetElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEOffsetElementBase::) - - 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); - - // Offset - NS_DECL_NSIDOMSVGFEOFFSETELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEOffsetElementBase::) - - 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: - nsIntPoint GetOffset(const nsSVGFilterInstance& aInstance); - - virtual NumberAttributesInfo GetNumberInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { DX, DY }; - nsSVGNumber2 mNumberAttributes[2]; - static NumberInfo sNumberInfo[2]; - - enum { RESULT, IN1 }; - nsSVGString mStringAttributes[2]; - static StringInfo sStringInfo[2]; -}; - -nsSVGElement::NumberInfo nsSVGFEOffsetElement::sNumberInfo[2] = -{ - { &nsGkAtoms::dx, 0, false }, - { &nsGkAtoms::dy, 0, false } -}; - -nsSVGElement::StringInfo nsSVGFEOffsetElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEOffset) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEOffsetElement,nsSVGFEOffsetElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEOffsetElement,nsSVGFEOffsetElementBase) - -DOMCI_NODE_DATA(SVGFEOffsetElement, nsSVGFEOffsetElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEOffsetElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEOffsetElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEOffsetElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEOffsetElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEOffsetElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEOffsetElement) - - -//---------------------------------------------------------------------- -// nsIDOMSVGFEOffsetElement methods - -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFEOffsetElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber dx; */ -NS_IMETHODIMP nsSVGFEOffsetElement::GetDx(nsIDOMSVGAnimatedNumber * *aDx) -{ - return mNumberAttributes[DX].ToDOMAnimatedNumber(aDx, this); -} - -/* readonly attribute nsIDOMSVGAnimatedNumber dy; */ -NS_IMETHODIMP nsSVGFEOffsetElement::GetDy(nsIDOMSVGAnimatedNumber * *aDy) -{ - return mNumberAttributes[DY].ToDOMAnimatedNumber(aDy, this); -} - -nsIntPoint -nsSVGFEOffsetElement::GetOffset(const nsSVGFilterInstance& aInstance) -{ - return nsIntPoint(int32_t(aInstance.GetPrimitiveNumber( - SVGContentUtils::X, &mNumberAttributes[DX])), - int32_t(aInstance.GetPrimitiveNumber( - SVGContentUtils::Y, &mNumberAttributes[DY]))); -} - -nsresult -nsSVGFEOffsetElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - nsIntPoint offset = GetOffset(*instance); - - gfxContext ctx(aTarget->mImage); - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - // Ensure rendering is limited to the filter primitive subregion - ctx.Clip(aTarget->mFilterPrimitiveSubregion); - ctx.Translate(gfxPoint(offset.x, offset.y)); - ctx.SetSource(aSources[0]->mImage); - ctx.Paint(); - - return NS_OK; -} - -bool -nsSVGFEOffsetElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFEOffsetElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::dx || - aAttribute == nsGkAtoms::dy)); -} - -void -nsSVGFEOffsetElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -nsIntRect -nsSVGFEOffsetElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - return aSourceBBoxes[0] + GetOffset(aInstance); -} - -nsIntRect -nsSVGFEOffsetElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - return aSourceChangeBoxes[0] + GetOffset(aInstance); -} - -void -nsSVGFEOffsetElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) -{ - aSourceBBoxes[0] = aTargetBBox - GetOffset(aInstance); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFEOffsetElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFEOffsetElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Flood------------------------ - -typedef nsSVGFE nsSVGFEFloodElementBase; - -class nsSVGFEFloodElement : public nsSVGFEFloodElementBase, - public nsIDOMSVGFEFloodElement -{ - friend nsresult NS_NewSVGFEFloodElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEFloodElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEFloodElementBase(aNodeInfo) {} - -public: - virtual bool SubregionIsUnionOfRegions() { return false; } - - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEFloodElementBase::) - - virtual nsresult Filter(nsSVGFilterInstance* aInstance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& aDataRect); - virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; } - virtual nsIntRect ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance); - - // Flood - NS_DECL_NSIDOMSVGFEFLOODELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEFloodElementBase::) - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - // nsIContent interface - NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const; - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual bool OperatesOnSRGB(nsSVGFilterInstance*, - int32_t, Image*) { return true; } - - virtual StringAttributesInfo GetStringInfo(); - - enum { RESULT }; - nsSVGString mStringAttributes[1]; - static StringInfo sStringInfo[1]; -}; - -nsSVGElement::StringInfo nsSVGFEFloodElement::sStringInfo[1] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEFlood) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEFloodElement,nsSVGFEFloodElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEFloodElement,nsSVGFEFloodElementBase) - -DOMCI_NODE_DATA(SVGFEFloodElement, nsSVGFEFloodElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEFloodElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEFloodElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEFloodElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEFloodElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEFloodElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEFloodElement) - - -//---------------------------------------------------------------------- -// nsIDOMSVGFEFloodElement methods - -nsresult -nsSVGFEFloodElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& aDataRect) -{ - nsIFrame* frame = GetPrimaryFrame(); - if (!frame) return NS_ERROR_FAILURE; - nsStyleContext* style = frame->StyleContext(); - - nscolor floodColor = style->StyleSVGReset()->mFloodColor; - float floodOpacity = style->StyleSVGReset()->mFloodOpacity; - - gfxContext ctx(aTarget->mImage); - ctx.SetColor(gfxRGBA(NS_GET_R(floodColor) / 255.0, - NS_GET_G(floodColor) / 255.0, - NS_GET_B(floodColor) / 255.0, - NS_GET_A(floodColor) / 255.0 * floodOpacity)); - ctx.Rectangle(aTarget->mFilterPrimitiveSubregion); - ctx.Fill(); - return NS_OK; -} - -nsIntRect -nsSVGFEFloodElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - return GetMaxRect(); -} - -//---------------------------------------------------------------------- -// nsIContent methods - -NS_IMETHODIMP_(bool) -nsSVGFEFloodElement::IsAttributeMapped(const nsIAtom* name) const -{ - static const MappedAttributeEntry* const map[] = { - sFEFloodMap - }; - - return FindAttributeDependence(name, map) || - nsSVGFEFloodElementBase::IsAttributeMapped(name); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::StringAttributesInfo -nsSVGFEFloodElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Tile------------------------ - -typedef nsSVGFE nsSVGFETileElementBase; - -class nsSVGFETileElement : public nsSVGFETileElementBase, - public nsIDOMSVGFETileElement -{ - friend nsresult NS_NewSVGFETileElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFETileElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFETileElementBase(aNodeInfo) {} - -public: - virtual bool SubregionIsUnionOfRegions() { return false; } - - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETileElementBase::) - - 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); - - // Tile - NS_DECL_NSIDOMSVGFETILEELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETileElementBase::) - - 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 StringAttributesInfo GetStringInfo(); - - enum { RESULT, IN1 }; - nsSVGString mStringAttributes[2]; - static StringInfo sStringInfo[2]; -}; - -nsSVGElement::StringInfo nsSVGFETileElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FETile) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFETileElement,nsSVGFETileElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFETileElement,nsSVGFETileElementBase) - -DOMCI_NODE_DATA(SVGFETileElement, nsSVGFETileElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFETileElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFETileElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFETileElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETileElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFETileElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETileElement) - - -//---------------------------------------------------------------------- -// nsSVGFETileElement methods - -/* readonly attribute nsIDOMSVGAnimatedString in1; */ -NS_IMETHODIMP nsSVGFETileElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -void -nsSVGFETileElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -nsIntRect -nsSVGFETileElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - return GetMaxRect(); -} - -void -nsSVGFETileElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) -{ - // Just assume we need the entire source bounding box, so do nothing. -} - -nsIntRect -nsSVGFETileElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - return GetMaxRect(); -} - -static int32_t WrapInterval(int32_t aVal, int32_t aMax) -{ - aVal = aVal % aMax; - return aVal < 0 ? aMax + aVal : aVal; -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -/* - * This function computes the size of partial match on either side of the tile. - * eg: If we are talking about the X-axis direction, then it computes, the - * size of the tile that would be copied to the lesser X-axis side (usually - * left), the higher X-axis side (usualy right) and the centre. - * This is needed because often, the tile doesn't exactly align to the target - * region and is partially copied on the edges. This function computes the - * dimensions of the partially copied regions in one axis. - * - * OUTPUT: - * aLesserSidePartialMatchSize: The size of the partial match on the lesser - * side of the axis being considered. - * eg: for X-axis, usually left side and - * for Y-axis, usually top - * aHigherSidePartialMatchSize: The size of the partial match on the higher - * side of the axis being considered. - * eg: for X-axis, usually right side and - * for Y-axis, usually bottom - * aCentreSize: The size of the target area where the tile is copied in full. - * This lies between the lesser and higher side partial matches. - * (the partially matched areas may be of zero width) - * - * INPUT: - * aLesserTargetExtent: Edge of the target area on the axis being considered - * on the lesser side. (eg: usually left on the X-axis) - * aTargetSize: Size of the target area on the axis being considered (eg: - * usually width for X-axis) - * aLesserTileExtent: Edge of the tile on the axis being considered on the - * lesser side. - * aTileSize: Size of the tile on the axis being considered. - */ -static inline void -ComputePartialTileExtents(int32_t *aLesserSidePartialMatchSize, - int32_t *aHigherSidePartialMatchSize, - int32_t *aCentreSize, - int32_t aLesserTargetExtent, - int32_t aTargetSize, - int32_t aLesserTileExtent, - int32_t aTileSize) -{ - int32_t targetExtentMost = aLesserTargetExtent + aTargetSize; - int32_t tileExtentMost = aLesserTileExtent + aTileSize; - - int32_t lesserSidePartialMatchSize; - if (aLesserTileExtent < aLesserTargetExtent) { - lesserSidePartialMatchSize = tileExtentMost - aLesserTargetExtent; - } else { - lesserSidePartialMatchSize = (aLesserTileExtent - aLesserTargetExtent) % - aTileSize; - } - - int32_t higherSidePartialMatchSize; - if (lesserSidePartialMatchSize > aTargetSize) { - lesserSidePartialMatchSize = aTargetSize; - higherSidePartialMatchSize = 0; - } else if (tileExtentMost > targetExtentMost) { - higherSidePartialMatchSize = targetExtentMost - aLesserTileExtent; - } else { - higherSidePartialMatchSize = (targetExtentMost - tileExtentMost) % - aTileSize; - } - - if (lesserSidePartialMatchSize + higherSidePartialMatchSize > - aTargetSize) { - higherSidePartialMatchSize = aTargetSize - lesserSidePartialMatchSize; - } - - /* - * To understand the conditon below, let us consider the X-Axis: - * Lesser side is left and the Higher side is right. - * This implies: - * aTargetSize is rect.width. - * lesserSidePartialMatchSize would mean leftPartialTileWidth. - * higherSidePartialMatchSize would mean rightPartialTileWidth. - * - * leftPartialTileWidth == rect.width only happens when the tile entirely - * overlaps with the target area in the X-axis and exceeds its bounds by at - * least one pixel on the lower X-Axis side. - * - * leftPartialTileWidth + rightPartialTileWidth == rect.width only happens - * when the tile overlaps the target area in such a way that the edge of the - * tile on the higher X-Axis side cuts through the target area and there is no - * space for a complete tile in the X-Axis in the target area on either side - * of that edge. In this scenario, centre will be of zero width and the - * partial widths on left and right will add up to the width of the rect. In - * case the tile is bigger than the rect in the X-axis, it will get clipped - * and remain equal to rect.width. - * - * Therefore, those two conditions are separate cases which lead to centre - * being of zero width. - * - * The condition below is the same logic as above expressed independent of - * the axis in consideration. - */ - - int32_t centreSize; - if (lesserSidePartialMatchSize == aTargetSize || - lesserSidePartialMatchSize + higherSidePartialMatchSize == - aTargetSize) { - centreSize = 0; - } else { - centreSize = aTargetSize - - (lesserSidePartialMatchSize + higherSidePartialMatchSize); - } - - *aLesserSidePartialMatchSize = lesserSidePartialMatchSize; - *aHigherSidePartialMatchSize = higherSidePartialMatchSize; - *aCentreSize = centreSize; -} - -static inline void -TilePixels(uint8_t *aTargetData, - const uint8_t *aSourceData, - const nsIntRect &targetRegion, - const nsIntRect &aTile, - uint32_t aStride) -{ - if (targetRegion.IsEmpty()) { - return; - } - - uint32_t tileRowCopyMemSize = aTile.width * 4; - uint32_t numTimesToCopyTileRows = targetRegion.width / aTile.width; - - uint8_t *targetFirstRowOffset = aTargetData + 4 * targetRegion.x; - const uint8_t *tileFirstRowOffset = aSourceData + 4 * aTile.x; - - int32_t tileYOffset = 0; - for (int32_t targetY = targetRegion.y; - targetY < targetRegion.YMost(); - ++targetY) { - uint8_t *targetRowOffset = targetFirstRowOffset + aStride * targetY; - const uint8_t *tileRowOffset = tileFirstRowOffset + - aStride * (aTile.y + tileYOffset); - - for (uint32_t i = 0; i < numTimesToCopyTileRows; ++i) { - memcpy(targetRowOffset + i * tileRowCopyMemSize, - tileRowOffset, - tileRowCopyMemSize); - } - - tileYOffset = (tileYOffset + 1) % aTile.height; - } -} - -nsresult -nsSVGFETileElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - // XXX This code depends on the surface rect containing the filter - // primitive subregion. ComputeTargetBBox, ComputeNeededSourceBBoxes - // and ComputeChangeBBox are all pessimal, so that will normally be OK, - // but nothing clips mFilterPrimitiveSubregion so this should be changed. - - nsIntRect tile; - bool res = gfxUtils::GfxRectToIntRect(aSources[0]->mFilterPrimitiveSubregion, - &tile); - - NS_ENSURE_TRUE(res, NS_ERROR_FAILURE); // asserts on failure (not - if (tile.IsEmpty()) - return NS_OK; - - const nsIntRect &surfaceRect = instance->GetSurfaceRect(); - if (!tile.Intersects(surfaceRect)) { - // nothing to draw - return NS_OK; - } - - // clip tile - tile = tile.Intersect(surfaceRect); - - // Get it into surface space - tile -= surfaceRect.TopLeft(); - - uint8_t* sourceData = aSources[0]->mImage->Data(); - uint8_t* targetData = aTarget->mImage->Data(); - uint32_t stride = aTarget->mImage->Stride(); - - /* - * priority: left before right before centre - * and - * top before bottom before centre - * - * eg: If we have a target area which is 1.5 times the width of a tile, - * then, based on alignment, we get: - * 'left and right' - * or - * 'left and centre' - * - */ - - int32_t leftPartialTileWidth; - int32_t rightPartialTileWidth; - int32_t centreWidth; - ComputePartialTileExtents(&leftPartialTileWidth, - &rightPartialTileWidth, - ¢reWidth, - rect.x, - rect.width, - tile.x, - tile.width); - - int32_t topPartialTileHeight; - int32_t bottomPartialTileHeight; - int32_t centreHeight; - ComputePartialTileExtents(&topPartialTileHeight, - &bottomPartialTileHeight, - ¢reHeight, - rect.y, - rect.height, - tile.y, - tile.height); - - /* We have nine regions of the target area which have to be tiled differetly: - * - * Top Left, Top Middle, Top Right, - * Left Middle, Centre, Right Middle, - * Bottom Left, Bottom Middle, Bottom Right - * - * + Centre is tiled by repeating the tiled image in full. - * + Top Left, Top Middle and Top Right: - * Some of the rows from the top of the tile will be clipped here. - * + Bottom Left, Bottom Middle and Bottom Right: - * Some of the rows from the bottom of the tile will be clipped here. - * + Top Left, Left Middle and Bottom left: - * Some of the columns from the Left of the tile will be clipped here. - * + Top Right, Right Middle and Bottom Right: - * Some of the columns from the right of the tile will be clipped here. - * - * If the sizes and positions of the target and tile are such that the tile - * aligns exactly on any (or all) of the edges, then some (or all) of the - * regions above (except Centre) will be zero sized. - */ - - nsIntRect targetRects[] = { - // Top Left - nsIntRect(rect.x, rect.y, leftPartialTileWidth, topPartialTileHeight), - // Top Middle - nsIntRect(rect.x + leftPartialTileWidth, - rect.y, - centreWidth, - topPartialTileHeight), - // Top Right - nsIntRect(rect.XMost() - rightPartialTileWidth, - rect.y, - rightPartialTileWidth, - topPartialTileHeight), - // Left Middle - nsIntRect(rect.x, - rect.y + topPartialTileHeight, - leftPartialTileWidth, - centreHeight), - // Centre - nsIntRect(rect.x + leftPartialTileWidth, - rect.y + topPartialTileHeight, - centreWidth, - centreHeight), - // Right Middle - nsIntRect(rect.XMost() - rightPartialTileWidth, - rect.y + topPartialTileHeight, - rightPartialTileWidth, - centreHeight), - // Bottom Left - nsIntRect(rect.x, - rect.YMost() - bottomPartialTileHeight, - leftPartialTileWidth, - bottomPartialTileHeight), - // Bottom Middle - nsIntRect(rect.x + leftPartialTileWidth, - rect.YMost() - bottomPartialTileHeight, - centreWidth, - bottomPartialTileHeight), - // Bottom Right - nsIntRect(rect.XMost() - rightPartialTileWidth, - rect.YMost() - bottomPartialTileHeight, - rightPartialTileWidth, - bottomPartialTileHeight) - }; - - nsIntRect tileRects[] = { - // Top Left - nsIntRect(tile.XMost() - leftPartialTileWidth, - tile.YMost() - topPartialTileHeight, - leftPartialTileWidth, - topPartialTileHeight), - // Top Middle - nsIntRect(tile.x, - tile.YMost() - topPartialTileHeight, - tile.width, - topPartialTileHeight), - // Top Right - nsIntRect(tile.x, - tile.YMost() - topPartialTileHeight, - rightPartialTileWidth, - topPartialTileHeight), - // Left Middle - nsIntRect(tile.XMost() - leftPartialTileWidth, - tile.y, - leftPartialTileWidth, - tile.height), - // Centre - nsIntRect(tile.x, - tile.y, - tile.width, - tile.height), - // Right Middle - nsIntRect(tile.x, - tile.y, - rightPartialTileWidth, - tile.height), - // Bottom Left - nsIntRect(tile.XMost() - leftPartialTileWidth, - tile.y, - leftPartialTileWidth, - bottomPartialTileHeight), - // Bottom Middle - nsIntRect(tile.x, - tile.y, - tile.width, - bottomPartialTileHeight), - // Bottom Right - nsIntRect(tile.x, - tile.y, - rightPartialTileWidth, - bottomPartialTileHeight) - }; - - for (uint32_t i = 0; i < ArrayLength(targetRects); ++i) { - TilePixels(targetData, - sourceData, - targetRects[i], - tileRects[i], - stride); - } - - return NS_OK; -} - -bool -nsSVGFETileElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFETileElementBase::AttributeAffectsRendering(aNameSpaceID, - aAttribute) || - (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::in); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::StringAttributesInfo -nsSVGFETileElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------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(); - - 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() +SVGFEBlendElement::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() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFEMorphologyElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -//---------------------Convolve Matrix------------------------ - -typedef nsSVGFE nsSVGFEConvolveMatrixElementBase; - -class nsSVGFEConvolveMatrixElement : public nsSVGFEConvolveMatrixElementBase, - public nsIDOMSVGFEConvolveMatrixElement -{ - friend nsresult NS_NewSVGFEConvolveMatrixElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEConvolveMatrixElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEConvolveMatrixElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEConvolveMatrixElementBase::) - - 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); - - // Color Matrix - NS_DECL_NSIDOMSVGFECONVOLVEMATRIXELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEConvolveMatrixElementBase::) - - 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 bool OperatesOnPremultipledAlpha(int32_t) { - return !mBooleanAttributes[PRESERVEALPHA].GetAnimValue(); - } - - virtual NumberAttributesInfo GetNumberInfo(); - virtual NumberPairAttributesInfo GetNumberPairInfo(); - virtual IntegerAttributesInfo GetIntegerInfo(); - virtual IntegerPairAttributesInfo GetIntegerPairInfo(); - virtual BooleanAttributesInfo GetBooleanInfo(); - virtual EnumAttributesInfo GetEnumInfo(); - virtual StringAttributesInfo GetStringInfo(); - virtual NumberListAttributesInfo GetNumberListInfo(); - - enum { DIVISOR, BIAS }; - nsSVGNumber2 mNumberAttributes[2]; - static NumberInfo sNumberInfo[2]; - - enum { KERNEL_UNIT_LENGTH }; - nsSVGNumberPair mNumberPairAttributes[1]; - static NumberPairInfo sNumberPairInfo[1]; - - enum { TARGET_X, TARGET_Y }; - nsSVGInteger mIntegerAttributes[2]; - static IntegerInfo sIntegerInfo[2]; - - enum { ORDER }; - nsSVGIntegerPair mIntegerPairAttributes[1]; - static IntegerPairInfo sIntegerPairInfo[1]; - - enum { PRESERVEALPHA }; - nsSVGBoolean mBooleanAttributes[1]; - static BooleanInfo sBooleanInfo[1]; - - enum { EDGEMODE }; - nsSVGEnum mEnumAttributes[1]; - static nsSVGEnumMapping sEdgeModeMap[]; - static EnumInfo sEnumInfo[1]; - - enum { RESULT, IN1 }; - nsSVGString mStringAttributes[2]; - static StringInfo sStringInfo[2]; - - enum { KERNELMATRIX }; - SVGAnimatedNumberList mNumberListAttributes[1]; - static NumberListInfo sNumberListInfo[1]; -}; - -nsSVGElement::NumberInfo nsSVGFEConvolveMatrixElement::sNumberInfo[2] = -{ - { &nsGkAtoms::divisor, 1, false }, - { &nsGkAtoms::bias, 0, false } -}; - -nsSVGElement::NumberPairInfo nsSVGFEConvolveMatrixElement::sNumberPairInfo[1] = -{ - { &nsGkAtoms::kernelUnitLength, 0, 0 } -}; - -nsSVGElement::IntegerInfo nsSVGFEConvolveMatrixElement::sIntegerInfo[2] = -{ - { &nsGkAtoms::targetX, 0 }, - { &nsGkAtoms::targetY, 0 } -}; - -nsSVGElement::IntegerPairInfo nsSVGFEConvolveMatrixElement::sIntegerPairInfo[1] = -{ - { &nsGkAtoms::order, 3, 3 } -}; - -nsSVGElement::BooleanInfo nsSVGFEConvolveMatrixElement::sBooleanInfo[1] = -{ - { &nsGkAtoms::preserveAlpha, false } -}; - -nsSVGEnumMapping nsSVGFEConvolveMatrixElement::sEdgeModeMap[] = { - {&nsGkAtoms::duplicate, nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_DUPLICATE}, - {&nsGkAtoms::wrap, nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_WRAP}, - {&nsGkAtoms::none, nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_NONE}, - {nullptr, 0} -}; - -nsSVGElement::EnumInfo nsSVGFEConvolveMatrixElement::sEnumInfo[1] = -{ - { &nsGkAtoms::edgeMode, - sEdgeModeMap, - nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_DUPLICATE - } -}; - -nsSVGElement::StringInfo nsSVGFEConvolveMatrixElement::sStringInfo[2] = -{ - { &nsGkAtoms::result, kNameSpaceID_None, true }, - { &nsGkAtoms::in, kNameSpaceID_None, true } -}; - -nsSVGElement::NumberListInfo nsSVGFEConvolveMatrixElement::sNumberListInfo[1] = -{ - { &nsGkAtoms::kernelMatrix } -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEConvolveMatrix) - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEConvolveMatrixElement,nsSVGFEConvolveMatrixElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEConvolveMatrixElement,nsSVGFEConvolveMatrixElementBase) - -DOMCI_NODE_DATA(SVGFEConvolveMatrixElement, nsSVGFEConvolveMatrixElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEConvolveMatrixElement) - NS_NODE_INTERFACE_TABLE5(nsSVGFEConvolveMatrixElement, nsIDOMNode, - nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGFilterPrimitiveStandardAttributes, - nsIDOMSVGFEConvolveMatrixElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEConvolveMatrixElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEConvolveMatrixElementBase) - - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEConvolveMatrixElement) - -//---------------------------------------------------------------------- -// nsSVGFEConvolveMatrixElement methods - -NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetIn1(nsIDOMSVGAnimatedString * *aIn) -{ - return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this); -} - -NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetOrderX(nsIDOMSVGAnimatedInteger * *aOrderX) -{ - return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(aOrderX, nsSVGIntegerPair::eFirst, this); -} - -NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetOrderY(nsIDOMSVGAnimatedInteger * *aOrderY) -{ - return mIntegerPairAttributes[ORDER].ToDOMAnimatedInteger(aOrderY, nsSVGIntegerPair::eSecond, this); -} - -NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetKernelMatrix(nsISupports * *aKernelMatrix) -{ - *aKernelMatrix = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[KERNELMATRIX], - this, KERNELMATRIX).get(); - return NS_OK; -} - -NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetTargetX(nsIDOMSVGAnimatedInteger * *aTargetX) -{ - return mIntegerAttributes[TARGET_X].ToDOMAnimatedInteger(aTargetX, this); -} - -NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetTargetY(nsIDOMSVGAnimatedInteger * *aTargetY) -{ - return mIntegerAttributes[TARGET_Y].ToDOMAnimatedInteger(aTargetY, this); -} - -NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetEdgeMode(nsIDOMSVGAnimatedEnumeration * *aEdgeMode) -{ - return mEnumAttributes[EDGEMODE].ToDOMAnimatedEnum(aEdgeMode, this); -} - -NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetPreserveAlpha(nsISupports * *aPreserveAlpha) -{ - return mBooleanAttributes[PRESERVEALPHA].ToDOMAnimatedBoolean(aPreserveAlpha, this); -} - -NS_IMETHODIMP -nsSVGFEConvolveMatrixElement::GetDivisor(nsIDOMSVGAnimatedNumber **aDivisor) -{ - return mNumberAttributes[DIVISOR].ToDOMAnimatedNumber(aDivisor, this); -} - -NS_IMETHODIMP -nsSVGFEConvolveMatrixElement::GetBias(nsIDOMSVGAnimatedNumber **aBias) -{ - return mNumberAttributes[BIAS].ToDOMAnimatedNumber(aBias, this); -} - -NS_IMETHODIMP -nsSVGFEConvolveMatrixElement::GetKernelUnitLengthX(nsIDOMSVGAnimatedNumber **aKernelX) -{ - return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(aKernelX, - nsSVGNumberPair::eFirst, - this); -} - -NS_IMETHODIMP -nsSVGFEConvolveMatrixElement::GetKernelUnitLengthY(nsIDOMSVGAnimatedNumber **aKernelY) -{ - return mNumberPairAttributes[KERNEL_UNIT_LENGTH].ToDOMAnimatedNumber(aKernelY, - nsSVGNumberPair::eSecond, - this); -} - -void -nsSVGFEConvolveMatrixElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) -{ - aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this)); -} - -nsIntRect -nsSVGFEConvolveMatrixElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes, - const nsSVGFilterInstance& aInstance) -{ - // XXX A more precise box is possible when 'bias' is zero and 'edgeMode' is - // 'none', but it requires analysis of 'kernelUnitLength', 'order' and - // 'targetX/Y', so it's quite a lot of work. Don't do it for now. - return GetMaxRect(); -} - -void -nsSVGFEConvolveMatrixElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance) -{ - // XXX Precise results are possible but we're going to skip that work - // for now. Do nothing, which means the needed-box remains the - // source's output bounding box. -} - -nsIntRect -nsSVGFEConvolveMatrixElement::ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance) -{ - // XXX Precise results are possible but we're going to skip that work - // for now. - return GetMaxRect(); -} - -static int32_t BoundInterval(int32_t aVal, int32_t aMax) -{ - aVal = std::max(aVal, 0); - return std::min(aVal, aMax - 1); -} - -static void -ConvolvePixel(const uint8_t *aSourceData, - uint8_t *aTargetData, - int32_t aWidth, int32_t aHeight, - int32_t aStride, - int32_t aX, int32_t aY, - uint16_t aEdgeMode, - const float *aKernel, - float aDivisor, float aBias, - bool aPreserveAlpha, - int32_t aOrderX, int32_t aOrderY, - int32_t aTargetX, int32_t aTargetY) -{ - float sum[4] = {0, 0, 0, 0}; - aBias *= 255; - int32_t offsets[4] = {GFX_ARGB32_OFFSET_R, - GFX_ARGB32_OFFSET_G, - GFX_ARGB32_OFFSET_B, - GFX_ARGB32_OFFSET_A } ; - int32_t channels = aPreserveAlpha ? 3 : 4; - - for (int32_t y = 0; y < aOrderY; y++) { - int32_t sampleY = aY + y - aTargetY; - bool overscanY = sampleY < 0 || sampleY >= aHeight; - for (int32_t x = 0; x < aOrderX; x++) { - int32_t sampleX = aX + x - aTargetX; - bool overscanX = sampleX < 0 || sampleX >= aWidth; - for (int32_t i = 0; i < channels; i++) { - if (overscanY || overscanX) { - switch (aEdgeMode) { - case nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_DUPLICATE: - sum[i] += - aSourceData[BoundInterval(sampleY, aHeight) * aStride + - BoundInterval(sampleX, aWidth) * 4 + offsets[i]] * - aKernel[aOrderX * y + x]; - break; - case nsSVGFEConvolveMatrixElement::SVG_EDGEMODE_WRAP: - sum[i] += - aSourceData[WrapInterval(sampleY, aHeight) * aStride + - WrapInterval(sampleX, aWidth) * 4 + offsets[i]] * - aKernel[aOrderX * y + x]; - break; - default: - break; - } - } else { - sum[i] += - aSourceData[sampleY * aStride + 4 * sampleX + offsets[i]] * - aKernel[aOrderX * y + x]; - } - } - } - } - for (int32_t i = 0; i < channels; i++) { - aTargetData[aY * aStride + 4 * aX + offsets[i]] = - BoundInterval(static_cast<int32_t>(sum[i] / aDivisor + aBias), 256); - } - if (aPreserveAlpha) { - aTargetData[aY * aStride + 4 * aX + GFX_ARGB32_OFFSET_A] = - aSourceData[aY * aStride + 4 * aX + GFX_ARGB32_OFFSET_A]; - } -} - -nsresult -nsSVGFEConvolveMatrixElement::Filter(nsSVGFilterInstance *instance, - const nsTArray<const Image*>& aSources, - const Image* aTarget, - const nsIntRect& rect) -{ - const SVGNumberList &kernelMatrix = - mNumberListAttributes[KERNELMATRIX].GetAnimValue(); - uint32_t kmLength = kernelMatrix.Length(); - - int32_t orderX = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eFirst); - int32_t orderY = mIntegerPairAttributes[ORDER].GetAnimValue(nsSVGIntegerPair::eSecond); - - if (orderX <= 0 || orderY <= 0 || - static_cast<uint32_t>(orderX * orderY) != kmLength) { - return NS_ERROR_FAILURE; - } - - int32_t targetX, targetY; - GetAnimatedIntegerValues(&targetX, &targetY, nullptr); - - if (mIntegerAttributes[TARGET_X].IsExplicitlySet()) { - if (targetX < 0 || targetX >= orderX) - return NS_ERROR_FAILURE; - } else { - targetX = orderX / 2; - } - if (mIntegerAttributes[TARGET_Y].IsExplicitlySet()) { - if (targetY < 0 || targetY >= orderY) - return NS_ERROR_FAILURE; - } else { - targetY = orderY / 2; - } - - if (orderX > NS_SVG_OFFSCREEN_MAX_DIMENSION || - orderY > NS_SVG_OFFSCREEN_MAX_DIMENSION) - return NS_ERROR_FAILURE; - nsAutoArrayPtr<float> kernel(new float[orderX * orderY]); - if (!kernel) - return NS_ERROR_FAILURE; - for (uint32_t i = 0; i < kmLength; i++) { - kernel[kmLength - 1 - i] = kernelMatrix[i]; - } - - float divisor; - if (mNumberAttributes[DIVISOR].IsExplicitlySet()) { - divisor = mNumberAttributes[DIVISOR].GetAnimValue(); - if (divisor == 0) - return NS_ERROR_FAILURE; - } else { - divisor = kernel[0]; - for (uint32_t i = 1; i < kmLength; i++) - divisor += kernel[i]; - if (divisor == 0) - divisor = 1; - } - - ScaleInfo info = SetupScalingFilter(instance, aSources[0], aTarget, rect, - &mNumberPairAttributes[KERNEL_UNIT_LENGTH]); - if (!info.mTarget) - return NS_ERROR_FAILURE; - - uint16_t edgeMode = mEnumAttributes[EDGEMODE].GetAnimValue(); - bool preserveAlpha = mBooleanAttributes[PRESERVEALPHA].GetAnimValue(); - - float bias = mNumberAttributes[BIAS].GetAnimValue(); - - const nsIntRect& dataRect = info.mDataRect; - int32_t stride = info.mSource->Stride(); - int32_t width = info.mSource->GetSize().width; - int32_t height = info.mSource->GetSize().height; - uint8_t *sourceData = info.mSource->Data(); - uint8_t *targetData = info.mTarget->Data(); - - for (int32_t y = dataRect.y; y < dataRect.YMost(); y++) { - for (int32_t x = dataRect.x; x < dataRect.XMost(); x++) { - ConvolvePixel(sourceData, targetData, - width, height, stride, - x, y, - edgeMode, kernel, divisor, bias, preserveAlpha, - orderX, orderY, targetX, targetY); - } - } - - FinishScalingFilter(&info); - - return NS_OK; -} - -bool -nsSVGFEConvolveMatrixElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return nsSVGFEConvolveMatrixElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) || - (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::in || - aAttribute == nsGkAtoms::divisor || - aAttribute == nsGkAtoms::bias || - aAttribute == nsGkAtoms::kernelUnitLength || - aAttribute == nsGkAtoms::targetX || - aAttribute == nsGkAtoms::targetY || - aAttribute == nsGkAtoms::order || - aAttribute == nsGkAtoms::preserveAlpha|| - aAttribute == nsGkAtoms::edgeMode || - aAttribute == nsGkAtoms::kernelMatrix)); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFEConvolveMatrixElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -nsSVGElement::NumberPairAttributesInfo -nsSVGFEConvolveMatrixElement::GetNumberPairInfo() -{ - return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo, - ArrayLength(sNumberPairInfo)); -} - -nsSVGElement::IntegerAttributesInfo -nsSVGFEConvolveMatrixElement::GetIntegerInfo() -{ - return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo, - ArrayLength(sIntegerInfo)); -} - -nsSVGElement::IntegerPairAttributesInfo -nsSVGFEConvolveMatrixElement::GetIntegerPairInfo() -{ - return IntegerPairAttributesInfo(mIntegerPairAttributes, sIntegerPairInfo, - ArrayLength(sIntegerPairInfo)); -} - -nsSVGElement::BooleanAttributesInfo -nsSVGFEConvolveMatrixElement::GetBooleanInfo() -{ - return BooleanAttributesInfo(mBooleanAttributes, sBooleanInfo, - ArrayLength(sBooleanInfo)); -} - -nsSVGElement::EnumAttributesInfo -nsSVGFEConvolveMatrixElement::GetEnumInfo() -{ - return EnumAttributesInfo(mEnumAttributes, sEnumInfo, - ArrayLength(sEnumInfo)); -} - -nsSVGElement::StringAttributesInfo -nsSVGFEConvolveMatrixElement::GetStringInfo() -{ - return StringAttributesInfo(mStringAttributes, sStringInfo, - ArrayLength(sStringInfo)); -} - -nsSVGElement::NumberListAttributesInfo -nsSVGFEConvolveMatrixElement::GetNumberListInfo() -{ - return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo, - ArrayLength(sNumberListInfo)); -} - -//---------------------DistantLight------------------------ - -typedef SVGFEUnstyledElement nsSVGFEDistantLightElementBase; - -class nsSVGFEDistantLightElement : public nsSVGFEDistantLightElementBase, - public nsIDOMSVGFEDistantLightElement -{ - friend nsresult NS_NewSVGFEDistantLightElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEDistantLightElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEDistantLightElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIDOMSVGFEDISTANTLIGHTELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEDistantLightElementBase::) - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - virtual bool AttributeAffectsRendering( - int32_t aNameSpaceID, nsIAtom* aAttribute) const; - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual NumberAttributesInfo GetNumberInfo(); - - enum { AZIMUTH, ELEVATION }; - nsSVGNumber2 mNumberAttributes[2]; - static NumberInfo sNumberInfo[2]; -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEDistantLight) - -nsSVGElement::NumberInfo nsSVGFEDistantLightElement::sNumberInfo[2] = -{ - { &nsGkAtoms::azimuth, 0, false }, - { &nsGkAtoms::elevation, 0, false } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEDistantLightElement,nsSVGFEDistantLightElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEDistantLightElement,nsSVGFEDistantLightElementBase) - -DOMCI_NODE_DATA(SVGFEDistantLightElement, nsSVGFEDistantLightElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEDistantLightElement) - NS_NODE_INTERFACE_TABLE4(nsSVGFEDistantLightElement, nsIDOMNode, - nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGFEDistantLightElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEDistantLightElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEDistantLightElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEDistantLightElement) - -//---------------------------------------------------------------------- -// nsFEUnstyledElement methods - -bool -nsSVGFEDistantLightElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::azimuth || - aAttribute == nsGkAtoms::elevation); -} - -//---------------------------------------------------------------------- -// nsIDOMSVGFEDistantLightElement methods - -NS_IMETHODIMP -nsSVGFEDistantLightElement::GetAzimuth(nsIDOMSVGAnimatedNumber **aAzimuth) -{ - return mNumberAttributes[AZIMUTH].ToDOMAnimatedNumber(aAzimuth, - this); -} - -NS_IMETHODIMP -nsSVGFEDistantLightElement::GetElevation(nsIDOMSVGAnimatedNumber **aElevation) -{ - return mNumberAttributes[ELEVATION].ToDOMAnimatedNumber(aElevation, - this); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFEDistantLightElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -//---------------------PointLight------------------------ - -typedef SVGFEUnstyledElement nsSVGFEPointLightElementBase; - -class nsSVGFEPointLightElement : public nsSVGFEPointLightElementBase, - public nsIDOMSVGFEPointLightElement -{ - friend nsresult NS_NewSVGFEPointLightElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); -protected: - nsSVGFEPointLightElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFEPointLightElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIDOMSVGFEPOINTLIGHTELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEPointLightElementBase::) - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - virtual bool AttributeAffectsRendering( - int32_t aNameSpaceID, nsIAtom* aAttribute) const; - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual NumberAttributesInfo GetNumberInfo(); - - enum { X, Y, Z }; - nsSVGNumber2 mNumberAttributes[3]; - static NumberInfo sNumberInfo[3]; -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FEPointLight) - -nsSVGElement::NumberInfo nsSVGFEPointLightElement::sNumberInfo[3] = -{ - { &nsGkAtoms::x, 0, false }, - { &nsGkAtoms::y, 0, false }, - { &nsGkAtoms::z, 0, false } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFEPointLightElement,nsSVGFEPointLightElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFEPointLightElement,nsSVGFEPointLightElementBase) - -DOMCI_NODE_DATA(SVGFEPointLightElement, nsSVGFEPointLightElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFEPointLightElement) - NS_NODE_INTERFACE_TABLE4(nsSVGFEPointLightElement, nsIDOMNode, - nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGFEPointLightElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEPointLightElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFEPointLightElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEPointLightElement) - -//---------------------------------------------------------------------- -// nsFEUnstyledElement methods - -bool -nsSVGFEPointLightElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::x || - aAttribute == nsGkAtoms::y || - aAttribute == nsGkAtoms::z); -} - -//---------------------------------------------------------------------- -// nsIDOMSVGFEPointLightElement methods - -NS_IMETHODIMP -nsSVGFEPointLightElement::GetX(nsIDOMSVGAnimatedNumber **aX) -{ - return mNumberAttributes[X].ToDOMAnimatedNumber(aX, this); -} - -NS_IMETHODIMP -nsSVGFEPointLightElement::GetY(nsIDOMSVGAnimatedNumber **aY) -{ - return mNumberAttributes[Y].ToDOMAnimatedNumber(aY, this); -} - -NS_IMETHODIMP -nsSVGFEPointLightElement::GetZ(nsIDOMSVGAnimatedNumber **aZ) -{ - return mNumberAttributes[Z].ToDOMAnimatedNumber(aZ, this); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFEPointLightElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -//---------------------SpotLight------------------------ - -typedef SVGFEUnstyledElement nsSVGFESpotLightElementBase; - -class nsSVGFESpotLightElement : public nsSVGFESpotLightElementBase, - public nsIDOMSVGFESpotLightElement -{ - friend nsresult NS_NewSVGFESpotLightElement(nsIContent **aResult, - already_AddRefed<nsINodeInfo> aNodeInfo); - friend class nsSVGFELightingElement; -protected: - nsSVGFESpotLightElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFESpotLightElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIDOMSVGFESPOTLIGHTELEMENT - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFESpotLightElementBase::) - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_FORWARD_NSIDOMELEMENT_TO_GENERIC - - virtual bool AttributeAffectsRendering( - int32_t aNameSpaceID, nsIAtom* aAttribute) const; - - virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; - - virtual nsXPCClassInfo* GetClassInfo(); - - virtual nsIDOMNode* AsDOMNode() { return this; } -protected: - virtual NumberAttributesInfo GetNumberInfo(); - - enum { X, Y, Z, POINTS_AT_X, POINTS_AT_Y, POINTS_AT_Z, - SPECULAR_EXPONENT, LIMITING_CONE_ANGLE }; - nsSVGNumber2 mNumberAttributes[8]; - static NumberInfo sNumberInfo[8]; -}; - -NS_IMPL_NS_NEW_SVG_ELEMENT(FESpotLight) - -nsSVGElement::NumberInfo nsSVGFESpotLightElement::sNumberInfo[8] = -{ - { &nsGkAtoms::x, 0, false }, - { &nsGkAtoms::y, 0, false }, - { &nsGkAtoms::z, 0, false }, - { &nsGkAtoms::pointsAtX, 0, false }, - { &nsGkAtoms::pointsAtY, 0, false }, - { &nsGkAtoms::pointsAtZ, 0, false }, - { &nsGkAtoms::specularExponent, 1, false }, - { &nsGkAtoms::limitingConeAngle, 0, false } -}; - -//---------------------------------------------------------------------- -// nsISupports methods - -NS_IMPL_ADDREF_INHERITED(nsSVGFESpotLightElement,nsSVGFESpotLightElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGFESpotLightElement,nsSVGFESpotLightElementBase) - -DOMCI_NODE_DATA(SVGFESpotLightElement, nsSVGFESpotLightElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGFESpotLightElement) - NS_NODE_INTERFACE_TABLE4(nsSVGFESpotLightElement, nsIDOMNode, - nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGFESpotLightElement) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFESpotLightElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGFESpotLightElementBase) - -//---------------------------------------------------------------------- -// nsIDOMNode methods - -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFESpotLightElement) - -//---------------------------------------------------------------------- -// nsFEUnstyledElement methods - -bool -nsSVGFESpotLightElement::AttributeAffectsRendering(int32_t aNameSpaceID, - nsIAtom* aAttribute) const -{ - return aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::x || - aAttribute == nsGkAtoms::y || - aAttribute == nsGkAtoms::z || - aAttribute == nsGkAtoms::pointsAtX || - aAttribute == nsGkAtoms::pointsAtY || - aAttribute == nsGkAtoms::pointsAtZ || - aAttribute == nsGkAtoms::specularExponent || - aAttribute == nsGkAtoms::limitingConeAngle); -} - -//---------------------------------------------------------------------- -// nsIDOMSVGFESpotLightElement methods - -NS_IMETHODIMP -nsSVGFESpotLightElement::GetX(nsIDOMSVGAnimatedNumber **aX) -{ - return mNumberAttributes[X].ToDOMAnimatedNumber(aX, this); -} - -NS_IMETHODIMP -nsSVGFESpotLightElement::GetY(nsIDOMSVGAnimatedNumber **aY) -{ - return mNumberAttributes[Y].ToDOMAnimatedNumber(aY, this); -} - -NS_IMETHODIMP -nsSVGFESpotLightElement::GetZ(nsIDOMSVGAnimatedNumber **aZ) -{ - return mNumberAttributes[Z].ToDOMAnimatedNumber(aZ, this); -} - -NS_IMETHODIMP -nsSVGFESpotLightElement::GetPointsAtX(nsIDOMSVGAnimatedNumber **aX) -{ - return mNumberAttributes[POINTS_AT_X].ToDOMAnimatedNumber(aX, this); -} - -NS_IMETHODIMP -nsSVGFESpotLightElement::GetPointsAtY(nsIDOMSVGAnimatedNumber **aY) -{ - return mNumberAttributes[POINTS_AT_Y].ToDOMAnimatedNumber(aY, this); -} - -NS_IMETHODIMP -nsSVGFESpotLightElement::GetPointsAtZ(nsIDOMSVGAnimatedNumber **aZ) -{ - return mNumberAttributes[POINTS_AT_Z].ToDOMAnimatedNumber(aZ, this); -} - -NS_IMETHODIMP -nsSVGFESpotLightElement::GetSpecularExponent(nsIDOMSVGAnimatedNumber **aExponent) -{ - return mNumberAttributes[SPECULAR_EXPONENT].ToDOMAnimatedNumber(aExponent, - this); -} - -NS_IMETHODIMP -nsSVGFESpotLightElement::GetLimitingConeAngle(nsIDOMSVGAnimatedNumber **aAngle) -{ - return mNumberAttributes[LIMITING_CONE_ANGLE].ToDOMAnimatedNumber(aAngle, - this); -} - -//---------------------------------------------------------------------- -// nsSVGElement methods - -nsSVGElement::NumberAttributesInfo -nsSVGFESpotLightElement::GetNumberInfo() -{ - return NumberAttributesInfo(mNumberAttributes, sNumberInfo, - ArrayLength(sNumberInfo)); -} - -//------------------------------------------------------------ - -typedef nsSVGFE nsSVGFELightingElementBase; - -class nsSVGFELightingElement : public nsSVGFELightingElementBase -{ -protected: - nsSVGFELightingElement(already_AddRefed<nsINodeInfo> aNodeInfo) - : nsSVGFELightingElementBase(aNodeInfo) {} - -public: - // interfaces: - NS_DECL_ISUPPORTS_INHERITED - - // FE Base - NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFELightingElementBase::) - - 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); - // XXX shouldn't we have ComputeTargetBBox here, since the output can - // extend beyond the bounds of the inputs thanks to the convolution kernel? - virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox, - nsTArray<nsIntRect>& aSourceBBoxes, const nsSVGFilterInstance& aInstance); - virtual nsIntRect ComputeChangeBBox(const nsTArray<nsIntRect>& aSourceChangeBoxes, - const nsSVGFilterInstance& aInstance); - - NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFELightingElementBase::) - - NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const; - -protected: - virtual bool OperatesOnSRGB(nsSVGFilterInstance*, - int32_t, Image*) { return true; } - virtual void - LightPixel(const float *N, const float *L, - nscolor color, uint8_t *targetData) = 0; - - virtual NumberAttributesInfo GetNumberInfo(); - virtual NumberPairAttributesInfo GetNumberPairInfo(); - virtual StringAttributesInfo GetStringInfo(); - - enum { SURFACE_SCALE, DIFFUSE_CONSTANT, SPECULAR_CONSTANT, SPECULAR_EXPONENT }; - nsSVGNumber2 mNumberAttributes[4]; - static NumberInfo sNumberInfo[4]; - - enum { KERNEL_UNIT_LENGTH }; - nsSVGNumberPair mNumberPairAttributes[1]; - static NumberPairInfo sNumberPairInfo[1]; - - enum { RESULT, IN1 }; - nsSVGString mStringAttributes[2]; - static StringInfo sStringInfo[2]; -}; - -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(); -} - -#define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]) -#define NORMALIZE(vec) \ - PR_BEGIN_MACRO \ - float norm = sqrt(DOT(vec, vec)); \ - vec[0] /= norm; \ - vec[1] /= norm; \ - vec[2] /= norm; \ - PR_END_MACRO - -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;