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   484738 use v5.12;
  52         158  
6 52     52   201 use warnings;
  52         102  
  52         2178  
7 52     52   16532 use Graphics::Toolkit::Color::Space::Util qw/is_nr/;
  52         112  
  52         3868  
8 52     52   18710 use Graphics::Toolkit::Color::Error;
  52         138  
  52         77752  
9              
10             sub new {
11 547     547 0 7956 my ($pkg, $axis_long_names, $axis_short_names, $space_name, $alias_name, $family, $axis_role_names) = @_;
12 547 100       1516 return 'first argument (axis names) has to be an ARRAY reference' unless ref $axis_long_names eq 'ARRAY';
13 544 100 66     1135 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         1048 my @axis_long_name = map {lc} @$axis_long_names;
  1657         3318  
17 543 100       1191 my @axis_short_name = map { color_key_shortcut($_) } (defined $axis_short_names) ? @$axis_short_names : @axis_long_name;
  1657         2015  
18 543 50       999 return 'need some axis names to create a color space' unless @axis_long_name > 0;
19 543 50       985 return 'need same amount of axis short names and long names' unless @axis_long_name == @axis_short_name;
20 543 50 66     1506 return 'space family dan only be a string' if defined $family and ref $family;
21 543 50 66     1209 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     1177 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         1051 my @iterator = 0 .. $#axis_long_name;
26 543         2236 my %long_name_order = map { $axis_long_name[$_] => $_ } @iterator;
  1657         4693  
27 543         865 my %short_name_order = map { $axis_short_name[$_] => $_ } @iterator;
  1657         2535  
28 543         1436 my $axis_initials = uc join( '', @axis_short_name );
29 543   66     1241 $space_name //= $axis_initials;
30 543   100     1150 $alias_name //= '';
31              
32 543         545 my %role_name_order;
33 543 100       925 %role_name_order = map { $axis_role_names->[$_] => $_ } @iterator if defined $axis_role_names;
  432         768  
34              
35 543   100     1148 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 4844 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 11239 my ($self, $alias, $given) = @_;
49 8038 50 66     11896 $given = undef if defined $given and not $given;
50 8038 100 66     12154 if (defined $alias and $alias ){ return defined( $given ) ? $self->{'alias_name'} : $self->{'normal_alias'} }
  545 100       1325  
51 7493 100       19642 else { return defined( $given ) ? $self->{'space_name'} : $self->{'normal_name'} }
52             }
53 990     990 0 2253 sub family { $_[0]{'space_family_name'}} #
54 312     312 0 414 sub long_axis_names { @{$_[0]{'axis_long_name'}} } #
  312         994  
55 9     9 0 14 sub short_axis_names { @{$_[0]{'axis_short_name'}} } #
  9         48  
56 0     0 0 0 sub axis_role_names { @{$_[0]{'axis_role_name'}} } #
  0         0  
57 12490     12490 0 10823 sub axis_iterator { @{$_[0]{'axis_iterator'}} } # counting all axis 0 .. -1
  12490         20220  
58 19205     19205 0 19759 sub axis_count { int @{$_[0]{'axis_iterator'}} } #
  19205         48482  
