Blame synfig-core/src/synfig/layers/layer_shape.cpp

Carlos Lopez a09598
/* === S Y N F I G ========================================================= */
Carlos Lopez a09598
/*!	\file layer_shape.cpp
Carlos Lopez a09598
**	\brief Implementation of the "Shape" 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) 2012-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
bac702
#include <cfloat></cfloat>
bac702
bw 94d8a6
#include <vector></vector>
bw 94d8a6
Carlos Lopez a09598
#include "layer_shape.h"
62f347
bw 94d8a6
#include <synfig general.h=""></synfig>
bw 94d8a6
#include <synfig localization.h=""></synfig>
bw 94d8a6
bw 94d8a6
#include <synfig blur.h=""></synfig>
Diego Barrios Romero dcc14d
#include <synfig context.h=""></synfig>
bw 94d8a6
#include <synfig curve_helper.h=""></synfig>
Diego Barrios Romero dcc14d
#include <synfig paramdesc.h=""></synfig>
Diego Barrios Romero dcc14d
#include <synfig renddesc.h=""></synfig>
bw 94d8a6
#include <synfig string.h=""></synfig>
Diego Barrios Romero dcc14d
#include <synfig surface.h=""></synfig>
bw 94d8a6
#include <synfig time.h=""></synfig>
Diego Barrios Romero dcc14d
#include <synfig value.h=""></synfig>
Diego Barrios Romero dcc14d
#include <synfig valuenode.h=""></synfig>
Diego Barrios Romero dcc14d
8c834e
#include <synfig intersector.h="" primitive="" rendering=""></synfig>
62f347
#include <synfig common="" rendering="" task="" taskblend.h=""></synfig>
61adbe
#include <synfig common="" rendering="" task="" taskblur.h=""></synfig>
bw 94d8a6
#include <synfig common="" rendering="" task="" taskcontour.h=""></synfig>
563c13
#include <synfig contour.h="" function="" rendering="" software=""></synfig>
dd9f4e
#include <synfig blur.h="" function="" rendering="" software=""></synfig>
62f347
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
/* === U S I N G =========================================================== */
Carlos Lopez a09598
Carlos Lopez a09598
using namespace synfig;
Carlos Lopez a09598
using namespace std;
Carlos Lopez a09598
using namespace etl;
Carlos Lopez a09598
Carlos Lopez a09598
/* === G L O B A L S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
SYNFIG_LAYER_INIT(Layer_Shape);
Carlos Lopez a09598
SYNFIG_LAYER_SET_NAME(Layer_Shape,"shape");
Carlos Lopez a09598
SYNFIG_LAYER_SET_LOCAL_NAME(Layer_Shape,N_("Shape"));
Carlos Lopez a09598
SYNFIG_LAYER_SET_CATEGORY(Layer_Shape,N_("Internal"));
Carlos Lopez a09598
SYNFIG_LAYER_SET_VERSION(Layer_Shape,"0.1");
Carlos Lopez a09598
SYNFIG_LAYER_SET_CVS_ID(Layer_Shape,"$Id$");
Carlos Lopez a09598
Carlos Lopez a09598
/* === C L A S S E S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
/* === M E T H O D S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
Layer_Shape::Layer_Shape(const Real &a, const Color::BlendMethod m):
bac702
	Layer_Composite      (a, m),
Carlos Lopez 519b30
	param_color          (Color::black()),
Carlos Lopez 519b30
	param_origin         (Vector(0,0)),
Carlos Lopez 519b30
	param_invert         (bool(false)),
Carlos Lopez 519b30
	param_antialias      (bool(true)),
Carlos Lopez 519b30
	param_blurtype       (int(Blur::FASTGAUSSIAN)),
Carlos Lopez 519b30
	param_feather        (Real(0.0)),
bac702
	param_winding_style	 (int(rendering::Contour::WINDING_NON_ZERO)),
bac702
	contour				 (new rendering::Contour)
8c834e
{ }
Carlos Lopez a09598
Carlos Lopez a09598
Layer_Shape::~Layer_Shape()
8c834e
	{ }
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
Layer_Shape::clear()
8c834e
	{ contour->clear(); }
Carlos Lopez a09598
Carlos Lopez a09598
bool
dd97a8
Layer_Shape::set_shape_param(const String &/* param */, const synfig::ValueBase &/* value */)
8c834e
	{ return false; }
