1
//----------------------------------------------------------------------------
2
// Anti-Grain Geometry - Version 2.4 (Public License)
3
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5
// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
6
// Pascal Port By: Milan Marusinec alias Milano
8
// http://www.aggpas.org
9
// Copyright (c) 2005-2006
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.
16
//----------------------------------------------------------------------------
17
// Contact: mcseem@antigrain.com
18
// mcseemagg@yahoo.com
19
// http://www.antigrain.com
21
//----------------------------------------------------------------------------
23
// Adaptation for high precision colors has been sponsored by
24
// Liberty Technology Systems, Inc., visit http://lib-sys.com
26
// Liberty Technology Systems, Inc. is the provider of
27
// PostScript and PDF technology for software developers.
29
// [Pascal Port History] -----------------------------------------------------
31
// 23.06.2006-Milano: ptrcomp adjustments
32
// 27.01.2006-Milano: Unit port establishment
34
{ agg_span_gouraud_rgba.pas }
36
agg_span_gouraud_rgba ;
53
subpixel_size = 1 shl subpixel_shift;
56
rgba_calc_ptr = ^rgba_calc;
58
m_x1 ,m_y1 ,m_dx ,m_1dy : double;
60
m_r1 ,m_g1 ,m_b1 ,m_a1 ,
61
m_dr ,m_dg ,m_db ,m_da ,
62
m_r ,m_g ,m_b ,m_a ,m_x : int;
64
function round(v : double ) : int;
65
procedure init (c1 ,c2 : coord_type_ptr );
66
procedure calc (y : double );
70
span_gouraud_rgba_ptr = ^span_gouraud_rgba;
71
span_gouraud_rgba = object(span_gouraud )
79
constructor Construct(alloc : span_allocator_ptr ); overload;
80
constructor Construct(
81
alloc : span_allocator_ptr;
82
c1 ,c2 ,c3 : aggclr_ptr;
83
x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d : double ); overload;
85
procedure prepare (max_span_len : unsigned ); virtual;
86
function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
89
constructor Construct_(
90
c1 ,c2 ,c3 : aggclr_ptr;
91
x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double;
95
procedure generate_(span : aggclr_ptr; x ,y : int; len : unsigned );
103
{ LOCAL VARIABLES & CONSTANTS }
104
{ UNIT IMPLEMENTATION }
106
function rgba_calc.round;
109
result:=trunc(v - 0.5 )
111
result:=trunc(v + 0.5 );
116
procedure rgba_calc.init;
136
m_dr:=c2.color.r - m_r1;
137
m_dg:=c2.color.g - m_g1;
138
m_db:=c2.color.b - m_b1;
139
m_da:=c2.color.a - m_a1;
144
procedure rgba_calc.calc;
149
k:=(y - m_y1 ) * m_1dy;
157
m_r:=m_r1 + self.round(m_dr * k );
158
m_g:=m_g1 + self.round(m_dg * k );
159
m_b:=m_b1 + self.round(m_db * k );
160
m_a:=m_a1 + self.round(m_da * k );
161
m_x:=self.round((m_x1 + m_dx * k ) * subpixel_size );
166
constructor span_gouraud_rgba.Construct(alloc : span_allocator_ptr );
168
inherited Construct(alloc );
173
constructor span_gouraud_rgba.Construct(
174
alloc : span_allocator_ptr;
175
c1 ,c2 ,c3 : aggclr_ptr;
176
x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d : double );
178
inherited Construct(alloc ,c1 ,c2 ,c3 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d );
183
procedure span_gouraud_rgba.prepare;
185
coord : array[0..2 ] of coord_type;
188
inherited prepare(max_span_len );
190
arrange_vertices(@coord );
192
m_y2:=trunc(coord[1 ].y );
196
coord[0 ].x ,coord[0 ].y,
197
coord[2 ].x ,coord[2 ].y,
198
coord[1 ].x ,coord[1 ].y ) < 0.0;
200
m_rgba1.init(@coord[0 ] ,@coord[2 ] );
201
m_rgba2.init(@coord[0 ] ,@coord[1 ] );
202
m_rgba3.init(@coord[1 ] ,@coord[2 ] );
207
function span_gouraud_rgba.generate;
209
lim = agg_color.base_mask;
212
pc1 ,pc2 ,t : rgba_calc_ptr;
214
nlen ,start ,vr ,vg ,vb ,va : int;
216
r ,g ,b ,a : dda_line_interpolator;
221
m_rgba1.calc(y ); //(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
227
// Bottom part of the triangle (first subtriangle)
228
m_rgba2.calc(y + m_rgba2.m_1dy )
231
// Upper part (second subtriangle)
232
m_rgba3.calc(y - m_rgba3.m_1dy );
240
// It means that the triangle is oriented clockwise,
241
// so that we need to swap the controlling structures
248
// Get the horizontal length with subpixel accuracy
249
// and protect it from division by zero
250
nlen:=Abs(pc2.m_x - pc1.m_x );
255
r.Construct(pc1.m_r ,pc2.m_r ,nlen ,14 );
256
g.Construct(pc1.m_g ,pc2.m_g ,nlen ,14 );
257
b.Construct(pc1.m_b ,pc2.m_b ,nlen ,14 );
258
a.Construct(pc1.m_a ,pc2.m_a ,nlen ,14 );
260
// Calculate the starting point of the gradient with subpixel
261
// accuracy and correct (roll back) the interpolators.
262
// This operation will also clip the beginning of the span
264
start:=pc1.m_x - (x shl subpixel_shift );
266
r.dec_operator(start );
267
g.dec_operator(start );
268
b.dec_operator(start );
269
a.dec_operator(start );
273
span:=_allocator.span;
275
// Beginning part of the span. Since we rolled back the
276
// interpolators, the color values may have overflow.
277
// So that, we render the beginning part with checking
278
// for overflow. It lasts until "start" is positive;
279
// typically it's 1-2 pixels, but may be more in some cases.
280
while (len <> 0 ) and
317
r.inc_operator(subpixel_size );
318
g.inc_operator(subpixel_size );
319
b.inc_operator(subpixel_size );
320
a.inc_operator(subpixel_size );
322
dec(nlen ,subpixel_size );
323
dec(start ,subpixel_size );
324
inc(ptrcomp(span ) ,sizeof(aggclr ) );
329
// Middle part, no checking for overflow.
330
// Actual spans can be longer than the calculated length
331
// because of anti-aliasing, thus, the interpolators can
332
// overflow. But while "nlen" is positive we are safe.
333
while (len <> 0 ) and
336
span.r:=int8u(r._y );
337
span.g:=int8u(g._y );
338
span.b:=int8u(b._y );
339
span.a:=int8u(a._y );
341
r.inc_operator(subpixel_size );
342
g.inc_operator(subpixel_size );
343
b.inc_operator(subpixel_size );
344
a.inc_operator(subpixel_size );
346
dec(nlen ,subpixel_size );
347
inc(ptrcomp(span ) ,sizeof(aggclr ) );
352
// Ending part; checking for overflow.
353
// Typically it's 1-2 pixels, but may be more in some cases.
390
r.inc_operator(subpixel_size );
391
g.inc_operator(subpixel_size );
392
b.inc_operator(subpixel_size );
393
a.inc_operator(subpixel_size );
395
inc(ptrcomp(span ) ,sizeof(aggclr ) );
400
result:=_allocator.span;
405
constructor span_gouraud_rgba.Construct_(
406
c1 ,c2 ,c3 : aggclr_ptr;
407
x1 ,y1 ,x2 ,y2 ,x3 ,y3 : double;
410
inherited Construct(NIL ,c1 ,c2 ,c3 ,x1 ,y1 ,x2 ,y2 ,x3 ,y3 ,d );
415
procedure span_gouraud_rgba.prepare_;
417
coord : array[0..2 ] of coord_type;
420
arrange_vertices(@coord );
422
m_y2:=int(Trunc(coord[1 ].y ) );
426
coord[0 ].x ,coord[0 ].y,
427
coord[2 ].x ,coord[2 ].y,
428
coord[1 ].x ,coord[1 ].y ) < 0.0;
430
m_rgba1.init(@coord[0 ] ,@coord[2 ] );
431
m_rgba2.init(@coord[0 ] ,@coord[1 ] );
432
m_rgba3.init(@coord[1 ] ,@coord[2 ] );
437
procedure span_gouraud_rgba.generate_(span : aggclr_ptr; x ,y : int; len : unsigned );
439
lim = agg_color.base_mask;
442
pc1 ,pc2 ,t : rgba_calc_ptr;
444
nlen ,start ,vr ,vg ,vb ,va : int;
446
r ,g ,b ,a : dda_line_interpolator;
449
m_rgba1.calc(y ); //(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
455
// Bottom part of the triangle (first subtriangle)
456
m_rgba2.calc(y + m_rgba2.m_1dy )
459
// Upper part (second subtriangle)
460
m_rgba3.calc(y - m_rgba3.m_1dy );
468
// It means that the triangle is oriented clockwise,
469
// so that we need to swap the controlling structures
476
// Get the horizontal length with subpixel accuracy
477
// and protect it from division by zero
478
nlen:=Abs(pc2.m_x - pc1.m_x );
483
r.Construct(pc1.m_r ,pc2.m_r ,nlen ,14 );
484
g.Construct(pc1.m_g ,pc2.m_g ,nlen ,14 );
485
b.Construct(pc1.m_b ,pc2.m_b ,nlen ,14 );
486
a.Construct(pc1.m_a ,pc2.m_a ,nlen ,14 );
488
// Calculate the starting point of the gradient with subpixel
489
// accuracy and correct (roll back) the interpolators.
490
// This operation will also clip the beginning of the span
492
start:=pc1.m_x - (x shl subpixel_shift );
494
r.dec_operator(start );
495
g.dec_operator(start );
496
b.dec_operator(start );
497
a.dec_operator(start );
501
// Beginning part of the span. Since we rolled back the
502
// interpolators, the color values may have overflow.
503
// So that, we render the beginning part with checking
504
// for overflow. It lasts until "start" is positive;
505
// typically it's 1-2 pixels, but may be more in some cases.
506
while (len <> 0 ) and
543
r.inc_operator(subpixel_size );
544
g.inc_operator(subpixel_size );
545
b.inc_operator(subpixel_size );
546
a.inc_operator(subpixel_size );
548
dec(nlen ,subpixel_size );
549
dec(start ,subpixel_size );
550
inc(ptrcomp(span ) ,sizeof(aggclr ) );
555
// Middle part, no checking for overflow.
556
// Actual spans can be longer than the calculated length
557
// because of anti-aliasing, thus, the interpolators can
558
// overflow. But while "nlen" is positive we are safe.
559
while (len <> 0 ) and
562
span.r:=int8u(r._y );
563
span.g:=int8u(g._y );
564
span.b:=int8u(b._y );
565
span.a:=int8u(a._y );
567
r.inc_operator(subpixel_size );
568
g.inc_operator(subpixel_size );
569
b.inc_operator(subpixel_size );
570
a.inc_operator(subpixel_size );
572
dec(nlen ,subpixel_size );
573
inc(ptrcomp(span ) ,sizeof(aggclr ) );
578
// Ending part; checking for overflow.
579
// Typically it's 1-2 pixels, but may be more in some cases.
616
r.inc_operator(subpixel_size );
617
g.inc_operator(subpixel_size );
618
b.inc_operator(subpixel_size );
619
a.inc_operator(subpixel_size );
621
inc(ptrcomp(span ) ,sizeof(aggclr ) );