mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 01:19:47 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			541 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			541 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{target:win}
 | 
						|
//
 | 
						|
// 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
 | 
						|
 trans_curve2 ;
 | 
						|
 | 
						|
{DEFINE AGG_GRAY8 }
 | 
						|
{$DEFINE AGG_BGR24 }
 | 
						|
{DEFINE AGG_RGB24 }
 | 
						|
{DEFINE AGG_BGRA32 }
 | 
						|
{DEFINE AGG_RGBA32 }
 | 
						|
{DEFINE AGG_ARGB32 }
 | 
						|
{DEFINE AGG_ABGR32 }
 | 
						|
{DEFINE AGG_RGB565 }
 | 
						|
{DEFINE AGG_RGB555 }
 | 
						|
 | 
						|
uses
 | 
						|
 Windows ,
 | 
						|
 | 
						|
 agg_basics ,
 | 
						|
 agg_platform_support ,
 | 
						|
 
 | 
						|
 agg_ctrl ,
 | 
						|
 agg_cbox_ctrl ,
 | 
						|
 agg_slider_ctrl ,
 | 
						|
 | 
						|
 agg_rasterizer_scanline_aa ,
 | 
						|
 agg_scanline ,
 | 
						|
 agg_scanline_p ,
 | 
						|
 | 
						|
 agg_rendering_buffer ,
 | 
						|
 agg_renderer_base ,
 | 
						|
 agg_renderer_scanline ,
 | 
						|
 agg_render_scanlines ,
 | 
						|
 | 
						|
 agg_math ,
 | 
						|
 agg_conv_curve ,
 | 
						|
 agg_conv_transform ,
 | 
						|
 agg_trans_double_path ,
 | 
						|
 agg_conv_bspline ,
 | 
						|
 agg_conv_segmentator ,
 | 
						|
 agg_conv_stroke ,
 | 
						|
 agg_font_win32_tt ,
 | 
						|
 agg_font_cache_manager ,
 | 
						|
 interactive_polygon_ 
 | 
						|
 | 
						|
{$I pixel_formats.inc }
 | 
						|
{$I agg_mode.inc }
 | 
						|
 | 
						|
const
 | 
						|
 flip_y = true;
 | 
						|
 | 
						|
 text_ : PChar =
 | 
						|
  'Anti-Grain Geometry is designed as a set of loosely coupled ' +
 | 
						|
  'algorithms and class templates united with a common idea, ' +
 | 
						|
  'so that all the components can be easily combined. Also, ' +
 | 
						|
  'the template based design allows you to replace any part of ' +
 | 
						|
  'the library without the necessity to modify a single byte in ' +
 | 
						|
  'the existing code. ';
 | 
						|
 | 
						|
type
 | 
						|
 the_application = object(platform_support )
 | 
						|
   m_feng  : font_engine_win32_tt_int16;
 | 
						|
   m_fman  : font_cache_manager;
 | 
						|
   m_poly1 ,
 | 
						|
   m_poly2 : interactive_polygon;
 | 
						|
 | 
						|
   m_num_points       : slider_ctrl;
 | 
						|
   m_fixed_len        ,
 | 
						|
   m_preserve_x_scale ,
 | 
						|
   m_animate          : cbox_ctrl;
 | 
						|
 | 
						|
   m_dx1 ,
 | 
						|
   m_dy1 ,
 | 
						|
   m_dx2 ,
 | 
						|
   m_dy2 : array[0..5 ] of double;
 | 
						|
 | 
						|
   m_prev_animate : boolean;
 | 
						|
 | 
						|
   constructor Construct(dc : HDC; 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_mouse_button_up  (x ,y : int; flags : unsigned ); virtual;
 | 
						|
 | 
						|
   procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
 | 
						|
   procedure on_ctrl_change; virtual;
 | 
						|
 | 
						|
   procedure move_point     (x ,y ,dx ,dy : double_ptr );
 | 
						|
   procedure normalize_point(i : unsigned );
 | 
						|
 | 
						|
   procedure on_idle; virtual;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
{ CONSTRUCT }
 | 
						|
constructor the_application.Construct;
 | 
						|
begin
 | 
						|
 inherited Construct(format_ ,flip_y_ );
 | 
						|
 | 
						|
 m_feng.Construct (dc );
 | 
						|
 m_fman.Construct (@m_feng );
 | 
						|
 m_poly1.Construct(6 ,5.0 );
 | 
						|
 m_poly2.Construct(6 ,5.0 );
 | 
						|
 | 
						|
 m_num_points.Construct      (5.0 ,5.0  ,340.0 ,12.0 ,not flip_y_ );
 | 
						|
 m_fixed_len.Construct       (350 ,5.0  ,'Fixed Length' ,not flip_y_ );
 | 
						|
 m_preserve_x_scale.Construct(465 ,5.0  ,'Preserve X scale' ,not flip_y_ );
 | 
						|
 m_animate.Construct         (350 ,25.0 ,'Animate' ,not flip_y_ );
 | 
						|
 | 
						|
 m_prev_animate:=false;
 | 
						|
 | 
						|
 add_ctrl(@m_fixed_len );
 | 
						|
 add_ctrl(@m_preserve_x_scale );
 | 
						|
 add_ctrl(@m_animate );
 | 
						|
 | 
						|
 m_fixed_len.status_       (true );
 | 
						|
 m_preserve_x_scale.status_(true );
 | 
						|
 | 
						|
 m_num_points.range_(10.0 ,400.0 );
 | 
						|
 m_num_points.value_(200.0 );
 | 
						|
 m_num_points.label_('Number of intermediate Points = %.3f' );
 | 
						|
 | 
						|
 add_ctrl(@m_num_points );
 | 
						|
 | 
						|
 m_poly1.close_(false );
 | 
						|
 m_poly2.close_(false );
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ DESTRUCT }
 | 
						|
