File Coverage

blib/lib/PeGS/PDF.pm
Criterion Covered Total %
statement 21 220 9.5
branch 0 18 0.0
condition 0 3 0.0
subroutine 7 49 14.2
pod 0 33 0.0
total 28 323 8.6


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