]> git.vpit.fr Git - perl/modules/LaTeX-TikZ.git/blob - lib/LaTeX/TikZ/Formatter.pm
Make some accessors writable for the formatter object
[perl/modules/LaTeX-TikZ.git] / lib / LaTeX / TikZ / Formatter.pm
1 package LaTeX::TikZ::Formatter;
2
3 use strict;
4 use warnings;
5
6 =head1 NAME
7
8 LaTeX::TikZ::Formatter - LaTeX::TikZ formatter object.
9
10 =head1 VERSION
11
12 Version 0.01
13
14 =cut
15
16 our $VERSION = '0.01';
17
18 use Sub::Name ();
19
20 use LaTeX::TikZ::Point;
21
22 use LaTeX::TikZ::Interface;
23
24 use LaTeX::TikZ::Tools;
25
26 use Any::Moose;
27 use Any::Moose 'Util::TypeConstraints';
28
29 has 'unit' => (
30  is      => 'ro',
31  isa     => enum([ qw/cm pt/ ]),
32  default => 'cm',
33 );
34
35 has 'format' => (
36  is      => 'ro',
37  isa     => 'Str',
38  default => '%s',
39 );
40
41 has 'scale' => (
42  is      => 'rw',
43  isa     => 'Num',
44  default => 1,
45 );
46
47 has 'width' => (
48  is  => 'rw',
49  isa => 'Maybe[Num]',
50 );
51
52 has 'height' => (
53  is  => 'rw',
54  isa => 'Maybe[Num]',
55 );
56
57 has 'origin' => (
58  is     => 'rw',
59  isa    => 'Maybe[LaTeX::TikZ::Point::Autocoerce]',
60  coerce => 1,
61 );
62
63 sub id {
64  my $tikz = shift;
65
66  join $;, map {
67   my $val = $tikz->$_;
68   defined($val) ? "$val" : '(undef)';
69  } qw/unit format scale width height origin/;
70 }
71
72 my $find_mods = do {
73  our %seen;
74
75  my $find_mods_rec;
76  $find_mods_rec = do {
77   no warnings 'recursion';
78
79   Sub::Name::subname('find_mods_rec' => sub {
80    my ($set, $layers, $others) = @_;
81
82    for ($set->mods) {
83     my $tag = $_->tag;
84     next if $seen{$tag}++;
85
86     if ($_->isa('LaTeX::TikZ::Mod::Layer')) {
87      push @$layers, $_;
88     } else {
89      push @$others, $_;
90     }
91    }
92
93    my @subsets = $set->isa('LaTeX::TikZ::Set::Sequence')
94                  ? $set->kids
95                  : $set->isa('LaTeX::TikZ::Set::Path')
96                    ? $set->ops
97                    : ();
98
99    $find_mods_rec->($_, $layers, $others) for @subsets;
100   });
101  };
102
103  Sub::Name::subname('find_mods' => sub {
104   local %seen = ();
105
106   $find_mods_rec->(@_);
107  });
108 };
109
110 sub render {
111  my $tikz = shift;
112
113  my $seq = LaTeX::TikZ::Set::Sequence->new(
114   kids => \@_,
115  );
116
117  my (@layers, @other_mods);
118  $find_mods->($seq, \@layers, \@other_mods);
119
120  my $w = $tikz->width;
121  my $h = $tikz->height;
122  my $canvas = '';
123  if (defined $w and defined $h) {
124   require LaTeX::TikZ::Set::Rectangle;
125   $seq->clip(LaTeX::TikZ::Set::Rectangle->new(
126    from   => 0,
127    width  => $w,
128    height => $h,
129   ));
130   $_ = $tikz->len($_) for $w, $h;
131   $canvas = ",papersize={$w,$h},body={$w,$h}";
132  }
133
134  my @header = (
135   "\\usepackage[pdftex,hcentering,vcentering$canvas]{geometry}",
136   "\\usepackage{tikz}",
137   "\\usetikzlibrary{patterns}",
138  );
139
140  my @decls;
141  push @decls, LaTeX::TikZ::Mod::Layer->declare(@layers) if  @layers;
142  push @decls, $_->declare($tikz)                        for @other_mods;
143
144  my @content = (
145   "\\begin{tikzpicture}",
146   @{ $seq->draw($tikz) },
147   "\\end{tikzpicture}",
148  );
149
150  return \@header, \@decls, \@content;
151 }
152
153 sub len {
154  my ($tikz, $len) = @_;
155
156  $len = 0 if LaTeX::TikZ::Tools::numeq($len, 0);
157
158  sprintf $tikz->format . $tikz->unit, $len * $tikz->scale;
159 }
160
161 sub angle {
162  my ($tikz, $a) = @_;
163
164  $a = ($a * 180) / CORE::atan2(0, -1);
165  $a += 360 if LaTeX::TikZ::Tools::numcmp($a, 0) < 0;
166
167  require POSIX;
168  sprintf $tikz->format, POSIX::ceil($a);
169 }
170
171 sub label {
172  my ($tikz, $name, $pos) = @_;
173
174  my $scale = sprintf '%0.2f', $tikz->scale / 5;
175
176  "node[scale=$scale,$pos] {\$$name\$}";
177 }
178
179 sub thickness {
180  my ($tikz, $width) = @_;
181
182  # width=1 is 0.4 points for a scale of 2.5
183  0.8 * $width * ($tikz->scale / 5);
184 }
185
186 LaTeX::TikZ::Interface->register(
187  formatter => sub {
188   shift;
189
190   __PACKAGE__->new(@_);
191  },
192 );
193
194 __PACKAGE__->meta->make_immutable;
195
196 =head1 AUTHOR
197
198 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
199
200 You can contact me by mail or on C<irc.perl.org> (vincent).
201
202 =head1 BUGS
203
204 Please report any bugs or feature requests to C<bug-latex-tikz at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=LaTeX-TikZ>.
205 I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
206
207 =head1 SUPPORT
208
209 You can find documentation for this module with the perldoc command.
210
211     perldoc LaTeX::TikZ
212
213 =head1 COPYRIGHT & LICENSE
214
215 Copyright 2010 Vincent Pit, all rights reserved.
216
217 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
218
219 =cut
220
221 1; # End of LaTeX::TikZ::Formatter