Update with current status
[gnash.git] / libcore / FillStyle.cpp
blobfb5f4660ffcf16869948891919eff1f7966e857e
1 // FillStyle.cpp: Graphical region filling styles, for Gnash.
2 //
3 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc.
5 //
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.
10 //
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"
23 #include <ostream>
24 #include <boost/variant.hpp>
26 #include "CachedBitmap.h"
27 #include "movie_definition.h"
28 #include "SWF.h"
29 #include "GnashNumeric.h"
30 #include "RunResources.h"
31 #include "GnashImage.h"
33 namespace gnash {
35 namespace {
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<>
43 public:
44 SetLerp(const FillStyle::Fill& a, const FillStyle::Fill& b, double ratio)
46 _a(a),
47 _b(b),
48 _ratio(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);
58 private:
59 const FillStyle::Fill& _a;
60 const FillStyle::Fill& _b;
61 const double _ratio;
67 SWFMatrix
68 gradientMatrix(GradientFill::Type t, const SWFMatrix& m)
70 SWFMatrix base;
71 switch (t) {
72 case GradientFill::LINEAR:
73 base.set_translation(128, 0);
74 base.set_scale(1.0 / 128, 1.0 / 128);
75 break;
76 case GradientFill::RADIAL:
77 base.set_scale(1.0 / 512, 1.0 / 512);
78 break;
80 base.concatenate(m);
81 return base;
84 GradientFill::GradientFill(Type t, const SWFMatrix& m,
85 const GradientRecords& recs)
87 spreadMode(PAD),
88 interpolation(RGB),
89 _focalPoint(0.0),
90 _gradients(recs),
91 _type(t),
92 _matrix(gradientMatrix(t, m))
94 assert(recs.empty() || recs.size() > 1);
97 void
98 GradientFill::setFocalPoint(double d)
100 _focalPoint = clamp<float>(d, -1, 1);
103 BitmapFill::BitmapFill(Type t, const CachedBitmap* bi, SWFMatrix m,
104 SmoothingPolicy pol)
106 _type(t),
107 _smoothingPolicy(pol),
108 _matrix(std::move(m)),
109 _bitmapInfo(bi),
110 _md(nullptr),
111 _id(0)
115 BitmapFill::BitmapFill(SWF::FillType t, movie_definition* md,
116 std::uint16_t id, SWFMatrix m)
118 _type(),
119 _smoothingPolicy(),
120 _matrix(std::move(m)),
121 _bitmapInfo(nullptr),
122 _md(md),
123 _id(id)
125 assert(md);
127 _smoothingPolicy = md->get_version() >= 8 ?
128 BitmapFill::SMOOTHING_ON : BitmapFill::SMOOTHING_UNSPECIFIED;
130 switch (t) {
131 case SWF::FILL_TILED_BITMAP_HARD:
132 _type = BitmapFill::TILED;
133 _smoothingPolicy = BitmapFill::SMOOTHING_OFF;
134 break;
136 case SWF::FILL_TILED_BITMAP:
137 _type = BitmapFill::TILED;
138 break;
140 case SWF::FILL_CLIPPED_BITMAP_HARD:
141 _type = BitmapFill::CLIPPED;
142 _smoothingPolicy = BitmapFill::SMOOTHING_OFF;
143 break;
145 case SWF::FILL_CLIPPED_BITMAP:
146 _type = BitmapFill::CLIPPED;
147 break;
149 default:
150 std::abort();
154 BitmapFill::BitmapFill(const BitmapFill& other)
156 _type(other._type),
157 _smoothingPolicy(other._smoothingPolicy),
158 _matrix(other._matrix),
159 _bitmapInfo(other._bitmapInfo),
160 _md(other._md),
161 _id(other._id)
165 BitmapFill::~BitmapFill()
169 BitmapFill&
170 BitmapFill::operator=(const BitmapFill& other)
172 _type = other._type;
173 _smoothingPolicy = other._smoothingPolicy;
174 _matrix = other._matrix;
175 _bitmapInfo = other._bitmapInfo;
176 _md = other._md;
177 _id = other._id;
178 return *this;
181 const CachedBitmap*
182 BitmapFill::bitmap() const
184 if (_bitmapInfo) {
185 return _bitmapInfo.get();
187 if (!_md) {
188 return nullptr;
190 _bitmapInfo = _md->getBitmap(_id);
192 // May still be 0!
193 return _bitmapInfo.get();
196 void
197 GradientFill::setLerp(const GradientFill& a, const GradientFill& b,
198 double ratio)
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);
213 void
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]
220 void
221 setLerp(FillStyle& f, const FillStyle& a, const FillStyle& b, double t)
223 assert(t >= 0 && t <= 1);
224 f.fill = a.fill;
225 boost::apply_visitor(SetLerp(a.fill, b.fill, t), f.fill);
228 std::ostream&
229 operator<<(std::ostream& os, const BitmapFill::SmoothingPolicy& p)
231 switch (p) {
232 case BitmapFill::SMOOTHING_UNSPECIFIED:
233 os << "unspecified";
234 break;
235 case BitmapFill::SMOOTHING_ON:
236 os << "on";
237 break;
238 case BitmapFill::SMOOTHING_OFF:
239 os << "off";
240 break;
241 default:
242 // cast to int required to avoid infinite recursion
243 os << "unknown " << +p;
244 break;
246 return os;
249 std::ostream&
250 operator<<(std::ostream& o, GradientFill::Type t)
252 switch (t) {
253 case GradientFill::LINEAR:
254 return o << "linear";
255 default:
256 case GradientFill::RADIAL:
257 return o << "radial";
261 std::ostream&
262 operator<<(std::ostream& o, GradientFill::SpreadMode t)
264 switch (t) {
265 case GradientFill::PAD:
266 return o << "pad";
267 case GradientFill::REPEAT:
268 return o << "repeat";
269 default:
270 case GradientFill::REFLECT:
271 return o << "reflect";
275 std::ostream&
276 operator<<(std::ostream& o, GradientFill::InterpolationMode t)
278 switch (t) {
279 case GradientFill::RGB:
280 return o << "rgb";
281 default:
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();
303 private:
304 std::ostream& _os;
307 std::ostream&
308 operator<<(std::ostream& os, const FillStyle& fs)
310 FillStyleOutput out(os);
311 boost::apply_visitor(out, fs.fill);
312 return os;
315 } // namespace gnash
318 // Local Variables:
319 // mode: C++
320 // End: