1 // FillStyle.cpp: Graphical region filling styles, for Gnash.
3 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc.
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "FillStyle.h"
24 #include <boost/variant.hpp>
26 #include "CachedBitmap.h"
27 #include "movie_definition.h"
29 #include "GnashNumeric.h"
30 #include "RunResources.h"
31 #include "GnashImage.h"
37 /// Create a lerped version of two other FillStyles.
39 /// The two fill styles must have exactly the same types. Callers are
40 /// responsible for ensuring this.
41 class SetLerp
: public boost::static_visitor
<>
44 SetLerp(const FillStyle::Fill
& a
, const FillStyle::Fill
& b
, double ratio
)
52 template<typename T
> void operator()(T
& f
) const {
53 const T
& a
= boost::get
<T
>(_a
);
54 const T
& b
= boost::get
<T
>(_b
);
55 f
.setLerp(a
, b
, _ratio
);
59 const FillStyle::Fill
& _a
;
60 const FillStyle::Fill
& _b
;
68 gradientMatrix(GradientFill::Type t
, const SWFMatrix
& m
)
72 case GradientFill::LINEAR
:
73 base
.set_translation(128, 0);
74 base
.set_scale(1.0 / 128, 1.0 / 128);
76 case GradientFill::RADIAL
:
77 base
.set_scale(1.0 / 512, 1.0 / 512);
84 GradientFill::GradientFill(Type t
, const SWFMatrix
& m
,
85 const GradientRecords
& recs
)
92 _matrix(gradientMatrix(t
, m
))
94 assert(recs
.empty() || recs
.size() > 1);
98 GradientFill::setFocalPoint(double d
)
100 _focalPoint
= clamp
<float>(d
, -1, 1);
103 BitmapFill::BitmapFill(Type t
, const CachedBitmap
* bi
, SWFMatrix m
,
107 _smoothingPolicy(pol
),
108 _matrix(std::move(m
)),
115 BitmapFill::BitmapFill(SWF::FillType t
, movie_definition
* md
,
116 std::uint16_t id
, SWFMatrix m
)
120 _matrix(std::move(m
)),
121 _bitmapInfo(nullptr),
127 _smoothingPolicy
= md
->get_version() >= 8 ?
128 BitmapFill::SMOOTHING_ON
: BitmapFill::SMOOTHING_UNSPECIFIED
;
131 case SWF::FILL_TILED_BITMAP_HARD
:
132 _type
= BitmapFill::TILED
;
133 _smoothingPolicy
= BitmapFill::SMOOTHING_OFF
;
136 case SWF::FILL_TILED_BITMAP
:
137 _type
= BitmapFill::TILED
;
140 case SWF::FILL_CLIPPED_BITMAP_HARD
:
141 _type
= BitmapFill::CLIPPED
;
142 _smoothingPolicy
= BitmapFill::SMOOTHING_OFF
;
145 case SWF::FILL_CLIPPED_BITMAP
:
146 _type
= BitmapFill::CLIPPED
;
154 BitmapFill::BitmapFill(const BitmapFill
& other
)
157 _smoothingPolicy(other
._smoothingPolicy
),
158 _matrix(other
._matrix
),
159 _bitmapInfo(other
._bitmapInfo
),
165 BitmapFill::~BitmapFill()
170 BitmapFill::operator=(const BitmapFill
& other
)
173 _smoothingPolicy
= other
._smoothingPolicy
;
174 _matrix
= other
._matrix
;
175 _bitmapInfo
= other
._bitmapInfo
;
182 BitmapFill::bitmap() const
185 return _bitmapInfo
.get();
190 _bitmapInfo
= _md
->getBitmap(_id
);
193 return _bitmapInfo
.get();
197 GradientFill::setLerp(const GradientFill
& a
, const GradientFill
& b
,
200 assert(type() == a
.type());
201 assert(_gradients
.size() == a
.recordCount());
202 assert(_gradients
.size() == b
.recordCount());
204 for (size_t i
= 0, e
= _gradients
.size(); i
< e
; ++i
) {
205 const GradientRecord
& ra
= a
.record(i
);
206 const GradientRecord
& rb
= b
.record(i
);
207 _gradients
[i
].ratio
= frnd(lerp
<float>(ra
.ratio
, rb
.ratio
, ratio
));
208 _gradients
[i
].color
= lerp(ra
.color
, rb
.color
, ratio
);
210 _matrix
.set_lerp(a
.matrix(), b
.matrix(), ratio
);
214 BitmapFill::setLerp(const BitmapFill
& a
, const BitmapFill
& b
, double ratio
)
216 _matrix
.set_lerp(a
.matrix(), b
.matrix(), ratio
);
219 // Sets this style to a blend of a and b. t = [0,1]
221 setLerp(FillStyle
& f
, const FillStyle
& a
, const FillStyle
& b
, double t
)
223 assert(t
>= 0 && t
<= 1);
225 boost::apply_visitor(SetLerp(a
.fill
, b
.fill
, t
), f
.fill
);
229 operator<<(std::ostream
& os
, const BitmapFill::SmoothingPolicy
& p
)
232 case BitmapFill::SMOOTHING_UNSPECIFIED
:
235 case BitmapFill::SMOOTHING_ON
:
238 case BitmapFill::SMOOTHING_OFF
:
242 // cast to int required to avoid infinite recursion
243 os
<< "unknown " << +p
;
250 operator<<(std::ostream
& o
, GradientFill::Type t
)
253 case GradientFill::LINEAR
:
254 return o
<< "linear";
256 case GradientFill::RADIAL
:
257 return o
<< "radial";
262 operator<<(std::ostream
& o
, GradientFill::SpreadMode t
)
265 case GradientFill::PAD
:
267 case GradientFill::REPEAT
:
268 return o
<< "repeat";
270 case GradientFill::REFLECT
:
271 return o
<< "reflect";
276 operator<<(std::ostream
& o
, GradientFill::InterpolationMode t
)
279 case GradientFill::RGB
:
282 case GradientFill::LINEAR_RGB
:
283 return o
<< "linear rgb";
287 struct FillStyleOutput
: boost::static_visitor
<>
289 FillStyleOutput(std::ostream
& o
) : _os(o
) {}
290 void operator()(const BitmapFill
& bf
) {
291 _os
<< boost::format("Bitmap fill: type %1%, smoothing %2%, "
292 "matrix %3%") % bf
.type() % bf
.smoothingPolicy() % bf
.matrix();
294 void operator()(const GradientFill
& gf
) {
295 _os
<< boost::format("Gradient fill: type %1%, spread mode %2%, "
296 "interpolation mode %3%, gradient count %4%, matrix %5%")
297 % gf
.type() % gf
.spreadMode
% gf
.interpolation
%
298 gf
.recordCount() % gf
.matrix();
300 void operator()(const SolidFill
& sf
) {
301 _os
<< boost::format("Solid Fill: color %1%") % sf
.color();
308 operator<<(std::ostream
& os
, const FillStyle
& fs
)
310 FillStyleOutput
out(os
);
311 boost::apply_visitor(out
, fs
.fill
);