File Coverage

lib/Graphics/Toolkit/Color/Space.pm
Criterion Covered Total %
statement 107 110 97.2
branch 38 56 67.8
condition 27 69 39.1
subroutine 44 47 93.6
pod 0 40 0.0
total 216 322 67.0


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 49     49   278846 use v5.12;
  49         138  
6 49     49   227 use warnings;
  49         64  
  49         1895  
7 49     49   20341 use Graphics::Toolkit::Color::Space::Basis; # 1 attr class
  49         99  
  49         1554  
8 49     49   22009 use Graphics::Toolkit::Color::Space::Shape; # 2 ..
  49         96  
  49         1628  
9 49     49   29679 use Graphics::Toolkit::Color::Space::Format; # 3 ..
  49         201  
  49         1774  
10 49     49   267 use Graphics::Toolkit::Color::Space::Util qw/:all/; # forward all its symbols
  49         70  
  49         8249  
11 49     49   265 use Exporter;
  49         67  
  49         70456  
12             our @ISA = qw(Exporter);
13             our @EXPORT_OK = qw/min max uniq round_int round_decimals mod_real spow mult_matrix_vector_3 is_nr/;
14             our %EXPORT_TAGS = (all => [@EXPORT_OK]);
15              
16             ########################################################################
17             sub new {
18 536     536 0 9963 my $pkg = shift;
19 536 50       1583 return if @_ % 2;
20 536         2129 my %args = @_;
21             my $basis = Graphics::Toolkit::Color::Space::Basis->new( $args{'axis'}, $args{'short'}, $args{'name'}, $args{'alias_name'},
22 536         4385 $args{'family'}, $args{'role'}, );
23 536 100       1512 return $basis unless ref $basis;
24 535         3318 my $shape = Graphics::Toolkit::Color::Space::Shape->new( $basis, $args{'type'}, $args{'range'}, $args{'precision'}, $args{'constraint'} );
25 535 50       1143 return $shape unless ref $shape;
26 535         3508 my $format = Graphics::Toolkit::Color::Space::Format->new( $basis, $args{'value_form'}, $args{'prefix'}, $args{'suffix'} );
27 535 50       1291 return $format unless ref $format;
28 535         7865 my $self = bless { basis => $basis, shape => $shape, format => $format, convert => {} };
29 535 100       1170 if (ref $args{'format'} eq 'HASH'){
30 16         30 for my $format_name (keys %{$args{'format'}}){
  16         49  
31 16         25 my $formatter = $args{'format'}{$format_name};
32 16 50 33     120 next unless ref $formatter eq 'ARRAY' and @$formatter > 0;
33 16 50 33     121 $format->add_formatter($format_name, $formatter->[0])
34             if exists $formatter->[0] and ref $formatter->[0] eq 'CODE';
35 16 50 33     81 $format->add_deformatter($format_name, $formatter->[1])
36             if exists $formatter->[1] and ref $formatter->[1] eq 'CODE';
37             }
38             }
39 535 100       1067 if (ref $args{'convert'} eq 'HASH'){
40 512         553 for my $converter_target_space_name (keys %{$args{'convert'}}){
  512         1305  
41 512         653 my $converter_data = $args{'convert'}{ $converter_target_space_name };
42 512 50 33     2922 next unless ref $converter_data eq 'ARRAY' and @$converter_data > 1
      33        
      33        
43             and ref $converter_data->[0] eq 'CODE' and ref $converter_data->[1] eq 'CODE';
44 512         1107 $self->add_converter( $converter_target_space_name, @$converter_data );
45             }
46             }
47 535 100       999 if (ref $args{'values'} eq 'HASH') {
48 16         35 my $numifier = $args{'values'};
49             $format->set_value_numifier( $numifier->{'read'}, $numifier->{'write'} )
50 16 50 33     155 if ref $numifier->{'read'} eq 'CODE' and ref $numifier->{'write'} eq 'CODE';
51             }
52 535         6931 return $self;
53             }
54              
55             ########################################################################
56 28687     28687 0 46615 sub basis { $_[0]{'basis'} }
57 7819     7819 0 60887 sub name { shift->basis->space_name(@_) } # -- ?alias ?given --> ~
58 990     990 0 1082 sub family { shift->basis->family(@_) } # --> ~
59 529     529 0 796 sub is_name { shift->basis->is_name(@_) } # ~name --> ?
60 16211     16211 0 19154 sub normalize_name { shift->basis->normalize_name(@_) } # ~name --> ~
61 133     133 0 310 sub axis_count { shift->basis->axis_count } # --> +
62 235     235 0 601 sub is_axis_name { shift->basis->is_axis_name(@_) } # ~axis_name --> ?
63 28     28 0 68 sub is_axis_role { shift->basis->is_axis_role(@_) } # ~role_name --> ?
64 205     205 0 567 sub pos_from_axis_name { shift->basis->pos_from_axis_name(@_) }# ~axis_name --> +|
65 88     88 0 166 sub pos_from_axis_role { shift->basis->pos_from_axis_role(@_) }# ~axis_name --> +|
66 1071     1071 0 1377 sub is_value_tuple { shift->basis->is_value_tuple(@_) } # @+tuple --> ?
67 828     828 0 1261 sub is_number_tuple { shift->basis->is_number_tuple(@_) } # @+tuple --> ?
68 98     98 0 386 sub is_partial_hash { shift->basis->is_partial_hash(@_) } # %+partial_hash --> ?
69 379     379 0 514 sub tuple_from_partial_hash { shift->basis->tuple_from_partial_hash(@_) } # %+partial_hash --> @+tuple
70              
71             ########################################################################
72 4947     4947 0 12357 sub shape { $_[0]{'shape'} }
73 34     34 0 192 sub is_euclidean { shift->shape->is_euclidean() } # --> ?
74 33     33 0 152 sub is_cylindrical { shift->shape->is_cylindrical } # --> ?
75 0     0 0 0 sub is_equal { shift->shape->is_equal( @_ ) } # @+tuple_a, @+tuple_b -- @+precision --> ?
76 368     368 0 501 sub is_in_linear_bounds{ shift->shape->is_in_linear_bounds(@_)}#@+tuple -- @+range --> ?
77 0     0 0 0 sub is_in_bounds { shift->shape->is_in_bounds(@_)} # @+tuple -- @+range --> ?
78 1224     1224 0 8380 sub round { shift->shape->round( @_ ) } # @+tuple -- @+precision --> @+tuple
79 989     989 0 21842 sub clamp { shift->shape->clamp( @_ ) } # @+tuple -- @+range --> @+tuple
80 14     14 0 28 sub rotate { shift->shape->rotate( @_ ) } # @+tuple -- @+range --> @+tuple
81 365     365 0 889 sub check_value_shape { shift->shape->check_value_shape( @_)}# @+tuple -- @+range, @+precision --> @+tuple|!~ # errmsg
82 719     719 0 5773 sub normalize { shift->shape->normalize(@_)} # @+tuple -- @+range --> @+tuple|!~
83 1021     1021 0 6766 sub denormalize { shift->shape->denormalize(@_)} # @+tuple -- @+range --> @+tuple|!~
84 29     29 0 3730 sub denormalize_delta { shift->shape->denormalize_delta(@_)} # @+tuple -- @+range --> @+tuple|!~
85 54     54 0 12632 sub delta { shift->shape->delta( @_ ) } # @+tuple_a, @+tuple_b --> @+tuple| # on normalized values
86 2     2 0 7 sub has_constraints { shift->shape->has_constraints(@_)} # --> ?
87 0     0 0 0 sub add_constraint { shift->shape->add_constraint(@_)} # ~name, ~error, &checker, &remedy --> %constraint
88              
89             ########################################################################
90 2470     2470 0 5423 sub form { $_[0]{'format'} }
91 135     135 0 14266 sub format { shift->form->format(@_) } # @+values, ~format_name -- @~suffix --> $*color
92 2330     2330 0 29888 sub deformat { shift->form->deformat(@_) } # $*color -- @~suffix --> @+values, ~format_name
93              
94             #### conversion ########################################################
95 855     855 0 1306 sub conversion_tree_parent { (keys %{ $_[0]{'convert'} })[0] }
  855         2404  
