File Coverage

lib/SVG/Estimate/Path.pm
Criterion Covered Total %
statement 71 72 98.6
branch 21 32 65.6
condition 1 3 33.3
subroutine 13 13 100.0
pod 1 2 50.0
total 107 122 87.7


line stmt bran cond sub pod time code
1             package SVG::Estimate::Path;
2             $SVG::Estimate::Path::VERSION = '1.0107';
3 2     2   826 use Moo;
  2         3  
  2         12  
4 2     2   1316 use Image::SVG::Path qw/extract_path_info/;
  2         26500  
  2         185  
5 2     2   665 use SVG::Estimate::Path::Moveto;
  2         4  
  2         47  
6 2     2   550 use SVG::Estimate::Path::Lineto;
  2         24  
  2         48  
7 2     2   562 use SVG::Estimate::Path::CubicBezier;
  2         3  
  2         48  
8 2     2   622 use SVG::Estimate::Path::QuadraticBezier;
  2         4  
  2         66  
9 2     2   618 use SVG::Estimate::Path::HorizontalLineto;
  2         3  
  2         49  
10 2     2   550 use SVG::Estimate::Path::VerticalLineto;
  2         2  
  2         47  
11 2     2   598 use SVG::Estimate::Path::Arc;
  2         3  
  2         58  
12 2     2   9 use Clone qw/clone/;
  2         2  
  2         118  
13 2     2   7 use Ouch;
  2         2  
  2         884  
14              
15             extends 'SVG::Estimate::Shape';
16              
17             =head1 NAME
18              
19             SVG::Estimate::Path - Handles estimating arbitrary vectors.
20              
21             =head1 VERSION
22              
23             version 1.0107
24              
25             =head1 SYNOPSIS
26              
27             my $path = SVG::Estimate::Path->new(
28             transformer => $transform,
29             start_point => [45,13],
30             d => 'M150 0 L75 200 L225 200 Z',
31             );
32              
33             my $length = $path->length;
34              
35             =head1 INHERITANCE
36              
37             This class extends L.
38              
39             =head1 METHODS
40              
41             =head2 new()
42              
43             Constructor.
44              
45             =over
46              
47             =item d
48              
49             An SVG path string as described L.
50              
51             =back
52              
53             =cut
54              
55             has d => ( is => 'ro', required => 1, );
56             has commands => ( is => 'ro', );
57             has internal_travel_length => ( is => 'ro', required => 1, );
58             has summarize => ( is => 'ro', default => sub { 0 }, );
59              
60             sub BUILDARGS {
61 3     3 0 4877 my ($class, @args) = @_;
62             ##Upgrade to hashref
63 3 50       12 my $args = @args % 2 ? $args[0] : { @args };
64              
65 3         12 my @path_info = extract_path_info($args->{d}, { absolute => 1, no_shortcuts=> 1, });
66 3         3122 my @commands = ();
67              
68 3         3 my $first_flag = 1;
69 3         3 my $first;
70 3         18 my $cursor = clone $args->{start_point};
71 3         4 $args->{length} = 0;
72 3         3 foreach my $subpath (@path_info) {
73 13         16 $subpath->{transformer} = $args->{transformer};
74             ##On the first command, set the start point to the moveto destination, otherwise the travel length gets counted twice.
75 13         51 $subpath->{start_point} = clone $cursor;
76             my $command = $subpath->{type} eq 'moveto' ? SVG::Estimate::Path::Moveto->new($subpath)
77             : $subpath->{type} eq 'line-to' ? SVG::Estimate::Path::Lineto->new($subpath)
78             : $subpath->{type} eq 'cubic-bezier' ? SVG::Estimate::Path::CubicBezier->new($subpath)
79             : $subpath->{type} eq 'quadratic-bezier' ? SVG::Estimate::Path::QuadraticBezier->new($subpath)
80             : $subpath->{type} eq 'horizontal-line-to' ? SVG::Estimate::Path::HorizontalLineto->new($subpath)
81             : $subpath->{type} eq 'vertical-line-to' ? SVG::Estimate::Path::VerticalLineto->new($subpath)
82             : $subpath->{type} eq 'arc' ? SVG::Estimate::Path::Arc->new($subpath)
83             : $subpath->{type} eq 'closepath' ? '' #Placeholder so we don't fall through
84 13 50       156 : ouch('unknown_path', "Unknown subpath type ".$subpath->{type}) ; ##Something bad happened
    50          
    50          
    50          
    50          
    50          
    100          
    100          
85 13 100       68 if ($subpath->{type} eq 'closepath') {
86 2         13 $subpath->{point} = clone $first->point;
87 2         31 $command = SVG::Estimate::Path::Lineto->new($subpath);
88             }
89 13         91 $cursor = clone $command->end_point;
90 13 100       28 if ($first_flag) {
91             ##Save the first point in order to handle a closepath, if it exists
92 3         3 $first_flag = 0;
93 3         2 $first = $command; ##According to SVG, this will be a Moveto.
94 3         10 $args->{min_x} = $command->min_x;
95 3         7 $args->{max_x} = $command->max_x;
96 3         5 $args->{min_y} = $command->min_y;
97 3         10 $args->{max_y} = $command->max_y;
98 3         5 $args->{draw_start} = $command->end_point;
99             }
100 13         22 $args->{shape_length} += $command->shape_length;
101 13         30 $args->{internal_travel_length} += $command->travel_length;
102 13 50       33 $args->{min_x} = $command->min_x if $command->min_x < $args->{min_x};
103 13 100       30 $args->{max_x} = $command->max_x if $command->max_x > $args->{max_x};
104 13 50       22 $args->{min_y} = $command->min_y if $command->min_y < $args->{min_y};
105 13 100       28 $args->{max_y} = $command->max_y if $command->max_y > $args->{max_y};
106 13 0 33     19 if (exists $args->{summarize} && $args->{summarize}) {
107 0         0 $command->summarize_myself;
108             }
109 13         18 push @commands, $command;
110             }
111 3         7 $args->{draw_end} = $cursor;
112              
113 3         5 $args->{commands} = \@commands;
114 3         58 return $args;
115             }
116              
117             ##Return the internally calculated travel length, not the standard one use by SVG::Estimate::Shape
118             sub travel_length {
119 4     4 1 5 my $self = shift;
120 4         6 my $length = $self->internal_travel_length;
121 4         14 return $length;
122             }
123              
124             1;