1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4 (Public License)
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
6 // Pascal Port By: Milan Marusinec alias Milano
7 // milan@marusinec.sk
8 // http://www.aggpas.org
9 // Copyright (c) 2005-2007
10 //
11 // Permission to copy, use, modify, sell and distribute this software
12 // is granted provided this copyright notice appears in all copies.
13 // This software is provided "as is" without express or implied
14 // warranty, and with no claim as to its suitability for any purpose.
15 //
16 //----------------------------------------------------------------------------
17 // Contact: mcseem@antigrain.com
18 // mcseemagg@yahoo.com
19 // http://www.antigrain.com
20 //
21 // [Pascal Port History] -----------------------------------------------------
22 //
23 // 12.10.2007-Milano: Unit port establishment
24 //
25 { agg_gradient_lut.pas }
26 unit
27 agg_gradient_lut ;
28
29 INTERFACE
30
31 {$I agg_mode.inc }
32
33 uses
34 agg_basics ,
35 agg_array ,
36 agg_dda_line ,
37 agg_color ;
38
39 { TYPES DEFINITION }
40 type
41 gradient_lut_ptr = ^gradient_lut;
42 gradient_lut = object(array_base )
43 private
44 m_color_lut_size : unsigned;
45 m_color_profile : pod_bvector;
46 m_color_lut : pod_array;
47
48 public
49 constructor Construct(size_ : unsigned = 256 );
50 destructor Destruct;
51
52 // Build Gradient Lut
53 // First, call remove_all(), then add_color() at least twice,
54 // then build_lut(). Argument "offset" in add_color must be
55 // in range [0...1] and defines a color stop as it is described
56 // in SVG specification, section Gradients and Patterns.
57 // The simplest linear gradient is:
58 // gradient_lut.add_color(0.0, start_color);
59 // gradient_lut.add_color(1.0, end_color);
60 procedure remove_all;
61 procedure add_color(offset : double; color : aggclr_ptr );
62 procedure build_lut;
63
64 // Size-index Interface. This class can be used directly as the
65 // ColorF in span_gradient. All it needs is two access methods
66 // size() and operator [].
sizenull67 function size : unsigned; virtual;
entrynull68 function entry : unsigned; virtual;
array_operatornull69 function array_operator(i : unsigned ) : pointer; virtual;
70
71 end;
72
73 { GLOBAL VARIABLES & CONSTANTS }
74 { GLOBAL PROCEDURES }
75
76
77 IMPLEMENTATION
78 { LOCAL VARIABLES & CONSTANTS }
79 type
80 color_point_ptr = ^color_point;
81 color_point = object
82 offset : double;
83 color : aggclr;
84
85 constructor Construct; overload;
86 constructor Construct(off : double; c : aggclr_ptr ); overload;
87
88 end;
89
90 color_interpolator = object
91 m_c1 ,
92 m_c2 : aggclr;
93
94 m_len ,
95 m_count : unsigned;
96
97 v ,r ,g ,b ,a : dda_line_interpolator;
98
99 m_is_gray : boolean;
100
101 constructor Construct(c1 ,c2 : aggclr_ptr; len : unsigned; is_gray : boolean = false );
102
103 procedure operator_inc;
104
colornull105 function color : aggclr;
106
107 end;
108
109 { UNIT IMPLEMENTATION }
110 { CONSTRUCT }
111 constructor color_point.Construct;
112 begin
113 offset:=0;
114
115 color.Construct;
116
117 end;
118
119 { CONSTRUCT }
120 constructor color_point.Construct(off : double; c : aggclr_ptr );
121 begin
122 offset:=off;
123
124 color.Construct(c );
125
126 if offset < 0.0 then
127 offset:=0.0;
128
129 if offset > 1.0 then
130 offset:=1.0;
131
132 end;
133
134 { CONSTRUCT }
135 constructor color_interpolator.Construct(c1 ,c2 : aggclr_ptr; len : unsigned; is_gray : boolean = false );
136 begin
137 m_c1.Construct(c1 );
138 m_c2.Construct(c2 );
139
140 m_len :=len;
141 m_count:=0;
142
143 m_is_gray:=is_gray;
144
145 if m_is_gray then
146 v.Construct(c1.v ,c2.v ,len ,14 )
147
148 else
149 begin
150 r.Construct(c1.r ,c2.r ,len ,14 );
151 g.Construct(c1.g ,c2.g ,len ,14 );
152 b.Construct(c1.b ,c2.b ,len ,14 );
153
154 end;
155
156 a.Construct(c1.a ,c2.a ,len ,14 );
157
158 end;
159
160 { OPERATOR_INC }
161 procedure color_interpolator.operator_inc;
162 begin
163 inc(m_count );
164
165 if m_is_gray then
166 v.plus_operator
167
168 else
169 begin
170 r.plus_operator;
171 g.plus_operator;
172 b.plus_operator;
173
174 end;
175
176 a.plus_operator;
177
178 end;
179
180 { COLOR }
color_interpolator.colornull181 function color_interpolator.color : aggclr;
182 begin
183 // result:=m_c1.gradient(@m_c2 ,m_count / m_len );
184
185 if m_is_gray then
186 result.ConstrInt(r._y ,a._y )
187 else
188 result.ConstrInt(r._y ,g._y ,b._y ,a._y )
189
190 end;
191
192 { CONSTRUCT }
193 constructor gradient_lut.Construct(size_ : unsigned = 256 );
194 begin
195 m_color_lut_size:=size_;
196
197 m_color_profile.Construct(sizeof(color_point ) ,4 );
198 m_color_lut.Construct(sizeof(aggclr ) ,m_color_lut_size );
199
200 end;
201
202 { DESTRUCT }
203 destructor gradient_lut.Destruct;
204 begin
205 m_color_profile.Destruct;
206 m_color_lut.Destruct;
207
208 end;
209
210 { REMOVE_ALL }
211 procedure gradient_lut.remove_all;
212 begin
213 m_color_profile.remove_all;
214
215 end;
216
217 { ADD_COLOR }
218 procedure gradient_lut.add_color(offset : double; color : aggclr_ptr );
219 var
220 cp : color_point;
221
222 begin
223 cp.Construct(offset ,color );
224
225 m_color_profile.add(@cp );
226
227 end;
228
229 { offset_less }
offset_lessnull230 function offset_less(a ,b : color_point_ptr ) : boolean;
231 begin
232 result:=a.offset < b.offset;
233
234 end;
235
236 { offset_equal }
offset_equalnull237 function offset_equal(a ,b : color_point_ptr ) : boolean;
238 begin
239 result:=a.offset = b.offset;
240
241 end;
242
243 { BUILD_LUT }
244 procedure gradient_lut.build_lut;
245 var
246 i ,start ,end_ : unsigned;
247
248 c : aggclr;
249
250 ci : color_interpolator;
251
252 begin
253 quick_sort (@m_color_profile ,@offset_less );
254 m_color_profile.cut_at(remove_duplicates(@m_color_profile ,@offset_equal ) );
255
256 if m_color_profile.size >= 2 then
257 begin
258 start:=
259 uround(
260 color_point_ptr(m_color_profile.array_operator(0 ) ).offset * m_color_lut_size );
261
262 c:=color_point_ptr(m_color_profile.array_operator(0 ) ).color;
263 i:=0;
264
265 while i < start do
266 begin
267 aggclr_ptr(m_color_lut.array_operator(i ) )^:=c;
268
269 inc(i );
270
271 end;
272
273 i:=1;
274
275 while i < m_color_profile.size do
276 begin
277 end_:=uround(color_point_ptr(m_color_profile.array_operator(i ) ).offset * m_color_lut_size );
278
279 ci.Construct(
280 @color_point_ptr(m_color_profile.array_operator(i - 1 ) ).color ,
281 @color_point_ptr(m_color_profile.array_operator(i ) ).color ,
282 end_ - start + 1 );
283
284 while start < end_ do
285 begin
286 aggclr_ptr(m_color_lut.array_operator(start ) )^:=ci.color;
287
288 ci.operator_inc;
289
290 inc(start );
291
292 end;
293
294 inc(i );
295
296 end;
297
298 c:=color_point_ptr(m_color_profile.last ).color;
299
300 while end_ < m_color_lut.size do
301 begin
302 aggclr_ptr(m_color_lut.array_operator(end_ ) )^:=c;
303
304 inc(end_ );
305
306 end;
307
308 end;
309
310 end;
311
312 { SIZE }
gradient_lut.sizenull313 function gradient_lut.size : unsigned;
314 begin
315 result:=m_color_lut_size;
316
317 end;
318
319 { ENTRY }
gradient_lut.entrynull320 function gradient_lut.entry : unsigned;
321 begin
322 result:=m_color_lut.m_entry_sz;
323
324 end;
325
326 { ARRAY_OPERATOR }
gradient_lut.array_operatornull327 function gradient_lut.array_operator(i : unsigned ) : pointer;
328 begin
329 result:=m_color_lut.array_operator(i );
330
331 end;
332
333 END.
334
335