96 2586 100 66 2586 0 6105 sub can_convert { (defined $_[1] and exists $_[0]{'convert'}{ $_[0]->normalize_name($_[1]) }) ? 1 : 0 }
97             sub add_converter {
98 514     514 0 941 my ($self, $space_name, $to_code, $from_code, $normal) = @_;
99 514 50 33     2471 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        
100 514 50       892 return 0 if $self->can_convert( $space_name );
101 514 50 66     1032 return 0 if defined $normal and ref $normal ne 'HASH';
102 514 100       1341 $normal = { from => 1, to => 1, } unless ref $normal; # flags: default is full normalisation
103 514 50 33     2021 $normal->{'from'} = {} if not exists $normal->{'from'} or (exists $normal->{'from'} and not $normal->{'from'});
      33        
104 514 100       1373 $normal->{'from'} = {in => 1, out => 1} if not ref $normal->{'from'};
105 514 50       838 $normal->{'from'}{'in'} = 0 unless exists $normal->{'from'}{'in'};
106 514 100       783 $normal->{'from'}{'out'} = 0 unless exists $normal->{'from'}{'out'};
107 514 50 33     1729 $normal->{'to'} = {} if not exists $normal->{'to'} or (exists $normal->{'to'} and not $normal->{'to'});
      33        
108 514 100       1176 $normal->{'to'} = {in => 1, out => 1} if not ref $normal->{'to'};
109 514 100       702 $normal->{'to'}{'in'} = 0 unless exists $normal->{'to'}{'in'};
110 514 50       806 $normal->{'to'}{'out'} = 0 unless exists $normal->{'to'}{'out'};
111 514         1505 $self->{'convert'}{ $self->normalize_name( $space_name ) } = { from => $from_code, to => $to_code, normal => $normal };
112             }
113              
114             sub convert_to { # convert value tuple from this space into another
115 517     517 0 11733 my ($self, $space_name, $tuple) = @_;
116 517         767 $space_name = $self->normalize_name( $space_name );
117 517 50 33     844 return unless $self->is_value_tuple( $tuple ) and defined $space_name and $self->can_convert( $space_name );
      33        
118 517         1441 return $self->{'convert'}{ $space_name }{'to'}->( $tuple );
119             }
120             sub convert_from { # convert value tuple from another space into this
121 620     620 0 19681 my ($self, $space_name, $tuple) = @_;
122 620         940 $space_name = $self->normalize_name( $space_name );
123 620 50 33     2200 return unless ref $tuple eq 'ARRAY' and defined $space_name and $self->can_convert( $space_name );
      33        
124 620         1700 return $self->{'convert'}{ $space_name }{'from'}->( $tuple );
125             }
126             sub converter_normal_states {
127 848     848 0 1180 my ($self, $direction, $space_name) = @_;
128 848         1009 $space_name = $self->normalize_name( $space_name );
129 848 50 33     1414 return unless $self->can_convert( $space_name )
      66        
      66        
130             and defined $direction and ($direction eq 'from' or $direction eq 'to');
131 848         898 return @{$self->{'convert'}{ $space_name }{'normal'}{$direction}}{'in', 'out'};
  848         2359  
132             }
133              
134             1;