DrawTargetOffset.cpp (9007B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "DrawTargetOffset.h" 8 #include "Logging.h" 9 #include "PathHelpers.h" 10 11 namespace mozilla { 12 namespace gfx { 13 14 DrawTargetOffset::DrawTargetOffset() = default; 15 16 bool DrawTargetOffset::Init(DrawTarget* aDrawTarget, IntPoint aOrigin) { 17 mDrawTarget = aDrawTarget; 18 mOrigin = aOrigin; 19 mDrawTarget->SetTransform(Matrix::Translation(-mOrigin.x, -mOrigin.y)); 20 mFormat = mDrawTarget->GetFormat(); 21 SetPermitSubpixelAA(IsOpaque(mFormat)); 22 return true; 23 } 24 25 already_AddRefed<SourceSurface> DrawTargetOffset::Snapshot() { 26 RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot(); 27 28 if (!snapshot) { 29 return nullptr; 30 } 31 32 return MakeAndAddRef<SourceSurfaceOffset>(snapshot, mOrigin); 33 } 34 35 void DrawTargetOffset::DetachAllSnapshots() {} 36 37 // Skip the mClippedOut check since this is only used for Flush() which 38 // should happen even if we're clipped. 39 #define OFFSET_COMMAND(command) \ 40 void DrawTargetOffset::command() { mDrawTarget->command(); } 41 #define OFFSET_COMMAND1(command, type1) \ 42 void DrawTargetOffset::command(type1 arg1) { mDrawTarget->command(arg1); } 43 #define OFFSET_COMMAND3(command, type1, type2, type3) \ 44 void DrawTargetOffset::command(type1 arg1, type2 arg2, type3 arg3) { \ 45 mDrawTarget->command(arg1, arg2, arg3); \ 46 } 47 #define OFFSET_COMMAND4(command, type1, type2, type3, type4) \ 48 void DrawTargetOffset::command(type1 arg1, type2 arg2, type3 arg3, \ 49 type4 arg4) { \ 50 mDrawTarget->command(arg1, arg2, arg3, arg4); \ 51 } 52 #define OFFSET_COMMAND5(command, type1, type2, type3, type4, type5) \ 53 void DrawTargetOffset::command(type1 arg1, type2 arg2, type3 arg3, \ 54 type4 arg4, type5 arg5) { \ 55 mDrawTarget->command(arg1, arg2, arg3, arg4, arg5); \ 56 } 57 58 OFFSET_COMMAND(Flush) 59 OFFSET_COMMAND1(ClearRect, const Rect&) 60 OFFSET_COMMAND4(MaskSurface, const Pattern&, SourceSurface*, Point, 61 const DrawOptions&) 62 OFFSET_COMMAND4(FillGlyphs, ScaledFont*, const GlyphBuffer&, const Pattern&, 63 const DrawOptions&) 64 OFFSET_COMMAND5(StrokeGlyphs, ScaledFont*, const GlyphBuffer&, const Pattern&, 65 const StrokeOptions&, const DrawOptions&) 66 OFFSET_COMMAND3(FillRoundedRect, const RoundedRect&, const Pattern&, 67 const DrawOptions&) 68 69 bool DrawTargetOffset::Draw3DTransformedSurface(SourceSurface* aSrc, 70 const Matrix4x4& aMatrix) { 71 return mDrawTarget->Draw3DTransformedSurface(aSrc, aMatrix); 72 } 73 74 OFFSET_COMMAND3(Mask, const Pattern&, const Pattern&, const DrawOptions&) 75 76 void DrawTargetOffset::DrawFilter(FilterNode* aNode, const Rect& aSourceRect, 77 const Point& aDestPoint, 78 const DrawOptions& aOptions) { 79 auto clone = mTransform; 80 bool invertible = clone.Invert(); 81 // aSourceRect is in filter space. The filter outputs from aSourceRect need 82 // to be drawn at aDestPoint in user space. 83 Rect userSpaceSource = Rect(aDestPoint, aSourceRect.Size()); 84 if (invertible) { 85 // Try to reduce the source rect so that it's not much bigger 86 // than the draw target. The result is not minimal. Examples 87 // are left as an exercise for the reader. 88 auto destRect = Rect(mDrawTarget->GetRect() + mOrigin); 89 Rect userSpaceBounds = clone.TransformBounds(destRect); 90 userSpaceSource = userSpaceSource.Intersect(userSpaceBounds); 91 } 92 93 // Compute how much we moved the top-left of the source rect by, and use that 94 // to compute the new dest point, and move our intersected source rect back 95 // into the (new) filter space. 96 Point shift = userSpaceSource.TopLeft() - aDestPoint; 97 Rect filterSpaceSource = 98 Rect(aSourceRect.TopLeft() + shift, userSpaceSource.Size()); 99 mDrawTarget->DrawFilter(aNode, filterSpaceSource, aDestPoint + shift, 100 aOptions); 101 } 102 103 void DrawTargetOffset::PushClip(const Path* aPath) { 104 mDrawTarget->PushClip(aPath); 105 } 106 107 void DrawTargetOffset::PushClipRect(const Rect& aRect) { 108 mDrawTarget->PushClipRect(aRect); 109 } 110 111 void DrawTargetOffset::PopClip() { mDrawTarget->PopClip(); } 112 113 void DrawTargetOffset::CopySurface(SourceSurface* aSurface, 114 const IntRect& aSourceRect, 115 const IntPoint& aDestination) { 116 IntPoint tileOrigin = mOrigin; 117 // CopySurface ignores the transform, account for that here. 118 mDrawTarget->CopySurface(aSurface, aSourceRect, aDestination - tileOrigin); 119 } 120 121 void DrawTargetOffset::SetTransform(const Matrix& aTransform) { 122 Matrix mat = aTransform; 123 mat.PostTranslate(Float(-mOrigin.x), Float(-mOrigin.y)); 124 mDrawTarget->SetTransform(mat); 125 126 DrawTarget::SetTransform(aTransform); 127 } 128 129 void DrawTargetOffset::SetPermitSubpixelAA(bool aPermitSubpixelAA) { 130 mDrawTarget->SetPermitSubpixelAA(aPermitSubpixelAA); 131 } 132 133 void DrawTargetOffset::DrawSurface(SourceSurface* aSurface, const Rect& aDest, 134 const Rect& aSource, 135 const DrawSurfaceOptions& aSurfaceOptions, 136 const DrawOptions& aDrawOptions) { 137 mDrawTarget->DrawSurface(aSurface, aDest, aSource, aSurfaceOptions, 138 aDrawOptions); 139 } 140 141 void DrawTargetOffset::FillRect(const Rect& aRect, const Pattern& aPattern, 142 const DrawOptions& aDrawOptions) { 143 mDrawTarget->FillRect(aRect, aPattern, aDrawOptions); 144 } 145 146 void DrawTargetOffset::Stroke(const Path* aPath, const Pattern& aPattern, 147 const StrokeOptions& aStrokeOptions, 148 const DrawOptions& aDrawOptions) { 149 mDrawTarget->Stroke(aPath, aPattern, aStrokeOptions, aDrawOptions); 150 } 151 152 void DrawTargetOffset::StrokeRect(const Rect& aRect, const Pattern& aPattern, 153 const StrokeOptions& aStrokeOptions, 154 const DrawOptions& aDrawOptions) { 155 mDrawTarget->StrokeRect(aRect, aPattern, aStrokeOptions, aDrawOptions); 156 } 157 158 void DrawTargetOffset::StrokeLine(const Point& aStart, const Point& aEnd, 159 const Pattern& aPattern, 160 const StrokeOptions& aStrokeOptions, 161 const DrawOptions& aDrawOptions) { 162 mDrawTarget->StrokeLine(aStart, aEnd, aPattern, aStrokeOptions, aDrawOptions); 163 } 164 165 void DrawTargetOffset::Fill(const Path* aPath, const Pattern& aPattern, 166 const DrawOptions& aDrawOptions) { 167 mDrawTarget->Fill(aPath, aPattern, aDrawOptions); 168 } 169 170 void DrawTargetOffset::PushLayer(bool aOpaque, Float aOpacity, 171 SourceSurface* aMask, 172 const Matrix& aMaskTransform, 173 const IntRect& aBounds, bool aCopyBackground) { 174 IntRect bounds = aBounds - mOrigin; 175 176 mDrawTarget->PushLayer(aOpaque, aOpacity, aMask, aMaskTransform, bounds, 177 aCopyBackground); 178 SetPermitSubpixelAA(mDrawTarget->GetPermitSubpixelAA()); 179 } 180 181 already_AddRefed<SourceSurface> DrawTargetOffset::IntoLuminanceSource( 182 LuminanceType aLuminanceType, float aOpacity) { 183 RefPtr<SourceSurface> surface = 184 mDrawTarget->IntoLuminanceSource(aLuminanceType, aOpacity); 185 186 if (!surface) { 187 return nullptr; 188 } 189 190 return MakeAndAddRef<SourceSurfaceOffset>(surface, mOrigin); 191 } 192 193 void DrawTargetOffset::PushLayerWithBlend(bool aOpaque, Float aOpacity, 194 SourceSurface* aMask, 195 const Matrix& aMaskTransform, 196 const IntRect& aBounds, 197 bool aCopyBackground, 198 CompositionOp aOp) { 199 IntRect bounds = aBounds - mOrigin; 200 201 mDrawTarget->PushLayerWithBlend(aOpaque, aOpacity, aMask, aMaskTransform, 202 bounds, aCopyBackground, aOp); 203 SetPermitSubpixelAA(mDrawTarget->GetPermitSubpixelAA()); 204 } 205 206 void DrawTargetOffset::PopLayer() { 207 mDrawTarget->PopLayer(); 208 SetPermitSubpixelAA(mDrawTarget->GetPermitSubpixelAA()); 209 } 210 211 RefPtr<DrawTarget> DrawTargetOffset::CreateClippedDrawTarget( 212 const Rect& aBounds, SurfaceFormat aFormat) { 213 RefPtr<DrawTarget> result; 214 RefPtr<DrawTarget> dt = 215 mDrawTarget->CreateClippedDrawTarget(aBounds, aFormat); 216 if (dt) { 217 result = gfx::Factory::CreateOffsetDrawTarget(dt, mOrigin); 218 if (result) { 219 result->SetTransform(mTransform); 220 } 221 } 222 return result; 223 } 224 225 } // namespace gfx 226 } // namespace mozilla