File Coverage

blib/lib/Image/Button.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::Button;
2              
3 1     1   12 use strict;
  1         2  
  1         35  
4 1     1   5 use vars qw($VERSION);
  1         1  
  1         47  
5              
6             $VERSION = "0.53";
7             # $Id: Button.pm,v 1.5 2003/02/22 15:41:19 joanmg Exp $
8              
9 1     1   6781 use GD 1.20;
  0            
  0            
10             use Cwd 'abs_path';
11              
12             sub new
13             {
14             my $pkg = shift;
15             my %args = (@_);
16             my $self = bless {}, $pkg;
17             $self->allocate(%args);
18             return $self;
19             }
20              
21             # You might need to override allocate when subclassing. Be careful,
22             # though: for the copy constructor to work and everything to be clean
23             # and nice, the entries in the $self dictionary have to have the same
24             # names as the arguments.
25             sub allocate
26             {
27             my $self = shift;
28             my %args = (text => '',
29             file => '',
30             font => undef,
31             fontsize => 12,
32             btcolor => [ 238, 238, 204 ],
33             fgcolor => [ 0, 0, 0 ],
34             bgcolor => [ 255, 255, 255 ],
35             vmargin => 4,
36             hmargin => 4,
37             @_,);
38              
39             unless ($args{file}) {
40             if ($args{text}) {
41             $args{file} = $self->fileFromText(text => $args{text});
42             }
43             }
44             # There might be something in $self, coming from a possibly
45             # overridden new function. The arguments to allocate take
46             # precedence.
47             %$self = (%$self, %args);
48             }
49              
50             sub print
51             {
52             die "Button class should override print.\n";
53             }
54              
55             sub copy
56             {
57             my $self = shift;
58             my %args = (@_);
59              
60             unless ($args{file}) {
61             if ($args{text}) {
62             $args{file} = $self->fileFromText(text => $args{text});
63             }
64             }
65              
66             my $nself = {};
67             %$nself = (%$self, %args);
68             bless $nself, ref($self);
69             return $nself;
70             }
71              
72             # Used by Button::Set to change values.
73             sub override
74             {
75             my $self = shift;
76             my %args = (self => {},
77             @_,);
78             while (my ($par, $val) = each(%{ $args{self} })) {
79             $self->{$par} = $val;
80             }
81             }
82              
83             # Used by Button::Set to set the text size.
84             sub textSize
85             {
86             my $self = shift;
87             my %args = (texth => undef,
88             textw => undef,
89             @_,);
90             $self->{texth} = $args{texth};
91             $self->{textw} = $args{textw};
92             }
93              
94             # Used by Button::Set when it needs to figure out a common size for a
95             # set of buttons. Returns width and height.
96             sub getSize
97             {
98             my $self = shift;
99              
100             my $text = $self->{text};
101             my $font = $self->{font};
102             my $size = $self->{fontsize};
103            
104             $font = $self->getFont($font);
105              
106             my @bounds = &GD::Image::stringFT('GD::Image', 0, $font,
107             $size, 0, 0, 0, $text);
108             if (!@bounds) {
109             die "Error figuring out bounds for '$text': $@\n";
110             }
111              
112             return ($bounds[2] - $bounds[0], $bounds[1] - $bounds[7]);
113             }
114              
115             # We need the absolute path of the font. Using TTFONTS environment
116             # variable to point to the fonts directory; is there a standard
117             # way/place to do that? ##!!
118             sub getFont
119             {
120             my $self = shift;
121             my ($font) = @_;
122              
123             if ($font !~ m|^/|) {
124             if (-f $font) {
125             $font = abs_path . "/$font";
126             }
127             elsif ($ENV{TTFONTS}) {
128             $font = $ENV{TTFONTS} . "/$font";
129             }
130             }
131             die "Cound not find absolute path for font $font\n" unless -f $font;
132             return $font;
133             }
134              
135             # Applies prefix and postfix. Should be the same for all button types.
136             sub buildFile
137             {
138             my $self = shift;
139             my %args = (file => $self->{file},
140             prefix => '',
141             postfix => '',
142             @_,);
143              
144             my $file = $args{file}; die "Need output file\n" unless $file;
145             if ($args{prefix}) { $file = "$args{prefix}$file" }
146             if ($args{postfix}) {
147             my $short = $file;
148             my $ext = '';
149             if ($short =~ s/(\..+?)$//) {
150             $ext = $1;
151             }
152             $file = "$short$args{postfix}$ext";
153             }
154             $file;
155             }
156              
157             sub fileFromText
158             {
159             my $self = shift;
160             my %args = (text => '',
161             @_,);
162             my $text = $args{text};
163              
164             # Don't want spaces in my file names
165             $text =~ s/\s+/-/g;
166              
167             # Don't want tildes either
168             my %toplain = ('á' => "a", 'à' => "a", 'ä' => "a",
169             'é' => "e", 'è' => "e", 'ë' => "e",
170             'í' => "i", 'ì' => "i", 'ï' => "i",
171             'ó' => "o", 'ò' => "o", 'ö' => "o",
172             'ú' => "u", 'ù' => "u", 'ü' => "u");
173             while (my ($accent, $plain) = each(%toplain)) {
174             $text =~ s/$accent/$plain/g;
175             }
176              
177             return "$text.png";
178             }
179              
180             1;
181              
182             =head1 NAME
183              
184             Image::Button - Base class for building PNG buttons using GD.
185              
186             =head1 SYNOPSIS
187              
188             use Image::Button::Rect;
189              
190             my $b1 = new Image::Button::Rect(text => 'text b1',
191             font => 'newsgotn.ttf',
192             fontsize => 20,
193             file => 'b1.png');
194              
195             # $b2 is like $b1, but with different text and going to another file
196             my $b2 = $b1->copy(text => 'text b2',
197             file => 'b2.png');
198              
199             $b1->print;
200             $b2->print;
201              
202             =head1 DESCRIPTION
203              
204             Image::Button builds simple PNG buttons of the type you would use in
205             an on-line application. It provides facilities to build several of
206             them, possibly related (same width and/or height). Modules to create
207             different types of buttons can be easily integrated. The buttons it
208             can create so far would not cause a graphic designer to jump from his
209             chair, drooling with excitement. But he wouldn't fall from his chair
210             in disgust either (I hope).
211              
212             =head2 Fonts
213              
214             Image::Button uses GD with TrueType support, which requires freetype
215             (http://www.freetype.org). It also requires true type fonts. It's
216             remarkably difficult to find free fonts out there that can be used to
217             make decent buttons (clean, non-pretentious, ideally sans-serif). Let
218             me know if you find any.
219              
220             The TrueType fonts should be located either in the current directory
221             or in the directory pointed at by the environment variable I.
222              
223             =head2 Adding new button types
224              
225             Image::Button is a base class intended to be derived by classes
226             implementing different types of buttons. Available so far are:
227              
228             =over 4
229              
230             =item F,
231              
232             plain rectangular buttons with an optional border,
233              
234             =item F,
235              
236             rectangular three dimensional buttons.
237              
238             =back
239              
240             If you want to implement a new type of button (say, oval) you can take
241             advantage of the existing infrastructure by deriving from
242             Image::Button, and overriding the I, I and I
243             functions, as Image::Button::Plain does.
244              
245             =head1 FUNCTIONS
246              
247             There is only OO interface to the packages, and all function calls
248             require named parameters.
249              
250             =head2 Constructor
251              
252             The way to construct the button will depend on the button type being
253             constructed, but it will generally be of the form:
254              
255             my $b = new Image::Button::Rect(text => 'text',
256             font => 'newsgotn.ttf',
257             fontsize => 20,
258             fgcolor => [ 85, 85, 136 ], # text
259             btcolor => [ 238, 238, 204 ],
260             bgcolor => [ 255, 255, 255 ],
261             file => 'file.png');
262              
263             See the man page of the button you are trying to construct for a
264             description of the arguments.
265              
266             =head2 Print the button
267              
268             $b->print(file => 'button.png',
269             prefix => '',
270             postfix => '');
271              
272             Prints the button to a file. If the I argument is not set it
273             will print to the one specified in the button constructor. The
274             I and I arguments are prepended and appended to the
275             file name, respectively. They are useful when printing sets of
276             buttons, where you might want to print them several times, with small
277             modifications, to different file names (for example, changing the
278             color).
279              
280             =head2 Copy the button
281              
282             $b2 = $b->copy(text => 'new text',
283             file => 'button2.png',
284             fontsize => 21);
285              
286             Copy constructor. If no arguments are specified returns an exact copy
287             of the original button. If called with any of the arguments of the
288             original button constructor it will override the original button's
289             values. Use it to build sets of related buttons; for example, same
290             font and colors, but different texts and output files.
291              
292             =head2 Change the button
293              
294             $b->override(self => { btcolor => [10, 10, 10],
295             fontsize => 12 });
296              
297             Accepts a dictionary reference I with new parameters. Any
298             parameter that the button's constructor understands can be reset here.
299              
300             =head1 SEE ALSO
301              
302             F for specifics on plain rectangular buttons.
303              
304             F for specifics on 3D rectangular buttons.
305              
306             F for building sets of related buttons.
307              
308             =head1 TODO
309              
310             Add tests. Oval buttons. Triangular buttons (arrow type).
311              
312             =head1 AUTHOR
313              
314             Juan M. García-Reyero Ejoanmg@twostones.orgE
315              
316             =head1 COPYRIGHT
317              
318             Copyright (C) 2003 Juan M. García-Reyero. All Rights Reserved.
319              
320             This module is free software; you can redistribute it and/or
321             modify it under the same terms as Perl itself.
322              
323