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 ¶m)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