sub mods_unique {
my ($set) = @_;
- my (@mods, $has_layer);
+ my (@mods, $last_layer);
MOD:
for my $mod ($set->mods) {
- $has_layer = 1 if $ltml_tc->check($mod);
+ my $is_layer = $ltml_tc->check($mod);
+ $last_layer = $mod if $is_layer;
my $tag = $mod->tag;
my $old = $mods{$tag} || [];
for (@$old) {
next MOD if $_->[0]->cover($mod);
}
- push @{$mods{$tag}}, [ $mod, $last_mod++ ];
+ push @{$mods{$tag}}, [ $mod, $last_mod++, $is_layer ];
push @mods, $mod;
}
- if ($has_layer) {
+ if ($last_layer) {
# Clips and mods don't propagate through layers. Hence if a layer is set,
# force their reuse.
- @mods = map $_->[0], sort { $a->[1] <=> $b->[1] } map @$_, values %mods;
+ @mods = $last_layer;
+ push @mods, map $_->[0],
+ sort { $a->[1] <=> $b->[1] }
+ grep !$_->[2],
+ map @$_,
+ values %mods;
}
return @mods;
--- /dev/null
+#!perl -T
+
+use strict;
+use warnings;
+
+use Test::More tests => 9 + 3 * 6;
+
+use LaTeX::TikZ;
+
+my $tikz = Tikz->formatter(
+ format => '%d',
+);
+
+sub check {
+ my ($set, $desc, $exp, $layers) = @_;
+
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+ my ($head, $decl, $body) = eval {
+ $tikz->render(ref $set eq 'ARRAY' ? @$set : $set);
+ };
+ is $@, '', "$desc: no error";
+
+ unless (ref $exp eq 'ARRAY') {
+ $exp = [ split /\n/, $exp ];
+ }
+ unshift @$exp, '\begin{tikzpicture}';
+ push @$exp, '\end{tikzpicture}';
+
+ my $exp_decl = [
+ map("\\pgfdeclarelayer{$_}", @$layers),
+ "\\pgfsetlayers{main,@{[join ',', @$layers]}}",
+ ];
+
+ is_deeply $decl, $exp_decl, "$desc: declarations";
+ is_deeply $body, $exp, "$desc: body";
+}
+
+my $middle = eval {
+ Tikz->layer('middle');
+};
+is $@, '', 'creating a layer doesn\'t croak';
+
+my $top = eval {
+ Tikz->layer(
+ 'top',
+ above => [ 'middle' ],
+ );
+};
+is $@, '', 'creating a layer above another doesn\'t croak';
+
+my $bottom = eval {
+ Tikz->layer(
+ 'bottom',
+ above => [ 'main' ],
+ below => [ 'middle' ],
+ );
+};
+is $@, '', 'creating a layer above and below anothers doesn\'t croak';
+
+my $foo = eval {
+ Tikz->raw('foo')
+ ->mod($middle)
+};
+is $@, '', 'creating a layered raw set doesn\'t croak';
+
+check $foo, 'one layered raw set', <<'RES', [ 'middle' ];
+\begin{pgfonlayer}{middle}
+\draw foo ;
+\end{pgfonlayer}
+RES
+
+my $bar = eval {
+ Tikz->raw('bar')
+ ->mod($top)
+};
+is $@, '', 'creating another layered raw set doesn\'t croak';
+
+my $seq = Tikz->seq($foo, $bar);
+
+check $seq, 'a sequence of two layered raw sets', <<'RES', [ qw/middle top/ ];
+\begin{pgfonlayer}{middle}
+\draw foo ;
+\end{pgfonlayer}
+\begin{pgfonlayer}{top}
+\draw bar ;
+\end{pgfonlayer}
+RES
+
+sub failed_valid {
+ my ($tc) = @_;
+ qr/Validation failed for '\Q$tc\E'/;
+}
+
+eval {
+ $seq->layer(sub { });
+};
+like $@, failed_valid('Str'), 'directly adding a wrong layer croaks';
+
+eval {
+ $seq->layer($bottom);
+};
+is $@, '', 'directly adding a layer to a sequence doesn\'t croak';
+
+my $res = eval {
+ $seq->layer;
+};
+is $@, '', 'calling an empty ->layer onto a sequence doesn\'t croak';
+is "$res", "$seq", 'empty ->layer returns the object itself';
+
+check $seq, 'a layered sequence', <<'RES', [ qw/bottom middle top/ ];
+\begin{pgfonlayer}{bottom}
+\begin{pgfonlayer}{middle}
+\draw foo ;
+\end{pgfonlayer}
+\begin{pgfonlayer}{top}
+\draw bar ;
+\end{pgfonlayer}
+\end{pgfonlayer}
+RES
+
+my $baz = Tikz->raw('baz');
+$seq->add($baz);
+
+my $red = Tikz->color('red');
+$seq->mod($red);
+
+check $seq, 'mods folding with layers 1', <<'RES', [ qw/bottom middle top/ ];
+\begin{pgfonlayer}{bottom}
+\begin{scope} [color=red]
+\begin{pgfonlayer}{middle}
+\draw [color=red] foo ;
+\end{pgfonlayer}
+\begin{pgfonlayer}{top}
+\draw [color=red] bar ;
+\end{pgfonlayer}
+\draw baz ;
+\end{scope}
+\end{pgfonlayer}
+RES
+
+$baz->mod($top);
+
+check $seq, 'mods folding with layers 2', <<'RES', [ qw/bottom middle top/ ];
+\begin{pgfonlayer}{bottom}
+\begin{scope} [color=red]
+\begin{pgfonlayer}{middle}
+\draw [color=red] foo ;
+\end{pgfonlayer}
+\begin{pgfonlayer}{top}
+\draw [color=red] bar ;
+\end{pgfonlayer}
+\begin{pgfonlayer}{top}
+\draw [color=red] baz ;
+\end{pgfonlayer}
+\end{scope}
+\end{pgfonlayer}
+RES
+
+my $seq2 = Tikz->seq($bar, $baz, $foo)
+ ->mod($red);
+
+check $seq2, 'mods folding with layers 3', <<'RES', [ qw/middle top/ ];
+\begin{scope} [color=red]
+\begin{pgfonlayer}{top}
+\begin{scope} [color=red]
+\draw bar ;
+\draw baz ;
+\end{scope}
+\end{pgfonlayer}
+\begin{pgfonlayer}{middle}
+\draw [color=red] foo ;
+\end{pgfonlayer}
+\end{scope}
+RES
+