File Coverage

lib/Graphics/Toolkit/Color/Space.pm
Criterion Covered Total %
statement 99 101 98.0
branch 33 56 58.9
condition 26 69 37.6
subroutine 40 42 95.2
pod 1 36 2.7
total 199 304 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   417777 use v5.12;
  33         106  
6 33     33   166 use warnings;
  33         63  
  33         2321  
7             require Exporter;
8             our @ISA = qw(Exporter);
9 33     33   14628 use Graphics::Toolkit::Color::Space::Basis;
  33         67  
  33         1200  
10 33     33   16675 use Graphics::Toolkit::Color::Space::Shape;
  33         124  
  33         1264  
11 33     33   16488 use Graphics::Toolkit::Color::Space::Format;
  33         76  
  33         1439  
12 33     33   213 use Graphics::Toolkit::Color::Space::Util qw/:all/;
  33         47  
  33         55697  
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 14106 my $pkg = shift;
19 278 50       915 return if @_ % 2;
20 278         1084 my %args = @_;
21 278         2317 my $basis = Graphics::Toolkit::Color::Space::Basis->new( $args{'axis'}, $args{'short'}, $args{'name'}, $args{'alias'});
22 278 100       772 return $basis unless ref $basis;
23 277         1885 my $shape = Graphics::Toolkit::Color::Space::Shape->new( $basis, $args{'type'}, $args{'range'}, $args{'precision'}, $args{'constraint'} );
24 277 50       628 return $shape unless ref $shape;
25 277         1938 my $format = Graphics::Toolkit::Color::Space::Format->new( $basis, $args{'value_form'}, $args{'prefix'}, $args{'suffix'} );
26 277 50       705 return $format unless ref $format;
27 277         946 my $self = bless { basis => $basis, shape => $shape, format => $format, convert => {} };
28 277 100       701 if (ref $args{'format'} eq 'HASH'){
29 15         18 for my $format_name (keys %{$args{'format'}}){
  15         50  
30 30         63 my $formatter = $args{'format'}{$format_name};
31 30 50 33     137 next unless ref $formatter eq 'ARRAY' and @$formatter > 0;
32 30 50 33     164 $format->add_formatter($format_name, $formatter->[0])
33             if exists $formatter->[0] and ref $formatter->[0] eq 'CODE';
34 30 50 33     136 $format->add_deformatter($format_name, $formatter->[1])
35             if exists $formatter->[1] and ref $formatter->[1] eq 'CODE';
36             }
37             }
38 277 100       684 if (ref $args{'convert'} eq 'HASH'){
39 255         296 for my $converter_target (keys %{$args{'convert'}}){
  255         743  
40 255         354 my $converter = $args{'convert'}{ $converter_target };
41 255 50 33     1573 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         661 $self->add_converter( $converter_target, @$converter );
44             }
45             }
46 277 100       722 if (ref $args{'values'} eq 'HASH') {
47 15         23 my $numifier = $args{'values'};
48             $format->set_value_numifier( $numifier->{'read'}, $numifier->{'write'} )
49 15 50 33     151 if ref $numifier->{'read'} eq 'CODE' and ref $numifier->{'write'} eq 'CODE';
50             }
51              
52 277         4084 return $self;
53             }
54              
55             ########################################################################
56 7012     7012 0 13462 sub basis { $_[0]{'basis'} }
57 4301     4301 0 37906 sub name { shift->basis->space_name } # --> ~
58 936     936 0 1093 sub alias { shift->basis->alias_name } # --> ~
59 48     48 0 164 sub is_name { shift->basis->is_name(@_) } # ~name --> ?
60 115     115 0 255 sub axis_count { shift->basis->axis_count } # --> +
61 4     4 0 14 sub is_axis_name { shift->basis->is_axis_name(@_) } # ~axis_name --> ?
62 1248     1248 0 2163 sub is_value_tuple { shift->basis->is_value_tuple(@_) } # @+values --> ?
63 6     6 0 24 sub is_number_tuple { shift->basis->is_number_tuple(@_) } # @+values --> ?
64 47     47 0 161 sub is_partial_hash { shift->basis->is_partial_hash(@_) } # %+values --> ?
65 28     28 0 67 sub pos_from_axis_name { shift->basis->pos_from_axis_name(@_) } # ~name --> +|
66 209     209 0 331 sub tuple_from_partial_hash { shift->basis->tuple_from_partial_hash(@_) } # %+values --> ?
67              
68             ########################################################################
69 5509     5509 0 12701 sub shape { $_[0]{'shape'} }
70 19     19 0 71 sub is_euclidean { shift->shape->is_euclidean() } # --> ?
71 18     18 0 65 sub is_cylindrical { shift->shape->is_cylindrical } # --> ?
72 0     0 0 0 sub is_equal { shift->shape->is_equal( @_ ) } # @+val_a, @+val_b -- @+precision --> ?
73 339     339 0 514 sub is_in_linear_bounds{ shift->shape->is_in_linear_bounds(@_)}#@+values -- @+range --> ?
74 4     4 0 14 sub is_in_bounds { shift->shape->is_in_bounds(@_)} # @+values -- @+range --> ?
75 1327     1327 0 7638 sub round { shift->shape->round( @_ ) } # @+values -- @+precision --> @+rvals # result values
76 1511     1511 0 60070 sub clamp { shift->shape->clamp( @_ ) } # @+values -- @+range --> @+rvals # result values
77 214     214 0 591 sub check_value_shape { shift->shape->check_value_shape( @_)}# @+values -- @+range, @+precision --> @+values|!~ # errmsg
78 565     565 0 21915 sub normalize { shift->shape->normalize(@_)} # @+values -- @+range --> @+rvals|!~
79 1367     1367 0 27155 sub denormalize { shift->shape->denormalize(@_)} # @+values -- @+range --> @+rvals|!~
80 29     29 0 4949 sub denormalize_delta { shift->shape->denormalize_delta(@_)} # @+values -- @+range --> @+rvals|!~
81 35     35 0 15089 sub delta { shift->shape->delta( @_ ) } # @+val_a, @+val_b --> @+rvals| # on normalized values
82 0     0 0 0 sub add_constraint { shift->shape->add_constraint(@_)} # ~name, ~error, &checker, &remedy --> %constraint
83              
84             ########################################################################
85 2364     2364 0 6548 sub form { $_[0]{'format'} }
86 119     119 0 43690 sub format { shift->form->format(@_) } # @+values, ~format_name -- @~suffix --> $*color
87 2240     2240 0 90206 sub deformat { shift->form->deformat(@_) } # $*color -- @~suffix --> @+values, ~format_name
88              
89             #### conversion ########################################################
90 530     530 0 1048 sub converter_names { keys %{ $_[0]{'convert'} } }
  530         1845  