destructor the_application.Destruct;
 | 
						|
begin
 | 
						|
 inherited Destruct;
 | 
						|
 | 
						|
 m_num_points.Destruct;
 | 
						|
 m_fixed_len.Destruct;
 | 
						|
 m_preserve_x_scale.Destruct;
 | 
						|
 m_animate.Destruct;
 | 
						|
 | 
						|
 m_poly1.Destruct;
 | 
						|
 m_poly2.Destruct;
 | 
						|
 | 
						|
 m_feng.Destruct;
 | 
						|
 m_fman.Destruct;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_INIT }
 | 
						|
procedure the_application.on_init;
 | 
						|
begin
 | 
						|
 m_poly1.xn_ptr(0 )^:= 10 + 50;
 | 
						|
 m_poly1.yn_ptr(0 )^:=-10 + 50;
 | 
						|
 m_poly1.xn_ptr(1 )^:= 10 + 150 + 20;
 | 
						|
 m_poly1.yn_ptr(1 )^:=-10 + 150 - 20;
 | 
						|
 m_poly1.xn_ptr(2 )^:= 10 + 250 - 20;
 | 
						|
 m_poly1.yn_ptr(2 )^:=-10 + 250 + 20;
 | 
						|
 m_poly1.xn_ptr(3 )^:= 10 + 350 + 20;
 | 
						|
 m_poly1.yn_ptr(3 )^:=-10 + 350 - 20;
 | 
						|
 m_poly1.xn_ptr(4 )^:= 10 + 450 - 20;
 | 
						|
 m_poly1.yn_ptr(4 )^:=-10 + 450 + 20;
 | 
						|
 m_poly1.xn_ptr(5 )^:= 10 + 550;
 | 
						|
 m_poly1.yn_ptr(5 )^:=-10 + 550;
 | 
						|
 | 
						|
 m_poly2.xn_ptr(0 )^:=-10 + 50;
 | 
						|
 m_poly2.yn_ptr(0 )^:= 10 + 50;
 | 
						|
 m_poly2.xn_ptr(1 )^:=-10 + 150 + 20;
 | 
						|
 m_poly2.yn_ptr(1 )^:= 10 + 150 - 20;
 | 
						|
 m_poly2.xn_ptr(2 )^:=-10 + 250 - 20;
 | 
						|
 m_poly2.yn_ptr(2 )^:= 10 + 250 + 20;
 | 
						|
 m_poly2.xn_ptr(3 )^:=-10 + 350 + 20;
 | 
						|
 m_poly2.yn_ptr(3 )^:= 10 + 350 - 20;
 | 
						|
 m_poly2.xn_ptr(4 )^:=-10 + 450 - 20;
 | 
						|
 m_poly2.yn_ptr(4 )^:= 10 + 450 + 20;
 | 
						|
 m_poly2.xn_ptr(5 )^:=-10 + 550;
 | 
						|
 m_poly2.yn_ptr(5 )^:= 10 + 550;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_DRAW }
 | 
						|
procedure the_application.on_draw;
 | 
						|
