marked stable
[synfig.git] / synfig-core / tags / stable / src / modules / lyr_std / clamp.cpp
1 /* === S I N F G =========================================================== */
2 /*!     \file clamp.cpp
3 **      \brief Template Header
4 **
5 **      $Id: clamp.cpp,v 1.2 2005/01/24 05:00:18 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 **
10 **      This software and associated documentation
11 **      are CONFIDENTIAL and PROPRIETARY property of
12 **      the above-mentioned copyright holder.
13 **
14 **      You may not copy, print, publish, or in any
15 **      other way distribute this software without
16 **      a prior written agreement with
17 **      the copyright holder.
18 **      \endlegal
19 */
20 /* ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #ifdef USING_PCH
25 #       include "pch.h"
26 #else
27 #ifdef HAVE_CONFIG_H
28 #       include <config.h>
29 #endif
30
31 #include "clamp.h"
32 #include <sinfg/string.h>
33 #include <sinfg/time.h>
34 #include <sinfg/context.h>
35 #include <sinfg/paramdesc.h>
36 #include <sinfg/renddesc.h>
37 #include <sinfg/surface.h>
38 #include <sinfg/value.h>
39 #include <sinfg/valuenode.h>
40
41 #endif
42
43 /* === U S I N G =========================================================== */
44
45 using namespace etl;
46 using namespace std;
47 using namespace sinfg;
48
49 /* === G L O B A L S ======================================================= */
50
51 SINFG_LAYER_INIT(Layer_Clamp);
52 SINFG_LAYER_SET_NAME(Layer_Clamp,"clamp");
53 SINFG_LAYER_SET_LOCAL_NAME(Layer_Clamp,_("Clamp"));
54 SINFG_LAYER_SET_CATEGORY(Layer_Clamp,_("Filters"));
55 SINFG_LAYER_SET_VERSION(Layer_Clamp,"0.2");
56 SINFG_LAYER_SET_CVS_ID(Layer_Clamp,"$Id: clamp.cpp,v 1.2 2005/01/24 05:00:18 darco Exp $");
57
58 /* === P R O C E D U R E S ================================================= */
59
60 /* === M E T H O D S ======================================================= */
61
62 /* === E N T R Y P O I N T ================================================= */
63
64 Layer_Clamp::Layer_Clamp():
65         invert_negative(false),
66         clamp_ceiling(true),
67         ceiling(1.0f),
68         floor(0.0f)
69 {
70 }
71
72 inline Color
73 Layer_Clamp::clamp_color(const Color &in)const
74 {
75         Color ret(in);
76                 
77         if(ret.get_a()==0)
78                 return Color::alpha();
79
80         if(invert_negative)
81         {
82                 if(ret.get_a()<floor)
83                         ret=-ret;
84         
85                 if(ret.get_r()<floor)
86                 {
87                         ret.set_g(ret.get_g()-ret.get_r());
88                         ret.set_b(ret.get_b()-ret.get_r());
89                         ret.set_r(floor);
90                 }
91                 if(ret.get_g()<floor)
92                 {
93                         ret.set_r(ret.get_r()-ret.get_g());
94                         ret.set_b(ret.get_b()-ret.get_g());
95                         ret.set_g(floor);
96                 }
97                 if(ret.get_b()<floor)
98                 {
99                         ret.set_g(ret.get_g()-ret.get_b());
100                         ret.set_r(ret.get_r()-ret.get_b());
101                         ret.set_b(floor);
102                 }
103         }
104         else
105         {
106                 if(ret.get_r()<floor) ret.set_r(floor);
107                 if(ret.get_g()<floor) ret.set_g(floor);
108                 if(ret.get_b()<floor) ret.set_b(floor);
109                 if(ret.get_a()<floor) ret.set_a(floor);
110         }
111
112         if(clamp_ceiling)
113         {
114                 if(ret.get_r()>ceiling) ret.set_r(ceiling);
115                 if(ret.get_g()>ceiling) ret.set_g(ceiling);
116                 if(ret.get_b()>ceiling) ret.set_b(ceiling);
117                 if(ret.get_a()>ceiling) ret.set_a(ceiling);
118         }
119         return ret;
120 }
121         
122 bool
123 Layer_Clamp::set_param(const String & param, const ValueBase &value)
124 {
125         IMPORT(invert_negative);
126         IMPORT(clamp_ceiling);
127         IMPORT(ceiling);
128         IMPORT(floor);
129         
130         return false;   
131 }
132
133 ValueBase
134 Layer_Clamp::get_param(const String &param)const
135 {
136         EXPORT(invert_negative);
137         EXPORT(clamp_ceiling);
138
139         EXPORT(ceiling);
140         EXPORT(floor);
141
142         EXPORT_NAME();
143         EXPORT_VERSION();
144                 
145         return ValueBase();     
146 }
147
148 Layer::Vocab
149 Layer_Clamp::get_param_vocab()const
150 {
151         Layer::Vocab ret;
152         
153         ret.push_back(ParamDesc("invert_negative")
154                 .set_local_name(_("Invert Negative"))
155         );
156
157         ret.push_back(ParamDesc("clamp_ceiling")
158                 .set_local_name(_("Clamp Ceiling"))
159         );
160
161         ret.push_back(ParamDesc("ceiling")
162                 .set_local_name(_("Ceiling"))
163         );
164
165         ret.push_back(ParamDesc("floor")
166                 .set_local_name(_("Floor"))
167         );
168         
169         return ret;
170 }
171
172 Color
173 Layer_Clamp::get_color(Context context, const Point &pos)const
174 {
175         return clamp_color(context.get_color(pos));
176 }
177         
178 bool
179 Layer_Clamp::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
180 {
181         SuperCallback supercb(cb,0,9500,10000);
182
183         if(!context.accelerated_render(surface,quality,renddesc,&supercb))
184                 return false;
185
186         int x,y;
187
188         Surface::pen pen(surface->begin());
189
190         for(y=0;y<renddesc.get_h();y++,pen.inc_y(),pen.dec_x(x))
191                 for(x=0;x<renddesc.get_w();x++,pen.inc_x())
192                         pen.put_value(clamp_color(pen.get_value()));
193
194         // Mark our progress as finished
195         if(cb && !cb->amount_complete(10000,10000))
196                 return false;
197
198         return true;
199 }
200
201
202 Rect
203 Layer_Clamp::get_full_bounding_rect(Context context)const
204 {
205         return context.get_full_bounding_rect();
206 }