91             sub alias_converter_name {
92 225     225 0 392 my ($self, $space_name, $name_alias) = @_;
93 225         705 $self->{'convert'}{ uc $name_alias } = $self->{'convert'}{ uc $space_name };
94             }
95 977 100 66 977 0 13496 sub can_convert { (defined $_[1] and exists $_[0]{'convert'}{ uc $_[1] }) ? 1 : 0 }
96             sub add_converter {
97 257     257 0 551 my ($self, $space_name, $to_code, $from_code, $normal) = @_;
98 257 50 33     1405 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        
99 257 50       487 return 0 if $self->can_convert( $space_name );
100 257 50 33     530 return 0 if defined $normal and ref $normal ne 'HASH';
101 257 50       734 $normal = { from => 1, to => 1, } unless ref $normal; # default is full normalisation
102 257 50 33     1120 $normal->{'from'} = {} if not exists $normal->{'from'} or (exists $normal->{'from'} and not $normal->{'from'});
      33        
103 257 50       767 $normal->{'from'} = {in => 1, out => 1} if not ref $normal->{'from'};
104 257 50       500 $normal->{'from'}{'in'} = 0 unless exists $normal->{'from'}{'in'};
105 257 50       428 $normal->{'from'}{'out'} = 0 unless exists $normal->{'from'}{'out'};
106 257 50 33     1052 $normal->{'to'} = {} if not exists $normal->{'to'} or (exists $normal->{'to'} and not $normal->{'to'});
      33        
107 257 50       680 $normal->{'to'} = {in => 1, out => 1} if not ref $normal->{'to'};
108 257 50       399 $normal->{'to'}{'in'} = 0 unless exists $normal->{'to'}{'in'};
109 257 50       445 $normal->{'to'}{'out'} = 0 unless exists $normal->{'to'}{'out'};
110 257         1167 $self->{'convert'}{ uc $space_name } = { from => $from_code, to => $to_code, normal => $normal };
111             }
112              
113             sub convert_to { # convert value tuple from this space into another
114 215     215 0 76291 my ($self, $space_name, $values) = @_;
115 215 50 33     547 return unless $self->is_value_tuple( $values ) and defined $space_name and $self->can_convert( $space_name );
      33        
116 215         1001 return $self->{'convert'}{ uc $space_name }{'to'}->( $values );
117             }
118             sub convert_from { # convert value tuple from another space into this
119 198     198 0 90511 my ($self, $space_name, $values) = @_;
120 198 50 33     1170 return unless ref $values eq 'ARRAY' and defined $space_name and $self->can_convert( $space_name );
      33        
121 198         874 return $self->{'convert'}{ uc $space_name }{'from'}->( $values );
122             }
123              
124             sub converter_normal_states {
125 274     274 0 496 my ($self, $direction, $space_name) = @_;
126 274 50 33     563 return unless $self->can_convert( $space_name )
      66        
      66        
127             and defined $direction and ($direction eq 'from' or $direction eq 'to');
128 274         371 return @{$self->{'convert'}{ uc $space_name }{'normal'}{$direction}}{'in', 'out'};
  274         974  
129             }
130              
131              
132             1;
133              
134             __END__