X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FLaTeX-TikZ.git;a=blobdiff_plain;f=lib%2FLaTeX%2FTikZ%2FFormatter.pm;h=afdbd388c93d3aa8f36f74b3342c581be61dacc1;hp=899b4b036c7cd2ed70c210016820c3754b5c67ad;hb=1c53f7e28198adfb2905667acd5741f163832d7b;hpb=4a815ba07fc07f94629ca6364fae6204988e3dab diff --git a/lib/LaTeX/TikZ/Formatter.pm b/lib/LaTeX/TikZ/Formatter.pm index 899b4b0..afdbd38 100644 --- a/lib/LaTeX/TikZ/Formatter.pm +++ b/lib/LaTeX/TikZ/Formatter.pm @@ -9,11 +9,17 @@ LaTeX::TikZ::Formatter - LaTeX::TikZ formatter object. =head1 VERSION -Version 0.01 +Version 0.02 =cut -our $VERSION = '0.01'; +our $VERSION = '0.02'; + +=head1 DESCRIPTION + +A formatter object turns a L tree into the actual TikZ code, depending on some parameters such as the scale, the unit or the origin. + +=cut use Sub::Name (); @@ -26,46 +32,106 @@ use LaTeX::TikZ::Tools; use Any::Moose; use Any::Moose 'Util::TypeConstraints'; +=head1 ATTRIBUTES + +=head2 C + +The unit in which lengths are printed. +Valid units are C for centimeters and C for points. + +Defaults to C. + +=cut + has 'unit' => ( is => 'ro', - isa => enum([ qw/cm pt/ ]), + isa => enum([ qw ]), default => 'cm', ); +=head2 C + +The format used to print the numbers. + +Defaults to C<%s>. + +=cut + has 'format' => ( is => 'ro', isa => 'Str', default => '%s', ); +=head2 C + +The scale of the drawing. + +Defaults to C<1>. + +=cut + has 'scale' => ( is => 'rw', isa => 'Num', default => 1, ); +=head2 C + +The width of the drawing area. + +Defaults to C for none. + +=cut + has 'width' => ( is => 'rw', isa => 'Maybe[Num]', ); +=head2 C + +The height of the drawing area. + +Defaults to C for none. + +=cut + has 'height' => ( is => 'rw', isa => 'Maybe[Num]', ); +=head2 C + +A point coerced into a L object that represents the logical origin of the printed area. +If L and L are set, the canvas will be equivalent to a rectangle whose lower left corner at C<-$origin> and of given width and length. + +Defaults to C<(0, 0)>, meaning that the drawing area goes from C<(0, 0)> to C<($width, $height)>. + +=cut + has 'origin' => ( is => 'rw', isa => 'LaTeX::TikZ::Point::Autocoerce', coerce => 1, ); +=head1 METHODS + +=head2 C + +An unique identifier of the formatter object. + +=cut + sub id { my $tikz = shift; my $origin = $tikz->origin; if (defined $origin) { - my ($x, $y) = map $origin->$_, qw/x y/; + my ($x, $y) = map $origin->$_, qw; $origin = "($x;$y)"; } else { $origin = "(0;0)"; @@ -73,9 +139,58 @@ sub id { join $;, map { defined() ? "$_" : '(undef)'; - } map($tikz->$_, qw/unit format scale width height/), $origin; + } map($tikz->$_, qw), $origin; } +=head2 C + +Processes all the L objects given in C<@sets> to produce the actual TikZ code to insert in the LaTeX file. +First, all the mods applied to the sets and their subsets are collected, and a declaration is emitted if needed for each of them by calling L. +Then, the image code is generated for each set. + +This method returns a list of array references : + +=over 4 + +=item * + +The first one contains the header lines to include between the C<\documentclass> and the C<\begin{document}>. + +=item * + +The second one contains the mod declaration lines to put inside the document, between C<\begin{document}> and C<\end{document}>. + +=item * + +Finally, there's one array reference for each given TikZ set, which contain the lines for the actual TikZ pictures. + +=back + +The lines returned by L don't end with a line feed. + + my ($header, $declarations, $set1_body, $set2_body) = $formatter->render($set1, $set2); + + open my $tex, '>', 'test.tex' or die "open('>test.tex'): $!"; + + print $tex "$_\n" for ( + "\\documentclass[12pt]{article}", + @$header, + "\\begin{document}", + "\\pagestyle{empty}", + @$declarations, + "First set :" + "\\begin{center}", + @$set1_body, + "\\end{center}", + "Second set :" + "\\begin{center}", + @$set2_body, + "\\end{center}", + "\\end{document}", + ); + +=cut + my $find_mods = do { our %seen; @@ -97,11 +212,9 @@ my $find_mods = do { } } - my @subsets = $set->isa('LaTeX::TikZ::Set::Sequence') + my @subsets = $set->does('LaTeX::TikZ::Set::Container') ? $set->kids - : $set->isa('LaTeX::TikZ::Set::Path') - ? $set->ops - : (); + : (); $find_mods_rec->($_, $layers, $others) for @subsets; }); @@ -117,11 +230,7 @@ my $find_mods = do { my $translate; sub render { - my $tikz = shift; - - my $seq = LaTeX::TikZ::Set::Sequence->new( - kids => \@_, - ); + my ($tikz, @sets) = @_; unless ($translate) { require LaTeX::TikZ::Functor; @@ -144,9 +253,12 @@ sub render { } my $origin = $tikz->origin; - $seq = $seq->$translate($origin) if defined $origin; + if (defined $origin) { + @sets = map $_->$translate($origin), @sets; + } my (@layers, @other_mods); + my $seq = LaTeX::TikZ::Set::Sequence->new(kids => \@sets); $find_mods->($seq, \@layers, \@other_mods); my $w = $tikz->width; @@ -154,11 +266,13 @@ sub render { my $canvas = ''; if (defined $w and defined $h) { require LaTeX::TikZ::Set::Rectangle; - $seq->clip(LaTeX::TikZ::Set::Rectangle->new( - from => 0, - width => $w, - height => $h, - )); + for (@sets) { + $_->clip(LaTeX::TikZ::Set::Rectangle->new( + from => 0, + width => $w, + height => $h, + )); + } $_ = $tikz->len($_) for $w, $h; $canvas = ",papersize={$w,$h},body={$w,$h}"; } @@ -173,15 +287,21 @@ sub render { push @decls, LaTeX::TikZ::Mod::Layer->declare(@layers) if @layers; push @decls, $_->declare($tikz) for @other_mods; - my @content = ( + my @bodies = map [ "\\begin{tikzpicture}", - @{ $seq->draw($tikz) }, + @{ $_->draw($tikz) }, "\\end{tikzpicture}", - ); + ], @sets; - return \@header, \@decls, \@content; + return \@header, \@decls, @bodies; } +=head2 C + +Format the given length according to the formatter options. + +=cut + sub len { my ($tikz, $len) = @_; @@ -190,6 +310,12 @@ sub len { sprintf $tikz->format . $tikz->unit, $len * $tikz->scale; } +=head2 C + +Format the given angle (in radians) according to the formatter options. + +=cut + sub angle { my ($tikz, $a) = @_; @@ -200,14 +326,26 @@ sub angle { sprintf $tikz->format, POSIX::ceil($a); } +=head2 C