File Coverage

blib/lib/Convert/Color/XTerm.pm
Criterion Covered Total %
statement 53 56 94.6
branch 17 24 70.8
condition 1 3 33.3
subroutine 8 8 100.0
pod 2 2 100.0
total 81 93 87.1


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2009-2021 -- leonerd@leonerd.org.uk
5              
6             package Convert::Color::XTerm 0.06;
7              
8 2     2   1325 use v5.14;
  2         14  
9 2     2   11 use warnings;
  2         4  
  2         58  
10 2     2   11 use base qw( Convert::Color::RGB8 );
  2         3  
  2         1097  
11              
12             __PACKAGE__->register_color_space( 'xterm' );
13              
14 2     2   51402 use Carp;
  2         6  
  2         1882  
15              
16             =head1 NAME
17              
18             C - indexed colors used by XTerm
19              
20             =head1 SYNOPSIS
21              
22             Directly:
23              
24             use Convert::Color::XTerm;
25              
26             my $red = Convert::Color::XTerm->new( 1 );
27              
28             Via L:
29              
30             use Convert::Color;
31              
32             my $cyan = Convert::Color->new( 'xterm:14' );
33              
34             =head1 DESCRIPTION
35              
36             This subclass of L provides lookup of the colors that
37             F uses by default. Note that the module is not intelligent enough to
38             actually parse the XTerm configuration on a machine, nor to query a running
39             terminal for its actual colors. It simply implements the colors that are
40             present as defaults in the XTerm source code.
41              
42             It implements the complete 256-color model in XTerm. This range consists of:
43              
44             =over 4
45              
46             =item *
47              
48             0-7: The basic VGA colors, dark intensity. 7 is a "dark" white, i.e. a light
49             grey.
50              
51             =item *
52              
53             8-15: The basic VGA colors, light intensity. 8 represents a "light" black,
54             i.e. a dark grey.
55              
56             =item *
57              
58             16-231: A 6x6x6 RGB color cube.
59              
60             I This can also be specified as C where
61             each of R, G and B can be C<0> to C<5>, or C<0%> to C<100%>.
62              
63             =item *
64              
65             232-255: 24 greyscale ramp.
66              
67             I This can also be specified as C, where
68             GREY is C<0> to C<23>, or C<0%> to C<100%>.
69              
70             =back
71              
72             =cut
73              
74             my @color;
75              
76             sub _init_colors
77             {
78             # The first 16 colors are dark and light versions of the basic 8 VGA colors.
79             # XTerm itself pulls these from the X11 database, except for light blue.
80             # These color names from xterm's charproc.c
81              
82 1     1   2 my @colnames;
83              
84 1 50       3 if( eval { require Convert::Color::X11; Convert::Color::X11->colors } ) {
  1         523  
  1         881  
85 0         0 @colnames = (qw(
86             x11:black x11:red3 x11:green3 x11:yellow3
87             x11:blue2 x11:magenta3 x11:cyan3 x11:gray90
88             x11:gray50 x11:red x11:green x11:yellow
89             rgb8:5C5CFF x11:magenta x11:cyan x11:white
90             ));
91             }
92             else {
93 1         143 @colnames = (qw(
94             rgb8:000000 rgb8:cd0000 rgb8:00cd00 rgb8:cdcd00
95             rgb8:0000ee rgb8:cd00cd rgb8:00cdcd rgb8:e5e5e5
96             rgb8:7f7f7f rgb8:ff0000 rgb8:00ff00 rgb8:ffff00
97             rgb8:5c5cff rgb8:ff00ff rgb8:00ffff rgb8:ffffff
98             ));
99             }
100              
101 1         5 foreach my $index ( 0 .. $#colnames )
102             {
103 16         159 my $c_tmp = Convert::Color->new( $colnames[$index] );
104 16         10940 $color[$index] = __PACKAGE__->SUPER::new( $c_tmp->as_rgb8->rgb8 );
105 16         696 $color[$index]->[3] = $index;
106             }
107              
108             # These descriptions and formulae from xterm's 256colres.pl
109              
110             # Next is a 6x6x6 color cube, with an attempt at a gamma correction
111 1         12 foreach my $red ( 0 .. 5 ) {
112 6         12 foreach my $green ( 0 .. 5 ) {
113 36         58 foreach my $blue ( 0 .. 5 ) {
114 216         348 my $index = 16 + ($red*36) + ($green*6) + $blue;
115              
116             $color[$index] = __PACKAGE__->SUPER::new(
117 216 100       328 map { $_ ? $_*40 + 55 : 0 } ( $red, $green, $blue )
  648         1267  
118             );
119 216         4222 $color[$index]->[3] = $index;
120             }
121             }
122             }
123              
124             # Finally a 24-level greyscale ramp
125 1         4 foreach my $grey ( 0 .. 23 ) {
126 24         35 my $index = 232 + $grey;
127 24         84 my $whiteness = $grey*10 + 8;
128              
129 24         55 $color[$index] = __PACKAGE__->SUPER::new( $whiteness, $whiteness, $whiteness );
130 24         461 $color[$index]->[3] = $index;
131             }
132             }
133              
134             __PACKAGE__->register_palette(
135             enumerate_once => sub {
136             @color or _init_colors;
137             @color
138             },
139             );
140              
141             =head1 CONSTRUCTOR
142              
143             =cut
144              
145             =head2 new
146              
147             $color = Convert::Color::XTerm->new( $index )
148              
149             Returns a new object to represent the color at that index.
150              
151             =cut
152              
153             sub _index_or_percent
154             {
155 8     8   37 my ( $name, $val, $max ) = @_;
156              
157 8 100       36 if( $val =~ m/^(\d+)%$/ ) {
    50          
158 4 50       19 $1 <= 100 or croak "Convert::Color::XTerm: Invalid percentage for $name: '$val'";
159 4         15 return int( $max * $1 / 100 );
160             }
161             elsif( $val =~ m/^(\d+)$/ ) {
162 4 50       14 $1 <= $max or croak "Convert::Color::XTerm: Invalid index for $name: '$val'";
163 4         12 return $1;
164             }
165             else {
166 0         0 croak "Convert::Color::XTerm: Invalid value for $name: '$val'";
167             }
168             }
169              
170             sub new
171             {
172 6     6 1 621 my $class = shift;
173 6 50       26 @_ == 1 or
174             croak "usage: Convert::Color::XTerm->new( INDEX )";
175              
176 6 100       20 @color or _init_colors;
177              
178 6 100       54 if( $_[0] =~ m/^grey\((.*)\)$/ ) {
    100          
    50          
179 2         8 my $grey = _index_or_percent( grey => $1, 23 );
180 2         10 return $color[232 + $grey];
181             }
182             elsif( $_[0] =~ m/^rgb\((.*),(.*),(.*)\)$/ ) {
183 2         7 my $red = _index_or_percent( red => $1, 5 );
184 2         7 my $green = _index_or_percent( green => $2, 5 );
185 2         6 my $blue = _index_or_percent( blue => $3, 5 );
186 2         11 return $color[16 + 36*$red + 6*$green + $blue];
187             }
188             elsif( $_[0] =~ m/^(\d+)$/ ) {
189 2         8 my $index = $1;
190              
191 2 50 33     30 $index >= 0 and $index < 256 or
192             croak "No such XTerm color at index '$index'";
193              
194 2         17 return $color[$index];
195             }
196             else {
197 0         0 croak "Convert::Color::XTerm: Expected index, grey() or rgb() specification, got '$_[0]'";
198             }
199             }
200              
201             =head1 METHODS
202              
203             =cut
204              
205             =head2 index
206              
207             $index = $color->index
208              
209             The index of the XTerm color.
210              
211             =cut
212              
213             sub index
214             {
215 7     7 1 24912 my $self = shift;
216 7         34 return $self->[3];
217             }
218              
219             =head1 SEE ALSO
220              
221             =over 4
222              
223             =item *
224              
225             L - color space conversions
226              
227             =back
228              
229             =head1 AUTHOR
230              
231             Paul Evans
232              
233             =cut
234              
235             0x55AA;