Skip to content

Instantly share code, notes, and snippets.

@hyoiutu
Created December 15, 2019 13:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyoiutu/ddf60b156e9590c0909cd7f32f2047dc to your computer and use it in GitHub Desktop.
Save hyoiutu/ddf60b156e9590c0909cd7f32f2047dc to your computer and use it in GitHub Desktop.
Perl script for convert to SVG to TikZ
use strict;
use warnings;
use utf8;
sub read_SVG_info {
my $file_name = shift;
my $svg_lines = load_SVG_file($file_name);
my ($max_x, $max_y) = read_draw_area($svg_lines);
my @images_path_list = read_path_list($svg_lines);
return +{
max_x => $max_x,
max_y => $max_y,
images_path_list => \@images_path_list
};
}
sub read_draw_area {
my $svg_lines = shift;
my $viewBox = shift(
[ grep {
$_ =~ /viewBox="0 0 [0-9]* [0-9]*"/
} @$svg_lines ]
);
$viewBox =~ /viewBox="0 0 ([0-9]*) ([0-9]*)"/;
return ($1, $2);
}
sub read_path_list {
my $svg_lines = shift;
return grep {
$_ =~ /<path class=/
} @$svg_lines;
}
sub load_SVG_file {
my $file_name = shift;
die 'Can\'t open file !' unless(
open(
my $svg, '<', $file_name
)
);
my $svg_code = do {local $/; <$svg>};
close $svg;
return [ split(/\n/, $svg_code) ];
}
sub save_TeX_file {
my ($file_name, $save_texts) = @_;
die 'Can\'t open file !' unless(
open(
my $tex, '>', $file_name
)
);
print $tex $save_texts;
die 'Can\'t close file' unless(
close $tex
)
}
sub get_svg_opes {
my $svg_info = shift;
$svg_info =~ /<path class=.*d="(.*)"\/>/;
my $coodinates_string = $1;
return [ split(/(?=[a-zA-Z])/, $coodinates_string) ]; # 肯定的先読み
}
sub fetch_abs_point {
my ($ope, $scale) = @_;
$ope =~ /M(-?[0-9.]*)[ ,](-?[0-9.]*)/;
return [$1*$scale, $2*$scale];
}
sub fetch_rel_point {
my ($ope, $current_point, $scale) = @_;
$ope =~ /m(-?[0-9.]*)[ ,](-?[0-9.]*)/;
return [($1*$scale + $current_point->[0]), ($2*$scale + $current_point->[1])];
}
sub fetch_draw_line_ope {
my ($ope, $current_point, $scale) = @_;
$ope =~ /l(-?[0-9.]*)[ ,](-?[0-9.]*)/;
my $tikz_ope = sprintf(
"\\draw (%f, %f) -- (%f, %f);\n",
$current_point->[0], -$current_point->[1],
$1*$scale + $current_point->[0], -($2*$scale + $current_point->[1])
);
return +{
new_point => [($1*$scale + $current_point->[0]), ($2*$scale + $current_point->[1])],
tikz_ope => $tikz_ope
};
}
sub fetch_draw_cubic_bezier_curve_ope {
my ($ope, $current_point, $scale) = @_;
my $tikz_ope = '';
while(
$ope =~ /(-?[0-9.]*),(-?[0-9.]*) (-?[0-9.]*),(-?[0-9.]*) (-?[0-9.]*),(-?[0-9.]*)/g
) {
$tikz_ope .= sprintf(
"\\draw (%f, %f) .. controls (%f, %f) and (%f, %f) .. (%f, %f);\n",
$current_point->[0], -$current_point->[1],
$1*$scale + $current_point->[0],
-($2*$scale + $current_point->[1]),
$3*$scale + $current_point->[0],
-($4*$scale + $current_point->[1]),
$5*$scale + $current_point->[0],
-($6*$scale + $current_point->[1])
);
$current_point = [($5*$scale + $current_point->[0]), ($6*$scale + $current_point->[1])];
}
return +{
new_point => $current_point,
tikz_ope => $tikz_ope
};
}
sub fetch_close_path_ope {
my ($current_point, $start_point) = @_;
my $tikz_ope = sprintf(
"\\draw (%f, %f) -- (%f, %f);\n",
$current_point->[0],
-$current_point->[1],
$start_point->[0],
-$start_point->[1]
);
return +{
new_point => $start_point,
tikz_ope => $tikz_ope
};
}
sub convert_tikz_from_svg_opes {
my ($svg_opes, $scale) = @_;
my $start_point = [0, 0];
my $current_point = [0, 0];
my $output_code = '';
for my $cursor (@$svg_opes) {
if ($cursor =~ /M/) {
$current_point = fetch_abs_point($cursor, $scale);
$start_point = $current_point;
}
elsif ($cursor =~ /m/) {
$current_point = fetch_rel_point($cursor, $current_point, $scale);
$start_point = $current_point;
}
elsif ($cursor =~ /l/) {
my $converted = fetch_draw_line_ope($cursor, $current_point, $scale);
$current_point = $converted->{new_point};
$output_code .= $converted->{tikz_ope};
}
elsif ($cursor =~ /c/) {
my $converted = fetch_draw_cubic_bezier_curve_ope($cursor, $current_point, $scale);
$current_point = $converted->{new_point};
$output_code .= $converted->{tikz_ope};
}
elsif($cursor =~ /z/) {
my $converted = fetch_close_path_ope($current_point, $start_point);
$current_point = $converted->{new_point};
$output_code .= $converted->{tikz_ope};
}
}
return $output_code;
}
sub convert_tikz_from_svg {
my ($svg_file_name, $scale) = @_;
my $result = read_SVG_info($svg_file_name);
my @svg_opes = map { get_svg_opes($_) } @{$result->{images_path_list}};
return join('', map { convert_tikz_from_svg_opes($_, $scale) } @svg_opes);
}
my $result = convert_tikz_from_svg('japon04.svg', 0.01);
save_TeX_file('island.tex', $result);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment