//---------------------------------------------------------------------------- // 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-2006 // // 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] ----------------------------------------------------- // // 23.06.2006-Milano: ptrcomp adjustments // 15.02.2006-Milano: Unit port establishment // { agg_scanline_storage_aa.pas } unit agg_scanline_storage_aa ; INTERFACE {$I agg_mode.inc } {$Q- } {$R- } uses agg_basics , agg_array , agg_scanline , agg_renderer_scanline , agg_render_scanlines , agg_rasterizer_scanline_aa ; { TYPES DEFINITION } type //----------------------------------------------scanline_cell_storage extra_span_ptr = ^extra_span; extra_span = record len : unsigned; ptr : pointer; end; scanline_cell_storage_ptr = ^scanline_cell_storage; scanline_cell_storage = object m_cells , m_extra_storage : pod_deque; constructor Construct(entry_sz : unsigned ); overload; constructor Construct(v : scanline_cell_storage_ptr ); overload; destructor Destruct; procedure remove_all; function add_cells(cells : pointer; num_cells : unsigned ) : int; function assign_operator(v : scanline_cell_storage_ptr ) : scanline_cell_storage_ptr; function array_operator (idx : int ) : pointer; procedure copy_extra_storage(v : scanline_cell_storage_ptr ); end; //-----------------------------------------------scanline_storage_aa span_data_ss_ptr = ^span_data_ss; span_data_ss = record x , len : int32; // If negative, it's a solid span, covers is valid covers_id : int; // The index of the cells in the scanline_cell_storage end; scanline_data_ss_ptr = ^scanline_data_ss; scanline_data_ss = record y : int; num_spans , start_span : unsigned; end; span_ss_ptr = ^span_ss; span_ss = record x , len : int32; // If negative, it's a solid span, covers is valid covers : pointer; end; scanline_storage_aa_ptr = ^scanline_storage_aa; embedded_scanline_ss_ptr = ^embedded_scanline_ss; const_iterator_ss = object(span_obj ) m_storage : scanline_storage_aa_ptr; m_span_idx : unsigned; m_span : span_ss; constructor Construct(sl : embedded_scanline_ss_ptr ); function x : int; virtual; function len : int; virtual; function covers : int8u_ptr; virtual; procedure inc_operator; virtual; procedure init_span; end; embedded_scanline_ss = object(scanline ) m_storage : scanline_storage_aa_ptr; m_scanline : scanline_data_ss; m_scanline_idx : unsigned; m_result : const_iterator_ss; constructor Construct(storage : scanline_storage_aa_ptr ); procedure reset(min_x ,max_x : int ); virtual; function y : int; virtual; function num_spans : unsigned; virtual; function begin_ : pointer; virtual; function sz_of_span : unsigned; virtual; function is_plain_span : boolean; virtual; function is_embedded : boolean; virtual; procedure setup(scanline_idx : unsigned ); virtual; end; scanline_storage_aa = object(renderer_scanline ) m_covers : scanline_cell_storage; m_spans , m_scanlines : pod_deque; m_fake_span : span_data_ss; m_fake_scanline : scanline_data_ss; m_min_x , m_min_y , m_max_x , m_max_y : int; m_cur_scanline : unsigned; constructor Construct; destructor Destruct; // Renderer Interface procedure prepare(u : unsigned ); virtual; procedure render (sl : scanline_ptr ); virtual; // Iterate scanlines interface function _min_x : int; virtual; function _min_y : int; virtual; function _max_x : int; virtual; function _max_y : int; virtual; function rewind_scanlines : boolean; virtual; function sweep_scanline(sl : scanline_ptr ) : boolean; virtual; // Specialization for embedded_scanline function sweep_scanline_em(sl : scanline_ptr ) : boolean; virtual; function byte_size : unsigned; virtual; procedure write_int32(dst : int8u_ptr; val : int32 ); procedure serialize (data : int8u_ptr ); virtual; function scanline_by_index(i : unsigned ) : scanline_data_ss_ptr; function span_by_index (i : unsigned ) : span_data_ss_ptr; function covers_by_index (i : int ) : pointer; end; scanline_storage_aa8 = object(scanline_storage_aa ) end; scanline_storage_aa16 = object(scanline_storage_aa ) constructor Construct; function sweep_scanline(sl : scanline_ptr ) : boolean; virtual; function byte_size : unsigned; virtual; procedure serialize(data : int8u_ptr ); virtual; end; scanline_storage_aa32 = object(scanline_storage_aa ) constructor Construct; function sweep_scanline(sl : scanline_ptr ) : boolean; virtual; function byte_size : unsigned; virtual; procedure serialize(data : int8u_ptr ); virtual; end; //------------------------------------------serialized_scanlines_adaptor_aa embedded_scanline_sa_ptr = ^embedded_scanline_sa; const_iterator_sa = object(span_obj ) m_ptr : int8u_ptr; m_span : span_ss; m_dx : int; m_sz : unsigned; constructor Construct(sl : embedded_scanline_sa_ptr; sz : unsigned ); function x : int; virtual; function len : int; virtual; function covers : int8u_ptr; virtual; procedure inc_operator; virtual; procedure init_span; function read_int32 : int; end; embedded_scanline_sa = object(scanline ) m_ptr : int8u_ptr; m_y : int; m_num_spans : unsigned; m_dx : int; m_sz : unsigned; m_result : const_iterator_sa; constructor Construct(sz : unsigned ); procedure reset(min_x ,max_x : int ); virtual; function y : int; virtual; function num_spans : unsigned; virtual; function begin_ : pointer; virtual; function sz_of_span : unsigned; virtual; function is_plain_span : boolean; virtual; function is_embedded : boolean; virtual; procedure init(ptr : int8u_ptr; dx ,dy : int ); virtual; function read_int32 : int; end; serialized_scanlines_adaptor_aa = object(rasterizer_scanline ) m_data , m_end , m_ptr : int8u_ptr; m_dx , m_dy , m_min_x , m_min_y , m_max_x , m_max_y : int; m_sz : unsigned; constructor Construct(sz : unsigned ); overload; constructor Construct(sz : unsigned; data : int8u_ptr; size : unsigned; dx ,dy : double ); overload; procedure init(data : int8u_ptr; size : unsigned; dx ,dy : double ); function read_int32 : int; function read_int32u : unsigned; // Iterate scanlines interface function rewind_scanlines : boolean; virtual; function _min_x : int; virtual; function _min_y : int; virtual; function _max_x : int; virtual; function _max_y : int; virtual; function sweep_scanline(sl : scanline_ptr ) : boolean; virtual; // Specialization for embedded_scanline function sweep_scanline_em(sl : scanline_ptr ) : boolean; virtual; end; serialized_scanlines_adaptor_aa8 = object(serialized_scanlines_adaptor_aa ) constructor Construct; overload; constructor Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); overload; end; serialized_scanlines_adaptor_aa16 = object(serialized_scanlines_adaptor_aa ) constructor Construct; overload; constructor Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); overload; end; serialized_scanlines_adaptor_aa32 = object(serialized_scanlines_adaptor_aa ) constructor Construct; overload; constructor Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); overload; end; { GLOBAL PROCEDURES } IMPLEMENTATION { LOCAL VARIABLES & CONSTANTS } { UNIT IMPLEMENTATION } { CONSTRUCT } constructor scanline_cell_storage.Construct(entry_sz : unsigned ); begin m_cells.Construct (128 - 2 ,entry_sz ,12 ); m_extra_storage.Construct(sizeof(extra_span ) ,6 ); end; { CONSTRUCT } constructor scanline_cell_storage.Construct(v : scanline_cell_storage_ptr ); begin m_cells.Construct (v.m_cells.m_entry_sz ); m_extra_storage.Construct(sizeof(extra_span ) ,6 ); assign_operator (v ); copy_extra_storage(v ); end; { DESTRUCT } destructor scanline_cell_storage.Destruct; begin remove_all; m_cells.Destruct; m_extra_storage.Destruct; end; { REMOVE_ALL } procedure scanline_cell_storage.remove_all; var i : int; s : extra_span_ptr; begin i:=m_extra_storage.size; dec(i ); while i >= 0 do begin s:=m_extra_storage.array_operator(i ); agg_freemem(s.ptr ,s.len * m_cells.m_entry_sz ); dec(i ); end; m_extra_storage.remove_all; m_cells.remove_all; end; { ADD_CELLS } function scanline_cell_storage.add_cells; var idx : int; ptr : pointer; s : extra_span; begin idx:=m_cells.allocate_continuous_block(num_cells ); if idx >= 0 then begin ptr:=m_cells.array_operator(idx ); move(cells^ ,ptr^ ,m_cells.m_entry_sz * num_cells ); result:=idx; exit; end; s.len:=num_cells; agg_getmem(s.ptr ,s.len * m_cells.m_entry_sz ); move(cells^ ,s.ptr^ ,s.len * m_cells.m_entry_sz ); m_extra_storage.add(@s ); result:=-int(m_extra_storage.size ); end; { ASSIGN_OPERATOR } function scanline_cell_storage.assign_operator; begin remove_all; m_cells.assign_operator(@v.m_cells ); copy_extra_storage (v ); result:=@self; end; { ARRAY_OPERATOR } function scanline_cell_storage.array_operator; var i : unsigned; begin if idx >= 0 then begin if idx >= m_cells.size then begin result:=NIL; exit; end; result:=m_cells.array_operator(idx ); exit; end; i:=unsigned(-idx - 1 ); if i >= m_extra_storage.size then begin result:=0; exit; end; result:=extra_span_ptr(m_extra_storage.array_operator(i ) ).ptr; end; { COPY_EXTRA_STORAGE } procedure scanline_cell_storage.copy_extra_storage; var i : unsigned; src : extra_span_ptr; dst : extra_span; begin i:=0; while i < v.m_extra_storage.size do begin src:=v.m_extra_storage.array_operator(i ); dst.len:=src.len; agg_getmem(dst.ptr ,dst.len * v.m_cells.m_entry_sz ); move(src.ptr^ ,dst.ptr^ ,dst.len * v.m_cells.m_entry_sz ); m_extra_storage.add(@dst ); inc(i ); end; end; { CONSTRUCT } constructor const_iterator_ss.Construct; begin m_storage :=sl.m_storage; m_span_idx:=sl.m_scanline.start_span; init_span; end; { X } function const_iterator_ss.x; begin result:=m_span.x; end; { LEN } function const_iterator_ss.len; begin result:=m_span.len; end; { COVERS } function const_iterator_ss.covers; begin result:=m_span.covers; end; { INC_OPERATOR } procedure const_iterator_ss.inc_operator; begin inc(m_span_idx ); init_span; end; { INIT_SPAN } procedure const_iterator_ss.init_span; var s : span_data_ss_ptr; begin s:=m_storage.span_by_index(m_span_idx ); m_span.x :=s.x; m_span.len :=s.len; m_span.covers:=m_storage.covers_by_index(s.covers_id ); end; { CONSTRUCT } constructor embedded_scanline_ss.Construct; begin m_storage:=storage; setup(0 ); end; { RESET } procedure embedded_scanline_ss.reset; begin end; { Y } function embedded_scanline_ss.y; begin result:=m_scanline.y; end; { NUM_SPANS } function embedded_scanline_ss.num_spans; begin result:=m_scanline.num_spans; end; { BEGIN_ } function embedded_scanline_ss.begin_; begin m_result.Construct(@self ); result:=@m_result; end; { SZ_OF_SPAN } function embedded_scanline_ss.sz_of_span; begin result:=sizeof(span_ss ); end; { IS_PLAIN_SPAN } function embedded_scanline_ss.is_plain_span; begin result:=false; end; { IS_EMBEDDED } function embedded_scanline_ss.is_embedded; begin result:=true; end; { SETUP } procedure embedded_scanline_ss.setup; begin m_scanline_idx:=scanline_idx; m_scanline :=m_storage.scanline_by_index(m_scanline_idx )^; end; { CONSTRUCT } constructor scanline_storage_aa.Construct; begin m_covers.Construct (sizeof(int8u ) ); m_spans.Construct (256 - 2 ,sizeof(span_data_ss ) ,10 ); // Block increment size m_scanlines.Construct(sizeof(scanline_data_ss ) ,8 ); m_min_x:=$7FFFFFFF; m_min_y:=$7FFFFFFF; m_max_x:=-$7FFFFFFF; m_max_y:=-$7FFFFFFF; m_cur_scanline:=0; m_fake_scanline.y :=0; m_fake_scanline.num_spans :=0; m_fake_scanline.start_span:=0; m_fake_span.x :=0; m_fake_span.len :=0; m_fake_span.covers_id:=0; end; { DESTRUCT } destructor scanline_storage_aa.Destruct; begin m_covers.Destruct; m_spans.Destruct; m_scanlines.Destruct; end; { PREPARE } procedure scanline_storage_aa.prepare; begin m_covers.remove_all; m_scanlines.remove_all; m_spans.remove_all; m_min_x:=$7FFFFFFF; m_min_y:=$7FFFFFFF; m_max_x:=-$7FFFFFFF; m_max_y:=-$7FFFFFFF; m_cur_scanline:=0; end; { RENDER } procedure scanline_storage_aa.render; var sl_this : scanline_data_ss; y ,x1 ,x2 ,len : int; num_spans ,ss : unsigned; span_pl : span_ptr; span_obj : span_obj_ptr; sp : span_data_ss; begin y:=sl.y; if y < m_min_y then m_min_y:=y; if y > m_max_y then m_max_y:=y; sl_this.y :=y; sl_this.num_spans :=sl.num_spans; sl_this.start_span:=m_spans.size; num_spans:=sl_this.num_spans; span_pl :=NIL; span_obj:=NIL; if sl.is_plain_span then begin span_pl:=sl.begin_; ss:=sl.sz_of_span; end else span_obj:=sl.begin_; repeat if span_pl <> NIL then begin sp.x :=span_pl.x; sp.len:=span_pl.len; end else begin sp.x :=span_obj.x; sp.len:=span_obj.len; end; len:=Abs(sp.len ); if span_pl <> NIL then sp.covers_id:=m_covers.add_cells(span_pl.covers ,unsigned(len ) ) else sp.covers_id:=m_covers.add_cells(span_obj.covers ,unsigned(len ) ); m_spans.add(@sp ); x1:=sp.x; x2:=sp.x + len - 1; if x1 < m_min_x then m_min_x:=x1; if x2 > m_max_x then m_max_x:=x2; dec(num_spans ); if num_spans = 0 then break; if span_pl <> NIL then inc(ptrcomp(span_pl ) ,ss ) else span_obj.inc_operator; until false; m_scanlines.add(@sl_this ); end; { _MIN_X } function scanline_storage_aa._min_x; begin result:=m_min_x; end; { _MIN_Y } function scanline_storage_aa._min_y; begin result:=m_min_y; end; { _MAX_X } function scanline_storage_aa._max_x; begin result:=m_max_x; end; { _MAX_Y } function scanline_storage_aa._max_y; begin result:=m_max_y; end; { REWIND_SCANLINES } function scanline_storage_aa.rewind_scanlines; begin m_cur_scanline:=0; result:=m_scanlines.size > 0; end; { SWEEP_SCANLINE } function scanline_storage_aa.sweep_scanline; var sl_this : scanline_data_ss_ptr; num_spans ,span_idx : unsigned; sp : span_data_ss_ptr; covers : int8u_ptr; begin sl.reset_spans; repeat if m_cur_scanline >= m_scanlines.size then begin result:=false; exit; end; sl_this:=m_scanlines.array_operator(m_cur_scanline ); num_spans:=sl_this.num_spans; span_idx :=sl_this.start_span; repeat sp:=m_spans.array_operator(span_idx ); inc(span_idx ); covers:=covers_by_index(sp.covers_id ); if sp.len < 0 then sl.add_span(sp.x ,unsigned(-sp.len ) ,covers^ ) else sl.add_cells(sp.x ,sp.len ,covers ); dec(num_spans ); until num_spans = 0; inc(m_cur_scanline ); if sl.num_spans <> 0 then begin sl.finalize(sl_this.y ); break; end; until false; result:=true; end; { SWEEP_SCANLINE } function scanline_storage_aa.sweep_scanline_em; begin repeat if m_cur_scanline >= m_scanlines.size then begin result:=false; exit; end; sl.setup(m_cur_scanline ); inc(m_cur_scanline ); until sl.num_spans <> 0; result:=true; end; { BYTE_SIZE } function scanline_storage_aa.byte_size; var i ,size ,num_spans ,span_idx : unsigned; sl_this : scanline_data_ss_ptr; sp : span_data_ss_ptr; begin size:=sizeof(int32 ) * 4; // min_x, min_y, max_x, max_y i:=0; while i < m_scanlines.size do begin inc(size ,sizeof(int32 ) * 3 ); // scanline size in bytes, Y, num_spans sl_this:=m_scanlines.array_operator(i ); num_spans:=sl_this.num_spans; span_idx :=sl_this.start_span; repeat sp:=m_spans.array_operator(span_idx ); inc(span_idx ); inc(size ,sizeof(int32 ) * 2 ); // X, span_len if sp.len < 0 then inc(size ,sizeof(int8u ) ) // cover else inc(size ,sizeof(int8u ) * unsigned(sp.len ) ); // covers dec(num_spans ); until num_spans = 0; inc(i ); end; result:=size; end; { WRITE_INT32 } procedure scanline_storage_aa.write_int32; begin int8u_ptr(ptrcomp(dst ) + 0 * sizeof(int8u ) )^:=int32_int8u(val )._0; int8u_ptr(ptrcomp(dst ) + 1 * sizeof(int8u ) )^:=int32_int8u(val )._1; int8u_ptr(ptrcomp(dst ) + 2 * sizeof(int8u ) )^:=int32_int8u(val )._2; int8u_ptr(ptrcomp(dst ) + 3 * sizeof(int8u ) )^:=int32_int8u(val )._3; end; { SERIALIZE } procedure scanline_storage_aa.serialize; var i ,num_spans ,span_idx : unsigned; sl_this : scanline_data_ss_ptr; sp : span_data_ss_ptr; covers : int8u_ptr; size_ptr : int8u_ptr; begin write_int32(data ,_min_x ); // min_x inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,_min_y ); // min_y inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,_max_x ); // max_x inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,_max_y ); // max_y inc(ptrcomp(data ) ,sizeof(int32 ) ); i:=0; while i < m_scanlines.size do begin sl_this :=m_scanlines.array_operator(i ); size_ptr:=data; inc(ptrcomp(data ) ,sizeof(int32 ) ); // Reserve space for scanline size in bytes write_int32(data ,sl_this.y ); // Y inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,sl_this.num_spans ); // num_spans inc(ptrcomp(data ) ,sizeof(int32 ) ); num_spans:=sl_this.num_spans; span_idx :=sl_this.start_span; repeat sp:=m_spans.array_operator(span_idx ); inc(span_idx ); covers:=covers_by_index(sp.covers_id ); write_int32(data ,sp.x ); // X inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,sp.len ); // span_len inc(ptrcomp(data ) ,sizeof(int32 ) ); if sp.len < 0 then begin move(covers^ ,data^ ,sizeof(int8u ) ); inc (ptrcomp(data ) ,sizeof(int8u ) ); end else begin move(covers^ ,data^ ,unsigned(sp.len ) * sizeof(int8u ) ); inc (ptrcomp(data ) ,sizeof(int8u ) * unsigned(sp.len ) ); end; dec(num_spans ); until num_spans = 0; write_int32(size_ptr ,ptrcomp(data ) - ptrcomp(size_ptr ) ); inc(i ); end; end; { SCANLINE_BY_INDEX } function scanline_storage_aa.scanline_by_index; begin if i < m_scanlines.size then result:=m_scanlines.array_operator(i ) else result:=@m_fake_scanline; end; { SPAN_BY_INDEX } function scanline_storage_aa.span_by_index; begin if i < m_spans.size then result:=m_spans.array_operator(i ) else result:=@m_fake_span; end; { COVERS_BY_INDEX } function scanline_storage_aa.covers_by_index; begin result:=m_covers.array_operator(i ); end; { CONSTRUCT } constructor scanline_storage_aa16.Construct; begin m_covers.Construct (sizeof(int16u ) ); m_spans.Construct (256 - 2 ,sizeof(span_data_ss ) ,10 ); // Block increment size m_scanlines.Construct(sizeof(scanline_data_ss ) ,8 ); m_min_x:=$7FFFFFFF; m_min_y:=$7FFFFFFF; m_max_x:=-$7FFFFFFF; m_max_y:=-$7FFFFFFF; m_cur_scanline:=0; m_fake_scanline.y :=0; m_fake_scanline.num_spans :=0; m_fake_scanline.start_span:=0; m_fake_span.x :=0; m_fake_span.len :=0; m_fake_span.covers_id:=0; end; { SWEEP_SCANLINE } function scanline_storage_aa16.sweep_scanline; var sl_this : scanline_data_ss_ptr; num_spans ,span_idx : unsigned; sp : span_data_ss_ptr; covers : int16u_ptr; begin sl.reset_spans; repeat if m_cur_scanline >= m_scanlines.size then begin result:=false; exit; end; sl_this:=m_scanlines.array_operator(m_cur_scanline ); num_spans:=sl_this.num_spans; span_idx :=sl_this.start_span; repeat sp:=m_spans.array_operator(span_idx ); inc(span_idx ); covers:=covers_by_index(sp.covers_id ); if sp.len < 0 then sl.add_span(sp.x ,unsigned(-sp.len ) ,covers^ ) else sl.add_cells(sp.x ,sp.len ,int8u_ptr(covers ) ); dec(num_spans ); until num_spans = 0; inc(m_cur_scanline ); if sl.num_spans <> 0 then begin sl.finalize(sl_this.y ); break; end; until false; result:=true; end; { BYTE_SIZE } function scanline_storage_aa16.byte_size; var i ,size ,num_spans ,span_idx : unsigned; sl_this : scanline_data_ss_ptr; sp : span_data_ss_ptr; begin size:=sizeof(int32 ) * 4; // min_x, min_y, max_x, max_y i:=0; while i < m_scanlines.size do begin inc(size ,sizeof(int32 ) * 3 ); // scanline size in bytes, Y, num_spans sl_this:=m_scanlines.array_operator(i ); num_spans:=sl_this.num_spans; span_idx :=sl_this.start_span; repeat sp:=m_spans.array_operator(span_idx ); inc(span_idx ); inc(size ,sizeof(int32 ) * 2 ); // X, span_len if sp.len < 0 then inc(size ,sizeof(int16u ) ) // cover else inc(size ,sizeof(int16u ) * unsigned(sp.len ) ); // covers dec(num_spans ); until num_spans = 0; inc(i ); end; result:=size; end; { SERIALIZE } procedure scanline_storage_aa16.serialize; var i ,num_spans ,span_idx : unsigned; sl_this : scanline_data_ss_ptr; sp : span_data_ss_ptr; covers : int16u_ptr; size_ptr : int8u_ptr; begin write_int32(data ,_min_x ); // min_x inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,_min_y ); // min_y inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,_max_x ); // max_x inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,_max_y ); // max_y inc(ptrcomp(data ) ,sizeof(int32 ) ); i:=0; while i < m_scanlines.size do begin sl_this :=m_scanlines.array_operator(i ); size_ptr:=data; inc(ptrcomp(data ) ,sizeof(int32 ) ); // Reserve space for scanline size in bytes write_int32(data ,sl_this.y ); // Y inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,sl_this.num_spans ); // num_spans inc(ptrcomp(data ) ,sizeof(int32 ) ); num_spans:=sl_this.num_spans; span_idx :=sl_this.start_span; repeat sp:=m_spans.array_operator(span_idx ); inc(span_idx ); covers:=covers_by_index(sp.covers_id ); write_int32(data ,sp.x ); // X inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,sp.len ); // span_len inc(ptrcomp(data ) ,sizeof(int32 ) ); if sp.len < 0 then begin move(covers^ ,data^ ,sizeof(int16u ) ); inc (ptrcomp(data ) ,sizeof(int16u ) ); end else begin move(covers^ ,data^ ,unsigned(sp.len ) * sizeof(int16u ) ); inc (ptrcomp(data ) ,sizeof(int16u ) * unsigned(sp.len ) ); end; dec(num_spans ); until num_spans = 0; write_int32(size_ptr ,ptrcomp(data ) - ptrcomp(size_ptr ) ); inc(i ); end; end; { CONSTRUCT } constructor scanline_storage_aa32.Construct; begin m_covers.Construct (sizeof(int32u ) ); m_spans.Construct (256 - 2 ,sizeof(span_data_ss ) ,10 ); // Block increment size m_scanlines.Construct(sizeof(scanline_data_ss ) ,8 ); m_min_x:=$7FFFFFFF; m_min_y:=$7FFFFFFF; m_max_x:=-$7FFFFFFF; m_max_y:=-$7FFFFFFF; m_cur_scanline:=0; m_fake_scanline.y :=0; m_fake_scanline.num_spans :=0; m_fake_scanline.start_span:=0; m_fake_span.x :=0; m_fake_span.len :=0; m_fake_span.covers_id:=0; end; { SWEEP_SCANLINE } function scanline_storage_aa32.sweep_scanline; var sl_this : scanline_data_ss_ptr; num_spans ,span_idx : unsigned; sp : span_data_ss_ptr; covers : int32u_ptr; begin sl.reset_spans; repeat if m_cur_scanline >= m_scanlines.size then begin result:=false; exit; end; sl_this:=m_scanlines.array_operator(m_cur_scanline ); num_spans:=sl_this.num_spans; span_idx :=sl_this.start_span; repeat sp:=m_spans.array_operator(span_idx ); inc(span_idx ); covers:=covers_by_index(sp.covers_id ); if sp.len < 0 then sl.add_span(sp.x ,unsigned(-sp.len ) ,covers^ ) else sl.add_cells(sp.x ,sp.len ,int8u_ptr(covers ) ); dec(num_spans ); until num_spans = 0; inc(m_cur_scanline ); if sl.num_spans <> 0 then begin sl.finalize(sl_this.y ); break; end; until false; result:=true; end; { BYTE_SIZE } function scanline_storage_aa32.byte_size; var i ,size ,num_spans ,span_idx : unsigned; sl_this : scanline_data_ss_ptr; sp : span_data_ss_ptr; begin size:=sizeof(int32 ) * 4; // min_x, min_y, max_x, max_y i:=0; while i < m_scanlines.size do begin inc(size ,sizeof(int32 ) * 3 ); // scanline size in bytes, Y, num_spans sl_this:=m_scanlines.array_operator(i ); num_spans:=sl_this.num_spans; span_idx :=sl_this.start_span; repeat sp:=m_spans.array_operator(span_idx ); inc(span_idx ); inc(size ,sizeof(int32 ) * 2 ); // X, span_len if sp.len < 0 then inc(size ,sizeof(int32u ) ) // cover else inc(size ,sizeof(int32u ) * unsigned(sp.len ) ); // covers dec(num_spans ); until num_spans = 0; inc(i ); end; result:=size; end; { SERIALIZE } procedure scanline_storage_aa32.serialize; var i ,num_spans ,span_idx : unsigned; sl_this : scanline_data_ss_ptr; sp : span_data_ss_ptr; covers : int32u_ptr; size_ptr : int8u_ptr; begin write_int32(data ,_min_x ); // min_x inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,_min_y ); // min_y inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,_max_x ); // max_x inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,_max_y ); // max_y inc(ptrcomp(data ) ,sizeof(int32 ) ); i:=0; while i < m_scanlines.size do begin sl_this :=m_scanlines.array_operator(i ); size_ptr:=data; inc(ptrcomp(data ) ,sizeof(int32 ) ); // Reserve space for scanline size in bytes write_int32(data ,sl_this.y ); // Y inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,sl_this.num_spans ); // num_spans inc(ptrcomp(data ) ,sizeof(int32 ) ); num_spans:=sl_this.num_spans; span_idx :=sl_this.start_span; repeat sp:=m_spans.array_operator(span_idx ); inc(span_idx ); covers:=covers_by_index(sp.covers_id ); write_int32(data ,sp.x ); // X inc(ptrcomp(data ) ,sizeof(int32 ) ); write_int32(data ,sp.len ); // span_len inc(ptrcomp(data ) ,sizeof(int32 ) ); if sp.len < 0 then begin move(covers^ ,data^ ,sizeof(int32u ) ); inc (ptrcomp(data ) ,sizeof(int32u ) ); end else begin move(covers^ ,data^ ,unsigned(sp.len ) * sizeof(int32u ) ); inc (ptrcomp(data ) ,sizeof(int32u ) * unsigned(sp.len ) ); end; dec(num_spans ); until num_spans = 0; write_int32(size_ptr ,ptrcomp(data ) - ptrcomp(size_ptr ) ); inc(i ); end; end; { CONSTRUCT } constructor const_iterator_sa.Construct; begin m_ptr:=sl.m_ptr; m_dx :=sl.m_dx; m_sz :=sz; init_span; end; { X } function const_iterator_sa.x; begin result:=m_span.x; end; { LEN } function const_iterator_sa.len; begin result:=m_span.len; end; { COVERS } function const_iterator_sa.covers; begin result:=m_span.covers; end; { INC_OPERATOR } procedure const_iterator_sa.inc_operator; begin if m_span.len < 0 then inc(ptrcomp(m_ptr ) ,m_sz ) else inc(ptrcomp(m_ptr ) ,m_span.len * m_sz ); init_span; end; { INIT_SPAN } procedure const_iterator_sa.init_span; begin m_span.x :=read_int32 + m_dx; m_span.len :=read_int32; m_span.covers:=m_ptr; end; { READ_INT32 } function const_iterator_sa.read_int32; begin int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); end; { CONSTRUCT } constructor embedded_scanline_sa.Construct; begin m_ptr:=NIL; m_y :=0; m_sz :=sz; m_num_spans:=0; end; { RESET } procedure embedded_scanline_sa.reset; begin end; { Y } function embedded_scanline_sa.y; begin result:=m_y; end; { NUM_SPANS } function embedded_scanline_sa.num_spans; begin result:=m_num_spans; end; { BEGIN_ } function embedded_scanline_sa.begin_; begin m_result.Construct(@self ,m_sz ); result:=@m_result; end; { SZ_OF_SPAN } function embedded_scanline_sa.sz_of_span; begin result:=sizeof(span_ss ); end; { IS_PLAIN_SPAN } function embedded_scanline_sa.is_plain_span; begin result:=false; end; { IS_EMBEDDED } function embedded_scanline_sa.is_embedded; begin result:=true; end; { INIT } procedure embedded_scanline_sa.init; begin m_ptr :=ptr; m_y :=read_int32 + dy; m_num_spans:=unsigned(read_int32 ); m_dx :=dx; end; { READ_INT32 } function embedded_scanline_sa.read_int32; begin int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); end; { CONSTRUCT } constructor serialized_scanlines_adaptor_aa.Construct(sz : unsigned ); begin m_data:=NIL; m_end :=NIL; m_ptr :=NIL; m_dx:=0; m_dy:=0; m_min_x:=$7FFFFFFF; m_min_y:=$7FFFFFFF; m_max_x:=-$7FFFFFFF; m_max_y:=-$7FFFFFFF; m_sz:=sz; end; { CONSTRUCT } constructor serialized_scanlines_adaptor_aa.Construct(sz : unsigned; data : int8u_ptr; size : unsigned; dx ,dy : double ); begin m_data:=data; m_end :=int8u_ptr(ptrcomp(data ) + size ); m_ptr :=data; m_dx:=trunc(dx + 0.5 ); m_dy:=trunc(dy + 0.5 ); m_min_x:=$7FFFFFFF; m_min_y:=$7FFFFFFF; m_max_x:=-$7FFFFFFF; m_max_y:=-$7FFFFFFF; m_sz:=sz; end; { INIT } procedure serialized_scanlines_adaptor_aa.init; begin m_data:=data; m_end :=int8u_ptr(ptrcomp(data ) + size ); m_ptr :=data; m_dx:=trunc(dx + 0.5 ); m_dy:=trunc(dy + 0.5 ); m_min_x:=$7FFFFFFF; m_min_y:=$7FFFFFFF; m_max_x:=-$7FFFFFFF; m_max_y:=-$7FFFFFFF; end; { READ_INT32 } function serialized_scanlines_adaptor_aa.read_int32; begin int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); end; { READ_INT32U } function serialized_scanlines_adaptor_aa.read_int32u; begin int32_int8u(result )._0:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._1:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._2:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); int32_int8u(result )._3:=m_ptr^; inc(ptrcomp(m_ptr ) ,sizeof(int8u ) ); end; { REWIND_SCANLINES } function serialized_scanlines_adaptor_aa.rewind_scanlines; begin m_ptr:=m_data; if ptrcomp(m_ptr ) < ptrcomp(m_end ) then begin m_min_x:=read_int32 + m_dx; m_min_y:=read_int32 + m_dy; m_max_x:=read_int32 + m_dx; m_max_y:=read_int32 + m_dy; result:=true; exit; end; result:=false; end; { _MIN_X } function serialized_scanlines_adaptor_aa._min_x; begin result:=m_min_x; end; { _MIN_Y } function serialized_scanlines_adaptor_aa._min_y; begin result:=m_min_y; end; { _MAX_X } function serialized_scanlines_adaptor_aa._max_x; begin result:=m_max_x; end; { _MAX_Y } function serialized_scanlines_adaptor_aa._max_y; begin result:=m_max_y; end; { SWEEP_SCANLINE } function serialized_scanlines_adaptor_aa.sweep_scanline; var y ,x ,len : int; num_spans : unsigned; begin sl.reset_spans; repeat if ptrcomp(m_ptr ) >= ptrcomp(m_end ) then begin result:=false; exit; end; read_int32; // Skip scanline size in bytes y :=read_int32 + m_dy; num_spans:=read_int32; repeat x :=read_int32 + m_dx; len:=read_int32; if len < 0 then begin sl.add_span(x ,unsigned(-len ) ,m_ptr^ ); inc(ptrcomp(m_ptr ) ,m_sz ); end else begin sl.add_cells(x ,len ,m_ptr ); inc(ptrcomp(m_ptr ) ,len * m_sz ); end; dec(num_spans ); until num_spans = 0; if sl.num_spans <> 0 then begin sl.finalize(y ); break; end; until false; result:=true; end; { SWEEP_SCANLINE } function serialized_scanlines_adaptor_aa.sweep_scanline_em; var byte_size : unsigned; begin repeat if ptrcomp(m_ptr ) >= ptrcomp(m_end ) then begin result:=false; exit; end; byte_size:=read_int32u; sl.init(m_ptr ,m_dx ,m_dy ); inc(ptrcomp(m_ptr ) ,byte_size - sizeof(int32 ) ); until sl.num_spans <> 0; result:=true; end; { CONSTRUCT } constructor serialized_scanlines_adaptor_aa8.Construct; begin inherited Construct(sizeof(int8u ) ); end; { CONSTRUCT } constructor serialized_scanlines_adaptor_aa8.Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); begin inherited Construct(sizeof(int8u ) ,data ,size ,dx ,dy ); end; { CONSTRUCT } constructor serialized_scanlines_adaptor_aa16.Construct; begin inherited Construct(sizeof(int16u ) ); end; { CONSTRUCT } constructor serialized_scanlines_adaptor_aa16.Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); begin inherited Construct(sizeof(int8u ) ,data ,size ,dx ,dy ); end; { CONSTRUCT } constructor serialized_scanlines_adaptor_aa32.Construct; begin inherited Construct(sizeof(int32u ) ); end; { CONSTRUCT } constructor serialized_scanlines_adaptor_aa32.Construct(data : int8u_ptr; size : unsigned; dx ,dy : double ); begin inherited Construct(sizeof(int8u ) ,data ,size ,dx ,dy ); end; END.