line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Graph::Chart; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
########################################################### |
4
|
|
|
|
|
|
|
# RPN package with DICT |
5
|
|
|
|
|
|
|
# Gnu GPL2 license |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# Fabrice Dulaunoy |
8
|
|
|
|
|
|
|
########################################################### |
9
|
|
|
|
|
|
|
# ChangeLog: |
10
|
|
|
|
|
|
|
# |
11
|
|
|
|
|
|
|
########################################################### |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 SYNOPSIS |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=over 3 |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
B |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
A Wrapper around GD to easyly graph chart |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=back |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=cut |
24
|
|
|
|
|
|
|
|
25
|
1
|
|
|
1
|
|
7664
|
use strict; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
62
|
|
26
|
|
|
|
|
|
|
|
27
|
1
|
|
|
1
|
|
4
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
99
|
|
28
|
1
|
|
|
1
|
|
2135
|
use Data::Dumper; |
|
1
|
|
|
|
|
17075
|
|
|
1
|
|
|
|
|
88
|
|
29
|
|
|
|
|
|
|
|
30
|
1
|
|
|
1
|
|
1248
|
use Clone qw(clone); |
|
1
|
|
|
|
|
26741
|
|
|
1
|
|
|
|
|
132
|
|
31
|
1
|
|
|
1
|
|
4594
|
use Compress::Zlib; |
|
1
|
|
|
|
|
171918
|
|
|
1
|
|
|
|
|
384
|
|
32
|
1
|
|
|
1
|
|
2253
|
use Data::Serializer; |
|
1
|
|
|
|
|
3777
|
|
|
1
|
|
|
|
|
45
|
|
33
|
|
|
|
|
|
|
# use fields qw{ size }; |
34
|
1
|
|
|
1
|
|
10599
|
use GD; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
use GD::Polyline; |
36
|
|
|
|
|
|
|
use List::Util qw[min max sum]; |
37
|
|
|
|
|
|
|
use POSIX; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
use vars qw( $VERSION ); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
use constant PI => 4 * atan2( 1, 1 ); |
42
|
|
|
|
|
|
|
# use constant NEPER => 2.718281828459045; |
43
|
|
|
|
|
|
|
# use constant LOG10 => 2.30258509299405; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
$VERSION = '0.65'; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
########################################################################### |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
########################################################################### |
50
|
|
|
|
|
|
|
### class creator ### |
51
|
|
|
|
|
|
|
########################################################################### |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head1 METHODS |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
OO interface |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head2 new |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=over |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
Create a new Chart |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=over |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
my $graph = Graph::Chart->new( \%options ); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
%options could be defined like this: |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
size => [ W, H ] # the size ( Width, Height ) in pixel of the real graph ( without border ) |
72
|
|
|
|
|
|
|
bg_color => '0xfffff0' # an ARRAY with all possible section |
73
|
|
|
|
|
|
|
frame => { color => '0xff00ff', thickness => 1 }, # an optional frame around the real chart |
74
|
|
|
|
|
|
|
border => [ 150, 80, 100, 100 ], # extra space around the graph in pixel [ left side, right side , top side, bottom side ]" |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
grid => { # a grid over the graph |
77
|
|
|
|
|
|
|
debord => [ 5, 20, 10, 30 ], # some extension of the grid size ( same order as border ) B |
78
|
|
|
|
|
|
|
x => { # vertical grid |
79
|
|
|
|
|
|
|
color => '0xff00ff' # color of the grid ( hex HTML value ) |
80
|
|
|
|
|
|
|
number => 5, # number of grid division |
81
|
|
|
|
|
|
|
thickness => 1, # size of the division's line ( default = 1 ) |
82
|
|
|
|
|
|
|
type => log, # create a log graduation (only one modules). If missing, normal graduation. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
label => { # an optional label on the left side |
85
|
|
|
|
|
|
|
font => '/usr/lib/cinelerra/fonts/trebucbi.ttf', # a TrueType font to use |
86
|
|
|
|
|
|
|
color => '0xff0000', # the color of the label |
87
|
|
|
|
|
|
|
size => 10, # the size of the font |
88
|
|
|
|
|
|
|
text => [ 'toto', undef, 'truc', 'bazar', 122 ], # the text to render ( a undef element is not ploted, this allow to skip some label ) |
89
|
|
|
|
|
|
|
space => 80, # an extra space between the division and the text |
90
|
|
|
|
|
|
|
align => 'right', # align the text on the right ( = aligned on the division ) |
91
|
|
|
|
|
|
|
rotation => 30, # a rotation of the text in degree |
92
|
|
|
|
|
|
|
kerning_correction => 0.85, # a kerning correcting to correct align of text when rotated ( default 0.91 ) |
93
|
|
|
|
|
|
|
surround => { color => '0x0000ff' , thickness => 1 }, # create a frame around the text with the specified color and thickness |
94
|
|
|
|
|
|
|
}, |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
x_up => { # vertical grid on the upper half of the graph ( to use with up_ graph) |
97
|
|
|
|
|
|
|
color => '0xff00ff' # color of the grid ( hex HTML value ) |
98
|
|
|
|
|
|
|
number => 5, # number of grid division |
99
|
|
|
|
|
|
|
thickness => 1, # size of the division's line ( default = 1 ) |
100
|
|
|
|
|
|
|
type => log, # create a log graduation (only one modules). If missing, normal graduation. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
label => { # an optional label on the left side |
103
|
|
|
|
|
|
|
font => '/usr/lib/cinelerra/fonts/trebucbi.ttf', # a TrueType font to use |
104
|
|
|
|
|
|
|
color => '0xff0000', # the color of the label |
105
|
|
|
|
|
|
|
size => 10, # the size of the font |
106
|
|
|
|
|
|
|
text => [ 'toto', undef, 'truc', 'bazar', 122 ], # the text to render ( a undef element is not ploted, this allow to skip some label ) |
107
|
|
|
|
|
|
|
space => 80, # an extra space between the division and the text |
108
|
|
|
|
|
|
|
align => 'right', # align the text on the right ( = aligned on the division ) |
109
|
|
|
|
|
|
|
rotation => 30, # a rotation of the text in degree |
110
|
|
|
|
|
|
|
kerning_correction => 0.85, # a kerning correcting to correct align of text when rotated ( default 0.91 ) |
111
|
|
|
|
|
|
|
surround => { color => '0x0000ff' , thickness => 1 }, # create a frame around the text with the specified color and thickness |
112
|
|
|
|
|
|
|
}, |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
x_down => { # vertical grid on the lower half of the graph ( to use with down_ graph) |
115
|
|
|
|
|
|
|
color => '0xff00ff' # color of the grid ( hex HTML value ) |
116
|
|
|
|
|
|
|
number => 5, # number of grid division |
117
|
|
|
|
|
|
|
thickness => 1, # size of the division's line ( default = 1 ) |
118
|
|
|
|
|
|
|
type => log, # create a log graduation (only one modules). If missing, normal graduation. |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
label => { # an optional label on the left side |
121
|
|
|
|
|
|
|
font => '/usr/lib/cinelerra/fonts/trebucbi.ttf', # a TrueType font to use |
122
|
|
|
|
|
|
|
color => '0xff0000', # the color of the label |
123
|
|
|
|
|
|
|
size => 10, # the size of the font |
124
|
|
|
|
|
|
|
text => [ 'toto', undef, 'truc', 'bazar', 122 ], # the text to render ( a undef element is not ploted, this allow to skip some label ) |
125
|
|
|
|
|
|
|
space => 80, # an extra space between the division and the text |
126
|
|
|
|
|
|
|
align => 'right', # align the text on the right ( = aligned on the division ) |
127
|
|
|
|
|
|
|
rotation => 30, # a rotation of the text in degree |
128
|
|
|
|
|
|
|
kerning_correction => 0.85, # a kerning correcting to correct align of text when rotated ( default 0.91 ) |
129
|
|
|
|
|
|
|
surround => { color => '0x0000ff' , thickness => 1 }, # create a frame around the text with the specified color and thickness |
130
|
|
|
|
|
|
|
}, |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
label2 => { # an optional label on the right side |
133
|
|
|
|
|
|
|
font => '/usr/lib/cinelerra/fonts/lucon.ttf', # a TrueType font to use |
134
|
|
|
|
|
|
|
color => '0xff0000', # the color of the label |
135
|
|
|
|
|
|
|
size => 10, # the size of the font |
136
|
|
|
|
|
|
|
text => [ 'toto', undef, 'truc', 'bazar', 122 ],, # the text to render ( a undef element is not ploted, this allow to skip some label ) |
137
|
|
|
|
|
|
|
space => 50, # an extra space between the division and the text |
138
|
|
|
|
|
|
|
align => 'right', # align the text on the right ( not really useful ) |
139
|
|
|
|
|
|
|
rotation => -30, # an rotation of the text in degree |
140
|
|
|
|
|
|
|
kerning_correction => 0.85, # a kerning correcting to correct align of text when rotated ( default 0.91 ) |
141
|
|
|
|
|
|
|
surround => { color => '0x0000ff' , thickness => 1 }, # create a frame around the text with the specified color and thickness |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
}, |
144
|
|
|
|
|
|
|
}, " |
145
|
|
|
|
|
|
|
y => { # horizontal grid |
146
|
|
|
|
|
|
|
color => '0x00fff0',' # color of the grid ( hex HTML value ) |
147
|
|
|
|
|
|
|
number => 8, # number of grid division |
148
|
|
|
|
|
|
|
thickness => 1, # size of the division's line ( default = 1 ) |
149
|
|
|
|
|
|
|
label => { # an optional label on the bottom side |
150
|
|
|
|
|
|
|
font => '/usr/lib/cinelerra/fonts/trebuc.ttf', # a TrueType font to use |
151
|
|
|
|
|
|
|
color => '0xff0000',', # the color of the label |
152
|
|
|
|
|
|
|
size => 12, # the size of the font |
153
|
|
|
|
|
|
|
text => [ 100, undef, '20', undef, 1585, undef, 555 ], # the text to render ( a undef element is not ploted, this allow to skip some label ) |
154
|
|
|
|
|
|
|
# space => 10, # an extra space between the division and the text |
155
|
|
|
|
|
|
|
rotation => 45, # an rotation of the text in degree |
156
|
|
|
|
|
|
|
kerning_correction => 0.85, # a kerning correcting to correct align of text when rotated ( default 0.91 ) |
157
|
|
|
|
|
|
|
surround => { color => '0x0000ff' , thickness => 1 }, # create a frame around the text with the specified color and thickness |
158
|
|
|
|
|
|
|
}, |
159
|
|
|
|
|
|
|
# label2 => { # an optional label on the top side |
160
|
|
|
|
|
|
|
# font => '/usr/lib/cinelerra/fonts/trebuc.ttf', # a TrueType font to use |
161
|
|
|
|
|
|
|
color => '0xff0000',', # the color of the label |
162
|
|
|
|
|
|
|
size => 12, # the size of the font |
163
|
|
|
|
|
|
|
text => [ 100, undef, '20', undef, 1585, undef, 555 ], # the text to render ( a undef element is not ploted, this allow to skip some label ) |
164
|
|
|
|
|
|
|
# space => 10, # an extra space between the division and the text |
165
|
|
|
|
|
|
|
rotation => 45, # an rotation of the text in degree |
166
|
|
|
|
|
|
|
kerning_correction => 0.85, # a kerning correcting to correct align of text when rotated ( default 0.91 ) |
167
|
|
|
|
|
|
|
surround => { color => '0x0000ff' , thickness => 1 }, # create a frame around the text with the specified color and thickness |
168
|
|
|
|
|
|
|
# } |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
reticle => { # when the Chart's type is of any circular shape, create polar division |
173
|
|
|
|
|
|
|
debord => 30, # the extra debord of the division |
174
|
|
|
|
|
|
|
color => '0xff0000', # the color of the division |
175
|
|
|
|
|
|
|
number => 10, # the number of division |
176
|
|
|
|
|
|
|
label_middle => { # the label to write between 2 division |
177
|
|
|
|
|
|
|
font => '/usr/lib/cinelerra/fonts/lucon.ttf', # a TrueType font to use |
178
|
|
|
|
|
|
|
kerning_correction => 0.85, # a kerning correcting to correct align of text when rotated ( default 0.91 ) |
179
|
|
|
|
|
|
|
color => '0xff0000', # the text color |
180
|
|
|
|
|
|
|
size => 10, # the font size to use |
181
|
|
|
|
|
|
|
# space => 10, # an extra space between the division and the text |
182
|
|
|
|
|
|
|
# rotate => 'follow', # rotate the text to be following the division direction |
183
|
|
|
|
|
|
|
rotate => 'perpendicular', # rotate the the to be perpendicular to the division |
184
|
|
|
|
|
|
|
# if missing write the text without rotation |
185
|
|
|
|
|
|
|
text => [700031220,45,90,135,180,225,270,31500 , 1 ,2], # the text to render ( a undef element is not ploted, this allow to skip some label ) |
186
|
|
|
|
|
|
|
}, |
187
|
|
|
|
|
|
|
# label => { # the label to write at the division |
188
|
|
|
|
|
|
|
font => '/usr/lib/cinelerra/fonts/lucon.ttf', # a TrueType font to use |
189
|
|
|
|
|
|
|
kerning_correction => 0.85, # a kerning correcting to correct align of text when rotated ( default 0.91 ) |
190
|
|
|
|
|
|
|
color => '0xff0000', # the text color |
191
|
|
|
|
|
|
|
size => 10, # the font size to use |
192
|
|
|
|
|
|
|
# space => 10, # an extra space between the division and the text |
193
|
|
|
|
|
|
|
# rotate => 'follow', # rotate the text to be following the division direction |
194
|
|
|
|
|
|
|
rotate => 'perpendicular', # rotate the the to be perpendicular to the division |
195
|
|
|
|
|
|
|
# if missing write the text without rotation |
196
|
|
|
|
|
|
|
text => [700031220,45,90,135,180,225,270,31500 , 1 ,2], # the text to render ( a undef element is not ploted, this allow to skip some label ) |
197
|
|
|
|
|
|
|
# }, |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
overlay=> { # add an overlay to the graph (useful to show an alert period ) |
200
|
|
|
|
|
|
|
layer => 10, # the layer where the data is plotted ( the lowest number is the deepest layer ) If missing, the layer is created by call order of the method data |
201
|
|
|
|
|
|
|
set => \@alarm, # a array ref with the data ( the number of dot plotted is the number W provided by the size parameter/method |
202
|
|
|
|
|
|
|
type => 'pie', # the type of graph ( dot, line, bar, up_dot, up_bar, up_line , down_dot,down_line, down_bar, pie, target, radial ) |
203
|
|
|
|
|
|
|
color => '0xFFD2D2', # color of the plotted element |
204
|
|
|
|
|
|
|
type => 'pie', # if missing normal overlay are used, if present use a polar structure ( data are in the range of 0 to 360 ° ) |
205
|
|
|
|
|
|
|
merge => 1, # if present and not = 0 all overlay are overwrited by the overlay from a higer layer |
206
|
|
|
|
|
|
|
opacity => 100, # when merge is missing, the overlay % of opacity copied on the chart |
207
|
|
|
|
|
|
|
debord => 50, # the debord of the overlay. if missing use the full graph height and in polar ( pie ) use the smallest vertical border ( top or bottom ) |
208
|
|
|
|
|
|
|
}, |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
glyph => { # add some ornament on the graph like line, text or polygon |
211
|
|
|
|
|
|
|
x => $graph->{x}{min}+200, # the origin of the glyph, all other position are relative to this origin |
212
|
|
|
|
|
|
|
y => $graph->{x}{max} , # either in pixel x =>0 , y=> 0 = corner lower left |
213
|
|
|
|
|
|
|
# see the active method |
214
|
|
|
|
|
|
|
type => 'filled', # type of glyph ( missing = open polygyn, 'filled' = filled polygon, 'text' = text ) |
215
|
|
|
|
|
|
|
color => '0x00FFff', # color of the glyph |
216
|
|
|
|
|
|
|
data => [ # if one of the polygon type, the data is a set of point to plot ( value relative to the origin ) |
217
|
|
|
|
|
|
|
[ 0, 0 ], |
218
|
|
|
|
|
|
|
[ 8, 10 ], |
219
|
|
|
|
|
|
|
[ 0, 10 ], |
220
|
|
|
|
|
|
|
[ 0, 10 + 20 ], |
221
|
|
|
|
|
|
|
[ 0, 10 ], |
222
|
|
|
|
|
|
|
[ -8, 10 ], |
223
|
|
|
|
|
|
|
[ 0, 0 ] |
224
|
|
|
|
|
|
|
], |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
glyph => { |
227
|
|
|
|
|
|
|
x => 100, |
228
|
|
|
|
|
|
|
y => 'active_max', |
229
|
|
|
|
|
|
|
type => 'text', |
230
|
|
|
|
|
|
|
color => '0xff0000', |
231
|
|
|
|
|
|
|
size => 12, # if the glyph's type is 'text', this is the font size |
232
|
|
|
|
|
|
|
font => '/usr/lib/cinelerra/fonts/lucon.ttf', # the TrueType font to use |
233
|
|
|
|
|
|
|
data => [ # the data set contain an array with all the text to plot followed by the relative position + the optional rotation |
234
|
|
|
|
|
|
|
[ 'hello world', 0, 0, 30 ], # |
235
|
|
|
|
|
|
|
[ 'hello universe', 100, 0, 0 ], |
236
|
|
|
|
|
|
|
], |
237
|
|
|
|
|
|
|
}, |
238
|
|
|
|
|
|
|
}, |
239
|
|
|
|
|
|
|
}, |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
all these parameters are optional except the size |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
my $a = B->new( size => [ 800,400 ] |
244
|
|
|
|
|
|
|
); |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=back |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=back |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=cut |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub new |
253
|
|
|
|
|
|
|
{ |
254
|
|
|
|
|
|
|
my ( $class ) = shift; |
255
|
|
|
|
|
|
|
# no strict "refs"; |
256
|
|
|
|
|
|
|
# my $fields_ref = \%{ "${class}::FIELDS" }; |
257
|
|
|
|
|
|
|
# my $self = $fields_ref; |
258
|
|
|
|
|
|
|
my $self; |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
$self->{ size } = { @_ }->{ size }; |
261
|
|
|
|
|
|
|
$self->{ bg_color } = _re_color( { @_ }->{ bg_color }, 'ffffffff' ); |
262
|
|
|
|
|
|
|
if ( exists { @_ }->{ frame } ) |
263
|
|
|
|
|
|
|
{ |
264
|
|
|
|
|
|
|
$self->{ frame } = { @_ }->{ frame }; |
265
|
|
|
|
|
|
|
if ( exists { @_ }->{ frame }{ color } ) |
266
|
|
|
|
|
|
|
{ |
267
|
|
|
|
|
|
|
$self->{ frame }{ color } = _re_color( { @_ }->{ frame }{ color }, '00000000' ); |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
$self->{ frame }{ thickness } = { @_ }->{ frame }{ thickness } || 1; |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
$self->{ border } = { @_ }->{ border } || [ 0, 0, 0, 0 ]; |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
if ( exists { @_ }->{ grid } ) |
275
|
|
|
|
|
|
|
{ |
276
|
|
|
|
|
|
|
$self->{ grid } = { @_ }->{ grid }; |
277
|
|
|
|
|
|
|
unless ( exists $self->{ grid }->{ debord } ) |
278
|
|
|
|
|
|
|
{ |
279
|
|
|
|
|
|
|
$self->{ grid }->{ debord } = [ 0, 0, 0, 0 ]; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
if ( exists { @_ }->{ reticle } ) |
283
|
|
|
|
|
|
|
{ |
284
|
|
|
|
|
|
|
$self->{ reticle } = { @_ }->{ reticle }; |
285
|
|
|
|
|
|
|
if ( !exists { @_ }->{ reticle }->{ debord } ) |
286
|
|
|
|
|
|
|
{ |
287
|
|
|
|
|
|
|
$self->{ reticle }{ debord } = 0; |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
if ( !exists $self->{ reticle }{ number } ) |
290
|
|
|
|
|
|
|
{ |
291
|
|
|
|
|
|
|
$self->{ reticle }->{ number } = 2; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
if ( exists { @_ }->{ overlay } ) |
296
|
|
|
|
|
|
|
{ |
297
|
|
|
|
|
|
|
if ( exists { @_ }->{ overlay }{ layer } ) |
298
|
|
|
|
|
|
|
{ |
299
|
|
|
|
|
|
|
$self->{ overlay }[ { @_ }->{ overlay }{ layer } ] = clone( { @_ }->{ overlay } ); |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
else |
302
|
|
|
|
|
|
|
{ |
303
|
|
|
|
|
|
|
push @{ $self->{ overlay } }, clone( { @_ }->{ overlay } ); |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
if ( exists { @_ }->{ glyph } ) |
307
|
|
|
|
|
|
|
{ |
308
|
|
|
|
|
|
|
if ( exists { @_ }->{ glyph }{ layer } ) |
309
|
|
|
|
|
|
|
{ |
310
|
|
|
|
|
|
|
$self->{ glyph }[ { @_ }->{ glyph }{ layer } ] = clone( { @_ }->{ glyph } ); |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
else |
313
|
|
|
|
|
|
|
{ |
314
|
|
|
|
|
|
|
push @{ $self->{ glyph } }, clone( { @_ }->{ glyph } ); |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
bless( $self, $class ); |
319
|
|
|
|
|
|
|
return $self; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
sub _color_allocate |
323
|
|
|
|
|
|
|
{ |
324
|
|
|
|
|
|
|
my $col = shift; |
325
|
|
|
|
|
|
|
my $def = shift; |
326
|
|
|
|
|
|
|
my $graph = shift; |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
if ( ref $col eq 'ARRAY' ) |
329
|
|
|
|
|
|
|
{ |
330
|
|
|
|
|
|
|
my @style; |
331
|
|
|
|
|
|
|
foreach my $c ( @{ $col } ) |
332
|
|
|
|
|
|
|
{ |
333
|
|
|
|
|
|
|
my ( $r, $g, $b, $a ) = unpack "a2 a2 a2 a2 ", _re_color( $c, 'ffffffff' ); |
334
|
|
|
|
|
|
|
push @style, $graph->colorAllocateAlpha( hex $r, hex $g, hex $b, hex $a ); |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
$graph->setStyle( @style ); |
337
|
|
|
|
|
|
|
return gdStyled; |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
else |
340
|
|
|
|
|
|
|
{ |
341
|
|
|
|
|
|
|
if ( $col =~ /^(0x)??([[:xdigit:]]{6})$/i ) |
342
|
|
|
|
|
|
|
{ |
343
|
|
|
|
|
|
|
$col = $2 . '00'; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
elsif ( $col =~ /^(0x)??([[:xdigit:]]{8})$/i ) |
346
|
|
|
|
|
|
|
{ |
347
|
|
|
|
|
|
|
$col = $2; |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
else |
350
|
|
|
|
|
|
|
{ |
351
|
|
|
|
|
|
|
$col = $def; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
my ( $r, $g, $b, $a ) = unpack "a2 a2 a2 a2 ", $col; |
354
|
|
|
|
|
|
|
return $graph->colorAllocateAlpha( hex $r, hex $g, hex $b, hex $a ); |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
sub _re_color |
359
|
|
|
|
|
|
|
{ |
360
|
|
|
|
|
|
|
my $col = shift; |
361
|
|
|
|
|
|
|
my $def = shift; |
362
|
|
|
|
|
|
|
my $graph = shift; |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
if ( $col =~ /^(0x)??([[:xdigit:]]{6})$/i ) |
365
|
|
|
|
|
|
|
{ |
366
|
|
|
|
|
|
|
$col = $2 . '00'; |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
elsif ( $col =~ /^(0x)??([[:xdigit:]]{8})$/i ) |
369
|
|
|
|
|
|
|
{ |
370
|
|
|
|
|
|
|
$col = $2; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
else |
373
|
|
|
|
|
|
|
{ |
374
|
|
|
|
|
|
|
$col = $def; |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
return $col; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
########################################################################### |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
########################################################################### |
381
|
|
|
|
|
|
|
sub img_from |
382
|
|
|
|
|
|
|
{ |
383
|
|
|
|
|
|
|
my $self = shift; |
384
|
|
|
|
|
|
|
my $object = shift; |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
my $file = $object->{ file }; |
387
|
|
|
|
|
|
|
my $image; |
388
|
|
|
|
|
|
|
{ |
389
|
|
|
|
|
|
|
local $/ = undef; |
390
|
|
|
|
|
|
|
open IMG, $file; |
391
|
|
|
|
|
|
|
binmode IMG; |
392
|
|
|
|
|
|
|
$image = ; |
393
|
|
|
|
|
|
|
close IMG; |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
my $image_gd = GD::Image->new( $image ); |
396
|
|
|
|
|
|
|
my $image_png = $image_gd->png; |
397
|
|
|
|
|
|
|
my @chunks; |
398
|
|
|
|
|
|
|
my $chunks_nbr = 0; |
399
|
|
|
|
|
|
|
substr( $image, 0, 33, '' ); |
400
|
|
|
|
|
|
|
while ( 1 ) |
401
|
|
|
|
|
|
|
{ |
402
|
|
|
|
|
|
|
my $slice = substr( $image, 0, 8, '' ); |
403
|
|
|
|
|
|
|
my ( $len, $type ) = unpack( "Na4", $slice ); |
404
|
|
|
|
|
|
|
last if $type eq 'IEND'; |
405
|
|
|
|
|
|
|
if ( $type eq 'tEXt' ) |
406
|
|
|
|
|
|
|
{ |
407
|
|
|
|
|
|
|
my $tEXt = substr( $image, 0, $len, '' ); |
408
|
|
|
|
|
|
|
my @all = split( /\0/, $tEXt, 2 ); |
409
|
|
|
|
|
|
|
my $obj = Data::Serializer->new(); |
410
|
|
|
|
|
|
|
my $tags = $obj->deserialize( $all[1] ); |
411
|
|
|
|
|
|
|
foreach my $tag ( keys %{ $tags } ) |
412
|
|
|
|
|
|
|
{ |
413
|
|
|
|
|
|
|
next if ( $tag eq 'Graph::Chart' ); |
414
|
|
|
|
|
|
|
$self->{ $tag } = $tags->{ $tag }; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
foreach my $tag ( keys %{ $tags->{ 'Graph::Chart' } } ) |
417
|
|
|
|
|
|
|
{ |
418
|
|
|
|
|
|
|
$self->{ $tag } = $tags->{ 'Graph::Chart' }{ $tag }; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
last; |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
$self->{ img } = $image_png; |
424
|
|
|
|
|
|
|
if ( !exists $self->{ size_tot } ) |
425
|
|
|
|
|
|
|
{ |
426
|
|
|
|
|
|
|
( $self->{ size_tot }->[0], $self->{ size_tot }->[1] ) = ( $image_gd->getBounds() )[ 0, 1 ]; |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
$self; |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
########################################################################### |
432
|
|
|
|
|
|
|
### method to reduce a set of data ### |
433
|
|
|
|
|
|
|
### with specific polling time ### |
434
|
|
|
|
|
|
|
### to fit the dot size ### |
435
|
|
|
|
|
|
|
########################################################################### |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
=head2 reduce |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
get a set of data as input and return the data to fill the array with the plotting values |
440
|
|
|
|
|
|
|
if more input data then the dot in the graph, process by averaging for a sample calculated on the target size |
441
|
|
|
|
|
|
|
if lower input data then the dot in the graph, repeat the input data in the slice related |
442
|
|
|
|
|
|
|
if called in array context return a ref to the array with reduced data and a ref to a hash with the statistical data |
443
|
|
|
|
|
|
|
in sclar context return a ref to the array with reduced data |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
my $dr= $graph->reduce( |
446
|
|
|
|
|
|
|
{ |
447
|
|
|
|
|
|
|
start => 5, # start to fill the destination array at that element ( optional, default = 0 ) |
448
|
|
|
|
|
|
|
end => 50, # fill the destination array until that element ( optional, default = plot width ) |
449
|
|
|
|
|
|
|
data => \@dot, # the input data set |
450
|
|
|
|
|
|
|
init => 0, # a default value for the destination set if not filled ( optional, default = undef ) |
451
|
|
|
|
|
|
|
type => 'line' # type of interpollation if lower element in the input data set then in the target |
452
|
|
|
|
|
|
|
# default = step, the value is duplicate to fill-in all the destination dot for the slice |
453
|
|
|
|
|
|
|
# if line, the dot are filled with an increasing/decreasing step created by the to adjacent value/ by the number of dot in the slice |
454
|
|
|
|
|
|
|
# if nrz = keep the previous value if now value == 0 |
455
|
|
|
|
|
|
|
percentile => 0.90 # a percentile to use (default = 0.95 ) |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
); |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
=cut |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
sub reduce |
462
|
|
|
|
|
|
|
{ |
463
|
|
|
|
|
|
|
my $self = shift; |
464
|
|
|
|
|
|
|
my $object = shift; |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
my $width_out = $self->{ size }->[0]; |
467
|
|
|
|
|
|
|
my $start = $object->{ start } || 0; |
468
|
|
|
|
|
|
|
my $percentile_value = $object->{ percentile } || 0.95; |
469
|
|
|
|
|
|
|
my $end = $object->{ end } || $width_out; |
470
|
|
|
|
|
|
|
my @data_in = @{ $object->{ data } }; |
471
|
|
|
|
|
|
|
my $data_in_size = scalar @data_in; |
472
|
|
|
|
|
|
|
my @perc = sort { $a <=> $b } @data_in[$start .. $end ] ; |
473
|
|
|
|
|
|
|
my $prec_ind = int( scalar( @perc ) * $percentile_value); |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
my @data_out; |
476
|
|
|
|
|
|
|
my %STATS; |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
$STATS{ percentile } = $perc[$prec_ind]; |
479
|
|
|
|
|
|
|
$STATS{ min } = min @perc; |
480
|
|
|
|
|
|
|
$STATS{ max } = max @data_in; |
481
|
|
|
|
|
|
|
$STATS{ sum } = sum @data_in; |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
$STATS{ avg } = $STATS{ sum } / scalar( @perc ); |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
$#data_out = $width_out; |
486
|
|
|
|
|
|
|
my $width_in = $end - $start + 1; |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
my $data_dot = ( scalar @data_in ) / $width_in; |
489
|
|
|
|
|
|
|
my $data_dot_int = int( $data_dot + 0.5 ); |
490
|
|
|
|
|
|
|
my @chars; |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
if ( exists $object->{ init } ) |
493
|
|
|
|
|
|
|
{ |
494
|
|
|
|
|
|
|
@data_out = map( $object->{ init }, @data_out ); |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
if ( $#data_out <= $#data_in ) |
497
|
|
|
|
|
|
|
{ |
498
|
|
|
|
|
|
|
my $old_val = 0; |
499
|
|
|
|
|
|
|
for ( my $dot = $start ; $dot <= $end ; $dot++ ) |
500
|
|
|
|
|
|
|
{ |
501
|
|
|
|
|
|
|
my $s = ( $dot - $start ) * $data_dot; |
502
|
|
|
|
|
|
|
my $e = $s + $data_dot - 1; |
503
|
|
|
|
|
|
|
my @slice = @data_in[ $s .. $e ]; |
504
|
|
|
|
|
|
|
if ( scalar( @slice ) ) |
505
|
|
|
|
|
|
|
{ |
506
|
|
|
|
|
|
|
if ( $object->{ type } =~ /^nrz$/i ) |
507
|
|
|
|
|
|
|
{ |
508
|
|
|
|
|
|
|
foreach my $idx ( 0 .. $#slice ) |
509
|
|
|
|
|
|
|
{ |
510
|
|
|
|
|
|
|
if ( $slice[$idx] == 0 ) |
511
|
|
|
|
|
|
|
{ |
512
|
|
|
|
|
|
|
$slice[$idx] = $old_val; |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
else |
515
|
|
|
|
|
|
|
{ |
516
|
|
|
|
|
|
|
$old_val = $slice[$idx]; |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
$data_out[$dot] = sum( @slice ) / scalar( @slice ); |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
else |
523
|
|
|
|
|
|
|
{ |
524
|
|
|
|
|
|
|
$data_out[$dot] = 0; |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
$STATS{ last } = $dot; |
527
|
|
|
|
|
|
|
$STATS{ last_val } = $data_in[ -1 ] ; |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
else |
531
|
|
|
|
|
|
|
{ |
532
|
|
|
|
|
|
|
if ( exists $object->{ type } && $object->{ type } =~ /^line|nrz$/i ) |
533
|
|
|
|
|
|
|
{ |
534
|
|
|
|
|
|
|
my $dot = 0; |
535
|
|
|
|
|
|
|
my $old_val = 0; |
536
|
|
|
|
|
|
|
W: while ( $dot <= $width_in ) |
537
|
|
|
|
|
|
|
{ |
538
|
|
|
|
|
|
|
my $ind = ( int( ( $dot / ( $width_in / $data_in_size ) ) ) ); |
539
|
|
|
|
|
|
|
my $val1 = $ind > $#data_in ? $data_in[-1] : $data_in[$ind]; |
540
|
|
|
|
|
|
|
my $val2 = ( $ind + 1 ) > $#data_in ? $data_in[-1] : $data_in[ ( $ind + 1 ) ]; |
541
|
|
|
|
|
|
|
my $inc = ( $val2 - $val1 ) / ( ( $width_in / $data_in_size ) ); |
542
|
|
|
|
|
|
|
my $val = $val1 || 0; |
543
|
|
|
|
|
|
|
for ( 0 .. ( $width_in / $data_in_size ) ) |
544
|
|
|
|
|
|
|
{ |
545
|
|
|
|
|
|
|
$STATS{ last } = $dot; |
546
|
|
|
|
|
|
|
last W if ( $dot >= $width_in ); |
547
|
|
|
|
|
|
|
if ( $object->{ type } =~ /^nrz$/i && ( !$val2 || !$val ) ) |
548
|
|
|
|
|
|
|
{ |
549
|
|
|
|
|
|
|
$data_out[ $dot + $start ] = $old_val; |
550
|
|
|
|
|
|
|
} |
551
|
|
|
|
|
|
|
else |
552
|
|
|
|
|
|
|
{ |
553
|
|
|
|
|
|
|
$data_out[ $dot + $start ] = $val; |
554
|
|
|
|
|
|
|
$old_val = $val; |
555
|
|
|
|
|
|
|
$val += $inc; |
556
|
|
|
|
|
|
|
} |
557
|
|
|
|
|
|
|
if ( $inc > 0 ) |
558
|
|
|
|
|
|
|
{ |
559
|
|
|
|
|
|
|
$val = $val > $val2 ? $val2 : $val; |
560
|
|
|
|
|
|
|
} |
561
|
|
|
|
|
|
|
else |
562
|
|
|
|
|
|
|
{ |
563
|
|
|
|
|
|
|
$val = $val < $val2 ? $val2 : $val; |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
$dot++; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
} |
570
|
|
|
|
|
|
|
else |
571
|
|
|
|
|
|
|
{ |
572
|
|
|
|
|
|
|
for ( my $dot = 1 ; $dot <= $width_in ; $dot++ ) |
573
|
|
|
|
|
|
|
{ |
574
|
|
|
|
|
|
|
$STATS{ last } = $dot; |
575
|
|
|
|
|
|
|
my $ind = ( int( ( $dot / ( $width_in / $data_in_size ) ) ) ); |
576
|
|
|
|
|
|
|
$data_out[ $dot + $start - 1 ] = $ind > $#data_in ? $data_in[-1] : $data_in[$ind]; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
} |
580
|
|
|
|
|
|
|
return wantarray ? ( \@data_out, \%STATS ) : \@data_out; |
581
|
|
|
|
|
|
|
# return \@data_out, \%STATS; |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
########################################################################### |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
########################################################################### |
586
|
|
|
|
|
|
|
### method to set the grid ### |
587
|
|
|
|
|
|
|
########################################################################### |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
=head2 grid |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
set the grid |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
use the same parameter as the new() |
594
|
|
|
|
|
|
|
if the option is already present, overwrite this option |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=cut |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
sub grid |
599
|
|
|
|
|
|
|
{ |
600
|
|
|
|
|
|
|
my $self = shift; |
601
|
|
|
|
|
|
|
my $object = shift; |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
if ( $object ) |
604
|
|
|
|
|
|
|
{ |
605
|
|
|
|
|
|
|
foreach my $item ( keys %{ $object } ) |
606
|
|
|
|
|
|
|
{ |
607
|
|
|
|
|
|
|
if ( ref( $object->{ $item } ) eq 'HASH' ) |
608
|
|
|
|
|
|
|
{ |
609
|
|
|
|
|
|
|
foreach my $sub_item ( keys %{ $object->{ $item } } ) |
610
|
|
|
|
|
|
|
{ |
611
|
|
|
|
|
|
|
$self->{ grid }{ $item }{ $sub_item } = $object->{ $item }{ $sub_item }; |
612
|
|
|
|
|
|
|
} |
613
|
|
|
|
|
|
|
} |
614
|
|
|
|
|
|
|
else |
615
|
|
|
|
|
|
|
{ |
616
|
|
|
|
|
|
|
$self->{ grid }{ $item } = $object->{ $item }; |
617
|
|
|
|
|
|
|
} |
618
|
|
|
|
|
|
|
unless ( exists $self->{ grid }->{ debord } ) |
619
|
|
|
|
|
|
|
{ |
620
|
|
|
|
|
|
|
$self->{ grid }->{ debord } = [ 0, 0, 0, 0 ]; |
621
|
|
|
|
|
|
|
} |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
} |
624
|
|
|
|
|
|
|
return $self->{ grid }; |
625
|
|
|
|
|
|
|
} |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
########################################################################### |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
########################################################################### |
630
|
|
|
|
|
|
|
### method to set the reticle ### |
631
|
|
|
|
|
|
|
########################################################################### |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
=head2 reticle |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
set the reticle |
636
|
|
|
|
|
|
|
the reticle are the division when using a polar chart ( pie, target .... ) |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
use the same parameter as the new() |
639
|
|
|
|
|
|
|
if the option is already present, overwrite this option |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
=cut |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
sub reticle |
644
|
|
|
|
|
|
|
{ |
645
|
|
|
|
|
|
|
my $self = shift; |
646
|
|
|
|
|
|
|
my $object = shift; |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
if ( $object ) |
649
|
|
|
|
|
|
|
{ |
650
|
|
|
|
|
|
|
foreach my $item ( keys %{ $object } ) |
651
|
|
|
|
|
|
|
{ |
652
|
|
|
|
|
|
|
if ( ref( $object->{ $item } ) eq 'HASH' ) |
653
|
|
|
|
|
|
|
{ |
654
|
|
|
|
|
|
|
foreach my $sub_item ( %{ $object->{ $item } } ) |
655
|
|
|
|
|
|
|
{ |
656
|
|
|
|
|
|
|
$self->{ reticle }{ $item }{ $sub_item } = $object->{ $item }{ $sub_item }; |
657
|
|
|
|
|
|
|
} |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
else |
660
|
|
|
|
|
|
|
{ |
661
|
|
|
|
|
|
|
$self->{ reticle }{ $item } = $object->{ $item }; |
662
|
|
|
|
|
|
|
} |
663
|
|
|
|
|
|
|
unless ( exists $self->{ reticle }->{ debord } ) |
664
|
|
|
|
|
|
|
{ |
665
|
|
|
|
|
|
|
$self->{ reticle }->{ debord } = 0; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
} |
668
|
|
|
|
|
|
|
} |
669
|
|
|
|
|
|
|
return $self->{ reticle }; |
670
|
|
|
|
|
|
|
} |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
########################################################################### |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
########################################################################### |
675
|
|
|
|
|
|
|
### method to set the frame ### |
676
|
|
|
|
|
|
|
########################################################################### |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
=head2 frame |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
set the frame |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
use the same parameter as the new() |
683
|
|
|
|
|
|
|
if the option is already present, overwrite this option |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
=cut |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
sub frame |
688
|
|
|
|
|
|
|
{ |
689
|
|
|
|
|
|
|
my $self = shift; |
690
|
|
|
|
|
|
|
my $object = shift; |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
if ( $object ) |
693
|
|
|
|
|
|
|
{ |
694
|
|
|
|
|
|
|
$self->{ frame } = $object; |
695
|
|
|
|
|
|
|
foreach my $item ( keys %{ $object } ) |
696
|
|
|
|
|
|
|
{ |
697
|
|
|
|
|
|
|
if ( ref( $object->{ $item } ) eq 'HASH' ) |
698
|
|
|
|
|
|
|
{ |
699
|
|
|
|
|
|
|
foreach my $sub_item ( %{ $object->{ $item } } ) |
700
|
|
|
|
|
|
|
{ |
701
|
|
|
|
|
|
|
$self->{ frame }{ $item }{ $sub_item } = $object->{ $item }{ $sub_item }; |
702
|
|
|
|
|
|
|
} |
703
|
|
|
|
|
|
|
} |
704
|
|
|
|
|
|
|
else |
705
|
|
|
|
|
|
|
{ |
706
|
|
|
|
|
|
|
$self->{ frame }{ $item } = $object->{ $item }; |
707
|
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
if ( exists $object->{ color } ) |
710
|
|
|
|
|
|
|
{ |
711
|
|
|
|
|
|
|
$self->{ frame }{ color } = _re_color( $object->{ color }, '00000000' ); |
712
|
|
|
|
|
|
|
} |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
return $self->{ frame }; |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
########################################################################### |
718
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
########################################################################### |
720
|
|
|
|
|
|
|
### method to set the size ### |
721
|
|
|
|
|
|
|
########################################################################### |
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
=head2 size |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
set the size ( this is the only mandatory option ) |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
use the same parameter as the new() |
728
|
|
|
|
|
|
|
if the option is already present, overwrite this option |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
=cut |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
sub size |
733
|
|
|
|
|
|
|
{ |
734
|
|
|
|
|
|
|
my $self = shift; |
735
|
|
|
|
|
|
|
my $object = shift; |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
if ( $object ) |
738
|
|
|
|
|
|
|
{ |
739
|
|
|
|
|
|
|
$self->{ size } = $object; |
740
|
|
|
|
|
|
|
} |
741
|
|
|
|
|
|
|
return $self->{ size }; |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
########################################################################### |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
########################################################################### |
746
|
|
|
|
|
|
|
### method to get the active border size ### |
747
|
|
|
|
|
|
|
########################################################################### |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
=head2 active |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
get the active border size |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
return a hash ref with |
754
|
|
|
|
|
|
|
$ref->{ x }{ max } ==> left border of the main graph |
755
|
|
|
|
|
|
|
$ref->{ x }{ min } ==> right border of the main graph |
756
|
|
|
|
|
|
|
$ref->{ y }{ max } ==> upper border of the main graph |
757
|
|
|
|
|
|
|
$ref->{ y }{ min } ==> lower border of the main graph |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
=cut |
760
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
sub active |
762
|
|
|
|
|
|
|
{ |
763
|
|
|
|
|
|
|
my $self = shift; |
764
|
|
|
|
|
|
|
my %tmp; |
765
|
|
|
|
|
|
|
$tmp{ x }{ max } = $self->{ border }->[0] + $self->{ size }->[0]; |
766
|
|
|
|
|
|
|
$tmp{ x }{ min } = $self->{ border }->[0]; |
767
|
|
|
|
|
|
|
$tmp{ y }{ max } = $self->{ border }->[3] + $self->{ size }->[1]; |
768
|
|
|
|
|
|
|
$tmp{ y }{ min } = $self->{ border }->[2]; |
769
|
|
|
|
|
|
|
return \%tmp; |
770
|
|
|
|
|
|
|
} |
771
|
|
|
|
|
|
|
########################################################################### |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
########################################################################### |
774
|
|
|
|
|
|
|
### method to set the bg_color ### |
775
|
|
|
|
|
|
|
########################################################################### |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
=head2 bg_color |
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
set the bg_color |
780
|
|
|
|
|
|
|
set the background color of the graph |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
use the same parameter as the new() |
783
|
|
|
|
|
|
|
if the option is already present, overwrite this option |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
=cut |
786
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
sub bg_color |
788
|
|
|
|
|
|
|
{ |
789
|
|
|
|
|
|
|
my $self = shift; |
790
|
|
|
|
|
|
|
my $object = shift; |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
if ( $object ) |
793
|
|
|
|
|
|
|
{ |
794
|
|
|
|
|
|
|
$self->{ bg_color } = $object; |
795
|
|
|
|
|
|
|
} |
796
|
|
|
|
|
|
|
return $self->{ bg_color }; |
797
|
|
|
|
|
|
|
} |
798
|
|
|
|
|
|
|
########################################################################### |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
########################################################################### |
801
|
|
|
|
|
|
|
### method to provide the data to plot ### |
802
|
|
|
|
|
|
|
########################################################################### |
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
=head2 data |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
set the data to be plotted |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
$graph->data( |
810
|
|
|
|
|
|
|
{ |
811
|
|
|
|
|
|
|
layer => 10, # the layer where the data is plotted ( the lowest number is the deepest layer ) If missing, the layer is created by call order of the method data |
812
|
|
|
|
|
|
|
set => \@dot, # a array ref with the data ( the number of dot plotted is the number W provided by the size parameter/method |
813
|
|
|
|
|
|
|
type => 'pie', # the type of graph ( dot, line, bar, up_dot, up_bar, up_line , down_dot,down_line, down_bar, pie, target, radial ) |
814
|
|
|
|
|
|
|
bar_size => 1, # if any type of bar used, this is an extra width of the bar created, if not defined, the bar width= 1 if set to 1 the size of the bar became 3 ( 1 before, 1 for the bar and one after ) |
815
|
|
|
|
|
|
|
color => '0x0000ff', # color of the plotted element |
816
|
|
|
|
|
|
|
thickness => 1, # for any type of dot and line, the thiskness to used ( default = 1 ) |
817
|
|
|
|
|
|
|
scale => '90%', # a vertical scale on the value provided ( a decimal number scale all the data value using the value ( data could be outside of the graph) 1 = 100% |
818
|
|
|
|
|
|
|
# a percent value like, '90%' scale the graph to that percentage ( lower then 100% = some data are plotted outside the graph ) |
819
|
|
|
|
|
|
|
# missing or '100%' resize the graph using the maximal value |
820
|
|
|
|
|
|
|
# 'auto' or '110%' allow to always have a small extra gap and never reach to extremity of the graph area, |
821
|
|
|
|
|
|
|
max => 3000, # a maximal value to use to create the graph ( if missing, max = maximal value from the data set ) |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
} |
824
|
|
|
|
|
|
|
); |
825
|
|
|
|
|
|
|
=cut |
826
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
sub data |
828
|
|
|
|
|
|
|
{ |
829
|
|
|
|
|
|
|
my $self = shift; |
830
|
|
|
|
|
|
|
my $object = shift; |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
if ( $object ) |
833
|
|
|
|
|
|
|
{ |
834
|
|
|
|
|
|
|
if ( exists $object->{ layer } ) |
835
|
|
|
|
|
|
|
{ |
836
|
|
|
|
|
|
|
$self->{ data }[ $object->{ layer } ] = clone( $object ); |
837
|
|
|
|
|
|
|
} |
838
|
|
|
|
|
|
|
else |
839
|
|
|
|
|
|
|
{ |
840
|
|
|
|
|
|
|
push @{ $self->{ data } }, clone( $object ); |
841
|
|
|
|
|
|
|
} |
842
|
|
|
|
|
|
|
} |
843
|
|
|
|
|
|
|
return $self->{ data }; |
844
|
|
|
|
|
|
|
} |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
########################################################################### |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
########################################################################### |
849
|
|
|
|
|
|
|
### method to put an overlay on top of the graph ### |
850
|
|
|
|
|
|
|
########################################################################### |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
=head2 overlay |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
method to put an overlay on top of the graph ( to show alarm period ... ) |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
use the same parameter as the new() |
858
|
|
|
|
|
|
|
if the same layer is already present, overwrite this layer |
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
=cut |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
sub overlay |
863
|
|
|
|
|
|
|
{ |
864
|
|
|
|
|
|
|
my $self = shift; |
865
|
|
|
|
|
|
|
my $object = shift; |
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
if ( $object ) |
868
|
|
|
|
|
|
|
{ |
869
|
|
|
|
|
|
|
if ( exists $object->{ layer } ) |
870
|
|
|
|
|
|
|
{ |
871
|
|
|
|
|
|
|
$self->{ overlay }[ $object->{ layer } ] = clone( $object ); |
872
|
|
|
|
|
|
|
} |
873
|
|
|
|
|
|
|
else |
874
|
|
|
|
|
|
|
{ |
875
|
|
|
|
|
|
|
push @{ $self->{ overlay } }, clone( $object ); |
876
|
|
|
|
|
|
|
} |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
return $self->{ overlay }; |
879
|
|
|
|
|
|
|
} |
880
|
|
|
|
|
|
|
########################################################################### |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
########################################################################### |
883
|
|
|
|
|
|
|
### method to put a glyph on the graph ### |
884
|
|
|
|
|
|
|
########################################################################### |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
=head2 overlay |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
method to put a glyph on the graph ( to show the latest data polled, or a trend value, ... ) |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
use the same parameter as the new() |
892
|
|
|
|
|
|
|
if the same layer is already present, overwrite this layer |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
=cut |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
sub glyph |
897
|
|
|
|
|
|
|
{ |
898
|
|
|
|
|
|
|
my $self = shift; |
899
|
|
|
|
|
|
|
my $object = shift; |
900
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
if ( $object ) |
902
|
|
|
|
|
|
|
{ |
903
|
|
|
|
|
|
|
if ( exists $object->{ layer } ) |
904
|
|
|
|
|
|
|
{ |
905
|
|
|
|
|
|
|
$self->{ glyph }[ $object->{ layer } ] = clone( $object ); |
906
|
|
|
|
|
|
|
} |
907
|
|
|
|
|
|
|
else |
908
|
|
|
|
|
|
|
{ |
909
|
|
|
|
|
|
|
push @{ $self->{ glyph } }, clone( $object ); |
910
|
|
|
|
|
|
|
} |
911
|
|
|
|
|
|
|
} |
912
|
|
|
|
|
|
|
return $self->{ glyph }; |
913
|
|
|
|
|
|
|
} |
914
|
|
|
|
|
|
|
########################################################################### |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
########################################################################### |
917
|
|
|
|
|
|
|
### method to add a png data TAG ( not standard ) ### |
918
|
|
|
|
|
|
|
########################################################################### |
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
=head2 png_zEXt |
921
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
method to add a png data TAG |
923
|
|
|
|
|
|
|
This tag is not a PNG standard, but allowed by the RFC |
924
|
|
|
|
|
|
|
see code in img_info.pl |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
my $png_out1 =$graph->png_zEXt( { eerer => 1, ggg => 'zed' } ); |
927
|
|
|
|
|
|
|
this overwrite the png TAG data with the new value and return the new image |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
=cut |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
sub png_zEXt |
932
|
|
|
|
|
|
|
{ |
933
|
|
|
|
|
|
|
my $self = shift; |
934
|
|
|
|
|
|
|
my $object = shift; |
935
|
|
|
|
|
|
|
$self->{ size_tot }->[0] = $self->{ size }->[0] + $self->{ border }->[0] + $self->{ border }->[1]; |
936
|
|
|
|
|
|
|
$self->{ size_tot }->[1] = $self->{ size }->[1] + $self->{ border }->[2] + $self->{ border }->[3]; |
937
|
|
|
|
|
|
|
my $tmp = clone( $self ); |
938
|
|
|
|
|
|
|
# delete $tmp->{ data }; |
939
|
|
|
|
|
|
|
foreach my $idx (0 .. scalar @{$tmp->{ data }}) |
940
|
|
|
|
|
|
|
{ |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
next if ( ! defined $tmp->{ data }[ $idx ] ); |
943
|
|
|
|
|
|
|
delete $tmp->{ data }[ $idx]{ set}; |
944
|
|
|
|
|
|
|
} |
945
|
|
|
|
|
|
|
delete $tmp->{ img }; |
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
my $obj = Data::Serializer->new( 'compress' => 1 ); |
948
|
|
|
|
|
|
|
$object->{ 'Graph::Chart' } = $tmp; |
949
|
|
|
|
|
|
|
my $tag = $obj->serialize( $object ); |
950
|
|
|
|
|
|
|
my $png_out; |
951
|
|
|
|
|
|
|
my $ihdr; # IHDR chunk |
952
|
|
|
|
|
|
|
my %tEXt; # tEXt chunks to insert |
953
|
|
|
|
|
|
|
my $sig; # PNG signature |
954
|
|
|
|
|
|
|
my $pos; # position in $png |
955
|
|
|
|
|
|
|
my $pngsize; # Total size of png |
956
|
|
|
|
|
|
|
my $text; # 'string' of all tEXt chunks with CRC, etc. |
957
|
|
|
|
|
|
|
my $tchunk; # content of text chunk |
958
|
|
|
|
|
|
|
$tEXt{ data } = $tag; |
959
|
|
|
|
|
|
|
( $sig, $ihdr, $png_out ) = unpack "a8 a25 a*", $self->{ img }; |
960
|
|
|
|
|
|
|
$png_out =~ /(.*)(....PLTE.*)/s; |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
my $old_tag = $1; |
963
|
|
|
|
|
|
|
my $end_png = $2; |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
foreach my $keyword ( keys %tEXt ) |
966
|
|
|
|
|
|
|
{ |
967
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
#* A tEXt chunk contains: |
969
|
|
|
|
|
|
|
#* |
970
|
|
|
|
|
|
|
#* Keyword: 1-79 bytes (character string) |
971
|
|
|
|
|
|
|
#* Null separator: 1 byte |
972
|
|
|
|
|
|
|
#* Compression method: 1 byte |
973
|
|
|
|
|
|
|
#* Compressed text: n bytes |
974
|
|
|
|
|
|
|
my $tbuffer; |
975
|
|
|
|
|
|
|
$tbuffer = $tEXt{ $keyword }; |
976
|
|
|
|
|
|
|
$tbuffer =~ s/\\([tnrfbae])/control_char($1)/eg; |
977
|
|
|
|
|
|
|
$tchunk = sprintf "%s%c%s", $keyword, 0, $tbuffer; |
978
|
|
|
|
|
|
|
$text .= pack "N A* N", ( length( $tchunk ), 'tEXt' . $tchunk, &crc32( 'tEXt' . $tchunk ) ); |
979
|
|
|
|
|
|
|
$pngsize += length( $tchunk ) + 8; |
980
|
|
|
|
|
|
|
} |
981
|
|
|
|
|
|
|
$png_out = $sig . $ihdr . $text . $end_png; |
982
|
|
|
|
|
|
|
$self->{ img } = $png_out; |
983
|
|
|
|
|
|
|
return $self->{ img }; |
984
|
|
|
|
|
|
|
} |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
########################################################################### |
987
|
|
|
|
|
|
|
sub update |
988
|
|
|
|
|
|
|
{ |
989
|
|
|
|
|
|
|
my $self = shift; |
990
|
|
|
|
|
|
|
my $object = shift; |
991
|
|
|
|
|
|
|
# carp Dumper($self); |
992
|
|
|
|
|
|
|
my $image_gd = GD::Image->new( $self->{img}); |
993
|
|
|
|
|
|
|
# carp $image_gd; |
994
|
|
|
|
|
|
|
# |
995
|
|
|
|
|
|
|
# $image->copy($sourceImage,$dstX,$dstY, $srcX,$srcY,$width,$height) |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
} |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
########################################################################### |
1003
|
|
|
|
|
|
|
### method to render the Chart ### |
1004
|
|
|
|
|
|
|
########################################################################### |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
=head2 render |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
render the chart and return a png image |
1009
|
|
|
|
|
|
|
|
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
my $img = $graph->render( \%tag ) |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
|
1014
|
|
|
|
|
|
|
the hash ref contain data to put in the PNG meta tag. |
1015
|
|
|
|
|
|
|
the tools img_info.pl allow to see the result. |
1016
|
|
|
|
|
|
|
the tag is serialized in the png |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
the returned value could be writted in a file like this: |
1019
|
|
|
|
|
|
|
my $png_out = $graph->render(); |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
open( my $IMG, '>', $file ) or die $!; |
1022
|
|
|
|
|
|
|
binmode $IMG; |
1023
|
|
|
|
|
|
|
print $IMG $png_out; |
1024
|
|
|
|
|
|
|
close $IMG; |
1025
|
|
|
|
|
|
|
); |
1026
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
=cut |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
sub render |
1030
|
|
|
|
|
|
|
{ |
1031
|
|
|
|
|
|
|
my $self = shift; |
1032
|
|
|
|
|
|
|
my $object = shift; |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
my $frame = new GD::Image( $self->{ size }->[0] + $self->{ border }->[0] + $self->{ border }->[1], $self->{ size }->[1] + $self->{ border }->[2] + $self->{ border }->[3] ); |
1035
|
|
|
|
|
|
|
my $bg_color = _color_allocate( $self->{ bg_color }, 'ffffffff', $frame ); |
1036
|
|
|
|
|
|
|
my $bg_color = _color_allocate( $self->{ bg_color }, 'ffffffff', $frame ); |
1037
|
|
|
|
|
|
|
$frame->transparent( $bg_color ); |
1038
|
|
|
|
|
|
|
$frame->interlaced( 'true' ); |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
### plot overlay |
1041
|
|
|
|
|
|
|
if ( exists $self->{ overlay } ) |
1042
|
|
|
|
|
|
|
{ |
1043
|
|
|
|
|
|
|
foreach my $layer ( @{ $self->{ overlay } } ) |
1044
|
|
|
|
|
|
|
{ |
1045
|
|
|
|
|
|
|
next unless ( ref $layer eq 'HASH' ); |
1046
|
|
|
|
|
|
|
my $col_graph; |
1047
|
|
|
|
|
|
|
my $frame_over; |
1048
|
|
|
|
|
|
|
if ( exists $layer->{ merge } && $layer->{ merge } ) |
1049
|
|
|
|
|
|
|
{ |
1050
|
|
|
|
|
|
|
$col_graph = _color_allocate( $layer->{ color }, '00000000', $frame ); |
1051
|
|
|
|
|
|
|
} |
1052
|
|
|
|
|
|
|
else |
1053
|
|
|
|
|
|
|
{ |
1054
|
|
|
|
|
|
|
$frame_over = new GD::Image( $self->{ size }->[0] + $self->{ border }->[0] + $self->{ border }->[1], $self->{ size }->[1] + $self->{ border }->[2] + $self->{ border }->[3] ); |
1055
|
|
|
|
|
|
|
my ( $r, $g, $b, $a ) = unpack "a2 a2 a2 a2 ", $self->{ bg_color }; |
1056
|
|
|
|
|
|
|
my $bg_color_over = $frame_over->colorAllocateAlpha( hex $r, hex $g, hex $b, hex $a ); |
1057
|
|
|
|
|
|
|
$frame_over->transparent( $bg_color_over ); |
1058
|
|
|
|
|
|
|
$frame_over->interlaced( 'true' ); |
1059
|
|
|
|
|
|
|
$frame_over->setThickness( 1 ); |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
$col_graph = _color_allocate( $layer->{ color }, '00000000', $frame ); |
1062
|
|
|
|
|
|
|
} |
1063
|
|
|
|
|
|
|
my $extra = |
1064
|
|
|
|
|
|
|
$self->{ border }->[2] > $self->{ border }->[3] |
1065
|
|
|
|
|
|
|
? $self->{ border }->[3] |
1066
|
|
|
|
|
|
|
: $self->{ border }->[2]; |
1067
|
|
|
|
|
|
|
if ( exists $layer->{ debord } ) |
1068
|
|
|
|
|
|
|
{ |
1069
|
|
|
|
|
|
|
$extra = $layer->{ debord }; |
1070
|
|
|
|
|
|
|
} |
1071
|
|
|
|
|
|
|
my $dot = -1; |
1072
|
|
|
|
|
|
|
my $last_pie; |
1073
|
|
|
|
|
|
|
foreach my $raw_val ( @{ $layer->{ set } } ) |
1074
|
|
|
|
|
|
|
{ |
1075
|
|
|
|
|
|
|
$dot++; |
1076
|
|
|
|
|
|
|
next if ( !defined $raw_val || !$raw_val ); |
1077
|
|
|
|
|
|
|
my $plot_dot = $self->{ border }->[0] + $dot; |
1078
|
|
|
|
|
|
|
my $plot_val = $self->{ border }->[2] + $self->{ border }->[3] + $self->{ size }->[1]; |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
if ( exists $layer->{ merge } && $layer->{ merge } ) |
1081
|
|
|
|
|
|
|
{ |
1082
|
|
|
|
|
|
|
if ( exists $layer->{ type } && $layer->{ type } eq 'pie' ) |
1083
|
|
|
|
|
|
|
{ |
1084
|
|
|
|
|
|
|
$frame->filledArc( $self->{ size }->[0] / 2 + $self->{ border }->[0], ( $self->{ size }->[1] / 2 ) + $self->{ border }->[2], ( $self->{ size }->[1] + ( 2 * $extra ) ), ( $self->{ size }->[1] + ( 2 * $extra ) ), $dot, $dot + 1, $col_graph, gdEdged ); |
1085
|
|
|
|
|
|
|
$last_pie = $dot; |
1086
|
|
|
|
|
|
|
} |
1087
|
|
|
|
|
|
|
else |
1088
|
|
|
|
|
|
|
{ |
1089
|
|
|
|
|
|
|
$frame->line( $plot_dot, 0, $plot_dot, $plot_val, $col_graph ); |
1090
|
|
|
|
|
|
|
} |
1091
|
|
|
|
|
|
|
} |
1092
|
|
|
|
|
|
|
else |
1093
|
|
|
|
|
|
|
{ |
1094
|
|
|
|
|
|
|
if ( exists $layer->{ type } && $layer->{ type } eq 'pie' ) |
1095
|
|
|
|
|
|
|
{ |
1096
|
|
|
|
|
|
|
$frame_over->filledArc( $self->{ size }->[0] / 2 + $self->{ border }->[0], ( $self->{ size }->[1] / 2 ) + $self->{ border }->[2], ( $self->{ size }->[1] + ( 2 * $extra ) ), ( $self->{ size }->[1] + ( 2 * $extra ) ), $dot, $dot + 1, $col_graph, gdEdged ); |
1097
|
|
|
|
|
|
|
} |
1098
|
|
|
|
|
|
|
else |
1099
|
|
|
|
|
|
|
{ |
1100
|
|
|
|
|
|
|
$frame_over->line( $plot_dot, 0, $plot_dot, $plot_val, $col_graph ); |
1101
|
|
|
|
|
|
|
} |
1102
|
|
|
|
|
|
|
} |
1103
|
|
|
|
|
|
|
} |
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
if ( exists $layer->{ merge } && $layer->{ merge } ) |
1106
|
|
|
|
|
|
|
{ |
1107
|
|
|
|
|
|
|
} |
1108
|
|
|
|
|
|
|
else |
1109
|
|
|
|
|
|
|
{ |
1110
|
|
|
|
|
|
|
my $trans = $layer->{ opacity } || 20; |
1111
|
|
|
|
|
|
|
$frame->copyMerge( $frame_over, 0, 0, 0, 0, $self->{ size }->[0] + $self->{ border }->[0] + $self->{ border }->[1], $self->{ size }->[1] + $self->{ border }->[2] + $self->{ border }->[3], $trans ); |
1112
|
|
|
|
|
|
|
} |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
} |
1115
|
|
|
|
|
|
|
} |
1116
|
|
|
|
|
|
|
### end plot overlay |
1117
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
### plot data |
1119
|
|
|
|
|
|
|
if ( exists $self->{ data } ) |
1120
|
|
|
|
|
|
|
{ |
1121
|
|
|
|
|
|
|
my $last_pie; |
1122
|
|
|
|
|
|
|
foreach my $layer ( @{ $self->{ data } } ) |
1123
|
|
|
|
|
|
|
{ |
1124
|
|
|
|
|
|
|
next unless ( ref $layer eq 'HASH' ); |
1125
|
|
|
|
|
|
|
my $max = max( @{ $layer->{ set } } ); |
1126
|
|
|
|
|
|
|
my $min = min( @{ $layer->{ set } } ); |
1127
|
|
|
|
|
|
|
my $scale = 1; |
1128
|
|
|
|
|
|
|
my $pre_scale = 1; |
1129
|
|
|
|
|
|
|
my $bar_size = $layer->{ bar_size } || 1; |
1130
|
|
|
|
|
|
|
if ( exists $layer->{ scale } ) |
1131
|
|
|
|
|
|
|
{ |
1132
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
if ( $layer->{ scale } =~ /^(\d*\.*\d*)%$/ ) |
1134
|
|
|
|
|
|
|
{ |
1135
|
|
|
|
|
|
|
$pre_scale = $1 / 100; |
1136
|
|
|
|
|
|
|
} |
1137
|
|
|
|
|
|
|
if ( $layer->{ scale } =~ /^(\d*\.*\d*)$/ ) |
1138
|
|
|
|
|
|
|
{ |
1139
|
|
|
|
|
|
|
$pre_scale = $1; |
1140
|
|
|
|
|
|
|
} |
1141
|
|
|
|
|
|
|
elsif ( $layer->{ scale } eq 'auto' ) |
1142
|
|
|
|
|
|
|
{ |
1143
|
|
|
|
|
|
|
$pre_scale = 1.1; |
1144
|
|
|
|
|
|
|
} |
1145
|
|
|
|
|
|
|
} |
1146
|
|
|
|
|
|
|
if ( exists $layer->{ max } ) |
1147
|
|
|
|
|
|
|
{ |
1148
|
|
|
|
|
|
|
$max = $layer->{ max }; |
1149
|
|
|
|
|
|
|
} |
1150
|
|
|
|
|
|
|
$scale = $self->{ size }->[1] / ( $pre_scale * $max ); |
1151
|
|
|
|
|
|
|
if ( exists $layer->{ type } && $layer->{ type } =~ /(up|down)/ ) |
1152
|
|
|
|
|
|
|
{ |
1153
|
|
|
|
|
|
|
$scale /= 2; |
1154
|
|
|
|
|
|
|
} |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
my $thickness = $layer->{ thickness } || 1; |
1157
|
|
|
|
|
|
|
$frame->setThickness( $thickness ); |
1158
|
|
|
|
|
|
|
my $col_graph = _color_allocate( $layer->{ color }, '00000000', $frame ); |
1159
|
|
|
|
|
|
|
|
1160
|
|
|
|
|
|
|
if ( !exists $layer->{ type } || $layer->{ type } =~ /line|dot|bar/ ) |
1161
|
|
|
|
|
|
|
{ |
1162
|
|
|
|
|
|
|
my $poly = new GD::Polygon; |
1163
|
|
|
|
|
|
|
my $dot = -1; |
1164
|
|
|
|
|
|
|
foreach my $raw_val ( @{ $layer->{ set } } ) |
1165
|
|
|
|
|
|
|
{ |
1166
|
|
|
|
|
|
|
$dot++; |
1167
|
|
|
|
|
|
|
next if ( !defined $raw_val ); |
1168
|
|
|
|
|
|
|
last if ( $dot >= $self->{ size }->[0] ); |
1169
|
|
|
|
|
|
|
my $offset = $layer->{ offset } || 0; |
1170
|
|
|
|
|
|
|
my $val = ( $scale * $raw_val ) + $offset; |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
if ( exists $layer->{ scale } && $layer->{ scale } eq 'log' ) |
1173
|
|
|
|
|
|
|
{ |
1174
|
|
|
|
|
|
|
$raw_val = $raw_val <= 0 ? $min : $raw_val; |
1175
|
|
|
|
|
|
|
next if ( $raw_val <= 0 ); |
1176
|
|
|
|
|
|
|
$val = log10( $raw_val ) + $offset; |
1177
|
|
|
|
|
|
|
} |
1178
|
|
|
|
|
|
|
elsif ( exists $layer->{ scale } && $layer->{ scale } eq 'ln' ) |
1179
|
|
|
|
|
|
|
{ |
1180
|
|
|
|
|
|
|
$raw_val = $raw_val <= 0 ? $min : $raw_val; |
1181
|
|
|
|
|
|
|
next if ( $raw_val <= 0 ); |
1182
|
|
|
|
|
|
|
$val = log( $raw_val ) + $offset; |
1183
|
|
|
|
|
|
|
} |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
$val = $val > $self->{ size }->[1] ? $self->{ size }->[1] : $val; |
1186
|
|
|
|
|
|
|
$val = $val < 0 ? 0 : $val; |
1187
|
|
|
|
|
|
|
my $plot_dot = $self->{ border }->[0] + $dot; |
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
my $plot_val = $self->{ border }->[2] + $self->{ size }->[1] - $val; |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
my $y_size = $self->{ size }->[1]; |
1192
|
|
|
|
|
|
|
if ( $layer->{ type } =~ /up/ ) |
1193
|
|
|
|
|
|
|
{ |
1194
|
|
|
|
|
|
|
$y_size /= 2; |
1195
|
|
|
|
|
|
|
$val = $val > $y_size ? $y_size : $val; |
1196
|
|
|
|
|
|
|
$plot_val = $self->{ border }->[2] + $y_size - $val; |
1197
|
|
|
|
|
|
|
} |
1198
|
|
|
|
|
|
|
elsif ( $layer->{ type } =~ /down/ ) |
1199
|
|
|
|
|
|
|
{ |
1200
|
|
|
|
|
|
|
$y_size /= 2; |
1201
|
|
|
|
|
|
|
$val = $val > $y_size ? $y_size : $val; |
1202
|
|
|
|
|
|
|
$plot_val = $self->{ border }->[2] + $y_size + $val; |
1203
|
|
|
|
|
|
|
} |
1204
|
|
|
|
|
|
|
if ( $layer->{ type } =~ /line/ ) |
1205
|
|
|
|
|
|
|
{ |
1206
|
|
|
|
|
|
|
$poly->addPt( $plot_dot, $plot_val ); |
1207
|
|
|
|
|
|
|
} |
1208
|
|
|
|
|
|
|
elsif ( $layer->{ type } =~ /dot/ ) |
1209
|
|
|
|
|
|
|
{ |
1210
|
|
|
|
|
|
|
$frame->filledEllipse( $plot_dot, $plot_val, $thickness, $thickness, $col_graph ); |
1211
|
|
|
|
|
|
|
} |
1212
|
|
|
|
|
|
|
elsif ( $layer->{ type } =~ /bar/ ) |
1213
|
|
|
|
|
|
|
{ |
1214
|
|
|
|
|
|
|
$frame->filledRectangle( $plot_dot - $bar_size, $self->{ border }->[2] + $y_size - $layer->{ offset }, $plot_dot + $bar_size, $plot_val, $col_graph ); |
1215
|
|
|
|
|
|
|
} |
1216
|
|
|
|
|
|
|
} |
1217
|
|
|
|
|
|
|
$frame->unclosedPolygon( $poly, $col_graph ) if ( $layer->{ type } =~ /line/ ); |
1218
|
|
|
|
|
|
|
} |
1219
|
|
|
|
|
|
|
elsif ( $layer->{ type } eq 'pie' ) |
1220
|
|
|
|
|
|
|
{ |
1221
|
|
|
|
|
|
|
my $img_width = $self->{ size }->[0]; |
1222
|
|
|
|
|
|
|
my $img_height = $self->{ size }->[1]; |
1223
|
|
|
|
|
|
|
my $graph_offset = 0; |
1224
|
|
|
|
|
|
|
my $alarm_border = 0; |
1225
|
|
|
|
|
|
|
my $target_value_graph; |
1226
|
|
|
|
|
|
|
my $scale = 1; |
1227
|
|
|
|
|
|
|
|
1228
|
|
|
|
|
|
|
my $bar_size = $layer->{ bar_size } || 1; |
1229
|
|
|
|
|
|
|
if ( exists $layer->{ scale } ) |
1230
|
|
|
|
|
|
|
{ |
1231
|
|
|
|
|
|
|
if ( $layer->{ scale } =~ /^\d*\.*\d*$/ ) |
1232
|
|
|
|
|
|
|
{ |
1233
|
|
|
|
|
|
|
$scale = $layer->{ scale }; |
1234
|
|
|
|
|
|
|
} |
1235
|
|
|
|
|
|
|
} |
1236
|
|
|
|
|
|
|
$frame->filledArc( $img_width / 2 + $self->{ border }->[0], ( $img_height / 2 ) + $self->{ border }->[2], ( $img_height ) * $scale, ( $img_height ) * $scale, $last_pie, $layer->{ set }[-1] + $last_pie, $col_graph, gdEdged ); |
1237
|
|
|
|
|
|
|
$last_pie = $layer->{ set }[-1],; |
1238
|
|
|
|
|
|
|
} |
1239
|
|
|
|
|
|
|
elsif ( $layer->{ type } eq 'target' ) |
1240
|
|
|
|
|
|
|
{ |
1241
|
|
|
|
|
|
|
my $img_width = $self->{ size }->[0]; |
1242
|
|
|
|
|
|
|
my $img_height = $self->{ size }->[1]; |
1243
|
|
|
|
|
|
|
my $graph_offset = 0; |
1244
|
|
|
|
|
|
|
my $alarm_border = 0; |
1245
|
|
|
|
|
|
|
my $target_value_graph; |
1246
|
|
|
|
|
|
|
my $scale = 1; |
1247
|
|
|
|
|
|
|
|
1248
|
|
|
|
|
|
|
my $bar_size = $layer->{ bar_size } || 1; |
1249
|
|
|
|
|
|
|
if ( exists $layer->{ scale } ) |
1250
|
|
|
|
|
|
|
{ |
1251
|
|
|
|
|
|
|
if ( $layer->{ scale } =~ /^\d*\.*\d*$/ ) |
1252
|
|
|
|
|
|
|
{ |
1253
|
|
|
|
|
|
|
$scale = $layer->{ scale }; |
1254
|
|
|
|
|
|
|
} |
1255
|
|
|
|
|
|
|
} |
1256
|
|
|
|
|
|
|
$frame->filledArc( $img_width / 2 + $self->{ border }->[0], ( $img_height / 2 ) + $self->{ border }->[2], ( $img_height ) * $scale, ( $img_height ) * $scale, 0, $layer->{ set }[-1], $col_graph, gdEdged ); |
1257
|
|
|
|
|
|
|
} |
1258
|
|
|
|
|
|
|
elsif ( $layer->{ type } eq 'radial' ) |
1259
|
|
|
|
|
|
|
{ |
1260
|
|
|
|
|
|
|
my $img_width = $self->{ size }->[0]; |
1261
|
|
|
|
|
|
|
my $img_height = $self->{ size }->[1]; |
1262
|
|
|
|
|
|
|
my $graph_offset = 0; |
1263
|
|
|
|
|
|
|
my $alarm_border = 0; |
1264
|
|
|
|
|
|
|
my $target_value_graph; |
1265
|
|
|
|
|
|
|
my $tot = $self->{ size }->[1]; |
1266
|
|
|
|
|
|
|
my $max; |
1267
|
|
|
|
|
|
|
my $scale = 1; |
1268
|
|
|
|
|
|
|
my $pre_scale = 1; |
1269
|
|
|
|
|
|
|
my $bar_size = $layer->{ bar_size } || 1; |
1270
|
|
|
|
|
|
|
|
1271
|
|
|
|
|
|
|
if ( exists $layer->{ scale } || $layer->{ scale } eq 'auto' ) |
1272
|
|
|
|
|
|
|
{ |
1273
|
|
|
|
|
|
|
if ( $layer->{ scale } =~ /^\d*\.*\d*$/ ) |
1274
|
|
|
|
|
|
|
{ |
1275
|
|
|
|
|
|
|
$pre_scale = $layer->{ scale }; |
1276
|
|
|
|
|
|
|
} |
1277
|
|
|
|
|
|
|
$max = max( @{ $layer->{ set } } ); |
1278
|
|
|
|
|
|
|
$scale = $self->{ size }->[1] / ( $pre_scale * $max ); |
1279
|
|
|
|
|
|
|
} |
1280
|
|
|
|
|
|
|
my $dot = -1; |
1281
|
|
|
|
|
|
|
foreach my $raw_val ( @{ $layer->{ set } } ) |
1282
|
|
|
|
|
|
|
{ |
1283
|
|
|
|
|
|
|
my $plot_val = $raw_val * $scale; |
1284
|
|
|
|
|
|
|
$dot++; |
1285
|
|
|
|
|
|
|
$frame->filledArc( $img_width / 2 + $self->{ border }->[0], ( $img_height / 2 ) + $self->{ border }->[2], ( $plot_val ), ( $plot_val ), $dot, $dot + 1, $col_graph, gdEdged ); |
1286
|
|
|
|
|
|
|
} |
1287
|
|
|
|
|
|
|
} |
1288
|
|
|
|
|
|
|
} |
1289
|
|
|
|
|
|
|
} |
1290
|
|
|
|
|
|
|
### end plot |
1291
|
|
|
|
|
|
|
|
1292
|
|
|
|
|
|
|
### plot grid + label |
1293
|
|
|
|
|
|
|
if ( exists $self->{ grid } ) |
1294
|
|
|
|
|
|
|
{ |
1295
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y } ) |
1296
|
|
|
|
|
|
|
{ |
1297
|
|
|
|
|
|
|
$frame->setThickness( $self->{ grid }{ y }{ thickness } ); |
1298
|
|
|
|
|
|
|
my $grid_color = _color_allocate( $self->{ grid }{ y }{ color }, 'ffffffff', $frame ); |
1299
|
|
|
|
|
|
|
for my $nbr ( 0 .. ( $self->{ grid }{ y }{ number } - 1 ) ) |
1300
|
|
|
|
|
|
|
{ |
1301
|
|
|
|
|
|
|
my $val = ( ( $nbr ) * ( ( ( ( $self->{ size }->[0] ) / ( $self->{ grid }{ y }{ number } - 1 ) ) ) ) ); |
1302
|
|
|
|
|
|
|
$frame->line( $self->{ border }->[0] + $val, $self->{ border }->[2] - $self->{ grid }{ debord }->[2], $self->{ border }->[0] + $val, $self->{ size }->[1] + $self->{ border }->[2] + $self->{ grid }{ debord }->[3], $grid_color ); |
1303
|
|
|
|
|
|
|
if ( defined $self->{ grid }{ y }{ label }{ text }->[$nbr] ) |
1304
|
|
|
|
|
|
|
{ |
1305
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1306
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y }{ label }{ color } ) |
1307
|
|
|
|
|
|
|
{ |
1308
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ grid }{ y }{ label }{ color }, 'ffffffff', $frame ); |
1309
|
|
|
|
|
|
|
} |
1310
|
|
|
|
|
|
|
my $radian = ( $self->{ grid }{ y }{ label }{ rotation } / 180 ) * PI || 0; |
1311
|
|
|
|
|
|
|
my $kerning = $self->{ grid }{ y }{ label }{ kerning_correction } || 0.91; |
1312
|
|
|
|
|
|
|
my $cos = cos( $radian ); |
1313
|
|
|
|
|
|
|
my $sin = sin( $radian ); |
1314
|
|
|
|
|
|
|
my $Xoff; |
1315
|
|
|
|
|
|
|
my $Yoff; |
1316
|
|
|
|
|
|
|
my $len = length( $self->{ grid }{ y }{ label }{ text }->[$nbr] ); |
1317
|
|
|
|
|
|
|
|
1318
|
|
|
|
|
|
|
if ( $self->{ grid }{ y }{ label }{ rotation } ) |
1319
|
|
|
|
|
|
|
{ |
1320
|
|
|
|
|
|
|
$Xoff = ( $cos * ( $self->{ grid }{ y }{ label }{ size } ) ) - ( $cos * ( ( $len**$kerning ) * $self->{ grid }{ y }{ label }{ size } ) ); |
1321
|
|
|
|
|
|
|
$Yoff = ( $sin * ( ( $len**$kerning ) * $self->{ grid }{ y }{ label }{ size } ) ) + ( $sin * $self->{ grid }{ y }{ label }{ size } ); |
1322
|
|
|
|
|
|
|
} |
1323
|
|
|
|
|
|
|
else |
1324
|
|
|
|
|
|
|
{ |
1325
|
|
|
|
|
|
|
$Xoff = -( ( $len**$kerning ) * $self->{ grid }{ y }{ label }{ size } / 2 ); |
1326
|
|
|
|
|
|
|
$Yoff = $self->{ grid }{ y }{ label }{ size }; |
1327
|
|
|
|
|
|
|
} |
1328
|
|
|
|
|
|
|
if ( $self->{ grid }{ y }{ label }{ rotation } == 90 ) |
1329
|
|
|
|
|
|
|
{ |
1330
|
|
|
|
|
|
|
$Xoff = $self->{ grid }{ y }{ label }{ size } / 2; |
1331
|
|
|
|
|
|
|
$Yoff = ( ( $len**$kerning ) * $self->{ grid }{ y }{ label }{ size } ); |
1332
|
|
|
|
|
|
|
} |
1333
|
|
|
|
|
|
|
my @b = $frame->stringFT( |
1334
|
|
|
|
|
|
|
$text_color, |
1335
|
|
|
|
|
|
|
$self->{ grid }{ y }{ label }{ font }, |
1336
|
|
|
|
|
|
|
$self->{ grid }{ y }{ label }{ size }, |
1337
|
|
|
|
|
|
|
$radian, |
1338
|
|
|
|
|
|
|
$self->{ border }->[0] + $val + $Xoff, |
1339
|
|
|
|
|
|
|
$self->{ size }->[1] + |
1340
|
|
|
|
|
|
|
$self->{ border }->[2] + |
1341
|
|
|
|
|
|
|
$self->{ grid }{ debord }->[3] + |
1342
|
|
|
|
|
|
|
( $self->{ grid }{ y }{ label }{ space } || 0 ) + |
1343
|
|
|
|
|
|
|
$Yoff, |
1344
|
|
|
|
|
|
|
$self->{ grid }{ y }{ label }{ text }->[$nbr], |
1345
|
|
|
|
|
|
|
# { resolution => "95,95" } |
1346
|
|
|
|
|
|
|
); |
1347
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y }{ label }{ surround } ) |
1348
|
|
|
|
|
|
|
{ |
1349
|
|
|
|
|
|
|
my $surround_color = $grid_color; |
1350
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y }{ label }{ surround }{ color } ) |
1351
|
|
|
|
|
|
|
{ |
1352
|
|
|
|
|
|
|
$surround_color = _color_allocate( $self->{ grid }{ y }{ label }{ surround }{ color }, $self->{ grid }{ y }{ label }{ color }, $frame ); |
1353
|
|
|
|
|
|
|
} |
1354
|
|
|
|
|
|
|
$frame->setThickness( $self->{ grid }{ y }{ label }{ surround }{ thickness } ) |
1355
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y }{ label }{ surround }{ thickness } ); |
1356
|
|
|
|
|
|
|
my $polyT = new GD::Polygon; |
1357
|
|
|
|
|
|
|
$polyT->addPt( $b[0], $b[1] ); |
1358
|
|
|
|
|
|
|
$polyT->addPt( $b[2], $b[3] ); |
1359
|
|
|
|
|
|
|
$polyT->addPt( $b[4], $b[5] ); |
1360
|
|
|
|
|
|
|
$polyT->addPt( $b[6], $b[7] ); |
1361
|
|
|
|
|
|
|
$frame->openPolygon( $polyT, $surround_color ); |
1362
|
|
|
|
|
|
|
} |
1363
|
|
|
|
|
|
|
} |
1364
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y }{ label }{ text } && defined $self->{ grid }{ y }{ label2 }{ text }->[$nbr] ) |
1366
|
|
|
|
|
|
|
{ |
1367
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1368
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y }{ label2 }{ color } ) |
1369
|
|
|
|
|
|
|
{ |
1370
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ grid }{ y }{ label2 }{ color }, 'ffffffff', $frame ); |
1371
|
|
|
|
|
|
|
} |
1372
|
|
|
|
|
|
|
my $radian = ( $self->{ grid }{ y }{ label2 }{ rotation } / 180 ) * PI || 0; |
1373
|
|
|
|
|
|
|
my $kerning = $self->{ grid }{ y }{ label2 }{ kerning_correction } || 0.91; |
1374
|
|
|
|
|
|
|
my $cos = cos( $radian ); |
1375
|
|
|
|
|
|
|
my $sin = sin( $radian ); |
1376
|
|
|
|
|
|
|
my $Xoff = 0; |
1377
|
|
|
|
|
|
|
my $Yoff = 0; |
1378
|
|
|
|
|
|
|
my $len = length( $self->{ grid }{ y }{ label2 }{ text }->[$nbr] ); |
1379
|
|
|
|
|
|
|
|
1380
|
|
|
|
|
|
|
unless ( $self->{ grid }{ y }{ label2 }{ rotation } ) |
1381
|
|
|
|
|
|
|
{ |
1382
|
|
|
|
|
|
|
$Xoff = -( ( $len**$kerning ) * $self->{ grid }{ y }{ label2 }{ size } / 2 ); |
1383
|
|
|
|
|
|
|
} |
1384
|
|
|
|
|
|
|
if ( $self->{ grid }{ y }{ label2 }{ rotation } == 90 ) |
1385
|
|
|
|
|
|
|
{ |
1386
|
|
|
|
|
|
|
$Xoff = $self->{ grid }{ y }{ label2 }{ size } / 2; |
1387
|
|
|
|
|
|
|
} |
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
my @b = $frame->stringFT( |
1390
|
|
|
|
|
|
|
$text_color, |
1391
|
|
|
|
|
|
|
$self->{ grid }{ y }{ label2 }{ font }, |
1392
|
|
|
|
|
|
|
$self->{ grid }{ y }{ label2 }{ size }, |
1393
|
|
|
|
|
|
|
$radian, |
1394
|
|
|
|
|
|
|
$self->{ border }->[0] + $val + $Xoff, |
1395
|
|
|
|
|
|
|
$self->{ border }->[2] - $self->{ grid }{ debord }->[2] - ( $self->{ grid }{ y }{ label2 }{ space } || 0 ) - $Yoff, |
1396
|
|
|
|
|
|
|
$self->{ grid }{ y }{ label2 }{ text }->[$nbr], |
1397
|
|
|
|
|
|
|
# { resolution => "95,95" } |
1398
|
|
|
|
|
|
|
); |
1399
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y }{ label2 }{ surround } ) |
1400
|
|
|
|
|
|
|
{ |
1401
|
|
|
|
|
|
|
my $surround_color = $grid_color; |
1402
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y }{ label2 }{ surround }{ color } ) |
1403
|
|
|
|
|
|
|
{ |
1404
|
|
|
|
|
|
|
$surround_color = _color_allocater( $self->{ grid }{ y }{ label2 }{ surround }{ color }, $self->{ grid }{ y }{ label2 }{ color }, $frame ); |
1405
|
|
|
|
|
|
|
} |
1406
|
|
|
|
|
|
|
$frame->setThickness( $self->{ grid }{ y }{ label2 }{ surround }{ thickness } ) |
1407
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ y }{ label2 }{ surround }{ thickness } ); |
1408
|
|
|
|
|
|
|
my $polyT = new GD::Polygon; |
1409
|
|
|
|
|
|
|
$polyT->addPt( $b[0], $b[1] ); |
1410
|
|
|
|
|
|
|
$polyT->addPt( $b[2], $b[3] ); |
1411
|
|
|
|
|
|
|
$polyT->addPt( $b[4], $b[5] ); |
1412
|
|
|
|
|
|
|
$polyT->addPt( $b[6], $b[7] ); |
1413
|
|
|
|
|
|
|
$frame->openPolygon( $polyT, $surround_color ); |
1414
|
|
|
|
|
|
|
} |
1415
|
|
|
|
|
|
|
$frame->setThickness( 1 ); |
1416
|
|
|
|
|
|
|
} |
1417
|
|
|
|
|
|
|
} |
1418
|
|
|
|
|
|
|
} |
1419
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x } ) |
1420
|
|
|
|
|
|
|
{ |
1421
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x }{ thickness } ) |
1422
|
|
|
|
|
|
|
{ |
1423
|
|
|
|
|
|
|
$frame->setThickness( $self->{ grid }{ x }{ thickness } ); |
1424
|
|
|
|
|
|
|
} |
1425
|
|
|
|
|
|
|
my $grid_color = _color_allocate( $self->{ grid }{ x }{ color }, 'ffffffff', $frame ); |
1426
|
|
|
|
|
|
|
for ( my $nbr = $self->{ grid }{ x }{ number } - 1 ; $nbr >= 0 ; $nbr-- ) |
1427
|
|
|
|
|
|
|
{ |
1428
|
|
|
|
|
|
|
my $val = ( ( $nbr ) * ( ( ( ( $self->{ size }->[1] ) / ( $self->{ grid }{ x }{ number } - 1 ) ) ) ) ); |
1429
|
|
|
|
|
|
|
my $text_indx = $self->{ grid }{ x }{ number } - $nbr - 1; |
1430
|
|
|
|
|
|
|
|
1431
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x }{ type } && $self->{ grid }{ x }{ type } eq 'log' ) |
1432
|
|
|
|
|
|
|
{ |
1433
|
|
|
|
|
|
|
$text_indx = $nbr; |
1434
|
|
|
|
|
|
|
my $s = $self->{ size }->[1] / log( $self->{ grid }{ x }{ number } ); |
1435
|
|
|
|
|
|
|
$val = $self->{ size }->[1] - ( log( $nbr + 1 ) * $s ); |
1436
|
|
|
|
|
|
|
} |
1437
|
|
|
|
|
|
|
$frame->line( $self->{ border }->[0] - $self->{ grid }{ debord }->[0], $self->{ border }->[2] + $val, $self->{ border }->[0] + $self->{ size }->[0] + $self->{ grid }{ debord }->[1], $self->{ border }->[2] + $val, $grid_color ); |
1438
|
|
|
|
|
|
|
if ( defined $self->{ grid }{ x }{ label }{ text }->[$text_indx] ) |
1439
|
|
|
|
|
|
|
{ |
1440
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1441
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x }{ label }{ color } ) |
1442
|
|
|
|
|
|
|
{ |
1443
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ grid }{ x }{ label }{ color }, 'ffffffff', $frame ); |
1444
|
|
|
|
|
|
|
} |
1445
|
|
|
|
|
|
|
|
1446
|
|
|
|
|
|
|
my $radian = ( $self->{ grid }{ x }{ label }{ rotation } / 180 ) * PI || 0; |
1447
|
|
|
|
|
|
|
my $kerning = $self->{ grid }{ x }{ label }{ kerning_correction } || 0.91; |
1448
|
|
|
|
|
|
|
my $cos = cos( $radian ); |
1449
|
|
|
|
|
|
|
my $sin = sin( $radian ); |
1450
|
|
|
|
|
|
|
my $len = length( $self->{ grid }{ x }{ label }{ text }->[$text_indx] ); |
1451
|
|
|
|
|
|
|
my $Xoff; |
1452
|
|
|
|
|
|
|
my $Yoff; |
1453
|
|
|
|
|
|
|
|
1454
|
|
|
|
|
|
|
if ( $self->{ grid }{ x }{ label }{ align } eq 'right' ) |
1455
|
|
|
|
|
|
|
{ |
1456
|
|
|
|
|
|
|
$Xoff = -( ( $len**$kerning ) * $self->{ grid }{ x }{ label }{ size } ); |
1457
|
|
|
|
|
|
|
} |
1458
|
|
|
|
|
|
|
if ( $self->{ grid }{ x }{ label }{ rotation } ) |
1459
|
|
|
|
|
|
|
{ |
1460
|
|
|
|
|
|
|
$Xoff = ( $cos * ( $self->{ grid }{ x }{ label }{ size } ) ) - ( $cos * ( ( $len**$kerning ) * $self->{ grid }{ x }{ label }{ size } ) ); |
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
$Yoff = ( $sin * ( ( $len**$kerning ) * $self->{ grid }{ x }{ label }{ size } ) ) - ( $sin * $self->{ grid }{ x }{ label }{ size } ); |
1463
|
|
|
|
|
|
|
} |
1464
|
|
|
|
|
|
|
$frame->stringFT( $text_color, $self->{ grid }{ x }{ label }{ font }, $self->{ grid }{ x }{ label }{ size }, $radian, $self->{ border }->[0] - $self->{ grid }{ debord }->[0] + $Xoff - ( $self->{ grid }{ x }{ label }{ space } || 0 ), $self->{ border }->[2] + ( $self->{ grid }{ x }{ label }{ size } / 2 ) + $val + $Yoff, $self->{ grid }{ x }{ label }{ text }->[$text_indx] ); |
1465
|
|
|
|
|
|
|
} |
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
if ( defined $self->{ grid }{ x }{ label2 }{ text }->[$text_indx] ) |
1468
|
|
|
|
|
|
|
{ |
1469
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1470
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x }{ label2 }{ color } ) |
1471
|
|
|
|
|
|
|
{ |
1472
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ grid }{ x }{ label2 }{ color }, 'ffffffff', $frame ); |
1473
|
|
|
|
|
|
|
} |
1474
|
|
|
|
|
|
|
my $radian = ( $self->{ grid }{ x }{ label2 }{ rotation } / 180 ) * PI || 0; |
1475
|
|
|
|
|
|
|
my $kerning = $self->{ grid }{ x }{ label2 }{ kerning_correction } || 0.91; |
1476
|
|
|
|
|
|
|
my $cos = cos( $radian ); |
1477
|
|
|
|
|
|
|
my $sin = sin( $radian ); |
1478
|
|
|
|
|
|
|
my $len = length( $self->{ grid }{ x }{ label2 }{ text }->[$text_indx] ); |
1479
|
|
|
|
|
|
|
my $Xoff = 0; |
1480
|
|
|
|
|
|
|
my $Yoff = 0; |
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
if ( $self->{ grid }{ x }{ label2 }{ align } eq 'right' ) |
1483
|
|
|
|
|
|
|
{ |
1484
|
|
|
|
|
|
|
$Xoff = -( ( $len**$kerning ) * $self->{ grid }{ x }{ label2 }{ size } ); |
1485
|
|
|
|
|
|
|
} |
1486
|
|
|
|
|
|
|
$frame->stringFT( |
1487
|
|
|
|
|
|
|
$text_color, |
1488
|
|
|
|
|
|
|
$self->{ grid }{ x }{ label2 }{ font }, |
1489
|
|
|
|
|
|
|
$self->{ grid }{ x }{ label2 }{ size }, |
1490
|
|
|
|
|
|
|
$radian, |
1491
|
|
|
|
|
|
|
$self->{ border }->[0] + $self->{ grid }{ debord }->[1] + $Xoff + $self->{ grid }{ x }{ label2 }{ space } + $self->{ size }->[0], |
1492
|
|
|
|
|
|
|
$self->{ border }->[2] + ( $self->{ grid }{ x }{ label2 }{ size } / 2 ) + $val + $Yoff, |
1493
|
|
|
|
|
|
|
$self->{ grid }{ x }{ label2 }{ text }->[$text_indx] |
1494
|
|
|
|
|
|
|
); |
1495
|
|
|
|
|
|
|
} |
1496
|
|
|
|
|
|
|
} |
1497
|
|
|
|
|
|
|
} |
1498
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_up } ) |
1499
|
|
|
|
|
|
|
{ |
1500
|
|
|
|
|
|
|
$frame->setThickness( $self->{ grid }{ x_up }{ thickness } ); |
1501
|
|
|
|
|
|
|
my $grid_color = _color_allocate( $self->{ grid }{ x_up }{ color }, 'ffffffff', $frame ); |
1502
|
|
|
|
|
|
|
|
1503
|
|
|
|
|
|
|
for ( my $nbr = $self->{ grid }{ x_up }{ number } ; $nbr >= 1 ; $nbr-- ) |
1504
|
|
|
|
|
|
|
{ |
1505
|
|
|
|
|
|
|
my $val = ( $nbr - 1 ) * ( int( ( $self->{ size }->[1] ) / ( $self->{ grid }{ x_up }{ number } - 1 ) ) ); |
1506
|
|
|
|
|
|
|
my $text_indx = $self->{ grid }{ x_up }{ number } - $nbr; |
1507
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_up }{ type } && $self->{ grid }{ x_up }{ type } eq 'log' ) |
1508
|
|
|
|
|
|
|
{ |
1509
|
|
|
|
|
|
|
$text_indx = $nbr - 1; |
1510
|
|
|
|
|
|
|
my $s = $self->{ size }->[1] / log( $self->{ grid }{ x_up }{ number } ) / 2; |
1511
|
|
|
|
|
|
|
$val = ( $self->{ size }->[1] / 2 ) - ( log( $nbr ) * $s ); |
1512
|
|
|
|
|
|
|
} |
1513
|
|
|
|
|
|
|
else |
1514
|
|
|
|
|
|
|
{ |
1515
|
|
|
|
|
|
|
$val /= 2; |
1516
|
|
|
|
|
|
|
} |
1517
|
|
|
|
|
|
|
|
1518
|
|
|
|
|
|
|
$frame->line( $self->{ border }->[0] - $self->{ grid }{ debord }->[0], $self->{ border }->[2] + 1 + $val, $self->{ border }->[0] + $self->{ size }->[0] + $self->{ grid }{ debord }->[1], $self->{ border }->[2] + 1 + $val, $grid_color ); |
1519
|
|
|
|
|
|
|
if ( defined $self->{ grid }{ x_up }{ label }{ text }->[$text_indx] ) |
1520
|
|
|
|
|
|
|
{ |
1521
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1522
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_up }{ label }{ color } ) |
1523
|
|
|
|
|
|
|
{ |
1524
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ grid }{ x_up }{ label }{ color }, 'ffffffff', $frame ); |
1525
|
|
|
|
|
|
|
} |
1526
|
|
|
|
|
|
|
|
1527
|
|
|
|
|
|
|
my $radian = ( $self->{ grid }{ x_up }{ label }{ rotation } / 180 ) * PI || 0; |
1528
|
|
|
|
|
|
|
my $kerning = $self->{ grid }{ x_up }{ label }{ kerning_correction } || 0.91; |
1529
|
|
|
|
|
|
|
my $cos = cos( $radian ); |
1530
|
|
|
|
|
|
|
my $sin = sin( $radian ); |
1531
|
|
|
|
|
|
|
my $len = length( $self->{ grid }{ x_up }{ label }{ text }->[$text_indx] ); |
1532
|
|
|
|
|
|
|
my $Xoff; |
1533
|
|
|
|
|
|
|
my $Yoff; |
1534
|
|
|
|
|
|
|
|
1535
|
|
|
|
|
|
|
if ( $self->{ grid }{ x_up }{ label }{ align } eq 'right' ) |
1536
|
|
|
|
|
|
|
{ |
1537
|
|
|
|
|
|
|
$Xoff = -( ( $len**$kerning ) * $self->{ grid }{ x_up }{ label }{ size } ); |
1538
|
|
|
|
|
|
|
} |
1539
|
|
|
|
|
|
|
if ( $self->{ grid }{ x_up }{ label }{ rotation } ) |
1540
|
|
|
|
|
|
|
{ |
1541
|
|
|
|
|
|
|
$Xoff = ( $cos * ( $self->{ grid }{ x_up }{ label }{ size } ) ) - ( $cos * ( ( $len**$kerning ) * $self->{ grid }{ x_up }{ label }{ size } ) ); |
1542
|
|
|
|
|
|
|
|
1543
|
|
|
|
|
|
|
$Yoff = ( $sin * ( ( $len**$kerning ) * $self->{ grid }{ x_up }{ label }{ size } ) ) - ( $sin * $self->{ grid }{ x_up }{ label }{ size } ); |
1544
|
|
|
|
|
|
|
} |
1545
|
|
|
|
|
|
|
$frame->stringFT( $text_color, $self->{ grid }{ x_up }{ label }{ font }, $self->{ grid }{ x_up }{ label }{ size }, $radian, $self->{ border }->[0] - $self->{ grid }{ debord }->[0] + $Xoff - $self->{ grid }{ x_up }{ label }{ space }, $self->{ border }->[2] + ( $self->{ grid }{ x_up }{ label }{ size } / 2 ) + $val + $Yoff, $self->{ grid }{ x_up }{ label }{ text }->[$text_indx] ); |
1546
|
|
|
|
|
|
|
} |
1547
|
|
|
|
|
|
|
|
1548
|
|
|
|
|
|
|
if ( defined $self->{ grid }{ x_up }{ label2 }{ text }->[$text_indx] ) |
1549
|
|
|
|
|
|
|
{ |
1550
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1551
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_up }{ label2 }{ color } ) |
1552
|
|
|
|
|
|
|
{ |
1553
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ grid }{ x_up }{ label2 }{ color }, 'ffffffff', $frame ); |
1554
|
|
|
|
|
|
|
} |
1555
|
|
|
|
|
|
|
my $radian = ( $self->{ grid }{ x_up }{ label2 }{ rotation } / 180 ) * PI || 0; |
1556
|
|
|
|
|
|
|
my $kerning = $self->{ grid }{ x_up }{ label2 }{ kerning_correction } || 0.91; |
1557
|
|
|
|
|
|
|
my $cos = cos( $radian ); |
1558
|
|
|
|
|
|
|
my $sin = sin( $radian ); |
1559
|
|
|
|
|
|
|
my $len = length( $self->{ grid }{ x_up }{ label2 }{ text }->[$text_indx] ); |
1560
|
|
|
|
|
|
|
my $Xoff; |
1561
|
|
|
|
|
|
|
my $Yoff; |
1562
|
|
|
|
|
|
|
|
1563
|
|
|
|
|
|
|
if ( $self->{ grid }{ x_up }{ label2 }{ align } eq 'right' ) |
1564
|
|
|
|
|
|
|
{ |
1565
|
|
|
|
|
|
|
$Xoff = -( ( $len**$kerning ) * $self->{ grid }{ x_up }{ label2 }{ size } ); |
1566
|
|
|
|
|
|
|
} |
1567
|
|
|
|
|
|
|
$frame->stringFT( |
1568
|
|
|
|
|
|
|
$text_color, |
1569
|
|
|
|
|
|
|
$self->{ grid }{ x_up }{ label2 }{ font }, |
1570
|
|
|
|
|
|
|
$self->{ grid }{ x_up }{ label2 }{ size }, |
1571
|
|
|
|
|
|
|
$radian, |
1572
|
|
|
|
|
|
|
$self->{ border }->[0] + $self->{ grid }{ debord }->[1] + $Xoff + $self->{ grid }{ x_up }{ label2 }{ space } + $self->{ size }->[0], |
1573
|
|
|
|
|
|
|
$self->{ border }->[2] + ( $self->{ grid }{ x_up }{ label2 }{ size } / 2 ) + $val + $Yoff, |
1574
|
|
|
|
|
|
|
$self->{ grid }{ x_up }{ label2 }{ text }->[$text_indx] |
1575
|
|
|
|
|
|
|
); |
1576
|
|
|
|
|
|
|
} |
1577
|
|
|
|
|
|
|
} |
1578
|
|
|
|
|
|
|
} |
1579
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_down } ) |
1580
|
|
|
|
|
|
|
{ |
1581
|
|
|
|
|
|
|
$frame->setThickness( $self->{ grid }{ x_down }{ thickness } ); |
1582
|
|
|
|
|
|
|
my $grid_color = _color_allocate( $self->{ grid }{ x_down }{ color }, 'ffffffff', $frame ); |
1583
|
|
|
|
|
|
|
for ( my $nbr = $self->{ grid }{ x_down }{ number } ; $nbr >= 1 ; $nbr-- ) |
1584
|
|
|
|
|
|
|
{ |
1585
|
|
|
|
|
|
|
my $val = ( $nbr - 1 ) * ( int( ( $self->{ size }->[1] ) / ( $self->{ grid }{ x_down }{ number } - 1 ) ) ); |
1586
|
|
|
|
|
|
|
my $text_indx = $self->{ grid }{ x_down }{ number } - $nbr; |
1587
|
|
|
|
|
|
|
my $x_offset = 0; |
1588
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_down }{ type } && $self->{ grid }{ x_down }{ type } eq 'log' ) |
1589
|
|
|
|
|
|
|
{ |
1590
|
|
|
|
|
|
|
$text_indx = $nbr - 1; |
1591
|
|
|
|
|
|
|
my $s = $self->{ size }->[1] / log( $self->{ grid }{ x_down }{ number } ) / 2; |
1592
|
|
|
|
|
|
|
$val = ( $self->{ size }->[1] / 2 ) + ( log( $nbr ) * $s ); |
1593
|
|
|
|
|
|
|
} |
1594
|
|
|
|
|
|
|
else |
1595
|
|
|
|
|
|
|
{ |
1596
|
|
|
|
|
|
|
$x_offset = $self->{ size }->[1] / 2; |
1597
|
|
|
|
|
|
|
$val /= 2; |
1598
|
|
|
|
|
|
|
} |
1599
|
|
|
|
|
|
|
$frame->line( $self->{ border }->[0] - $self->{ grid }{ debord }->[0], $self->{ border }->[2] + 1 + $val + $x_offset, $self->{ border }->[0] + $self->{ size }->[0] + $self->{ grid }{ debord }->[1], $self->{ border }->[2] + 1 + $val + $x_offset, $grid_color ); |
1600
|
|
|
|
|
|
|
if ( defined $self->{ grid }{ x_down }{ label }{ text }->[$text_indx] ) |
1601
|
|
|
|
|
|
|
{ |
1602
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1603
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_down }{ label }{ color } ) |
1604
|
|
|
|
|
|
|
{ |
1605
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ grid }{ x_down }{ label }{ color }, 'ffffffff', $frame ); |
1606
|
|
|
|
|
|
|
} |
1607
|
|
|
|
|
|
|
|
1608
|
|
|
|
|
|
|
my $radian = ( $self->{ grid }{ x_down }{ label }{ rotation } / 180 ) * PI || 0; |
1609
|
|
|
|
|
|
|
my $kerning = $self->{ grid }{ x_down }{ label }{ kerning_correction } || 0.91; |
1610
|
|
|
|
|
|
|
my $cos = cos( $radian ); |
1611
|
|
|
|
|
|
|
my $sin = sin( $radian ); |
1612
|
|
|
|
|
|
|
my $len = length( $self->{ grid }{ x_down }{ label }{ text }->[$text_indx] ); |
1613
|
|
|
|
|
|
|
my $Xoff; |
1614
|
|
|
|
|
|
|
my $Yoff; |
1615
|
|
|
|
|
|
|
|
1616
|
|
|
|
|
|
|
if ( $self->{ grid }{ x_down }{ label }{ align } eq 'right' ) |
1617
|
|
|
|
|
|
|
{ |
1618
|
|
|
|
|
|
|
$Xoff = -( ( $len**$kerning ) * $self->{ grid }{ x_down }{ label }{ size } ); |
1619
|
|
|
|
|
|
|
} |
1620
|
|
|
|
|
|
|
if ( $self->{ grid }{ x_down }{ label }{ rotation } ) |
1621
|
|
|
|
|
|
|
{ |
1622
|
|
|
|
|
|
|
$Xoff = ( $cos * ( $self->{ grid }{ x_down }{ label }{ size } ) ) - ( $cos * ( ( $len**$kerning ) * $self->{ grid }{ x_down }{ label }{ size } ) ); |
1623
|
|
|
|
|
|
|
|
1624
|
|
|
|
|
|
|
$Yoff = ( $sin * ( ( $len**$kerning ) * $self->{ grid }{ x_down }{ label }{ size } ) ) - ( $sin * $self->{ grid }{ x_down }{ label }{ size } ); |
1625
|
|
|
|
|
|
|
} |
1626
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_down }{ type } && $self->{ grid }{ x_down }{ type } eq 'log' ) |
1627
|
|
|
|
|
|
|
{ |
1628
|
|
|
|
|
|
|
$x_offset = 0; |
1629
|
|
|
|
|
|
|
$val *= -1; |
1630
|
|
|
|
|
|
|
} |
1631
|
|
|
|
|
|
|
else |
1632
|
|
|
|
|
|
|
{ |
1633
|
|
|
|
|
|
|
$x_offset = $self->{ size }->[1]; |
1634
|
|
|
|
|
|
|
} |
1635
|
|
|
|
|
|
|
$frame->stringFT( |
1636
|
|
|
|
|
|
|
$text_color, |
1637
|
|
|
|
|
|
|
$self->{ grid }{ x_down }{ label }{ font }, |
1638
|
|
|
|
|
|
|
$self->{ grid }{ x_down }{ label }{ size }, |
1639
|
|
|
|
|
|
|
$radian, |
1640
|
|
|
|
|
|
|
$self->{ border }->[0] - $self->{ grid }{ debord }->[0] + $Xoff - $self->{ grid }{ x_down }{ label }{ space }, |
1641
|
|
|
|
|
|
|
$self->{ border }->[2] + ( $self->{ grid }{ x_down }{ label }{ size } / 2 ) - $val + $Yoff + $x_offset, |
1642
|
|
|
|
|
|
|
$self->{ grid }{ x_down }{ label }{ text }->[$text_indx] |
1643
|
|
|
|
|
|
|
); |
1644
|
|
|
|
|
|
|
} |
1645
|
|
|
|
|
|
|
|
1646
|
|
|
|
|
|
|
if ( defined $self->{ grid }{ x_down }{ label2 }{ text }->[$text_indx] ) |
1647
|
|
|
|
|
|
|
{ |
1648
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1649
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_down }{ label2 }{ color } ) |
1650
|
|
|
|
|
|
|
{ |
1651
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ grid }{ x_down }{ label2 }{ color }, 'ffffffff', $frame ); |
1652
|
|
|
|
|
|
|
} |
1653
|
|
|
|
|
|
|
my $radian = ( $self->{ grid }{ x_down }{ label2 }{ rotation } / 180 ) * PI || 0; |
1654
|
|
|
|
|
|
|
my $kerning = $self->{ grid }{ x_down }{ label2 }{ kerning_correction } || 0.91; |
1655
|
|
|
|
|
|
|
my $cos = cos( $radian ); |
1656
|
|
|
|
|
|
|
my $sin = sin( $radian ); |
1657
|
|
|
|
|
|
|
my $len = length( $self->{ grid }{ x_down }{ label2 }{ text }->[$text_indx] ); |
1658
|
|
|
|
|
|
|
my $Xoff; |
1659
|
|
|
|
|
|
|
my $Yoff; |
1660
|
|
|
|
|
|
|
|
1661
|
|
|
|
|
|
|
if ( $self->{ grid }{ x_down }{ label2 }{ align } eq 'right' ) |
1662
|
|
|
|
|
|
|
{ |
1663
|
|
|
|
|
|
|
$Xoff = -( ( $len**$kerning ) * $self->{ grid }{ x_down }{ label2 }{ size } ); |
1664
|
|
|
|
|
|
|
} |
1665
|
|
|
|
|
|
|
if ( exists $self->{ grid }{ x_down }{ type } && $self->{ grid }{ x_down }{ type } eq 'log' ) |
1666
|
|
|
|
|
|
|
{ |
1667
|
|
|
|
|
|
|
$x_offset = 0; |
1668
|
|
|
|
|
|
|
$val *= -1; |
1669
|
|
|
|
|
|
|
} |
1670
|
|
|
|
|
|
|
else |
1671
|
|
|
|
|
|
|
{ |
1672
|
|
|
|
|
|
|
$x_offset = $self->{ size }->[1]; |
1673
|
|
|
|
|
|
|
} |
1674
|
|
|
|
|
|
|
$frame->stringFT( |
1675
|
|
|
|
|
|
|
$text_color, |
1676
|
|
|
|
|
|
|
$self->{ grid }{ x_down }{ label2 }{ font }, |
1677
|
|
|
|
|
|
|
$self->{ grid }{ x_down }{ label2 }{ size }, |
1678
|
|
|
|
|
|
|
$radian, |
1679
|
|
|
|
|
|
|
$self->{ border }->[0] + $self->{ grid }{ debord }->[1] + $Xoff + $self->{ grid }{ x_down }{ label2 }{ space } + $self->{ size }->[0], |
1680
|
|
|
|
|
|
|
$self->{ border }->[2] + ( $self->{ grid }{ x_down }{ label2 }{ size } / 2 ) - $val + $Yoff + $x_offset, |
1681
|
|
|
|
|
|
|
$self->{ grid }{ x_down }{ label2 }{ text }->[$text_indx] |
1682
|
|
|
|
|
|
|
); |
1683
|
|
|
|
|
|
|
} |
1684
|
|
|
|
|
|
|
} |
1685
|
|
|
|
|
|
|
} |
1686
|
|
|
|
|
|
|
} |
1687
|
|
|
|
|
|
|
### end plot grid +label |
1688
|
|
|
|
|
|
|
$frame->setThickness( 1 ); |
1689
|
|
|
|
|
|
|
|
1690
|
|
|
|
|
|
|
### plot reticle +label |
1691
|
|
|
|
|
|
|
if ( exists $self->{ reticle } ) |
1692
|
|
|
|
|
|
|
{ |
1693
|
|
|
|
|
|
|
$frame->setThickness( $self->{ reticle }{ thickness } ) || 1; |
1694
|
|
|
|
|
|
|
my $grid_color = _color_allocate( $self->{ reticle }{ color }, '00000000', $frame ); |
1695
|
|
|
|
|
|
|
my $angle_inc = ( PI ) / ( $self->{ reticle }{ number } / 2 ); |
1696
|
|
|
|
|
|
|
|
1697
|
|
|
|
|
|
|
for my $nbr ( 1 .. ( $self->{ reticle }{ number } ) ) |
1698
|
|
|
|
|
|
|
{ |
1699
|
|
|
|
|
|
|
my $polyline = new GD::Polyline; |
1700
|
|
|
|
|
|
|
my $text_angle = 0; |
1701
|
|
|
|
|
|
|
my $angle = ( $angle_inc * ( -$nbr ) ) + ( PI / 2 ); |
1702
|
|
|
|
|
|
|
$polyline->addPt( ( $self->{ size }[0] / 2 ) + $self->{ border }[0], $self->{ border }[2] + ( $self->{ size }[1] / 2 ) ); |
1703
|
|
|
|
|
|
|
$polyline->addPt( ( $self->{ size }[0] / 2 ) + $self->{ border }[0], $self->{ border }[2] + $self->{ size }[1] + $self->{ reticle }{ debord } ); |
1704
|
|
|
|
|
|
|
$polyline->rotate( $angle, ( $self->{ size }[0] / 2 ) + $self->{ border }[0], $self->{ border }[2] + ( $self->{ size }[1] / 2 ) ); |
1705
|
|
|
|
|
|
|
$frame->polydraw( $polyline, $grid_color ); |
1706
|
|
|
|
|
|
|
my $val = ( $nbr - 1 ) * ( int( ( $self->{ size }->[1] ) / ( $self->{ reticle }{ number } - 1 ) ) ); |
1707
|
|
|
|
|
|
|
|
1708
|
|
|
|
|
|
|
if ( defined $self->{ reticle }{ label_middle }{ text }->[ $nbr - 1 ] ) |
1709
|
|
|
|
|
|
|
{ |
1710
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1711
|
|
|
|
|
|
|
if ( exists $self->{ reticle }{ label_middle }{ color } ) |
1712
|
|
|
|
|
|
|
{ |
1713
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ reticle }{ label_middle }{ color }, 'ffffffff', $frame ); |
1714
|
|
|
|
|
|
|
} |
1715
|
|
|
|
|
|
|
my $kerning = $self->{ reticle }{ label_middle }{ kerning_correction } || 0.91; |
1716
|
|
|
|
|
|
|
my $len = length( $self->{ reticle }{ label_middle }{ text }->[ $nbr - 1 ] ); |
1717
|
|
|
|
|
|
|
my $beta; |
1718
|
|
|
|
|
|
|
my $c; |
1719
|
|
|
|
|
|
|
my $pos_angle = ( $angle_inc * ( $nbr ) ) + PI - ( PI / $self->{ reticle }{ number } ); |
1720
|
|
|
|
|
|
|
if ( exists $self->{ reticle }{ label_middle }{ rotate } ) |
1721
|
|
|
|
|
|
|
{ |
1722
|
|
|
|
|
|
|
|
1723
|
|
|
|
|
|
|
if ( $self->{ reticle }{ label_middle }{ rotate } eq 'perpendicular' ) |
1724
|
|
|
|
|
|
|
{ |
1725
|
|
|
|
|
|
|
$text_angle = ( PI / 2 ) + ( $angle_inc * ( -$nbr ) ) + ( PI / $self->{ reticle }{ number } ); |
1726
|
|
|
|
|
|
|
$c = ( ( ( ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } + $self->{ reticle }{ label_middle }{ space } )**2 ) + ( ( ( ( $len**$kerning ) * $self->{ reticle }{ label_middle }{ size } ) / 2 )**2 ) )**.5; |
1727
|
|
|
|
|
|
|
$beta = asin( ( ( ( $len**$kerning ) * $self->{ reticle }{ label_middle }{ size } ) / 2 ) / $c ); |
1728
|
|
|
|
|
|
|
} |
1729
|
|
|
|
|
|
|
else |
1730
|
|
|
|
|
|
|
{ |
1731
|
|
|
|
|
|
|
$text_angle = ( $angle_inc * ( -$nbr ) ) + ( PI / $self->{ reticle }{ number } ); |
1732
|
|
|
|
|
|
|
$c = ( ( ( ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } + $self->{ reticle }{ label_middle }{ space } )**2 ) + ( ( ( $self->{ reticle }{ label }{ size } ) / 2 )**2 ) )**.5; |
1733
|
|
|
|
|
|
|
$beta = asin( ( ( $self->{ reticle }{ label }{ size } ) / 2 ) / $c ); |
1734
|
|
|
|
|
|
|
} |
1735
|
|
|
|
|
|
|
} |
1736
|
|
|
|
|
|
|
my $cos = cos( $pos_angle + $beta ); |
1737
|
|
|
|
|
|
|
my $sin = sin( $pos_angle + $beta ); |
1738
|
|
|
|
|
|
|
my $Xoff = $cos * ( $self->{ reticle }{ label_middle }{ space } + ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } ); |
1739
|
|
|
|
|
|
|
my $Yoff = $sin * ( $self->{ reticle }{ label_middle }{ space } + ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } ); |
1740
|
|
|
|
|
|
|
|
1741
|
|
|
|
|
|
|
if ( exists $self->{ reticle }{ label_middle }{ rotate } ) |
1742
|
|
|
|
|
|
|
{ |
1743
|
|
|
|
|
|
|
if ( $self->{ reticle }{ label_middle }{ rotate } eq 'perpendicular' ) |
1744
|
|
|
|
|
|
|
{ |
1745
|
|
|
|
|
|
|
$Xoff = $cos * ( $self->{ reticle }{ label_middle }{ space } + $c + ( $self->{ reticle }{ label_middle }{ size } ) ); |
1746
|
|
|
|
|
|
|
$Yoff = $sin * ( $self->{ reticle }{ label_middle }{ space } + $c + ( $self->{ reticle }{ label_middle }{ size } ) ); |
1747
|
|
|
|
|
|
|
} |
1748
|
|
|
|
|
|
|
else |
1749
|
|
|
|
|
|
|
{ |
1750
|
|
|
|
|
|
|
$Xoff = $cos * ( $self->{ reticle }{ label_middle }{ size } + $self->{ reticle }{ label_middle }{ space } + ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } ); |
1751
|
|
|
|
|
|
|
$Yoff = $sin * ( $self->{ reticle }{ label_middle }{ size } + $self->{ reticle }{ label_middle }{ space } + ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } ); |
1752
|
|
|
|
|
|
|
} |
1753
|
|
|
|
|
|
|
} |
1754
|
|
|
|
|
|
|
$frame->stringFT( $text_color, $self->{ reticle }{ label_middle }{ font }, $self->{ reticle }{ label_middle }{ size }, $text_angle, ( $self->{ size }[0] / 2 ) + $self->{ border }[0] - $Xoff, $self->{ border }[2] + ( $self->{ size }[1] / 2 ) - $Yoff, $self->{ reticle }{ label_middle }{ text }->[ $nbr - 1 ] ); |
1755
|
|
|
|
|
|
|
} |
1756
|
|
|
|
|
|
|
|
1757
|
|
|
|
|
|
|
if ( defined $self->{ reticle }{ label }{ text }->[ $nbr - 1 ] ) |
1758
|
|
|
|
|
|
|
{ |
1759
|
|
|
|
|
|
|
my $text_color = $grid_color; |
1760
|
|
|
|
|
|
|
if ( exists $self->{ reticle }{ label }{ color } ) |
1761
|
|
|
|
|
|
|
{ |
1762
|
|
|
|
|
|
|
$text_color = _color_allocate( $self->{ reticle }{ label }{ color }, 'ffffffff', $frame ); |
1763
|
|
|
|
|
|
|
} |
1764
|
|
|
|
|
|
|
my $kerning = $self->{ reticle }{ label }{ kerning_correction } || 0.91; |
1765
|
|
|
|
|
|
|
my $len = length( $self->{ reticle }{ label }{ text }->[ $nbr - 1 ] ); |
1766
|
|
|
|
|
|
|
my $beta; |
1767
|
|
|
|
|
|
|
my $c; |
1768
|
|
|
|
|
|
|
my $pos_angle = ( $angle_inc * ( $nbr ) ) + PI - ( 2 * PI / $self->{ reticle }{ number } ); |
1769
|
|
|
|
|
|
|
|
1770
|
|
|
|
|
|
|
if ( exists $self->{ reticle }{ label }{ rotate } ) |
1771
|
|
|
|
|
|
|
{ |
1772
|
|
|
|
|
|
|
if ( $self->{ reticle }{ label }{ rotate } eq 'perpendicular' ) |
1773
|
|
|
|
|
|
|
{ |
1774
|
|
|
|
|
|
|
$text_angle = ( PI / 2 ) + ( $angle_inc * ( -$nbr ) ) + ( 2 * PI / $self->{ reticle }{ number } ); |
1775
|
|
|
|
|
|
|
$c = ( ( ( ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } + $self->{ reticle }{ label_middle }{ space } )**2 ) + ( ( ( ( $len**$kerning ) * $self->{ reticle }{ label }{ size } ) / 2 )**2 ) )**.5; |
1776
|
|
|
|
|
|
|
$beta = asin( ( ( ( $len**$kerning ) * $self->{ reticle }{ label }{ size } ) / 2 ) / $c ); |
1777
|
|
|
|
|
|
|
} |
1778
|
|
|
|
|
|
|
else |
1779
|
|
|
|
|
|
|
{ |
1780
|
|
|
|
|
|
|
$text_angle = ( $angle_inc * ( -$nbr ) ) + ( 2 * PI / $self->{ reticle }{ number } ); |
1781
|
|
|
|
|
|
|
$c = ( ( ( ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } + $self->{ reticle }{ label_middle }{ space } )**2 ) + ( ( ( $self->{ reticle }{ label }{ size } ) / 2 )**2 ) )**.5; |
1782
|
|
|
|
|
|
|
$beta = asin( ( ( $self->{ reticle }{ label }{ size } ) / 2 ) / $c ); |
1783
|
|
|
|
|
|
|
} |
1784
|
|
|
|
|
|
|
} |
1785
|
|
|
|
|
|
|
my $cos = cos( $pos_angle + $beta ); |
1786
|
|
|
|
|
|
|
my $sin = sin( $pos_angle + $beta ); |
1787
|
|
|
|
|
|
|
my $Xoff = $cos * ( $self->{ reticle }{ label }{ space } + ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } ); |
1788
|
|
|
|
|
|
|
my $Yoff = $sin * ( $self->{ reticle }{ label }{ space } + ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } ); |
1789
|
|
|
|
|
|
|
|
1790
|
|
|
|
|
|
|
if ( exists $self->{ reticle }{ label }{ rotate } ) |
1791
|
|
|
|
|
|
|
{ |
1792
|
|
|
|
|
|
|
if ( $self->{ reticle }{ label }{ rotate } eq 'perpendicular' ) |
1793
|
|
|
|
|
|
|
{ |
1794
|
|
|
|
|
|
|
$Xoff = $cos * ( $self->{ reticle }{ label }{ space } + $c + ( $self->{ reticle }{ label }{ size } ) ); |
1795
|
|
|
|
|
|
|
$Yoff = $sin * ( $self->{ reticle }{ label }{ space } + $c + ( $self->{ reticle }{ label }{ size } ) ); |
1796
|
|
|
|
|
|
|
} |
1797
|
|
|
|
|
|
|
else |
1798
|
|
|
|
|
|
|
{ |
1799
|
|
|
|
|
|
|
$Xoff = $cos * ( $self->{ reticle }{ label }{ size } + $self->{ reticle }{ label }{ space } + ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } ); |
1800
|
|
|
|
|
|
|
$Yoff = $sin * ( $self->{ reticle }{ label }{ size } + $self->{ reticle }{ label }{ space } + ( $self->{ size }[1] / 2 ) + $self->{ reticle }{ debord } ); |
1801
|
|
|
|
|
|
|
} |
1802
|
|
|
|
|
|
|
} |
1803
|
|
|
|
|
|
|
$frame->stringFT( $text_color, $self->{ reticle }{ label }{ font }, $self->{ reticle }{ label }{ size }, $text_angle, ( $self->{ size }[0] / 2 ) + $self->{ border }[0] - $Xoff, $self->{ border }[2] + ( $self->{ size }[1] / 2 ) - $Yoff, $self->{ reticle }{ label }{ text }->[ $nbr - 1 ] ); |
1804
|
|
|
|
|
|
|
} |
1805
|
|
|
|
|
|
|
} |
1806
|
|
|
|
|
|
|
} |
1807
|
|
|
|
|
|
|
### end plot reticle +label |
1808
|
|
|
|
|
|
|
|
1809
|
|
|
|
|
|
|
### plot frame around main chart |
1810
|
|
|
|
|
|
|
if ( exists $self->{ frame } ) |
1811
|
|
|
|
|
|
|
{ |
1812
|
|
|
|
|
|
|
my $frame_color = _color_allocate( $self->{ frame }{ color }, '00000000', $frame ); |
1813
|
|
|
|
|
|
|
|
1814
|
|
|
|
|
|
|
my $polyF = new GD::Polygon; |
1815
|
|
|
|
|
|
|
$frame->setThickness( $self->{ frame }{ thickness } ); |
1816
|
|
|
|
|
|
|
$polyF->addPt( $self->{ border }->[0], $self->{ border }->[2] ); |
1817
|
|
|
|
|
|
|
$polyF->addPt( $self->{ border }->[0], $self->{ border }->[2] + $self->{ size }->[1] ); |
1818
|
|
|
|
|
|
|
$polyF->addPt( $self->{ border }->[0] + $self->{ size }->[0], $self->{ border }->[2] + $self->{ size }->[1] ); |
1819
|
|
|
|
|
|
|
$polyF->addPt( $self->{ border }->[0] + $self->{ size }->[0], $self->{ border }->[2] ); |
1820
|
|
|
|
|
|
|
$frame->openPolygon( $polyF, $frame_color ); |
1821
|
|
|
|
|
|
|
} |
1822
|
|
|
|
|
|
|
### end plot frame |
1823
|
|
|
|
|
|
|
|
1824
|
|
|
|
|
|
|
### plot glyph on the main chart |
1825
|
|
|
|
|
|
|
if ( exists $self->{ glyph } ) |
1826
|
|
|
|
|
|
|
{ |
1827
|
|
|
|
|
|
|
foreach my $item ( @{ $self->{ glyph } } ) |
1828
|
|
|
|
|
|
|
{ |
1829
|
|
|
|
|
|
|
my $X = 1; |
1830
|
|
|
|
|
|
|
my $Y = 1; |
1831
|
|
|
|
|
|
|
|
1832
|
|
|
|
|
|
|
$X += $item->{ x }; |
1833
|
|
|
|
|
|
|
$Y += $item->{ y }; |
1834
|
|
|
|
|
|
|
|
1835
|
|
|
|
|
|
|
my $glyph_color = _color_allocate( $item->{ color }, '00000000', $frame ); |
1836
|
|
|
|
|
|
|
if ( exists $item->{ type } && $item->{ type } eq 'filled' ) |
1837
|
|
|
|
|
|
|
{ |
1838
|
|
|
|
|
|
|
my $polyG = new GD::Polygon; |
1839
|
|
|
|
|
|
|
foreach my $point ( @{ $item->{ data } } ) |
1840
|
|
|
|
|
|
|
{ |
1841
|
|
|
|
|
|
|
next unless ( ref $point eq 'ARRAY' ); |
1842
|
|
|
|
|
|
|
$polyG->addPt( $X + $point->[0], $self->{ border }->[3] + $self->{ border }->[2] + $self->{ size }->[1] - $Y - $point->[1] ); |
1843
|
|
|
|
|
|
|
} |
1844
|
|
|
|
|
|
|
|
1845
|
|
|
|
|
|
|
$frame->filledPolygon( $polyG, $glyph_color ); |
1846
|
|
|
|
|
|
|
} |
1847
|
|
|
|
|
|
|
elsif ( exists $item->{ type } && $item->{ type } eq 'text' ) |
1848
|
|
|
|
|
|
|
{ |
1849
|
|
|
|
|
|
|
foreach my $point ( @{ $item->{ data } } ) |
1850
|
|
|
|
|
|
|
{ |
1851
|
|
|
|
|
|
|
my $text_angle = 0; |
1852
|
|
|
|
|
|
|
if ( exists $point->[3] ) |
1853
|
|
|
|
|
|
|
{ |
1854
|
|
|
|
|
|
|
$text_angle = ( $point->[3] / 180 ) * PI; |
1855
|
|
|
|
|
|
|
} |
1856
|
|
|
|
|
|
|
$frame->stringFT( $glyph_color, $item->{ font }, $item->{ size }, $text_angle, $X + $point->[1], $self->{ border }->[3] + $self->{ border }->[2] + $self->{ size }->[1] - $Y - $point->[2], $point->[0] ); |
1857
|
|
|
|
|
|
|
} |
1858
|
|
|
|
|
|
|
} |
1859
|
|
|
|
|
|
|
else |
1860
|
|
|
|
|
|
|
{ |
1861
|
|
|
|
|
|
|
my $polyG = new GD::Polygon; |
1862
|
|
|
|
|
|
|
foreach my $point ( @{ $item->{ data } } ) |
1863
|
|
|
|
|
|
|
{ |
1864
|
|
|
|
|
|
|
next unless ( ref $point eq 'ARRAY' ); |
1865
|
|
|
|
|
|
|
$polyG->addPt( $X + $point->[0], $self->{ border }->[3] + $self->{ border }->[2] + $self->{ size }->[1] - $Y - $point->[1] ); |
1866
|
|
|
|
|
|
|
} |
1867
|
|
|
|
|
|
|
$frame->openPolygon( $polyG, $glyph_color ); |
1868
|
|
|
|
|
|
|
} |
1869
|
|
|
|
|
|
|
} |
1870
|
|
|
|
|
|
|
} |
1871
|
|
|
|
|
|
|
### end plot glyph |
1872
|
|
|
|
|
|
|
|
1873
|
|
|
|
|
|
|
$self->{ img } = $frame->png; |
1874
|
|
|
|
|
|
|
if ( $object ) |
1875
|
|
|
|
|
|
|
{ |
1876
|
|
|
|
|
|
|
$self->png_zEXt( $object ); |
1877
|
|
|
|
|
|
|
} |
1878
|
|
|
|
|
|
|
return $self->{ img }; |
1879
|
|
|
|
|
|
|
} |
1880
|
|
|
|
|
|
|
|
1881
|
|
|
|
|
|
|
# sub log10 |
1882
|
|
|
|
|
|
|
# { |
1883
|
|
|
|
|
|
|
# my $n = shift; |
1884
|
|
|
|
|
|
|
# return log( $n ) / log( 10 ); |
1885
|
|
|
|
|
|
|
# } |
1886
|
|
|
|
|
|
|
|
1887
|
|
|
|
|
|
|
1; |
1888
|
|
|
|
|
|
|
|
1889
|
|
|
|
|
|
|
__END__ |