Bug 1890689 accumulate input in LargerReceiverBlockSizeThanDesiredBuffering GTest...
[gecko.git] / gfx / 2d / DrawTargetOffset.cpp
blobcc49cf04939e44a70b6b22541bf8e01aba84ad4c
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/. */
7 #include "DrawTargetOffset.h"
8 #include "Logging.h"
9 #include "PathHelpers.h"
11 namespace mozilla {
12 namespace gfx {
14 DrawTargetOffset::DrawTargetOffset() = default;
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;
25 already_AddRefed<SourceSurface> DrawTargetOffset::Snapshot() {
26 RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot();
28 if (!snapshot) {
29 return nullptr;
32 return MakeAndAddRef<SourceSurfaceOffset>(snapshot, mOrigin);
35 void DrawTargetOffset::DetachAllSnapshots() {}
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); \
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); \
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); \
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&)
69 bool DrawTargetOffset::Draw3DTransformedSurface(SourceSurface* aSrc,
70 const Matrix4x4& aMatrix) {
71 return mDrawTarget->Draw3DTransformedSurface(aSrc, aMatrix);
74 OFFSET_COMMAND3(Mask, const Pattern&, const Pattern&, const DrawOptions&)
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);
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);
103 void DrawTargetOffset::PushClip(const Path* aPath) {
104 mDrawTarget->PushClip(aPath);
107 void DrawTargetOffset::PushClipRect(const Rect& aRect) {
108 mDrawTarget->PushClipRect(aRect);
111 void DrawTargetOffset::PopClip() { mDrawTarget->PopClip(); }
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);
121 void DrawTargetOffset::SetTransform(const Matrix& aTransform) {
122 Matrix mat = aTransform;
123 mat.PostTranslate(Float(-mOrigin.x), Float(-mOrigin.y));
124 mDrawTarget->SetTransform(mat);
126 DrawTarget::SetTransform(aTransform);
129 void DrawTargetOffset::SetPermitSubpixelAA(bool aPermitSubpixelAA) {
130 mDrawTarget->SetPermitSubpixelAA(aPermitSubpixelAA);
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);
141 void DrawTargetOffset::FillRect(const Rect& aRect, const Pattern& aPattern,
142 const DrawOptions& aDrawOptions) {
143 mDrawTarget->FillRect(aRect, aPattern, aDrawOptions);
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);
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);
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);
165 void DrawTargetOffset::Fill(const Path* aPath, const Pattern& aPattern,
166 const DrawOptions& aDrawOptions) {
167 mDrawTarget->Fill(aPath, aPattern, aDrawOptions);
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;
176 mDrawTarget->PushLayer(aOpaque, aOpacity, aMask, aMaskTransform, bounds,
177 aCopyBackground);
178 SetPermitSubpixelAA(mDrawTarget->GetPermitSubpixelAA());
181 already_AddRefed<SourceSurface> DrawTargetOffset::IntoLuminanceSource(
182 LuminanceType aLuminanceType, float aOpacity) {
183 RefPtr<SourceSurface> surface =
184 mDrawTarget->IntoLuminanceSource(aLuminanceType, aOpacity);
186 if (!surface) {
187 return nullptr;
190 return MakeAndAddRef<SourceSurfaceOffset>(surface, mOrigin);
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;
201 mDrawTarget->PushLayerWithBlend(aOpaque, aOpacity, aMask, aMaskTransform,
202 bounds, aCopyBackground, aOp);
203 SetPermitSubpixelAA(mDrawTarget->GetPermitSubpixelAA());
206 void DrawTargetOffset::PopLayer() {
207 mDrawTarget->PopLayer();
208 SetPermitSubpixelAA(mDrawTarget->GetPermitSubpixelAA());
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);
222 return result;
225 } // namespace gfx
226 } // namespace mozilla