Merge branch 'master' of git.sv.gnu.org:/srv/git/gnash
[gnash.git] / libcore / asobj / Color_as.cpp
blob46456aeeb5ba3fc5a896ec582c3e58ac1f39e0da
1 // Color.cpp: ActionScript class for colors, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
4 // 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.
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 "Color_as.h"
23 #include <sstream>
25 #include "as_object.h" // for inheritance
26 #include "log.h"
27 #include "fn_call.h"
28 #include "Global_as.h"
29 #include "smart_ptr.h" // for boost intrusive_ptr
30 #include "builtin_function.h" // need builtin_function
31 #include "NativeFunction.h"
32 #include "SWFCxForm.h" // for composition
33 #include "VM.h"
34 #include "MovieClip.h"
35 #include "namedStrings.h"
37 namespace gnash {
39 // Forward declarations.
40 namespace {
41 as_value color_getrgb(const fn_call& fn);
42 as_value color_gettransform(const fn_call& fn);
43 as_value color_setrgb(const fn_call& fn);
44 as_value color_settransform(const fn_call& fn);
45 as_value color_ctor(const fn_call& fn);
47 void attachColorInterface(as_object& o);
48 inline void parseColorTransProp(as_object& obj, const ObjectURI& key,
49 boost::int16_t& target, bool scale);
50 inline MovieClip* getTarget(as_object* obj, const fn_call& fn);
53 void
54 registerColorNative(as_object& o)
56 VM& vm = getVM(o);
58 vm.registerNative(color_setrgb, 700, 0);
59 vm.registerNative(color_settransform, 700, 1);
60 vm.registerNative(color_getrgb, 700, 2);
61 vm.registerNative(color_gettransform, 700, 3);
64 // extern (used by Global.cpp)
65 void
66 color_class_init(as_object& where, const ObjectURI& uri)
68 as_object* cl = registerBuiltinClass(where, color_ctor,
69 attachColorInterface, 0, uri);
71 as_object* proto = toObject(
72 getMember(*cl, NSV::PROP_PROTOTYPE), getVM(where));
74 if (!proto) return;
76 const int protect = as_object::DefaultFlags | PropFlags::readOnly;
77 proto->set_member_flags(NSV::PROP_uuPROTOuu, protect);
78 proto->set_member_flags(NSV::PROP_CONSTRUCTOR, protect);
83 namespace {
85 void
86 attachColorInterface(as_object& o)
88 VM& vm = getVM(o);
90 const int flags = PropFlags::dontEnum |
91 PropFlags::dontDelete |
92 PropFlags::readOnly;
94 o.init_member("setRGB", vm.getNative(700, 0), flags);
95 o.init_member("setTransform", vm.getNative(700, 1), flags);
96 o.init_member("getRGB", vm.getNative(700, 2), flags);
97 o.init_member("getTransform", vm.getNative(700, 3), flags);
101 as_value
102 color_getrgb(const fn_call& fn)
104 as_object* obj = ensure<ValidThis>(fn);
106 MovieClip* sp = getTarget(obj, fn);
107 if (!sp) return as_value();
109 const SWFCxForm& trans = getCxForm(*sp);
111 const int r = trans.rb;
112 const int g = trans.gb;
113 const int b = trans.bb;
115 const boost::int32_t rgb = (r<<16) | (g<<8) | b;
117 return as_value(rgb);
120 as_value
121 color_gettransform(const fn_call& fn)
123 as_object* obj = ensure<ValidThis>(fn);
125 MovieClip* sp = getTarget(obj, fn);
126 if (!sp) return as_value();
128 const SWFCxForm& cx = getCxForm(*sp);
130 // Convert to as_object
132 Global_as& gl = getGlobal(fn);
133 as_object* ret = createObject(gl);
135 ret->init_member("ra", double(cx.ra / 2.56));
136 ret->init_member("ga", double(cx.ga / 2.56));
137 ret->init_member("ba", double(cx.ba / 2.56));
138 ret->init_member("aa", double(cx.aa / 2.56));
140 ret->init_member("rb", int(cx.rb));
141 ret->init_member("gb", int(cx.gb));
142 ret->init_member("bb", int(cx.bb));
143 ret->init_member("ab", int(cx.ab));
145 return ret;
148 as_value
149 color_setrgb(const fn_call& fn)
151 as_object* obj = ensure<ValidThis>(fn);
153 if (!fn.nargs) {
154 IF_VERBOSE_ASCODING_ERRORS(
155 log_aserror(_("Color.setRGB() : missing argument"));
157 return as_value();
160 MovieClip* sp = getTarget(obj, fn);
161 if (!sp) return as_value();
163 boost::int32_t color = toInt(fn.arg(0), getVM(fn));
165 const int r = (color & 0xff0000) >> 16;
166 const int g = (color & 0x00ff00) >> 8;
167 const int b = (color & 0x0000ff);
169 SWFCxForm newTrans = getCxForm(*sp);
170 newTrans.rb = static_cast<boost::int16_t>(r);
171 newTrans.gb = static_cast<boost::int16_t>(g);
172 newTrans.bb = static_cast<boost::int16_t>(b);
173 newTrans.ra = 0;
174 newTrans.ga = 0;
175 newTrans.ba = 0;
177 sp->setCxForm(newTrans);
179 return as_value();
181 as_value
182 color_settransform(const fn_call& fn)
184 as_object* obj = ensure<ValidThis>(fn);
186 if (!fn.nargs) {
187 IF_VERBOSE_ASCODING_ERRORS(
188 log_aserror(_("Color.setTransform() : missing argument"));
190 return as_value();
193 as_object* trans = toObject(fn.arg(0), getVM(fn));
195 if (!trans) {
196 IF_VERBOSE_ASCODING_ERRORS(
197 std::ostringstream ss; fn.dump_args(ss);
198 log_aserror(_("Color.setTransform(%s) : first argument doesn't "
199 "cast to an object"), ss.str());
201 return as_value();
204 MovieClip* sp = getTarget(obj, fn);
205 if (!sp) return as_value();
207 VM& vm = getVM(*obj);
209 SWFCxForm newTrans = getCxForm(*sp);
211 // TODO: use NSV
213 // multipliers
214 parseColorTransProp(*trans, getURI(vm, "ra"), newTrans.ra, true);
215 parseColorTransProp(*trans, getURI(vm, "ga"), newTrans.ga, true);
216 parseColorTransProp(*trans, getURI(vm, "ba"), newTrans.ba, true);
217 parseColorTransProp(*trans, getURI(vm, "aa"), newTrans.aa, true);
219 // offsets
220 parseColorTransProp(*trans, getURI(vm, "rb"), newTrans.rb, false);
221 parseColorTransProp(*trans, getURI(vm, "gb"), newTrans.gb, false);
222 parseColorTransProp(*trans, getURI(vm, "bb"), newTrans.bb, false);
223 parseColorTransProp(*trans, getURI(vm, "ab"), newTrans.ab, false);
225 sp->setCxForm(newTrans);
227 return as_value();
230 /// The first argument is set as the target property.
232 /// The target property is used to change the MovieClip's color.
233 /// The pp calls ASSetPropFlags on all Color properties during construction,
234 /// adding the readOnly flag. Because Gnash adds the __constructor__ property
235 /// during construction, we have no control over its flags.
236 as_value
237 color_ctor(const fn_call& fn)
240 as_object* obj = ensure<ValidThis>(fn);
242 as_value target;
243 if (fn.nargs) target = fn.arg(0);
245 obj->set_member(NSV::PROP_TARGET, target);
247 Global_as& gl = getGlobal(fn);
248 as_object* null = 0;
249 callMethod(&gl, NSV::PROP_AS_SET_PROP_FLAGS, obj, null, 7);
251 return as_value();
254 inline void
255 parseColorTransProp(as_object& obj, const ObjectURI& key, boost::int16_t&
256 target, bool scale)
258 as_value tmp;
259 if (!obj.get_member(key, &tmp)) return;
261 const double d = toNumber(tmp, getVM(obj));
262 if (scale) {
263 target = static_cast<boost::int16_t>(d * 2.56);
265 else {
266 target = static_cast<boost::int16_t>(d);
270 // First try to convert target to a MovieClip. If that fails, convert to
271 // a string and look up the target.
272 inline MovieClip*
273 getTarget(as_object* obj, const fn_call& fn)
275 const as_value& target = getMember(*obj, NSV::PROP_TARGET);
276 MovieClip* sp = target.toMovieClip();
277 if (sp) return sp;
278 DisplayObject* o = findTarget(fn.env(), target.to_string());
279 if (o) return o->to_movie();
280 return 0;
283 } // anonymous namespace
284 } // end of gnash namespace