Bug 745066 - Add comments documenting the declaration of nsSVGFilterInstance, its methods and its members. r=longsonr.
authorJonathan Watt <jwatt@jwatt.org>
Fri, 13 Apr 2012 14:22:06 +0100
changeset 91595 dc0b57deb507d4685fe1fb8656c1f7d5ea5551fd
parent 91594 c44c5a7141e3ccbbb03d314e1ac59255ec9176d8
child 91596 c0975fb1e62dc57e436f2f6aa3781433feeabe52
push id8288
push userjwatt@jwatt.org
push dateFri, 13 Apr 2012 13:24:39 +0000
treeherdermozilla-inbound@dc0b57deb507 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslongsonr
bugs745066
milestone14.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
Bug 745066 - Add comments documenting the declaration of nsSVGFilterInstance, its methods and its members. r=longsonr.
layout/svg/base/src/nsSVGFilterFrame.cpp
layout/svg/base/src/nsSVGFilterInstance.h
layout/svg/base/src/nsSVGUtils.h
--- a/layout/svg/base/src/nsSVGFilterFrame.cpp
+++ b/layout/svg/base/src/nsSVGFilterFrame.cpp
@@ -95,38 +95,33 @@ private:
 class NS_STACK_CLASS nsAutoFilterInstance {
 public:
   nsAutoFilterInstance(nsIFrame *aTarget,
                        nsSVGFilterFrame *aFilterFrame,
                        nsSVGFilterPaintCallback *aPaint,
                        const nsIntRect *aDirtyOutputRect,
                        const nsIntRect *aDirtyInputRect,
                        const nsIntRect *aOverrideSourceBBox);
-  ~nsAutoFilterInstance();
+  ~nsAutoFilterInstance() {}
 
   // If this returns null, then draw nothing. Either the filter draws
   // nothing or it is "in error".
   nsSVGFilterInstance* get() { return mInstance; }
 
 private:
   nsAutoPtr<nsSVGFilterInstance> mInstance;
-  // Store mTarget separately even though mInstance has it, because if
-  // mInstance creation fails we still need to be able to clean up
-  nsISVGChildFrame*              mTarget;
 };
 
 nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
                                            nsSVGFilterFrame *aFilterFrame,
                                            nsSVGFilterPaintCallback *aPaint,
                                            const nsIntRect *aDirtyOutputRect,
                                            const nsIntRect *aDirtyInputRect,
                                            const nsIntRect *aOverrideSourceBBox)
 {
-  mTarget = do_QueryFrame(aTarget);
-
   const nsSVGFilterElement *filter = aFilterFrame->GetFilterContent();
 
   PRUint16 filterUnits =
     aFilterFrame->GetEnumValue(nsSVGFilterElement::FILTERUNITS);
   PRUint16 primitiveUnits =
     aFilterFrame->GetEnumValue(nsSVGFilterElement::PRIMITIVEUNITS);
 
   gfxRect bbox;
@@ -242,20 +237,16 @@ nsAutoFilterInstance::nsAutoFilterInstan
   // Setup instance data
   mInstance = new nsSVGFilterInstance(aTarget, aPaint, filter, bbox, filterRegion,
                                       nsIntSize(filterRes.width, filterRes.height),
                                       filterToDeviceSpace, targetBoundsFilterSpace,
                                       dirtyOutputRect, dirtyInputRect,
                                       primitiveUnits);
 }
 
