File Coverage

lib/Graphics/Toolkit/Color/Space.pm
Criterion Covered Total %
statement 99 102 97.0
branch 38 56 67.8
condition 27 69 39.1
subroutine 38 41 92.6
pod 1 35 2.8
total 203 303 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 45     45   294427 use v5.12;
  45         174  
6 45     45   324 use warnings;
  45         97  
  45         5400  
7             require Exporter;
8             our @ISA = qw(Exporter);
9 45     45   26248 use Graphics::Toolkit::Color::Space::Basis;
  45         134  
  45         1963  
10 45     45   27299 use Graphics::Toolkit::Color::Space::Shape;
  45         192  
  45         2113  
11 45     45   26260 use Graphics::Toolkit::Color::Space::Format;
  45         135  
  45         2115  
12 45     45   364 use Graphics::Toolkit::Color::Space::Util qw/:all/;
  45         79  
  45         100919  
13             our @EXPORT_OK = qw/min max uniq round_int round_decimals mod_real gamma_correct mult_matrix_vector_3 is_nr/;
14             our %EXPORT_TAGS = (all => [@EXPORT_OK]);
15              
16             ########################################################################
17             sub new {
18 458     458 1 16036 my $pkg = shift;
19 458 50       1811 return if @_ % 2;
20 458         2354 my %args = @_;
21 458         4968 my $basis = Graphics::Toolkit::Color::Space::Basis->new( $args{'axis'}, $args{'short'}, $args{'name'}, $args{'alias'});
22 458 100       3338 return $basis unless ref $basis;
23 457         8816 my $shape = Graphics::Toolkit::Color::Space::Shape->new( $basis, $args{'type'}, $args{'range'}, $args{'precision'}, $args{'constraint'} );
24 457 50       1559 return $shape unless ref $shape;
25 457         4519 my $format = Graphics::Toolkit::Color::Space::Format->new( $basis, $args{'value_form'}, $args{'prefix'}, $args{'suffix'} );
26 457 50       1610 return $format unless ref $format;
27 457         2059 my $self = bless { basis => $basis, shape => $shape, format => $format, convert => {} };
28 457 100       1563 if (ref $args{'format'} eq 'HASH'){
29 15         24 for my $format_name (keys %{$args{'format'}}){
  15         60  
30 30         93 my $formatter = $args{'format'}{$format_name};
31 30 50 33     171 next unless ref $formatter eq 'ARRAY' and @$formatter > 0;
32 30 50 33     208 $format->add_formatter($format_name, $formatter->[0])
33             if exists $formatter->[0] and ref $formatter->[0] eq 'CODE';
34 30 50 33     186 $format->add_deformatter($format_name, $formatter->[1])
35             if exists $formatter->[1] and ref $formatter->[1] eq 'CODE';
36             }
37             }
38 457 100       1313 if (ref $args{'convert'} eq 'HASH'){
39 435         620 for my $converter_target_space_name (keys %{$args{'convert'}}){
  435         1573  
40 435         799 my $converter_data = $args{'convert'}{ $converter_target_space_name };
41 435 50 33     4725 next unless ref $converter_data eq 'ARRAY' and @$converter_data > 1
      33        
      33        
42             and ref $converter_data->[0] eq 'CODE' and ref $converter_data->[1] eq 'CODE';
43 435         1501 $self->add_converter( $converter_target_space_name, @$converter_data );
44             }
45             }
46 457 100       1396 if (ref $args{'values'} eq 'HASH') {
47 15         31 my $numifier = $args{'values'};
48             $format->set_value_numifier( $numifier->{'read'}, $numifier->{'write'} )
49 15 50 33     296 if ref $numifier->{'read'} eq 'CODE' and ref $numifier->{'write'} eq 'CODE';
50             }
51              
52 457         8065 return $self;
53             }
54              
55             ########################################################################
56 13391     13391 0 33330 sub basis { $_[0]{'basis'} }
57 4594     4594 0 73409 sub name { shift->basis->space_name(@_) } # -- ?alias ?given --> ~
58 89     89 0 344 sub is_name { shift->basis->is_name(@_) } # ~name --> ?
59 6144     6144 0 11028 sub normalize_name { shift->basis->normalize_name(@_) } # ~name --> ~
60 126     126 0 348 sub axis_count { shift->basis->axis_count } # --> +
61 214     214 0 762 sub is_axis_name { shift->basis->is_axis_name(@_) } # ~axis_name --> ?
62 179     179 0 631 sub pos_from_axis_name { shift->basis->pos_from_axis_name(@_) }# ~axis_name --> +|
63 858     858 0 1544 sub is_value_tuple { shift->basis->is_value_tuple(@_) } # @+tuple --> ?
64 718     718 0 1249 sub is_number_tuple { shift->basis->is_number_tuple(@_) } # @+tuple --> ?
65 86     86 0 395 sub is_partial_hash { shift->basis->is_partial_hash(@_) } # %+partial_hash --> ?
66 314     314 0 399 sub tuple_from_partial_hash { shift->basis->tuple_from_partial_hash(@_) } # %+partial_hash --> @+tuple
67              
68             ########################################################################
69 4532     4532 0 16120 sub shape { $_[0]{'shape'} }
70 31     31 0 180 sub is_euclidean { shift->shape->is_euclidean() } # --> ?
71 30     30 0 138 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 354     354 0 533 sub is_in_linear_bounds{ shift->shape->is_in_linear_bounds(@_)}#@+values -- @+range --> ?
74 0     0 0 0 sub is_in_bounds { shift->shape->is_in_bounds(@_)} # @+values -- @+range --> ?
75 1122     1122 0 9445 sub round { shift->shape->round( @_ ) } # @+values -- @+precision --> @+rvals # result values
76 957     957 0 26310 sub clamp { shift->shape->clamp( @_ ) } # @+values -- @+range --> @+rvals # result values
77 335     335 0 1179 sub check_value_shape { shift->shape->check_value_shape( @_)}# @+values -- @+range, @+precision --> @+values|!~ # errmsg
78 606     606 0 8719 sub normalize { shift->shape->normalize(@_)} # @+values -- @+range --> @+rvals|!~
79 928     928 0 10312 sub denormalize { shift->shape->denormalize(@_)} # @+values -- @+range --> @+rvals|!~
80 29     29 0 5700 sub denormalize_delta { shift->shape->denormalize_delta(@_)} # @+values -- @+range --> @+rvals|!~
81 51     51 0 23034 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 2116     2116 0 5333 sub form { $_[0]{'format'} }
86 123     123 0 17698 sub format { shift->form->format(@_) } # @+values, ~format_name -- @~suffix --> $*color
87 1988     1988 0 46661 sub deformat { shift->form->deformat(@_) } # $*color -- @~suffix --> @+values, ~format_name
88              
89             #### conversion ########################################################
90 602     602 0 1096 sub conversion_tree_parent { (keys %{ $_[0]{'convert'} })[0] }
  602         2526  