var
 | 
						|
 pixf : pixel_formats;
 | 
						|
 rgba : aggclr;
 | 
						|
 | 
						|
 rb : renderer_base;
 | 
						|
 r  : renderer_scanline_aa_solid;
 | 
						|
 sl : scanline_p8;
 | 
						|
 | 
						|
 ras : rasterizer_scanline_aa;
 | 
						|
 | 
						|
 path1 ,
 | 
						|
 path2 : simple_polygon_vertex_source;
 | 
						|
 | 
						|
 bspline1 ,
 | 
						|
 bspline2 : conv_bspline;
 | 
						|
 | 
						|
 tcurve  : trans_double_path;
 | 
						|
 fcurves : conv_curve;
 | 
						|
 fsegm   : conv_segmentator;
 | 
						|
 ftrans  : conv_transform;
 | 
						|
 | 
						|
 x ,y : double;
 | 
						|
 | 
						|
 p : int8u_ptr;
 | 
						|
 | 
						|
 glyph : glyph_cache_ptr;
 | 
						|
 
 | 
						|
 stroke1 ,
 | 
						|
 stroke2 : conv_stroke;
 | 
						|
 | 
						|
begin
 | 
						|
// Initialize structures
 | 
						|
 pixfmt(pixf ,rbuf_window );
 | 
						|
 | 
						|
 rb.Construct(@pixf );
 | 
						|
 r.Construct (@rb );
 | 
						|
 | 
						|
 rgba.ConstrDbl(1 ,1 ,1 );
 | 
						|
 rb.clear      (@rgba );
 | 
						|
 | 
						|
 sl.Construct;
 | 
						|
 ras.Construct;
 | 
						|
 | 
						|
// Render the text
 | 
						|
 path1.Construct(m_poly1.polygon ,m_poly1.num_points ,false ,false );
 | 
						|
 path2.Construct(m_poly2.polygon ,m_poly2.num_points ,false ,false );
 | 
						|
 | 
						|
 bspline1.Construct(@path1 );
 | 
						|
 bspline2.Construct(@path2 );
 | 
						|
 | 
						|
 bspline1.interpolation_step_(1.0 / m_num_points._value );
 | 
						|
 bspline2.interpolation_step_(1.0 / m_num_points._value );
 | 
						|
 | 
						|
 tcurve.Construct;
 | 
						|
 fcurves.Construct(m_fman.path_adaptor );
 | 
						|
 fsegm.Construct  (@fcurves);
 | 
						|
 ftrans.Construct (@fsegm ,@tcurve );
 | 
						|
 | 
						|
 tcurve.preserve_x_scale_(m_preserve_x_scale._status );
 | 
						|
 | 
						|
 if m_fixed_len._status then
 | 
						|
  tcurve.base_length_(1140.0 );
 | 
						|
 | 
						|
 tcurve.base_height_(30.0 );
 | 
						|
 tcurve.add_paths   (@bspline1 ,@bspline2 );
 | 
						|
 | 
						|
 fsegm.approximation_scale_  (3.0 );
 | 
						|
 fcurves.approximation_scale_(5.0 );
 | 
						|
 | 
						|
 m_feng.height_ (40.0 );
 | 
						|
 m_feng.hinting_(false );
 | 
						|
 m_feng.italic_ (true );
 | 
						|
 | 
						|
 if m_feng.create_font('Times New Roman' ,glyph_ren_outline ) then
 | 
						|
  begin
 | 
						|
   x:=0.0;
 | 
						|
   y:=3.0;
 | 
						|
   p:=@text_[0 ];
 | 
						|
 | 
						|
   while p^ <> 0 do
 | 
						|
    begin
 | 
						|
     glyph:=m_fman.glyph(p^ );
 | 
						|
 | 
						|
     if glyph <> NIL then
 | 
						|
      begin
 | 
						|
       if x > tcurve.total_length1 then
 | 
						|
        break;
 | 
						|
 | 
						|
       m_fman.add_kerning           (@x ,@y );
 | 
						|
       m_fman.init_embedded_adaptors(glyph ,x ,y );
 | 
						|
 | 
						|
       if glyph.data_type = glyph_data_outline then
 | 
						|
        begin
 | 
						|
         ras.reset;
 | 
						|
         ras.add_path(@ftrans );
 | 
						|
 | 
						|
         rgba.ConstrInt(0 ,0 ,0 );
 | 
						|
         r.color_      (@rgba );
 | 
						|
 | 
						|
         render_scanlines(@ras ,@sl ,@r );
 | 
						|
 | 
						|
        end;
 | 
						|
 | 
						|
      // increment pen position
 | 
						|
       x:=x + glyph.advance_x;
 | 
						|
       y:=y + glyph.advance_y;
 | 
						|
 | 
						|
      end;
 | 
						|
 | 
						|
     inc(ptrcomp(p ) ,sizeof(int8u ) );
 | 
						|
 | 
						|
    end;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
