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