mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-10 00:52:42 +02:00
335 lines
6.5 KiB
ObjectPascal
335 lines
6.5 KiB
ObjectPascal
//----------------------------------------------------------------------------
|
|
// Anti-Grain Geometry - Version 2.4 (Public License)
|
|
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
|
//
|
|
// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
|
|
// Pascal Port By: Milan Marusinec alias Milano
|
|
// milan@marusinec.sk
|
|
// http://www.aggpas.org
|
|
// Copyright (c) 2005-2007
|
|
//
|
|
// Permission to copy, use, modify, sell and distribute this software
|
|
// is granted provided this copyright notice appears in all copies.
|
|
// This software is provided "as is" without express or implied
|
|
// warranty, and with no claim as to its suitability for any purpose.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
// Contact: mcseem@antigrain.com
|
|
// mcseemagg@yahoo.com
|
|
// http://www.antigrain.com
|
|
//
|
|
// [Pascal Port History] -----------------------------------------------------
|
|
//
|
|
// 12.10.2007-Milano: Unit port establishment
|
|
//
|
|
{ agg_gradient_lut.pas }
|
|
unit
|
|
agg_gradient_lut ;
|
|
|
|
INTERFACE
|
|
|
|
{$I agg_mode.inc }
|
|
|
|
uses
|
|
agg_basics ,
|
|
agg_array ,
|
|
agg_dda_line ,
|
|
agg_color ;
|
|
|
|
{ TYPES DEFINITION }
|
|
type
|
|
gradient_lut_ptr = ^gradient_lut;
|
|
gradient_lut = object(array_base )
|
|
private
|
|
m_color_lut_size : unsigned;
|
|
m_color_profile : pod_bvector;
|
|
m_color_lut : pod_array;
|
|
|
|
public
|
|
constructor Construct(size_ : unsigned = 256 );
|
|
destructor Destruct;
|
|
|
|
// Build Gradient Lut
|
|
// First, call remove_all(), then add_color() at least twice,
|
|
// then build_lut(). Argument "offset" in add_color must be
|
|
// in range [0...1] and defines a color stop as it is described
|
|
// in SVG specification, section Gradients and Patterns.
|
|
// The simplest linear gradient is:
|
|
// gradient_lut.add_color(0.0, start_color);
|
|
// gradient_lut.add_color(1.0, end_color);
|
|
procedure remove_all;
|
|
procedure add_color(offset : double; color : aggclr_ptr );
|
|
procedure build_lut;
|
|
|
|
// Size-index Interface. This class can be used directly as the
|
|
// ColorF in span_gradient. All it needs is two access methods
|
|
// size() and operator [].
|
|
function size : unsigned; virtual;
|
|
function entry : unsigned; virtual;
|
|
function array_operator(i : unsigned ) : pointer; virtual;
|
|
|
|
end;
|
|
|
|
{ GLOBAL VARIABLES & CONSTANTS }
|
|
{ GLOBAL PROCEDURES }
|
|
|
|
|
|
IMPLEMENTATION
|
|
{ LOCAL VARIABLES & CONSTANTS }
|
|
type
|
|
color_point_ptr = ^color_point;
|
|
color_point = object
|
|
offset : double;
|
|
color : aggclr;
|
|
|
|
constructor Construct; overload;
|
|
constructor Construct(off : double; c : aggclr_ptr ); overload;
|
|
|
|
end;
|
|
|
|
color_interpolator = object
|
|
m_c1 ,
|
|
m_c2 : aggclr;
|
|
|
|
m_len ,
|
|
m_count : unsigned;
|
|
|
|
v ,r ,g ,b ,a : dda_line_interpolator;
|
|
|
|
m_is_gray : boolean;
|
|
|
|
constructor Construct(c1 ,c2 : aggclr_ptr; len : unsigned; is_gray : boolean = false );
|
|
|
|
procedure operator_inc;
|
|
|
|
function color : aggclr;
|
|
|
|
end;
|
|
|
|
{ UNIT IMPLEMENTATION }
|
|
{ CONSTRUCT }
|
|
constructor color_point.Construct;
|
|
begin
|
|
offset:=0;
|
|
|
|
color.Construct;
|
|
|
|
end;
|
|
|
|
{ CONSTRUCT }
|
|
constructor color_point.Construct(off : double; c : aggclr_ptr );
|
|
begin
|
|
offset:=off;
|
|
|
|
color.Construct(c );
|
|
|
|
if offset < 0.0 then
|
|
offset:=0.0;
|
|
|
|
if offset > 1.0 then
|
|
offset:=1.0;
|
|
|
|
end;
|
|
|
|
{ CONSTRUCT }
|
|
constructor color_interpolator.Construct(c1 ,c2 : aggclr_ptr; len : unsigned; is_gray : boolean = false );
|
|
begin
|
|
m_c1.Construct(c1 );
|
|
m_c2.Construct(c2 );
|
|
|
|
m_len :=len;
|
|
m_count:=0;
|
|
|
|
m_is_gray:=is_gray;
|
|
|
|
if m_is_gray then
|
|
v.Construct(c1.v ,c2.v ,len ,14 )
|
|
|
|
else
|
|
begin
|
|
r.Construct(c1.r ,c2.r ,len ,14 );
|
|
g.Construct(c1.g ,c2.g ,len ,14 );
|
|
b.Construct(c1.b ,c2.b ,len ,14 );
|
|
|
|
end;
|
|
|
|
a.Construct(c1.a ,c2.a ,len ,14 );
|
|
|
|
end;
|
|
|
|
{ OPERATOR_INC }
|
|
procedure color_interpolator.operator_inc;
|
|
begin
|
|
inc(m_count );
|
|
|
|
if m_is_gray then
|
|
v.plus_operator
|
|
|
|
else
|
|
begin
|
|
r.plus_operator;
|
|
g.plus_operator;
|
|
b.plus_operator;
|
|
|
|
end;
|
|
|
|
a.plus_operator;
|
|
|
|
end;
|
|
|
|
{ COLOR }
|
|
function color_interpolator.color : aggclr;
|
|
begin
|
|
// result:=m_c1.gradient(@m_c2 ,m_count / m_len );
|
|
|
|
if m_is_gray then
|
|
result.ConstrInt(r._y ,a._y )
|
|
else
|
|
result.ConstrInt(r._y ,g._y ,b._y ,a._y )
|
|
|
|
end;
|
|
|
|
{ CONSTRUCT }
|
|
constructor gradient_lut.Construct(size_ : unsigned = 256 );
|
|
begin
|
|
m_color_lut_size:=size_;
|
|
|
|
m_color_profile.Construct(sizeof(color_point ) ,4 );
|
|
m_color_lut.Construct(sizeof(aggclr ) ,m_color_lut_size );
|
|
|
|
end;
|
|
|
|
{ DESTRUCT }
|
|
destructor gradient_lut.Destruct;
|
|
begin
|
|
m_color_profile.Destruct;
|
|
m_color_lut.Destruct;
|
|
|
|
end;
|
|
|
|
{ REMOVE_ALL }
|
|
procedure gradient_lut.remove_all;
|
|
begin
|
|
m_color_profile.remove_all;
|
|
|
|
end;
|
|
|
|
{ ADD_COLOR }
|
|
procedure gradient_lut.add_color(offset : double; color : aggclr_ptr );
|
|
var
|
|
cp : color_point;
|
|
|
|
begin
|
|
cp.Construct(offset ,color );
|
|
|
|
m_color_profile.add(@cp );
|
|
|
|
end;
|
|
|
|
{ offset_less }
|
|
function offset_less(a ,b : color_point_ptr ) : boolean;
|
|
begin
|
|
result:=a.offset < b.offset;
|
|
|
|
end;
|
|
|
|
{ offset_equal }
|
|
function offset_equal(a ,b : color_point_ptr ) : boolean;
|
|
begin
|
|
result:=a.offset = b.offset;
|
|
|
|
end;
|
|
|
|
{ BUILD_LUT }
|
|
procedure gradient_lut.build_lut;
|
|
var
|
|
i ,start ,end_ : unsigned;
|
|
|
|
c : aggclr;
|
|
|
|
ci : color_interpolator;
|
|
|
|
begin
|
|
quick_sort (@m_color_profile ,@offset_less );
|
|
m_color_profile.cut_at(remove_duplicates(@m_color_profile ,@offset_equal ) );
|
|
|
|
if m_color_profile.size >= 2 then
|
|
begin
|
|
start:=
|
|
uround(
|
|
color_point_ptr(m_color_profile.array_operator(0 ) ).offset * m_color_lut_size );
|
|
|
|
c:=color_point_ptr(m_color_profile.array_operator(0 ) ).color;
|
|
i:=0;
|
|
|
|
while i < start do
|
|
begin
|
|
aggclr_ptr(m_color_lut.array_operator(i ) )^:=c;
|
|
|
|
inc(i );
|
|
|
|
end;
|
|
|
|
i:=1;
|
|
|
|
while i < m_color_profile.size do
|
|
begin
|
|
end_:=uround(color_point_ptr(m_color_profile.array_operator(i ) ).offset * m_color_lut_size );
|
|
|
|
ci.Construct(
|
|
@color_point_ptr(m_color_profile.array_operator(i - 1 ) ).color ,
|
|
@color_point_ptr(m_color_profile.array_operator(i ) ).color ,
|
|
end_ - start + 1 );
|
|
|
|
while start < end_ do
|
|
begin
|
|
aggclr_ptr(m_color_lut.array_operator(start ) )^:=ci.color;
|
|
|
|
ci.operator_inc;
|
|
|
|
inc(start );
|
|
|
|
end;
|
|
|
|
inc(i );
|
|
|
|
end;
|
|
|
|
c:=color_point_ptr(m_color_profile.last ).color;
|
|
|
|
while end_ < m_color_lut.size do
|
|
begin
|
|
aggclr_ptr(m_color_lut.array_operator(end_ ) )^:=c;
|
|
|
|
inc(end_ );
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
{ SIZE }
|
|
function gradient_lut.size : unsigned;
|
|
begin
|
|
result:=m_color_lut_size;
|
|
|
|
end;
|
|
|
|
{ ENTRY }
|
|
function gradient_lut.entry : unsigned;
|
|
begin
|
|
result:=m_color_lut.m_entry_sz;
|
|
|
|
end;
|
|
|
|
{ ARRAY_OPERATOR }
|
|
function gradient_lut.array_operator(i : unsigned ) : pointer;
|
|
begin
|
|
result:=m_color_lut.array_operator(i );
|
|
|
|
end;
|
|
|
|
END.
|
|
|