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   266202 use v5.12;
  49         158  
6 49     49   201 use warnings;
  49         65  
  49         1908  
7 49     49   19504 use Graphics::Toolkit::Color::Space::Basis; # 1 attr class
  49         97  
  49         1572  
8 49     49   22093 use Graphics::Toolkit::Color::Space::Shape; # 2 ..
  49         128  
  49         1620  
9 49     49   20111 use Graphics::Toolkit::Color::Space::Format; # 3 ..
  49         129  
  49         1634  
10 49     49   265 use Graphics::Toolkit::Color::Space::Util qw/:all/; # forward all its symbols
  49         63  
  49         7593  
11 49     49   239 use Exporter;
  49         59  
  49         66614  
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 9156 my $pkg = shift;
19 536 50       1665 return if @_ % 2;
20 536         2294 my %args = @_;
21             my $basis = Graphics::Toolkit::Color::Space::Basis->new( $args{'axis'}, $args{'short'}, $args{'name'}, $args{'alias_name'},
22 536         4633 $args{'family'}, $args{'role'}, );
23 536 100       1551 return $basis unless ref $basis;
24 535         3616 my $shape = Graphics::Toolkit::Color::Space::Shape->new( $basis, $args{'type'}, $args{'range'}, $args{'precision'}, $args{'constraint'} );
25 535 50       1108 return $shape unless ref $shape;
26 535         3567 my $format = Graphics::Toolkit::Color::Space::Format->new( $basis, $args{'value_form'}, $args{'prefix'}, $args{'suffix'} );
27 535 50       1292 return $format unless ref $format;
28 535         1597 my $self = bless { basis => $basis, shape => $shape, format => $format, convert => {} };
29 535 100       1212 if (ref $args{'format'} eq 'HASH'){
30 16         22 for my $format_name (keys %{$args{'format'}}){
  16         43  
31 16         22 my $formatter = $args{'format'}{$format_name};
32 16 50 33     100 next unless ref $formatter eq 'ARRAY' and @$formatter > 0;
33 16 50 33     125 $format->add_formatter($format_name, $formatter->[0])
34             if exists $formatter->[0] and ref $formatter->[0] eq 'CODE';
35 16 50 33     75 $format->add_deformatter($format_name, $formatter->[1])
36             if exists $formatter->[1] and ref $formatter->[1] eq 'CODE';
37             }
38             }
39 535 100       1055 if (ref $args{'convert'} eq 'HASH'){
40 512         500 for my $converter_target_space_name (keys %{$args{'convert'}}){
  512         1456  
41 512         691 my $converter_data = $args{'convert'}{ $converter_target_space_name };
42 512 50 33     2983 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         1154 $self->add_converter( $converter_target_space_name, @$converter_data );
45             }
46             }
47 535 100       1182 if (ref $args{'values'} eq 'HASH') {
48 16         26 my $numifier = $args{'values'};
49             $format->set_value_numifier( $numifier->{'read'}, $numifier->{'write'} )
50 16 50 33     180 if ref $numifier->{'read'} eq 'CODE' and ref $numifier->{'write'} eq 'CODE';
51             }
52 535         7260 return $self;
53             }
54              
55             ########################################################################
56 28687     28687 0 46031 sub basis { $_[0]{'basis'} }
57 7819     7819 0 57402 sub name { shift->basis->space_name(@_) } # -- ?alias ?given --> ~
58 990     990 0 1149 sub family { shift->basis->family(@_) } # --> ~
59 529     529 0 787 sub is_name { shift->basis->is_name(@_) } # ~name --> ?
60 16211     16211 0 19188 sub normalize_name { shift->basis->normalize_name(@_) } # ~name --> ~
61 133     133 0 263 sub axis_count { shift->basis->axis_count } # --> +
62 235     235 0 597 sub is_axis_name { shift->basis->is_axis_name(@_) } # ~axis_name --> ?
63 28     28 0 62 sub is_axis_role { shift->basis->is_axis_role(@_) } # ~role_name --> ?
64 205     205 0 546 sub pos_from_axis_name { shift->basis->pos_from_axis_name(@_) }# ~axis_name --> +|
65 88     88 0 191 sub pos_from_axis_role { shift->basis->pos_from_axis_role(@_) }# ~axis_name --> +|
66 1071     1071 0 1375 sub is_value_tuple { shift->basis->is_value_tuple(@_) } # @+tuple --> ?
67 828     828 0 1219 sub is_number_tuple { shift->basis->is_number_tuple(@_) } # @+tuple --> ?
68 98     98 0 324 sub is_partial_hash { shift->basis->is_partial_hash(@_) } # %+partial_hash --> ?
69 379     379 0 369 sub tuple_from_partial_hash { shift->basis->tuple_from_partial_hash(@_) } # %+partial_hash --> @+tuple
70              
71             ########################################################################
72 4947     4947 0 11872 sub shape { $_[0]{'shape'} }
73 34     34 0 106 sub is_euclidean { shift->shape->is_euclidean() } # --> ?
74 33     33 0 169 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 429 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 7090 sub round { shift->shape->round( @_ ) } # @+tuple -- @+precision --> @+tuple
79 989     989 0 19617 sub clamp { shift->shape->clamp( @_ ) } # @+tuple -- @+range --> @+tuple
80 14     14 0 23 sub rotate { shift->shape->rotate( @_ ) } # @+tuple -- @+range --> @+tuple
81 365     365 0 957 sub check_value_shape { shift->shape->check_value_shape( @_)}# @+tuple -- @+range, @+precision --> @+tuple|!~ # errmsg
82 719     719 0 5708 sub normalize { shift->shape->normalize(@_)} # @+tuple -- @+range --> @+tuple|!~
83 1021     1021 0 6498 sub denormalize { shift->shape->denormalize(@_)} # @+tuple -- @+range --> @+tuple|!~
84 29     29 0 3144 sub denormalize_delta { shift->shape->denormalize_delta(@_)} # @+tuple -- @+range --> @+tuple|!~
85 54     54 0 12334 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 4957 sub form { $_[0]{'format'} }
91 135     135 0 14525 sub format { shift->form->format(@_) } # @+values, ~format_name -- @~suffix --> $*color
92 2330     2330 0 29349 sub deformat { shift->form->deformat(@_) } # $*color -- @~suffix --> @+values, ~format_name
93              
94             #### conversion ########################################################
95 855     855 0 1365 sub conversion_tree_parent { (keys %{ $_[0]{'convert'} })[0] }
  855         2561  
