|
Carlos Lopez |
a09598 |
/* === S Y N F I G ========================================================= */
|
|
Carlos Lopez |
a09598 |
/*! \file checkerboard.cpp
|
|
Carlos Lopez |
a09598 |
** \brief Implementation of the "Checkerboard" layer
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** $Id$
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** \legal
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2007, 2008 Chris Moore
|
|
Carlos Lopez |
e83454 |
** Copyright (c) 2011-2013 Carlos Lรณpez
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is free software; you can redistribute it and/or
|
|
Carlos Lopez |
a09598 |
** modify it under the terms of the GNU General Public License as
|
|
Carlos Lopez |
a09598 |
** published by the Free Software Foundation; either version 2 of
|
|
Carlos Lopez |
a09598 |
** the License, or (at your option) any later version.
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is distributed in the hope that it will be useful,
|
|
Carlos Lopez |
a09598 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Carlos Lopez |
a09598 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Carlos Lopez |
a09598 |
** General Public License for more details.
|
|
Carlos Lopez |
a09598 |
** \endlegal
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
/* ========================================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === H E A D E R S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#ifdef USING_PCH
|
|
Carlos Lopez |
a09598 |
# include "pch.h"
|
|
Carlos Lopez |
a09598 |
#else
|
|
Carlos Lopez |
a09598 |
#ifdef HAVE_CONFIG_H
|
|
Carlos Lopez |
a09598 |
# include <config.h></config.h>
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
|
e03d25 |
#include <algorithm></algorithm>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#include <synfig string.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig time.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig context.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig paramdesc.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig renddesc.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig surface.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig value.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig valuenode.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig segment.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
|
|
|
e03d25 |
#include <synfig common="" rendering="" task="" tasktransformation.h=""></synfig>
|
|
|
e03d25 |
#include <synfig common="" rendering="" task="" taskblend.h=""></synfig>
|
|
|
e03d25 |
#include <synfig rendering="" software="" task="" tasksw.h=""></synfig>
|
|
|
e03d25 |
|
|
|
e03d25 |
#include "checkerboard.h"
|
|
|
e03d25 |
|
|
|
e03d25 |
#include <synfig localization.h=""></synfig>
|
|
|
e03d25 |
#include <synfig general.h=""></synfig>
|
|
|
e03d25 |
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
using namespace synfig;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M A C R O S ========================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === G L O B A L S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_INIT(CheckerBoard);
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_NAME(CheckerBoard,"checker_board");
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_LOCAL_NAME(CheckerBoard,N_("Checkerboard"));
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_CATEGORY(CheckerBoard,N_("Geometry"));
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_VERSION(CheckerBoard,"0.1");
|
|
Carlos Lopez |
a09598 |
SYNFIG_LAYER_SET_CVS_ID(CheckerBoard,"$Id$");
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === P R O C E D U R E S ================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
|
e03d25 |
namespace {
|
|
|
e03d25 |
|
|
|
e03d25 |
class TaskCheckerBoard: public rendering::Task, public rendering::TaskInterfaceTransformation
|
|
|
e03d25 |
{
|
|
|
e03d25 |
public:
|
|
|
e03d25 |
typedef etl::handle<taskcheckerboard> Handle;</taskcheckerboard>
|
|
|
e03d25 |
static Token token;
|
|
|
e03d25 |
virtual Token::Handle get_token() const { return token.handle(); }
|
|
|
e03d25 |
|
|
|
e03d25 |
Color color;
|
|
|
e03d25 |
bool antialias;
|
|
|
e03d25 |
rendering::Holder<rendering::transformationaffine> transformation;</rendering::transformationaffine>
|
|
|
e03d25 |
|
|
|
e03d25 |
TaskCheckerBoard(): antialias(true) { }
|
|
|
3ae388 |
virtual rendering::Transformation::Handle get_transformation() const
|
|
|
e03d25 |
{ return transformation.handle(); }
|
|
|
e03d25 |
};
|
|
|
e03d25 |
|
|
|
e03d25 |
|
|
|
e03d25 |
class TaskCheckerBoardSW: public TaskCheckerBoard, public rendering::TaskSW,
|
|
|
e03d25 |
public rendering::TaskInterfaceBlendToTarget,
|
|
|
e03d25 |
public rendering::TaskInterfaceSplit
|
|
|
e03d25 |
{
|
|
|
e03d25 |
public:
|
|
|
e03d25 |
typedef etl::handle<taskcheckerboardsw> Handle;</taskcheckerboardsw>
|
|
|
e03d25 |
static Token token;
|
|
|
e03d25 |
virtual Token::Handle get_token() const { return token.handle(); }
|
|
|
e03d25 |
|
|
|
111532 |
virtual void on_target_set_as_source() {
|
|
|
111532 |
Task::Handle &subtask = sub_task(0);
|
|
|
111532 |
if ( subtask
|
|
|
111532 |
&& subtask->target_surface == target_surface
|
|
|
111532 |
&& !Color::is_straight(blend_method) )
|
|
|
111532 |
{
|
|
|
111532 |
trunc_by_bounds();
|
|
|
111532 |
subtask->source_rect = source_rect;
|
|
|
111532 |
subtask->target_rect = target_rect;
|
|
|
111532 |
}
|
|
|
111532 |
}
|
|
|
111532 |
|
|
|
e03d25 |
virtual Color::BlendMethodFlags get_supported_blend_methods() const
|
|
|
e03d25 |
{ return Color::BLEND_METHODS_ALL; }
|
|
|
e03d25 |
|
|
|
e03d25 |
virtual bool run(RunParams&) const {
|
|
|
e03d25 |
if (!is_valid())
|
|
|
e03d25 |
return true;
|
|
|
e03d25 |
|
|
|
e03d25 |
Vector ppu = get_pixels_per_unit();
|
|
|
e03d25 |
|
|
|
e03d25 |
Matrix bounds_transfromation;
|
|
|
e03d25 |
bounds_transfromation.m00 = ppu[0];
|
|
|
e03d25 |
bounds_transfromation.m11 = ppu[1];
|
|
|
e03d25 |
bounds_transfromation.m20 = target_rect.minx - ppu[0]*source_rect.minx;
|
|
|
e03d25 |
bounds_transfromation.m21 = target_rect.miny - ppu[1]*source_rect.miny;
|
|
|
e03d25 |
|
|
|
e03d25 |
Matrix matrix = bounds_transfromation * transformation->matrix;
|
|
|
e03d25 |
Matrix inv_matrix = matrix.get_inverted();
|
|
|
e03d25 |
|
|
|
e03d25 |
int tw = target_rect.get_width();
|
|
|
e03d25 |
Vector dx = inv_matrix.axis_x();
|
|
|
e03d25 |
Vector dy = inv_matrix.axis_y() - dx*(Real)tw;
|
|
|
e03d25 |
Vector p = inv_matrix.get_transformed( Vector((Real)target_rect.minx, (Real)target_rect.miny) );
|
|
|
e03d25 |
|
|
|
e03d25 |
LockWrite la(this);
|
|
|
e03d25 |
if (!la)
|
|
|
e03d25 |
return false;
|
|
|
e03d25 |
|
|
|
e03d25 |
Surface::alpha_pen apen(la->get_surface().get_pen(target_rect.minx, target_rect.miny));
|
|
|
111532 |
ColorReal amount = blend ? this->amount : ColorReal(1.0);
|
|
|
111532 |
apen.set_blend_method(blend ? blend_method : Color::BLEND_COMPOSITE);
|
|
|
e03d25 |
Color c = color;
|
|
|
e03d25 |
if (antialias) {
|
|
|
e03d25 |
ColorReal kx(matrix.axis_x().mag()*0.5);
|
|
|
e03d25 |
ColorReal ky(matrix.axis_y().mag()*0.5);
|
|
|
e03d25 |
for(int iy = target_rect.miny; iy < target_rect.maxy; ++iy, p += dy, apen.inc_y(), apen.dec_x(tw))
|
|
|
e03d25 |
for(int ix = target_rect.minx; ix < target_rect.maxx; ++ix, p += dx, apen.inc_x()) {
|
|
|
e03d25 |
p[0] -= floor(p[0]);
|
|
|
e03d25 |
p[1] -= floor(p[1]);
|
|
|
e03d25 |
|
|
|
e03d25 |
ColorReal px = p[0]*ColorReal(2);
|
|
|
e03d25 |
px -= floor(px);
|
|
|
e03d25 |
px = std::min(px, ColorReal(1) - px)*kx;
|
|
|
e03d25 |
|
|
|
e03d25 |
ColorReal py = p[1]*ColorReal(2);
|
|
|
e03d25 |
py -= floor(py);
|
|
|
e03d25 |
py = std::min(py, ColorReal(1) - py)*ky;
|
|
|
e03d25 |
|
|
|
e03d25 |
ColorReal a = std::min(px, py);
|
|
|
e03d25 |
if ((p[0] < 0.5) != (p[1] < 0.5)) a = -a;
|
|
|
e03d25 |
a = std::max(ColorReal(0), std::min(ColorReal(1), a + ColorReal(0.5)));
|
|
|
e03d25 |
|
|
|
e03d25 |
c.set_a(color.get_a()*a);
|
|
|
e03d25 |
apen.put_value(c, amount);
|
|
|
e03d25 |
}
|
|
|
e03d25 |
} else {
|
|
|
e03d25 |
for(int iy = target_rect.miny; iy < target_rect.maxy; ++iy, p += dy, apen.inc_y(), apen.dec_x(tw))
|
|
|
e03d25 |
for(int ix = target_rect.minx; ix < target_rect.maxx; ++ix, p += dx, apen.inc_x()) {
|
|
|
e03d25 |
p[0] -= floor(p[0]);
|
|
|
e03d25 |
p[1] -= floor(p[1]);
|
|
|
e03d25 |
ColorReal a((p[0] < 0.5) == (p[1] < 0.5) ? 1.0 : 0.0);
|
|
|
e03d25 |
c.set_a(color.get_a()*a);
|
|
|
e03d25 |
apen.put_value(c, amount);
|
|
|
e03d25 |
}
|
|
|
e03d25 |
}
|
|
|
e03d25 |
|
|
|
e03d25 |
return true;
|
|
|
e03d25 |
}
|
|
|
e03d25 |
};
|
|
|
e03d25 |
|
|
|
e03d25 |
rendering::Task::Token TaskCheckerBoard::token(
|
|
|
111532 |
DescAbstract<taskcheckerboard>("CheckerBoard") );</taskcheckerboard>
|
|
|
e03d25 |
rendering::Task::Token TaskCheckerBoardSW::token(
|
|
|
111532 |
DescReal<taskcheckerboardsw, taskcheckerboard="">("CheckerBoardSW") );</taskcheckerboardsw,>
|
|
|
e03d25 |
|
|
|
e03d25 |
} // namespace
|
|
|
e03d25 |
|
|
Carlos Lopez |
a09598 |
/* === M E T H O D S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
CheckerBoard::CheckerBoard():
|
|
Carlos Lopez |
346618 |
Layer_Composite (1.0,Color::BLEND_COMPOSITE),
|
|
Carlos Lopez |
53cfd6 |
param_color (ValueBase(Color::black())),
|
|
Carlos Lopez |
53cfd6 |
param_origin (ValueBase(Point(0.125,0.125))),
|
|
Carlos Lopez |
53cfd6 |
param_size (ValueBase(Point(0.25,0.25)))
|
|
Carlos Lopez |
5b3df3 |
{
|
|
Carlos Lopez |
53cfd6 |
SET_INTERPOLATION_DEFAULTS();
|
|
Carlos Lopez |
53cfd6 |
SET_STATIC_DEFAULTS();
|
|
Carlos Lopez |
5b3df3 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
inline bool
|
|
Carlos Lopez |
a09598 |
CheckerBoard::point_test(const synfig::Point& getpos)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
53cfd6 |
Point origin=param_origin.get(Point());
|
|
Carlos Lopez |
53cfd6 |
Point size=param_size.get(Point());
|
|
Carlos Lopez |
53cfd6 |
|
|
Carlos Lopez |
a09598 |
int val=((int)((getpos[0]-origin[0])/size[0])+(int)((getpos[1]-origin[1])/size[1]));
|
|
Carlos Lopez |
a09598 |
if(getpos[0]-origin[0] < 0.0)
|
|
Carlos Lopez |
a09598 |
val++;
|
|
Carlos Lopez |
a09598 |
if(getpos[1]-origin[1] < 0.0)
|
|
Carlos Lopez |
a09598 |
val++;
|
|
Carlos Lopez |
a09598 |
return val&1;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
CheckerBoard::set_param(const String ¶m, const ValueBase &value)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
53cfd6 |
IMPORT_VALUE_PLUS(param_color,
|
|
Carlos Lopez |
53cfd6 |
{
|
|
Carlos Lopez |
53cfd6 |
Color color(param_color.get(Color()));
|
|
Carlos Lopez |
53cfd6 |
if (color.get_a() == 0)
|
|
Carlos Lopez |
53cfd6 |
{
|
|
Carlos Lopez |
53cfd6 |
if(converted_blend_)
|
|
Carlos Lopez |
53cfd6 |
{
|
|
Carlos Lopez |
53cfd6 |
set_blend_method(Color::BLEND_ALPHA_OVER);
|
|
Carlos Lopez |
53cfd6 |
color.set_a(1);
|
|
Carlos Lopez |
53cfd6 |
param_color.set(color);
|
|
Carlos Lopez |
53cfd6 |
}
|
|
Carlos Lopez |
53cfd6 |
else
|
|
Carlos Lopez |
53cfd6 |
transparent_color_ = true;
|
|
Carlos Lopez |
53cfd6 |
}
|
|
Carlos Lopez |
53cfd6 |
}
|
|
Carlos Lopez |
53cfd6 |
);
|
|
Carlos Lopez |
53cfd6 |
IMPORT_VALUE(param_origin);
|
|
Carlos Lopez |
53cfd6 |
IMPORT_VALUE(param_size);
|
|
Carlos Lopez |
53cfd6 |
|
|
Carlos Lopez |
53cfd6 |
if(param=="pos")
|
|
Carlos Lopez |
1c6c0b |
return set_param("origin", value);
|
|
Carlos Lopez |
53cfd6 |
|
|
Carlos Lopez |
53cfd6 |
for(int i=0;i<2;i++)
|
|
|
e03d25 |
if(param==etl::strprintf("pos[%d]",i) && value.get_type()==type_real)
|
|
Carlos Lopez |
53cfd6 |
{
|
|
Carlos Lopez |
53cfd6 |
Point p=param_origin.get(Point());
|
|
Carlos Lopez |
53cfd6 |
p[i]=value.get(Real());
|
|
Carlos Lopez |
53cfd6 |
param_origin.set(p);
|
|
Carlos Lopez |
53cfd6 |
return true;
|
|
Carlos Lopez |
53cfd6 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return Layer_Composite::set_param(param,value);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ValueBase
|
|
Carlos Lopez |
a09598 |
CheckerBoard::get_param(const String ¶m)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
53cfd6 |
EXPORT_VALUE(param_color);
|
|
Carlos Lopez |
53cfd6 |
EXPORT_VALUE(param_origin);
|
|
Carlos Lopez |
53cfd6 |
EXPORT_VALUE(param_size);
|
|
Carlos Lopez |
a09598 |
EXPORT_NAME();
|
|
Carlos Lopez |
a09598 |
EXPORT_VERSION();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return Layer_Composite::get_param(param);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Layer::Vocab
|
|
Carlos Lopez |
a09598 |
CheckerBoard::get_param_vocab()const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Layer::Vocab ret(Layer_Composite::get_param_vocab());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("color")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Color"))
|
|
Carlos Lopez |
a09598 |
.set_description(_("Color of checkers"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("origin")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Origin"))
|
|
Carlos Lopez |
42e8f2 |
.set_description(_("Center of the checkers"))
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
ret.push_back(ParamDesc("size")
|
|
Carlos Lopez |
a09598 |
.set_local_name(_("Size"))
|
|
Carlos Lopez |
a09598 |
.set_description(_("Size of checkers"))
|
|
Carlos Lopez |
a09598 |
.set_origin("origin")
|
|
Carlos Lopez |
a09598 |
);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return ret;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
synfig::Layer::Handle
|
|
Carlos Lopez |
a09598 |
CheckerBoard::hit_check(synfig::Context context, const synfig::Point &getpos)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(get_amount()!=0.0 && point_test(getpos))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
synfig::Layer::Handle tmp;
|
|
Carlos Lopez |
a09598 |
if(get_blend_method()==Color::BLEND_BEHIND && (tmp=context.hit_check(getpos)))
|
|
Carlos Lopez |
a09598 |
return tmp;
|
|
Carlos Lopez |
a09598 |
if(Color::is_onto(get_blend_method()) && !(tmp=context.hit_check(getpos)))
|
|
Carlos Lopez |
a09598 |
return 0;
|
|
Carlos Lopez |
a09598 |
return const_cast<checkerboard*>(this);</checkerboard*>
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
return context.hit_check(getpos);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Color
|
|
Carlos Lopez |
a09598 |
CheckerBoard::get_color(Context context, const Point &getpos)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
53cfd6 |
Color color=param_color.get(Color());
|
|
Carlos Lopez |
53cfd6 |
|
|
Carlos Lopez |
a09598 |
if(get_amount()!=0.0 && point_test(getpos))
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
|
|
Carlos Lopez |
a09598 |
return color;
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
return Color::blend(color,context.get_color(getpos),get_amount(),get_blend_method());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
return Color::blend(Color::alpha(),context.get_color(getpos),get_amount(),get_blend_method());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
|
e03d25 |
rendering::Task::Handle
|
|
|
e03d25 |
CheckerBoard::build_composite_task_vfunc(ContextParams /*context_params*/)const
|
|
|
e03d25 |
{
|
|
|
e03d25 |
Color color = param_color.get(Color());
|
|
|
e03d25 |
Point origin = param_origin.get(Point());
|
|
|
e03d25 |
Point size = param_size.get(Point());
|
|
|
e03d25 |
|
|
|
e03d25 |
origin[0] += size[0]; // make first cell empty (by history)
|
|
|
e03d25 |
size *= 2.0; // task expects repeat period instead of cell size
|
|
|
e03d25 |
|
|
|
e03d25 |
TaskCheckerBoard::Handle task(new TaskCheckerBoard());
|
|
|
e03d25 |
task->color = color;
|
|
|
e03d25 |
task->transformation->matrix = Matrix().set_translate(origin)
|
|
|
e03d25 |
* Matrix().set_scale(size);
|
|
|
e03d25 |
|
|
|
e03d25 |
return task;
|
|
|
e03d25 |
}
|
|
|
e03d25 |
|