91 1466 100 66 1466 0 5757 sub can_convert { (defined $_[1] and exists $_[0]{'convert'}{ $_[0]->normalize_name($_[1]) }) ? 1 : 0 }
92             sub add_converter {
93 437     437 0 1148 my ($self, $space_name, $to_code, $from_code, $normal) = @_;
94 437 50 33     3065 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        
95 437 50       1009 return 0 if $self->can_convert( $space_name );
96 437 50 66     1171 return 0 if defined $normal and ref $normal ne 'HASH';
97 437 100       1730 $normal = { from => 1, to => 1, } unless ref $normal; # flags: default is full normalisation
98 437 50 33     2434 $normal->{'from'} = {} if not exists $normal->{'from'} or (exists $normal->{'from'} and not $normal->{'from'});
      33        
99 437 100       1833 $normal->{'from'} = {in => 1, out => 1} if not ref $normal->{'from'};
100 437 50       1168 $normal->{'from'}{'in'} = 0 unless exists $normal->{'from'}{'in'};
101 437 100       911 $normal->{'from'}{'out'} = 0 unless exists $normal->{'from'}{'out'};
102 437 50 33     2203 $normal->{'to'} = {} if not exists $normal->{'to'} or (exists $normal->{'to'} and not $normal->{'to'});
      33        
103 437 100       1630 $normal->{'to'} = {in => 1, out => 1} if not ref $normal->{'to'};
104 437 100       1017 $normal->{'to'}{'in'} = 0 unless exists $normal->{'to'}{'in'};
105 437 50       894 $normal->{'to'}{'out'} = 0 unless exists $normal->{'to'}{'out'};
106 437         2009 $self->{'convert'}{ $self->normalize_name( $space_name ) } = { from => $from_code, to => $to_code, normal => $normal };
107             }
108              
109             sub convert_to { # convert value tuple from this space into another
110 316     316 0 17553 my ($self, $space_name, $tuple) = @_;
111 316         759 $space_name = $self->normalize_name( $space_name );
112 316 50 33     769 return unless $self->is_value_tuple( $tuple ) and defined $space_name and $self->can_convert( $space_name );
      33        
113 316         1191 return $self->{'convert'}{ $space_name }{'to'}->( $tuple );
114             }
115             sub convert_from { # convert value tuple from another space into this
116 282     282 0 27063 my ($self, $space_name, $tuple) = @_;
117 282         646 $space_name = $self->normalize_name( $space_name );
118 282 50 33     1681 return unless ref $tuple eq 'ARRAY' and defined $space_name and $self->can_convert( $space_name );
      33        
119 282         1154 return $self->{'convert'}{ $space_name }{'from'}->( $tuple );
120             }
121             sub converter_normal_states {
122 353     353 0 729 my ($self, $direction, $space_name) = @_;
123 353         587 $space_name = $self->normalize_name( $space_name );
124 353 50 33     843 return unless $self->can_convert( $space_name )
      66        
      66        
125             and defined $direction and ($direction eq 'from' or $direction eq 'to');
126 353         468 return @{$self->{'convert'}{ $space_name }{'normal'}{$direction}}{'in', 'out'};
  353         1334  
127             }
128              
129             1;
130              
131             __END__