96 2586 100 66 2586 0 6462 sub can_convert { (defined $_[1] and exists $_[0]{'convert'}{ $_[0]->normalize_name($_[1]) }) ? 1 : 0 }
97             sub add_converter {
98 514     514 0 1039 my ($self, $space_name, $to_code, $from_code, $normal) = @_;
99 514 50 33     2734 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       873 return 0 if $self->can_convert( $space_name );
101 514 50 66     1026 return 0 if defined $normal and ref $normal ne 'HASH';
102 514 100       1436 $normal = { from => 1, to => 1, } unless ref $normal; # flags: default is full normalisation
103 514 50 33     2098 $normal->{'from'} = {} if not exists $normal->{'from'} or (exists $normal->{'from'} and not $normal->{'from'});
      33        
104 514 100       1379 $normal->{'from'} = {in => 1, out => 1} if not ref $normal->{'from'};
105 514 50       852 $normal->{'from'}{'in'} = 0 unless exists $normal->{'from'}{'in'};
106 514 100       859 $normal->{'from'}{'out'} = 0 unless exists $normal->{'from'}{'out'};
107 514 50 33     1659 $normal->{'to'} = {} if not exists $normal->{'to'} or (exists $normal->{'to'} and not $normal->{'to'});
      33        
108 514 100       1230 $normal->{'to'} = {in => 1, out => 1} if not ref $normal->{'to'};
109 514 100       739 $normal->{'to'}{'in'} = 0 unless exists $normal->{'to'}{'in'};
110 514 50       801 $normal->{'to'}{'out'} = 0 unless exists $normal->{'to'}{'out'};
111 514         1499 $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 12001 my ($self, $space_name, $tuple) = @_;
116 517         813 $space_name = $self->normalize_name( $space_name );
117 517 50 33     911 return unless $self->is_value_tuple( $tuple ) and defined $space_name and $self->can_convert( $space_name );
      33        
118 517         1442 return $self->{'convert'}{ $space_name }{'to'}->( $tuple );
119             }
120             sub convert_from { # convert value tuple from another space into this
121 620     620 0 19953 my ($self, $space_name, $tuple) = @_;
122 620         1094 $space_name = $self->normalize_name( $space_name );
123 620 50 33     2428 return unless ref $tuple eq 'ARRAY' and defined $space_name and $self->can_convert( $space_name );
      33        
124 620         1934 return $self->{'convert'}{ $space_name }{'from'}->( $tuple );
125             }
126             sub converter_normal_states {
127 848     848 0 1231 my ($self, $direction, $space_name) = @_;
128 848         1086 $space_name = $self->normalize_name( $space_name );
129 848 50 33     1302 return unless $self->can_convert( $space_name )
      66        
      66        
130             and defined $direction and ($direction eq 'from' or $direction eq 'to');
131 848         939 return @{$self->{'convert'}{ $space_name }{'normal'}{$direction}}{'in', 'out'};
  848         2498  
132             }
133              
134             1;