File Coverage

lib/Graphics/Toolkit/Color/Space.pm
Criterion Covered Total %
statement 98 100 98.0
branch 33 56 58.9
condition 26 69 37.6
subroutine 39 41 95.1
pod 1 35 2.8
total 197 301 65.4


line stmt bran cond sub pod time code
1              
2             # common code of Graphics::Toolkit::Color::Space::Instance::* packages
3              
4             package Graphics::Toolkit::Color::Space;
5 33     33   309744 use v5.12;
  33         128  
6 33     33   192 use warnings;
  33         119  
  33         2843  
7             require Exporter;
8             our @ISA = qw(Exporter);
9 33     33   19304 use Graphics::Toolkit::Color::Space::Basis;
  33         98  
  33         1411  
10 33     33   19841 use Graphics::Toolkit::Color::Space::Shape;
  33         119  
  33         1640  
11 33     33   20916 use Graphics::Toolkit::Color::Space::Format;
  33         92  
  33         1739  
12 33     33   232 use Graphics::Toolkit::Color::Space::Util qw/:all/;
  33         92  
  33         71894  
13             our @EXPORT_OK = qw/round_int round_decimals mod_real min max uniq mult_matrix_vector_3 is_nr/;
14             our %EXPORT_TAGS = (all => [@EXPORT_OK]);
15              
16             ########################################################################
17             sub new {
18 278     278 1 14927 my $pkg = shift;
19 278 50       1081 return if @_ % 2;
20 278         1372 my %args = @_;
21 278         3014 my $basis = Graphics::Toolkit::Color::Space::Basis->new( $args{'axis'}, $args{'short'}, $args{'name'}, $args{'alias'});
22 278 100       1153 return $basis unless ref $basis;
23 277         2518 my $shape = Graphics::Toolkit::Color::Space::Shape->new( $basis, $args{'type'}, $args{'range'}, $args{'precision'}, $args{'constraint'} );
24 277 50       887 return $shape unless ref $shape;
25 277         2681 my $format = Graphics::Toolkit::Color::Space::Format->new( $basis, $args{'value_form'}, $args{'prefix'}, $args{'suffix'} );
26 277 50       1034 return $format unless ref $format;
27 277         1226 my $self = bless { basis => $basis, shape => $shape, format => $format, convert => {} };
28 277 100       1059 if (ref $args{'format'} eq 'HASH'){
29 15         38 for my $format_name (keys %{$args{'format'}}){
  15         61  
30 30         60 my $formatter = $args{'format'}{$format_name};
31 30 50 33     198 next unless ref $formatter eq 'ARRAY' and @$formatter > 0;
32 30 50 33     254 $format->add_formatter($format_name, $formatter->[0])
33             if exists $formatter->[0] and ref $formatter->[0] eq 'CODE';
34 30 50 33     171 $format->add_deformatter($format_name, $formatter->[1])
35             if exists $formatter->[1] and ref $formatter->[1] eq 'CODE';
36             }
37             }
38 277 100       870 if (ref $args{'convert'} eq 'HASH'){
39 255         399 for my $converter_target (keys %{$args{'convert'}}){
  255         897  
40 255         543 my $converter = $args{'convert'}{ $converter_target };
41 255 50 33     2013 next unless ref $converter eq 'ARRAY' and @$converter > 1
      33        
      33        
42             and ref $converter->[0] eq 'CODE' and ref $converter->[1] eq 'CODE';
43 255         827 $self->add_converter( $converter_target, @$converter );
44             }
45             }
46 277 100       870 if (ref $args{'values'} eq 'HASH') {
47 15         55 my $numifier = $args{'values'};
48             $format->set_value_numifier( $numifier->{'read'}, $numifier->{'write'} )
49 15 50 33     219 if ref $numifier->{'read'} eq 'CODE' and ref $numifier->{'write'} eq 'CODE';
50             }
51              
52 277         5371 return $self;
53             }
54              
55             ########################################################################
56 6596     6596 0 18574 sub basis { $_[0]{'basis'} }
57 4149     4149 0 50173 sub name { shift->basis->space_name } # --> ~
58 767     767 0 1361 sub alias { shift->basis->alias_name } # --> ~
59 46     46 0 228 sub is_name { shift->basis->is_name(@_) } # ~name --> ?
60 109     109 0 419 sub axis_count { shift->basis->axis_count } # --> +
61 4     4 0 13 sub is_axis_name { shift->basis->is_axis_name(@_) } # ~axis_name --> ?
62 1203     1203 0 3082 sub is_value_tuple { shift->basis->is_value_tuple(@_) } # @+values --> ?
63 6     6 0 23 sub is_number_tuple { shift->basis->is_number_tuple(@_) } # @+values --> ?
64 47     47 0 195 sub is_partial_hash { shift->basis->is_partial_hash(@_) } # %+values --> ?
65 223     223 0 419 sub tuple_from_partial_hash { shift->basis->tuple_from_partial_hash(@_) } # %+values --> ?
66 21     21 0 59 sub select_tuple_value_from_name { shift->basis->select_tuple_value_from_axis_name(@_) } # ~axis_name. %+values --> +
67              
68             ########################################################################
69 4832     4832 0 17814 sub shape { $_[0]{'shape'} }
70 19     19 0 89 sub is_euclidean { shift->shape->is_euclidean() } # --> ?
71 18     18 0 74 sub is_cylindrical { shift->shape->is_cylindrical } # --> ?
72 339     339 0 728 sub is_in_linear_bounds{ shift->shape->is_in_linear_bounds(@_)}#@+values --> ?
73 0     0 0 0 sub is_equal { shift->shape->is_equal( @_ ) } # @+val_a, @+val_b -- @+precision --> ?
74 813     813 0 6458 sub round { shift->shape->round( @_ ) } # @+values -- @+precision --> @+rvals # result values
75 1946     1946 0 62376 sub clamp { shift->shape->clamp( @_ ) } # @+values -- @+range --> @+rvals # result values
76 212     212 0 653 sub check_value_shape { shift->shape->check_value_shape( @_)}# @+values -- @+range, @+precision --> @+values|!~ # errmsg
77 550     550 0 41773 sub normalize { shift->shape->normalize(@_)} # @+values -- @+range --> @+rvals|!~
78 853     853 0 49804 sub denormalize { shift->shape->denormalize(@_)} # @+values -- @+range --> @+rvals|!~
79 29     29 0 5570 sub denormalize_delta { shift->shape->denormalize_delta(@_)} # @+values -- @+range --> @+rvals|!~
80 35     35 0 24484 sub delta { shift->shape->delta( @_ ) } # @+val_a, @+val_b --> @+rvals| # on normalized values
81 0     0 0 0 sub add_constraint { shift->shape->add_constraint(@_)} # ~name, ~error, &checker, &remedy --> %constraint
82              
83             ########################################################################
84 2232     2232 0 7514 sub form { $_[0]{'format'} }
85 116     116 0 56365 sub format { shift->form->format(@_) } # @+values, ~format_name -- @~suffix --> $*color
86 2111     2111 0 89950 sub deformat { shift->form->deformat(@_) } # $*color -- @~suffix --> @+values, ~format_name
87              
88             #### conversion ########################################################
89 525     525 0 1189 sub converter_names { keys %{ $_[0]{'convert'} } }
  525         2273  
