File Coverage

blib/lib/Image/Magick/PolyText.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Image::Magick::PolyText;
2             {
3 1     1   27555 use strict;
  1         2  
  1         43  
4 1     1   4 use warnings;
  1         2  
  1         33  
5              
6 1     1   577 use Class::Std;
  0            
  0            
7             use Math::Bezier;
8             use Math::Interpolate;
9             use Readonly;
10              
11             our $VERSION = '1.0.3';
12              
13             # ------------------------------------------------
14             # Attributes.
15              
16             my %debug : ATTR(init_arg => 'debug', default => 0);
17             my %fill : ATTR(init_arg => 'fill', default => 'Red');
18             my %image : ATTR(init_arg => 'image');
19             my %pointsize : ATTR(init_arg => 'pointsize', default => 16);
20             my %rotate : ATTR(init_arg => 'rotate', default => 1);
21             my %slide : ATTR(init_arg => 'slide', default => 0);
22             my %stroke : ATTR(init_arg => 'stroke', default => 'Red');
23             my %strokewidth : ATTR(init_arg => 'strokewidth', default => 1);
24             my %text : ATTR(init_arg => 'text');
25             my %x : ATTR(init_arg => 'x');
26             my %y : ATTR(init_arg => 'y');
27              
28             # ------------------------------------------------
29             # Constants.
30              
31             Readonly::Scalar my $pi => 3.14159265;
32              
33             # ------------------------------------------------
34             # Methods.
35              
36             sub annotate
37             {
38             my $self = shift @_;
39             my $id = ident $self;
40              
41             if ($debug{$id})
42             {
43             $self -> dump();
44             }
45              
46             my $i;
47             my $result;
48             my $rotation;
49             my @text = split //, $text{$id};
50             my @value;
51             my $x = $x{$id}[0];
52             my $y;
53              
54             if ($slide{$id})
55             {
56             my $b = Math::Bezier -> new(map{($x{$id}[$_], $y{$id}[$_])} 0 .. $#{$x{$id} });
57             ($x, $y) = $b -> point($slide{$id});
58             }
59              
60             for ($i = 0; $i <= $#text; $i++)
61             {
62             @value = Math::Interpolate::robust_interpolate($x, $x{$id}, $y{$id});
63             $rotation = $rotate{$id} ? 180 * $value[1] / $pi : 0; # Convert radians to degrees.
64             $y = $value[0];
65             $result = $image{$id} -> Annotate
66             (
67             fill => $fill{$id},
68             pointsize => $pointsize{$id},
69             rotate => $rotation,
70             stroke => $stroke{$id},
71             strokewidth => $strokewidth{$id},
72             text => $text[$i],
73             x => $x,
74             'y' => $y, # y eq tr, so syntax highlighting stuffed without ''.
75             );
76              
77             die $result if $result;
78              
79             $x += $pointsize{$id};
80             }
81              
82             } # End of annotate.
83              
84             # ------------------------------------------------
85              
86             sub draw : CUMULATIVE
87             {
88             my $self = shift @_;
89             my $arg = shift @_;
90             my $id = ident $self;
91              
92             my $i;
93             my $s = '';
94              
95             for $i (0 .. $#{$x{$id} })
96             {
97             $s .= "$x{$id}[$i],$y{$id}[$i] ";
98             }
99              
100             my %option =
101             (
102             fill => 'None',
103             points => $s,
104             primitive => 'polyline',
105             stroke => 'Green',
106             strokewidth => 1,
107             map{(lc $_, $$arg{$_})} keys %$arg,
108             );
109              
110             my $result = $image{$id} -> Draw(%option);
111              
112             die $result if $result;
113              
114             } # End of draw.
115              
116             # ------------------------------------------------
117              
118             sub dump
119             {
120             my $self = shift @_;
121              
122             print $self -> _DUMP();
123             $self -> dump_font_metrics();
124             $self -> highlight_data_points();
125              
126             } # End of dump.
127              
128             # ------------------------------------------------
129              
130             sub dump_font_metrics
131             {
132             my $self = shift @_;
133             my $id = ident $self;
134             my %metric_name =
135             (
136             0 => 'character width',
137             1 => 'character height',
138             2 => 'ascender',
139             3 => 'descender',
140             4 => 'text width',
141             5 => 'text height',
142             6 => 'maximum horizontal advance',
143             7 => 'bounds.x1',
144             8 => 'bounds.y1',
145             9 => 'bounds.x2',
146             10 => 'bounds.y2',
147             11 => 'origin.x',
148             12 => 'origin.y',
149             );
150              
151             my @metric = $image{$id} -> QueryFontMetrics
152             (
153             pointsize => $pointsize{$id},
154             strokewidth => $strokewidth{$id},
155             text => 'W',
156             );
157              
158             print map{"$metric_name{$_}: $metric[$_]. \n"} 0 .. $#metric;
159             print "\n";
160              
161             my $i;
162             my $left_x;
163             my $left_y;
164             my $result;
165             my $right_x;
166             my $right_y;
167              
168             for ($i = 0; $i <= $#{$x{$id} }; $i++)
169             {
170             $left_x = $x{$id}[$i] - $metric[7];
171             $left_y = $y{$id}[$i] - $metric[8];
172             $right_x = $x{$id}[$i] + $metric[9];
173             $right_y = $y{$id}[$i] + $metric[10];
174             $result = $image{$id} -> Draw
175             (
176             fill => 'None',
177             points => "$left_x,$left_y $right_x,$right_y",
178             primitive => 'rectangle',
179             stroke => 'Blue',
180             strokewidth => 1,
181             );
182              
183             die $result if $result;
184             }
185              
186             } # End of dump_font_metrics.
187              
188             # ------------------------------------------------
189              
190             sub highlight_data_points
191             {
192             my $self = shift @_;
193             my $arg = shift @_;
194             my $id = ident $self;
195             my %option =
196             (
197             fill => 'None',
198             primitive => 'rectangle',
199             stroke => 'Red',
200             strokewidth => 1,
201             map{(lc $_, $$arg{$_})} keys %$arg,
202             );
203              
204             my $i;
205             my $left_x;
206             my $left_y;
207             my $result;
208             my $right_x;
209             my $right_y;
210              
211             for ($i = 0; $i <= $#{$x{$id} }; $i++)
212             {
213             $left_x = $x{$id}[$i] - 2;
214             $left_y = $y{$id}[$i] - 2;
215             $right_x = $x{$id}[$i] + 2;
216             $right_y = $y{$id}[$i] + 2;
217             $option{'points'} = "$left_x,$left_y $right_x,$right_y";
218             $result = $image{$id} -> Draw(%option);
219              
220             die $result if $result;
221             }
222              
223             } # End of highlight_data_points.
224              
225             # ------------------------------------------------
226              
227             } # End of package.
228              
229             1;
230              
231             =head1 NAME
232              
233             C - Draw text along a polyline
234              
235             =head1 Synopsis
236              
237             my $polytext = Image::Magick::PolyText -> new
238             ({
239             debug => 0,
240             fill => 'Red',
241             image => $image,
242             pointsize => 16,
243             rotate => 1,
244             slide => 0.1,
245             stroke => 'Red',
246             strokewidth => 1,
247             text => 'Draw text along a polyline',
248             x => [0, 1, 2, 3, 4],
249             'y' => [0, 1, 2, 3, 4], # y eq tr so emacs' syntax highlighting is stuffed without ''.
250             });
251              
252             $polytext -> annotate();
253              
254             =head1 Description
255              
256             C is a pure Perl module.
257              
258             It is a convenient wrapper around C method, for drawing text along a polyline.
259              
260             =head1 Distributions
261              
262             This module is available both as a Unix-style distro (*.tgz) and an
263             ActiveState-style distro (*.ppd). The latter is shipped in a *.zip file.
264              
265             See http://savage.net.au/Perl-modules.html for details.
266              
267             See http://savage.net.au/Perl-modules/html/installing-a-module.html for
268             help on unpacking and installing each type of distro.
269              
270             =head1 Constructor and initialization
271              
272             new(...) returns an C object.
273              
274             This is the class's contructor.
275              
276             Usage: Image::Magick::PolyText -> new({...}).
277              
278             This method takes a hashref of parameters.
279              
280             For each parameter you wish to use, call new as new({param_1 => value_1, ...}).
281              
282             =over 4
283              
284             =item debug
285              
286             Takes either 0 or 1 as its value.
287              
288             The default value is 0.
289              
290             When set to 1, the module writes to STDOUT, and plots various stuff on your image.
291              
292             This parameter is optional.
293              
294             =item fill
295              
296             Takes an C color as its value.
297              
298             The default value is 'Red'.
299              
300             The value is passed to C method.
301              
302             This parameter is optional.
303              
304             =item image
305              
306             Takes an C object as its value.
307              
308             There is no default value.
309              
310             This parameter is mandatory.
311              
312             =item pointsize
313              
314             Takes an integer as its value.
315              
316             The default value is 16.
317              
318             The value is passed to C method.
319              
320             This parameter is optional.
321              
322             =item rotate
323              
324             Takes either 0 or 1 as its value.
325              
326             The default value is 1.
327              
328             When set to 0, the module does not rotate any characters in the text.
329              
330             When set to 1, the module rotates each character in the text to match the tangent of the polyline
331             at the 'current' (x, y) position.
332              
333             This parameter is optional.
334              
335             =item slide
336              
337             Takes a real number in the range 0.0 to 1.0 as its value.
338              
339             The default value is 0.0.
340              
341             The value represents how far along the polyline (0.0 = 0%, 1.0 = 100%) to slide the first character of the text.
342              
343             The parameter is optional.
344              
345             =item stroke
346              
347             Takes an C color as its value.
348              
349             The default value is 'Red'.
350              
351             The value is passed to C method.
352              
353             This parameter is optional.
354              
355             =item strokewidth
356              
357             Takes an integer as its value.
358              
359             The default value is 1.
360              
361             The value is passed to C method.
362              
363             This parameter is optional.
364              
365             =item text
366              
367             Takes a string of characters as its value.
368              
369             There is no default value.
370              
371             This text is split character by character, and each character is drawn with a separate call to
372             C method. This is a very slow process. You have been warned.
373              
374             This parameter is mandatory.
375              
376             =item x
377              
378             Takes an array ref of x (co-ordinate) values as its value.
379              
380             There is no default value.
381              
382             These co-ordinates are the x-axis values of the known points along the polyline.
383              
384             This parameter is mandatory.
385              
386             =item y
387              
388             Takes an array ref of y (abcissa) values as its value.
389              
390             There is no default value.
391              
392             These abcissae are the y-axis values of the known points along the polyline.
393              
394             This parameter is mandatory.
395              
396             =back
397              
398             =head1 Method: annotate()
399              
400             This method writes the text on to your image.
401              
402             =head1 Method: draw({options})
403              
404             This method draws straight lines from data point to data point.
405              
406             The default line color is Green.
407              
408             The options are a hash ref which is passed to C method, so any option
409             acceptable to C is acceptable here.
410              
411             A typical usage would be $polytext -> draw({stroke => 'Blue'});
412              
413             =head1 Method: highlight_data_points({options})
414              
415             This method draws little (5x5 pixel) rectangles centered on the data points.
416              
417             The default rectangle color is Red.
418              
419             The options are a hash ref which is passed to C method, so any option
420             acceptable to C is acceptable here.
421              
422             A typical usage would be $polytext -> highlight_data_points({stroke => 'Black'});
423              
424             =head1 Example code
425              
426             See the file examples/pt.pl in the distro.
427              
428             =head1 Required Modules
429              
430             =over 4
431              
432             =item Class::Std
433              
434             =item Math::Bezier
435              
436             =item Math::Interpolate
437              
438             =item Readonly
439              
440             =back
441              
442             =head1 Changes
443              
444             See the ChangeLog file.
445              
446             =head1 Author
447              
448             C was written by Ron Savage Iron@savage.net.auE> in 2007.
449              
450             Home page: http://savage.net.au/index.html
451              
452             =head1 Copyright
453              
454             Australian copyright (c) 2007, Ron Savage. All rights reserved.
455              
456             All Programs of mine are 'OSI Certified Open Source Software';
457             you can redistribute them and/or modify them under the terms of
458             The Artistic License, a copy of which is available at:
459             http://www.opensource.org/licenses/index.html
460              
461             =cut