line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Image::BoxModel::Lowlevel; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
13
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
31
|
|
4
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
29
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
1075
|
use POSIX; #for ceil() in ::Box |
|
1
|
|
|
|
|
12865
|
|
|
1
|
|
|
|
|
8
|
|
7
|
1
|
|
|
1
|
|
3131
|
use Carp; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
2465
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 NAME |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
Image::BoxModel::Lowlevel - Lowlevel functions for Image::BoxModel |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 SYNOPSIS |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
For an example and general information see Image::BoxModel.pm |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 DESCRIPTION |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Image::BoxModel::Lowlevel implements some basic functionality. |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
It does so by using the methods from Image::BoxModel::Backend::[LIBRARY] |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
There are more backends planned and more functionality for each backend. |
24
|
|
|
|
|
|
|
(backends, patches, wishes are very welcome - in this order ;-) |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
Image::BoxModel::Lowlevel can be used directly, which is considered painful sometimes. |
27
|
|
|
|
|
|
|
You need to specify the size of a box before you can put text on it, for example, while 'Annotate' (inherited from ::Text) easily inserts a box and puts text on it. |
28
|
|
|
|
|
|
|
On the other hand, ::Lowlevel gives you full control. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head2 Methods: |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=cut |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
######################### |
35
|
|
|
|
|
|
|
#Get width & height of a Box |
36
|
|
|
|
|
|
|
######################### |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=head3 GetBoxSize |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
($width, $height) = $image -> GetBoxSize (box => "name_of_your_box"); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=cut |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub GetBoxSize{ |
45
|
0
|
|
|
0
|
1
|
|
my $image = shift; |
46
|
0
|
|
|
|
|
|
my %p = @_; |
47
|
|
|
|
|
|
|
|
48
|
0
|
0
|
0
|
|
|
|
if ((exists $p{box} && defined $p{box}) && (exists $image->{$p{box}}{width})){ |
|
|
|
0
|
|
|
|
|
49
|
0
|
|
|
|
|
|
return $image->{$p{box}}{width}, $image->{$p{box}}{height}; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
else{ |
52
|
0
|
|
|
|
|
|
return "Box '$p{box}' is not (correctly, at least) defined"; |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
######################### |
59
|
|
|
|
|
|
|
# Add a new box and resize another one (the "free"-box unless resize => box-to-resize is set) |
60
|
|
|
|
|
|
|
######################### |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head3 Box |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
If you don't specify 'resize => $name_of_box_to_be_resized', the standard-box 'free' is chosen. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
$image -> Box ( |
67
|
|
|
|
|
|
|
position =>[left|right|top|bottom], |
68
|
|
|
|
|
|
|
width => $x, |
69
|
|
|
|
|
|
|
height => $y, |
70
|
|
|
|
|
|
|
name => $name_of_new_box, |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# You can either specify a background color, then the box will be filled with that color |
73
|
|
|
|
|
|
|
background => [color] |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# or you can define a border color and a background color, then you will get a nice rectangle with border. |
76
|
|
|
|
|
|
|
# if you omit border_thickness it defaults to 1 |
77
|
|
|
|
|
|
|
background => [color], |
78
|
|
|
|
|
|
|
border_color => [color], |
79
|
|
|
|
|
|
|
border_thickness =>[color] |
80
|
|
|
|
|
|
|
); |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=cut |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub Box{ |
85
|
0
|
|
|
0
|
1
|
|
my $image = shift; |
86
|
0
|
|
|
|
|
|
my %p = @_; #%p holds the _p_arameters |
87
|
0
|
|
0
|
|
|
|
my $resize = $p{resize} || 'free'; |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
#~ print "Name: $resize, Wert: ", $image->{$resize},"\n"; |
90
|
0
|
0
|
|
|
|
|
croak __PACKAGE__,"::Box: You tried to put a box on '$resize' which does not exists. Die." unless exists $image ->{ $resize}; |
91
|
|
|
|
|
|
|
|
92
|
0
|
0
|
|
|
|
|
croak __PACKAGE__,"::Box: Mandatory parameter name missing. Die." unless $p{name}; |
93
|
0
|
0
|
|
|
|
|
return "$p{name} already exists. No box added" if (exists $image->{$p{name}}); |
94
|
0
|
0
|
|
|
|
|
croak __PACKAGE__,"::Box: Mandatory parameter position missing. Die." unless $p{position}; |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
#return if width or height is not specified. |
97
|
|
|
|
|
|
|
#(height wenn adding at top or bottom, width wen adding at left or right side.) |
98
|
0
|
0
|
0
|
|
|
|
if ($p{position} eq "top" or $p{position} eq "bottom"){ |
|
|
0
|
0
|
|
|
|
|
99
|
|
|
|
|
|
|
|
100
|
0
|
0
|
0
|
|
|
|
return "Box: Please specify height > 0. No box added\n" |
101
|
|
|
|
|
|
|
unless (exists $p{height} and $p{height} > 0); |
102
|
|
|
|
|
|
|
|
103
|
0
|
0
|
|
|
|
|
return "Box: Not enough free space on $resize for $p{name}. No box added\n (requested space: $p{height}, available: $image->{$resize}{height})\n" |
104
|
|
|
|
|
|
|
if ($p{height} > $image->{$resize}{height}); |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
elsif ($p{position} eq "left" or $p{position} eq "right"){ |
107
|
|
|
|
|
|
|
|
108
|
0
|
0
|
0
|
|
|
|
return "Box: Please specify width > 0. No box added\n" |
|
|
|
0
|
|
|
|
|
109
|
|
|
|
|
|
|
unless (exists $p{width} and $p{width} and $p{width} > 0); |
110
|
|
|
|
|
|
|
|
111
|
0
|
0
|
|
|
|
|
return "Box: Not enough free space on $resize for $p{name}. No box added\n (requested space: $p{width}, available: $image->{$resize}{width})\n" |
112
|
|
|
|
|
|
|
if ($p{width} > $image->{$resize}{width}); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
0
|
|
|
|
|
|
$image -> print_message ("Add Box \"$p{name}\" with ", __PACKAGE__,"\n"); |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
|
118
|
0
|
|
|
|
|
|
$image->{$p{name}}={ #First we make the new box as big as the field which will be resized.. |
119
|
|
|
|
|
|
|
top => $image->{$resize}{top}, |
120
|
|
|
|
|
|
|
bottom => $image->{$resize}{bottom}, |
121
|
|
|
|
|
|
|
left => $image->{$resize}{left} , |
122
|
|
|
|
|
|
|
right => $image->{$resize}{right}, |
123
|
|
|
|
|
|
|
}; |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
#.. then we overwrite as needed. |
126
|
|
|
|
|
|
|
|
127
|
0
|
0
|
|
|
|
|
$p{width} = ceil ($p{width}) if exists $p{width}; |
128
|
0
|
0
|
|
|
|
|
$p{height} = ceil ($p{height}) if exists $p{height}; |
129
|
|
|
|
|
|
|
|
130
|
0
|
0
|
|
|
|
|
if ($p{position} eq "top"){ |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
131
|
0
|
|
|
|
|
|
$image->{$p{name}}{bottom} = $image->{$resize}{top} + $p{height}; |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
#The top margin of the resized field is set to the bottom of the new box. |
134
|
0
|
|
|
|
|
|
$image->{$resize}{top} = $image->{$p{name}}{bottom}+1; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
elsif ($p{position} eq "bottom"){ |
137
|
0
|
|
|
|
|
|
$image->{$p{name}}{top} = $image->{$resize}{bottom} - $p{height}; |
138
|
0
|
|
|
|
|
|
$image->{$resize}{bottom} = $image->{$p{name}}{top}-1; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
elsif ($p{position} eq "left"){ |
141
|
0
|
|
|
|
|
|
$image->{$p{name}}{right} = $image->{$resize}{left} + $p{width}; |
142
|
0
|
|
|
|
|
|
$image->{$resize}{left} = $image->{$p{name}}{right}+1; |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
elsif ($p{position} eq "right"){ |
145
|
0
|
|
|
|
|
|
$image->{$p{name}}{left} = $image->{$resize}{right} - $p{width}; |
146
|
0
|
|
|
|
|
|
$image->{$resize}{right} = $image->{$p{name}}{left}-1; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
else { |
149
|
0
|
|
|
|
|
|
return "Image::BoxModel::Lowlevel::Box: Position $p{position} unknown. No box added"; |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# if border_color and background are defined, draw a rectangle with border and fill it. |
154
|
0
|
0
|
0
|
|
|
|
if (exists $p{border_color} and defined $p{border_color} |
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
155
|
|
|
|
|
|
|
and |
156
|
|
|
|
|
|
|
exists $p{background} and defined $p{background} |
157
|
|
|
|
|
|
|
){ |
158
|
|
|
|
|
|
|
|
159
|
0
|
0
|
0
|
|
|
|
$p{border_thickness} = 1 unless (exists $p{border_thickness} and defined $p{border_thickness} and $p{border_thickness} > 1); |
|
|
|
0
|
|
|
|
|
160
|
|
|
|
|
|
|
|
161
|
0
|
|
|
|
|
|
$image -> DrawRectangle( |
162
|
|
|
|
|
|
|
left => $image->{$p{name}}{left}, |
163
|
|
|
|
|
|
|
right => $image->{$p{name}}{right}, |
164
|
|
|
|
|
|
|
top => $image->{$p{name}}{top}, |
165
|
|
|
|
|
|
|
bottom => $image->{$p{name}}{bottom}, |
166
|
|
|
|
|
|
|
fill_color => $p{background}, |
167
|
|
|
|
|
|
|
border_color => $p{border_color}, |
168
|
|
|
|
|
|
|
border_thickness => $p{border_thickness} |
169
|
|
|
|
|
|
|
); |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
# if there is only background, just fill the box with the color |
172
|
|
|
|
|
|
|
elsif (exists $p{background} and defined $p{background}){ |
173
|
0
|
|
|
|
|
|
$image-> DrawRectangle( |
174
|
|
|
|
|
|
|
left => $image->{$p{name}}{left}, |
175
|
|
|
|
|
|
|
right => $image->{$p{name}}{right}, |
176
|
|
|
|
|
|
|
top => $image->{$p{name}}{top}, |
177
|
|
|
|
|
|
|
bottom => $image->{$p{name}}{bottom}, |
178
|
|
|
|
|
|
|
color => $p{background} |
179
|
|
|
|
|
|
|
); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
0
|
|
|
|
|
|
$image->{$p{name}}{width} = $image->{$p{name}}{right} - $image->{$p{name}}{left}; |
183
|
0
|
|
|
|
|
|
$image->{$p{name}}{height} = $image->{$p{name}}{bottom} - $image->{$p{name}}{top}; |
184
|
|
|
|
|
|
|
|
185
|
0
|
|
|
|
|
|
$image->{$resize}{height} = $image->{$resize}{bottom} - $image->{$resize}{top}; #calculate these values for later use.. laziness |
186
|
0
|
|
|
|
|
|
$image->{$resize}{width} = $image->{$resize}{right} - $image->{$resize}{left}; |
187
|
|
|
|
|
|
|
|
188
|
0
|
|
|
|
|
|
return; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
######################### |
192
|
|
|
|
|
|
|
# Add Floating Box. These boxes can reside anywhere and can overlap. Poor error-checking! |
193
|
|
|
|
|
|
|
######################### |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head3 FloatBox |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
To position a free-floating box wherever you want. There is virtually no error-checking, so perhaps better keep your hands off. ;-) |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
$image -> FloatBox( |
200
|
|
|
|
|
|
|
top => $top, |
201
|
|
|
|
|
|
|
bottom => $bottom, |
202
|
|
|
|
|
|
|
right => $right, |
203
|
|
|
|
|
|
|
left => $top, |
204
|
|
|
|
|
|
|
name => "whatever_you_call_it", |
205
|
|
|
|
|
|
|
background =>[color] |
206
|
|
|
|
|
|
|
); |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=cut |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub FloatBox{ |
211
|
0
|
|
|
0
|
1
|
|
my $image = shift; |
212
|
0
|
|
|
|
|
|
my %p =@_; |
213
|
0
|
0
|
|
|
|
|
return "$p{name} already exists. No FloatBox added" if (exists $image->{$p{name}}); |
214
|
0
|
|
|
|
|
|
foreach ("top", "bottom", "left", "right"){ |
215
|
0
|
0
|
|
|
|
|
return __PACKAGE__,"::FloatBox: argument $_ missing. No FloatBox added" unless (exists $p{$_}); |
216
|
0
|
|
|
|
|
|
$image->{$p{name}}{$_} = $p{$_}; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
0
|
|
|
|
|
|
$image -> print_message ("Add FloatBox \"$p{name}\" with ", __PACKAGE__,"\n"); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
#shift right <-> left if left is more right than right ;-) |
222
|
0
|
0
|
|
|
|
|
($image->{$p{name}}{right}, $image->{$p{name}}{left}) = ($image->{$p{name}}{left}, $image->{$p{name}}{right}) |
223
|
|
|
|
|
|
|
if ($image->{$p{name}}{left} > $image->{$p{name}}{right}); |
224
|
|
|
|
|
|
|
#same for bottom and top |
225
|
0
|
0
|
|
|
|
|
($image->{$p{name}}{top} , $image->{$p{name}}{bottom}) = ($image->{$p{name}}{bottom} , $image->{$p{name}}{top}) |
226
|
|
|
|
|
|
|
if ($image->{$p{name}}{bottom} < $image->{$p{name}}{top}); |
227
|
|
|
|
|
|
|
|
228
|
0
|
|
|
|
|
|
$image->{$p{name}}{$_} = int ($image->{$p{name}}{$_}) foreach ('top', 'left'); #only allow integer values |
229
|
0
|
|
|
|
|
|
$image->{$p{name}}{$_} = ceil ($image->{$p{name}}{$_}) foreach ('right', 'bottom'); |
230
|
|
|
|
|
|
|
|
231
|
0
|
|
|
|
|
|
my $top = $image->{$p{name}}{top}; |
232
|
0
|
|
|
|
|
|
my $bottom = $image->{$p{name}}{bottom}; |
233
|
0
|
|
|
|
|
|
my $left = $image->{$p{name}}{left}; |
234
|
0
|
|
|
|
|
|
my $right = $image->{$p{name}}{right}; |
235
|
0
|
0
|
0
|
|
|
|
if ((exists $p{background}) && (defined $p{background})){ |
236
|
0
|
|
|
|
|
|
$image -> DrawRectangle( |
237
|
|
|
|
|
|
|
left => $left, |
238
|
|
|
|
|
|
|
right => $right, |
239
|
|
|
|
|
|
|
top => $top, |
240
|
|
|
|
|
|
|
bottom => $bottom, |
241
|
|
|
|
|
|
|
color => $p{background} |
242
|
|
|
|
|
|
|
); |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
0
|
|
|
|
|
|
$image->{$p{name}}{width} = $image->{$p{name}}{right} - $image->{$p{name}}{left}; |
246
|
0
|
|
|
|
|
|
$image->{$p{name}}{height} = $image->{$p{name}}{bottom} - $image->{$p{name}}{top}; |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
return |
249
|
0
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
=head3 GetTextSize |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
Get the boundig size of (rotated) text. Very useful to find out how big boxes need to be. |
254
|
|
|
|
|
|
|
($width, $height) = $image -> GetTextSize( |
255
|
|
|
|
|
|
|
text => "Your Text", |
256
|
|
|
|
|
|
|
textsize => [number], |
257
|
|
|
|
|
|
|
rotate => [in degrees, may be negative as well] |
258
|
|
|
|
|
|
|
); |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=cut |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
sub GetTextSize{ |
263
|
0
|
|
|
0
|
1
|
|
my $image = shift; |
264
|
0
|
|
|
|
|
|
my %p = ( |
265
|
|
|
|
|
|
|
rotate => 0, |
266
|
|
|
|
|
|
|
@_ |
267
|
|
|
|
|
|
|
); |
268
|
|
|
|
|
|
|
|
269
|
0
|
0
|
0
|
|
|
|
$p{font} = default_font() unless (exists $p{font} and $p{font} and -f $p{font}); |
|
|
|
0
|
|
|
|
|
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
#die if the mandatory parameters are missing |
272
|
0
|
|
|
|
|
|
my $warning; |
273
|
0
|
|
|
|
|
|
foreach ("text", "textsize"){ |
274
|
0
|
0
|
|
|
|
|
$warning .= "Mandatory parameter \"$_\" missing. " unless (exists $p{$_}); |
275
|
|
|
|
|
|
|
} |
276
|
0
|
0
|
|
|
|
|
die __PACKAGE__,"::GetTextSize: ".$warning . "dying." if ($warning); |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
#get x&y of all corners: |
279
|
|
|
|
|
|
|
#@corner[0-3]{x|y} |
280
|
0
|
|
|
|
|
|
my @corner = $image->TextSize(text => $p{text}, font => $p{font}, textsize => $p{textsize}); |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
#rotate all 4 corners |
283
|
0
|
0
|
|
|
|
|
if ($p{rotate}){ |
284
|
0
|
|
|
|
|
|
for (my $i = 0; $i < scalar(@corner); $i++){ |
285
|
0
|
|
|
|
|
|
($corner[$i]{x}, $corner[$i]{y}) = $image -> rotation ($corner[$i]{x}, $corner[$i]{y}, 0, 0, $p{rotate}); |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
0
|
|
|
|
|
|
my %most =( |
290
|
|
|
|
|
|
|
left => 0, |
291
|
|
|
|
|
|
|
right => 0, |
292
|
|
|
|
|
|
|
top => 0, |
293
|
|
|
|
|
|
|
bottom =>0 |
294
|
|
|
|
|
|
|
); |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
#find the left-, right-, top- and bottommost values. |
297
|
0
|
|
|
|
|
|
foreach (@corner){ |
298
|
0
|
0
|
|
|
|
|
$most{left} = $_->{x} if ($_->{x} < $most{left}); |
299
|
0
|
0
|
|
|
|
|
$most{right} = $_->{x} if ($_->{x} > $most{right}); |
300
|
0
|
0
|
|
|
|
|
$most{top} = $_->{y} if ($_->{y} < $most{top}); |
301
|
0
|
0
|
|
|
|
|
$most{bottom} = $_->{y} if ($_->{y} > $most{bottom}); |
302
|
|
|
|
|
|
|
} |
303
|
0
|
|
|
|
|
|
return (ceil($most{right}- $most{left})), (ceil($most{bottom}-$most{top})); #return width and height |
304
|
|
|
|
|
|
|
#ceil to ensure that the a the text will surely and safely fit.. There were strange errors in ::Backend::GD with values equaling while being inequal at the same time! I don't unterstand this. |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=head3 BoxSplit |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
$image -> BoxSplit ( |
310
|
|
|
|
|
|
|
box => "name_of_parent", |
311
|
|
|
|
|
|
|
orientation=> "[vertical|horizontal]", |
312
|
|
|
|
|
|
|
number => $number_of_little_boxes), |
313
|
|
|
|
|
|
|
); |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
Splits a box into "number" small boxes. This can be useful if you want to have spreadsheet-style segmentation. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Naming of little boxes: parent_[number, counting from 0] |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
In bitmap-land we only have integer-size-boxes. Therefore some boxes may be 1 pixel taller than others.. |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
Example: |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
If the parent is "myBox", then the babies are named myBox_0, myBox_1, ...myBox_2635 (if you are crazy enough to have 2635 babies) |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=cut |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
sub BoxSplit{ |
328
|
0
|
|
|
0
|
1
|
|
my $image = shift; |
329
|
0
|
|
|
|
|
|
my %p = @_; |
330
|
|
|
|
|
|
|
|
331
|
0
|
|
|
|
|
|
my $parent_size; #because ::Box ignores the not used given dimension, we just set this to with or height of parent and feed it twice.. |
332
|
|
|
|
|
|
|
my $position; |
333
|
0
|
0
|
|
|
|
|
if ($p{orientation} eq "vertical"){ |
|
|
0
|
|
|
|
|
|
334
|
0
|
|
|
|
|
|
$parent_size = $image -> {$p{box}}{height}; |
335
|
0
|
|
|
|
|
|
$position = "top"; |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
elsif ($p{orientation} eq "horizontal"){ |
338
|
0
|
|
|
|
|
|
$parent_size = $image -> {$p{box}}{width}; |
339
|
0
|
|
|
|
|
|
$position = "left"; |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
else{ |
342
|
0
|
|
|
|
|
|
die __PACKAGE__,": Wrong value of mandatory parameter 'orientation': $p{orientation}, should be [vertical|horizontal]. Die."; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
0
|
|
|
|
|
|
foreach (0.. $p{number}-1){ #baby-box No. 1 holds number 0.. |
346
|
0
|
|
|
|
|
|
my $baby_size = sprintf("%.0f", ($parent_size / ($p{number} - $_))); |
347
|
|
|
|
|
|
|
#~ print "baby-size: $baby_size\t baby-name: $p{box}_$_\n"; |
348
|
|
|
|
|
|
|
|
349
|
0
|
|
|
|
|
|
$parent_size -= $baby_size; |
350
|
|
|
|
|
|
|
|
351
|
0
|
|
|
|
|
|
$image -> Box ( |
352
|
|
|
|
|
|
|
resize => $p{box}, |
353
|
|
|
|
|
|
|
position => $position, |
354
|
|
|
|
|
|
|
width => $baby_size-1, |
355
|
|
|
|
|
|
|
height => $baby_size-1, |
356
|
|
|
|
|
|
|
name => "$p{box}_$_", |
357
|
|
|
|
|
|
|
background => $p{background_colors}[$_], |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
border_color => $p{border_color}, |
360
|
|
|
|
|
|
|
border_thickness => $p{border_thickness} |
361
|
|
|
|
|
|
|
); |
362
|
|
|
|
|
|
|
} |
363
|
0
|
|
|
|
|
|
return; #nothing at the moment |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
######################### |
367
|
|
|
|
|
|
|
# Add text to a box |
368
|
|
|
|
|
|
|
######################### |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
=head3 Text |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
For easy use: Better use 'Annotate' (inherited from ::Text) instead of 'Text'. Annotate reserves a box automatically while Text does not. |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
But of course, if you need / want full control, use 'Text'. |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
Put (rotated, antialized) text on a box. Takes a bunch of parameters, of which "text" and "textsize" are mandatory. |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
$image -> Text( |
379
|
|
|
|
|
|
|
text => $text, |
380
|
|
|
|
|
|
|
textsize => [number], |
381
|
|
|
|
|
|
|
color => "black", |
382
|
|
|
|
|
|
|
font => [font-file] |
383
|
|
|
|
|
|
|
rotate => [in degrees, may be negative as well], |
384
|
|
|
|
|
|
|
box => "free", |
385
|
|
|
|
|
|
|
align => [Left|Center|Right]", #align is how multiline-text is aligned |
386
|
|
|
|
|
|
|
position => [Center #position is how text will be positioned inside its box |
387
|
|
|
|
|
|
|
NorthWest| |
388
|
|
|
|
|
|
|
North| |
389
|
|
|
|
|
|
|
NorthEast| |
390
|
|
|
|
|
|
|
West| |
391
|
|
|
|
|
|
|
SoutEast| |
392
|
|
|
|
|
|
|
South| |
393
|
|
|
|
|
|
|
SouthWest| |
394
|
|
|
|
|
|
|
West |
395
|
|
|
|
|
|
|
], |
396
|
|
|
|
|
|
|
background => [color] #rather for debugging |
397
|
|
|
|
|
|
|
); |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=cut |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
sub Text{ |
402
|
0
|
|
|
0
|
1
|
|
my $image = shift; |
403
|
0
|
|
|
|
|
|
my %p = ( |
404
|
|
|
|
|
|
|
color =>"black", |
405
|
|
|
|
|
|
|
rotate =>0, |
406
|
|
|
|
|
|
|
box => "free", |
407
|
|
|
|
|
|
|
rotate => 0, |
408
|
|
|
|
|
|
|
align => "Center", |
409
|
|
|
|
|
|
|
position=> "Center", |
410
|
|
|
|
|
|
|
@_ |
411
|
|
|
|
|
|
|
); |
412
|
|
|
|
|
|
|
|
413
|
0
|
0
|
0
|
|
|
|
$p{font} = default_font() unless (exists $p{font} and $p{font} and -f $p{font}); |
|
|
|
0
|
|
|
|
|
414
|
|
|
|
|
|
|
|
415
|
0
|
|
|
|
|
|
my $warning; |
416
|
0
|
|
|
|
|
|
foreach ("text", "textsize"){ |
417
|
0
|
0
|
|
|
|
|
$warning .= "Mandatory parameter \"$_\" missing. " unless (exists $p{$_}); |
418
|
|
|
|
|
|
|
} |
419
|
0
|
0
|
0
|
|
|
|
$warning .= "align = $p{align} is invalid. Valid are Right / Left / Center. " unless ($p{align} =~ /left/i or $p{align} =~ /right/i or $p{align} =~ /center/i); |
|
|
|
0
|
|
|
|
|
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
#if the box does not exist (Box couldn't / didn't want to make it due to missing parameters), we can't add text. |
422
|
|
|
|
|
|
|
#(It's better if we don't want to..) |
423
|
0
|
0
|
|
|
|
|
$warning .= "Box '$p{box}' does not exist. " unless (exists $image->{$p{box}}); |
424
|
|
|
|
|
|
|
|
425
|
0
|
0
|
|
|
|
|
return "Text: ".$warning . "No Text added.\n" if ($warning); |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
#center of box = left + (right-left) /2 |
428
|
|
|
|
|
|
|
#later we will rotate the text around the center of the box. |
429
|
0
|
|
|
|
|
|
$p{x_box_center} = $image->{$p{box}}{left} + ($image->{$p{box}}{right} - $image->{$p{box}}{left}) / 2; |
430
|
0
|
|
|
|
|
|
$p{y_box_center} = $image->{$p{box}}{top} + ($image->{$p{box}}{bottom} - $image->{$p{box}}{top}) / 2; |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
#DrawText lives in ::Backend::[your_library], because it has to do much library-specific calculations |
433
|
|
|
|
|
|
|
|
434
|
0
|
|
|
|
|
|
my $w = $image -> DrawText(%p); |
435
|
0
|
0
|
|
|
|
|
$warning .= $w if $w; |
436
|
|
|
|
|
|
|
|
437
|
0
|
|
|
|
|
|
$image -> print_message ("Add Text to Box \"$p{box}\" with ",__PACKAGE__,"\n"); |
438
|
0
|
|
0
|
|
|
|
return $warning || return; #to avoid "uninitialized value in calling line when using -w" |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
=head3 Save |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
$image -> Save($filename); |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
Save the image to file. There is no error-checking at the moment. You need to know yourself if your chosen library supports the desired file-type. |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=head3 DrawRectangle |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
Rectangle without border: |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
$image -> DrawRectangle (top => $top, bottom => $bottom, right => $right, left => $left, color => "color"); |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
Rectangle with border: |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
$image -> DrawRectangle (top => $top, bottom => $bottom, right => $right, left => $left, fill_color => "color", border_color => "color"); |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
Draws a rectangle with the given sides. There are no rotated rectangles at the moment. |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=cut |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
#There is no Save, DrawRectangle.. here really, because they're in ::Backend::[library] |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
=head2 Internal methods: |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
(documentation for myself rather than the user) |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
=head3 rotation |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
To rotate a given point by any point. It takes the angle in degrees, which is very comfortable to me. |
471
|
|
|
|
|
|
|
If you want to rotate something, feel free to use it. :-) |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
($x, $y) = $image -> rotation($x, $y, $x_center, $y_center, $angle); |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
=cut |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
sub rotation{ |
478
|
0
|
|
|
0
|
1
|
|
my $image = shift; |
479
|
0
|
|
|
|
|
|
my ($x, $y, $x_center, $y_center, $angle) = @_; |
480
|
|
|
|
|
|
|
#~ print "X: $x Y: $y x-center: $x_center y-center: $y_center angle: $angle\n"; |
481
|
|
|
|
|
|
|
|
482
|
0
|
0
|
|
|
|
|
return ($x, $y) if ($angle == 0); # if angle == 0 then return immediately. 1st because there's nothing to do, 2nd to prevent from division by 0 |
483
|
|
|
|
|
|
|
|
484
|
0
|
|
|
|
|
|
$angle = $image->{PI} / (360 / $angle) * 2; |
485
|
|
|
|
|
|
|
|
486
|
0
|
|
|
|
|
|
my $sin = sin ($angle); |
487
|
0
|
|
|
|
|
|
my $cos = cos ($angle); |
488
|
|
|
|
|
|
|
|
489
|
0
|
|
|
|
|
|
my $x1=$x; |
490
|
0
|
|
|
|
|
|
my $y1=$y; |
491
|
|
|
|
|
|
|
|
492
|
0
|
|
|
|
|
|
$x = ($x1 * $cos) - ($y1 * $sin) - ($x_center * $cos) + ($y_center * $sin) + $x_center; |
493
|
0
|
|
|
|
|
|
$y = ($x1 * $sin) + ($y1 * $cos) - ($x_center * $sin) - ($y_center * $cos) + $y_center; |
494
|
|
|
|
|
|
|
|
495
|
0
|
|
|
|
|
|
return $x, $y; |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=head3 print_message |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
Checks if verbose is on and then prints messages. |
501
|
|
|
|
|
|
|
$image -> print_message("Text"); |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=cut |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
sub print_message{ |
506
|
0
|
|
|
0
|
1
|
|
my $image = shift; |
507
|
0
|
0
|
|
|
|
|
print @_ if $image->{verbose}; |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
sub default_font{ |
511
|
0
|
|
|
0
|
0
|
|
my $package = __PACKAGE__; # Gives Image::BoxModel::Lowlevel |
512
|
0
|
|
|
|
|
|
$package =~ s/::/\//g; # Image/BoxModel/Lowlevel |
513
|
|
|
|
|
|
|
# Make default font: (path-to-lib)/Image/BoxModel/Backend/FreeSans.ttf |
514
|
0
|
|
|
|
|
|
(my $default_font = $INC{"$package.pm"}) =~ s/Lowlevel\.pm/Backend\/FreeSans.ttf/; |
515
|
0
|
0
|
|
|
|
|
if (-f $default_font){ |
516
|
0
|
|
|
|
|
|
return $default_font; |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
else{ |
519
|
0
|
|
|
|
|
|
die "Can't find default font. Please file bug report."; |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
1; |
525
|
|
|
|
|
|
|
__END__ |