dd97a8
dd97a8
bool
Carlos Lopez a09598
Layer_Shape::set_param(const String & param, const ValueBase &value)
Carlos Lopez a09598
{
dd97a8
	if (set_shape_param(param, value))
dd97a8
		{ force_sync(); return true; }
dd97a8
Carlos Lopez 519b30
	IMPORT_VALUE_PLUS(param_color,
Carlos Lopez 519b30
	{
Carlos Lopez 519b30
		Color color=param_color.get(Color());
Carlos Lopez 519b30
		if (color.get_a() == 0)
Carlos Lopez 519b30
		{
Carlos Lopez 519b30
			if (converted_blend_)
Carlos Lopez 519b30
			{
Carlos Lopez 519b30
				set_blend_method(Color::BLEND_ALPHA_OVER);
Carlos Lopez 519b30
				color.set_a(1);
Carlos Lopez 519b30
			}
Carlos Lopez 519b30
			else
Carlos Lopez 519b30
			transparent_color_ = true;
Carlos Lopez 519b30
		}
Carlos Lopez 519b30
		param_color.set(color);
Carlos Lopez 519b30
	}
Carlos Lopez 519b30
	);
Carlos Lopez 519b30
	IMPORT_VALUE(param_origin);
Carlos Lopez 519b30
	IMPORT_VALUE(param_invert);
Carlos Lopez 519b30
	IMPORT_VALUE(param_antialias);
Carlos Lopez 519b30
	IMPORT_VALUE_PLUS(param_feather,
Carlos Lopez 519b30
	{
Carlos Lopez 519b30
		Real feather=param_feather.get(Real());
Carlos Lopez 519b30
		if(feather<0)
Carlos Lopez 519b30
		{
Carlos Lopez 519b30
			feather=0;
Carlos Lopez 519b30
			param_feather.set(feather);
Carlos Lopez 519b30
		}
dd9f4e
		set_feather(Vector(feather, feather));
Carlos Lopez 519b30
	}
Carlos Lopez 519b30
	);
Carlos Lopez 519b30
Carlos Lopez 519b30
	IMPORT_VALUE(param_blurtype);
Carlos Lopez 519b30
	IMPORT_VALUE(param_winding_style);
Carlos Lopez a09598
Carlos Lopez 519b30
	if(param=="offset" && param_origin.get_type() == value.get_type())
Carlos Lopez 519b30
	{
Carlos Lopez 519b30
		param_origin=value;
Carlos Lopez 519b30
		return true;
Carlos Lopez 519b30
	}
Carlos Lopez a09598
	return Layer_Composite::set_param(param,value);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
ValueBase
Carlos Lopez a09598
Layer_Shape::get_param(const String ¶m)const
Carlos Lopez a09598
{
Carlos Lopez 519b30
	EXPORT_VALUE(param_color);
Carlos Lopez 519b30
	EXPORT_VALUE(param_origin);
Carlos Lopez 519b30
	EXPORT_VALUE(param_invert);
Carlos Lopez 519b30
	EXPORT_VALUE(param_antialias);
Carlos Lopez 519b30
	EXPORT_VALUE(param_feather);
Carlos Lopez 519b30
	EXPORT_VALUE(param_blurtype);
Carlos Lopez 519b30
	EXPORT_VALUE(param_winding_style);
Carlos Lopez a09598
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
Layer_Shape::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(_("Layer_Shape Color"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("origin")
Carlos Lopez a09598
		.set_local_name(_("Origin"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("invert")
Carlos Lopez a09598
		.set_local_name(_("Invert"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("antialias")
Carlos Lopez a09598
		.set_local_name(_("Antialiasing"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("feather")
Carlos Lopez a09598
		.set_local_name(_("Feather"))
Carlos Lopez a09598
		.set_is_distance()
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("blurtype")
Carlos Lopez a09598
		.set_local_name(_("Type of Feather"))
Carlos Lopez a09598
		.set_description(_("Type of feathering to use"))
Carlos Lopez a09598
		.set_hint("enum")
Carlos Lopez a09598
		.add_enum_value(Blur::BOX,"box",_("Box Blur"))
Carlos Lopez a09598
		.add_enum_value(Blur::FASTGAUSSIAN,"fastgaussian",_("Fast Gaussian Blur"))
Carlos Lopez a09598
		.add_enum_value(Blur::CROSS,"cross",_("Cross-Hatch Blur"))
Carlos Lopez a09598
		.add_enum_value(Blur::GAUSSIAN,"gaussian",_("Gaussian Blur"))
Carlos Lopez a09598
		.add_enum_value(Blur::DISC,"disc",_("Disc Blur"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
	ret.push_back(ParamDesc("winding_style")
Carlos Lopez a09598
		.set_local_name(_("Winding Style"))
Carlos Lopez a09598
		.set_description(_("Winding style to use"))
Carlos Lopez a09598
		.set_hint("enum")
bac702
		.add_enum_value(rendering::Contour::WINDING_NON_ZERO, "nonzero", _("Non Zero"))
bac702
		.add_enum_value(rendering::Contour::WINDING_EVEN_ODD, "evenodd", _("Even/Odd"))
Carlos Lopez a09598
	);
Carlos Lopez a09598
Carlos Lopez a09598
	return ret;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
synfig::Layer::Handle
8c834e
Layer_Shape::hit_check(synfig::Context context, const synfig::Point &point) const
Carlos Lopez a09598
{
dd97a8
	sync();
dd97a8
8c834e
	Color::BlendMethod blend_method = get_blend_method();
8c834e
	Color color = param_color.get(Color());
8c834e
	bool invert = param_invert.get(bool(true));
8c834e
	Point origin = param_origin.get(Point());
8c834e
	rendering::Contour::WindingStyle winding_style = (rendering::Contour::WindingStyle)param_winding_style.get(int());
Carlos Lopez a09598
8c834e
	bool inside = false;
8c834e
	if (get_amount() && blend_method != Color::BLEND_ALPHA_OVER)
8c834e
		inside = contour->is_inside(point - origin, winding_style, invert);
Carlos Lopez a09598
8c834e
	if (inside) {
8c834e
		if (blend_method == Color::BLEND_BEHIND) {
8c834e
			synfig::Layer::Handle layer = context.hit_check(point);
8c834e
			if (layer) return layer;
8c834e
		}
8c834e
		
8c834e
		if (Color::is_onto(blend_method)) {
Carlos Lopez a09598
			//if there's something in the lower layer then we're set...
8c834e
			if (context.hit_check(point))
Carlos Lopez a09598
				return const_cast<layer_shape*>(this);</layer_shape*>
8c834e
		} else
8c834e
		if (blend_method == Color::BLEND_ALPHA_OVER) {
Carlos Lopez a09598
			synfig::info("layer_shape::hit_check - we've got alphaover");
Carlos Lopez a09598
			//if there's something in the lower layer then we're set...
8c834e
			if (color.get_a() < 0.1 && get_amount() > .9) {
Carlos Lopez a09598
				synfig::info("layer_shape::hit_check - can see through us... so nothing");
Carlos Lopez a09598
				return Handle();
8c834e
			}
8c834e
		} else
Carlos Lopez a09598
			return const_cast<layer_shape*>(this);</layer_shape*>
Carlos Lopez a09598
	}
Carlos Lopez a09598
8c834e
	return context.hit_check(point);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Color
Carlos Lopez a09598
Layer_Shape::get_color(Context context, const Point &p)const
Carlos Lopez a09598
{
dd97a8
	sync();
dd97a8
8c834e
	Color color = param_color.get(Color());
8c834e
	Point origin = param_origin.get(Point());
8c834e
	bool invert = param_invert.get(bool(true));
8c834e
	int blurtype = param_blurtype.get(int());
8c834e
	Real feather = param_feather.get(Real());
8c834e
	rendering::Contour::WindingStyle winding_style = (rendering::Contour::WindingStyle)param_winding_style.get(int());
Carlos Lopez 519b30
Carlos Lopez a09598
	Point pp = p;
8c834e
	if (feather)
Carlos Lopez a09598
		pp = Blur(feather,feather,blurtype)(p);
Carlos Lopez a09598
8c834e
	bool inside = contour->is_inside(pp - origin, winding_style, invert);
8c834e
	if (!inside)
8c834e
		return Color::blend(Color::alpha(), context.get_color(pp), get_amount(), get_blend_method());
Carlos Lopez a09598
Carlos Lopez a09598
	//Ok, we're inside... bummmm ba bum buM...
8c834e
	if (get_blend_method() == Color::BLEND_STRAIGHT && get_amount() == 1)
Carlos Lopez a09598
		return color;
8c834e
	
8c834e
	return Color::blend(color, context.get_color(p), get_amount(), get_blend_method());
Carlos Lopez a09598
}
Carlos Lopez a09598
bac702
void Layer_Shape::move_to(Real x, Real y)
8c834e
	{ contour->move_to(Vector(x, y)); }
bac702
void Layer_Shape::close()
8c834e
	{ contour->close(); }
bac702
void Layer_Shape::line_to(Real x, Real y)
8c834e
	{ contour->line_to(Vector(x, y)); }
864ec3
void Layer_Shape::conic_to(Real x, Real y, Real x1, Real y1)
8c834e
	{ contour->conic_to(Vector(x, y), Vector(x1, y1)); }
864ec3
void Layer_Shape::cubic_to(Real x, Real y, Real x1, Real y1, Real x2, Real y2)
8c834e
	{ contour->cubic_to(Vector(x, y), Vector(x1, y1), Vector(x2, y2)); }
8c834e
void Layer_Shape::add(const rendering::Contour::Chunk &chunk)
8c834e
	{ contour->add_chunk(chunk); }
8c834e
void Layer_Shape::add(const rendering::Contour::ChunkList &chunks)
8c834e
	{ contour->add_chunks(chunks); }
8c834e
void Layer_Shape::add_reverse(const rendering::Contour::ChunkList &chunks)
8c834e
	{ contour->add_chunks_reverse(chunks); }
90788e
90788e
void
dd97a8
Layer_Shape::set_time_vfunc(IndependentContext context, Time time)const
dd97a8
{
dd97a8
	sync();
dd97a8
	Layer_Composite::set_time_vfunc(context, time);
dd97a8
}
dd97a8
dd97a8
void
dd97a8
Layer_Shape::sync(bool force) const
dd97a8
{
dd97a8
	if ( force
dd97a8
	  || !last_sync_time.is_equal(get_time_mark())
dd97a8
	  || fabs(last_sync_outline_grow - get_outline_grow_mark()) > 1e-8 )
dd97a8
	{
dd97a8
		last_sync_time = get_time_mark();
dd97a8
		last_sync_outline_grow = get_outline_grow_mark();
dd97a8
		const_cast<layer_shape*>(this)->sync_vfunc();</layer_shape*>
8c834e
		contour->close();
dd97a8
	}
dd97a8
}
dd97a8
dd97a8
void
dd97a8
Layer_Shape::sync_vfunc()
dd97a8
	{ }
dd97a8
bac702
bool
bac702
Layer_Shape::render_shape(Surface *surface, bool useblend, const RendDesc &renddesc) const
bac702
{
864ec3
	Point origin=param_origin.get(Point());
864ec3
	Matrix translate;
864ec3
	translate.set_translate(origin);
bac702
	Matrix world_to_pixels_matrix =
093a8b
	    renddesc.get_world_to_pixels_matrix()
864ec3
	  * renddesc.get_transformation_matrix()
093a8b
	  * translate;
bac702
563c13
	rendering::software::Contour::render_contour(
bac702
		*surface,
bac702
		contour->get_chunks(),
bac702
		param_invert.get(bool(true)),
bac702
		param_antialias.get(bool(true)),
bac702
		(rendering::Contour::WindingStyle)param_winding_style.get(int()),
bac702
		world_to_pixels_matrix,
bac702
		param_color.get(Color()),
bac702
		useblend ? get_amount() : 1.0,
bac702
		useblend ? get_blend_method() : Color::BLEND_STRAIGHT );
Carlos Lopez a09598
bac702
	return true;
bac702
}
Carlos Lopez a09598
bac702
rendering::Task::Handle
735ca3
Layer_Shape::build_composite_task_vfunc(ContextParams /*context_params*/)const
bac702
{
dd97a8
	sync();
61adbe
	rendering::Task::Handle task;
62f347
62f347
	rendering::TaskContour::Handle task_contour(new rendering::TaskContour());
62f347
	// TODO: multithreading without this copying
5e2754
	task_contour->transformation->matrix.set_translate( param_origin.get(Vector()) );
62f347
	task_contour->contour = new rendering::Contour();
62f347
	task_contour->contour->assign(*contour);
8bbd89
	task_contour->contour->color = param_color.get(Color());
8bbd89
	task_contour->contour->invert = param_invert.get(bool());
8bbd89
	task_contour->contour->antialias = param_antialias.get(bool());
8bbd89
	task_contour->contour->winding_style = (rendering::Contour::WindingStyle)param_winding_style.get(int());
61adbe
	task = task_contour;
61adbe
dd9f4e
	rendering::Blur::Type blurtype = (rendering::Blur::Type)param_blurtype.get(int());
dd9f4e
	Vector feather = get_feather();
dd9f4e
	if (feather != Vector::zero())
61adbe
	{
61adbe
		rendering::TaskBlur::Handle task_blur(new rendering::TaskBlur());
dd9f4e
		task_blur->blur.size = feather;
dd9f4e
		task_blur->blur.type = blurtype;
61adbe
		task_blur->sub_task() = task;
61adbe
		task = task_blur;
61adbe
	}
61adbe
61adbe
	return task;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Rect
Carlos Lopez a09598
Layer_Shape::get_bounding_rect()const
Carlos Lopez a09598
{
dd97a8
	sync();
dd9f4e
	Point origin = param_origin.get(Point());
dd9f4e
	bool invert = param_invert.get(bool(true));
dd9f4e
	rendering::Blur::Type blurtype = (rendering::Blur::Type)param_blurtype.get(int());
dd9f4e
	Vector feather = get_feather();
dd9f4e
dd9f4e
	Real feather_amplifier = rendering::software::Blur::get_size_amplifier(blurtype);
Carlos Lopez 519b30
Carlos Lopez a09598
	if(invert)
Carlos Lopez a09598
		return Rect::full_plane();
Carlos Lopez a09598
8c834e
	Rect bounds = contour->get_bounds();
8c834e
	if (!bounds.is_valid())
Carlos Lopez a09598
		return Rect::zero();
8c834e
	
8c834e
	bounds += origin;
dd9f4e
	bounds.expand((bounds.get_min() - bounds.get_max()).mag()*0.01);
dd9f4e
	bounds.expand_x( fabs(feather_amplifier * feather[0]) );
dd9f4e
	bounds.expand_x( fabs(feather_amplifier * feather[1]) );
Carlos Lopez a09598
Carlos Lopez a09598
	return bounds;
Carlos Lopez a09598
}