90             sub alias_converter_name {
91 84     84 0 198 my ($self, $space_name, $name_alias) = @_;
92 84         431 $self->{'convert'}{ uc $name_alias } = $self->{'convert'}{ uc $space_name };
93             }
94 967 100 66 967 0 8308 sub can_convert { (defined $_[1] and exists $_[0]{'convert'}{ uc $_[1] }) ? 1 : 0 }
95             sub add_converter {
96 257     257 0 621 my ($self, $space_name, $to_code, $from_code, $normal) = @_;
97 257 50 33     1945 return 0 if not defined $space_name or ref $space_name or ref $from_code ne 'CODE' or ref $to_code ne 'CODE';
      33        
      33        
98 257 50       604 return 0 if $self->can_convert( $space_name );
99 257 50 33     712 return 0 if defined $normal and ref $normal ne 'HASH';
100 257 50       958 $normal = { from => 1, to => 1, } unless ref $normal; # default is full normalisation
101 257 50 33     1478 $normal->{'from'} = {} if not exists $normal->{'from'} or (exists $normal->{'from'} and not $normal->{'from'});
      33        
102 257 50       1010 $normal->{'from'} = {in => 1, out => 1} if not ref $normal->{'from'};
103 257 50       646 $normal->{'from'}{'in'} = 0 unless exists $normal->{'from'}{'in'};
104 257 50       651 $normal->{'from'}{'out'} = 0 unless exists $normal->{'from'}{'out'};
105 257 50 33     1428 $normal->{'to'} = {} if not exists $normal->{'to'} or (exists $normal->{'to'} and not $normal->{'to'});
      33        
106 257 50       1095 $normal->{'to'} = {in => 1, out => 1} if not ref $normal->{'to'};
107 257 50       610 $normal->{'to'}{'in'} = 0 unless exists $normal->{'to'}{'in'};
108 257 50       555 $normal->{'to'}{'out'} = 0 unless exists $normal->{'to'}{'out'};
109 257         1578 $self->{'convert'}{ uc $space_name } = { from => $from_code, to => $to_code, normal => $normal };
110             }
111              
112             sub convert_to { # convert value tuple from this space into another
113 212     212 0 99934 my ($self, $space_name, $values) = @_;
114 212 50 33     700 return unless $self->is_value_tuple( $values ) and defined $space_name and $self->can_convert( $space_name );
      33        
115 212         1146 return $self->{'convert'}{ uc $space_name }{'to'}->( $values );
116             }
117             sub convert_from { # convert value tuple from another space into this
118 196     196 0 139104 my ($self, $space_name, $values) = @_;
119 196 50 33     1469 return unless ref $values eq 'ARRAY' and defined $space_name and $self->can_convert( $space_name );
      33        
120 196         1155 return $self->{'convert'}{ uc $space_name }{'from'}->( $values );
121             }
122              
123             sub converter_normal_states {
124 269     269 0 750 my ($self, $direction, $space_name) = @_;
125 269 50 33     685 return unless $self->can_convert( $space_name )
      66        
      66        
126             and defined $direction and ($direction eq 'from' or $direction eq 'to');
127 269         507 return @{$self->{'convert'}{ uc $space_name }{'normal'}{$direction}}{'in', 'out'};
  269         1376  
128             }
129              
130              
131             1;
132              
133             __END__