File Coverage

blib/lib/PeGS/PDF.pm
Criterion Covered Total %
statement 22 220 10.0
branch 0 18 0.0
condition 0 3 0.0
subroutine 8 49 16.3
pod 0 33 0.0
total 30 323 9.2


line stmt bran cond sub pod time code
1             package PeGS::PDF;
2 2     2   2308 use strict;
  2         4  
  2         95  
3              
4 2     2   11 use warnings;
  2         5  
  2         137  
5 2     2   168 no warnings;
  2         6  
  2         118  
6              
7 2     2   2323 use subs qw();
  2         66  
  2         51  
8 2     2   11 use vars qw($VERSION);
  2         3  
  2         126  
9              
10             $VERSION = '0.10_02';
11              
12             =encoding utf8
13              
14             =head1 NAME
15              
16             PeGS::PDF - Draw simple Perl Graphical Structures
17              
18             =head1 SYNOPSIS
19              
20             use PeGS::PDF;
21              
22             =head1 DESCRIPTION
23              
24             =over 4
25              
26             =cut
27              
28 2     2   11 use base qw(PDF::EasyPDF);
  2         2  
  2         1822  
29              
30 2     2   9759 use List::Util qw(max);
  2         6  
  2         8027  
31              
32 0     0 0   sub padding_factor { 0.7 }
33 0     0 0   sub font_height { 10 }
34 0     0 0   sub font_width { 6 }
35 0     0 0   sub font_size { 10 }
36 0     0 0   sub connector_height { 10 }
37 0     0 0   sub black_bar_height { 5 }
38 0     0 0   sub stroke_width { 0.5 }
39 0     0 0   sub pointy_width { ( $_[0]->font_height + 2 * $_[0]->y_padding ) / 2 * sqrt(2) }
40 0     0 0   sub box_height { $_[0]->font_height + 2 * $_[0]->y_padding }
41              
42 0     0 0   sub y_padding { $_[0]->padding_factor * $_[0]->font_height }
43 0     0 0   sub x_padding { $_[0]->padding_factor * $_[0]->font_width }
44              
45             sub make_reference {
46 0     0 0   my( $pdf, $name, $value, $bottom_left_x, $bottom_left_y ) = @_;
47              
48 0           my $scalar_width = $pdf->font_width * length $name;
49              
50 0           $pdf->make_pointy_box(
51             $bottom_left_x,
52             $bottom_left_y,
53             $scalar_width + 2 * $pdf->x_padding,
54             $pdf->box_height,
55             $name
56             );
57              
58 0           $pdf->lines(
59             ( $bottom_left_x + $pdf->x_padding + $scalar_width / 2 ), $bottom_left_y,
60             ( $bottom_left_x + $pdf->x_padding + $scalar_width / 2 ), $bottom_left_y - 10,
61             );
62              
63              
64 0           $pdf->make_text_box(
65             $bottom_left_x,
66             $bottom_left_y - 10 - $pdf->font_height - 2 * $pdf->y_padding,
67             $scalar_width + 2 * $pdf->x_padding,
68             $pdf->box_height,
69             ''
70             );
71              
72 0           my $arrow_start = XYPoint->new(
73             $bottom_left_x + ( $scalar_width + 2 * $pdf->x_padding ) / 2,
74             $bottom_left_y + $pdf->box_height / 2 - $pdf->connector_height - $pdf->box_height - 2*$pdf->stroke_width,
75             );
76              
77 0           my $arrow_end = $pdf->make_reference_arrow(
78             $arrow_start,
79             $pdf->arrow_angle,
80             $pdf->arrow_length($scalar_width),
81             );
82              
83 0           $pdf->make_reference_icon(
84             #$bottom_left_x + ( $scalar_width + 2 * $pdf->x_padding ) / 2,
85             #$bottom_left_y + $pdf->box_height / 2 - $pdf->connector_height - $pdf->box_height,
86             $arrow_start
87             );
88              
89 0           my $x = $pdf->arrow_length( $scalar_width ) + $bottom_left_x + ( $scalar_width + 2 * $pdf->x_padding ) / 2;
90              
91 0 0         if( ref $value eq ref \ '' ) {
    0          
    0          
92              
93             }
94             elsif( ref $value eq ref [] ) {
95 0           $pdf->make_list(
96             $value,
97             $arrow_end->x,
98             $arrow_end->y - $pdf->black_bar_height / 2,
99             );
100              
101             }
102             elsif( ref $value eq ref {} ) {
103 0           $pdf->make_anonymous_hash(
104             $value,
105             $arrow_end->x,
106             $arrow_end->y - $pdf->black_bar_height / 2,
107             );
108              
109             }
110              
111             }
112              
113             sub make_circle {
114 0     0 0   my( $pdf,
115             $xc, # x at the center of the circle
116             $yc, # y at the center of the circle
117             $r # radius
118             ) = @_;
119              
120 0           $pdf->lines( $xc, $yc + 30, $xc, $yc - 30 );
121 0           $pdf->lines( $xc - 30, $yc, $xc + 30, $yc );
122              
123 0           my $points = 5;
124 0           my $Pi = 3.1415926;
125              
126 0           my $arc = 2 * $Pi / $points;
127              
128 0           my $darc = $arc * 360 / ( 2 * $Pi );
129             =pod
130              
131             my @points = map
132             [ $xc + $r * cos( $arc * $_ / 2 ), $yc + $r * sin( $arc * $_ / 2 ) ],
133             0 .. $points - 1;
134              
135             =cut
136              
137 0           my @points = (
138             [ $r * cos( $arc / 2 ), $r * sin( $arc / 2 ) ],
139             [ $r * cos( - $arc / 2 ), $r * sin( - $arc / 2 ) ],
140             );
141              
142 0           $pdf->{stream} .= "@{$points[0]} m\n";
  0            
143              
144 0           foreach my $i ( 0 .. $points - 1 ) {
145 0           my( @xp, @yp );
146              
147 0           ( $xp[0], $yp[0], $xp[3], $yp[3] ) = ( @{ $points[0] }, @{ $points[1] } );
  0            
  0            
148              
149 0           ( $xp[1], $yp[1] ) = ( (4 * $r - $xp[0])/3, (1-$xp[0])*(3-$xp[0])/(3*$yp[0]) );
150              
151 0           ( $xp[2], $yp[2] ) = ( $xp[1], -$yp[1] );
152              
153             # rotate and translate
154 0           my @x = map { $_ + $xc } map { $xp[$_] * cos( $arc * $i ) + $yp[$_] * sin( $arc * $i ) } 0 .. $#xp;
  0            
  0            
155 0           my @y = map { $_ + $yc } map { - $xp[$_] * sin( $arc * $i ) + $yp[$_] * cos( $arc * $i ) } 0 .. $#yp;
  0            
  0            
156              
157 0           $pdf->{stream} .= "$x[0] $y[0] m\n$x[1] $y[1] $x[2] $y[2] $x[3] $y[3] c\nf\n";
158              
159             #$pdf->lines( $x0, $y0, $x1, $y1 );
160             #$pdf->lines( $x1, $y1, $x1, $y1 + 10 );
161             #$pdf->lines( $x3, $y3, $x2, $y2 );
162             #$pdf->lines( $x2, $y2, $x2, $y2 - 10 );
163             }
164              
165             }
166              
167             =pod
168              
169             $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
170                               $x + $b, $y,
171                               $x + $r, $y - $r + $b,
172                               $x + $r, $y - $r);
173                 /* Set x/y to the final point. */
174                 $x = $x + $r;
175                 $y = $y - $r;
176                 /* Third circle quarter. */
177                 $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c',
178                               $x, $y - $b,
179                               $x - $r + $b, $y - $r,
180                               $x - $r, $y - $r);
181                 /* Set x/y to the final point. */
182                 $x = $x - $r;
183                 $y = $y - $r;
184                 /* Fourth circle quarter. */
185                 $c .= sprintf(' %.2f %.2f %.2f %.2f %.2f %.2f c %s',
186                               $x - $b, $y,
187                               $x - $r, $y + $r - $b,
188                               $x - $r, $y + $r,
189                               $op);
190             =cut
191              
192             sub make_magic_circle {
193 0     0 0   my( $pdf,
194             $center,
195             $r # radius
196             ) = @_;
197              
198 0           my( $xc, $yc ) = $center->xy;
199              
200 0           my $magic = $r * 0.552;
201 0           my( $x0p, $y0p ) = ( $xc - $r, $yc );
202 0           $pdf->{stream} .= "$x0p $y0p m\n";
203              
204             {
205 0           ( $x0p, $y0p ) = ( $xc - $r, $yc );
  0            
206 0           my( $x1, $y1 ) = ( $x0p, $y0p + $magic );
207 0           my( $x2, $y2 ) = ( $x0p + $r - $magic, $y0p + $r );
208 0           my( $x3, $y3 ) = ( $x0p + $r, $y0p + $r );
209 0           $pdf->{stream} .= "$x1 $y1 $x2 $y2 $x3 $y3 c\n";
210             }
211              
212             {
213 0           ( $x0p, $y0p ) = ( $xc, $yc + $r );
  0            
214 0           my( $x1, $y1 ) = ( $x0p + $magic, $y0p );
215 0           my( $x2, $y2 ) = ( $x0p + $r, $y0p - $r + $magic );
216 0           my( $x3, $y3 ) = ( $x0p + $r, $y0p - $r );
217 0           $pdf->{stream} .= "$x1 $y1 $x2 $y2 $x3 $y3 c\n";
218             }
219              
220             {
221 0           ( $x0p, $y0p ) = ( $xc + $r, $yc );
  0            
222 0           my( $x1, $y1 ) = ( $x0p, $y0p - $magic );
223 0           my( $x2, $y2 ) = ( $x0p - $r + $magic, $y0p - $r );
224 0           my( $x3, $y3 ) = ( $x0p - $r, $y0p - $r );
225 0           $pdf->{stream} .= "$x1 $y1 $x2 $y2 $x3 $y3 c\n";
226             }
227              
228             {
229 0           ( $x0p, $y0p ) = ( $xc, $yc - $r );
  0            
230 0           my( $x1, $y1 ) = ( $x0p - $magic, $y0p );
231 0           my( $x2, $y2 ) = ( $x0p - $r, $y0p + $r - $magic );
232 0           my( $x3, $y3 ) = ( $x0p - $r, $y0p + $r );
233 0           $pdf->{stream} .= "$x1 $y1 $x2 $y2 $x3 $y3 c\n";
234             }
235              
236 0           $pdf->{stream} .= "f\n";
237             }
238              
239             sub make_regular_polygon {
240 0     0 0   my( $pdf,
241             $xc, # x at the center of the circle
242             $yc, # y at the center of the circle
243             $points,
244             $r # radius,
245             ) = @_;
246              
247 0           my $arc = 2 * 3.1415926 / $points;
248              
249 0           my @points = map
250             [ $xc + $r * cos( $arc * $_ ), $yc + $r * sin( $arc * $_ ) ],
251             0 .. $points - 1;
252              
253              
254 0           foreach my $i ( 0 .. $#points ) {
255 0           $pdf->lines(
256 0           @{ $points[$i] },
257 0           @{ $points[$i-1] },
258             );
259             }
260              
261             }
262              
263 0     0 0   sub arrow_factor { 15 }
264              
265             sub arrow_length {
266 0     0 0   my( $pdf, $base ) = @_;
267              
268 0 0         if( defined $base ) { $base + $pdf->arrow_factor; }
  0            
269 0           else { 85 }
270              
271             }
272              
273              
274 0     0 0   sub arrow_angle { 90 }
275              
276             sub make_reference_arrow {
277 0     0 0   my( $pdf, $start, $angle, $length ) = @_;
278              
279 0           my $arrow_end = $start->clone;
280 0           $arrow_end->add_x( $length * sin( $angle * 2 * 3.14 / 360 ) );
281 0           $arrow_end->add_y( $length * cos( $angle * 2 * 3.14 / 360 ) );
282              
283             # the line needs to end before the pointy tip of the arrow,
284             # so back off a little
285 0           my $line_end = $arrow_end->clone;
286 0           $line_end->add_x( -2 * sin( $angle * 2 * 3.14 / 360 ) );
287 0           $line_end->add_y( -2 * cos( $angle * 2 * 3.14 / 360 ) );
288              
289 0           my $L = 8;
290 0           my $l = 8;
291              
292 0           my $beta = 10;
293              
294 0           my $arrow_retro_tip_high = $arrow_end->clone;
295 0           my $arrow_retro_tip_low = $arrow_end->clone;
296              
297 0           $arrow_retro_tip_high->add_x( - $L*sin( $angle * 2 * 3.14 / 360 ) - $l * cos( $angle * 2 * 3.14 / 360 ) / 2 );
298 0           $arrow_retro_tip_high->add_y( - $L*cos( $angle * 2 * 3.14 / 360 ) + $l * sin( $angle * 2 * 3.14 / 360 ) / 2 );
299              
300 0           $arrow_retro_tip_low->add_x( - $L*sin( $angle * 2 * 3.14 / 360 ) + $l * cos( $angle * 2 * 3.14 / 360 ) / 2 );
301 0           $arrow_retro_tip_low->add_y( - $L*cos( $angle * 2 * 3.14 / 360 ) - $l * sin( $angle * 2 * 3.14 / 360 ) / 2 );
302              
303 0           $pdf->lines_xy( $start, $line_end );
304              
305             =pod
306              
307             $pdf->lines( $end_x, $end_y, $arrow_tip1_x, $arrow_tip1_y );
308             $pdf->lines( $end_x, $end_y, $arrow_tip2_x, $arrow_tip2_y );
309              
310             $pdf->lines( $arrow_tip1_x + $pdf->stroke_width, $arrow_tip1_y, $arrow_tip2_x + $pdf->stroke_width, $arrow_tip2_y );
311              
312             =cut
313              
314 0           $pdf->filledPolygon(
315             $arrow_end->xy,
316             $arrow_retro_tip_high->xy,
317             $arrow_retro_tip_low->xy,
318             );
319              
320 0           return $arrow_end;
321             }
322              
323             sub lines_xy {
324 0     0 0   my( $pdf, $start, $end ) = @_;
325              
326 0           $pdf->SUPER::lines(
327             $start->xy,
328             $end->xy,
329             );
330             }
331              
332             sub make_reference_icon {
333 0     0 0   my( $pdf, $center ) = @_;
334              
335 0           $pdf->make_magic_circle(
336             $center,
337             $pdf->box_height / 6,
338             );
339              
340 0           $center;
341             }
342              
343             =for comment
344              
345             http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
346              
347             sub make_circle
348             {
349             my( $pdf, $x, $y, $radius, $start_angle, $end_angle ) = @_;
350              
351             # theta is sweep, which is 360
352              
353             my $Pi2 = 3.1415926 * 2;
354              
355             my( $x0, $y0 ) = ( cos( 180 / $Pi2 ), sin( 180 / $Pi2 ) );
356             my( $x1, $y1 ) = ( (4 - $x0) / 3, (1-$x0)*(3-$x0)/(3*$y0) )
357             my( $x2, $y2 ) = ( $x1, -$y0 );
358             my( $x3, $y3 ) = ( $x1, -$y1 );
359              
360             $pdf->{stream} .= <<"PDF";
361             $x $y m
362             $x1 $y1 $x2 $y2 $x3 $y3 c
363              
364              
365             PDF
366              
367              
368             }
369              
370             =cut
371              
372             sub make_scalar {
373 0     0 0   my( $pdf, $name, $value, $bottom_left_x, $bottom_left_y ) = @_;
374              
375 0           my $length = max( map { length $_ } $name, $$value );
  0            
376              
377 0           my $scalar_width = $pdf->font_width * $length;
378 0           my $scalar_height = 10;
379              
380 0           $pdf->make_pointy_box(
381             $bottom_left_x,
382             $bottom_left_y,
383             $scalar_width + 2 * $pdf->x_padding,
384             $pdf->box_height,
385             $name
386             );
387              
388 0           $pdf->lines(
389             ( $bottom_left_x + $pdf->x_padding + $scalar_width / 2 ), $bottom_left_y,
390             ( $bottom_left_x + $pdf->x_padding + $scalar_width / 2 ), $bottom_left_y - 10,
391             );
392              
393 0           $pdf->make_text_box(
394             $bottom_left_x,
395             $bottom_left_y - 10 - $pdf->font_height - 2 * $pdf->y_padding,
396             $scalar_width + 2 * $pdf->x_padding,
397             $pdf->box_height,
398             $value
399             );
400             }
401              
402             sub make_array {
403 0     0 0   my( $pdf, $name, $array, $bottom_left_x, $bottom_left_y ) = @_;
404              
405 0           my $length = max( map { length $_ } $name, grep { ! ref $_ } @$array );
  0            
  0            
406              
407 0           my $scalar_width = $pdf->font_width * $length;
408              
409 0           $pdf->make_pointy_box(
410             $bottom_left_x,
411             $bottom_left_y,
412             $scalar_width + 2 * $pdf->x_padding,
413             $pdf->box_height,
414             $name
415             );
416              
417 0           $pdf->lines(
418             ( $bottom_left_x + $pdf->x_padding + $scalar_width / 2 ), $bottom_left_y,
419             ( $bottom_left_x + $pdf->x_padding + $scalar_width / 2 ), $bottom_left_y - $pdf->connector_height,
420             );
421              
422 0           $pdf->make_list(
423             $array,
424             $bottom_left_x,
425             $bottom_left_y - $pdf->connector_height - $pdf->black_bar_height,
426             $scalar_width + 2 * $pdf->x_padding
427             );
428              
429             }
430              
431             sub make_list {
432 0     0 0   my( $pdf, $array, $bottom_left_x, $bottom_left_y, $width ) = @_;
433              
434 0   0       my $scalar_width = $width || $pdf->get_list_width( $array );
435              
436 0           $pdf->make_collection_bar(
437             $bottom_left_x,
438             $bottom_left_y,
439             $scalar_width + $pdf->pointy_width + $pdf->x_padding,
440             );
441              
442 0           my $count = 0;
443 0           foreach my $value ( @$array ) {
444 0           $count++;
445              
446 0 0         my $box_value = ref $value ? '' : $value;
447 0           $pdf->make_text_box(
448             $bottom_left_x,
449             $bottom_left_y - $count*($pdf->font_height + 2 * $pdf->y_padding),
450             $scalar_width + $pdf->x_padding,
451             $pdf->box_height,
452             \ $box_value
453             );
454              
455 0 0         if( ref $value ) {
456 0           my $center = XYPoint->new(
457             $bottom_left_x + ( $scalar_width + $pdf->x_padding )/2 + $pdf->x_padding,
458             $bottom_left_y + $pdf->box_height / 2 - $count*$pdf->box_height,
459             );
460              
461 0           $pdf->make_reference_icon( $center );
462              
463 0           my $arrow_end = $pdf->make_reference_arrow(
464             $center,
465             $pdf->arrow_angle,
466             $pdf->arrow_length( $scalar_width + $pdf->x_padding ),
467             );
468              
469 0           my $ref_start = $arrow_end->clone;
470 0           $ref_start->add_y( - $pdf->black_bar_height / 2 );
471              
472 0 0         if( ref $value eq ref [] ) {
    0          
473 0           $pdf->make_list( $value, $ref_start->xy );
474             }
475             elsif( ref $value eq ref {} ) {
476 0           $pdf->make_anonymous_hash( $value, $ref_start->xy );
477             }
478             }
479             }
480              
481             }
482              
483             sub get_list_height {
484 0     0 0   my( $pdf, $array ) = @_;
485              
486             }
487              
488 0     0 0   sub minimum_scalar_width { 3 * $_[0]->font_width }
489             sub get_list_width {
490 0     0 0   my( $pdf, $array ) = @_;
491              
492 0           my $length = max( map { length $_ } grep { ! ref $_ } @$array );
  0            
  0            
493              
494 0           my $scalar_width = max( $pdf->minimum_scalar_width, $pdf->font_width * $length );
495             }
496              
497             sub make_hash {
498 0     0 0   my( $pdf, $name, $hash, $bottom_left_x, $bottom_left_y ) = @_;
499              
500 0           my( $key_length, $value_length ) = $pdf->get_hash_lengths( $hash );
501              
502 0           my $scalar_width = $pdf->font_width * ( $key_length + $value_length ) + 4 * $pdf->x_padding + $pdf->pointy_width;
503              
504 0           $pdf->make_pointy_box(
505             $bottom_left_x,
506             $bottom_left_y,
507             $scalar_width,
508             $pdf->box_height,
509             $name
510             );
511              
512 0           $pdf->lines(
513             ( $bottom_left_x + $pdf->x_padding + $scalar_width / 2 ), $bottom_left_y,
514             ( $bottom_left_x + $pdf->x_padding + $scalar_width / 2 ), $bottom_left_y - $pdf->connector_height,
515             );
516              
517 0           $pdf->make_anonymous_hash(
518             $hash,
519             $bottom_left_x,
520             $bottom_left_y - $pdf->connector_height - $pdf->black_bar_height,
521             );
522              
523             }
524              
525             sub get_hash_lengths {
526 0     0 0   my( $pdf, $hash ) = @_;
527              
528 0           my $key_length = max( map { length $_ } keys %$hash );
  0            
529 0           my $value_length = max( map { length $_ } grep { ! ref $_ } values %$hash );
  0            
  0            
530              
531 0           ( $key_length, $value_length );
532             }
533              
534             sub make_anonymous_hash {
535 0     0 0   my( $pdf, $hash, $bottom_left_x, $bottom_left_y ) = @_;
536              
537 0           my( $key_length, $value_length ) = $pdf->get_hash_lengths( $hash );
538              
539 0           my $scalar_width =
540             $pdf->font_width * ( $key_length + $value_length ) +
541             4 * $pdf->x_padding +
542             $pdf->pointy_width;
543              
544 0           $pdf->make_collection_bar(
545             $bottom_left_x,
546             $bottom_left_y,
547             $scalar_width + $pdf->pointy_width,
548             );
549              
550 0           my $count = 0;
551 0           foreach my $key ( keys %$hash ) {
552 0           $count++;
553              
554 0           my $key_box_width =
555             $pdf->font_width * $key_length + 1 * $pdf->x_padding + $pdf->pointy_width / 2;
556              
557             ; # share name box extra
558              
559 0           $pdf->make_pointy_box(
560             $bottom_left_x,
561             $bottom_left_y - $count*($pdf->font_height + 2 * $pdf->y_padding),
562             $key_box_width,
563             $pdf->box_height,
564             $key
565             );
566              
567 0           $pdf->make_text_box(
568             $bottom_left_x + $key_box_width + $pdf->pointy_width + 2 * $pdf->stroke_width,
569             $bottom_left_y - $count*($pdf->font_height + 2 * $pdf->y_padding),
570             $pdf->font_width * $value_length + $pdf->x_padding - 2.125*$pdf->stroke_width,
571             $pdf->box_height,
572             \ $hash->{$key}
573             );
574             }
575              
576             }
577              
578              
579             sub make_collection_bar {
580 0     0 0   my( $pdf, $bottom_left_x, $bottom_left_y, $width ) = @_;
581              
582 0           my $height = $pdf->black_bar_height;
583              
584 0           $pdf->filledRectangle(
585             $bottom_left_x - $pdf->stroke_width,
586             $bottom_left_y,
587             $width + 2 * $pdf->stroke_width,
588             $height,
589             );
590              
591 0           $pdf->strokePath;
592             }
593              
594             sub make_text_box {
595 0     0 0   my( $pdf, $bottom_left_x, $bottom_left_y, $width, $height, $text ) = @_;
596              
597 0           $pdf->rectangle(
598             $bottom_left_x,
599             $bottom_left_y,
600             $width + $height/2 * sqrt(2),
601             $height,
602             );
603              
604 0 0         $pdf->text(
605             $bottom_left_x + $pdf->x_padding,
606             $bottom_left_y + $pdf->y_padding,
607             ref $text ? $$text : $text
608             );
609              
610             }
611              
612             sub make_pointy_box {
613 0     0 0   my( $pdf, $bottom_left_x, $bottom_left_y, $width, $height, $text ) = @_;
614              
615 0           my $point_y = $bottom_left_y + $height / 2;
616 0           my $point_x = $bottom_left_x + $width + $height/2 * sqrt(2);
617              
618 0           my @vertices = (
619             $bottom_left_x, $bottom_left_y,
620             $bottom_left_x + $width, $bottom_left_y,
621             $point_x, $point_y,
622             $bottom_left_x + $width, $bottom_left_y + $height,
623             $bottom_left_x , $bottom_left_y + $height
624             );
625              
626 0           $pdf->polygon( @vertices );
627              
628 0           $pdf->text(
629             $bottom_left_x + $pdf->x_padding,
630             $bottom_left_y + $pdf->y_padding,
631             $text
632             );
633              
634             }
635              
636             =back
637              
638             =head1 TO DO
639              
640              
641             =head1 SEE ALSO
642              
643              
644             =head1 SOURCE AVAILABILITY
645              
646             This source is in Github:
647              
648             http://github.com/briandfoy/pegs-pdf/
649              
650             =head1 AUTHOR
651              
652             brian d foy, C<< >>
653              
654             =head1 COPYRIGHT AND LICENSE
655              
656             Copyright (c) 2009-2014, brian d foy, All Rights Reserved.
657              
658             You may redistribute this under the same terms as Perl itself.
659              
660             =cut
661              
662              
663 2     2   57 BEGIN {
664             package XYPoint;
665              
666 0     0     sub new { bless [ @_[1,2] ], $_[0] }
667 0     0     sub x { $_[0][0] }
668 0     0     sub y { $_[0][1] }
669              
670 0     0     sub add_x { $_[0][0] += $_[1] }
671 0     0     sub add_y { $_[0][1] += $_[1] }
672              
673 0     0     sub xy { ( $_[0]->x, $_[0]->y ) }
674              
675 0     0     sub clone { (ref $_[0])->new( $_[0]->xy ) }
676              
677 0     0     sub as_string { sprintf "(%d, %d)", $_[0]->x, $_[0]->y }
678             }
679              
680             1;