-
Notifications
You must be signed in to change notification settings - Fork 0
/
ShapeCall.pm
107 lines (84 loc) · 2.99 KB
/
ShapeCall.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package ShapeCall;
use strict;
use Transformation;
use constant SCALE => 10;
sub new {
my $class = shift;
my $self = shift;
$self->{transformations} = [ map { Transformation->new($_) } @{$self->{transformations}} ];
if ($self->{loop_cnt}) {
$self->{loop_transformations} = [ map { Transformation->new($_) } @{$self->{loop_transformations}} ];
}
bless $self, $class;
}
sub transform_to_str {
my $transformations = shift;
my $transform_str = "";
my $h = 0, my $s = 0, my $v = 0, my $opacity = 1;
foreach my $tr (@{$transformations}) {
if($tr->type() eq 'geometric') {
$transform_str = $transform_str.$tr->to_svg().", ";
}
elsif($tr->type() eq 'color') {
($h, $s, $v) = $tr->to_hsv($h, $s, $v);
}
elsif($tr->{cmd} eq 'alpha') {
$opacity *= $tr->{values}->[0];
}
}
if(length($transform_str) > 0) {
$transform_str = substr($transform_str, 0, -2);
}
my $color_str = Transformation::to_rgb($h, $s, $v);
return ($transform_str, $color_str, $opacity);
}
sub single_call {
my ($self, $parent, $grammar, $max_depth) = @_;
my ($transform_str, $color_str, $opacity) = ShapeCall::transform_to_str($self->{transformations});
my $group = $parent->tag('g',
style => {fill => $color_str, stroke => $color_str, 'fill-opacity' => "$opacity", 'stroke-opacity' => "$opacity" },
transform => $transform_str);
if($self->{call_name} eq 'TRIANGLE') {
my $xv = [-0.5 * SCALE, 0.5 * SCALE, 0];
my $yv = [-0.5 * SCALE, -0.5 * SCALE, 0.366 * SCALE];
my $points = $parent->get_path(
x=>$xv, y=>$yv,
-type=>'polygon',
-closed=>'true'
);
$group->polygon(%$points);
}
elsif($self->{call_name} eq 'SQUARE') {
$group->rect(width => SCALE, height => SCALE);
}
elsif($self->{call_name} eq 'CIRCLE') {
$group->circle(cx=>0, cy=>0, r => SCALE);
}
else {
my $successor = $grammar->{rules}->{$self->{call_name}};
if($successor) {
$successor->to_svg($group, $grammar, $max_depth);
}
}
}
sub iteration {
my ($self, $parent, $grammar, $max_depth, $count) = @_;
if ($count <= 0) { return; }
my ($transform_str, $color_str, $opacity) = ShapeCall::transform_to_str($self->{loop_transformations});
my $group = $parent->tag('g',
style => {fill => $color_str, stroke => $color_str, 'fill-opacity' => "$opacity", 'stroke-opacity' => "$opacity" },
transform => $transform_str);
$self->single_call($group, $grammar, $max_depth);
$count--;
$self->iteration($group, $grammar, $max_depth, $count);
}
sub to_svg {
my ($self, $parent, $grammar, $max_depth) = @_;
if ($max_depth <= 0) { return; }
if ($self->{loop_cnt}) {
$self->iteration($parent, $grammar, $max_depth, $self->{loop_cnt});
} else {
$self->single_call($parent, $grammar, $max_depth);
}
}
1;