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"
9 #include "PathHelpers.h"
14 DrawTargetOffset::DrawTargetOffset() = default;
16 bool DrawTargetOffset::Init(DrawTarget
* aDrawTarget
, IntPoint aOrigin
) {
17 mDrawTarget
= aDrawTarget
;
19 mDrawTarget
->SetTransform(Matrix::Translation(-mOrigin
.x
, -mOrigin
.y
));
20 mFormat
= mDrawTarget
->GetFormat();
21 SetPermitSubpixelAA(IsOpaque(mFormat
));
25 already_AddRefed
<SourceSurface
> DrawTargetOffset::Snapshot() {
26 RefPtr
<SourceSurface
> snapshot
= mDrawTarget
->Snapshot();
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, \
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); \
59 OFFSET_COMMAND1(ClearRect
, const Rect
&)
60 OFFSET_COMMAND4(MaskSurface
, const Pattern
&, SourceSurface
*, Point
,
62 OFFSET_COMMAND4(FillGlyphs
, ScaledFont
*, const GlyphBuffer
&, const Pattern
&,
64 OFFSET_COMMAND5(StrokeGlyphs
, ScaledFont
*, const GlyphBuffer
&, const Pattern
&,
65 const StrokeOptions
&, const DrawOptions
&)
66 OFFSET_COMMAND3(FillRoundedRect
, const RoundedRect
&, const Pattern
&,
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());
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
,
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
,
135 const DrawSurfaceOptions
& aSurfaceOptions
,
136 const DrawOptions
& aDrawOptions
) {
137 mDrawTarget
->DrawSurface(aSurface
, aDest
, aSource
, aSurfaceOptions
,
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
,
178 SetPermitSubpixelAA(mDrawTarget
->GetPermitSubpixelAA());
181 already_AddRefed
<SourceSurface
> DrawTargetOffset::IntoLuminanceSource(
182 LuminanceType aLuminanceType
, float aOpacity
) {
183 RefPtr
<SourceSurface
> surface
=
184 mDrawTarget
->IntoLuminanceSource(aLuminanceType
, aOpacity
);
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
,
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
);
217 result
= gfx::Factory::CreateOffsetDrawTarget(dt
, mOrigin
);
219 result
->SetTransform(mTransform
);
226 } // namespace mozilla