59              
60             #### predicates ########################################################
61             sub is_name { # --> ? # is this a valid name of this space
62 3452     3452 0 3895 my ($self, $name) = @_;
63 3452 100       5580 return 0 unless defined $name;
64 2428         3043 $name = $self->normalize_name( $name );
65 2428 100       4277 return 1 if $name eq $self->{'normal_name'};
66 2248 100 100     4462 return 1 if $self->{'alias_name'} and $name eq $self->{'normal_alias'};
67 2208         4199 return 0;
68             }
69             sub normalize_name {
70 19725     19725 0 22899 my ($self, $name) = @_;
71 19725 50       23102 return $name unless defined $name;
72 19725         20464 $name = uc $name;
73 19725         19813 $name =~ tr/_ .-//d; # '-' has to be last
74 19725         41147 return $name;
75             }
76              
77 1557 100 66 1557 0 6762 sub is_long_axis_name { (defined $_[1] and exists $_[0]->{'long_name_order'}{ lc $_[1] }) ? 1 : 0 } # ~long_name --> ?
78 1128 100 66 1128 0 5823 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 180 sub is_axis_role_name { (defined $_[1] and exists $_[0]->{'role_name_order'}{ lc $_[1] }) ? 1 : 0 } # ~role_name --> ?
80 1549 100   1549 0 2220 sub is_axis_name { $_[0]->is_long_axis_name($_[1]) or $_[0]->is_short_axis_name($_[1]) } # ~long|short --> ?
81 28 50   28 0 60 sub is_axis_role { $_[0]->is_axis_role_name($_[1]) or $_[0]->is_axis_name($_[1]) } # ~name --> ?
82              
83 1143 50   1143 0 3241 sub pos_from_long_axis_name { defined $_[1] ? $_[0]->{'long_name_order'}{ lc $_[1] } : undef } # ~long_name --> +pos
84 578 50   578 0 1856 sub pos_from_short_axis_name { defined $_[1] ? $_[0]->{'short_name_order'}{ lc $_[1] } : undef } # ~short_name --> +pos
85 88 50   88 0 334 sub pos_from_axis_role_name { defined $_[1] ? $_[0]->{'role_name_order'}{ lc $_[1] } : undef } # ~role_name --> +pos
86 495   100 495 0 829 sub pos_from_axis_name { pos_from_long_axis_name(@_) // pos_from_short_axis_name(@_) } # ~long|short --> +pos
87 88   66 88 0 178 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 2498 my ($self, $value_hash) = @_;
91 2355 100       2826 $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 2994 my ($self, $value_hash) = @_;
95 2849 100       6691 return 0 unless ref $value_hash eq 'HASH';
96 1034         1148 my $key_count = keys %$value_hash;
97 1034         976 my @axis_visited;
98 1034 100 100     1948 return 0 unless $key_count and $key_count <= $self->axis_count;
99 857         1332 for my $axis_name (keys %$value_hash) {
100 1265 100 66     1688 return 0 unless $self->is_axis_name( $axis_name ) and defined $value_hash->{$axis_name};
101 639         901 my $axis_pos = $self->pos_from_long_axis_name( $axis_name );
102 639 100       1132 $axis_pos = $self->pos_from_short_axis_name( $axis_name ) unless defined $axis_pos;
103 639         916 $axis_visited[ $axis_pos ]++;
104 639 100       1122 return 0 if $axis_visited[ $axis_pos ] > 1;
105             }
106 219         685 return 1;
107             }
108 10447 100 100 10447 0 19002 sub is_value_tuple { (ref $_[1] eq 'ARRAY' and @{$_[1]} == $_[0]->axis_count) ? 1 : 0 }
109             sub is_number_tuple {
110 2398     2398 0 2922 my ($self, $tuple) = @_;
111 2398 100       3233 return 0 unless $self->is_value_tuple( $tuple );
112 2389 100       3271 map { return 0 unless is_nr( $tuple->[$_] ) } $self->axis_iterator;
  7209         10114  
113 2385         4743 return 1;
114             }
115              
116             #### converter #########################################################
117             sub short_axis_name_from_long {
118 4     4 0 6 my ($self, $name) = @_;
119 4 100       10 return unless $self->is_long_axis_name( $name );
120 3         6 ($self->short_axis_names)[ $self->pos_from_long_axis_name( $name ) ];
121             }
122             sub long_axis_name_from_short {
123 4     4 0 9 my ($self, $name) = @_;
124 4 100       20 return unless $self->is_short_axis_name( $name );
125 3         7 ($self->long_axis_names)[ $self->pos_from_short_axis_name( $name ) ];
126             }
127              
128             sub long_name_hash_from_tuple {
129 13     13 0 30 my ($self, $tuple) = @_;
130 13 100       33 return unless $self->is_value_tuple( $tuple );
131 11         27 return { map { $self->{'axis_long_name'}[$_] => $tuple->[$_]} $self->axis_iterator };
  49         171  
132             }
133             sub short_name_hash_from_tuple {
134 10     10 0 17 my ($self, $tuple) = @_;
135 10 100       25 return unless $self->is_value_tuple( $tuple );
136 8         20 return { map {$self->{'axis_short_name'}[$_] => $tuple->[$_]} $self->axis_iterator };
  25         85  
137             }
138              
139             sub tuple_from_hash {
140 39     39 0 4069 my ($self, $value_hash) = @_;
141 39 100       57 return unless $self->is_hash( $value_hash );
142 38         56 my $values = [ (0) x $self->axis_count ];
143 38         69 for my $key (keys %$value_hash) {
144 120         185 $values->[ $self->pos_from_axis_name( $key ) ] = $value_hash->{ $key };
145             }
146 38         84 return $values;
147             }
148             sub tuple_from_partial_hash {
149 387     387 0 7247 my ($self, $value_hash) = @_;
150 387 100       479 return unless $self->is_partial_hash( $value_hash );
151 37         48 my $values = [];
152 37         67 for my $key (keys %$value_hash) {
153 57         101 $values->[ $self->pos_from_axis_name( $key ) ] = $value_hash->{ $key };
154             }
155 37         82 return $values;
156             }
157              
158             1;