Blame layout/svg/SVGObserverUtils.h

Packit f0b94e
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
Packit f0b94e
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
Packit f0b94e
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit f0b94e
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit f0b94e
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit f0b94e
Packit f0b94e
#ifndef NSSVGEFFECTS_H_
Packit f0b94e
#define NSSVGEFFECTS_H_
Packit f0b94e
Packit f0b94e
#include "mozilla/Attributes.h"
Packit f0b94e
#include "mozilla/dom/IDTracker.h"
Packit f0b94e
#include "FrameProperties.h"
Packit f0b94e
#include "mozilla/dom/Element.h"
Packit f0b94e
#include "nsHashKeys.h"
Packit f0b94e
#include "nsID.h"
Packit f0b94e
#include "nsIFrame.h"
Packit f0b94e
#include "nsIMutationObserver.h"
Packit f0b94e
#include "nsInterfaceHashtable.h"
Packit f0b94e
#include "nsISupportsBase.h"
Packit f0b94e
#include "nsISupportsImpl.h"
Packit f0b94e
#include "nsStubMutationObserver.h"
Packit f0b94e
#include "nsSVGUtils.h"
Packit f0b94e
#include "nsTHashtable.h"
Packit f0b94e
#include "nsURIHashKey.h"
Packit f0b94e
#include "nsCycleCollectionParticipant.h"
Packit f0b94e
Packit f0b94e
class nsAtom;
Packit f0b94e
class nsIPresShell;
Packit f0b94e
class nsIURI;
Packit f0b94e
class nsSVGClipPathFrame;
Packit f0b94e
class nsSVGPaintServerFrame;
Packit f0b94e
class nsSVGFilterFrame;
Packit f0b94e
class nsSVGMaskFrame;
Packit f0b94e
class nsSVGFilterChainObserver;
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * This interface allows us to be notified when a piece of SVG content is
Packit f0b94e
 * re-rendered.
Packit f0b94e
 *
Packit f0b94e
 * Concrete implementations of this interface need to implement
Packit f0b94e
 * "GetTarget()" to specify the piece of SVG content that they'd like to
Packit f0b94e
 * monitor, and they need to implement "OnRenderingChange" to specify how
Packit f0b94e
 * we'll react when that content gets re-rendered. They also need to implement
Packit f0b94e
 * a constructor and destructor, which should call StartObserving and
Packit f0b94e
 * StopObserving, respectively.
Packit f0b94e
 */
