/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- registerColorNative
- color_class_init
- attachColorInterface
- color_getrgb
- color_gettransform
- color_setrgb
- color_settransform
- color_ctor
- parseColorTransProp
- getTarget
// Color.cpp: ActionScript class for colors, for Gnash.
//
// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
// 2011 Free Software Foundation, Inc
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
#include "Color_as.h"
#include <sstream>
#include "as_object.h" // for inheritance
#include "log.h"
#include "fn_call.h"
#include "Global_as.h"
#include "smart_ptr.h" // for boost intrusive_ptr
#include "NativeFunction.h"
#include "SWFCxForm.h" // for composition
#include "VM.h"
#include "MovieClip.h"
#include "namedStrings.h"
namespace gnash {
// Forward declarations.
namespace {
as_value color_getrgb(const fn_call& fn);
as_value color_gettransform(const fn_call& fn);
as_value color_setrgb(const fn_call& fn);
as_value color_settransform(const fn_call& fn);
as_value color_ctor(const fn_call& fn);
void attachColorInterface(as_object& o);
inline void parseColorTransProp(as_object& obj, const ObjectURI& key,
boost::int16_t& target, bool scale);
inline MovieClip* getTarget(as_object* obj, const fn_call& fn);
}
void
registerColorNative(as_object& o)
{
VM& vm = getVM(o);
vm.registerNative(color_setrgb, 700, 0);
vm.registerNative(color_settransform, 700, 1);
vm.registerNative(color_getrgb, 700, 2);
vm.registerNative(color_gettransform, 700, 3);
}
// extern (used by Global.cpp)
void
color_class_init(as_object& where, const ObjectURI& uri)
{
as_object* cl = registerBuiltinClass(where, color_ctor,
attachColorInterface, 0, uri);
as_object* proto = toObject(
getMember(*cl, NSV::PROP_PROTOTYPE), getVM(where));
if (!proto) return;
const int protect = as_object::DefaultFlags | PropFlags::readOnly;
proto->set_member_flags(NSV::PROP_uuPROTOuu, protect);
proto->set_member_flags(NSV::PROP_CONSTRUCTOR, protect);
}
namespace {
void
attachColorInterface(as_object& o)
{
VM& vm = getVM(o);
const int flags = PropFlags::dontEnum |
PropFlags::dontDelete |
PropFlags::readOnly;
o.init_member("setRGB", vm.getNative(700, 0), flags);
o.init_member("setTransform", vm.getNative(700, 1), flags);
o.init_member("getRGB", vm.getNative(700, 2), flags);
o.init_member("getTransform", vm.getNative(700, 3), flags);
}
as_value
color_getrgb(const fn_call& fn)
{
as_object* obj = ensure<ValidThis>(fn);
MovieClip* sp = getTarget(obj, fn);
if (!sp) return as_value();
const SWFCxForm& trans = getCxForm(*sp);
const int r = trans.rb;
const int g = trans.gb;
const int b = trans.bb;
const boost::int32_t rgb = (r<<16) | (g<<8) | b;
return as_value(rgb);
}
as_value
color_gettransform(const fn_call& fn)
{
as_object* obj = ensure<ValidThis>(fn);
MovieClip* sp = getTarget(obj, fn);
if (!sp) return as_value();
const SWFCxForm& cx = getCxForm(*sp);
// Convert to as_object
Global_as& gl = getGlobal(fn);
as_object* ret = createObject(gl);
ret->init_member("ra", double(cx.ra / 2.56));
ret->init_member("ga", double(cx.ga / 2.56));
ret->init_member("ba", double(cx.ba / 2.56));
ret->init_member("aa", double(cx.aa / 2.56));
ret->init_member("rb", int(cx.rb));
ret->init_member("gb", int(cx.gb));
ret->init_member("bb", int(cx.bb));
ret->init_member("ab", int(cx.ab));
return ret;
}
as_value
color_setrgb(const fn_call& fn)
{
as_object* obj = ensure<ValidThis>(fn);
if (!fn.nargs) {
IF_VERBOSE_ASCODING_ERRORS(
log_aserror(_("Color.setRGB() : missing argument"));
);
return as_value();
}
MovieClip* sp = getTarget(obj, fn);
if (!sp) return as_value();
boost::int32_t color = toInt(fn.arg(0), getVM(fn));
const int r = (color & 0xff0000) >> 16;
const int g = (color & 0x00ff00) >> 8;
const int b = (color & 0x0000ff);
SWFCxForm newTrans = getCxForm(*sp);
newTrans.rb = static_cast<boost::int16_t>(r);
newTrans.gb = static_cast<boost::int16_t>(g);
newTrans.bb = static_cast<boost::int16_t>(b);
newTrans.ra = 0;
newTrans.ga = 0;
newTrans.ba = 0;
sp->setCxForm(newTrans);
return as_value();
}
as_value
color_settransform(const fn_call& fn)
{
as_object* obj = ensure<ValidThis>(fn);
if (!fn.nargs) {
IF_VERBOSE_ASCODING_ERRORS(
log_aserror(_("Color.setTransform() : missing argument"));
);
return as_value();
}
as_object* trans = toObject(fn.arg(0), getVM(fn));
if (!trans) {
IF_VERBOSE_ASCODING_ERRORS(
std::ostringstream ss; fn.dump_args(ss);
log_aserror(_("Color.setTransform(%s) : first argument doesn't "
"cast to an object"), ss.str());
);
return as_value();
}
MovieClip* sp = getTarget(obj, fn);
if (!sp) return as_value();
VM& vm = getVM(*obj);
SWFCxForm newTrans = getCxForm(*sp);
// TODO: use NSV
// multipliers
parseColorTransProp(*trans, getURI(vm, "ra"), newTrans.ra, true);
parseColorTransProp(*trans, getURI(vm, "ga"), newTrans.ga, true);
parseColorTransProp(*trans, getURI(vm, "ba"), newTrans.ba, true);
parseColorTransProp(*trans, getURI(vm, "aa"), newTrans.aa, true);
// offsets
parseColorTransProp(*trans, getURI(vm, "rb"), newTrans.rb, false);
parseColorTransProp(*trans, getURI(vm, "gb"), newTrans.gb, false);
parseColorTransProp(*trans, getURI(vm, "bb"), newTrans.bb, false);
parseColorTransProp(*trans, getURI(vm, "ab"), newTrans.ab, false);
sp->setCxForm(newTrans);
return as_value();
}
/// The first argument is set as the target property.
//
/// The target property is used to change the MovieClip's color.
/// The pp calls ASSetPropFlags on all Color properties during construction,
/// adding the readOnly flag. Because Gnash adds the __constructor__ property
/// during construction, we have no control over its flags.
as_value
color_ctor(const fn_call& fn)
{
as_object* obj = ensure<ValidThis>(fn);
as_value target;
if (fn.nargs) target = fn.arg(0);
obj->set_member(NSV::PROP_TARGET, target);
Global_as& gl = getGlobal(fn);
as_object* null = 0;
callMethod(&gl, NSV::PROP_AS_SET_PROP_FLAGS, obj, null, 7);
return as_value();
}
inline void
parseColorTransProp(as_object& obj, const ObjectURI& key, boost::int16_t&
target, bool scale)
{
as_value tmp;
if (!obj.get_member(key, &tmp)) return;
const double d = toNumber(tmp, getVM(obj));
if (scale) {
target = static_cast<boost::int16_t>(d * 2.56);
}
else {
target = static_cast<boost::int16_t>(d);
}
}
// First try to convert target to a MovieClip. If that fails, convert to
// a string and look up the target.
inline MovieClip*
getTarget(as_object* obj, const fn_call& fn)
{
const as_value& target = getMember(*obj, NSV::PROP_TARGET);
MovieClip* sp = target.toMovieClip();
if (sp) return sp;
DisplayObject* o = findTarget(fn.env(), target.to_string());
if (o) return o->to_movie();
return 0;
}
} // anonymous namespace
} // end of gnash namespace