layout/svg/nsFilterInstance.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/svg/nsFilterInstance.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,322 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef __NS_FILTERINSTANCE_H__
    1.10 +#define __NS_FILTERINSTANCE_H__
    1.11 +
    1.12 +#include "gfxMatrix.h"
    1.13 +#include "gfxPoint.h"
    1.14 +#include "gfxRect.h"
    1.15 +#include "nsCOMPtr.h"
    1.16 +#include "nsHashKeys.h"
    1.17 +#include "nsPoint.h"
    1.18 +#include "nsRect.h"
    1.19 +#include "nsSize.h"
    1.20 +#include "nsSVGFilters.h"
    1.21 +#include "nsSVGNumber2.h"
    1.22 +#include "nsSVGNumberPair.h"
    1.23 +#include "nsTArray.h"
    1.24 +#include "nsIFrame.h"
    1.25 +#include "mozilla/gfx/2D.h"
    1.26 +
    1.27 +class gfxASurface;
    1.28 +class nsIFrame;
    1.29 +class nsSVGFilterPaintCallback;
    1.30 +
    1.31 +/**
    1.32 + * This class performs all filter processing.
    1.33 + * 
    1.34 + * We build a graph of the filter image data flow, essentially
    1.35 + * converting the filter graph to SSA. This lets us easily propagate
    1.36 + * analysis data (such as bounding-boxes) over the filter primitive graph.
    1.37 + *
    1.38 + * Definition of "filter space": filter space is a coordinate system that is
    1.39 + * aligned with the user space of the filtered element, with its origin located
    1.40 + * at the top left of the filter region, and with one unit equal in size to one
    1.41 + * pixel of the offscreen surface into which the filter output would/will be
    1.42 + * painted.
    1.43 + *
    1.44 + * The definition of "filter region" can be found here:
    1.45 + * http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion
    1.46 + */
    1.47 +class nsFilterInstance
    1.48 +{
    1.49 +  typedef mozilla::gfx::IntRect IntRect;
    1.50 +  typedef mozilla::gfx::SourceSurface SourceSurface;
    1.51 +  typedef mozilla::gfx::DrawTarget DrawTarget;
    1.52 +  typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
    1.53 +
    1.54 +public:
    1.55 +  /**
    1.56 +   * Paint the given filtered frame.
    1.57 +   * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's
    1.58 +   *   frame space (i.e. relative to its origin, the top-left corner of its
    1.59 +   *   border box).
    1.60 +   */
    1.61 +  static nsresult PaintFilteredFrame(nsRenderingContext *aContext,
    1.62 +                                     nsIFrame *aFilteredFrame,
    1.63 +                                     nsSVGFilterPaintCallback *aPaintCallback,
    1.64 +                                     const nsRegion* aDirtyArea,
    1.65 +                                     nsIFrame* aTransformRoot = nullptr);
    1.66 +
    1.67 +  /**
    1.68 +   * Returns the post-filter area that could be dirtied when the given
    1.69 +   * pre-filter area of aFilteredFrame changes.
    1.70 +   * @param aPreFilterDirtyRegion The pre-filter area of aFilteredFrame that has
    1.71 +   *   changed, relative to aFilteredFrame, in app units.
    1.72 +   */
    1.73 +  static nsRegion GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
    1.74 +                                         const nsRegion& aPreFilterDirtyRegion);
    1.75 +
    1.76 +  /**
    1.77 +   * Returns the pre-filter area that is needed from aFilteredFrame when the
    1.78 +   * given post-filter area needs to be repainted.
    1.79 +   * @param aPostFilterDirtyRegion The post-filter area that is dirty, relative
    1.80 +   *   to aFilteredFrame, in app units.
    1.81 +   */
    1.82 +  static nsRegion GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
    1.83 +                                         const nsRegion& aPostFilterDirtyRegion);
    1.84 +
    1.85 +  /**
    1.86 +   * Returns the post-filter visual overflow rect (paint bounds) of
    1.87 +   * aFilteredFrame.
    1.88 +   * @param aOverrideBBox A user space rect, in user units, that should be used
    1.89 +   *   as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null.
    1.90 +   * @param aPreFilterBounds The pre-filter visual overflow rect of
    1.91 +   *   aFilteredFrame, if non-null.
    1.92 +   */
    1.93 +  static nsRect GetPostFilterBounds(nsIFrame *aFilteredFrame,
    1.94 +                                    const gfxRect *aOverrideBBox = nullptr,
    1.95 +                                    const nsRect *aPreFilterBounds = nullptr);
    1.96 +
    1.97 +  /**
    1.98 +   * @param aTargetFrame The frame of the filtered element under consideration.
    1.99 +   * @param aPaintCallback [optional] The callback that Render() should use to
   1.100 +   *   paint. Only required if you will call Render().
   1.101 +   * @param aPostFilterDirtyRegion [optional] The post-filter area
   1.102 +   *   that has to be repainted, in app units. Only required if you will
   1.103 +   *   call ComputeSourceNeededRect() or Render().
   1.104 +   * @param aPreFilterDirtyRegion [optional] The pre-filter area of
   1.105 +   *   the filtered element that changed, in app units. Only required if you
   1.106 +   *   will call ComputePostFilterDirtyRegion().
   1.107 +   * @param aOverridePreFilterVisualOverflowRect [optional] Use a different
   1.108 +   *   visual overflow rect for the target element.
   1.109 +   * @param aOverrideBBox [optional] Use a different SVG bbox for the target
   1.110 +   *   element.
   1.111 +   * @param aTransformRoot [optional] The transform root frame for painting.
   1.112 +   */
   1.113 +  nsFilterInstance(nsIFrame *aTargetFrame,
   1.114 +                   nsSVGFilterPaintCallback *aPaintCallback,
   1.115 +                   const nsRegion *aPostFilterDirtyRegion = nullptr,
   1.116 +                   const nsRegion *aPreFilterDirtyRegion = nullptr,
   1.117 +                   const nsRect *aOverridePreFilterVisualOverflowRect = nullptr,
   1.118 +                   const gfxRect *aOverrideBBox = nullptr,
   1.119 +                   nsIFrame* aTransformRoot = nullptr);
   1.120 +
   1.121 +  /**
   1.122 +   * Returns true if the filter instance was created successfully.
   1.123 +   */
   1.124 +  bool IsInitialized() const { return mInitialized; }
   1.125 +
   1.126 +  /**
   1.127 +   * Draws the filter output into aContext. The area that
   1.128 +   * needs to be painted must have been specified before calling this method
   1.129 +   * by passing it as the aPostFilterDirtyRegion argument to the
   1.130 +   * nsFilterInstance constructor.
   1.131 +   */
   1.132 +  nsresult Render(gfxContext* aContext);
   1.133 +
   1.134 +  /**
   1.135 +   * Sets the aPostFilterDirtyRegion outparam to the post-filter area in frame
   1.136 +   * space that would be dirtied by mTargetFrame when a given
   1.137 +   * pre-filter area of mTargetFrame is dirtied. The pre-filter area must have
   1.138 +   * been specified before calling this method by passing it as the
   1.139 +   * aPreFilterDirtyRegion argument to the nsFilterInstance constructor.
   1.140 +   */
   1.141 +  nsresult ComputePostFilterDirtyRegion(nsRegion* aPostFilterDirtyRegion);
   1.142 +
   1.143 +  /**
   1.144 +   * Sets the aPostFilterExtents outparam to the post-filter bounds in frame
   1.145 +   * space for the whole filter output. This is not necessarily equivalent to
   1.146 +   * the area that would be dirtied in the result when the entire pre-filter
   1.147 +   * area is dirtied, because some filter primitives can generate output
   1.148 +   * without any input.
   1.149 +   */
   1.150 +  nsresult ComputePostFilterExtents(nsRect* aPostFilterExtents);
   1.151 +
   1.152 +  /**
   1.153 +   * Sets the aDirty outparam to the pre-filter bounds in frame space of the
   1.154 +   * area of mTargetFrame that is needed in order to paint the filtered output
   1.155 +   * for a given post-filter dirtied area. The post-filter area must have been
   1.156 +   * specified before calling this method by passing it as the aPostFilterDirtyRegion
   1.157 +   * argument to the nsFilterInstance constructor.
   1.158 +   */
   1.159 +  nsresult ComputeSourceNeededRect(nsRect* aDirty);
   1.160 +
   1.161 +
   1.162 +  /**
   1.163 +   * Returns the transform from filter space to outer-<svg> device space.
   1.164 +   */
   1.165 +  gfxMatrix GetFilterSpaceToDeviceSpaceTransform() const {
   1.166 +    return mFilterSpaceToDeviceSpaceTransform;
   1.167 +  }
   1.168 +
   1.169 +private:
   1.170 +  struct SourceInfo {
   1.171 +    // Specifies which parts of the source need to be rendered.
   1.172 +    // Set by ComputeNeededBoxes().
   1.173 +    nsIntRect mNeededBounds;
   1.174 +
   1.175 +    // The surface that contains the input rendering.
   1.176 +    // Set by BuildSourceImage / BuildSourcePaint.
   1.177 +    mozilla::RefPtr<SourceSurface> mSourceSurface;
   1.178 +
   1.179 +    // The position and size of mSourceSurface in filter space.
   1.180 +    // Set by BuildSourceImage / BuildSourcePaint.
   1.181 +    IntRect mSurfaceRect;
   1.182 +  };
   1.183 +
   1.184 +  /**
   1.185 +   * Creates a SourceSurface for either the FillPaint or StrokePaint graph
   1.186 +   * nodes
   1.187 +   */
   1.188 +  nsresult BuildSourcePaint(SourceInfo *aPrimitive,
   1.189 +                            gfxASurface* aTargetSurface,
   1.190 +                            DrawTarget* aTargetDT);
   1.191 +
   1.192 +  /**
   1.193 +   * Creates a SourceSurface for either the FillPaint and StrokePaint graph
   1.194 +   * nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and
   1.195 +   * mStrokePaint.mSourceSurface respectively.
   1.196 +   */
   1.197 +  nsresult BuildSourcePaints(gfxASurface* aTargetSurface,
   1.198 +                             DrawTarget* aTargetDT);
   1.199 +
   1.200 +  /**
   1.201 +   * Creates the SourceSurface for the SourceGraphic graph node, paints its
   1.202 +   * contents, and assigns it to mSourceGraphic.mSourceSurface.
   1.203 +   */
   1.204 +  nsresult BuildSourceImage(gfxASurface* aTargetSurface,
   1.205 +                            DrawTarget* aTargetDT);
   1.206 +
   1.207 +  /**
   1.208 +   * Build the list of FilterPrimitiveDescriptions that describes the filter's
   1.209 +   * filter primitives and their connections. This populates
   1.210 +   * mPrimitiveDescriptions and mInputImages.
   1.211 +   */
   1.212 +  nsresult BuildPrimitives();
   1.213 +
   1.214 +  /**
   1.215 +   * Add to the list of FilterPrimitiveDescriptions for a particular SVG
   1.216 +   * reference filter or CSS filter. This populates mPrimitiveDescrs and
   1.217 +   * mInputImages.
   1.218 +   */
   1.219 +  nsresult BuildPrimitivesForFilter(const nsStyleFilter& aFilter);
   1.220 +
   1.221 +  /**
   1.222 +   * Computes the filter space bounds of the areas that we actually *need* from
   1.223 +   * the filter sources, based on the value of mPostFilterDirtyRegion.
   1.224 +   * This sets mNeededBounds on the corresponding SourceInfo structs.
   1.225 +   */
   1.226 +  void ComputeNeededBoxes();
   1.227 +
   1.228 +  /**
   1.229 +   * Compute the scale factors between user space and filter space.
   1.230 +   */
   1.231 +  nsresult ComputeUserSpaceToFilterSpaceScale();
   1.232 +
   1.233 +  /**
   1.234 +   * Transform a rect between user space and filter space.
   1.235 +   */
   1.236 +  gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpace) const;
   1.237 +  gfxRect FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const;
   1.238 +
   1.239 +  /**
   1.240 +   * Converts an nsRect or an nsRegion that is relative to a filtered frame's
   1.241 +   * origin (i.e. the top-left corner of its border box) into filter space,
   1.242 +   * rounding out.
   1.243 +   * Returns the entire filter region if aRect / aRegion is null, or if the
   1.244 +   * result is too large to be stored in an nsIntRect.
   1.245 +   */
   1.246 +  nsIntRect FrameSpaceToFilterSpace(const nsRect* aRect) const;
   1.247 +  nsIntRegion FrameSpaceToFilterSpace(const nsRegion* aRegion) const;
   1.248 +
   1.249 +  /**
   1.250 +   * Converts an nsIntRect or an nsIntRegion from filter space into the space
   1.251 +   * that is relative to a filtered frame's origin (i.e. the top-left corner
   1.252 +   * of its border box) in app units, rounding out.
   1.253 +   */
   1.254 +  nsRect FilterSpaceToFrameSpace(const nsIntRect& aRect) const;
   1.255 +  nsRegion FilterSpaceToFrameSpace(const nsIntRegion& aRegion) const;
   1.256 +
   1.257 +  /**
   1.258 +   * Returns the transform from frame space to the coordinate space that
   1.259 +   * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the
   1.260 +   * top-left corner of its border box, aka the top left corner of its mRect.
   1.261 +   */
   1.262 +  gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const;
   1.263 +
   1.264 +  /**
   1.265 +   * The frame for the element that is currently being filtered.
   1.266 +   */
   1.267 +  nsIFrame*               mTargetFrame;
   1.268 +
   1.269 +  nsSVGFilterPaintCallback* mPaintCallback;
   1.270 +
   1.271 +  /**
   1.272 +   * The SVG bbox of the element that is being filtered, in user space.
   1.273 +   */
   1.274 +  gfxRect                 mTargetBBox;
   1.275 +
   1.276 +  /**
   1.277 +   * The transform from filter space to outer-<svg> device space.
   1.278 +   */
   1.279 +  gfxMatrix               mFilterSpaceToDeviceSpaceTransform;
   1.280 +
   1.281 +  /**
   1.282 +   * Transform rects between filter space and frame space in CSS pixels.
   1.283 +   */
   1.284 +  gfxMatrix               mFilterSpaceToFrameSpaceInCSSPxTransform;
   1.285 +  gfxMatrix               mFrameSpaceInCSSPxToFilterSpaceTransform;
   1.286 +
   1.287 +  /**
   1.288 +   * The "filter region", in the filtered element's user space.
   1.289 +   */
   1.290 +  gfxRect                 mUserSpaceBounds;
   1.291 +  nsIntRect               mFilterSpaceBounds;
   1.292 +
   1.293 +  /**
   1.294 +   * The scale factors between user space and filter space.
   1.295 +   */
   1.296 +  gfxSize                 mUserSpaceToFilterSpaceScale;
   1.297 +  gfxSize                 mFilterSpaceToUserSpaceScale;
   1.298 +
   1.299 +  /**
   1.300 +   * Pre-filter paint bounds of the element that is being filtered, in filter
   1.301 +   * space.
   1.302 +   */
   1.303 +  nsIntRect               mTargetBounds;
   1.304 +
   1.305 +  /**
   1.306 +   * The dirty area that needs to be repainted, in filter space.
   1.307 +   */
   1.308 +  nsIntRegion             mPostFilterDirtyRegion;
   1.309 +
   1.310 +  /**
   1.311 +   * The pre-filter area of the filtered element that changed, in filter space.
   1.312 +   */
   1.313 +  nsIntRegion             mPreFilterDirtyRegion;
   1.314 +
   1.315 +  SourceInfo              mSourceGraphic;
   1.316 +  SourceInfo              mFillPaint;
   1.317 +  SourceInfo              mStrokePaint;
   1.318 +  nsIFrame*               mTransformRoot;
   1.319 +  nsTArray<mozilla::RefPtr<SourceSurface>> mInputImages;
   1.320 +  nsTArray<FilterPrimitiveDescription> mPrimitiveDescriptions;
   1.321 +  int32_t                 mAppUnitsPerCSSPx;
   1.322 +  bool                    mInitialized;
   1.323 +};
   1.324 +
   1.325 +#endif

mercurial