Skip to content

Commit

Permalink
Fix bug in parsing sequences of numbers.
Browse files Browse the repository at this point in the history
  • Loading branch information
benkasminbullock committed Dec 15, 2016
1 parent 4d10bc6 commit 480776a
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 35 deletions.
4 changes: 4 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Revision history for perl module Image::SVG::Path

0.30 2016-12-15

* Bug in parsing sequence of numbers like 2.4.1.2 fixed.

0.29 2016-10-15

* Exports $smooth_curveto regex
Expand Down
70 changes: 35 additions & 35 deletions lib/Image/SVG/Path.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ our @SVG_REGEX = qw/
our @FUNCTIONS = qw/extract_path_info reverse_path create_path_string/;
our @EXPORT_OK = (@FUNCTIONS, @SVG_REGEX);
our %EXPORT_TAGS = (all => \@FUNCTIONS, regex => \@SVG_REGEX);
our $VERSION = '0.29';
our $VERSION = '0.30';

use Carp;

Expand Down Expand Up @@ -418,21 +418,21 @@ sub extract_path_info
push @curves, [$command, $values, $original];
}
for my $curve_data (@curves) {
my ($curve_type, $curve) = @$curve_data;
$curve =~ s/^,//;
my ($command, $values) = @$curve_data;
# print "$curve\n";
my @numbers = split $split_re, $curve;
my @numbers = ($values =~ /($number)/g);
# print "@numbers\n";
if ($verbose) {
print "$me: Extracted numbers: @numbers\n";
printf "$me: Extracted %d numbers: %s\n", scalar (@numbers),
join (" ! ", @numbers);
}
if (uc $curve_type eq 'C') {
if (uc $command eq 'C') {
my $expect_numbers = 6;
if (@numbers % 6 != 0) {
croak "$me: Wrong number of values for a C curve " .
scalar @numbers . " in '$path'";
}
my $position = position_type ($curve_type);
my $position = position_type ($command);
for (my $i = 0; $i < @numbers / 6; $i++) {
my $offset = 6 * $i;
my @control1 = @numbers[$offset + 0, $offset + 1];
Expand All @@ -447,17 +447,17 @@ sub extract_path_info
control1 => \@control1,
control2 => \@control2,
end => \@end,
svg_key => $curve_type,
svg_key => $command,
};
}
}
elsif (uc $curve_type eq 'S') {
elsif (uc $command eq 'S') {
my $expect_numbers = 4;
if (@numbers % $expect_numbers != 0) {
croak "$me: Wrong number of values for an S curve " .
scalar @numbers . " in '$path'";
}
my $position = position_type ($curve_type);
my $position = position_type ($command);
for (my $i = 0; $i < @numbers / $expect_numbers; $i++) {
my $offset = $expect_numbers * $i;
my @control2 = @numbers[$offset + 0, $offset + 1];
Expand All @@ -468,41 +468,41 @@ sub extract_path_info
position => $position,
control2 => \@control2,
end => \@end,
svg_key => $curve_type,
svg_key => $command,
};
}
}
elsif (uc $curve_type eq 'L') {
elsif (uc $command eq 'L') {
my $expect_numbers = 2;
# Maintain this check here, even though it's duplicated
# inside build_lineto, because it's specific to the lineto
if (@numbers % $expect_numbers != 0) {
croak "Odd number of values for an L command " .
scalar (@numbers) . " in '$path'";
}
my $position = position_type ($curve_type);
my $position = position_type ($command);
push @path_info, build_lineto ($position, @numbers);
}
elsif (uc $curve_type eq 'Z') {
elsif (uc $command eq 'Z') {
if (@numbers > 0) {
croak "Wrong number of values for a Z command " .
scalar @numbers . " in '$path'";
}
my $position = position_type ($curve_type);
my $position = position_type ($command);
push @path_info, {
type => 'closepath',
name => 'closepath',
position => $position,
svg_key => $curve_type,
svg_key => $command,
}
}
elsif (uc $curve_type eq 'Q') {
elsif (uc $command eq 'Q') {
my $expect_numbers = 4;
if (@numbers % $expect_numbers != 0) {
croak "Wrong number of values for a Q command " .
scalar @numbers . " in '$path'";
}
my $position = position_type ($curve_type);
my $position = position_type ($command);
for (my $i = 0; $i < @numbers / $expect_numbers; $i++) {
my $o = $expect_numbers * $i;
push @path_info, {
Expand All @@ -511,72 +511,72 @@ sub extract_path_info
position => $position,
control => [@numbers[$o, $o + 1]],
end => [@numbers[$o + 2, $o + 3]],
svg_key => $curve_type,
svg_key => $command,
}
}
}
elsif (uc $curve_type eq 'T') {
elsif (uc $command eq 'T') {
my $expect_numbers = 2;
if (@numbers % $expect_numbers != 0) {
croak "$me: Wrong number of values for an T command " .
scalar @numbers . " in '$path'";
}
my $position = position_type ($curve_type);
my $position = position_type ($command);
for (my $i = 0; $i < @numbers / $expect_numbers; $i++) {
my $o = $expect_numbers * $i;
push @path_info, {
type => 'shortcut-quadratic-bezier',
name => 'Shorthand/smooth quadratic Bézier curveto',
position => $position,
end => [@numbers[$o, $o + 1]],
svg_key => $curve_type,
svg_key => $command,
}
}
}
elsif (uc $curve_type eq 'H') {
my $position = position_type ($curve_type);
elsif (uc $command eq 'H') {
my $position = position_type ($command);
for (my $i = 0; $i < @numbers; $i++) {
push @path_info, {
type => 'horizontal-line-to',
name => 'horizontal lineto',
position => $position,
x => $numbers[$i],
svg_key => $curve_type,
svg_key => $command,
};
}
}
elsif (uc $curve_type eq 'V') {
my $position = position_type ($curve_type);
elsif (uc $command eq 'V') {
my $position = position_type ($command);
for (my $i = 0; $i < @numbers; $i++) {
push @path_info, {
type => 'vertical-line-to',
name => 'vertical lineto',
position => $position,
y => $numbers[$i],
svg_key => $curve_type,
svg_key => $command,
};
}
}
elsif (uc $curve_type eq 'A') {
my $position = position_type ($curve_type);
elsif (uc $command eq 'A') {
my $position = position_type ($command);
my $expect_numbers = 7;
if (@numbers % $expect_numbers != 0) {
croak "$me: Need 7 parameters for arc";
}
for (my $i = 0; $i < @numbers / $expect_numbers; $i++) {
my $o = $expect_numbers * $i;
my %arc;
$arc{svg_key} = $curve_type;
$arc{svg_key} = $command;
$arc{type} = 'arc';
$arc{name} = 'elliptical arc';
$arc{position} = $position;
@arc{@arc_fields} = @numbers[$o .. $o + 6];
push @path_info, \%arc;
}
}
elsif (uc $curve_type eq 'M') {
elsif (uc $command eq 'M') {
my $expect_numbers = 2;
my $position = position_type ($curve_type);
my $position = position_type ($command);
if (@numbers < $expect_numbers) {
croak "$me: Need at least $expect_numbers numbers for move to";
}
Expand All @@ -589,7 +589,7 @@ sub extract_path_info
name => 'moveto',
position => $position,
point => [@numbers[0,1]],
svg_key => $curve_type,
svg_key => $command,
};
# M can be followed by implicit line-to commands, so
# consume these.
Expand All @@ -599,7 +599,7 @@ sub extract_path_info
}
}
else {
croak "I don't know what to do with a curve type '$curve_type'";
croak "I don't know what to do with a curve type '$command'";
}
}

Expand Down
13 changes: 13 additions & 0 deletions t/Image-SVG-Path.t
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,19 @@ like ($path, qr/A\s+23\.0+,20\.0+,0\.0+,0\.0+,1\.0+,147\.0+,172\.0+/,
"arc in path reproduced OK");
#};

# The numbers in the following path weren't being parsed correctly due
# to a bug where the correct number regex was not being used to split
# the string of numbers into numbers.

#<svg width="32" height="32" viewbox="-2 -2 32 32" class="inline-share-twitter__svg inline-icon__svg">
#<path d="M21.3 10.5v.5c0 4.7-3.5 10.1-9.9 10.1-2 0-3.8-.6-5.3-1.6.3 0 .6.1.8.1 1.6 0 3.1-.6 4.3-1.5-1.5 0-2.8-1-3.3-2.4.2 0 .4.1.7.1l.9-.1c-1.6-.3-2.8-1.8-2.8-3.5.5.3 1 .4 1.6.4-.9-.6-1.6-1.7-1.6-2.9 0-.6.2-1.3.5-1.8 1.7 2.1 4.3 3.6 7.2 3.7-.1-.3-.1-.5-.1-.8 0-2 1.6-3.5 3.5-3.5 1 0 1.9.4 2.5 1.1.8-.1 1.5-.4 2.2-.8-.3.8-.8 1.5-1.5 1.9.7-.1 1.4-.3 2-.5-.4.4-1 1-1.7 1.5z"/>
#</svg>

my $path = 'M21.3 10.5v.5c0 4.7-3.5 10.1-9.9 10.1-2 0-3.8-.6-5.3-1.6.3 0 .6.1.8.1 1.6 0 3.1-.6 4.3-1.5-1.5 0-2.8-1-3.3-2.4.2 0 .4.1.7.1l.9-.1c-1.6-.3-2.8-1.8-2.8-3.5.5.3 1 .4 1.6.4-.9-.6-1.6-1.7-1.6-2.9 0-.6.2-1.3.5-1.8 1.7 2.1 4.3 3.6 7.2 3.7-.1-.3-.1-.5-.1-.8 0-2 1.6-3.5 3.5-3.5 1 0 1.9.4 2.5 1.1.8-.1 1.5-.4 2.2-.8-.3.8-.8 1.5-1.5 1.9.7-.1 1.4-.3 2-.5-.4.4-1 1-1.7 1.5z';

my @info = extract_path_info ($path);#, {verbose => 1});
ok (@info);


done_testing ();
exit;

0 comments on commit 480776a

Please sign in to comment.