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