-nsAutoFilterInstance::~nsAutoFilterInstance()
-{
-}
-
 PRUint16
 nsSVGFilterFrame::GetEnumValue(PRUint32 aIndex, nsIContent *aDefault)
 {
   nsSVGEnum& thisEnum =
     static_cast<nsSVGFilterElement *>(mContent)->mEnumAttributes[aIndex];
 
   if (thisEnum.IsExplicitlySet())
     return thisEnum.GetAnimValue();
--- a/layout/svg/base/src/nsSVGFilterInstance.h
+++ b/layout/svg/base/src/nsSVGFilterInstance.h
@@ -57,20 +57,52 @@ class nsSVGFilterElement;
 class nsSVGFilterPaintCallback;
 
 /**
  * This class performs all filter processing.
  * 
  * We build a graph of the filter image data flow, essentially
  * converting the filter graph to SSA. This lets us easily propagate
  * analysis data (such as bounding-boxes) over the filter primitive graph.
+ *
+ * Definition of "filter space": filter space is a coordinate system that is
+ * aligned with the user space of the filtered element, with its origin located
+ * at the top left of the filter region (as returned by GetFilterRect,
+ * specifically), and with one unit equal in size to one pixel of the offscreen
+ * surface into which the filter output would/will be painted.
  */
 class NS_STACK_CLASS nsSVGFilterInstance
 {
 public:
+  /**
+   * @param aTargetFrame The frame of the filtered element under consideration.
+   * @param aPaintCallback [optional] The callback that Render() should use to
+   *   paint. Only required if you will call Render().
+   * @param aFilterElement The filter element referenced by aTargetFrame's
+   *   element.
+   * @param aTargetBBox The filtered element's bbox, in the filtered element's
+   *   user space.
+   * @param aFilterRect The "filter region", in the filtered element's user
+   *   space. The caller must have already expanded the region out so that its
+   *   edges coincide with pixel boundaries in the offscreen surface that
+   *   would/will be created to paint the filter output.
+   * @param aFilterSpaceSize The size of the user specified "filter region",
+   *   in filter space units.
+   * @param aFilterSpaceToDeviceSpaceTransform The transform from filter
+   *   space to outer-<svg> device space.
+   * @param aTargetBounds The pre-filter paint bounds of the filtered element,
+   *   in filter space.
+   * @param aDirtyOutputRect [optional] The bounds of the post-filter area that
+   *   has to be repainted, in filter space. Only required if you will call
+   *   ComputeSourceNeededRect() or Render().
+   * @param aDirtyInputRect [optional] The bounds of the pre-filter area of the
+   *   filtered element that changed, in filter space. Only required if you
+   *   will call ComputeOutputDirtyRect().
+   * @param aPrimitiveUnits The value from the 'primitiveUnits' attribute.
+   */
   nsSVGFilterInstance(nsIFrame *aTargetFrame,
                       nsSVGFilterPaintCallback *aPaintCallback,
                       const nsSVGFilterElement *aFilterElement,
                       const gfxRect &aTargetBBox,
                       const gfxRect& aFilterRect,
                       const nsIntSize& aFilterSpaceSize,
                       const gfxMatrix &aFilterSpaceToDeviceSpaceTransform,
                       const nsIntRect& aTargetBounds,
@@ -79,81 +111,168 @@ public:
                       PRUint16 aPrimitiveUnits) :
     mTargetFrame(aTargetFrame),
     mPaintCallback(aPaintCallback),
     mFilterElement(aFilterElement),
     mTargetBBox(aTargetBBox),
     mFilterSpaceToDeviceSpaceTransform(aFilterSpaceToDeviceSpaceTransform),
     mFilterRect(aFilterRect),
     mFilterSpaceSize(aFilterSpaceSize),
+    mSurfaceRect(nsIntPoint(0, 0), aFilterSpaceSize),
     mTargetBounds(aTargetBounds),
     mDirtyOutputRect(aDirtyOutputRect),
     mDirtyInputRect(aDirtyInputRect),
-    mSurfaceRect(nsIntPoint(0, 0), aFilterSpaceSize),
     mPrimitiveUnits(aPrimitiveUnits) {
   }
-  
-  // The area covered by temporary images, in filter space
-  void SetSurfaceRect(const nsIntRect& aRect) { mSurfaceRect = aRect; }
 
+  /**
+   * Returns the user specified "filter region", in the filtered element's user
+   * space, after it has been adjusted out (if necessary) so that its edges
+   * coincide with pixel boundaries of the offscreen surface into which the
+   * filtered output would/will be painted.
+   */
   gfxRect GetFilterRect() const { return mFilterRect; }
 
+  /**
+   * Returns the size of the user specified "filter region", in filter space.
+   * The size will be {filterRes.x by filterRes.y}, whether the user specified
+   * the filter's filterRes attribute explicitly, or the implementation chose
+   * the filterRes values. (The top-left of the filter region is the origin of
+   * filter space, which is why this method returns an nsIntSize and not an
+   * nsIntRect.)
+   */
   const nsIntSize& GetFilterSpaceSize() { return mFilterSpaceSize; }
   PRUint32 GetFilterResX() const { return mFilterSpaceSize.width; }
   PRUint32 GetFilterResY() const { return mFilterSpaceSize.height; }
-  
+
+  /**
+   * Returns the dimensions of the offscreen surface that is required for the
+   * output from the current filter operation, in filter space. This rect is
+   * clipped to, and therefore guaranteed to be fully contained by, the filter
+   * region.
+   */
   const nsIntRect& GetSurfaceRect() const { return mSurfaceRect; }
   PRInt32 GetSurfaceWidth() const { return mSurfaceRect.width; }
   PRInt32 GetSurfaceHeight() const { return mSurfaceRect.height; }
-  
+
+  /**
+   * Allocates a gfxASurface, renders the filtered element into the surface,
+   * and then returns the surface via the aOutput outparam. The area that
+   * needs to be painted must have been specified before calling this method
+   * by passing it as the aDirtyOutputRect argument to the
+   * nsSVGFilterInstance constructor.
+   */
   nsresult Render(gfxASurface** aOutput);
+
+  /**
+   * Sets the aDirty outparam to the post-filter bounds in filter space of the
+   * area that would be dirtied by mTargetFrame when a given pre-filter area of
+   * mTargetFrame is dirtied. The pre-filter area must have been specified
+   * before calling this method by passing it as the aDirtyInputRect argument
+   * to the nsSVGFilterInstance constructor.
+   */
   nsresult ComputeOutputDirtyRect(nsIntRect* aDirty);
+
+  /**
+   * Sets the aDirty outparam to the pre-filter bounds in filter space of the
+   * area of mTargetFrame that is needed in order to paint the filtered output
+   * for a given post-filter dirtied area. The post-filter area must have been
+   * specified before calling this method by passing it as the aDirtyOutputRect
+   * argument to the nsSVGFilterInstance constructor.
+   */
   nsresult ComputeSourceNeededRect(nsIntRect* aDirty);
+
+  /**
+   * Sets the aDirty outparam to the post-filter bounds in filter space of the
+   * area that would be dirtied by mTargetFrame if its entire pre-filter area
+   * is dirtied.
+   */
   nsresult ComputeOutputBBox(nsIntRect* aBBox);
 
   float GetPrimitiveNumber(PRUint8 aCtxType, const nsSVGNumber2 *aNumber) const
   {
     return GetPrimitiveNumber(aCtxType, aNumber->GetAnimValue());
   }
   float GetPrimitiveNumber(PRUint8 aCtxType, const nsSVGNumberPair *aNumberPair,
                            nsSVGNumberPair::PairIndex aIndex) const
   {
     return GetPrimitiveNumber(aCtxType, aNumberPair->GetAnimValue(aIndex));
   }
+
   /**
-   * Converts a point and a length in filter primitive units into filter space.
-   * For object-bounding-box units, the object bounding box offset is applied
-   * to the point.
+   * Converts a userSpaceOnUse/objectBoundingBoxUnits unitless point and length
+   * into filter space, depending on the value of mPrimitiveUnits. (For
+   * objectBoundingBoxUnits, the bounding box offset is applied to the point.)
    */
   void ConvertLocation(float aValues[3]) const;
 
+  /**
+   * Returns the transform from the filtered element's user space to filter
+   * space. This will be a simple translation and/or scale.
+   */
   gfxMatrix GetUserSpaceToFilterSpaceTransform() const;
+
+  /**
+   * Returns the transform from filter space to outer-<svg> device space.
+   */
   gfxMatrix GetFilterSpaceToDeviceSpaceTransform() const {
     return mFilterSpaceToDeviceSpaceTransform;
   }
+
   gfxPoint FilterSpaceToUserSpace(const gfxPoint& aPt) const;
 
 private:
   typedef nsSVGFE::Image Image;
   typedef nsSVGFE::ColorModel ColorModel;
 
   struct PrimitiveInfo {
+    /// Pointer to the filter primitive element.
     nsSVGFE*  mFE;
-    // the bounding box of the result image produced by this primitive, in
-    // filter space
+
+    /**
+     * The filter space bounds of this filter primitive's output, were a full
+     * repaint of mTargetFrame to occur. Note that a filter primitive's output
+     * (and hence this rect) is always clipped to both the filter region and
+     * to the filter primitive subregion.
+     * XXX maybe rename this to mMaxBounds?
+     */
     nsIntRect mResultBoundingBox;
-    // the bounding box of the part of the result image that is actually
-    // needed by other primitives or by the filter result, in filter space
-    // (used for Render only)
+
+    /**
+     * The filter space bounds of this filter primitive's output, were we to
+     * repaint a given post-filter dirty area, and were we to minimize
+     * repainting for that dirty area. In other words this is the part of the
+     * primitive's output that is needed by other primitives or the final
+     * filtered output in order to repaint that area. This rect is guaranteed
+     * to be contained within mResultBoundingBox and, if we're only painting
+     * part of the filtered output, may be smaller. This rect is used when
+     * calling Render() or ComputeSourceNeededRect().
+     * XXX maybe rename this to just mNeededBounds?
+     */
     nsIntRect mResultNeededBox;
-    // the bounding box of the part of the result image that could be
-    // changed by changes to mDirtyInputRect in the source image(s)
-    // (used for ComputeOutputDirtyRect only)
+
+    /**
+     * The filter space bounds of this filter primitive's output, were only
+     * part of mTargetFrame's pre-filter output to be dirtied, and were we to
+     * minimize repainting for that dirty area. This is used when calculating
+     * the area that needs to be invalidated when only part of a filtered
+     * element is dirtied. This rect is guaranteed to be contained within
+     * mResultBoundingBox.
+     */
     nsIntRect mResultChangeBox;
+
     Image     mImage;
+
+    /**
+     * The number of times that this filter primitive's output is used as an
+     * input by other filter primitives in the filter graph.
+     * XXX seems like we could better use this to avoid creating images for
+     * primitives that are not used, or whose ouput in not used during the
+     * current operation.
+     */
     PRInt32   mImageUsers;
   
     // Can't use nsAutoTArray here, because these Info objects
     // live in nsTArrays themselves and nsTArray moves the elements
     // around in memory, which breaks nsAutoTArray.
     nsTArray<PrimitiveInfo*> mInputs;
 
     PrimitiveInfo() : mFE(nsnull), mImageUsers(0) {}
@@ -163,67 +282,148 @@ private:
   public:
     ImageAnalysisEntry(KeyTypePointer aStr) : nsStringHashKey(aStr) { }
     ImageAnalysisEntry(const ImageAnalysisEntry& toCopy) : nsStringHashKey(toCopy),
       mInfo(toCopy.mInfo) { }
 
     PrimitiveInfo* mInfo;
   };
 
+  /**
+   * Initializes the SourceGraphic and SourceAlpha graph nodes (i.e. sets
+   * .mImage.mFilterPrimitiveSubregion and .mResultBoundingBox on
+   * mSourceColorAlpha and mSourceAlpha).
+   */
   nsresult BuildSources();
-  // Build graph of PrimitiveInfo nodes describing filter primitives
-  nsresult BuildPrimitives();
-  // Compute bounding boxes of the filter primitive outputs
-  void ComputeResultBoundingBoxes();
-  // Compute bounding boxes of what we actually *need* from the filter
-  // primitive outputs
-  void ComputeNeededBoxes();
-  // Compute bounding boxes of what could have changed given some changes
-  // to the source images.
-  void ComputeResultChangeBoxes();
-  nsIntRect ComputeUnionOfAllNeededBoxes();
+
+  /**
+   * Creates the gfxImageSurfaces for the SourceGraphic and SourceAlpha graph
+   * nodes, paints their contents, and assigns them to
+   * mSourceColorAlpha.mImage.mImage and mSourceAlpha.mImage.mImage
+   * respectively.
+   */
   nsresult BuildSourceImages();
 
-  // Allocates an image surface that covers mSurfaceRect (it uses
-  // device offsets so that its origin is positioned at mSurfaceRect.TopLeft()
-  // when using cairo to draw into the surface). The surface is cleared
-  // to transparent black.
+  /**
+   * Build the graph of PrimitiveInfo nodes that describes the filter's filter
+   * primitives and their connections. This populates mPrimitives, and sets
+   * each PrimitiveInfo's mFE, mInputs, mImageUsers, mFilterPrimitiveSubregion,
+   * etc.
+   */
+  nsresult BuildPrimitives();
+
+  /**
+   * Compute the filter space bounds of the output from each primitive, were we
+   * to do a full repaint of mTargetFrame. This sets mResultBoundingBox on the
+   * items in the filter graph, based on the mResultBoundingBox of each item's
+   * inputs, and clipped to the filter region and each primitive's filter
+   * primitive subregion.
+   */
+  void ComputeResultBoundingBoxes();
+
+  /**
+   * Computes the filter space bounds of the areas that we actually *need* from
+   * each filter primitive's output, based on the value of mDirtyOutputRect. 
+   * This sets mResultNeededBox on the items in the filter graph.
+   */
+   void ComputeNeededBoxes();
+
+  /**
+   * Computes the filter space bounds of the area of each filter primitive
+   * that will change, based on the value of mDirtyInputRect.
+   * This sets mResultChangeBox on the items in the filter graph.
+   */
+  void ComputeResultChangeBoxes();
+
+  /**
+   * Computes and returns the union of all mResultNeededBox rects in the filter
+   * graph. This is useful for deciding the size of the offscreen surface that
+   * needs to be created for the filter operation.
+   */
+  nsIntRect ComputeUnionOfAllNeededBoxes();
+
+  /**
+   * Allocates and returns a surface of mSurfaceRect.Size(), and with a device
+   * offset of -mSurfaceRect.TopLeft(). The surface is cleared to transparent
+   * black.
+   */
   already_AddRefed<gfxImageSurface> CreateImage();
 
+  /**
+   * Computes and sets mFilterPrimitiveSubregion for the given primitive.
+   */
   void ComputeFilterPrimitiveSubregion(PrimitiveInfo* aInfo);
+
+  /**
+   * If the color model of the pixel data in the aPrimitive's image isn't
+   * already aColorModel, then this method converts its pixel data to that
+   * color model.
+   */
   void EnsureColorModel(PrimitiveInfo* aPrimitive,
                         ColorModel aColorModel);
 
   /**
    * Scales a numeric filter primitive length in the X, Y or "XY" directions
    * into a length in filter space (no offset is applied).
    */
   float GetPrimitiveNumber(PRUint8 aCtxType, float aValue) const;
 
   gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpace) const;
+
+  /**
+   * Clip the filter space rect aRect to the filter region.
+   */
   void ClipToFilterSpace(nsIntRect* aRect) const
   {
     nsIntRect filterSpace(nsIntPoint(0, 0), mFilterSpaceSize);
     aRect->IntersectRect(*aRect, filterSpace);
   }
-  void ClipToGfxRect(nsIntRect* aRect, const gfxRect& aGfx) const;
 
+  /**
+   * The frame for the element that is currently being filtered.
+   */
   nsIFrame*               mTargetFrame;
+
   nsSVGFilterPaintCallback* mPaintCallback;
   const nsSVGFilterElement* mFilterElement;
-  // Bounding box of the target element, in user space
+
+  /**
+   * The SVG bbox of the element that is being filtered, in user space.
+   */
   gfxRect                 mTargetBBox;
+
   gfxMatrix               mFilterSpaceToDeviceSpaceTransform;
   gfxRect                 mFilterRect;
   nsIntSize               mFilterSpaceSize;
-  // Filter-space bounds of the target image (SourceAlpha/SourceGraphic)
+  nsIntRect               mSurfaceRect;
+
+  /**
+   * Pre-filter paint bounds of the element that is being filtered, in filter
+   * space.
+   */
   nsIntRect               mTargetBounds;
+
+  /**
+   * If set, this is the filter space bounds of the outer-<svg> device space
+   * bounds of the dirty area that needs to be repainted. (As bounds-of-bounds,
+   * this may be a fair bit bigger than we actually need, unfortunately.)
+   */
   nsIntRect               mDirtyOutputRect;
+
+  /**
+   * If set, this is the filter space bounds of the outer-<svg> device bounds
+   * of the pre-filter area of the filtered element that changed. (As
+   * bounds-of-bounds, this may be a fair bit bigger than we actually need,
+   * unfortunately.)
+   */
   nsIntRect               mDirtyInputRect;
-  nsIntRect               mSurfaceRect;
+
+  /**
+   * The 'primitiveUnits' attribute value (objectBoundingBox or userSpaceOnUse).
+   */
   PRUint16                mPrimitiveUnits;
 
   PrimitiveInfo           mSourceColorAlpha;
   PrimitiveInfo           mSourceAlpha;
   nsTArray<PrimitiveInfo> mPrimitives;
 };
 
 #endif
--- a/layout/svg/base/src/nsSVGUtils.h
+++ b/layout/svg/base/src/nsSVGUtils.h
@@ -537,17 +537,19 @@ public:
   };
   /**
    * Get the SVG bbox (the SVG spec's simplified idea of bounds) of aFrame in
    * aFrame's userspace.
    */
   static gfxRect GetBBox(nsIFrame *aFrame, PRUint32 aFlags = eBBoxIncludeFill);
 
   /**
-   * Compute a rectangle in userSpaceOnUse or objectBoundingBoxUnits.
+   * Convert a userSpaceOnUse/objectBoundingBoxUnits rectangle that's specified
+   * using four nsSVGLength2 values into a user unit rectangle in user space.
+   *
    * @param aXYWH pointer to 4 consecutive nsSVGLength2 objects containing
    * the x, y, width and height values in that order
    * @param aBBox the bounding box of the object the rect is relative to;
    * may be null if aUnits is not SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
    * @param aFrame the object in which to interpret user-space units;
    * may be null if aUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
    */
   static gfxRect