// Render the path curve
 | 
						|
 stroke1.Construct(@bspline1 );
 | 
						|
 stroke2.Construct(@bspline2 );
 | 
						|
 | 
						|
 stroke1.width_(2.0 );
 | 
						|
 stroke2.width_(2.0 );
 | 
						|
 | 
						|
 rgba.ConstrInt(170 ,50 ,20 ,100 );
 | 
						|
 r.color_      (@rgba );
 | 
						|
 | 
						|
 ras.add_path    (@stroke1 );
 | 
						|
 render_scanlines(@ras ,@sl ,@r );
 | 
						|
 | 
						|
 ras.add_path    (@stroke2);
 | 
						|
 render_scanlines(@ras ,@sl ,@r );
 | 
						|
 | 
						|
// Render the "poly" tool
 | 
						|
 rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.2 );
 | 
						|
 r.color_      (@rgba );
 | 
						|
 | 
						|
 ras.add_path    (@m_poly1 );
 | 
						|
 render_scanlines(@ras ,@sl ,@r );
 | 
						|
 | 
						|
 ras.add_path    (@m_poly2 );
 | 
						|
 render_scanlines(@ras ,@sl ,@r );
 | 
						|
 | 
						|
// Render the controls
 | 
						|
 render_ctrl(@ras ,@sl ,@r ,@m_fixed_len );
 | 
						|
 render_ctrl(@ras ,@sl ,@r ,@m_preserve_x_scale );
 | 
						|
 render_ctrl(@ras ,@sl ,@r ,@m_animate );
 | 
						|
 render_ctrl(@ras ,@sl ,@r ,@m_num_points );
 | 
						|
 | 
						|
// Free AGG resources
 | 
						|
 sl.Destruct;
 | 
						|
 ras.Destruct;
 | 
						|
 | 
						|
 bspline1.Destruct;
 | 
						|
 bspline2.Destruct;
 | 
						|
 tcurve.Destruct;
 | 
						|
 fcurves.Destruct;
 | 
						|
 fsegm.Destruct;
 | 
						|
 | 
						|
 stroke1.Destruct;
 | 
						|
 stroke2.Destruct;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_MOUSE_MOVE }
 | 
						|
procedure the_application.on_mouse_move;
 | 
						|
begin
 | 
						|
 if flags and mouse_left <> 0 then
 | 
						|
  begin
 | 
						|
   if m_poly1.on_mouse_move(x ,y ) then
 | 
						|
    force_redraw;
 | 
						|
 | 
						|
   if m_poly2.on_mouse_move(x ,y ) then
 | 
						|
    force_redraw;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
 if flags and mouse_left = 0 then
 | 
						|
  on_mouse_button_up(x ,y ,flags );
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_MOUSE_BUTTON_DOWN }
 | 
						|
procedure the_application.on_mouse_button_down;
 | 
						|
begin
 | 
						|
 if flags and mouse_left <> 0 then
 | 
						|
  begin
 | 
						|
   if m_poly1.on_mouse_button_down(x ,y ) then
 | 
						|
    force_redraw;
 | 
						|
 | 
						|
   if m_poly2.on_mouse_button_down(x ,y ) then
 | 
						|
    force_redraw;
 | 
						|
 | 
						|
  end;
 | 
						|
  
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_MOUSE_BUTTON_UP }
 | 
						|
procedure the_application.on_mouse_button_up;
 | 
						|
begin
 | 
						|
 if m_poly1.on_mouse_button_up(x ,y ) then
 | 
						|
  force_redraw;
 | 
						|
 | 
						|
 if m_poly2.on_mouse_button_up(x ,y ) then
 | 
						|
  force_redraw;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_KEY }
 | 
						|
procedure the_application.on_key;
 | 
						|
begin
 | 
						|
 if key = key_f1 then
 | 
						|
  message_(
 | 
						|
   'Similar to the "trans_curve1" demo, but here the transformer operates with two '#13 +
 | 
						|
   'arbitrary curves. It requires more calculations, but gives you more freedom. '#13 +
 | 
						|
   'In other words you will see :-).' +
 | 
						|
   #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory.  ' );
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_CTRL_CHANGE }
 | 
						|
