Beamer用に複数のEPSを生成する
概要
LaTeXのbeamerでプレゼンテーションを作る時,複数のEPSファイルを使ってアニメーションをしたいが,複数のEPSファイルを作成するのが面倒だ.そこで,Inkscapeを使って作成したSVGから複数のEPSファイルを作る方法を考えてみた.
multisvg
#!/usr/bin/perl use strict; use Getopt::Std; use XML::Simple; use Data::Dumper; $Data::Dumper::Indent = 1; use vars qw($opt_h $opt_e $opt_d); &getopts("hed"); my $inkscape = "inkscape"; if ($opt_h) { print "Usage: $0 file.svg file.txt\n"; print "\tgenerates files file_000.svg, file_001.svg, ...\n"; print " -e : generates EPS files instead of SVG by using inkscape\n"; print " -d : dump file.svg in perl syntax\n"; exit(1); } my $svg_file = shift(@ARGV); my $anim_file = shift(@ARGV); my $eps = $opt_e; my $svg = XMLin($svg_file, KeepRoot => 1, KeyAttr => {}); my $output0 = $svg_file; $output0 =~ s/\.svg$//; my $frame = 0; my ($tag0, $attr0); open(ANIM, "<", $anim_file) || die "$0: $anim_file $!"; while (<ANIM>) { chomp; next if /^\s*$/ || /^\#/; if (/^save$/i) { my $output = sprintf("%s_%03d", $output0, $frame); if ($opt_d) { print "##### $output\n"; print Dumper($svg); } &save($svg, "$output.svg"); if ($eps) { system("$inkscape -z -E '$output.eps' '$output.svg'"); unlink "$output.svg"; } $frame++; } else { my @rule = split(/\t/); $rule[0] ||= $tag0; $rule[1] ||= $attr0; &replace("", $svg, \@rule); } } close(ANIM); exit 0; sub replace { my ($tag, $data, $rule) = @_; if (ref($data) eq "ARRAY") { foreach my $d (@{$data}) { &replace($tag, $d, $rule); } } elsif (ref($data) eq "HASH") { if ($tag && $tag =~ /^$rule->[0]$/ && $data->{id} =~ /^$rule->[1]$/) { foreach my $x (keys %{$data}) { if ($x =~ /^$rule->[2]$/) { my $pattern = $rule->[3]; my $replace = $rule->[4]; my $opt = $rule->[5]; $_ = $data->{$x}; if ($opt eq "e") { s/\b$pattern\b/eval $replace/e; } else { s/$pattern/$replace/; } $data->{$x} = $_; } } } foreach my $x (keys %{$data}) { &replace($x, $data->{$x}, $rule); } } } sub save { my ($svg, $svg_output) = @_; my $fh; open($fh, ">:encoding(UTF-8)", $svg_output) || die; XMLout($svg, OutputFile => $fh, KeepRoot => 1, NoIndent => 1, KeyAttr => {}, XMLDecl => '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'); close($fh); }
使い方
まずはInkscapeで図を描く
- Inkscapeで図を描く
- IDを設定
- 図形を右クリックして「オブジェクトのプロパティ」を選択し,わかりやすい「id」を設定する.
- たとえば,テキストなら「text:a」,矩形なら「rect:a」など
- 図を保存する
- 以下は,サンプルの図 (multisvg_sample.svg)
- 以下は,multisvg_sample.svg の内容
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with Inkscape (http://www.inkscape.org/) --> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="579.16846" height="263.70392" id="svg2" sodipodi:version="0.32" inkscape:version="0.46" version="1.0" sodipodi:docname="multisvg_sample.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape"> <defs id="defs4"> <marker inkscape:stockid="Arrow1Lend" orient="auto" refY="0" refX="0" id="Arrow1Lend" style="overflow:visible"> <path id="path3167" d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z" style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" transform="matrix(-0.8,0,0,-0.8,-10,0)" /> </marker> <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" id="perspective10" /> </defs> <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" gridtolerance="10000" guidetolerance="10" objecttolerance="10" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="0.90976941" inkscape:cx="288.79217" inkscape:cy="122.46446" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="741" inkscape:window-height="715" inkscape:window-x="-4" inkscape:window-y="25" /> <metadata id="metadata7"> <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> </cc:Work> </rdf:RDF> </metadata> <g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(-211.6657,-79.168628)"> <rect style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="rect:a" width="169.75522" height="145.33836" x="247.83945" y="123.2529" rx="16.809414" ry="19.882915" inkscape:label="#rect2383" /> <rect style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="rect:b" width="138.36212" height="174.40604" x="605.90924" y="115.80508" rx="16.809414" ry="19.882915" inkscape:label="#rect2385" /> <text xml:space="preserve" style="font-size:32px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" x="329.22891" y="198.82886" id="text:a" inkscape:label="#text2389"><tspan sodipodi:role="line" id="tspan2391" x="329.22891" y="198.82886">a</tspan></text> <text xml:space="preserve" style="font-size:32px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" x="676.29956" y="200.61957" id="text:b" inkscape:label="#text2389"><tspan sodipodi:role="line" id="tspan2385" x="676.29956" y="200.61957">b</tspan></text> <path style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Lend);stroke-opacity:1" d="M 415.08637,189.48328 L 605.93041,203.93671" id="path:a:b" inkscape:label="#path2389" /> </g> </svg>
アニメーション設定用のファイルを作成する
- SVGファイルの中身を眺めながら,以下のようなファイル(multisvg_sample.txt)を作成する.
## multisvg のサンプル # すべての text を白に text .* style fill:#?\w+ fill:#ffffff # すべての path を白に path .* style stroke:#?\w+ stroke:#ffffff # path:a:b の Arrow1Lend (pathの最後の矢印)を削除 path path:a:b style marker-end:url\(#Arrow1Lend\) # svgを保存 save # rect:a を赤に rect rect:a style stroke:#?\w+ stroke:#ff0000 # text:a を赤で表示 text text:a style fill:#?\w+ fill:#ff0000 # svgを保存 save # rect:a を黒に rect rect:a style stroke:#?\w+ stroke:#000000 # text:a を黒に text text:a style fill:#?\w+ fill:#000000 # path:a:b を黒に path path:a:b style stroke:#?\w+ stroke:#000000 # path:a:b の Arrow1Lend (pathの最後の矢印)を表示 path path:a:b style ;; ;marker-end:url(#Arrow1Lend); # rect:b を赤の太線に rect rect:b style stroke:#?\w+ stroke:#ff0000 rect rect:b style stroke-width:\d+ stroke-width:3 # text:b を赤の太文字に text text:b style fill:#?\w+ fill:#ff0000 text text:b style font-weight:\w+ font-weight:bold # svgを保存 save