mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-01 09:25:05 +02:00
323 lines
6.4 KiB
ObjectPascal
323 lines
6.4 KiB
ObjectPascal
//
|
|
// AggPas 2.4 RM3 Demo application
|
|
// Note: Press F1 key on run to see more info about this demo
|
|
//
|
|
// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
|
|
//
|
|
program
|
|
gamma_correction ;
|
|
|
|
{$DEFINE AGG_BGR24 }
|
|
{DEFINE AGG_RGB24 }
|
|
{DEFINE AGG_RGB565 }
|
|
{DEFINE AGG_RGB555 }
|
|
|
|
uses
|
|
agg_basics ,
|
|
agg_platform_support ,
|
|
|
|
agg_ctrl ,
|
|
agg_slider_ctrl ,
|
|
|
|
agg_rasterizer_scanline_aa ,
|
|
agg_scanline ,
|
|
agg_scanline_u ,
|
|
|
|
agg_renderer_base ,
|
|
agg_renderer_scanline ,
|
|
agg_render_scanlines ,
|
|
|
|
agg_gamma_lut ,
|
|
agg_gamma_functions ,
|
|
agg_path_storage ,
|
|
agg_conv_stroke ,
|
|
agg_ellipse
|
|
|
|
{$I pixel_formats.inc }
|
|
{$I agg_mode.inc }
|
|
|
|
const
|
|
flip_y = true;
|
|
|
|
type
|
|
the_application = object(platform_support )
|
|
m_thickness ,
|
|
m_gamma ,
|
|
m_contrast : slider_ctrl;
|
|
|
|
m_rx ,
|
|
m_ry : double;
|
|
|
|
constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
|
|
destructor Destruct;
|
|
|
|
procedure on_init; virtual;
|
|
procedure on_draw; virtual;
|
|
|
|
procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
|
|
procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
|
|
|
|
procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
|
|
|
|
end;
|
|
|
|
{ CONSTRUCT }
|
|
constructor the_application.Construct;
|
|
begin
|
|
inherited Construct(format_ ,flip_y_ );
|
|
|
|
m_thickness.Construct(5 ,5 ,400 - 5 ,11 ,not flip_y_ );
|
|
m_gamma.Construct (5 ,5 + 15 ,400 - 5 ,11 + 15 ,not flip_y_ );
|
|
m_contrast.Construct (5 ,5 + 30 ,400 - 5 ,11 + 30 ,not flip_y_ );
|
|
|
|
add_ctrl(@m_thickness );
|
|
add_ctrl(@m_gamma );
|
|
add_ctrl(@m_contrast );
|
|
|
|
m_thickness.label_('Thickness=%3.2f' );
|
|
m_gamma.label_ ('Gamma=%3.2f' );
|
|
m_contrast.label_ ('Contrast' );
|
|
|
|
m_thickness.range_(0.0 ,3.0 );
|
|
m_gamma.range_ (0.5 ,3.0 );
|
|
m_contrast.range_ (0.0 ,1.0 );
|
|
|
|
m_thickness.value_(1.0 );
|
|
m_gamma.value_ (1.0 );
|
|
m_contrast.value_ (1.0 );
|
|
|
|
end;
|
|
|
|
{ DESTRUCT }
|
|
destructor the_application.Destruct;
|
|
begin
|
|
inherited Destruct;
|
|
|
|
m_thickness.Destruct;
|
|
m_gamma.Destruct;
|
|
m_contrast.Destruct;
|
|
|
|
end;
|
|
|
|
{ ON_INIT }
|
|
procedure the_application.on_init;
|
|
begin
|
|
m_rx:=_width / 3.0;
|
|
m_ry:=_height / 3.0;
|
|
|
|
end;
|
|
|
|
{ ON_DRAW }
|
|
procedure the_application.on_draw;
|
|
var
|
|
g ,dark ,light ,x ,y ,v ,gval ,dy : double;
|
|
|
|
i : unsigned;
|
|
|
|
gamma : gamma_lut;
|
|
pixf : pixel_formats;
|
|
|
|
renb : renderer_base;
|
|
ren : renderer_scanline_aa_solid;
|
|
|
|
ras : rasterizer_scanline_aa;
|
|
sl : scanline_u8;
|
|
|
|
rgba : aggclr;
|
|
path : path_storage;
|
|
|
|
gm_pw : gamma_power;
|
|
gpoly ,
|
|
poly : conv_stroke;
|
|
ell : ellipse;
|
|
|
|
begin
|
|
// Initialize structures
|
|
g:=m_gamma._value;
|
|
|
|
gamma.Construct(g );
|
|
|
|
pixfmt_gamma(pixf ,rbuf_window ,@gamma );
|
|
|
|
renb.Construct(@pixf );
|
|
ren.Construct (@renb );
|
|
|
|
rgba.ConstrDbl(1 ,1 ,1 );
|
|
renb.clear (@rgba );
|
|
|
|
dark :=1.0 - m_contrast._value;
|
|
light:=m_contrast._value;
|
|
|
|
rgba.ConstrDbl(dark ,dark ,dark );
|
|
renb.copy_bar (0 ,0 ,trunc(_width ) div 2 ,trunc(_height ) ,@rgba );
|
|
|
|
rgba.ConstrDbl(light ,light ,light );
|
|
renb.copy_bar (trunc(_width ) div 2 + 1 ,0 ,trunc(_width ) ,trunc(_height ) ,@rgba );
|
|
|
|
rgba.ConstrDbl(1.0 ,dark ,dark );
|
|
renb.copy_bar (0 ,trunc(_height ) div 2 + 1 ,trunc(_width ) ,trunc(_height ) ,@rgba );
|
|
|
|
ras.Construct;
|
|
sl.Construct;
|
|
|
|
// Graph line
|
|
path.Construct;
|
|
|
|
x:=(_width - 256.0 ) / 2.0;
|
|
y:=50.0;
|
|
|
|
for i:=0 to 255 do
|
|
begin
|
|
v:=i / 255.0;
|
|
|
|
gm_pw.Construct(g );
|
|
|
|
gval:=gm_pw.func_operator_gamma(v );
|
|
dy :=gval * 255.0;
|
|
|
|
if i = 0 then
|
|
path.move_to(x + i ,y + dy )
|
|
else
|
|
path.line_to(x + i ,y + dy );
|
|
|
|
end;
|
|
|
|
gpoly.Construct(@path );
|
|
gpoly.width_ (2.0 );
|
|
|
|
ras.reset;
|
|
ras.add_path(@gpoly );
|
|
|
|
rgba.ConstrInt(80 ,127 ,80 );
|
|
ren.color_ (@rgba );
|
|
|
|
render_scanlines(@ras ,@sl ,@ren );
|
|
|
|
// Ellipses
|
|
ell.Construct (_width / 2 ,_height / 2 ,m_rx ,m_ry ,150 );
|
|
poly.Construct(@ell );
|
|
poly.width_ (m_thickness._value );
|
|
|
|
ras.reset;
|
|
ras.add_path(@poly );
|
|
|
|
rgba.ConstrInt(255 ,0 ,0 );
|
|
ren.color_ (@rgba );
|
|
|
|
render_scanlines(@ras ,@sl ,@ren );
|
|
|
|
|
|
ell.init(_width / 2 ,_height / 2 ,m_rx - 5.0 ,m_ry - 5.0 ,150 );
|
|
|
|
ras.reset;
|
|
ras.add_path(@poly );
|
|
|
|
rgba.ConstrInt(0 ,255 ,0 );
|
|
ren.color_ (@rgba );
|
|
|
|
render_scanlines(@ras ,@sl ,@ren );
|
|
|
|
|
|
ell.init(_width / 2 ,_height / 2 ,m_rx - 10.0 ,m_ry - 10.0 ,150 );
|
|
|
|
ras.reset;
|
|
ras.add_path(@poly );
|
|
|
|
rgba.ConstrInt(0 ,0 ,255 );
|
|
ren.color_ (@rgba );
|
|
|
|
render_scanlines(@ras ,@sl ,@ren );
|
|
|
|
|
|
ell.init(_width / 2 ,_height / 2 ,m_rx - 15.0 ,m_ry - 15.0 ,150 );
|
|
|
|
ras.reset;
|
|
ras.add_path(@poly );
|
|
|
|
rgba.ConstrInt(0 ,0 ,0 );
|
|
ren.color_ (@rgba );
|
|
|
|
render_scanlines(@ras ,@sl ,@ren );
|
|
|
|
|
|
ell.init(_width / 2 ,_height / 2 ,m_rx - 20.0 ,m_ry - 20.0 ,150 );
|
|
|
|
ras.reset;
|
|
ras.add_path(@poly );
|
|
|
|
rgba.ConstrInt(255 ,255 ,255 );
|
|
ren.color_ (@rgba );
|
|
|
|
render_scanlines(@ras ,@sl ,@ren );
|
|
|
|
// Render the controls
|
|
render_ctrl(@ras ,@sl ,@ren ,@m_thickness );
|
|
render_ctrl(@ras ,@sl ,@ren ,@m_gamma );
|
|
render_ctrl(@ras ,@sl ,@ren ,@m_contrast );
|
|
|
|
// Free AGG resources
|
|
ras.Destruct;
|
|
sl.Destruct;
|
|
path.Destruct;
|
|
|
|
gamma.Destruct;
|
|
gpoly.Destruct;
|
|
poly.Destruct;
|
|
|
|
end;
|
|
|
|
{ ON_MOUSE_MOVE }
|
|
procedure the_application.on_mouse_move;
|
|
begin
|
|
on_mouse_button_down(x ,y ,flags );
|
|
|
|
end;
|
|
|
|
{ ON_MOUSE_BUTTON_DOWN }
|
|
procedure the_application.on_mouse_button_down;
|
|
begin
|
|
if flags and mouse_left <> 0 then
|
|
begin
|
|
m_rx:=Abs(_width / 2 - x );
|
|
m_ry:=Abs(_height / 2 - y );
|
|
|
|
force_redraw;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
{ ON_KEY }
|
|
procedure the_application.on_key;
|
|
begin
|
|
if key = key_f1 then
|
|
message_(
|
|
'Anti-Aliasing is very tricky because everything depends. Particularly, having '#13 +
|
|
'straight linear dependence "pixel coverage" -> "brightness" may be not the best. '#13 +
|
|
'It depends on the type of display (CRT, LCD), contrast, black-on-white vs '#13 +
|
|
'white-on-black, it even depends on your personal vision. There are no linear '#13 +
|
|
'dependencies in this World. This example demonstrates the importance of so called '#13 +
|
|
'Gamma Correction in Anti-Aliasing. There a traditional power function is used, '#13 +
|
|
'in terms of C++ it''s brighness = pow(brighness, gamma). Note, that if you improve '#13 +
|
|
'the quality on the white side, it becomes worse on the black side and vice versa.'#13 +
|
|
#13#13 +
|
|
'How to play with:'#13#13 +
|
|
'Change "Gamma" and see how the quality changes.'#13 +
|
|
'Use the left mouse button to resize the circles.' +
|
|
#13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
|
|
|
|
end;
|
|
|
|
VAR
|
|
app : the_application;
|
|
|
|
BEGIN
|
|
app.Construct(pix_format ,flip_y );
|
|
app.caption_ ('AGG Example. Thin red ellipse (F1-Help)' );
|
|
|
|
if app.init(400 ,320 ,0 ) then
|
|
app.run;
|
|
|
|
app.Destruct;
|
|
|
|
END. |