File Coverage

lib/Graphics/Toolkit/Color/Space/Basis.pm
Criterion Covered Total %
statement 117 119 98.3
branch 69 82 84.1
condition 45 60 75.0
subroutine 34 35 97.1
pod 0 31 0.0
total 265 327 81.0


line stmt bran cond sub pod time code
1              
2             # count and names of color space axis (short and long), space name = usr | prefix + axis initials
3              
4             package Graphics::Toolkit::Color::Space::Basis;
5 52     52   356880 use v5.12;
  52         138  
6 52     52   232 use warnings;
  52         77  
  52         2227  
7 52     52   16553 use Graphics::Toolkit::Color::Space::Util qw/is_nr/;
  52         127  
  52         3554  
8 52     52   17851 use Graphics::Toolkit::Color::Error;
  52         123  
  52         75348  
9              
10             sub new {
11 547     547 0 6989 my ($pkg, $axis_long_names, $axis_short_names, $space_name, $alias_name, $family, $axis_role_names) = @_;
12 547 100       1478 return 'first argument (axis names) has to be an ARRAY reference' unless ref $axis_long_names eq 'ARRAY';
13 544 100 66     1208 return 'amount of short axis names have to match the count of long axis names'
      100        
14             if defined $axis_short_names and (ref $axis_short_names ne 'ARRAY' or @$axis_long_names != @$axis_short_names);
15              
16 543         944 my @axis_long_name = map {lc} @$axis_long_names;
  1657         3245  
17 543 100       1138 my @axis_short_name = map { color_key_shortcut($_) } (defined $axis_short_names) ? @$axis_short_names : @axis_long_name;
  1657         1970  
18 543 50       1061 return 'need some axis names to create a color space' unless @axis_long_name > 0;
19 543 50       950 return 'need same amount of axis short names and long names' unless @axis_long_name == @axis_short_name;
20 543 50 66     1473 return 'space family dan only be a string' if defined $family and ref $family;
21 543 50 66     1217 return 'axis role description has to be provided with a family name' if defined($axis_role_names) and not defined($family);
22 543 50 33     1209 return 'axis role description has to have same length as axis names'
      66        
23             if defined $axis_role_names and (ref $axis_role_names ne 'ARRAY' or @$axis_role_names != @$axis_long_names);
24              
25 543         1037 my @iterator = 0 .. $#axis_long_name;
26 543         669 my %long_name_order = map { $axis_long_name[$_] => $_ } @iterator;
  1657         6365  
27 543         812 my %short_name_order = map { $axis_short_name[$_] => $_ } @iterator;
  1657         2401  
28 543         1482 my $axis_initials = uc join( '', @axis_short_name );
29 543   66     1252 $space_name //= $axis_initials;
30 543   100     1193 $alias_name //= '';
31              
32 543         627 my %role_name_order;
33 543 100       850 %role_name_order = map { $axis_role_names->[$_] => $_ } @iterator if defined $axis_role_names;
  432         717  
34              
35 543   100     1116 bless { space_name => $space_name, alias_name => $alias_name,
      100        
36             normal_name => normalize_name('',$space_name), normal_alias => normalize_name('',$alias_name),
37             space_family_name => $family // '',
38             axis_long_name => \@axis_long_name, long_name_order => \%long_name_order,
39             axis_short_name => \@axis_short_name, short_name_order => \%short_name_order,
40             axis_role_name => $axis_role_names // [], role_name_order => \%role_name_order,
41             axis_iterator => \@iterator,
42             }
43             }
44 1657 50   1657 0 4839 sub color_key_shortcut { lc substr($_[0], 0, 1) if defined $_[0] }
45              
46             #### getter ############################################################
47             sub space_name { # -- ?alias ?given --> ~
48 8038     8038 0 11110 my ($self, $alias, $given) = @_;
49 8038 50 66     11855 $given = undef if defined $given and not $given;
50 8038 100 66     12296 if (defined $alias and $alias ){ return defined( $given ) ? $self->{'alias_name'} : $self->{'normal_alias'} }
  545 100       1351  
51 7493 100       20178 else { return defined( $given ) ? $self->{'space_name'} : $self->{'normal_name'} }
52             }
53 990     990 0 2118 sub family { $_[0]{'space_family_name'}} #
54 312     312 0 353 sub long_axis_names { @{$_[0]{'axis_long_name'}} } #
  312         992  
