File Coverage

lib/Graphics/Toolkit/Color/Name/Scheme.pm
Criterion Covered Total %
statement 78 78 100.0
branch 35 40 87.5
condition 6 15 40.0
subroutine 13 13 100.0
pod 6 8 75.0
total 138 154 89.6


line stmt bran cond sub pod time code
1              
2             # name space for color names, translate values > names & back, find closest name
3              
4             package Graphics::Toolkit::Color::Name::Scheme;
5 11     11   278044 use v5.12;
  11         35  
6 11     11   95 use warnings;
  11         19  
  11         577  
7 11     11   6515 use Graphics::Toolkit::Color::Space::Hub;
  11         135  
  11         600  
8 11     11   457 use Graphics::Toolkit::Color::Space::Util qw/round_int uniq/;
  11         41  
  11         12828  
9              
10             my $RGB = Graphics::Toolkit::Color::Space::Hub::default_space_name();
11              
12             #### constructor #######################################################
13             sub new {
14 12     12 1 4590 my $pkg = shift;
15 12         141 bless { shaped => {name => [], values => {}}, normal => {} }
16             }
17             sub add_color {
18 7165     7165 1 15678 my ($self, $name, $values) = @_;
19 7165 50 33     29871 return 0 if not defined $name or ref $values ne 'ARRAY' or @$values != 3 or $self->is_name_taken($name);
      33        
      33        
20 7165         9452 $name = _clean_name( $name );
21 7165         13394 $self->{'shaped'}{'values'}{$name} = $values;
22             $self->{'shaped'}{'name'}[$values->[0]][$values->[1]][$values->[2]] =
23             (exists $self->{'shaped'}{'name'}[$values->[0]][$values->[1]][$values->[2]])
24 7165 100       57697 ? [@{$self->{'shaped'}{'name'}[$values->[0]][$values->[1]][$values->[2]]}, $name]
  571         1841  
25             : [$name];
26 7165         16053 1;
27             }
28              
29             #### exact getter ######################################################
30 2     2 1 907 sub all_names { keys %{$_[0]->{'shaped'}{'values'}} }
  2         357  
31             sub is_name_taken {
32 7177     7177 1 14225 my ($self, $name) = @_;
33 7177 100       11207 (exists $self->{'shaped'}{'values'}{_clean_name($name)}) ? 1 : 0;
34             }
35             sub values_from_name {
36 92     92 1 8058 my ($self, $name) = @_;
37 92 50       209 return unless defined $name;
38 92         234 $name = _clean_name($name);
39 92 100       526 return $self->{'shaped'}{'values'}{$name} if exists $self->{'shaped'}{'values'}{$name};
40             }
41             sub names_from_values {
42 577     577 1 8550 my ($self, $values) = @_;
43 577 100 66     2157 return '' unless ref $values eq 'ARRAY' and @$values == 3;
44 565 100       1720 return '' unless exists $self->{'shaped'}{'name'}[$values->[0]];
45 445 100       1380 return '' unless exists $self->{'shaped'}{'name'}[$values->[0]][$values->[1]];
46 184 100       593 return '' unless exists $self->{'shaped'}{'name'}[$values->[0]][$values->[1]][$values->[2]];
47 172         567 return $self->{'shaped'}{'name'}[$values->[0]][$values->[1]][$values->[2]];
48             }
49              
50             #### nearness methods ##################################################
51             sub closest_names_from_values {
52 12     12 0 12543 my ($self, $values) = @_;
53 12 50 33     75 return '' unless ref $values eq 'ARRAY' and @$values == 3;
54 12         52 my $names = names_from_values( $values );
55 12 50       37 return ($names, 0) if ref $names;
56 12         15 my @names;
57 12         22 my $sqr_min = 1 + 255**3;
58 12         31 my $all_values = $self->{'shaped'}{'values'};
59 12         617 for my $index_name (keys %$all_values){
60 3593         4579 my $index_values = $all_values->{ $index_name };
61 3593         4961 my $temp_sqr_sum = ($index_values->[0] - $values->[0]) ** 2;
62 3593 100       5562 next if $temp_sqr_sum > $sqr_min;
63 827         895 $temp_sqr_sum += ($index_values->[1] - $values->[1]) ** 2;
64 827 100       1152 next if $temp_sqr_sum > $sqr_min;
65 110         141 $temp_sqr_sum += ($index_values->[2] - $values->[2]) ** 2;
66 110 100       182 next if $temp_sqr_sum > $sqr_min;
67 49 100       111 @names = ($sqr_min == $temp_sqr_sum) ? (@names, $index_name) : $index_name;
68 49         73 $sqr_min = $temp_sqr_sum;
69             }
70 12 100       201 return '' unless @names;
71             # restore as much order as possible
72 11         31 @names = map { @{$self->names_from_values( $self->values_from_name($_))} } @names;
  16         25  
  16         42  
73 11         51 @names = uniq( @names );
74 11         51 return (\@names, sqrt($sqr_min));
75             }
76              
77             sub names_in_range {
78 3     3 0 9 my ($self, $values, $range) = @_;
79 3         7 my @names;
80 3         12 my $sqr_max = $range ** 2;
81 3         8 my $all_values = $self->{'shaped'}{'values'};
82 3         305 for my $index_name (keys %$all_values){
83 1433         2010 my $index_values = $all_values->{ $index_name };
84 1433         2253 my $temp_sqr_sum = ($index_values->[0] - $values->[0]) ** 2;
85 1433 100       2433 next if $temp_sqr_sum > $sqr_max;
86 153         219 $temp_sqr_sum += ($index_values->[1] - $values->[1]) ** 2;
87 153 100       285 next if $temp_sqr_sum > $sqr_max;
88 28         35 $temp_sqr_sum += ($index_values->[2] - $values->[2]) ** 2;
89 28 100       46 next if $temp_sqr_sum > $sqr_max;
90 5         11 push @names, $index_name;
91             }
92 3 50       95 return '' unless @names;
93             # restore as much order as possible
94 3         11 @names = map { @{$self->names_from_values( $self->values_from_name($_))} } @names;
  5         7  
  5         18  
95 3         21 return [ uniq( @names ) ];
96             }
97              
98             #### util ##############################################################
99             sub _clean_name {
100 14434     14434   17036 my $name = shift;
101 14434         18638 $name =~ tr/_'\///d;
102 14434         33935 lc $name;
103             }
104              
105             1;
106              
107             __END__