Created
December 15, 2019 13:13
-
-
Save hyoiutu/ddf60b156e9590c0909cd7f32f2047dc to your computer and use it in GitHub Desktop.
Perl script for convert to SVG to TikZ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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