File Coverage

blib/lib/HiPi/Utils/BitBuffer.pm
Criterion Covered Total %
statement 12 106 11.3
branch 0 34 0.0
condition 0 39 0.0
subroutine 4 15 26.6
pod 0 9 0.0
total 16 203 7.8


line stmt bran cond sub pod time code
1             #########################################################################################
2             # Package HiPi::Utils::BitBuffer
3             # Description : Bit Buffers
4             # Copyright : Copyright (c) 2018-2020 Mark Dootson
5             # License : This is free software; you can redistribute it and/or modify it under
6             # the same terms as the Perl 5 programming language system itself.
7             #########################################################################################
8              
9             package HiPi::Utils::BitBuffer;
10              
11             #########################################################################################
12              
13 1     1   7 use strict;
  1         2  
  1         29  
14 1     1   4 use warnings;
  1         2  
  1         24  
15 1     1   500 use Bit::Vector;
  1         1086  
  1         48  
16 1     1   7 use parent qw( HiPi::Class );
  1         3  
  1         5  
17              
18             our $VERSION ='0.82';
19              
20             __PACKAGE__->create_accessors ( qw( buffer y_buffer width height autoresize autoincrement ) );
21              
22             sub new {
23 0     0 0   my ( $class, %userparams ) = @_;
24            
25 0           my %params = (
26             width => 8,
27             height => 8,
28             autoresize => 0,
29             autoincrement => 1
30             );
31            
32             # get user params
33 0           foreach my $key( keys (%userparams) ) {
34 0           $params{$key} = $userparams{$key};
35             }
36            
37 0           my $buffer = _create_new_buffer( $params{width}, $params{height} );
38            
39 0           $params{buffer} = $buffer;
40 0           my $self = $class->SUPER::new( %params );
41            
42 0           return $self;
43             }
44              
45             sub _create_new_buffer {
46 0     0     my($w,$h, $val) = @_;
47 0   0       $val ||= 0;
48 0           my @buffer = ();
49 0           for ( my $i = 0; $i < $h; $i++ ) {
50 0           my $row = Bit::Vector->new( $w );
51 0           push @buffer, $row;
52             }
53            
54 0           return \@buffer;
55             }
56              
57             sub set_bit {
58 0     0 0   my ($self, $x, $y, $val) = @_;
59 0 0 0       return if( $x < 0 || $y < 0 );
60            
61             # check if buffer needs resizing
62 0 0         if( $self->autoresize ) {
63 0           my ($neww, $newh) = (0,0);
64 0 0         if( $x >= $self->width ) {
65 0           $neww = $x + $self->autoincrement;
66             }
67 0 0         if( $y >= $self->height ) {
68 0           $newh = $y + 1;
69             }
70 0 0 0       if( $neww || $newh ) {
71 0   0       $self->_reset_buffer( $neww || $self->width, $newh || $self->height );
      0        
72             }
73             } else {
74 0 0 0       return if( $x >= $self->width || $y >= $self->height );
75             }
76            
77             # set the bit
78 0 0         if($val) {
79 0           $self->buffer->[$y]->Bit_On($x);
80             } else {
81 0           $self->buffer->[$y]->Bit_Off($x);
82             }
83 0           return;
84             }
85              
86             sub get_bit {
87 0     0 0   my($self, $x, $y) = @_;
88 0 0 0       return 0 if( $x < 0 || $x >= $self->width || $y < 0 || $y >= $self->height );
      0        
      0        
89 0           return 0 + $self->buffer->[$y]->contains( $x );
90             }
91              
92             sub _reset_buffer {
93 0     0     my( $self, $w, $h ) = @_;
94            
95             # change the width ? extend each column vector
96 0 0         if( $w > $self->width ) {
97 0           for my $vector ( @{ $self->buffer } ) {
  0            
98 0           $vector->Resize( $w );
99             }
100 0           $self->width( $w );
101             }
102            
103             # change the height ? - add a new bit vector for every row
104 0 0         if( $h > $self->height ) {
105 0           for (my $i = 0; $i < $h - $self->height; $i++) {
106 0           push @{ $self->buffer }, Bit::Vector->new( $self->width );
  0            
107             }
108 0           $self->height( $h );
109             }
110            
111 0           return;
112             }
113              
114             sub clear {
115 0     0 0   my ( $self ) = @_;
116 0           for (my $row = 0; $row < $self->height; $row ++) {
117 0           $self->buffer->[$row]->Empty;
118             }
119             }
120              
121             sub fill {
122 0     0 0   my ( $self ) = @_;
123 0           for (my $row = 0; $row < $self->height; $row ++) {
124 0           $self->buffer->[$row]->Fill;
125             }
126             }
127              
128             sub clone_buffer {
129 0     0 0   my $self = shift;
130 0           my $class = ref( $self );
131            
132 0           my $clone = $class->new(
133             width => $self->width,
134             height => $self->height,
135             autoresize => $self->autoresize,
136             autoincrement => $self->autoincrement,
137             );
138            
139 0           my @newbuffer = ();
140 0           for (my $i = 0; $i < $self->height; $i ++ ) {
141 0           push @newbuffer, $self->buffer->[$i]->Clone;
142             }
143 0           $clone->buffer( \@newbuffer );
144            
145 0           return $clone;
146             }
147              
148             sub scroll_x_y {
149 0     0 0   my($self, $scrollx, $scrolly) = @_;
150 0           $scrollx %= $self->width;
151 0           $scrolly %= $self->height;
152 0 0 0       return unless($scrollx || $scrolly);
153 0 0         if( $scrolly ) {
154 0           my @vals = splice( @{ $self->buffer }, 0, $scrolly );
  0            
155 0           push @{ $self->buffer }, @vals;
  0            
156             }
157 0 0         if( $scrollx ) {
158 0           for ( my $y = 0; $y < $self->height; $y ++ ) {
159 0           $self->buffer->[$y]->Interval_Substitute($self->buffer->[$y],$self->buffer->[$y]->Size,$scrollx,0,$scrollx);
160 0           $self->buffer->[$y]->Interval_Substitute($self->buffer->[$y],0,$scrollx,0,0);
161             }
162             }
163 0           return;
164             }
165              
166             sub mirror {
167 0     0 0   my ($self, $shapex) = @_;
168 0   0       $shapex //= 0;
169 0           $shapex = abs($shapex);
170 0 0         $shapex = $self->width if $shapex > $self->width;
171 0           for ( my $y = 0; $y < $self->height; $y ++ ) {
172 0           $self->buffer->[$y]->Reverse($self->buffer->[$y]);
173             }
174 0 0 0       $self->scroll_x_y( $self->width - $shapex, 0 ) if $shapex && $shapex != $self->width;
175 0           return;
176             }
177              
178             sub flip {
179 0     0 0   my ($self, $shapex, $shapey) = @_;
180 0   0       $shapey //= 0;
181 0           $shapey = abs($shapey);
182 0 0         $shapey = $self->height if $shapey > $self->height;
183 0           my @newbuff;
184 0           for (my $i = 0; $i < $self->height; $i ++) {
185 0           unshift( @newbuff, $self->buffer->[$i] );
186             }
187            
188 0 0 0       if( $shapey && $shapey != $self->height ) {
189 0           my @vals = splice( @newbuff, 0, $self->height - $shapey );
190 0           push @newbuff, @vals;
191             }
192            
193 0           $self->buffer( \@newbuff );
194 0           $self->mirror( $shapex, 0 );
195 0           return;
196             }
197              
198             1;