procedure the_application.on_ctrl_change;
 | 
						|
var
 | 
						|
 i : int;
 | 
						|
 | 
						|
begin
 | 
						|
 if m_animate._status <> m_prev_animate then
 | 
						|
  begin
 | 
						|
   if m_animate._status then
 | 
						|
    begin
 | 
						|
     on_init;
 | 
						|
 | 
						|
     for i:=0 to 5 do
 | 
						|
      begin
 | 
						|
       m_dx1[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
 | 
						|
       m_dy1[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
 | 
						|
       m_dx2[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
 | 
						|
       m_dy2[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01;
 | 
						|
 | 
						|
      end;
 | 
						|
 | 
						|
     wait_mode_(false );
 | 
						|
 | 
						|
    end
 | 
						|
   else
 | 
						|
    wait_mode_(true );
 | 
						|
 | 
						|
   m_prev_animate:=m_animate._status;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ MOVE_POINT }
 | 
						|
procedure the_application.move_point;
 | 
						|
begin
 | 
						|
 if x^ < 0.0 then
 | 
						|
  begin
 | 
						|
   x^ :=0.0;
 | 
						|
   dx^:=-dx^;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
 if x^ > _width then
 | 
						|
  begin
 | 
						|
   x^ :=_width;
 | 
						|
   dx^:=-dx^;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
 if y^ < 0.0 then
 | 
						|
  begin
 | 
						|
   y^ :=0.0;
 | 
						|
   dy^:=-dy^;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
 if y^ > _height then
 | 
						|
  begin
 | 
						|
   y^ :=_height;
 | 
						|
   dy^:=-dy^;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
 x^:=x^ + dx^;
 | 
						|
 y^:=y^ + dy^;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ NORMALIZE_POINT }
 | 
						|
procedure the_application.normalize_point;
 | 
						|
var
 | 
						|
 d : double;
 | 
						|
 | 
						|
begin
 | 
						|
 d:=
 | 
						|
  calc_distance(
 | 
						|
   m_poly1.xn_ptr(i )^ ,m_poly1.yn_ptr(i )^ ,
 | 
						|
   m_poly2.xn_ptr(i )^ ,m_poly2.yn_ptr(i )^ );
 | 
						|
 | 
						|
// 28.8 is 20 * sqrt(2)
 | 
						|
 if d > 28.28 then
 | 
						|
  begin
 | 
						|
   m_poly2.xn_ptr(i )^:=
 | 
						|
    m_poly1.xn_ptr(i )^ +
 | 
						|
    (m_poly2.xn_ptr(i )^ -
 | 
						|
     m_poly1.xn_ptr(i )^ ) * 28.28 / d;
 | 
						|
 | 
						|
   m_poly2.yn_ptr(i )^:=
 | 
						|
    m_poly1.yn_ptr(i )^ +
 | 
						|
    (m_poly2.yn_ptr(i )^ -
 | 
						|
     m_poly1.yn_ptr(i )^ ) * 28.28 / d;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_IDLE }
 | 
						|
procedure the_application.on_idle;
 | 
						|
var
 | 
						|
 i : int;
 | 
						|
 | 
						|
begin
 | 
						|
 for i:=0 to 5 do
 | 
						|
  begin
 | 
						|
   move_point(m_poly1.xn_ptr(i ) ,m_poly1.yn_ptr(i ) ,@m_dx1[i ] ,@m_dy1[i ] );
 | 
						|
   move_point(m_poly2.xn_ptr(i ) ,m_poly2.yn_ptr(i ) ,@m_dx2[i ] ,@m_dy2[i ] );
 | 
						|
 | 
						|
   normalize_point(i);
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
 force_redraw;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
VAR
 | 
						|
 app : the_application;
 | 
						|
 dc  : HDC;
 | 
						|
 | 
						|
BEGIN
 | 
						|
 dc:=GetDC(0 );
 | 
						|
 | 
						|
 app.Construct(dc ,pix_format ,flip_y );
 | 
						|
 app.caption_ ('AGG Example. Non-linear "Along-A-Curve" Transformer - Win32 (F1-Help)' );
 | 
						|
 | 
						|
 if app.init(600 ,600 ,window_resize ) then
 | 
						|
  app.run;
 | 
						|
 | 
						|
 app.Destruct;
 | 
						|
 | 
						|
 ReleaseDC(0 ,dc );
 | 
						|
 | 
						|
END. |