File Coverage

lib/PDF/Boxer.pm
Criterion Covered Total %
statement 36 69 52.1
branch 0 4 0.0
condition n/a
subroutine 12 17 70.5
pod 4 4 100.0
total 52 94 55.3


line stmt bran cond sub pod time code
1             package PDF::Boxer;
2             {
3             $PDF::Boxer::VERSION = '0.004';
4             }
5 3     3   4659 use Moose;
  3         1736360  
  3         28  
6              
7             # ABSTRACT: Create PDFs from a simple box markup language.
8              
9              
10 3     3   27794 use namespace::autoclean;
  3         4564  
  3         17  
11              
12 3     3   1491 use PDF::Boxer::Doc;
  3         12  
  3         192  
13 3     3   2242 use PDF::Boxer::Content::Box;
  3         12  
  3         151  
14 3     3   2264 use PDF::Boxer::Content::Text;
  3         12  
  3         135  
15 3     3   1980 use PDF::Boxer::Content::Image;
  3         14  
  3         140  
16 3     3   1992 use PDF::Boxer::Content::Row;
  3         12  
  3         135  
17 3     3   7480 use PDF::Boxer::Content::Column;
  3         11  
  3         131  
18 3     3   2323 use PDF::Boxer::Content::Grid;
  3         11  
  3         171  
19 3     3   30 use Try::Tiny;
  3         7  
  3         237  
20 3     3   17 use Scalar::Util qw/weaken/;
  3         10  
  3         143  
21 3     3   18 use Moose::Util::TypeConstraints;
  3         8  
  3         57  
