| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package GD::Window; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
31164
|
use 5.008006; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
50
|
|
|
4
|
1
|
|
|
1
|
|
5
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
43
|
|
|
5
|
1
|
|
|
1
|
|
7
|
use warnings; |
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
45
|
|
|
6
|
1
|
|
|
1
|
|
5
|
use Carp qw( croak ); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
83
|
|
|
7
|
1
|
|
|
1
|
|
6
|
use vars qw/$VERSION $AUTOLOAD/; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1795
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
require Exporter; |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( 'all' => [ qw( |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
) ] ); |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
our @EXPORT = qw( |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
); |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
my %imWindowedFuncs = ( |
|
27
|
|
|
|
|
|
|
setPixel => {x => [0], 'y' => [1]}, |
|
28
|
|
|
|
|
|
|
line => {x => [0,2], 'y' => [1,3]}, |
|
29
|
|
|
|
|
|
|
dashedLine => {x => [0,2], 'y' => [1,3]}, |
|
30
|
|
|
|
|
|
|
rectangle => {x => [0,2], 'y' => [1,3]}, |
|
31
|
|
|
|
|
|
|
filledRectangle => {x => [0,2], 'y' => [1,3]}, |
|
32
|
|
|
|
|
|
|
ellipse => {x => [0], 'y' => [1], w => [2], h => [3]}, |
|
33
|
|
|
|
|
|
|
filledEllipse => {x => [0], 'y' => [1], w => [2], h => [3]}, |
|
34
|
|
|
|
|
|
|
arc => {x => [0], 'y' => [1], w => [2], h => [3]}, |
|
35
|
|
|
|
|
|
|
filledArc => {x => [0], 'y' => [1], w => [2], h => [3]}, |
|
36
|
|
|
|
|
|
|
fill => {x => [0], 'y' => [1]}, |
|
37
|
|
|
|
|
|
|
fillToBorder => {x => [0], 'y' => [1]}, |
|
38
|
|
|
|
|
|
|
copy => {x => [1], 'y' => [2]}, |
|
39
|
|
|
|
|
|
|
copyMerge => {x => [1], 'y' => [2]}, |
|
40
|
|
|
|
|
|
|
copyMergeGray => {x => [1], 'y' => [2]}, |
|
41
|
|
|
|
|
|
|
copyResized => {x => [1], 'y' => [2], w => [5], h => [6]}, |
|
42
|
|
|
|
|
|
|
copyResampled => {x => [1], 'y' => [2], w => [5], h => [6]}, |
|
43
|
|
|
|
|
|
|
copyRotated => {x => [1], 'y' => [2]}, |
|
44
|
|
|
|
|
|
|
string => {x => [1], 'y' => [2]}, |
|
45
|
|
|
|
|
|
|
stringUp => {x => [1], 'y' => [2]}, |
|
46
|
|
|
|
|
|
|
char => {x => [1], 'y' => [2]}, |
|
47
|
|
|
|
|
|
|
charUp => {x => [1], 'y' => [2]}, |
|
48
|
|
|
|
|
|
|
stringFT => {x => [4], 'y' => [5]}, |
|
49
|
|
|
|
|
|
|
stringFTCircle => {x => [0], 'y' => [1]}, |
|
50
|
|
|
|
|
|
|
clip => {x => [0,2], 'y' => [1,3]}, |
|
51
|
|
|
|
|
|
|
); |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
my %imWindowedPolyFuncs = (openPolygon => 1, |
|
54
|
|
|
|
|
|
|
unclosedPolygon => 1, |
|
55
|
|
|
|
|
|
|
filledPolygon => 1); |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
my $invertY_g = 0; |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub new { |
|
62
|
0
|
|
|
0
|
1
|
|
my $that = shift; |
|
63
|
0
|
|
0
|
|
|
|
my $class = ref($that) || $that; |
|
64
|
0
|
|
|
|
|
|
my ($im, $imX1, $imY1, $imX2, $imY2, |
|
65
|
|
|
|
|
|
|
$winX1, $winY1, $winX2, $winY2, |
|
66
|
|
|
|
|
|
|
%args) = @_; |
|
67
|
|
|
|
|
|
|
|
|
68
|
0
|
0
|
|
|
|
|
if (scalar(@_) < 9) { |
|
69
|
0
|
|
|
|
|
|
croak "Missing some arguments for new GD::Window"; |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Fill in the window's boundary |
|
73
|
0
|
0
|
|
|
|
|
my $self = { im => $im, |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
minX => $winX1 > $winX2 ? $winX2 : $winX1, |
|
75
|
|
|
|
|
|
|
minY => $winY1 > $winY2 ? $winY2 : $winY1, |
|
76
|
|
|
|
|
|
|
maxX => $winX1 > $winX2 ? $winX1 : $winX2, |
|
77
|
|
|
|
|
|
|
maxY => $winY1 > $winY2 ? $winY1 : $winY2, |
|
78
|
|
|
|
|
|
|
imMinX => $imX1 > $imX2 ? $imX2 : $imX1, |
|
79
|
|
|
|
|
|
|
imMinY => $imY1 > $imY2 ? $imY2 : $imY1, |
|
80
|
|
|
|
|
|
|
imMaxX => $imX1 > $imX2 ? $imX1 : $imX2, |
|
81
|
|
|
|
|
|
|
imMaxY => $imY1 > $imY2 ? $imY1 : $imY2, |
|
82
|
|
|
|
|
|
|
passThroughIfUnsupported => $args{passThrough}, |
|
83
|
|
|
|
|
|
|
useImage => $args{useImage}, |
|
84
|
|
|
|
|
|
|
invertY => defined $args{invertY} ? $args{invertY} : $invertY_g, |
|
85
|
|
|
|
|
|
|
}; |
|
86
|
|
|
|
|
|
|
|
|
87
|
0
|
0
|
|
|
|
|
if ($self->{useImage}) { |
|
88
|
|
|
|
|
|
|
# Need to make our own internal image |
|
89
|
0
|
|
|
|
|
|
$self->{parentIm} = $im; |
|
90
|
0
|
|
|
|
|
|
$self->{im} = GD::Image->new(($self->{maxX} - $self->{minX}), ($self->{maxY} - $self->{minY}), 1); |
|
91
|
0
|
|
|
|
|
|
$self->{scaleX} = 1; |
|
92
|
0
|
|
|
|
|
|
$self->{scaleY} = 1; |
|
93
|
0
|
|
|
|
|
|
$self->{srcImMinX} = $self->{imMinX}; |
|
94
|
0
|
|
|
|
|
|
$self->{srcImMinY} = $self->{imMinY}; |
|
95
|
0
|
|
|
|
|
|
$self->{imMinX} = 0; |
|
96
|
0
|
|
|
|
|
|
$self->{imMinY} = 0; |
|
97
|
|
|
|
|
|
|
} |
|
98
|
|
|
|
|
|
|
else { |
|
99
|
0
|
|
|
|
|
|
$self->{scaleX} = ($self->{imMaxX} - $self->{imMinX})/($self->{maxX} - $self->{minX}); |
|
100
|
0
|
|
|
|
|
|
$self->{scaleY} = ($self->{imMaxY} - $self->{imMinY})/($self->{maxY} - $self->{minY}); |
|
101
|
|
|
|
|
|
|
} |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# print "PostSub: $postSub\n"; |
|
104
|
0
|
0
|
|
|
|
|
if ($@) { |
|
105
|
0
|
|
|
|
|
|
die "Failed eval of autoloaded sub: $@"; |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
0
|
|
|
|
|
|
bless ($self, $class); |
|
109
|
0
|
|
|
|
|
|
return $self; |
|
110
|
|
|
|
|
|
|
} |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
## |
|
114
|
|
|
|
|
|
|
# The autoload function catches all the supported image functions and |
|
115
|
|
|
|
|
|
|
# creates the appropriate transformations for them. |
|
116
|
|
|
|
|
|
|
# |
|
117
|
|
|
|
|
|
|
# If passThrough is defined on window creation, then unsupported |
|
118
|
|
|
|
|
|
|
# functions will simply be forwarded to the image. Otherwise, |
|
119
|
|
|
|
|
|
|
# we will croak. |
|
120
|
|
|
|
|
|
|
## |
|
121
|
|
|
|
|
|
|
sub AUTOLOAD { |
|
122
|
0
|
|
|
0
|
|
|
my ($self) = @_; |
|
123
|
0
|
|
|
|
|
|
my ($name) = ($AUTOLOAD =~ /::([^:]+)$/); |
|
124
|
0
|
|
|
|
|
|
my @args = @_; |
|
125
|
|
|
|
|
|
|
|
|
126
|
0
|
0
|
|
|
|
|
if (exists $imWindowedFuncs{$name}) { |
|
|
|
0
|
|
|
|
|
|
|
127
|
0
|
|
|
|
|
|
my $fi = $imWindowedFuncs{$name}; |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# Create the function that should be called |
|
130
|
0
|
|
|
|
|
|
my $body = " my \$s = shift;my \@args = \@_;\n"; |
|
131
|
|
|
|
|
|
|
|
|
132
|
0
|
|
|
|
|
|
foreach my $dim (qw(x y w h)) { |
|
133
|
0
|
0
|
|
|
|
|
if ($fi->{$dim}) { |
|
134
|
0
|
|
|
|
|
|
foreach my $idx (@{$fi->{$dim}}) { |
|
|
0
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
$body .= " \$args[$idx] = \$s->translate". uc($dim) ."(\$args[$idx]);\n"; |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
} |
|
139
|
|
|
|
|
|
|
# $body .= " print \"calling $name with \$s->{im} -> \@args\\n\"; my \$res = \$s->{im}->$name(\@args); \$s->postRenderAdjustment(); return \$res; \n"; |
|
140
|
0
|
|
|
|
|
|
$body .= " my \$res = \$s->{im}->$name(\@args); \$s->postRenderAdjustment(); return \$res; \n"; |
|
141
|
|
|
|
|
|
|
# print "Eval: $body\n"; |
|
142
|
0
|
|
|
|
|
|
eval "sub $name { $body }; return $name(\@args);"; |
|
143
|
0
|
0
|
|
|
|
|
if ($@) { |
|
144
|
0
|
|
|
|
|
|
die "Failed eval of autoloaded sub: $@"; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
elsif (exists $imWindowedPolyFuncs{$name}) { |
|
148
|
|
|
|
|
|
|
|
|
149
|
0
|
|
|
|
|
|
my $body = qq ^ |
|
150
|
|
|
|
|
|
|
my (\$self, \$poly, \$color) = \@_; |
|
151
|
|
|
|
|
|
|
my \$transPoly = GD::Polygon->new; |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# Need to go through all the points and adjust them |
|
154
|
|
|
|
|
|
|
foreach my \$vertex (\$poly->vertices) { |
|
155
|
|
|
|
|
|
|
\$transPoly->addPt(\$self->translateX(\$vertex->[0]), \$self->translateY(\$vertex->[1])); |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
\$self->{im}->$name(\$transPoly, \$color); |
|
158
|
|
|
|
|
|
|
^; |
|
159
|
|
|
|
|
|
|
# print "Adding \@{\$vertex}\n"; |
|
160
|
|
|
|
|
|
|
# my \@v = \$transPoly->vertices; |
|
161
|
|
|
|
|
|
|
#foreach my \$v (\@v) { |
|
162
|
|
|
|
|
|
|
# print "poly: \@{\$v}\n"; |
|
163
|
|
|
|
|
|
|
#} |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# print "BODY: $body\n"; |
|
166
|
0
|
|
|
|
|
|
eval "sub $name { $body }; return $name(\@args);"; |
|
167
|
0
|
0
|
|
|
|
|
if ($@) { |
|
168
|
0
|
|
|
|
|
|
die "Failed eval of autoloaded sub: $@"; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
else { |
|
173
|
0
|
0
|
0
|
|
|
|
if ($self->{passThroughIfUnsupported} || $self->{useImage}) { |
|
174
|
0
|
|
|
|
|
|
eval("sub $name { my \$s = shift; my \$res = \$s->{im}->$name(\@_); \$s->postRenderAdjustment(); return \$res;}; return $name(\@_);"); |
|
175
|
0
|
0
|
|
|
|
|
if ($@) { |
|
176
|
0
|
|
|
|
|
|
die "Failed eval of autoloaded sub: $@"; |
|
177
|
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
} |
|
179
|
|
|
|
|
|
|
else { |
|
180
|
0
|
|
|
|
|
|
croak "Sub $name is not supported by GD::Window"; |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
} |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
## |
|
188
|
|
|
|
|
|
|
# Methods that can't be handled by the AUTOLOAD |
|
189
|
|
|
|
|
|
|
## |
|
190
|
|
|
|
|
|
|
sub boundsSafe { |
|
191
|
0
|
|
|
0
|
0
|
|
my ($self, $x, $y) = @_; |
|
192
|
0
|
|
0
|
|
|
|
return ($x >= $self->{minX} && |
|
193
|
|
|
|
|
|
|
$x <= $self->{maxX} && |
|
194
|
|
|
|
|
|
|
$y >= $self->{minY} && |
|
195
|
|
|
|
|
|
|
$y <= $self->{maxY}); |
|
196
|
|
|
|
|
|
|
} |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
sub bounds { |
|
199
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
200
|
0
|
0
|
|
|
|
|
if (!$self->{invertY}) { |
|
201
|
0
|
|
|
|
|
|
return($self->{minX}, |
|
202
|
|
|
|
|
|
|
$self->{minY}, |
|
203
|
|
|
|
|
|
|
$self->{maxX}, |
|
204
|
|
|
|
|
|
|
$self->{maxY}); |
|
205
|
|
|
|
|
|
|
} |
|
206
|
|
|
|
|
|
|
else { |
|
207
|
0
|
|
|
|
|
|
return($self->{minX}, |
|
208
|
|
|
|
|
|
|
$self->{maxY}, |
|
209
|
|
|
|
|
|
|
$self->{maxX}, |
|
210
|
|
|
|
|
|
|
$self->{minY}); |
|
211
|
|
|
|
|
|
|
} |
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub dimensions { |
|
216
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
|
217
|
0
|
|
|
|
|
|
return($self->{maxX} - $self->{minX}, |
|
218
|
|
|
|
|
|
|
$self->{maxY} - $self->{minY}); |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
## |
|
223
|
|
|
|
|
|
|
# Public Methods for changing globals |
|
224
|
|
|
|
|
|
|
## |
|
225
|
|
|
|
|
|
|
sub invertY { |
|
226
|
0
|
|
|
0
|
1
|
|
my ($that, $val) = @_; |
|
227
|
|
|
|
|
|
|
|
|
228
|
0
|
0
|
|
|
|
|
if (ref($that)) { |
|
229
|
0
|
|
|
|
|
|
$that->{invertY} = $val; |
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
else { |
|
232
|
0
|
|
|
|
|
|
$invertY_g = $val; |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
## |
|
239
|
|
|
|
|
|
|
# Private Methods |
|
240
|
|
|
|
|
|
|
## |
|
241
|
|
|
|
|
|
|
sub translateX { |
|
242
|
0
|
|
|
0
|
0
|
|
my ($self, $x) = @_; |
|
243
|
0
|
|
|
|
|
|
my $newX = ($x - $self->{minX}) * $self->{scaleX} + $self->{imMinX}; |
|
244
|
|
|
|
|
|
|
# print "translate from $x to $newX, $self->{scaleX}, $self->{minX}, $self->{imMinX}\n"; |
|
245
|
0
|
|
|
|
|
|
return $newX; |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub translateY { |
|
249
|
0
|
|
|
0
|
0
|
|
my ($self, $y) = @_; |
|
250
|
0
|
0
|
|
|
|
|
if ($self->{invertY}) { |
|
251
|
0
|
|
|
|
|
|
$y = $self->{maxY} - $y; |
|
252
|
|
|
|
|
|
|
} |
|
253
|
0
|
|
|
|
|
|
my $newY = ($y - $self->{minY}) * $self->{scaleY} + $self->{imMinY}; |
|
254
|
|
|
|
|
|
|
# print "translate from $y to $newY, $self->{scaleY}\n"; |
|
255
|
0
|
|
|
|
|
|
return $newY; |
|
256
|
|
|
|
|
|
|
} |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub translateW { |
|
259
|
0
|
|
|
0
|
0
|
|
my ($self, $w) = @_; |
|
260
|
0
|
|
|
|
|
|
return $w * $self->{scaleX}; |
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
sub translateH { |
|
264
|
0
|
|
|
0
|
0
|
|
my ($self, $h) = @_; |
|
265
|
0
|
|
|
|
|
|
return $h * $self->{scaleY}; |
|
266
|
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub postRenderAdjustment { |
|
269
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
270
|
0
|
0
|
|
|
|
|
return if !$self->{useImage}; |
|
271
|
0
|
|
|
|
|
|
$self->{parentIm}->copyResampled( |
|
272
|
|
|
|
|
|
|
$self->{im}, $self->{srcImMinX}, $self->{srcImMinY}, 0, 0, |
|
273
|
|
|
|
|
|
|
($self->{imMaxX} - $self->{srcImMinX}), ($self->{imMaxY} - $self->{srcImMinY}), |
|
274
|
|
|
|
|
|
|
($self->{maxX} - $self->{minX}), ($self->{maxY} - $self->{minY})); |
|
275
|
|
|
|
|
|
|
}; |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
|
|
278
|
0
|
|
|
0
|
|
|
sub DESTROY {} |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
1; |
|
282
|
|
|
|
|
|
|
__END__ |