Add new convert types 'From Integer' and 'Duplicate' and new layer 'Duplicate'.
[synfig.git] / synfig-core / trunk / src / synfig / layer_duplicate.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file layer_duplicate.cpp
3 **      \brief Implementation of the "Duplicate" layer
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2007 Chris Moore
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 "string.h"
34 #include "layer_duplicate.h"
35 #include "time.h"
36 #include "context.h"
37 #include "paramdesc.h"
38 #include "renddesc.h"
39 #include "surface.h"
40 #include "value.h"
41 #include "valuenode.h"
42 #include "canvas.h"
43
44 #endif
45
46 /* === U S I N G =========================================================== */
47
48 using namespace synfig;
49 using namespace etl;
50 using namespace std;
51
52 /* === G L O B A L S ======================================================= */
53
54 SYNFIG_LAYER_INIT(Layer_Duplicate);
55 SYNFIG_LAYER_SET_NAME(Layer_Duplicate,"duplicate");
56 SYNFIG_LAYER_SET_LOCAL_NAME(Layer_Duplicate,N_("Duplicate"));
57 SYNFIG_LAYER_SET_CATEGORY(Layer_Duplicate,N_("Other"));
58 SYNFIG_LAYER_SET_VERSION(Layer_Duplicate,"0.1");
59 SYNFIG_LAYER_SET_CVS_ID(Layer_Duplicate,"$Id$");
60
61 /* === M E M B E R S ======================================================= */
62
63 Layer_Duplicate::Layer_Duplicate():
64         Layer_Composite(1.0,Color::BLEND_COMPOSITE)
65 {
66 }
67
68 bool
69 Layer_Duplicate::set_param(const String &param, const ValueBase &value)
70 {
71         IMPORT(index);
72         return Layer_Composite::set_param(param,value);
73 }
74
75 ValueBase
76 Layer_Duplicate::get_param(const String &param)const
77 {
78         EXPORT(index);
79
80         EXPORT_NAME();
81         EXPORT_VERSION();
82
83         return Layer_Composite::get_param(param);
84 }
85
86 void
87 Layer_Duplicate::set_time(Context context, Time time)const
88 {
89         context.set_time(time);
90         time_cur=time;
91 }
92
93 void
94 Layer_Duplicate::set_time(Context context, Time time, const Point &pos)const
95 {
96         context.set_time(time,pos);
97         time_cur=time;
98 }
99
100 Color
101 Layer_Duplicate::get_color(Context context, const Point &pos)const
102 {
103         return context.get_color(pos);
104 }
105
106 Layer::Vocab
107 Layer_Duplicate::get_param_vocab()const
108 {
109         Layer::Vocab ret;
110         //ret=Layer_Composite::get_param_vocab();
111
112         ret.push_back(ParamDesc("index")
113                 .set_local_name(_("Index"))
114                 .set_description(_("Copy Index"))
115         );
116
117         return ret;
118 }
119
120 bool
121 Layer_Duplicate::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
122 {
123         if(quality == 10)
124                 return context.accelerated_render(surface,quality,renddesc,cb);
125
126         if(context->empty())
127         {
128                 surface->set_wh(renddesc.get_w(),renddesc.get_h());
129                 surface->clear();
130                 return true;
131         }
132
133         SuperCallback subimagecb;
134         Surface tmp;
135         int i = 0;
136
137         const DynamicParamList &dpl = dynamic_param_list();
138         DynamicParamList::const_iterator iter = dpl.find("index");
139         if (iter == dpl.end())
140                 return context.accelerated_render(surface,quality,renddesc,cb);
141
142         etl::rhandle<ValueNode> param(iter->second);
143         handle<ValueNode_Duplicate>     duplicate_param(handle<ValueNode_Duplicate>::cast_dynamic(param));
144
145         if (!duplicate_param)
146                 return context.accelerated_render(surface,quality,renddesc,cb);
147
148         surface->set_wh(renddesc.get_w(),renddesc.get_h());
149         surface->clear();
150
151         Color::BlendMethod blend_method(get_blend_method());
152         int steps = duplicate_param->count_steps(time_cur);
153
154         duplicate_param->reset_index(time_cur);
155         do
156         {
157                 subimagecb=SuperCallback(cb,i*(5000/steps),(i+1)*(5000/steps),5000);
158                 // \todo can we force a re-evaluation of all the variables without changing the time twice?
159                 context.set_time(time_cur+1);
160                 context.set_time(time_cur);
161                 if(!context.accelerated_render(&tmp,quality,renddesc,&subimagecb)) return false;
162
163                 Surface::alpha_pen apen(surface->begin());
164                 apen.set_alpha(1.0);
165                 // \todo have a checkbox allowing use of 'behind' to reverse the order?
166                 apen.set_blend_method(blend_method);
167                 tmp.blit_to(apen);
168                 i++;
169         } while (duplicate_param->step(time_cur));
170
171         duplicate_param->reset_index(time_cur);
172
173         return true;
174 }