22              
23             coerce 'PDF::Boxer::Doc'
24             => from 'HashRef'
25             => via { PDF::Boxer::Doc->new($_) };
26              
27             has 'debug' => ( isa => 'Bool', is => 'ro', default => 0 );
28              
29             has 'doc' => ( isa => 'PDF::Boxer::Doc', is => 'ro', coerce => 1, lazy_build => 1 );
30              
31             has 'max_width' => ( isa => 'Int', is => 'rw', default => 595 );
32             has 'max_height' => ( isa => 'Int', is => 'rw', default => 842 );
33              
34             has 'box_register' => ( isa => 'HashRef', is => 'ro', default => sub{{}} );
35              
36             sub _build_doc{
37 0     0     my ($self) = @_;
38 0           return PDF::Boxer::Doc->new;
39             }
40              
41             sub register_box{
42 0     0 1   my ($self, $box) = @_;
43 0 0         return unless $box->name;
44 0           weaken($box);
45 0           $self->box_register->{$box->name} = $box;
46             }
47              
48             sub box_lookup{
49 0     0 1   my ($self, $name) = @_;
50 0           return $self->box_register->{$name};
51             }
52              
53             sub add_to_pdf{
54 0     0 1   my ($self, $spec) = @_;
55              
56 0           my $weak_me = $self;
57 0           weaken($weak_me);
58 0           $spec->{boxer} = $weak_me;
59 0           $spec->{debug} = $self->debug;
60              
61 0 0         if ($spec->{type} eq 'Doc'){
62 0           foreach my $page (@{$spec->{children}}){
  0            
63 0           $page->{boxer} = $weak_me;
64 0           $page->{debug} = $self->debug;
65            
66 0           my $class = 'PDF::Boxer::Content::'.$page->{type};
67 0           my $node = $class->new($page);
68 0           $self->register_box($node);
69 0           $node->initialize;
70 0           $node->render;
71 0           $self->doc->new_page;
72             }
73             } else {
74 0           my $class = 'PDF::Boxer::Content::'.$spec->{type};
75 0           my $node = $class->new($spec);
76 0           $self->register_box($node);
77 0           $node->initialize;
78 0           $node->render;
79             }
80              
81 0           return 1;
82             #return $node;
83             }
84              
85             sub finish{
86 0     0 1   my ($self) = @_;
87 0           $self->doc->pdf->save;
88 0           $self->doc->pdf->end;
89             }
90              
91             __PACKAGE__->meta->make_immutable;
92              
93             1;
94              
95             __END__
96             =pod
97              
98             =head1 NAME
99              
100             PDF::Boxer - Create PDFs from a simple box markup language.
101              
102             =head1 VERSION
103              
104             version 0.004
105              
106             =head1 SYNOPSIS
107              
108             $pdfml = <<'__EOP__';
109             <column max_width="595" max_height="842">
110             <column border_color="blue" border="2">
111             <row>
112             <image src="t/lecstor.gif" align="center" valign="center" padding="10" scale="60" />
113             <column grow="1" padding="10 10 10 0">
114             <text padding="3" align="right" size="20">
115             Lecstor Pty Ltd
116             </text>
117             <text padding="3" align="right" size="14">
118             123 Example St, Somewhere, Qld 4879
119             </text>
120             </column>
121             </row>
122             <row padding="15 0">
123             <text padding="20" size="14">
124             Mr G Client
125             Shop 2 Some Centre, Retail Rd
126             Somewhere, NSW 2000
127             </text>
128             <column padding="20" border_color="red" grow="1">
129             <text size="16" align="right" font="Helvetica-Bold">
130             Tax Invoice No. 123
131             </text>
132             <text size="14" align="right">
133             Issued 01/01/2011
134             </text>
135             <text size="14" align="right" font="Helvetica-Bold">
136             Due 14/01/2011
137             </text>
138             </column>
139             </row>
140             </column>
141             <grid padding="10">
142             <row font="Helvetica-Bold" padding="0">
143             <text align="center" padding="0 10">Name</text>
144             <text grow="1" align="center" padding="0 10">Description</text>
145             <text padding="0 10" align="center">GST Amount</text>
146             <text padding="0 10" align="center">Payable Amount</text>
147             </row>
148             <row margin="10 0 0 0">
149             <text padding="0 5">Web Services</text>
150             <text name="ItemText2" grow="1" padding="0 5">
151             a long description which needs to be wrapped to fit in the box
152             </text>
153             <text padding="0 5" align="right">$9999.99</text>
154             <text padding="0 5" align="right">$99999.99</text>
155             </row>
156             </grid>
157             </column>
158             __EOP__
159              
160             $parser = PDF::Boxer::SpecParser->new;
161             $spec = $parser->parse($pdfml);
162              
163             $boxer = PDF::Boxer->new( doc => { file => 'test_invoice.pdf' } );
164              
165             $boxer->add_to_pdf($spec);
166             $boxer->finish;
167              
168             =head1 DESCRIPTION
169              
170             PDF::Boxer enables the creation of pdf documents using rows, columns, and grids
171             for layout. An xml styled document is used to specify the contents of the
172             document and is parsed into a block of data by PDF::Boxer::SpecParser and
173             passed to PDF::Boxer
174              
175             Suggestion: Use L<Template> to dynamically create your PDFML template.
176              
177             =head1 METHODS
178              
179             =head2 add_to_pdf
180              
181             $boxer->add_to_pdf($spec);
182              
183             Coverts markup to PDF.
184              
185             =head2 finish
186              
187             Writes the generated PDF to the file specified in the call to new.
188              
189             =head2 register_box
190              
191             each named element is added to an internal register upon creation.
192              
193             =head2 box_lookup
194              
195             $boxer->box_lookup('elementName');
196              
197             get an element from the register.
198              
199             =head1 MARKUP
200              
201             For a single page document the parent element may be a row, column, or grid.
202             Multiple pages can be generated by wrapping more than one of these elements
203             with a doc element.
204              
205             =head2 ELEMENTS
206              
207             =item column
208              
209             a column stacks elements vertically. Each element will be as wide as the
210             column's content space. If one or more children have the "grow" attribute
211             set then they will be stretched vertically to fill the column.
212              
213             =item row
214              
215             a row places it's children horizontally. If one or more children have the
216             "grow" attribute set then they will be stretched horizontally to fill the
217             row.
218              
219             =item grid
220              
221             a grid is a column with rows for children. The width of the rows' child elements
222             are locked vertically (like an html table).
223              
224             You can now set the hborder and/or vborder attributes an a grid to display
225             gridlines.
226              
227             eg <grid hborder="1" vborder="1">
228              
229             =item text
230              
231             the text element contains.. text! Text is wrapped to fith the width of it's
232             container if necessary.
233              
234             =item image
235              
236             the image element places an image in the PDF.. whoda thunkit, eh?
237             the image can be scaled to a percentage of it's original size.
238              
239             =head2 ATTRIBUTES
240              
241             =over
242              
243             =item align
244              
245             align="right"
246              
247             align right or center instead of the default left.
248              
249             =item background
250              
251             background="#FF0000"
252              
253             background is set as a hexadecimal color.
254              
255             =item border_color
256              
257             border_color="#FF0000"
258              
259             border_color is set as a hexadecimal color.
260              
261             =item font
262              
263             =item grow
264              
265             when set to true, the element will expand to take up any available space.
266              
267             =item margin, padding, border
268              
269             size set in pixels as a string for top, right, bottom, left.
270             eg:
271             margin="5 10 15 20"; top = 5, right = 10, bottom = 15, left = 20.
272             margin="5 10"; top = 5, right = 10, bottom = 5, left = 10.
273              
274             margin is space outside the border.
275             padding is space inside the border.
276             border IS the border..
277              
278             =item name
279              
280             I use this for debugging mostly.
281             It can be used to get an element object via the box_lookup method.
282              
283             =back
284              
285             =head1 BUGS
286              
287             positioning of elements not pixel perfect. eg. in a column the bottom of one
288             child overlaps the top of the next by 1 pixel.
289              
290             =head1 TODO
291              
292             =over
293              
294             =item paging
295              
296             - enable a single element to be nominated for paging so if it's content is too
297             large to fit on a page it is continued on the next page.
298              
299             - enable elements to be marked as first or last page only.
300              
301             =back
302              
303             =head1 SEE ALSO
304              
305             =over 4
306              
307             =item *
308              
309             L<PDF::Boxer::Content::Box>
310              
311             =item *
312              
313             L<PDF::Boxer::Content::Row>
314              
315             =item *
316              
317             L<PDF::Boxer::Content::Column>
318              
319             =item *
320              
321             L<PDF::Boxer::Content::Grid>
322              
323             =item *
324              
325             L<PDF::Boxer::Content::Text>
326              
327             =item *
328              
329             L<PDF::Boxer::Content::Image>
330              
331             =back
332              
333             =head1 AUTHOR
334              
335             Jason Galea <lecstor@cpan.org>
336              
337             =head1 COPYRIGHT AND LICENSE
338              
339             This software is copyright (c) 2012 by Jason Galea.
340              
341             This is free software; you can redistribute it and/or modify it under
342             the same terms as the Perl 5 programming language system itself.
343              
344             =cut
345