gfxBlur.h (7715B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef GFX_BLUR_H 7 #define GFX_BLUR_H 8 9 #include "gfxTypes.h" 10 #include "gfxRect.h" 11 #include "nsSize.h" 12 #include "gfxPoint.h" 13 #include "mozilla/RefPtr.h" 14 #include "mozilla/gfx/Blur.h" 15 16 class gfxContext; 17 18 namespace mozilla { 19 namespace gfx { 20 struct sRGBColor; 21 struct RectCornerRadii; 22 class SourceSurface; 23 class DrawTarget; 24 } // namespace gfx 25 } // namespace mozilla 26 27 /** 28 * Implementation of a Gaussian blur. 29 * 30 * A Gaussian blur is good for blurring because, when done independently 31 * in the horizontal and vertical directions, it matches the result that 32 * would be obtained using a different (rotated) set of axes. 33 * 34 * Creates an 8-bit alpha channel context for callers to draw in, 35 * spreads the contents of that context, blurs the contents, and applies 36 * it as an alpha mask on a different existing context. 37 * 38 * A spread N makes each output pixel the maximum value of all source 39 * pixels within a square of side length 2N+1 centered on the output pixel. 40 * 41 * A temporary surface is created in the Init function. The caller then draws 42 * any desired content onto the context acquired through GetContext, and lastly 43 * calls Paint to apply the blurred content as an alpha mask. 44 */ 45 class gfxGaussianBlur final { 46 typedef mozilla::gfx::sRGBColor sRGBColor; 47 typedef mozilla::gfx::DrawTarget DrawTarget; 48 typedef mozilla::gfx::RectCornerRadii RectCornerRadii; 49 50 public: 51 gfxGaussianBlur() = default; 52 53 ~gfxGaussianBlur(); 54 55 /** 56 * Constructs a gaussian blur and initializes the temporary surface. 57 * 58 * @param aDestinationCtx The destination to blur to. 59 * 60 * @param aRect The coordinates of the surface to create in device units. 61 * 62 * @param aBlurSigma The blur sigma. 63 * 64 * @param aDirtyRect A pointer to a dirty rect, measured in device units, 65 * if available. This will be used for optimizing the blur operation. It 66 * is safe to pass nullptr here. 67 * 68 * @param aSkipRect A pointer to a rect, measured in device units, that 69 * represents an area where blurring is unnecessary and shouldn't be done 70 * for speed reasons. It is safe to pass nullptr here. 71 * 72 * @param aClamp Whether clamping at border pixels is required. 73 */ 74 mozilla::UniquePtr<gfxContext> Init( 75 gfxContext* aDestinationCtx, const gfxRect& aRect, 76 const mozilla::gfx::IntSize& aSpreadRadius, 77 const mozilla::gfx::Point& aBlurSigma, const gfxRect* aDirtyRect, 78 const gfxRect* aSkipRect, bool aClamp = false); 79 80 mozilla::UniquePtr<gfxContext> Init( 81 gfxContext* aDestinationCtx, const gfxRect& aRect, 82 const mozilla::gfx::IntSize& aSpreadRadius, 83 const mozilla::gfx::IntSize& aBlurRadius, const gfxRect* aDirtyRect, 84 const gfxRect* aSkipRect, bool aClamp = false); 85 86 already_AddRefed<DrawTarget> InitDrawTarget( 87 const mozilla::gfx::DrawTarget* aReferenceDT, 88 const mozilla::gfx::Rect& aRect, 89 const mozilla::gfx::IntSize& aSpreadRadius, 90 const mozilla::gfx::Point& aBlurSigma, 91 const mozilla::gfx::Rect* aDirtyRect = nullptr, 92 const mozilla::gfx::Rect* aSkipRect = nullptr, bool aClamp = false); 93 94 /** 95 * Performs the blur and optionally colors the result if aShadowColor is not 96 * null. 97 */ 98 already_AddRefed<mozilla::gfx::SourceSurface> DoBlur( 99 const mozilla::gfx::sRGBColor* aShadowColor = nullptr, 100 mozilla::gfx::IntPoint* aOutTopLeft = nullptr); 101 102 /** 103 * Does the actual blurring/spreading and mask applying. Users of this 104 * object must have drawn whatever they want to be blurred onto the internal 105 * gfxContext returned by GetContext before calling this. 106 * 107 * @param aDestinationCtx The graphics context on which to apply the 108 * blurred mask. 109 */ 110 void Paint(gfxContext* aDestinationCtx); 111 112 /** 113 * Calculates a blur radius that, when used with box blur, approximates 114 * a Gaussian blur with the given standard deviation. The result of 115 * this function should be used as the aBlurRadius parameter to Init, 116 * above. 117 */ 118 static mozilla::gfx::IntSize CalculateBlurRadius( 119 const gfxPoint& aStandardDeviation); 120 static mozilla::gfx::Point CalculateBlurSigma( 121 const mozilla::gfx::IntSize& aBlurRadius); 122 123 /** 124 * Blurs a coloured rectangle onto aDestinationCtx. This is equivalent 125 * to calling Init(), drawing a rectangle onto the returned surface 126 * and then calling Paint, but may let us optimize better in the 127 * backend. 128 * 129 * @param aDestinationCtx The destination to blur to. 130 * @param aRect The rectangle to blur in device pixels. 131 * @param aCornerRadii Corner radii for aRect, if it is a rounded 132 * rectangle. 133 * @param aBlurRadius The standard deviation of the blur. 134 * @param aShadowColor The color to draw the blurred shadow. 135 * @param aDirtyRect An area in device pixels that is dirty and 136 * needs to be redrawn. 137 * @param aSkipRect An area in device pixels to avoid blurring 138 * over, to prevent unnecessary work. 139 */ 140 static void BlurRectangle(gfxContext* aDestinationCtx, const gfxRect& aRect, 141 const RectCornerRadii* aCornerRadii, 142 const gfxPoint& aBlurStdDev, 143 const sRGBColor& aShadowColor, 144 const gfxRect& aDirtyRect, 145 const gfxRect& aSkipRect); 146 147 static void ShutdownBlurCache(); 148 149 /*** 150 * Blurs an inset box shadow according to a given path. 151 * This is equivalent to calling Init(), drawing the inset path, 152 * and calling paint. Do not call Init() if using this method. 153 * 154 * @param aDestinationCtx The destination to blur to. 155 * @param aDestinationRect The destination rect in device pixels 156 * @param aShadowClipRect The destiniation inner rect of the 157 * inset path in device pixels. 158 * @param aBlurRadius The standard deviation of the blur. 159 * @param aShadowColor The color of the blur. 160 * @param aInnerClipRadii Corner radii for the inside rect if it is a 161 * rounded rect. 162 * @param aSkipRect An area in device pixels we don't have to 163 * paint in. 164 */ 165 void BlurInsetBox(gfxContext* aDestinationCtx, 166 const mozilla::gfx::Rect& aDestinationRect, 167 const mozilla::gfx::Rect& aShadowClipRect, 168 const mozilla::gfx::IntSize& aBlurRadius, 169 const mozilla::gfx::sRGBColor& aShadowColor, 170 const RectCornerRadii* aInnerClipRadii, 171 const mozilla::gfx::Rect& aSkipRect, 172 const mozilla::gfx::Point& aShadowOffset); 173 174 protected: 175 already_AddRefed<mozilla::gfx::SourceSurface> GetInsetBlur( 176 const mozilla::gfx::Rect& aOuterRect, 177 const mozilla::gfx::Rect& aWhitespaceRect, bool aIsDestRect, 178 const mozilla::gfx::sRGBColor& aShadowColor, 179 const mozilla::gfx::IntSize& aBlurRadius, 180 const RectCornerRadii* aInnerClipRadii, DrawTarget* aDestDrawTarget, 181 bool aMirrorCorners); 182 183 /** 184 * The DrawTarget of the temporary alpha surface. 185 */ 186 RefPtr<DrawTarget> mDrawTarget; 187 188 /** 189 * The temporary alpha surface. 190 */ 191 uint8_t* mData = nullptr; 192 193 /** 194 * The object that actually does the blurring for us. 195 */ 196 mozilla::gfx::GaussianBlur mBlur; 197 }; 198 199 #endif /* GFX_BLUR_H */