Packit f0b94e
class nsSVGRenderingObserver : public nsStubMutationObserver {
Packit f0b94e
 protected:
Packit f0b94e
  virtual ~nsSVGRenderingObserver() {}
Packit f0b94e
Packit f0b94e
 public:
Packit f0b94e
  typedef mozilla::dom::Element Element;
Packit f0b94e
  nsSVGRenderingObserver() : mInObserverList(false) {}
Packit f0b94e
Packit f0b94e
  // nsIMutationObserver
Packit f0b94e
  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
Packit f0b94e
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
Packit f0b94e
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
Packit f0b94e
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Called when non-DOM-mutation changes to the observed element should likely
Packit f0b94e
   * cause the rendering of our observer to change.  This includes changes to
Packit f0b94e
   * CSS computed values, but also changes to rendering observers that the
Packit f0b94e
   * observed element itself may have (for example, when we're being used to
Packit f0b94e
   * observe an SVG pattern, and an element in that pattern references and
Packit f0b94e
   * observes a gradient that has changed).
Packit f0b94e
   */
Packit f0b94e
  void OnNonDOMMutationRenderingChange();
Packit f0b94e
Packit f0b94e
  // When a nsSVGRenderingObserver list gets forcibly cleared, it uses this
Packit f0b94e
  // callback to notify every observer that's cleared from it, so they can
Packit f0b94e
  // react.
Packit f0b94e
  void NotifyEvictedFromRenderingObserverList();
Packit f0b94e
Packit f0b94e
  bool IsInObserverList() const { return mInObserverList; }
Packit f0b94e
Packit f0b94e
  nsIFrame* GetReferencedFrame();
Packit f0b94e
  /**
Packit f0b94e
   * @param aOK this is only for the convenience of callers. We set *aOK to
Packit f0b94e
   * false if the frame is the wrong type
Packit f0b94e
   */
Packit f0b94e
  nsIFrame* GetReferencedFrame(mozilla::LayoutFrameType aFrameType, bool* aOK);
Packit f0b94e
Packit f0b94e
  Element* GetReferencedElement();
Packit f0b94e
Packit f0b94e
  virtual bool ObservesReflow() { return true; }
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  void StartObserving();
Packit f0b94e
  void StopObserving();
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Called whenever the rendering of the observed element may have changed.
Packit f0b94e
   *
Packit f0b94e
   * More specifically, this method is called whenever DOM mutation occurs in
Packit f0b94e
   * the observed element's subtree, or whenever
Packit f0b94e
   * SVGObserverUtils::InvalidateRenderingObservers or
Packit f0b94e
   * SVGObserverUtils::InvalidateDirectRenderingObservers is called for the
Packit f0b94e
   * observed element's frame.
Packit f0b94e
   *
Packit f0b94e
   * Subclasses should override this method to handle rendering changes
Packit f0b94e
   * appropriately.
Packit f0b94e
   */
Packit f0b94e
  virtual void OnRenderingChange() = 0;
Packit f0b94e
Packit f0b94e
  // This is an internally-used version of GetReferencedElement that doesn't
Packit f0b94e
  // forcibly add us as an observer. (whereas GetReferencedElement does)
Packit f0b94e
  virtual Element* GetTarget() = 0;
Packit f0b94e
Packit f0b94e
  // Whether we're in our referenced element's observer list at this time.
Packit f0b94e
  bool mInObserverList;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * SVG elements reference supporting resources by element ID. We need to
Packit f0b94e
 * track when those resources change and when the DOM changes in ways
Packit f0b94e
 * that affect which element is referenced by a given ID (e.g., when
Packit f0b94e
 * element IDs change). The code here is responsible for that.
Packit f0b94e
 *
Packit f0b94e
 * When a frame references a supporting resource, we create a property
Packit f0b94e
 * object derived from nsSVGIDRenderingObserver to manage the relationship. The
Packit f0b94e
 * property object is attached to the referencing frame.
Packit f0b94e
 */
Packit f0b94e
class nsSVGIDRenderingObserver : public nsSVGRenderingObserver {
Packit f0b94e
 public:
Packit f0b94e
  typedef mozilla::dom::Element Element;
Packit f0b94e
  typedef mozilla::dom::IDTracker IDTracker;
Packit f0b94e
Packit f0b94e
  nsSVGIDRenderingObserver(nsIURI* aURI, nsIContent* aObservingContent,
Packit f0b94e
                           bool aReferenceImage);
Packit f0b94e
  virtual ~nsSVGIDRenderingObserver();
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  Element* GetTarget() override { return mObservedElementTracker.get(); }
Packit f0b94e
Packit f0b94e
  void OnRenderingChange() override;
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Helper that provides a reference to the element with the ID that our
Packit f0b94e
   * observer wants to observe, and that will invalidate our observer if the
Packit f0b94e
   * element that that ID identifies changes to a different element (or none).
Packit f0b94e
   */
Packit f0b94e
  class ElementTracker final : public IDTracker {
Packit f0b94e
   public:
Packit f0b94e
    explicit ElementTracker(nsSVGIDRenderingObserver* aOwningObserver)
Packit f0b94e
        : mOwningObserver(aOwningObserver) {}
Packit f0b94e
Packit f0b94e
   protected:
Packit f0b94e
    virtual void ElementChanged(Element* aFrom, Element* aTo) override {
Packit f0b94e
      mOwningObserver->StopObserving();  // stop observing the old element
Packit f0b94e
      IDTracker::ElementChanged(aFrom, aTo);
Packit f0b94e
      mOwningObserver->StartObserving();  // start observing the new element
Packit f0b94e
      mOwningObserver->OnRenderingChange();
Packit f0b94e
    }
Packit f0b94e
    /**
Packit f0b94e
     * Override IsPersistent because we want to keep tracking the element
Packit f0b94e
     * for the ID even when it changes.
Packit f0b94e
     */
Packit f0b94e
    virtual bool IsPersistent() override { return true; }
Packit f0b94e
Packit f0b94e
   private:
Packit f0b94e
    nsSVGIDRenderingObserver* mOwningObserver;
Packit f0b94e
  };
Packit f0b94e
Packit f0b94e
  ElementTracker mObservedElementTracker;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
struct nsSVGFrameReferenceFromProperty {
Packit f0b94e
  explicit nsSVGFrameReferenceFromProperty(nsIFrame* aFrame)
Packit f0b94e
      : mFrame(aFrame), mFramePresShell(aFrame->PresShell()) {}
Packit f0b94e
Packit f0b94e
  // Clear our reference to the frame.
Packit f0b94e
  void Detach();
Packit f0b94e
Packit f0b94e
  // null if the frame has become invalid
Packit f0b94e
  nsIFrame* Get();
Packit f0b94e
Packit f0b94e
 private:
Packit f0b94e
  // The frame that this property is attached to, may be null
Packit f0b94e
  nsIFrame* mFrame;
Packit f0b94e
  // When a presshell is torn down, we don't delete the properties for
Packit f0b94e
  // each frame until after the frames are destroyed. So here we remember
Packit f0b94e
  // the presshell for the frames we care about and, before we use the frame,
Packit f0b94e
  // we test the presshell to see if it's destroying itself. If it is,
Packit f0b94e
  // then the frame pointer is not valid and we know the frame has gone away.
Packit f0b94e
  // mFramePresShell may be null, but when mFrame is non-null, mFramePresShell
Packit f0b94e
  // is guaranteed to be non-null, too.
Packit f0b94e
  nsIPresShell* mFramePresShell;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
class nsSVGRenderingObserverProperty : public nsSVGIDRenderingObserver {
Packit f0b94e
 public:
Packit f0b94e
  NS_DECL_ISUPPORTS
Packit f0b94e
Packit f0b94e
  nsSVGRenderingObserverProperty(nsIURI* aURI, nsIFrame* aFrame,
Packit f0b94e
                                 bool aReferenceImage)
Packit f0b94e
      : nsSVGIDRenderingObserver(aURI, aFrame->GetContent(), aReferenceImage),
Packit f0b94e
        mFrameReference(aFrame) {}
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  virtual ~nsSVGRenderingObserverProperty() {}
Packit f0b94e
Packit f0b94e
  virtual void OnRenderingChange() override;
Packit f0b94e
Packit f0b94e
  nsSVGFrameReferenceFromProperty mFrameReference;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
/**
Packit f0b94e
 * In a filter chain, there can be multiple SVG reference filters.
Packit f0b94e
 * e.g. filter: url(#svg-filter-1) blur(10px) url(#svg-filter-2);
Packit f0b94e
 *
Packit f0b94e
 * This class keeps track of one SVG reference filter in a filter chain.
Packit f0b94e
 * e.g. url(#svg-filter-1)
Packit f0b94e
 *
Packit f0b94e
 * It fires invalidations when the SVG filter element's id changes or when
Packit f0b94e
 * the SVG filter element's content changes.
Packit f0b94e
 *
Packit f0b94e
 * The nsSVGFilterChainObserver class manages a list of nsSVGFilterReferences.
Packit f0b94e
 */
Packit f0b94e
class nsSVGFilterReference final : public nsSVGIDRenderingObserver,
Packit f0b94e
                                   public nsISVGFilterReference {
Packit f0b94e
 public:
Packit f0b94e
  nsSVGFilterReference(nsIURI* aURI, nsIContent* aObservingContent,
Packit f0b94e
                       nsSVGFilterChainObserver* aFilterChainObserver)
Packit f0b94e
      : nsSVGIDRenderingObserver(aURI, aObservingContent, false),
Packit f0b94e
        mFilterChainObserver(aFilterChainObserver) {}
Packit f0b94e
Packit f0b94e
  bool ReferencesValidResource() { return GetFilterFrame(); }
Packit f0b94e
Packit f0b94e
  void DetachFromChainObserver() { mFilterChainObserver = nullptr; }
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * @return the filter frame, or null if there is no filter frame
Packit f0b94e
   */
Packit f0b94e
  nsSVGFilterFrame* GetFilterFrame();
Packit f0b94e
Packit f0b94e
  // nsISupports
Packit f0b94e
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
Packit f0b94e
  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsSVGFilterReference,
Packit f0b94e
                                           nsSVGIDRenderingObserver)
Packit f0b94e
Packit f0b94e
  // nsISVGFilterReference
Packit f0b94e
  virtual void Invalidate() override { OnRenderingChange(); };
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  virtual ~nsSVGFilterReference() {}
Packit f0b94e
Packit f0b94e
  // nsSVGIDRenderingObserver
Packit f0b94e
  virtual void OnRenderingChange() override;
Packit f0b94e
Packit f0b94e
 private:
Packit f0b94e
  nsSVGFilterChainObserver* mFilterChainObserver;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
/**
Packit f0b94e
 * This class manages a list of nsSVGFilterReferences, which represent SVG
Packit f0b94e
 * reference filters in a filter chain.
Packit f0b94e
 * e.g. filter: url(#svg-filter-1) blur(10px) url(#svg-filter-2);
Packit f0b94e
 *
Packit f0b94e
 * In the above example, the nsSVGFilterChainObserver will manage two
Packit f0b94e
 * nsSVGFilterReferences, one for each SVG reference filter. CSS filters like
Packit f0b94e
 * "blur(10px)" don't reference filter elements, so they don't need an
Packit f0b94e
 * nsSVGFilterReference. The style system invalidates changes to CSS filters.
Packit f0b94e
 */
Packit f0b94e
class nsSVGFilterChainObserver : public nsISupports {
Packit f0b94e
 public:
Packit f0b94e
  nsSVGFilterChainObserver(const nsTArray<nsStyleFilter>& aFilters,
Packit f0b94e
                           nsIContent* aFilteredElement,
Packit f0b94e
                           nsIFrame* aFiltedFrame = nullptr);
Packit f0b94e
Packit f0b94e
  bool ReferencesValidResources();
Packit f0b94e
  bool IsInObserverLists() const;
Packit f0b94e
  void Invalidate() { OnRenderingChange(); }
Packit f0b94e
Packit f0b94e
  // nsISupports
Packit f0b94e
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
Packit f0b94e
  NS_DECL_CYCLE_COLLECTION_CLASS(nsSVGFilterChainObserver)
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  virtual ~nsSVGFilterChainObserver();
Packit f0b94e
Packit f0b94e
  virtual void OnRenderingChange() = 0;
Packit f0b94e
Packit f0b94e
 private:
Packit f0b94e
  void DetachReferences() {
Packit f0b94e
    for (uint32_t i = 0; i < mReferences.Length(); i++) {
Packit f0b94e
      mReferences[i]->DetachFromChainObserver();
Packit f0b94e
    }
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  nsTArray<RefPtr<nsSVGFilterReference>> mReferences;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
class nsSVGFilterProperty : public nsSVGFilterChainObserver {
Packit f0b94e
 public:
Packit f0b94e
  nsSVGFilterProperty(const nsTArray<nsStyleFilter>& aFilters,
Packit f0b94e
                      nsIFrame* aFilteredFrame)
Packit f0b94e
      : nsSVGFilterChainObserver(aFilters, aFilteredFrame->GetContent(),
Packit f0b94e
                                 aFilteredFrame),
Packit f0b94e
        mFrameReference(aFilteredFrame) {}
Packit f0b94e
Packit f0b94e
  void DetachFromFrame() { mFrameReference.Detach(); }
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  virtual void OnRenderingChange() override;
Packit f0b94e
Packit f0b94e
  nsSVGFrameReferenceFromProperty mFrameReference;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
class nsSVGMarkerProperty final : public nsSVGRenderingObserverProperty {
Packit f0b94e
 public:
Packit f0b94e
  nsSVGMarkerProperty(nsIURI* aURI, nsIFrame* aFrame, bool aReferenceImage)
Packit f0b94e
      : nsSVGRenderingObserverProperty(aURI, aFrame, aReferenceImage) {}
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  virtual void OnRenderingChange() override;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
class nsSVGTextPathProperty final : public nsSVGRenderingObserverProperty {
Packit f0b94e
 public:
Packit f0b94e
  nsSVGTextPathProperty(nsIURI* aURI, nsIFrame* aFrame, bool aReferenceImage)
Packit f0b94e
      : nsSVGRenderingObserverProperty(aURI, aFrame, aReferenceImage),
Packit f0b94e
        mValid(true) {}
Packit f0b94e
Packit f0b94e
  virtual bool ObservesReflow() override { return false; }
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  virtual void OnRenderingChange() override;
Packit f0b94e
Packit f0b94e
 private:
Packit f0b94e
  /**
Packit f0b94e
   * Returns true if the target of the textPath is the frame of a 'path'
Packit f0b94e
   * element.
Packit f0b94e
   */
Packit f0b94e
  bool TargetIsValid();
Packit f0b94e
Packit f0b94e
  bool mValid;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
class nsSVGPaintingProperty final : public nsSVGRenderingObserverProperty {
Packit f0b94e
 public:
Packit f0b94e
  nsSVGPaintingProperty(nsIURI* aURI, nsIFrame* aFrame, bool aReferenceImage)
Packit f0b94e
      : nsSVGRenderingObserverProperty(aURI, aFrame, aReferenceImage) {}
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  virtual void OnRenderingChange() override;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
class nsSVGMaskProperty final : public nsISupports {
Packit f0b94e
 public:
Packit f0b94e
  explicit nsSVGMaskProperty(nsIFrame* aFrame);
Packit f0b94e
Packit f0b94e
  // nsISupports
Packit f0b94e
  NS_DECL_ISUPPORTS
Packit f0b94e
Packit f0b94e
  const nsTArray<RefPtr<nsSVGPaintingProperty>>& GetProps() const {
Packit f0b94e
    return mProperties;
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  void ResolveImage(uint32_t aIndex);
Packit f0b94e
Packit f0b94e
 private:
Packit f0b94e
  virtual ~nsSVGMaskProperty() {}
Packit f0b94e
  nsTArray<RefPtr<nsSVGPaintingProperty>> mProperties;
Packit f0b94e
  nsIFrame* mFrame;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
/**
Packit f0b94e
 * A manager for one-shot nsSVGRenderingObserver tracking.
Packit f0b94e
 * nsSVGRenderingObservers can be added or removed. They are not strongly
Packit f0b94e
 * referenced so an observer must be removed before it dies.
Packit f0b94e
 * When InvalidateAll is called, all outstanding references get
Packit f0b94e
 * OnNonDOMMutationRenderingChange()
Packit f0b94e
 * called on them and the list is cleared. The intent is that
Packit f0b94e
 * the observer will force repainting of whatever part of the document
Packit f0b94e
 * is needed, and then at paint time the observer will do a clean lookup
Packit f0b94e
 * of the referenced element and [re-]add itself to the element's observer list.
Packit f0b94e
 *
Packit f0b94e
 * InvalidateAll must be called before this object is destroyed, i.e.
Packit f0b94e
 * before the referenced frame is destroyed. This should normally happen
Packit f0b94e
 * via nsSVGContainerFrame::RemoveFrame, since only frames in the frame
Packit f0b94e
 * tree should be referenced.
Packit f0b94e
 */
Packit f0b94e
class nsSVGRenderingObserverList {
Packit f0b94e
 public:
Packit f0b94e
  nsSVGRenderingObserverList() : mObservers(4) {
Packit f0b94e
    MOZ_COUNT_CTOR(nsSVGRenderingObserverList);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  ~nsSVGRenderingObserverList() {
Packit f0b94e
    InvalidateAll();
Packit f0b94e
    MOZ_COUNT_DTOR(nsSVGRenderingObserverList);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  void Add(nsSVGRenderingObserver* aObserver) {
Packit f0b94e
    mObservers.PutEntry(aObserver);
Packit f0b94e
  }
Packit f0b94e
  void Remove(nsSVGRenderingObserver* aObserver) {
Packit f0b94e
    mObservers.RemoveEntry(aObserver);
Packit f0b94e
  }
Packit f0b94e
#ifdef DEBUG
Packit f0b94e
  bool Contains(nsSVGRenderingObserver* aObserver) {
Packit f0b94e
    return (mObservers.GetEntry(aObserver) != nullptr);
Packit f0b94e
  }
Packit f0b94e
#endif
Packit f0b94e
  bool IsEmpty() { return mObservers.Count() == 0; }
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Drop all our observers, and notify them that we have changed and dropped
Packit f0b94e
   * our reference to them.
Packit f0b94e
   */
Packit f0b94e
  void InvalidateAll();
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Drop all observers that observe reflow, and notify them that we have
Packit f0b94e
   * changed and dropped our reference to them.
Packit f0b94e
   */
Packit f0b94e
  void InvalidateAllForReflow();
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Drop all our observers, and notify them that we have dropped our reference
Packit f0b94e
   * to them.
Packit f0b94e
   */
Packit f0b94e
  void RemoveAll();
Packit f0b94e
Packit f0b94e
 private:
Packit f0b94e
  nsTHashtable<nsPtrHashKey<nsSVGRenderingObserver>> mObservers;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
class SVGObserverUtils {
Packit f0b94e
 public:
Packit f0b94e
  typedef mozilla::dom::Element Element;
Packit f0b94e
  typedef nsInterfaceHashtable<nsURIHashKey, nsIMutationObserver>
Packit f0b94e
      URIObserverHashtable;
Packit f0b94e
Packit f0b94e
  using PaintingPropertyDescriptor =
Packit f0b94e
      const mozilla::FramePropertyDescriptor<nsSVGPaintingProperty>*;
Packit f0b94e
  using URIObserverHashtablePropertyDescriptor =
Packit f0b94e
      const mozilla::FramePropertyDescriptor<URIObserverHashtable>*;
Packit f0b94e
Packit f0b94e
  static void DestroyFilterProperty(nsSVGFilterProperty* aProp) {
Packit f0b94e
    // nsSVGFilterProperty is cycle-collected, so dropping the last reference
Packit f0b94e
    // doesn't necessarily destroy it. We need to tell it that the frame
Packit f0b94e
    // has now become invalid.
Packit f0b94e
    aProp->DetachFromFrame();
Packit f0b94e
Packit f0b94e
    aProp->Release();
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(FilterProperty, nsSVGFilterProperty,
Packit f0b94e
                                      DestroyFilterProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(MaskProperty, nsSVGMaskProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(ClipPathProperty, nsSVGPaintingProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(MarkerBeginProperty, nsSVGMarkerProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(MarkerMiddleProperty,
Packit f0b94e
                                       nsSVGMarkerProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(MarkerEndProperty, nsSVGMarkerProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(FillProperty, nsSVGPaintingProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(StrokeProperty, nsSVGPaintingProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(HrefAsTextPathProperty,
Packit f0b94e
                                       nsSVGTextPathProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_RELEASABLE(HrefAsPaintingProperty,
Packit f0b94e
                                       nsSVGPaintingProperty)
Packit f0b94e
  NS_DECLARE_FRAME_PROPERTY_DELETABLE(BackgroundImageProperty,
Packit f0b94e
                                      URIObserverHashtable)
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Get the paint server for a aTargetFrame.
Packit f0b94e
   */
Packit f0b94e
  static nsSVGPaintServerFrame* GetPaintServer(
Packit f0b94e
      nsIFrame* aTargetFrame, nsStyleSVGPaint nsStyleSVG::*aPaint,
Packit f0b94e
      PaintingPropertyDescriptor aProperty);
Packit f0b94e
Packit f0b94e
  struct EffectProperties {
Packit f0b94e
    nsSVGFilterProperty* mFilter;
Packit f0b94e
    nsSVGMaskProperty* mMask;
Packit f0b94e
    nsSVGPaintingProperty* mClipPath;
Packit f0b94e
Packit f0b94e
    /**
Packit f0b94e
     * @return the clip-path frame, or null if there is no clip-path frame
Packit f0b94e
     */
Packit f0b94e
    nsSVGClipPathFrame* GetClipPathFrame();
Packit f0b94e
Packit f0b94e
    /**
Packit f0b94e
     * @return an array which contains all SVG mask frames.
Packit f0b94e
     */
Packit f0b94e
    nsTArray<nsSVGMaskFrame*> GetMaskFrames();
Packit f0b94e
Packit f0b94e
    /*
Packit f0b94e
     * @return true if all effects we have are valid or we have no effect
Packit f0b94e
     * at all.
Packit f0b94e
     */
Packit f0b94e
    bool HasNoOrValidEffects();
Packit f0b94e
Packit f0b94e
    /*
Packit f0b94e
     * @return true if we have any invalid effect.
Packit f0b94e
     */
Packit f0b94e
    bool HasInvalidEffects() { return !HasNoOrValidEffects(); }
Packit f0b94e
Packit f0b94e
    /*
Packit f0b94e
     * @return true if we either do not have clip-path or have a valid
Packit f0b94e
     * clip-path.
Packit f0b94e
     */
Packit f0b94e
    bool HasNoOrValidClipPath();
Packit f0b94e
Packit f0b94e
    /*
Packit f0b94e
     * @return true if we have an invalid clip-path.
Packit f0b94e
     */
Packit f0b94e
    bool HasInvalidClipPath() { return !HasNoOrValidClipPath(); }
Packit f0b94e
Packit f0b94e
    /*
Packit f0b94e
     * @return true if we either do not have mask or all masks we have
Packit f0b94e
     * are valid.
Packit f0b94e
     */
Packit f0b94e
    bool HasNoOrValidMask();
Packit f0b94e
Packit f0b94e
    /*
Packit f0b94e
     * @return true if we have an invalid mask.
Packit f0b94e
     */
Packit f0b94e
    bool HasInvalidMask() { return !HasNoOrValidMask(); }
Packit f0b94e
Packit f0b94e
    bool HasValidFilter() {
Packit f0b94e
      return mFilter && mFilter->ReferencesValidResources();
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    /*
Packit f0b94e
     * @return true if we either do not have filter or all filters we have
Packit f0b94e
     * are valid.
Packit f0b94e
     */
Packit f0b94e
    bool HasNoOrValidFilter() {
Packit f0b94e
      return !mFilter || mFilter->ReferencesValidResources();
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    /*
Packit f0b94e
     * @return true if we have an invalid filter.
Packit f0b94e
     */
Packit f0b94e
    bool HasInvalidFilter() { return !HasNoOrValidFilter(); }
Packit f0b94e
  };
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * @param aFrame should be the first continuation
Packit f0b94e
   */
Packit f0b94e
  static EffectProperties GetEffectProperties(nsIFrame* aFrame);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Called when changes to an element (e.g. CSS property changes) cause its
Packit f0b94e
   * frame to start/stop referencing (or reference different) SVG resource
Packit f0b94e
   * elements. (_Not_ called for changes to referenced resource elements.)
Packit f0b94e
   *
Packit f0b94e
   * This function handles such changes by discarding _all_ the frame's SVG
Packit f0b94e
   * effects frame properties (causing those properties to stop watching their
Packit f0b94e
   * target element). It also synchronously (re)creates the filter and marker
Packit f0b94e
   * frame properties (XXX why not the other properties?), which makes it
Packit f0b94e
   * useful for initializing those properties during first reflow.
Packit f0b94e
   *
Packit f0b94e
   * XXX rename to something more meaningful like RefreshResourceReferences?
Packit f0b94e
   */
Packit f0b94e
  static void UpdateEffects(nsIFrame* aFrame);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * @param aFrame should be the first continuation
Packit f0b94e
   */
Packit f0b94e
  static nsSVGFilterProperty* GetFilterProperty(nsIFrame* aFrame);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * @param aFrame must be a first-continuation.
Packit f0b94e
   */
Packit f0b94e
  static void AddRenderingObserver(Element* aElement,
Packit f0b94e
                                   nsSVGRenderingObserver* aObserver);
Packit f0b94e
  /**
Packit f0b94e
   * @param aFrame must be a first-continuation.
Packit f0b94e
   */
Packit f0b94e
  static void RemoveRenderingObserver(Element* aElement,
Packit f0b94e
                                      nsSVGRenderingObserver* aObserver);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Removes all rendering observers from aElement.
Packit f0b94e
   */
Packit f0b94e
  static void RemoveAllRenderingObservers(Element* aElement);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * This can be called on any frame. We invalidate the observers of aFrame's
Packit f0b94e
   * element, if any, or else walk up to the nearest observable SVG parent
Packit f0b94e
   * frame with observers and invalidate them instead.
Packit f0b94e
   *
Packit f0b94e
   * Note that this method is very different to e.g.
Packit f0b94e
   * nsNodeUtils::AttributeChanged which walks up the content node tree all the
Packit f0b94e
   * way to the root node (not stopping if it encounters a non-container SVG
Packit f0b94e
   * node) invalidating all mutation observers (not just
Packit f0b94e
   * nsSVGRenderingObservers) on all nodes along the way (not just the first
Packit f0b94e
   * node it finds with observers). In other words, by doing all the
Packit f0b94e
   * things in parentheses in the preceding sentence, this method uses
Packit f0b94e
   * knowledge about our implementation and what can be affected by SVG effects
Packit f0b94e
   * to make invalidation relatively lightweight when an SVG effect changes.
Packit f0b94e
   */
Packit f0b94e
  static void InvalidateRenderingObservers(nsIFrame* aFrame);
Packit f0b94e
Packit f0b94e
  enum { INVALIDATE_REFLOW = 1 };
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * This can be called on any element or frame. Only direct observers of this
Packit f0b94e
   * (frame's) element, if any, are invalidated.
Packit f0b94e
   */
Packit f0b94e
  static void InvalidateDirectRenderingObservers(Element* aElement,
Packit f0b94e
                                                 uint32_t aFlags = 0);
Packit f0b94e
  static void InvalidateDirectRenderingObservers(nsIFrame* aFrame,
Packit f0b94e
                                                 uint32_t aFlags = 0);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Get an nsSVGMarkerProperty for the frame, creating a fresh one if necessary
Packit f0b94e
   */
Packit f0b94e
  static nsSVGMarkerProperty* GetMarkerProperty(
Packit f0b94e
      nsIURI* aURI, nsIFrame* aFrame,
Packit f0b94e
      const mozilla::FramePropertyDescriptor<nsSVGMarkerProperty>* aProperty);
Packit f0b94e
  /**
Packit f0b94e
   * Get an nsSVGTextPathProperty for the frame, creating a fresh one if
Packit f0b94e
   * necessary
Packit f0b94e
   */
Packit f0b94e
  static nsSVGTextPathProperty* GetTextPathProperty(
Packit f0b94e
      nsIURI* aURI, nsIFrame* aFrame,
Packit f0b94e
      const mozilla::FramePropertyDescriptor<nsSVGTextPathProperty>* aProperty);
Packit f0b94e
  /**
Packit f0b94e
   * Get an nsSVGPaintingProperty for the frame, creating a fresh one if
Packit f0b94e
   * necessary
Packit f0b94e
   */
Packit f0b94e
  static nsSVGPaintingProperty* GetPaintingProperty(
Packit f0b94e
      nsIURI* aURI, nsIFrame* aFrame,
Packit f0b94e
      const mozilla::FramePropertyDescriptor<nsSVGPaintingProperty>* aProperty);
Packit f0b94e
  /**
Packit f0b94e
   * Get an nsSVGPaintingProperty for the frame for that URI, creating a fresh
Packit f0b94e
   * one if necessary
Packit f0b94e
   */
Packit f0b94e
  static nsSVGPaintingProperty* GetPaintingPropertyForURI(
Packit f0b94e
      nsIURI* aURI, nsIFrame* aFrame,
Packit f0b94e
      URIObserverHashtablePropertyDescriptor aProp);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * A helper function to resolve marker's URL.
Packit f0b94e
   */
Packit f0b94e
  static already_AddRefed<nsIURI> GetMarkerURI(
Packit f0b94e
      nsIFrame* aFrame, RefPtr<mozilla::css::URLValue> nsStyleSVG::*aMarker);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * A helper function to resolve clip-path URL.
Packit f0b94e
   */
Packit f0b94e
  static already_AddRefed<nsIURI> GetClipPathURI(nsIFrame* aFrame);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * A helper function to resolve filter URL.
Packit f0b94e
   */
Packit f0b94e
  static already_AddRefed<nsIURI> GetFilterURI(nsIFrame* aFrame,
Packit f0b94e
                                               uint32_t aIndex);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * A helper function to resolve filter URL.
Packit f0b94e
   */
Packit f0b94e
  static already_AddRefed<nsIURI> GetFilterURI(nsIFrame* aFrame,
Packit f0b94e
                                               const nsStyleFilter& aFilter);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * A helper function to resolve paint-server URL.
Packit f0b94e
   */
Packit f0b94e
  static already_AddRefed<nsIURI> GetPaintURI(
Packit f0b94e
      nsIFrame* aFrame, nsStyleSVGPaint nsStyleSVG::*aPaint);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * A helper function to resolve SVG mask URL.
Packit f0b94e
   */
Packit f0b94e
  static already_AddRefed<nsIURI> GetMaskURI(nsIFrame* aFrame, uint32_t aIndex);
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * Return a baseURL for resolving a local-ref URL.
Packit f0b94e
   *
Packit f0b94e
   * @param aContent an element which uses a local-ref property. Here are some
Packit f0b94e
   *                 examples:
Packit f0b94e
   *                   <rect fill=url(#foo)>
Packit f0b94e
   *                   <circle clip-path=url(#foo)>
Packit f0b94e
   *                   <use xlink:href="#foo">
Packit f0b94e
   */
Packit f0b94e
  static already_AddRefed<nsIURI> GetBaseURLForLocalRef(nsIContent* aContent,
Packit f0b94e
                                                        nsIURI* aDocURI);
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
#endif /*NSSVGEFFECTS_H_*/