1 /* === S Y N F I G ========================================================= */
2 /*!	\file zoom.cpp
3 **	\brief Implementation of the "Zoom" layer, aka "Scale"
4 **
5 **	$Id$
6 **
7 **	\legal
8 **	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **	Copyright (c) 2012-2013 Carlos López
10 **
11 **	This package is free software; you can redistribute it and/or
12 **	modify it under the terms of the GNU General Public License as
13 **	published by the Free Software Foundation; either version 2 of
14 **	the License, or (at your option) any later version.
15 **
16 **	This package is distributed in the hope that it will be useful,
17 **	but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **	General Public License for more details.
20 **	\endlegal
21 */
22 /* ========================================================================= */
23 
24 /* === H E A D E R S ======================================================= */
25 
26 #ifdef USING_PCH
27 #	include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #	include <config.h>
31 #endif
32 
33 #include <synfig/localization.h>
34 #include <synfig/general.h>
35 
36 #include <synfig/string.h>
37 #include <synfig/time.h>
38 #include <synfig/context.h>
39 #include <synfig/paramdesc.h>
40 #include <synfig/renddesc.h>
41 #include <synfig/surface.h>
42 #include <synfig/value.h>
43 #include <synfig/valuenode.h>
44 #include <synfig/transform.h>
45 
46 #include "zoom.h"
47 
48 #include <synfig/rendering/common/task/tasktransformation.h>
49 #include <synfig/rendering/primitive/affinetransformation.h>
50 
51 #endif
52 
53 using namespace std;
54 using namespace etl;
55 using namespace synfig;
56 using namespace modules;
57 using namespace lyr_std;
58 
59 /* === M A C R O S ========================================================= */
60 
61 /* === G L O B A L S ======================================================= */
62 
63 SYNFIG_LAYER_INIT(Zoom);
64 SYNFIG_LAYER_SET_NAME(Zoom,"zoom");
65 SYNFIG_LAYER_SET_LOCAL_NAME(Zoom,N_("Scale"));
66 SYNFIG_LAYER_SET_CATEGORY(Zoom,N_("Transform"));
67 SYNFIG_LAYER_SET_VERSION(Zoom,"0.1");
68 SYNFIG_LAYER_SET_CVS_ID(Zoom,"$Id$");
69 
70 /* === P R O C E D U R E S ================================================= */
71 
72 /* === M E T H O D S ======================================================= */
73 
74 /* === E N T R Y P O I N T ================================================= */
75 
Zoom()76 Zoom::Zoom():
77 	param_center(ValueBase(Vector(0,0))),
78 	param_amount(ValueBase(Real(0)))
79 {
80 	SET_INTERPOLATION_DEFAULTS();
81 	SET_STATIC_DEFAULTS();
82 }
83 
84 bool
set_param(const String & param,const ValueBase & value)85 Zoom::set_param(const String & param, const ValueBase &value)
86 {
87 
88 	IMPORT_VALUE(param_center);
89 	IMPORT_VALUE(param_amount);
90 
91 	return false;
92 }
93 
94 ValueBase
get_param(const String & param) const95 Zoom::get_param(const String &param)const
96 {
97 	EXPORT_VALUE(param_center);
98 	EXPORT_VALUE(param_amount);
99 
100 	EXPORT_NAME();
101 	EXPORT_VERSION();
102 
103 	return ValueBase();
104 }
105 
106 Layer::Vocab
get_param_vocab() const107 Zoom::get_param_vocab()const
108 {
109 	Layer::Vocab ret;
110 
111 	ret.push_back(ParamDesc("amount")
112 		.set_local_name(_("Amount"))
113 		.set_description(_("Amount to scale to"))
114 		.set_origin("center")
115 		.set_exponential()
116 	);
117 
118 	ret.push_back(ParamDesc("center")
119 		.set_local_name(_("Origin"))
120 		.set_description(_("Point to scale from"))
121 	);
122 
123 	return ret;
124 }
125 
126 Layer::Handle
hit_check(Context context,const Point & pos) const127 Zoom::hit_check(Context context, const Point &pos)const
128 {
129 	Vector center=param_center.get(Vector());
130 	return context.hit_check((pos-center)/exp(param_amount.get(Real()))+center);
131 }
132 
133 Color
get_color(Context context,const Point & pos) const134 Zoom::get_color(Context context, const Point &pos)const
135 {
136 	Vector center=param_center.get(Vector());
137 	return context.get_color((pos-center)/exp(param_amount.get(Real()))+center);
138 }
139 
140 class lyr_std::Zoom_Trans : public Transform
141 {
142 	etl::handle<const Zoom> layer;
143 public:
Zoom_Trans(const Zoom * x)144 	Zoom_Trans(const Zoom* x):Transform(x->get_guid()),layer(x) { }
145 
perform(const Vector & x) const146 	Vector perform(const Vector& x)const
147 	{
148 		Vector center=layer->param_center.get(Vector());
149 		Real amount=layer->param_amount.get(Real());
150 		return (x-center)*exp(amount)+center;
151 	}
152 
unperform(const Vector & x) const153 	Vector unperform(const Vector& x)const
154 	{
155 		Vector center=layer->param_center.get(Vector());
156 		Real amount=layer->param_amount.get(Real());
157 		return (x-center)/exp(amount)+center;
158 	}
159 
get_string() const160 	String get_string()const
161 	{
162 		return "zoom";
163 	}
164 };
165 etl::handle<Transform>
get_transform() const166 Zoom::get_transform()const
167 {
168 	return new Zoom_Trans(this);
169 }
170 
171 bool
accelerated_render(Context context,Surface * surface,int quality,const RendDesc & renddesc,ProgressCallback * cb) const172 Zoom::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
173 {
174 	Vector center=param_center.get(Vector());
175 	Real amount=param_amount.get(Real());
176 
177 	RendDesc transformed_renddesc(renddesc);
178 	transformed_renddesc.clear_flags();
179 	transformed_renddesc.set_transformation_matrix(
180 		Matrix().set_translate(-center)
181 	  *	Matrix().set_scale(exp(amount))
182 	  *	Matrix().set_translate(center)
183 	  * renddesc.get_transformation_matrix() );
184 
185 	// Render the scene
186 	return context.accelerated_render(surface,quality,transformed_renddesc,cb);
187 }
188 
189 
190 /////
191 bool
accelerated_cairorender(Context context,cairo_t * cr,int quality,const RendDesc & renddesc,ProgressCallback * cb) const192 Zoom::accelerated_cairorender(Context context, cairo_t *cr,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
193 {
194 	Vector center=param_center.get(Vector());
195 	Real amount=param_amount.get(Real());
196 
197 	double zoomfactor=exp(amount);
198 
199 	cairo_save(cr);
200 	cairo_translate(cr, center[0], center[1]);
201 	cairo_scale(cr, zoomfactor, zoomfactor);
202 	cairo_translate(cr, -center[0], -center[1]);
203 
204 	if(!context.accelerated_cairorender(cr,quality,renddesc,cb))
205 	{
206 		cairo_restore(cr);
207 		return false;
208 	}
209 	cairo_restore(cr);
210 	return true;
211 }
212 /////
213 
214 
215 Rect
get_full_bounding_rect(Context context) const216 Zoom::get_full_bounding_rect(Context context)const
217 {
218 	Vector center=param_center.get(Vector());
219 	return (context.get_full_bounding_rect()-center)*exp(param_amount.get(Real()))+center;
220 }
221 
222 rendering::Task::Handle
build_rendering_task_vfunc(Context context) const223 Zoom::build_rendering_task_vfunc(Context context)const
224 {
225 	Real amount=param_amount.get(Real());
226 	Point center=param_center.get(Point());
227 
228 	rendering::TaskTransformation::Handle task_transformation(new rendering::TaskTransformation());
229 	rendering::AffineTransformation::Handle affine_transformation(new rendering::AffineTransformation());
230 	affine_transformation->matrix =
231 			Matrix().set_translate(-center)
232 		  * Matrix().set_scale(exp(amount))
233 		  * Matrix().set_translate(center);
234 	task_transformation->transformation = affine_transformation;
235 	task_transformation->sub_task() = context.build_rendering_task();
236 	return task_transformation;
237 }
238