55 9     9 0 11 sub short_axis_names { @{$_[0]{'axis_short_name'}} } #
  9         64  
56 0     0 0 0 sub axis_role_names { @{$_[0]{'axis_role_name'}} } #
  0         0  
57 12490     12490 0 11320 sub axis_iterator { @{$_[0]{'axis_iterator'}} } # counting all axis 0 .. -1
  12490         21000  
58 19205     19205 0 19088 sub axis_count { int @{$_[0]{'axis_iterator'}} } #
  19205         48590  
59              
60             #### predicates ########################################################
61             sub is_name { # --> ? # is this a valid name of this space
62 3452     3452 0 4120 my ($self, $name) = @_;
63 3452 100       5527 return 0 unless defined $name;
64 2428         3137 $name = $self->normalize_name( $name );
65 2428 100       4359 return 1 if $name eq $self->{'normal_name'};
66 2248 100 100     4722 return 1 if $self->{'alias_name'} and $name eq $self->{'normal_alias'};
67 2208         4215 return 0;
68             }
69             sub normalize_name {
70 19725     19725 0 23365 my ($self, $name) = @_;
71 19725 50       23192 return $name unless defined $name;
72 19725         20431 $name = uc $name;
73 19725         19796 $name =~ tr/_ .-//d; # '-' has to be last
74 19725         42603 return $name;
75             }
76              
77 1576 100 66 1576 0 7146 sub is_long_axis_name { (defined $_[1] and exists $_[0]->{'long_name_order'}{ lc $_[1] }) ? 1 : 0 } # ~long_name --> ?
78 1136 100 66 1136 0 6313 sub is_short_axis_name { (defined $_[1] and exists $_[0]->{'short_name_order'}{ lc $_[1] }) ? 1 : 0 } # ~short_name --> ?
79 28 50 33 28 0 162 sub is_axis_role_name { (defined $_[1] and exists $_[0]->{'role_name_order'}{ lc $_[1] }) ? 1 : 0 } # ~role_name --> ?
80 1568 100   1568 0 2460 sub is_axis_name { $_[0]->is_long_axis_name($_[1]) or $_[0]->is_short_axis_name($_[1]) } # ~long|short --> ?
81 28 50   28 0 56 sub is_axis_role { $_[0]->is_axis_role_name($_[1]) or $_[0]->is_axis_name($_[1]) } # ~name --> ?
82              
83 1162 50   1162 0 3329 sub pos_from_long_axis_name { defined $_[1] ? $_[0]->{'long_name_order'}{ lc $_[1] } : undef } # ~long_name --> +pos
84 586 50   586 0 1594 sub pos_from_short_axis_name { defined $_[1] ? $_[0]->{'short_name_order'}{ lc $_[1] } : undef } # ~short_name --> +pos
85 88 50   88 0 342 sub pos_from_axis_role_name { defined $_[1] ? $_[0]->{'role_name_order'}{ lc $_[1] } : undef } # ~role_name --> +pos
86 495   100 495 0 758 sub pos_from_axis_name { pos_from_long_axis_name(@_) // pos_from_short_axis_name(@_) } # ~long|short --> +pos
87 88   66 88 0 144 sub pos_from_axis_role { pos_from_axis_role_name(@_) // pos_from_axis_name(@_) } # ~name --> +pos
88              
89             sub is_hash { # with all axis names as keys
90 2355     2355 0 2669 my ($self, $value_hash) = @_;
91 2355 100       3096 $self->is_partial_hash( $value_hash ) and (keys %$value_hash == $self->axis_count);
92             }
93             sub is_partial_hash { # with some axis names as keys
94 2849     2849 0 3117 my ($self, $value_hash) = @_;
95 2849 100       7092 return 0 unless ref $value_hash eq 'HASH';
96 1034         1264 my $key_count = keys %$value_hash;
97 1034         1084 my @axis_visited;
98 1034 100 100     2263 return 0 unless $key_count and $key_count <= $self->axis_count;
99 857         1507 for my $axis_name (keys %$value_hash) {
100 1284 100 66     1860 return 0 unless $self->is_axis_name( $axis_name ) and defined $value_hash->{$axis_name};
101 658         926 my $axis_pos = $self->pos_from_long_axis_name( $axis_name );
102 658 100       1153 $axis_pos = $self->pos_from_short_axis_name( $axis_name ) unless defined $axis_pos;
103 658         832 $axis_visited[ $axis_pos ]++;
104 658 100       1186 return 0 if $axis_visited[ $axis_pos ] > 1;
105             }
106 219         722 return 1;
107             }
108 10447 100 100 10447 0 19544 sub is_value_tuple { (ref $_[1] eq 'ARRAY' and @{$_[1]} == $_[0]->axis_count) ? 1 : 0 }
109             sub is_number_tuple {
110 2398     2398 0 3070 my ($self, $tuple) = @_;
111 2398 100       3481 return 0 unless $self->is_value_tuple( $tuple );
112 2389 100       3321 map { return 0 unless is_nr( $tuple->[$_] ) } $self->axis_iterator;
  7209         10530  
113 2385         5041 return 1;
114             }
115              
116             #### converter #########################################################
117             sub short_axis_name_from_long {
118 4     4 0 8 my ($self, $name) = @_;
119 4 100       7 return unless $self->is_long_axis_name( $name );
120 3         7 ($self->short_axis_names)[ $self->pos_from_long_axis_name( $name ) ];
121             }
122             sub long_axis_name_from_short {
123 4     4 0 6 my ($self, $name) = @_;
124 4 100       9 return unless $self->is_short_axis_name( $name );
125 3         6 ($self->long_axis_names)[ $self->pos_from_short_axis_name( $name ) ];
126             }
127              
128             sub long_name_hash_from_tuple {
129 13     13 0 25 my ($self, $tuple) = @_;
130 13 100       27 return unless $self->is_value_tuple( $tuple );
131 11         22 return { map { $self->{'axis_long_name'}[$_] => $tuple->[$_]} $self->axis_iterator };
  49         145  
132             }
133             sub short_name_hash_from_tuple {
134 10     10 0 18 my ($self, $tuple) = @_;
135 10 100       20 return unless $self->is_value_tuple( $tuple );
136 8         13 return { map {$self->{'axis_short_name'}[$_] => $tuple->[$_]} $self->axis_iterator };
  25         82  
137             }
138              
139             sub tuple_from_hash {
140 39     39 0 5626 my ($self, $value_hash) = @_;
141 39 100       58 return unless $self->is_hash( $value_hash );
142 38         75 my $values = [ (0) x $self->axis_count ];
143 38         63 for my $key (keys %$value_hash) {
144 120         181 $values->[ $self->pos_from_axis_name( $key ) ] = $value_hash->{ $key };
145             }
146 38         86 return $values;
147             }
148             sub tuple_from_partial_hash {
149 387     387 0 7019 my ($self, $value_hash) = @_;
150 387 100       639 return unless $self->is_partial_hash( $value_hash );
151 37         56 my $values = [];
152 37         90 for my $key (keys %$value_hash) {
153 57         124 $values->[ $self->pos_from_axis_name( $key ) ] = $value_hash->{ $key };
154             }
155 37         96 return $values;
156             }
157              
158             1;