line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package GD::Icons; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $VERSION = '0.04'; |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# $Id: Icons.pm,v 1.8 2007/08/06 15:36:54 canaran Exp $ |
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
20793
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
37
|
|
8
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
31
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
658
|
use GD::Icons::Config; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
39
|
|
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
10
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
67
|
|
13
|
1
|
|
|
1
|
|
439
|
use GD; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
############### |
16
|
|
|
|
|
|
|
# CONSTRUCTOR # |
17
|
|
|
|
|
|
|
############### |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new { |
20
|
|
|
|
|
|
|
my ($class, %params) = @_; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $self = bless {}, $class; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
my $config_file = $params{config_file}; |
25
|
|
|
|
|
|
|
my $gd_icons_config = GD::Icons::Config->new($config_file); |
26
|
|
|
|
|
|
|
$self->config($gd_icons_config->config); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Assign alpha |
29
|
|
|
|
|
|
|
my $alpha = $params{alpha} ? $params{alpha} : 0; |
30
|
|
|
|
|
|
|
if ($alpha =~ /[^0-9]/ or $alpha > 127) { |
31
|
|
|
|
|
|
|
croak("alpha must be a value between 0 and 127!"); |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
$self->alpha($alpha); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Parse shapes keys |
36
|
|
|
|
|
|
|
my $shape_keys = |
37
|
|
|
|
|
|
|
$params{shape_keys} |
38
|
|
|
|
|
|
|
? $params{shape_keys} |
39
|
|
|
|
|
|
|
: [":default"]; |
40
|
|
|
|
|
|
|
$self->shape_keys($shape_keys); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
my $shape_values = |
43
|
|
|
|
|
|
|
$params{shape_values} |
44
|
|
|
|
|
|
|
? $params{shape_values} |
45
|
|
|
|
|
|
|
: $self->all_shapes; |
46
|
|
|
|
|
|
|
$self->shape_values($shape_values); |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# Parse color keys |
49
|
|
|
|
|
|
|
my $color_keys = |
50
|
|
|
|
|
|
|
$params{color_keys} |
51
|
|
|
|
|
|
|
? $params{color_keys} |
52
|
|
|
|
|
|
|
: [":default"]; |
53
|
|
|
|
|
|
|
$self->color_keys($color_keys); |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
my $color_values = |
56
|
|
|
|
|
|
|
$params{color_values} |
57
|
|
|
|
|
|
|
? $params{color_values} |
58
|
|
|
|
|
|
|
: $self->all_colors; |
59
|
|
|
|
|
|
|
$self->color_values($color_values); |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# Parse sval keys |
62
|
|
|
|
|
|
|
my $sval_keys = |
63
|
|
|
|
|
|
|
$params{sval_keys} |
64
|
|
|
|
|
|
|
? $params{sval_keys} |
65
|
|
|
|
|
|
|
: [":default"]; |
66
|
|
|
|
|
|
|
$self->sval_keys($sval_keys); |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
my $sval_values = |
69
|
|
|
|
|
|
|
$params{sval_values} |
70
|
|
|
|
|
|
|
? $params{sval_values} |
71
|
|
|
|
|
|
|
: [map { $_ / (@$sval_keys) * 100 } (1 .. @$sval_keys)]; # ratio only |
72
|
|
|
|
|
|
|
$self->sval_values($sval_values); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
my $icon_dir = $params{icon_dir} |
75
|
|
|
|
|
|
|
or croak("A icon_dir is required!"); |
76
|
|
|
|
|
|
|
$self->icon_dir($icon_dir); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
my $icon_prefix = $params{icon_prefix}; |
79
|
|
|
|
|
|
|
if (!defined $icon_prefix) { |
80
|
|
|
|
|
|
|
croak("A icon_prefix is required!"); |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
$self->icon_prefix($icon_prefix); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
return $self; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
################## |
88
|
|
|
|
|
|
|
# PUBLIC METHODS # |
89
|
|
|
|
|
|
|
################## |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# Function : Get method that ignores _* names |
92
|
|
|
|
|
|
|
# Arguments : None |
93
|
|
|
|
|
|
|
# Returns : \@all |
94
|
|
|
|
|
|
|
# Notes : None provided. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub all_colors { |
97
|
|
|
|
|
|
|
my ($self) = @_; |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
my $config = $self->config; |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
my @all; |
102
|
|
|
|
|
|
|
foreach (sort keys %{$config->{color}}) { |
103
|
|
|
|
|
|
|
push @all, $_ unless /^_/; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
return \@all; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# Function : Get method that ignores _* names |
110
|
|
|
|
|
|
|
# Arguments : None |
111
|
|
|
|
|
|
|
# Returns : \@all |
112
|
|
|
|
|
|
|
# Notes : None provided. |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub all_shapes { |
115
|
|
|
|
|
|
|
my ($self) = @_; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
my $config = $self->config; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
my @all; |
120
|
|
|
|
|
|
|
foreach (sort keys %{$config->{shape}}) { |
121
|
|
|
|
|
|
|
push @all, $_ unless /^_/; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
return \@all; |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# Function : Get/set method for icon location |
128
|
|
|
|
|
|
|
# Arguments : $shape_key, $color_key, $sval_key, $value |
129
|
|
|
|
|
|
|
# Returns : $value |
130
|
|
|
|
|
|
|
# Notes : None provided. |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub icon { |
133
|
|
|
|
|
|
|
my ($self, $shape_key, $color_key, $sval_key, $value) = @_; |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
$self->{icons}->{$shape_key}->{$color_key}->{$sval_key} = $value |
136
|
|
|
|
|
|
|
if @_ > 4; |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
return $self->{icons}->{$shape_key}->{$color_key}->{$sval_key}; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# Function : Make ... |
142
|
|
|
|
|
|
|
# Arguments : |
143
|
|
|
|
|
|
|
# Returns : |
144
|
|
|
|
|
|
|
# Notes : None provided. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub generate_icons { |
147
|
|
|
|
|
|
|
my ($self) = @_; |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
my $config = $self->config; |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
my $alpha = $self->alpha; |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
my @shape_keys = @{$self->shape_keys}; |
154
|
|
|
|
|
|
|
my @shape_values = @{$self->shape_values}; |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
my @color_keys = @{$self->color_keys}; |
157
|
|
|
|
|
|
|
my @color_values = @{$self->color_values}; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
my @sval_keys = @{$self->sval_keys}; |
160
|
|
|
|
|
|
|
my @sval_values = @{$self->sval_values}; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
my $icon_dir = $self->icon_dir; |
163
|
|
|
|
|
|
|
my $icon_prefix = $self->icon_prefix; |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
foreach my $shape_i (0 .. $#shape_keys) { |
166
|
|
|
|
|
|
|
foreach my $color_i (0 .. $#color_keys) { |
167
|
|
|
|
|
|
|
foreach my $sval_i (0 .. $#sval_keys) { |
168
|
|
|
|
|
|
|
my $shape = |
169
|
|
|
|
|
|
|
$config->{shape}->{$shape_values[$shape_i % @shape_values] |
170
|
|
|
|
|
|
|
}; # @shape_values here, not $#shape_values |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
my $color = |
173
|
|
|
|
|
|
|
$self->_resolve_color( |
174
|
|
|
|
|
|
|
$color_values[$color_i % @color_values]) |
175
|
|
|
|
|
|
|
; # @color_values here, not $#color_values |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
my $sval = $sval_values[$sval_i]; |
178
|
|
|
|
|
|
|
if (@sval_values > 1) { |
179
|
|
|
|
|
|
|
$color = $self->_blend_in_sval($color, $sval); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
my ($line_color) = $shape =~ /lc\[([^\[\]]+)\]/; |
183
|
|
|
|
|
|
|
if ($line_color eq ":fill") { |
184
|
|
|
|
|
|
|
$line_color = [@$color]; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
$line_color = $self->_resolve_color($line_color); |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
my ($line_thickness) = $shape =~ /lt\[(\d+)\]/; |
189
|
|
|
|
|
|
|
my ($side_length) = $shape =~ /sl\[(\d+)\]/; |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
my $image = new GD::Image($side_length, $side_length); |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
my $white_color = $image->colorAllocateAlpha(255, 255, 255, $alpha); |
194
|
|
|
|
|
|
|
my $fill_color = $image->colorAllocateAlpha(@$color, $alpha); |
195
|
|
|
|
|
|
|
my $draw_color = $image->colorAllocateAlpha(@$line_color, $alpha); |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
$image->transparent($white_color); |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
$image->setThickness($line_thickness); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
while ($shape =~ /\s*(py|fl|nm)\[([0-9, ]+|:auto)\]\s*/g) { |
202
|
|
|
|
|
|
|
my ($action, $values) = ($1, $2); |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
if ($action eq "py") { |
205
|
|
|
|
|
|
|
my @points = split(" ", $values); |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
foreach my $i (0 .. $#points - 1) { |
208
|
|
|
|
|
|
|
my ($x1, $y1) = split(",", $points[$i]); |
209
|
|
|
|
|
|
|
my ($x2, $y2) = split(",", $points[$i + 1]); |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
$image->line($x1, $y1, $x2, $y2, $draw_color); |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
elsif ($action eq "fl") { |
216
|
|
|
|
|
|
|
my ($x1, $y1) = split(",", $values); |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
$image->fill($x1, $y1, $fill_color); |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
elsif ($action eq "nm" && $values eq ":auto") { |
222
|
|
|
|
|
|
|
my ($number) = $shape_keys[$shape_i] =~ /:(\d+)/; |
223
|
|
|
|
|
|
|
if ($number && $number > 99) { |
224
|
|
|
|
|
|
|
$number = 'M'; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
if (!$number) { |
227
|
|
|
|
|
|
|
$number = 'U'; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
my $x = int(($side_length - 5 * length($number)) / 2) + 1; |
231
|
|
|
|
|
|
|
my $y = ($side_length - 8) / 2; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
$image->string(gdTinyFont, $x, $y, $number, $draw_color); |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
else { |
237
|
|
|
|
|
|
|
croak( |
238
|
|
|
|
|
|
|
"Unrecognized action ($action) in shapes file!"); |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
my $icon_file = |
243
|
|
|
|
|
|
|
qq[$icon_dir/${icon_prefix}-${shape_i}-${color_i}-${sval_i}.png]; |
244
|
|
|
|
|
|
|
my $icon_file_name = |
245
|
|
|
|
|
|
|
qq[${icon_prefix}-${shape_i}-${color_i}-${sval_i}.png]; |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
$self->icon( |
248
|
|
|
|
|
|
|
$shape_keys[$shape_i], $color_keys[$color_i], |
249
|
|
|
|
|
|
|
$sval_keys[$sval_i], $icon_file_name |
250
|
|
|
|
|
|
|
); |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
open(PNG, ">$icon_file") |
253
|
|
|
|
|
|
|
or croak("Cannot write file ($icon_file): $!"); |
254
|
|
|
|
|
|
|
binmode PNG; |
255
|
|
|
|
|
|
|
print PNG $image->png; |
256
|
|
|
|
|
|
|
close PNG; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
return 1; |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
################### |
266
|
|
|
|
|
|
|
# GET/SET METHODS # |
267
|
|
|
|
|
|
|
################### |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
sub alpha { |
270
|
|
|
|
|
|
|
my ($self, $value) = @_; |
271
|
|
|
|
|
|
|
$self->{alpha} = $value if @_ > 1; |
272
|
|
|
|
|
|
|
return $self->{alpha}; |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
sub color_keys { |
276
|
|
|
|
|
|
|
my ($self, $value) = @_; |
277
|
|
|
|
|
|
|
$self->{color_keys} = $value if @_ > 1; |
278
|
|
|
|
|
|
|
return $self->{color_keys}; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub color_values { |
282
|
|
|
|
|
|
|
my ($self, $value) = @_; |
283
|
|
|
|
|
|
|
$self->{color_values} = $value if @_ > 1; |
284
|
|
|
|
|
|
|
return $self->{color_values}; |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
sub config { |
288
|
|
|
|
|
|
|
my ($self, $value) = @_; |
289
|
|
|
|
|
|
|
$self->{config} = $value if @_ > 1; |
290
|
|
|
|
|
|
|
return $self->{config}; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub icon_dir { |
294
|
|
|
|
|
|
|
my ($self, $value) = @_; |
295
|
|
|
|
|
|
|
$self->{icon_dir} = $value if @_ > 1; |
296
|
|
|
|
|
|
|
return $self->{icon_dir}; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub icon_prefix { |
300
|
|
|
|
|
|
|
my ($self, $value) = @_; |
301
|
|
|
|
|
|
|
$self->{icon_prefix} = $value if @_ > 1; |
302
|
|
|
|
|
|
|
return $self->{icon_prefix}; |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub shape_keys { |
306
|
|
|
|
|
|
|
my ($self, $value) = @_; |
307
|
|
|
|
|
|
|
$self->{shape_keys} = $value if @_ > 1; |
308
|
|
|
|
|
|
|
return $self->{shape_keys}; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
sub shape_values { |
312
|
|
|
|
|
|
|
my ($self, $value) = @_; |
313
|
|
|
|
|
|
|
$self->{shape_values} = $value if @_ > 1; |
314
|
|
|
|
|
|
|
return $self->{shape_values}; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
sub sval_keys { |
318
|
|
|
|
|
|
|
my ($self, $value) = @_; |
319
|
|
|
|
|
|
|
$self->{sval_keys} = $value if @_ > 1; |
320
|
|
|
|
|
|
|
return $self->{sval_keys}; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
sub sval_values { |
324
|
|
|
|
|
|
|
my ($self, $value) = @_; |
325
|
|
|
|
|
|
|
$self->{sval_values} = $value if @_ > 1; |
326
|
|
|
|
|
|
|
return $self->{sval_values}; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
########################### |
330
|
|
|
|
|
|
|
# PRIVATE/UTILITY METHODS # |
331
|
|
|
|
|
|
|
########################### |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
# Function : Apply an S Value to color in RGB |
334
|
|
|
|
|
|
|
# Arguments : (\@color, $sval_percent) |
335
|
|
|
|
|
|
|
# Returns : \@new_color |
336
|
|
|
|
|
|
|
# Notes : This is a private method. |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
sub _blend_in_sval { |
339
|
|
|
|
|
|
|
my ($self, $color, $sval_percent) = @_; |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
my ($rval, $gval, $bval) = @$color; |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
my ($hval, $sval, $vval) = $self->_RGBtoHSV($rval, $gval, $bval); |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
$sval = int($sval * $sval_percent / 100); |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
my @new_color = $self->_HSVtoRGB($hval, $sval, $vval); |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
return \@new_color; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# Function : Determine the type of color designation |
353
|
|
|
|
|
|
|
# Arguments : $color |
354
|
|
|
|
|
|
|
# Returns : $rgb |
355
|
|
|
|
|
|
|
# Notes : This is a private method. |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
sub _resolve_color { |
358
|
|
|
|
|
|
|
my ($self, $color) = @_; |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
my $rgb; |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
if (ref $color) { |
363
|
|
|
|
|
|
|
$rgb = $color; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
elsif ($color =~ /^#/) { |
367
|
|
|
|
|
|
|
$rgb = $self->_hex2rgb($color); |
368
|
|
|
|
|
|
|
} |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
else { |
371
|
|
|
|
|
|
|
my $hex = $self->config->{color}->{$color}; |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
$rgb = $self->_hex2rgb($hex); |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
croak("Cannot resolve color ($color)!") unless $rgb; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
return $rgb; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# Function : Convert hex to rgb |
382
|
|
|
|
|
|
|
# Arguments : $hex |
383
|
|
|
|
|
|
|
# Returns : \@rgb |
384
|
|
|
|
|
|
|
# Notes : This is a private method. |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub _hex2rgb { |
387
|
|
|
|
|
|
|
my ($self, $hex) = @_; |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
$hex =~ s/^#//; |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
my @rgb = map { hex(substr($hex, $_, 2)); } qw[0 2 4]; |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
return \@rgb; |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
################################################## |
397
|
|
|
|
|
|
|
# _HSVtoRGB and _RGBtoHSV subs incorporated from # |
398
|
|
|
|
|
|
|
# GD::Simple module written by Lincoln Stein # |
399
|
|
|
|
|
|
|
################################################## |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# ($red,$green,$blue) = GD::Simple->HSVtoRGB($hue,$saturation,$value) |
402
|
|
|
|
|
|
|
# |
403
|
|
|
|
|
|
|
# Convert a Hue/Saturation/Value (HSV) color into an RGB triple. The |
404
|
|
|
|
|
|
|
# hue, saturation and value are integers from 0 to 255. |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
sub _HSVtoRGB { |
407
|
|
|
|
|
|
|
my $self = shift; |
408
|
|
|
|
|
|
|
@_ == 3 |
409
|
|
|
|
|
|
|
or croak "Usage: _HSVtoRGB(\$hue,\$saturation,\$value)"; |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
my ($h, $s, $v) = @_; |
412
|
|
|
|
|
|
|
my ($r, $g, $b, $i, $f, $p, $q, $t); |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
if ($s == 0) { |
415
|
|
|
|
|
|
|
## achromatic (grey) |
416
|
|
|
|
|
|
|
return ($v, $v, $v); |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
$h %= 255; |
419
|
|
|
|
|
|
|
$s /= 255; ## scale saturation from 0.0-1.0 |
420
|
|
|
|
|
|
|
$h /= 255; ## scale hue from 0 to 1.0 |
421
|
|
|
|
|
|
|
$h *= 360; ## and now scale it to 0 to 360 |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
$h /= 60; ## sector 0 to 5 |
424
|
|
|
|
|
|
|
$i = $h % 6; |
425
|
|
|
|
|
|
|
$f = $h - $i; ## factorial part of h |
426
|
|
|
|
|
|
|
$p = $v * (1 - $s); |
427
|
|
|
|
|
|
|
$q = $v * (1 - $s * $f); |
428
|
|
|
|
|
|
|
$t = $v * (1 - $s * (1 - $f)); |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
if ($i < 1) { |
431
|
|
|
|
|
|
|
$r = $v; |
432
|
|
|
|
|
|
|
$g = $t; |
433
|
|
|
|
|
|
|
$b = $p; |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
elsif ($i < 2) { |
436
|
|
|
|
|
|
|
$r = $q; |
437
|
|
|
|
|
|
|
$g = $v; |
438
|
|
|
|
|
|
|
$b = $p; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
elsif ($i < 3) { |
441
|
|
|
|
|
|
|
$r = $p; |
442
|
|
|
|
|
|
|
$g = $v; |
443
|
|
|
|
|
|
|
$b = $t; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
elsif ($i < 4) { |
446
|
|
|
|
|
|
|
$r = $p; |
447
|
|
|
|
|
|
|
$g = $q; |
448
|
|
|
|
|
|
|
$b = $v; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
elsif ($i < 5) { |
451
|
|
|
|
|
|
|
$r = $t; |
452
|
|
|
|
|
|
|
$g = $p; |
453
|
|
|
|
|
|
|
$b = $v; |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
else { |
456
|
|
|
|
|
|
|
$r = $v; |
457
|
|
|
|
|
|
|
$g = $p; |
458
|
|
|
|
|
|
|
$b = $q; |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
return (int($r + 0.5), int($g + 0.5), int($b + 0.5)); |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
# ($hue,$saturation,$value) = GD::Simple->RGBtoHSV($hue,$saturation,$value) |
464
|
|
|
|
|
|
|
# |
465
|
|
|
|
|
|
|
# Convert a Red/Green/Blue (RGB) value into a Hue/Saturation/Value (HSV) |
466
|
|
|
|
|
|
|
# triple. The hue, saturation and value are integers from 0 to 255. |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
sub _RGBtoHSV { |
469
|
|
|
|
|
|
|
my $self = shift; |
470
|
|
|
|
|
|
|
my ($r, $g, $bl) = @_; |
471
|
|
|
|
|
|
|
my ($min, undef, $max) = sort { $a <=> $b } ($r, $g, $bl); |
472
|
|
|
|
|
|
|
return (0, 0, 0) unless $max > 0; |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
my $v = $max; |
475
|
|
|
|
|
|
|
my $s = 255 * ($max - $min) / $max; |
476
|
|
|
|
|
|
|
my $h; |
477
|
|
|
|
|
|
|
my $range = $max - $min; |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
if ($range == 0) { # all colors are equal, so monochrome |
480
|
|
|
|
|
|
|
return (0, 0, $max); |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
if ($max == $r) { |
484
|
|
|
|
|
|
|
$h = 60 * ($g - $bl) / $range; |
485
|
|
|
|
|
|
|
} |
486
|
|
|
|
|
|
|
elsif ($max == $g) { |
487
|
|
|
|
|
|
|
$h = 60 * ($bl - $r) / $range + 120; |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
else { |
490
|
|
|
|
|
|
|
$h = 60 * ($r - $g) / $range + 240; |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
$h = int($h * 255 / 360 + 0.5); |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
return ($h, $s, $v); |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
1; |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
__END__ |