| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
############################################################################# |
|
2
|
|
|
|
|
|
|
# Parse VCG text into a Graph::Easy object |
|
3
|
|
|
|
|
|
|
# |
|
4
|
|
|
|
|
|
|
############################################################################# |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Graph::Easy::Parser::VCG; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
$VERSION = '0.75'; |
|
9
|
3
|
|
|
3
|
|
16504
|
use Graph::Easy::Parser::Graphviz; |
|
|
3
|
|
|
|
|
13
|
|
|
|
3
|
|
|
|
|
223
|
|
|
10
|
|
|
|
|
|
|
@ISA = qw/Graph::Easy::Parser::Graphviz/; |
|
11
|
|
|
|
|
|
|
|
|
12
|
3
|
|
|
3
|
|
32
|
use strict; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
125
|
|
|
13
|
3
|
|
|
3
|
|
19
|
use warnings; |
|
|
3
|
|
|
|
|
10
|
|
|
|
3
|
|
|
|
|
112
|
|
|
14
|
3
|
|
|
3
|
|
20
|
use utf8; |
|
|
3
|
|
|
|
|
10
|
|
|
|
3
|
|
|
|
|
28
|
|
|
15
|
3
|
|
|
3
|
|
92
|
use constant NO_MULTIPLES => 1; |
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
233
|
|
|
16
|
3
|
|
|
3
|
|
13065
|
use Encode qw/decode/; |
|
|
3
|
|
|
|
|
42160
|
|
|
|
3
|
|
|
|
|
24943
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub _init |
|
19
|
|
|
|
|
|
|
{ |
|
20
|
13
|
|
|
13
|
|
31
|
my $self = shift; |
|
21
|
|
|
|
|
|
|
|
|
22
|
13
|
|
|
|
|
84
|
$self->SUPER::_init(@_); |
|
23
|
13
|
|
|
|
|
29
|
$self->{attr_sep} = '='; |
|
24
|
|
|
|
|
|
|
|
|
25
|
13
|
|
|
|
|
55
|
$self; |
|
26
|
|
|
|
|
|
|
} |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $vcg_color_by_name = {}; |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
my $vcg_colors = [ |
|
31
|
|
|
|
|
|
|
white => 'white', |
|
32
|
|
|
|
|
|
|
blue => 'blue', |
|
33
|
|
|
|
|
|
|
red => 'red', |
|
34
|
|
|
|
|
|
|
green => 'green', |
|
35
|
|
|
|
|
|
|
yellow => 'yellow', |
|
36
|
|
|
|
|
|
|
magenta => 'magenta', |
|
37
|
|
|
|
|
|
|
cyan => 'cyan', |
|
38
|
|
|
|
|
|
|
darkgrey => 'rgb(85,85,85)', |
|
39
|
|
|
|
|
|
|
darkblue => 'rgb(0,0,128)', |
|
40
|
|
|
|
|
|
|
darkred => 'rgb(128,0,0)', |
|
41
|
|
|
|
|
|
|
darkgreen => 'rgb(0,128,0)', |
|
42
|
|
|
|
|
|
|
darkyellow => 'rgb(128,128,0)', |
|
43
|
|
|
|
|
|
|
darkmagenta => 'rgb(128,0,128)', |
|
44
|
|
|
|
|
|
|
darkcyan => 'rgb(0,128,128)', |
|
45
|
|
|
|
|
|
|
gold => 'rgb(255,215,0)', |
|
46
|
|
|
|
|
|
|
lightgrey => 'rgb(170,170,170)', |
|
47
|
|
|
|
|
|
|
lightblue => 'rgb(128,128,255)', |
|
48
|
|
|
|
|
|
|
lightred => 'rgb(255,128,128)', |
|
49
|
|
|
|
|
|
|
lightgreen => 'rgb(128,255,128)', |
|
50
|
|
|
|
|
|
|
lightyellow => 'rgb(255,255,128)', |
|
51
|
|
|
|
|
|
|
lightmagenta => 'rgb(255,128,255)', |
|
52
|
|
|
|
|
|
|
lightcyan => 'rgb(128,255,255)', |
|
53
|
|
|
|
|
|
|
lilac => 'rgb(238,130,238)', |
|
54
|
|
|
|
|
|
|
turquoise => 'rgb(64,224,208)', |
|
55
|
|
|
|
|
|
|
aquamarine => 'rgb(127,255,212)', |
|
56
|
|
|
|
|
|
|
khaki => 'rgb(240,230,140)', |
|
57
|
|
|
|
|
|
|
purple => 'rgb(160,32,240)', |
|
58
|
|
|
|
|
|
|
yellowgreen => 'rgb(154,205,50)', |
|
59
|
|
|
|
|
|
|
pink => 'rgb(255,192,203)', |
|
60
|
|
|
|
|
|
|
orange => 'rgb(255,165,0)', |
|
61
|
|
|
|
|
|
|
orchid => 'rgb(218,112,214)', |
|
62
|
|
|
|
|
|
|
black => 'black', |
|
63
|
|
|
|
|
|
|
]; |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
{ |
|
66
|
|
|
|
|
|
|
for (my $i = 0; $i < @$vcg_colors; $i+=2) |
|
67
|
|
|
|
|
|
|
{ |
|
68
|
|
|
|
|
|
|
$vcg_color_by_name->{$vcg_colors->[$i]} = $vcg_colors->[$i+1]; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub reset |
|
73
|
|
|
|
|
|
|
{ |
|
74
|
26
|
|
|
26
|
1
|
48
|
my $self = shift; |
|
75
|
|
|
|
|
|
|
|
|
76
|
26
|
|
|
|
|
85
|
Graph::Easy::Parser::reset($self, @_); |
|
77
|
|
|
|
|
|
|
|
|
78
|
26
|
|
|
|
|
52
|
my $g = $self->{_graph}; |
|
79
|
26
|
|
|
|
|
61
|
$self->{scope_stack} = []; |
|
80
|
|
|
|
|
|
|
|
|
81
|
26
|
|
|
|
|
60
|
$g->{_vcg_color_map} = []; |
|
82
|
26
|
|
|
|
|
97
|
for (my $i = 0; $i < @$vcg_colors; $i+=2) |
|
83
|
|
|
|
|
|
|
{ |
|
84
|
|
|
|
|
|
|
# set the first 32 colors as the default |
|
85
|
832
|
|
|
|
|
755
|
push @{$g->{_vcg_color_map}}, $vcg_colors->[$i+1]; |
|
|
832
|
|
|
|
|
2665
|
|
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
|
|
88
|
26
|
|
|
|
|
67
|
$g->{_vcg_class_names} = {}; |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# allow some temp. values during parsing |
|
91
|
26
|
|
|
|
|
257
|
$g->_allow_special_attributes( |
|
92
|
|
|
|
|
|
|
{ |
|
93
|
|
|
|
|
|
|
edge => { |
|
94
|
|
|
|
|
|
|
source => [ "", undef, '', '', undef, ], |
|
95
|
|
|
|
|
|
|
target => [ "", undef, '', '', undef, ], |
|
96
|
|
|
|
|
|
|
}, |
|
97
|
|
|
|
|
|
|
} ); |
|
98
|
|
|
|
|
|
|
|
|
99
|
26
|
|
|
|
|
62
|
$g->{_warn_on_unknown_attributes} = 1; |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# a hack to support multiline labels |
|
102
|
26
|
|
|
|
|
48
|
$self->{_in_vcg_multi_line_label} = 0; |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# set some default attributes on the graph object, because GDL has |
|
105
|
|
|
|
|
|
|
# some different defaults as Graph::Easy |
|
106
|
26
|
|
|
|
|
124
|
$g->set_attribute('flow', 'south'); |
|
107
|
26
|
|
|
|
|
79
|
$g->set_attribute('edge', 'arrow-style', 'filled'); |
|
108
|
26
|
|
|
|
|
70
|
$g->set_attribute('node', 'align', 'left'); |
|
109
|
|
|
|
|
|
|
|
|
110
|
26
|
|
|
|
|
81
|
$self; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub _vcg_color_map_entry |
|
114
|
|
|
|
|
|
|
{ |
|
115
|
2
|
|
|
2
|
|
9
|
my ($self, $index, $color) = @_; |
|
116
|
|
|
|
|
|
|
|
|
117
|
2
|
|
|
|
|
8
|
$color =~ /([0-9]+)\s+([0-9]+)\s+([0-9]+)/; |
|
118
|
2
|
|
|
|
|
18
|
$self->{_graph}->{_vcg_color_map}->[$index] = "rgb($1,$2,$3)"; |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub _unquote |
|
122
|
|
|
|
|
|
|
{ |
|
123
|
81
|
|
|
81
|
|
109
|
my ($self, $name) = @_; |
|
124
|
|
|
|
|
|
|
|
|
125
|
81
|
50
|
|
|
|
150
|
$name = '' unless defined $name; |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# "foo bar" => foo bar |
|
128
|
|
|
|
|
|
|
# we need to use "[ ]" here, because "\s" also matches 0x0c, and |
|
129
|
|
|
|
|
|
|
# these color codes need to be kept intact: |
|
130
|
81
|
|
|
|
|
383
|
$name =~ s/^"[ ]*//; # remove left-over quotes |
|
131
|
81
|
|
|
|
|
262
|
$name =~ s/[ ]*"\z//; |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
# unquote special chars |
|
134
|
81
|
|
|
|
|
114
|
$name =~ s/\\([\[\(\{\}\]\)#"])/$1/g; |
|
135
|
|
|
|
|
|
|
|
|
136
|
81
|
|
|
|
|
223
|
$name; |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
############################################################################# |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
sub _match_commented_line |
|
142
|
|
|
|
|
|
|
{ |
|
143
|
|
|
|
|
|
|
# matches only empty lines |
|
144
|
13
|
|
|
13
|
|
84
|
qr/^\s*\z/; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub _match_multi_line_comment |
|
148
|
|
|
|
|
|
|
{ |
|
149
|
|
|
|
|
|
|
# match a multi line comment |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
# /* * comment * */ |
|
152
|
103
|
|
|
103
|
|
365
|
qr#^\s*/\*.*?\*/\s*#; |
|
153
|
|
|
|
|
|
|
} |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub _match_optional_multi_line_comment |
|
156
|
|
|
|
|
|
|
{ |
|
157
|
|
|
|
|
|
|
# match a multi line comment |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# "/* * comment * */" or /* a */ /* b */ or "" |
|
160
|
13
|
|
|
13
|
|
52
|
qr#(?:(?:\s*/\*.*?\*/\s*)*|\s+)#; |
|
161
|
|
|
|
|
|
|
} |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub _match_classname |
|
164
|
|
|
|
|
|
|
{ |
|
165
|
|
|
|
|
|
|
# Return a regexp that matches something like classname 1: "foo" |
|
166
|
13
|
|
|
13
|
|
22
|
my $self = shift; |
|
167
|
|
|
|
|
|
|
|
|
168
|
13
|
|
|
|
|
64
|
qr/^\s*classname\s([0-9]+)\s*:\s*"((\\"|[^"])*)"/; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub _match_node |
|
172
|
|
|
|
|
|
|
{ |
|
173
|
|
|
|
|
|
|
# Return a regexp that matches a node at the start of the buffer |
|
174
|
13
|
|
|
13
|
|
19
|
my $self = shift; |
|
175
|
|
|
|
|
|
|
|
|
176
|
13
|
|
|
|
|
52
|
my $attr = $self->_match_attributes(); |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# Examples: "node: { title: "a" }" |
|
179
|
13
|
|
|
|
|
266
|
qr/^\s*node:\s*$attr/; |
|
180
|
|
|
|
|
|
|
} |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
sub _match_edge |
|
183
|
|
|
|
|
|
|
{ |
|
184
|
|
|
|
|
|
|
# Matches an edge at the start of the buffer |
|
185
|
13
|
|
|
13
|
|
28
|
my $self = shift; |
|
186
|
|
|
|
|
|
|
|
|
187
|
13
|
|
|
|
|
30
|
my $attr = $self->_match_attributes(); |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# Examples: "edge: { sourcename: "a" targetname: "b" }" |
|
190
|
|
|
|
|
|
|
# "backedge: { sourcename: "a" targetname: "b" }" |
|
191
|
13
|
|
|
|
|
270
|
qr/^\s*(|near|bentnear|back)edge:\s*$attr/; |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub _match_single_attribute |
|
195
|
|
|
|
|
|
|
{ |
|
196
|
|
|
|
|
|
|
|
|
197
|
52
|
|
|
52
|
|
208
|
qr/\s*( energetic\s\w+ # "energetic attraction" etc. |
|
198
|
|
|
|
|
|
|
| |
|
199
|
|
|
|
|
|
|
\w+ # a word |
|
200
|
|
|
|
|
|
|
| |
|
201
|
|
|
|
|
|
|
border\s(?:x|y) # "border x" or "border y" |
|
202
|
|
|
|
|
|
|
| |
|
203
|
|
|
|
|
|
|
colorentry\s+[0-9]{1,2} # colorentry |
|
204
|
|
|
|
|
|
|
)\s*:\s* |
|
205
|
|
|
|
|
|
|
( |
|
206
|
|
|
|
|
|
|
"(?:\\"|[^"])*" # "foo" |
|
207
|
|
|
|
|
|
|
| |
|
208
|
|
|
|
|
|
|
[0-9]{1,3}\s+[0-9]{1,3}\s+[0-9]{1,3} # "128 128 64" for color entries |
|
209
|
|
|
|
|
|
|
| |
|
210
|
|
|
|
|
|
|
\{[^\}]+\} # or {..} |
|
211
|
|
|
|
|
|
|
| |
|
212
|
|
|
|
|
|
|
[^<][^,\]\}\n\s;]* # or simple 'fooobar' |
|
213
|
|
|
|
|
|
|
) |
|
214
|
|
|
|
|
|
|
\s*/x; # possible trailing whitespace |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub _match_class_attribute |
|
218
|
|
|
|
|
|
|
{ |
|
219
|
|
|
|
|
|
|
# match something like "edge.color: 10" |
|
220
|
|
|
|
|
|
|
|
|
221
|
13
|
|
|
13
|
|
50
|
qr/\s*(edge|node)\.(\w+)\s*:\s* # the attribute name (label:") |
|
222
|
|
|
|
|
|
|
( |
|
223
|
|
|
|
|
|
|
"(?:\\"|[^"])*" # "foo" |
|
224
|
|
|
|
|
|
|
| |
|
225
|
|
|
|
|
|
|
[^<][^,\]\}\n\s]* # or simple 'fooobar' |
|
226
|
|
|
|
|
|
|
) |
|
227
|
|
|
|
|
|
|
\s*/x; # possible whitespace |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
sub _match_attributes |
|
231
|
|
|
|
|
|
|
{ |
|
232
|
|
|
|
|
|
|
# return a regexp that matches something like " { color=red; }" and returns |
|
233
|
|
|
|
|
|
|
# the inner text without the {} |
|
234
|
|
|
|
|
|
|
|
|
235
|
39
|
|
|
39
|
|
78
|
my $qr_att = _match_single_attribute(); |
|
236
|
39
|
|
|
|
|
81
|
my $qr_cmt = _match_multi_line_comment(); |
|
237
|
|
|
|
|
|
|
|
|
238
|
39
|
|
|
|
|
546
|
qr/\s*\{\s*((?:$qr_att|$qr_cmt)*)\s*\}/; |
|
239
|
|
|
|
|
|
|
} |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub _match_graph_attribute |
|
242
|
|
|
|
|
|
|
{ |
|
243
|
|
|
|
|
|
|
# return a regexp that matches something like " color: red " for attributes |
|
244
|
|
|
|
|
|
|
# that apply to a graph/subgraph |
|
245
|
13
|
|
|
13
|
|
51
|
qr/^\s*( |
|
246
|
|
|
|
|
|
|
( |
|
247
|
|
|
|
|
|
|
colorentry\s+[0-9]{1,2}:\s+[0-9]+\s+[0-9]+\s+[0-9]+ |
|
248
|
|
|
|
|
|
|
| |
|
249
|
|
|
|
|
|
|
(?!(node|edge|nearedge|bentnearedge|graph)) # not one of these |
|
250
|
|
|
|
|
|
|
\w+\s*:\s*("(?:\\"|[^"])*"|[^\n\s]+) |
|
251
|
|
|
|
|
|
|
) |
|
252
|
|
|
|
|
|
|
)([\n\s]\s*|\z)/x; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
sub _clean_attributes |
|
256
|
|
|
|
|
|
|
{ |
|
257
|
51
|
|
|
51
|
|
83
|
my ($self,$text) = @_; |
|
258
|
|
|
|
|
|
|
|
|
259
|
51
|
|
|
|
|
96
|
$text =~ s/^\s*\{\s*//; # remove left-over "{" and spaces |
|
260
|
51
|
|
|
|
|
68
|
$text =~ s/\s*;?\s*\}\s*\z//; # remove left-over "}" and spaces |
|
261
|
|
|
|
|
|
|
|
|
262
|
51
|
|
|
|
|
127
|
$text; |
|
263
|
|
|
|
|
|
|
} |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
sub _match_group_end |
|
266
|
|
|
|
|
|
|
{ |
|
267
|
|
|
|
|
|
|
# return a regexp that matches something like " }" at the beginning |
|
268
|
13
|
|
|
13
|
|
52
|
qr/^\s*\}\s*/; |
|
269
|
|
|
|
|
|
|
} |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub _match_group_start |
|
272
|
|
|
|
|
|
|
{ |
|
273
|
|
|
|
|
|
|
# return a regexp that matches something like "graph {" at the beginning |
|
274
|
13
|
|
|
13
|
|
44
|
qr/^\s*graph:\s+\{\s*/; |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub _clean_line |
|
278
|
|
|
|
|
|
|
{ |
|
279
|
|
|
|
|
|
|
# do some cleanups on a line before handling it |
|
280
|
96
|
|
|
96
|
|
146
|
my ($self,$line) = @_; |
|
281
|
|
|
|
|
|
|
|
|
282
|
96
|
|
|
|
|
172
|
chomp($line); |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
# collapse white space at start |
|
285
|
96
|
|
|
|
|
269
|
$line =~ s/^\s+//; |
|
286
|
|
|
|
|
|
|
|
|
287
|
96
|
100
|
|
|
|
353
|
if ($self->{_in_vcg_multi_line_label}) |
|
|
|
100
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
{ |
|
289
|
5
|
100
|
|
|
|
21
|
if ($line =~ /\"[^\"]*\z/) |
|
290
|
|
|
|
|
|
|
{ |
|
291
|
|
|
|
|
|
|
# '"\n' |
|
292
|
2
|
|
|
|
|
6
|
$self->{_in_vcg_multi_line_label} = 0; |
|
293
|
|
|
|
|
|
|
# restore the match stack |
|
294
|
2
|
|
|
|
|
6
|
$self->{match_stack} = $self->{_match_stack}; |
|
295
|
2
|
|
|
|
|
6
|
delete $self->{_match_stack}; |
|
296
|
|
|
|
|
|
|
} |
|
297
|
|
|
|
|
|
|
else |
|
298
|
|
|
|
|
|
|
{ |
|
299
|
|
|
|
|
|
|
# hack: convert "a" to \"a\" to fix faulty inputs |
|
300
|
3
|
|
|
|
|
8
|
$line =~ s/([^\\])\"/$1\\\"/g; |
|
301
|
|
|
|
|
|
|
} |
|
302
|
|
|
|
|
|
|
} |
|
303
|
|
|
|
|
|
|
# a line ending in 'label: "...\n' means a multi-line label |
|
304
|
|
|
|
|
|
|
elsif ($line =~ /(^|\s)label:\s+\"[^\"]*\z/) |
|
305
|
|
|
|
|
|
|
{ |
|
306
|
2
|
|
|
|
|
6
|
$self->{_in_vcg_multi_line_label} = 1; |
|
307
|
|
|
|
|
|
|
# swap out the match stack since we just wait for the end of the label |
|
308
|
2
|
|
|
|
|
5
|
$self->{_match_stack} = $self->{match_stack}; |
|
309
|
2
|
|
|
|
|
7
|
delete $self->{match_stack}; |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
|
|
312
|
96
|
|
|
|
|
342
|
$line; |
|
313
|
|
|
|
|
|
|
} |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
sub _line_insert |
|
316
|
|
|
|
|
|
|
{ |
|
317
|
|
|
|
|
|
|
# What to insert between two lines. |
|
318
|
96
|
|
|
96
|
|
161
|
my ($self) = @_; |
|
319
|
|
|
|
|
|
|
|
|
320
|
96
|
50
|
66
|
|
|
291
|
print STDERR "in multiline\n" if $self->{_in_vcg_multi_line_label} && $self->{debug}; |
|
321
|
|
|
|
|
|
|
# multiline labels => '\n' |
|
322
|
96
|
100
|
|
|
|
215
|
return '\\n' if $self->{_in_vcg_multi_line_label}; |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# the default is ' ' |
|
325
|
91
|
|
|
|
|
308
|
' '; |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
############################################################################# |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
sub _new_scope |
|
331
|
|
|
|
|
|
|
{ |
|
332
|
|
|
|
|
|
|
# create a new scope, with attributes from current scope |
|
333
|
13
|
|
|
13
|
|
30
|
my ($self, $is_group) = @_; |
|
334
|
|
|
|
|
|
|
|
|
335
|
13
|
|
|
|
|
46
|
my $scope = {}; |
|
336
|
|
|
|
|
|
|
|
|
337
|
13
|
50
|
|
|
|
24
|
if (@{$self->{scope_stack}} > 0) |
|
|
13
|
|
|
|
|
76
|
|
|
338
|
|
|
|
|
|
|
{ |
|
339
|
0
|
|
|
|
|
0
|
my $old_scope = $self->{scope_stack}->[-1]; |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# make a copy of the old scope's attribtues |
|
342
|
0
|
|
|
|
|
0
|
for my $t (sort keys %$old_scope) |
|
343
|
|
|
|
|
|
|
{ |
|
344
|
0
|
0
|
|
|
|
0
|
next if $t =~ /^_/; |
|
345
|
0
|
|
|
|
|
0
|
my $s = $old_scope->{$t}; |
|
346
|
0
|
0
|
|
|
|
0
|
$scope->{$t} = {} unless ref $scope->{$t}; my $sc = $scope->{$t}; |
|
|
0
|
|
|
|
|
0
|
|
|
347
|
0
|
|
|
|
|
0
|
for my $k (sort keys %$s) |
|
348
|
|
|
|
|
|
|
{ |
|
349
|
|
|
|
|
|
|
# skip things like "_is_group" |
|
350
|
0
|
0
|
|
|
|
0
|
$sc->{$k} = $s->{$k} unless $k =~ /^_/; |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
} |
|
354
|
13
|
50
|
|
|
|
59
|
$scope->{_is_group} = 1 if defined $is_group; |
|
355
|
|
|
|
|
|
|
|
|
356
|
13
|
|
|
|
|
20
|
push @{$self->{scope_stack}}, $scope; |
|
|
13
|
|
|
|
|
30
|
|
|
357
|
|
|
|
|
|
|
|
|
358
|
13
|
|
|
|
|
28
|
$scope; |
|
359
|
|
|
|
|
|
|
} |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
sub _edge_style |
|
362
|
|
|
|
|
|
|
{ |
|
363
|
|
|
|
|
|
|
# To convert "--" or "->" we simple do nothing, since the edge style in |
|
364
|
|
|
|
|
|
|
# VCG can only be set via the attributes (if at all) |
|
365
|
0
|
|
|
0
|
|
0
|
my ($self, $ed) = @_; |
|
366
|
|
|
|
|
|
|
|
|
367
|
0
|
|
|
|
|
0
|
'solid'; |
|
368
|
|
|
|
|
|
|
} |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
sub _build_match_stack |
|
371
|
|
|
|
|
|
|
{ |
|
372
|
13
|
|
|
13
|
|
24
|
my $self = shift; |
|
373
|
|
|
|
|
|
|
|
|
374
|
13
|
|
|
|
|
47
|
my $qr_cn = $self->_match_classname(); |
|
375
|
13
|
|
|
|
|
57
|
my $qr_node = $self->_match_node(); |
|
376
|
13
|
|
|
|
|
54
|
my $qr_cmt = $self->_match_multi_line_comment(); |
|
377
|
13
|
|
|
|
|
56
|
my $qr_ocmt = $self->_match_optional_multi_line_comment(); |
|
378
|
13
|
|
|
|
|
40
|
my $qr_attr = $self->_match_attributes(); |
|
379
|
13
|
|
|
|
|
59
|
my $qr_gatr = $self->_match_graph_attribute(); |
|
380
|
13
|
|
|
|
|
96
|
my $qr_oatr = $self->_match_optional_attributes(); |
|
381
|
13
|
|
|
|
|
59
|
my $qr_edge = $self->_match_edge(); |
|
382
|
13
|
|
|
|
|
52
|
my $qr_class = $self->_match_class_attribute(); |
|
383
|
|
|
|
|
|
|
|
|
384
|
13
|
|
|
|
|
50
|
my $qr_group_end = $self->_match_group_end(); |
|
385
|
13
|
|
|
|
|
51
|
my $qr_group_start = $self->_match_group_start(); |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
# "graph: {" |
|
388
|
|
|
|
|
|
|
$self->_register_handler( $qr_group_start, |
|
389
|
|
|
|
|
|
|
sub |
|
390
|
|
|
|
|
|
|
{ |
|
391
|
13
|
|
|
13
|
|
33
|
my $self = shift; |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
# the main graph |
|
394
|
13
|
50
|
|
|
|
18
|
if (@{$self->{scope_stack}} == 0) |
|
|
13
|
|
|
|
|
50
|
|
|
395
|
|
|
|
|
|
|
{ |
|
396
|
13
|
50
|
|
|
|
45
|
print STDERR "# Parser: found main graph\n" if $self->{debug}; |
|
397
|
13
|
|
|
|
|
34
|
$self->{_vcg_graph_name} = 'unnamed'; |
|
398
|
13
|
|
|
|
|
55
|
$self->_new_scope(1); |
|
399
|
|
|
|
|
|
|
} |
|
400
|
|
|
|
|
|
|
else |
|
401
|
|
|
|
|
|
|
{ |
|
402
|
0
|
0
|
|
|
|
0
|
print STDERR "# Parser: found subgraph\n" if $self->{debug}; |
|
403
|
|
|
|
|
|
|
# a new subgraph |
|
404
|
0
|
|
|
|
|
0
|
push @{$self->{group_stack}}, $self->_new_group(); |
|
|
0
|
|
|
|
|
0
|
|
|
405
|
|
|
|
|
|
|
} |
|
406
|
13
|
|
|
|
|
32
|
1; |
|
407
|
13
|
|
|
|
|
157
|
} ); |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
# graph or subgraph end "}" |
|
410
|
|
|
|
|
|
|
$self->_register_handler( $qr_group_end, |
|
411
|
|
|
|
|
|
|
sub |
|
412
|
|
|
|
|
|
|
{ |
|
413
|
13
|
|
|
13
|
|
25
|
my $self = shift; |
|
414
|
|
|
|
|
|
|
|
|
415
|
13
|
50
|
|
|
|
45
|
print STDERR "# Parser: found end of (sub-)graph\n" if $self->{debug}; |
|
416
|
|
|
|
|
|
|
|
|
417
|
13
|
|
|
|
|
16
|
my $scope = pop @{$self->{scope_stack}}; |
|
|
13
|
|
|
|
|
32
|
|
|
418
|
13
|
50
|
|
|
|
31
|
return $self->parse_error(0) if !defined $scope; |
|
419
|
|
|
|
|
|
|
|
|
420
|
13
|
|
|
|
|
57
|
1; |
|
421
|
13
|
|
|
|
|
87
|
} ); |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
# classname 1: "foo" |
|
424
|
|
|
|
|
|
|
$self->_register_handler( $qr_cn, |
|
425
|
|
|
|
|
|
|
sub { |
|
426
|
2
|
|
|
2
|
|
4
|
my $self = shift; |
|
427
|
2
|
|
|
|
|
5
|
my $class = $1; my $name = $2; |
|
|
2
|
|
|
|
|
5
|
|
|
428
|
|
|
|
|
|
|
|
|
429
|
2
|
50
|
|
|
|
7
|
print STDERR "# Found classname '$name' for class '$class'\n" if $self->{debug} > 1; |
|
430
|
|
|
|
|
|
|
|
|
431
|
2
|
|
|
|
|
8
|
$self->{_graph}->{_vcg_class_names}->{$class} = $name; |
|
432
|
2
|
|
|
|
|
5
|
1; |
|
433
|
13
|
|
|
|
|
86
|
} ); |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
# node: { ... } |
|
436
|
|
|
|
|
|
|
$self->_register_handler( $qr_node, |
|
437
|
|
|
|
|
|
|
sub { |
|
438
|
26
|
|
|
26
|
|
42
|
my $self = shift; |
|
439
|
26
|
|
50
|
|
|
167
|
my $att = $self->_parse_attributes($1 || '', 'node', NO_MULTIPLES ); |
|
440
|
26
|
50
|
|
|
|
71
|
return undef unless defined $att; # error in attributes? |
|
441
|
|
|
|
|
|
|
|
|
442
|
26
|
|
|
|
|
135
|
my $name = $att->{title}; delete $att->{title}; |
|
|
26
|
|
|
|
|
60
|
|
|
443
|
|
|
|
|
|
|
|
|
444
|
26
|
50
|
|
|
|
68
|
print STDERR "# Found node with name $name\n" if $self->{debug} > 1; |
|
445
|
|
|
|
|
|
|
|
|
446
|
26
|
|
|
|
|
163
|
my $node = $self->_new_node($self->{_graph}, $name, $self->{group_stack}, $att, []); |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
# set attributes from scope |
|
449
|
26
|
|
50
|
|
|
91
|
my $scope = $self->{scope_stack}->[-1] || {}; |
|
450
|
26
|
100
|
|
|
|
32
|
$node->set_attributes ($scope->{node}) if keys %{$scope->{node}} != 0; |
|
|
26
|
|
|
|
|
94
|
|
|
451
|
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
# override with local attributes |
|
453
|
26
|
100
|
|
|
|
96
|
$node->set_attributes ($att) if keys %$att != 0; |
|
454
|
26
|
|
|
|
|
89
|
1; |
|
455
|
13
|
|
|
|
|
112
|
} ); |
|
456
|
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
# "edge: { ... }" |
|
458
|
|
|
|
|
|
|
$self->_register_handler( $qr_edge, |
|
459
|
|
|
|
|
|
|
sub { |
|
460
|
13
|
|
|
13
|
|
26
|
my $self = shift; |
|
461
|
13
|
|
50
|
|
|
98
|
my $type = $1 || 'edge'; |
|
462
|
13
|
|
50
|
|
|
54
|
my $txt = $2 || ''; |
|
463
|
13
|
50
|
|
|
|
56
|
$type = "edge" if $type =~ /edge/; # bentnearedge => edge |
|
464
|
13
|
|
|
|
|
88
|
my $att = $self->_parse_attributes($txt, 'edge', NO_MULTIPLES ); |
|
465
|
13
|
50
|
|
|
|
51
|
return undef unless defined $att; # error in attributes? |
|
466
|
|
|
|
|
|
|
|
|
467
|
13
|
|
|
|
|
31
|
my $from = $att->{source}; delete $att->{source}; |
|
|
13
|
|
|
|
|
27
|
|
|
468
|
13
|
|
|
|
|
25
|
my $to = $att->{target}; delete $att->{target}; |
|
|
13
|
|
|
|
|
25
|
|
|
469
|
|
|
|
|
|
|
|
|
470
|
13
|
50
|
|
|
|
47
|
print STDERR "# Found edge ($type) from $from to $to\n" if $self->{debug} > 1; |
|
471
|
|
|
|
|
|
|
|
|
472
|
13
|
|
|
|
|
79
|
my $edge = $self->{_graph}->add_edge ($from, $to); |
|
473
|
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
# set attributes from scope |
|
475
|
13
|
|
50
|
|
|
51
|
my $scope = $self->{scope_stack}->[-1] || {}; |
|
476
|
13
|
100
|
|
|
|
20
|
$edge->set_attributes ($scope->{edge}) if keys %{$scope->{edge}} != 0; |
|
|
13
|
|
|
|
|
71
|
|
|
477
|
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
# override with local attributes |
|
479
|
13
|
100
|
|
|
|
55
|
$edge->set_attributes ($att) if keys %$att != 0; |
|
480
|
|
|
|
|
|
|
|
|
481
|
13
|
|
|
|
|
49
|
1; |
|
482
|
13
|
|
|
|
|
106
|
} ); |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# color: red (for graphs or subgraphs) |
|
485
|
13
|
|
|
|
|
226
|
$self->_register_attribute_handler($qr_gatr, 'parent'); |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
# edge.color: 10 |
|
488
|
|
|
|
|
|
|
$self->_register_handler( $qr_class, |
|
489
|
|
|
|
|
|
|
sub { |
|
490
|
6
|
|
|
6
|
|
12
|
my $self = shift; |
|
491
|
6
|
|
|
|
|
16
|
my $type = $1; |
|
492
|
6
|
|
|
|
|
12
|
my $name = $2; |
|
493
|
6
|
|
|
|
|
17
|
my $val = $3; |
|
494
|
|
|
|
|
|
|
|
|
495
|
6
|
50
|
|
|
|
18
|
print STDERR "# Found color definition $type $name $val\n" if $self->{debug} > 2; |
|
496
|
|
|
|
|
|
|
|
|
497
|
6
|
|
|
|
|
43
|
my $att = $self->_remap_attributes( { $name => $val }, $type, $self->_remap()); |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
# store the attributes in the current scope |
|
500
|
6
|
|
|
|
|
19
|
my $scope = $self->{scope_stack}->[-1]; |
|
501
|
6
|
100
|
|
|
|
24
|
$scope->{$type} = {} unless ref $scope->{$type}; |
|
502
|
6
|
|
|
|
|
10
|
my $s = $scope->{$type}; |
|
503
|
|
|
|
|
|
|
|
|
504
|
6
|
|
|
|
|
18
|
for my $k (sort keys %$att) |
|
505
|
|
|
|
|
|
|
{ |
|
506
|
6
|
|
|
|
|
17
|
$s->{$k} = $att->{$k}; |
|
507
|
|
|
|
|
|
|
} |
|
508
|
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
#$self->{_graph}->set_attributes ($type, $att); |
|
510
|
6
|
|
|
|
|
20
|
1; |
|
511
|
13
|
|
|
|
|
149
|
}); |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
# remove multi line comments /* comment */ |
|
514
|
13
|
|
|
|
|
43
|
$self->_register_handler( $qr_cmt, undef ); |
|
515
|
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
# remove single line comment // comment |
|
517
|
13
|
|
|
|
|
66
|
$self->_register_handler( qr/^\s*\/\/.*/, undef ); |
|
518
|
|
|
|
|
|
|
|
|
519
|
13
|
|
|
|
|
52
|
$self; |
|
520
|
|
|
|
|
|
|
} |
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
sub _new_node |
|
523
|
|
|
|
|
|
|
{ |
|
524
|
|
|
|
|
|
|
# add a node to the graph, overridable by subclasses |
|
525
|
26
|
|
|
26
|
|
56
|
my ($self, $graph, $name, $group_stack, $att, $stack) = @_; |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
# print STDERR "add_node $name\n"; |
|
528
|
|
|
|
|
|
|
|
|
529
|
26
|
|
|
|
|
104
|
my $node = $graph->node($name); |
|
530
|
|
|
|
|
|
|
|
|
531
|
26
|
50
|
|
|
|
66
|
if (!defined $node) |
|
532
|
|
|
|
|
|
|
{ |
|
533
|
26
|
|
|
|
|
94
|
$node = $graph->add_node($name); # add |
|
534
|
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
# apply attributes from the current scope (only for new nodes) |
|
536
|
26
|
|
|
|
|
59
|
my $scope = $self->{scope_stack}->[-1]; |
|
537
|
26
|
50
|
|
|
|
58
|
return $self->error("Scope stack is empty!") unless defined $scope; |
|
538
|
|
|
|
|
|
|
|
|
539
|
26
|
|
|
|
|
51
|
my $is_group = $scope->{_is_group}; |
|
540
|
26
|
|
|
|
|
49
|
delete $scope->{_is_group}; |
|
541
|
26
|
|
|
|
|
124
|
$node->set_attributes($scope->{node}); |
|
542
|
26
|
50
|
|
|
|
78
|
$scope->{_is_group} = $is_group if $is_group; |
|
543
|
|
|
|
|
|
|
|
|
544
|
26
|
|
|
|
|
48
|
my $group = $self->{group_stack}->[-1]; |
|
545
|
|
|
|
|
|
|
|
|
546
|
26
|
50
|
|
|
|
60
|
$node->add_to_group($group) if $group; |
|
547
|
|
|
|
|
|
|
} |
|
548
|
|
|
|
|
|
|
|
|
549
|
26
|
|
|
|
|
56
|
$node; |
|
550
|
|
|
|
|
|
|
} |
|
551
|
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
############################################################################# |
|
553
|
|
|
|
|
|
|
# attribute remapping |
|
554
|
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
# undef => drop that attribute |
|
556
|
|
|
|
|
|
|
# not listed attributes are simple copied unmodified |
|
557
|
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
my $vcg_remap = { |
|
559
|
|
|
|
|
|
|
'node' => { |
|
560
|
|
|
|
|
|
|
iconfile => 'x-vcg-iconfile', |
|
561
|
|
|
|
|
|
|
info1 => 'x-vcg-info1', |
|
562
|
|
|
|
|
|
|
info2 => 'x-vcg-info2', |
|
563
|
|
|
|
|
|
|
info3 => 'x-vcg-info3', |
|
564
|
|
|
|
|
|
|
invisible => \&_invisible_from_vcg, |
|
565
|
|
|
|
|
|
|
importance => 'x-vcg-importance', |
|
566
|
|
|
|
|
|
|
focus => 'x-vcg-focus', |
|
567
|
|
|
|
|
|
|
margin => 'x-vcg-margin', |
|
568
|
|
|
|
|
|
|
textmode => \&_textmode_from_vcg, |
|
569
|
|
|
|
|
|
|
textcolor => \&_node_color_from_vcg, |
|
570
|
|
|
|
|
|
|
color => \&_node_color_from_vcg, |
|
571
|
|
|
|
|
|
|
bordercolor => \&_node_color_from_vcg, |
|
572
|
|
|
|
|
|
|
level => 'rank', |
|
573
|
|
|
|
|
|
|
horizontal_order => \&_horizontal_order_from_vcg, |
|
574
|
|
|
|
|
|
|
shape => \&_vcg_node_shape, |
|
575
|
|
|
|
|
|
|
vertical_order => \&_vertical_order_from_vcg, |
|
576
|
|
|
|
|
|
|
}, |
|
577
|
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
'edge' => { |
|
579
|
|
|
|
|
|
|
anchor => 'x-vcg-anchor', |
|
580
|
|
|
|
|
|
|
right_anchor => 'x-vcg-right_anchor', |
|
581
|
|
|
|
|
|
|
left_anchor => 'x-vcg-left_anchor', |
|
582
|
|
|
|
|
|
|
arrowcolor => 'x-vcg-arrowcolor', |
|
583
|
|
|
|
|
|
|
arrowsize => 'x-vcg-arrowsize', |
|
584
|
|
|
|
|
|
|
# XXX remap this |
|
585
|
|
|
|
|
|
|
arrowstyle => 'x-vcg-arrowstyle', |
|
586
|
|
|
|
|
|
|
backarrowcolor => 'x-vcg-backarrowcolor', |
|
587
|
|
|
|
|
|
|
backarrowsize => 'x-vcg-backarrowsize', |
|
588
|
|
|
|
|
|
|
backarrowstyle => 'x-vcg-backarrowstyle', |
|
589
|
|
|
|
|
|
|
class => \&_edge_class_from_vcg, |
|
590
|
|
|
|
|
|
|
color => \&_edge_color_from_vcg, |
|
591
|
|
|
|
|
|
|
horizontal_order => 'x-vcg-horizontal_order', |
|
592
|
|
|
|
|
|
|
linestyle => 'style', |
|
593
|
|
|
|
|
|
|
priority => 'x-vcg-priority', |
|
594
|
|
|
|
|
|
|
source => 'source', |
|
595
|
|
|
|
|
|
|
sourcename => 'source', |
|
596
|
|
|
|
|
|
|
target => 'target', |
|
597
|
|
|
|
|
|
|
targetname => 'target', |
|
598
|
|
|
|
|
|
|
textcolor => \&_edge_color_from_vcg, |
|
599
|
|
|
|
|
|
|
thickness => 'x-vcg-thickness', # remap to broad etc. |
|
600
|
|
|
|
|
|
|
}, |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
'graph' => { |
|
603
|
|
|
|
|
|
|
color => \&_node_color_from_vcg, |
|
604
|
|
|
|
|
|
|
bordercolor => \&_node_color_from_vcg, |
|
605
|
|
|
|
|
|
|
textcolor => \&_node_color_from_vcg, |
|
606
|
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
x => 'x-vcg-x', |
|
608
|
|
|
|
|
|
|
y => 'x-vcg-y', |
|
609
|
|
|
|
|
|
|
xmax => 'x-vcg-xmax', |
|
610
|
|
|
|
|
|
|
ymax => 'x-vcg-ymax', |
|
611
|
|
|
|
|
|
|
xspace => 'x-vcg-xspace', |
|
612
|
|
|
|
|
|
|
yspace => 'x-vcg-yspace', |
|
613
|
|
|
|
|
|
|
xlspace => 'x-vcg-xlspace', |
|
614
|
|
|
|
|
|
|
ylspace => 'x-vcg-ylspace', |
|
615
|
|
|
|
|
|
|
xbase => 'x-vcg-xbase', |
|
616
|
|
|
|
|
|
|
ybase => 'x-vcg-ybase', |
|
617
|
|
|
|
|
|
|
xlraster => 'x-vcg-xlraster', |
|
618
|
|
|
|
|
|
|
xraster => 'x-vcg-xraster', |
|
619
|
|
|
|
|
|
|
yraster => 'x-vcg-yraster', |
|
620
|
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
amax => 'x-vcg-amax', |
|
622
|
|
|
|
|
|
|
bmax => 'x-vcg-bmax', |
|
623
|
|
|
|
|
|
|
cmax => 'x-vcg-cmax', |
|
624
|
|
|
|
|
|
|
cmin => 'x-vcg-cmin', |
|
625
|
|
|
|
|
|
|
smax => 'x-vcg-smax', |
|
626
|
|
|
|
|
|
|
pmax => 'x-vcg-pmax', |
|
627
|
|
|
|
|
|
|
pmin => 'x-vcg-pmin', |
|
628
|
|
|
|
|
|
|
rmax => 'x-vcg-rmax', |
|
629
|
|
|
|
|
|
|
rmin => 'x-vcg-rmin', |
|
630
|
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
splines => 'x-vcg-splines', |
|
632
|
|
|
|
|
|
|
focus => 'x-vcg-focus', |
|
633
|
|
|
|
|
|
|
hidden => 'x-vcg-hidden', |
|
634
|
|
|
|
|
|
|
horizontal_order => 'x-vcg-horizontal_order', |
|
635
|
|
|
|
|
|
|
iconfile => 'x-vcg-iconfile', |
|
636
|
|
|
|
|
|
|
inport_sharing => \&_inport_sharing_from_vcg, |
|
637
|
|
|
|
|
|
|
importance => 'x-vcg-importance', |
|
638
|
|
|
|
|
|
|
ignore_singles => 'x-vcg-ignore_singles', |
|
639
|
|
|
|
|
|
|
invisible => 'x-vcg-invisible', |
|
640
|
|
|
|
|
|
|
info1 => 'x-vcg-info1', |
|
641
|
|
|
|
|
|
|
info2 => 'x-vcg-info2', |
|
642
|
|
|
|
|
|
|
info3 => 'x-vcg-info3', |
|
643
|
|
|
|
|
|
|
infoname1 => 'x-vcg-infoname1', |
|
644
|
|
|
|
|
|
|
infoname2 => 'x-vcg-infoname2', |
|
645
|
|
|
|
|
|
|
infoname3 => 'x-vcg-infoname3', |
|
646
|
|
|
|
|
|
|
level => 'x-vcg-level', |
|
647
|
|
|
|
|
|
|
loc => 'x-vcg-loc', |
|
648
|
|
|
|
|
|
|
layout_algorithm => 'x-vcg-layout_algorithm', |
|
649
|
|
|
|
|
|
|
# also allow this variant: |
|
650
|
|
|
|
|
|
|
layoutalgorithm => 'x-vcg-layout_algorithm', |
|
651
|
|
|
|
|
|
|
layout_downfactor => 'x-vcg-layout_downfactor', |
|
652
|
|
|
|
|
|
|
layout_upfactor => 'x-vcg-layout_upfactor', |
|
653
|
|
|
|
|
|
|
layout_nearfactor => 'x-vcg-layout_nearfactor', |
|
654
|
|
|
|
|
|
|
linear_segments => 'x-vcg-linear_segments', |
|
655
|
|
|
|
|
|
|
margin => 'x-vcg-margin', |
|
656
|
|
|
|
|
|
|
manhattan_edges => \&_manhattan_edges_from_vcg, |
|
657
|
|
|
|
|
|
|
near_edges => 'x-vcg-near_edges', |
|
658
|
|
|
|
|
|
|
nearedges => 'x-vcg-nearedges', |
|
659
|
|
|
|
|
|
|
node_alignment => 'x-vcg-node_alignment', |
|
660
|
|
|
|
|
|
|
port_sharing => \&_port_sharing_from_vcg, |
|
661
|
|
|
|
|
|
|
priority_phase => 'x-vcg-priority_phase', |
|
662
|
|
|
|
|
|
|
outport_sharing => \&_outport_sharing_from_vcg, |
|
663
|
|
|
|
|
|
|
shape => 'x-vcg-shape', |
|
664
|
|
|
|
|
|
|
smanhattan_edges => 'x-vcg-smanhattan_edges', |
|
665
|
|
|
|
|
|
|
state => 'x-vcg-state', |
|
666
|
|
|
|
|
|
|
splines => 'x-vcg-splines', |
|
667
|
|
|
|
|
|
|
splinefactor => 'x-vcg-splinefactor', |
|
668
|
|
|
|
|
|
|
spreadlevel => 'x-vcg-spreadlevel', |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
title => 'label', |
|
671
|
|
|
|
|
|
|
textmode => \&_textmode_from_vcg, |
|
672
|
|
|
|
|
|
|
useractioncmd1 => 'x-vcg-useractioncmd1', |
|
673
|
|
|
|
|
|
|
useractioncmd2 => 'x-vcg-useractioncmd2', |
|
674
|
|
|
|
|
|
|
useractioncmd3 => 'x-vcg-useractioncmd3', |
|
675
|
|
|
|
|
|
|
useractioncmd4 => 'x-vcg-useractioncmd4', |
|
676
|
|
|
|
|
|
|
useractionname1 => 'x-vcg-useractionname1', |
|
677
|
|
|
|
|
|
|
useractionname2 => 'x-vcg-useractionname2', |
|
678
|
|
|
|
|
|
|
useractionname3 => 'x-vcg-useractionname3', |
|
679
|
|
|
|
|
|
|
useractionname4 => 'x-vcg-useractionname4', |
|
680
|
|
|
|
|
|
|
vertical_order => 'x-vcg-vertical_order', |
|
681
|
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
display_edge_labels => 'x-vcg-display_edge_labels', |
|
683
|
|
|
|
|
|
|
edges => 'x-vcg-edges', |
|
684
|
|
|
|
|
|
|
nodes => 'x-vcg-nodes', |
|
685
|
|
|
|
|
|
|
icons => 'x-vcg-icons', |
|
686
|
|
|
|
|
|
|
iconcolors => 'x-vcg-iconcolors', |
|
687
|
|
|
|
|
|
|
view => 'x-vcg-view', |
|
688
|
|
|
|
|
|
|
subgraph_labels => 'x-vcg-subgraph_labels', |
|
689
|
|
|
|
|
|
|
arrow_mode => 'x-vcg-arrow_mode', |
|
690
|
|
|
|
|
|
|
arrowmode => 'x-vcg-arrowmode', |
|
691
|
|
|
|
|
|
|
crossing_optimization => 'x-vcg-crossing_optimization', |
|
692
|
|
|
|
|
|
|
crossing_phase2 => 'x-vcg-crossing_phase2', |
|
693
|
|
|
|
|
|
|
crossing_weight => 'x-vcg-crossing_weight', |
|
694
|
|
|
|
|
|
|
equal_y_dist => 'x-vcg-equal_y_dist', |
|
695
|
|
|
|
|
|
|
equalydist => 'x-vcg-equalydist', |
|
696
|
|
|
|
|
|
|
finetuning => 'x-vcg-finetuning', |
|
697
|
|
|
|
|
|
|
fstraight_phase => 'x-vcg-fstraight_phase', |
|
698
|
|
|
|
|
|
|
straight_phase => 'x-vcg-straight_phase', |
|
699
|
|
|
|
|
|
|
import_sharing => 'x-vcg-import_sharing', |
|
700
|
|
|
|
|
|
|
late_edge_labels => 'x-vcg-late_edge_labels', |
|
701
|
|
|
|
|
|
|
treefactor => 'x-vcg-treefactor', |
|
702
|
|
|
|
|
|
|
orientation => \&_orientation_from_vcg, |
|
703
|
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
attraction => 'x-vcg-attraction', |
|
705
|
|
|
|
|
|
|
'border x' => 'x-vcg-border-x', |
|
706
|
|
|
|
|
|
|
'border y' => 'x-vcg-border-y', |
|
707
|
|
|
|
|
|
|
'energetic' => 'x-vcg-energetic', |
|
708
|
|
|
|
|
|
|
'energetic attraction' => 'x-vcg-energetic-attraction', |
|
709
|
|
|
|
|
|
|
'energetic border' => 'x-vcg-energetic-border', |
|
710
|
|
|
|
|
|
|
'energetic crossing' => 'x-vcg-energetic-crossing', |
|
711
|
|
|
|
|
|
|
'energetic gravity' => 'x-vcg-energetic gravity', |
|
712
|
|
|
|
|
|
|
'energetic overlapping' => 'x-vcg-energetic overlapping', |
|
713
|
|
|
|
|
|
|
'energetic repulsion' => 'x-vcg-energetic repulsion', |
|
714
|
|
|
|
|
|
|
fdmax => 'x-vcg-fdmax', |
|
715
|
|
|
|
|
|
|
gravity => 'x-vcg-gravity', |
|
716
|
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
magnetic_field1 => 'x-vcg-magnetic_field1', |
|
718
|
|
|
|
|
|
|
magnetic_field2 => 'x-vcg-magnetic_field2', |
|
719
|
|
|
|
|
|
|
magnetic_force1 => 'x-vcg-magnetic_force1', |
|
720
|
|
|
|
|
|
|
magnetic_force2 => 'x-vcg-magnetic_force2', |
|
721
|
|
|
|
|
|
|
randomfactor => 'x-vcg-randomfactor', |
|
722
|
|
|
|
|
|
|
randomimpulse => 'x-vcg-randomimpulse', |
|
723
|
|
|
|
|
|
|
randomrounds => 'x-vcg-randomrounds', |
|
724
|
|
|
|
|
|
|
repulsion => 'x-vcg-repulsion', |
|
725
|
|
|
|
|
|
|
tempfactor => 'x-vcg-tempfactor', |
|
726
|
|
|
|
|
|
|
tempmax => 'x-vcg-tempmax', |
|
727
|
|
|
|
|
|
|
tempmin => 'x-vcg-tempmin'. |
|
728
|
|
|
|
|
|
|
tempscheme => 'x-vcg-tempscheme'. |
|
729
|
|
|
|
|
|
|
temptreshold => 'x-vcg-temptreshold', |
|
730
|
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
dirty_edge_labels => 'x-vcg-dirty_edge_labels', |
|
732
|
|
|
|
|
|
|
fast_icons => 'x-vcg-fast_icons', |
|
733
|
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
}, |
|
735
|
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
'group' => { |
|
737
|
|
|
|
|
|
|
# graph attributes will be added here automatically |
|
738
|
|
|
|
|
|
|
title => \&_group_name_from_vcg, |
|
739
|
|
|
|
|
|
|
status => 'x-vcg-status', |
|
740
|
|
|
|
|
|
|
}, |
|
741
|
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
'all' => { |
|
743
|
|
|
|
|
|
|
loc => 'x-vcg-loc', |
|
744
|
|
|
|
|
|
|
folding => 'x-vcg-folding', |
|
745
|
|
|
|
|
|
|
scaling => 'x-vcg-scaling', |
|
746
|
|
|
|
|
|
|
shrink => 'x-vcg-shrink', |
|
747
|
|
|
|
|
|
|
stretch => 'x-vcg-stretch', |
|
748
|
|
|
|
|
|
|
width => 'x-vcg-width', |
|
749
|
|
|
|
|
|
|
height => 'x-vcg-height', |
|
750
|
|
|
|
|
|
|
fontname => 'font', |
|
751
|
|
|
|
|
|
|
}, |
|
752
|
|
|
|
|
|
|
}; |
|
753
|
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
{ |
|
755
|
|
|
|
|
|
|
# add all graph attributes to group, too |
|
756
|
|
|
|
|
|
|
my $group = $vcg_remap->{group}; |
|
757
|
|
|
|
|
|
|
my $graph = $vcg_remap->{graph}; |
|
758
|
|
|
|
|
|
|
for my $k (sort keys %$graph) |
|
759
|
|
|
|
|
|
|
{ |
|
760
|
|
|
|
|
|
|
$group->{$k} = $graph->{$k}; |
|
761
|
|
|
|
|
|
|
} |
|
762
|
|
|
|
|
|
|
} |
|
763
|
|
|
|
|
|
|
|
|
764
|
57
|
|
|
57
|
|
128
|
sub _remap { $vcg_remap; } |
|
765
|
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
my $vcg_edge_color_remap = { |
|
767
|
|
|
|
|
|
|
textcolor => 'labelcolor', |
|
768
|
|
|
|
|
|
|
}; |
|
769
|
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
my $vcg_node_color_remap = { |
|
771
|
|
|
|
|
|
|
textcolor => 'color', |
|
772
|
|
|
|
|
|
|
color => 'fill', |
|
773
|
|
|
|
|
|
|
}; |
|
774
|
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
sub _vertical_order_from_vcg |
|
776
|
|
|
|
|
|
|
{ |
|
777
|
|
|
|
|
|
|
# remap "vertical_order: 5" to "rank: 5" |
|
778
|
1
|
|
|
1
|
|
3
|
my ($graph, $name, $value) = @_; |
|
779
|
|
|
|
|
|
|
|
|
780
|
1
|
|
|
|
|
2
|
my $rank = $value; |
|
781
|
|
|
|
|
|
|
# insert a really really high rank |
|
782
|
1
|
50
|
|
|
|
4
|
$rank = '1000000' if $value eq 'maxdepth'; |
|
783
|
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
# save the original value, too |
|
785
|
1
|
|
|
|
|
5
|
('x-vcg-vertical_order', $value, 'rank', $rank); |
|
786
|
|
|
|
|
|
|
} |
|
787
|
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
sub _horizontal_order_from_vcg |
|
789
|
|
|
|
|
|
|
{ |
|
790
|
|
|
|
|
|
|
# remap "horizontal_order: 5" to "rank: 5" |
|
791
|
0
|
|
|
0
|
|
0
|
my ($graph, $name, $value) = @_; |
|
792
|
|
|
|
|
|
|
|
|
793
|
0
|
|
|
|
|
0
|
my $rank = $value; |
|
794
|
|
|
|
|
|
|
# insert a really really high rank |
|
795
|
0
|
0
|
|
|
|
0
|
$rank = '1000000' if $value eq 'maxdepth'; |
|
796
|
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
# save the original value, too |
|
798
|
0
|
|
|
|
|
0
|
('x-vcg-horizontal_order', $value, 'rank', $rank); |
|
799
|
|
|
|
|
|
|
} |
|
800
|
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
sub _invisible_from_vcg |
|
802
|
|
|
|
|
|
|
{ |
|
803
|
|
|
|
|
|
|
# remap "invisible: yes" to "shape: invisible" |
|
804
|
1
|
|
|
1
|
|
3
|
my ($graph, $name, $value) = @_; |
|
805
|
|
|
|
|
|
|
|
|
806
|
1
|
50
|
|
|
|
6
|
return (undef,undef) if $value ne 'yes'; |
|
807
|
|
|
|
|
|
|
|
|
808
|
1
|
|
|
|
|
4
|
('shape', 'invisible'); |
|
809
|
|
|
|
|
|
|
} |
|
810
|
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
sub _manhattan_edges_from_vcg |
|
812
|
|
|
|
|
|
|
{ |
|
813
|
|
|
|
|
|
|
# remap "manhattan_edges: yes" for graphs |
|
814
|
0
|
|
|
0
|
|
0
|
my ($graph, $name, $value) = @_; |
|
815
|
|
|
|
|
|
|
|
|
816
|
0
|
0
|
|
|
|
0
|
if ($value eq 'yes') |
|
817
|
|
|
|
|
|
|
{ |
|
818
|
0
|
|
|
|
|
0
|
$graph->set_attribute('edge','start','front'); |
|
819
|
0
|
|
|
|
|
0
|
$graph->set_attribute('edge','end','back'); |
|
820
|
|
|
|
|
|
|
} |
|
821
|
|
|
|
|
|
|
# store the value for proper VCG output |
|
822
|
0
|
|
|
|
|
0
|
('x-vcg-' . $name, $value); |
|
823
|
|
|
|
|
|
|
} |
|
824
|
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
sub _textmode_from_vcg |
|
826
|
|
|
|
|
|
|
{ |
|
827
|
|
|
|
|
|
|
# remap "textmode: left_justify" to "align: left;" |
|
828
|
0
|
|
|
0
|
|
0
|
my ($graph, $name, $align) = @_; |
|
829
|
|
|
|
|
|
|
|
|
830
|
0
|
|
|
|
|
0
|
$align =~ s/_.*//; # left_justify => left |
|
831
|
|
|
|
|
|
|
|
|
832
|
0
|
|
|
|
|
0
|
('align', lc($align)); |
|
833
|
|
|
|
|
|
|
} |
|
834
|
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
sub _edge_color_from_vcg |
|
836
|
|
|
|
|
|
|
{ |
|
837
|
|
|
|
|
|
|
# remap "darkyellow" to "rgb(128 128 0)" |
|
838
|
2
|
|
|
2
|
|
5
|
my ($graph, $name, $color) = @_; |
|
839
|
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
# print STDERR "edge $name $color\n"; |
|
841
|
|
|
|
|
|
|
# print STDERR ($vcg_edge_color_remap->{$name} || $name, " ", $vcg_color_by_name->{$color} || $color), "\n"; |
|
842
|
|
|
|
|
|
|
|
|
843
|
2
|
|
33
|
|
|
9
|
my $c = $vcg_color_by_name->{$color} || $color; |
|
844
|
2
|
50
|
33
|
|
|
9
|
$c = $graph->{_vcg_color_map}->[$c] if $c =~ /^[0-9]+\z/ && $c < 256; |
|
845
|
|
|
|
|
|
|
|
|
846
|
2
|
|
33
|
|
|
16
|
($vcg_edge_color_remap->{$name} || $name, $c); |
|
847
|
|
|
|
|
|
|
} |
|
848
|
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
sub _edge_class_from_vcg |
|
850
|
|
|
|
|
|
|
{ |
|
851
|
|
|
|
|
|
|
# remap "1" to "edgeclass1" to create a valid class name |
|
852
|
3
|
|
|
3
|
|
7
|
my ($graph, $name, $class) = @_; |
|
853
|
|
|
|
|
|
|
|
|
854
|
3
|
50
|
66
|
|
|
29
|
$class = $graph->{_vcg_class_names}->{$class} || ('edgeclass' . $class) if $class =~ /^[0-9]+\z/; |
|
855
|
|
|
|
|
|
|
#$class = 'edgeclass' . $class if $class !~ /^[a-zA-Z]/; |
|
856
|
|
|
|
|
|
|
|
|
857
|
3
|
|
|
|
|
13
|
('class', $class); |
|
858
|
|
|
|
|
|
|
} |
|
859
|
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
my $vcg_orientation = { |
|
861
|
|
|
|
|
|
|
top_to_bottom => 'south', |
|
862
|
|
|
|
|
|
|
bottom_to_top => 'north', |
|
863
|
|
|
|
|
|
|
left_to_right => 'east', |
|
864
|
|
|
|
|
|
|
right_to_left => 'west', |
|
865
|
|
|
|
|
|
|
}; |
|
866
|
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
sub _orientation_from_vcg |
|
868
|
|
|
|
|
|
|
{ |
|
869
|
4
|
|
|
4
|
|
10
|
my ($graph, $name, $value) = @_; |
|
870
|
|
|
|
|
|
|
|
|
871
|
4
|
|
50
|
|
|
35
|
('flow', $vcg_orientation->{$value} || 'south'); |
|
872
|
|
|
|
|
|
|
} |
|
873
|
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
sub _port_sharing_from_vcg |
|
875
|
|
|
|
|
|
|
{ |
|
876
|
|
|
|
|
|
|
# if we see this, add autojoin/autosplit |
|
877
|
0
|
|
|
0
|
|
0
|
my ($graph, $name, $value) = @_; |
|
878
|
|
|
|
|
|
|
|
|
879
|
0
|
0
|
|
|
|
0
|
$value = ($value =~ /yes/i) ? 'yes' : 'no'; |
|
880
|
|
|
|
|
|
|
|
|
881
|
0
|
|
|
|
|
0
|
('autojoin', $value, 'autosplit', $value); |
|
882
|
|
|
|
|
|
|
} |
|
883
|
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
sub _inport_sharing_from_vcg |
|
885
|
|
|
|
|
|
|
{ |
|
886
|
|
|
|
|
|
|
# if we see this, add autojoin/autosplit |
|
887
|
0
|
|
|
0
|
|
0
|
my ($graph, $name, $value) = @_; |
|
888
|
|
|
|
|
|
|
|
|
889
|
0
|
0
|
|
|
|
0
|
$value = ($value =~ /yes/i) ? 'yes' : 'no'; |
|
890
|
|
|
|
|
|
|
|
|
891
|
0
|
|
|
|
|
0
|
('autojoin', $value); |
|
892
|
|
|
|
|
|
|
} |
|
893
|
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
sub _outport_sharing_from_vcg |
|
895
|
|
|
|
|
|
|
{ |
|
896
|
|
|
|
|
|
|
# if we see this, add autojoin/autosplit |
|
897
|
0
|
|
|
0
|
|
0
|
my ($graph, $name, $value) = @_; |
|
898
|
|
|
|
|
|
|
|
|
899
|
0
|
0
|
|
|
|
0
|
$value = ($value =~ /yes/i) ? 'yes' : 'no'; |
|
900
|
|
|
|
|
|
|
|
|
901
|
0
|
|
|
|
|
0
|
('autosplit', $value); |
|
902
|
|
|
|
|
|
|
} |
|
903
|
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
sub _node_color_from_vcg |
|
905
|
|
|
|
|
|
|
{ |
|
906
|
|
|
|
|
|
|
# remap "darkyellow" to "rgb(128 128 0)" |
|
907
|
7
|
|
|
7
|
|
14
|
my ($graph, $name, $color) = @_; |
|
908
|
|
|
|
|
|
|
|
|
909
|
7
|
|
66
|
|
|
34
|
my $c = $vcg_color_by_name->{$color} || $color; |
|
910
|
7
|
100
|
66
|
|
|
52
|
$c = $graph->{_vcg_color_map}->[$c] if $c =~ /^[0-9]+\z/ && $c < 256; |
|
911
|
|
|
|
|
|
|
|
|
912
|
7
|
|
33
|
|
|
40
|
($vcg_node_color_remap->{$name} || $name, $c); |
|
913
|
|
|
|
|
|
|
} |
|
914
|
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
my $shapes = { |
|
916
|
|
|
|
|
|
|
box => 'rect', |
|
917
|
|
|
|
|
|
|
rhomb => 'diamond', |
|
918
|
|
|
|
|
|
|
triangle => 'triangle', |
|
919
|
|
|
|
|
|
|
ellipse => 'ellipse', |
|
920
|
|
|
|
|
|
|
circle => 'circle', |
|
921
|
|
|
|
|
|
|
hexagon => 'hexagon', |
|
922
|
|
|
|
|
|
|
trapeze => 'trapezium', |
|
923
|
|
|
|
|
|
|
uptrapeze => 'invtrapezium', |
|
924
|
|
|
|
|
|
|
lparallelogram => 'invparallelogram', |
|
925
|
|
|
|
|
|
|
rparallelogram => 'parallelogram', |
|
926
|
|
|
|
|
|
|
}; |
|
927
|
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
sub _vcg_node_shape |
|
929
|
|
|
|
|
|
|
{ |
|
930
|
2
|
|
|
2
|
|
5
|
my ($self, $name, $shape) = @_; |
|
931
|
|
|
|
|
|
|
|
|
932
|
2
|
|
|
|
|
5
|
my @rc; |
|
933
|
2
|
|
|
|
|
5
|
my $s = lc($shape); |
|
934
|
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
# map the name to what Graph::Easy expects (ellipse stays as ellipse but |
|
936
|
|
|
|
|
|
|
# everything unknown gets converted to rect) |
|
937
|
2
|
|
50
|
|
|
11
|
$s = $shapes->{$s} || 'rect'; |
|
938
|
|
|
|
|
|
|
|
|
939
|
2
|
|
|
|
|
9
|
(@rc, $name, $s); |
|
940
|
|
|
|
|
|
|
} |
|
941
|
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
sub _group_name_from_vcg |
|
943
|
|
|
|
|
|
|
{ |
|
944
|
0
|
|
|
0
|
|
0
|
my ($self, $attr, $name, $object) = @_; |
|
945
|
|
|
|
|
|
|
|
|
946
|
0
|
0
|
|
|
|
0
|
print STDERR "# Renaming anon group '$object->{name}' to '$name'\n" |
|
947
|
|
|
|
|
|
|
if $self->{debug} > 0; |
|
948
|
|
|
|
|
|
|
|
|
949
|
0
|
|
|
|
|
0
|
$self->rename_group($object, $name); |
|
950
|
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
# name was set, so drop the "title: name" pair |
|
952
|
0
|
|
|
|
|
0
|
(undef, undef); |
|
953
|
|
|
|
|
|
|
} |
|
954
|
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
############################################################################# |
|
956
|
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
sub _remap_attributes |
|
958
|
|
|
|
|
|
|
{ |
|
959
|
57
|
|
|
57
|
|
115
|
my ($self, $att, $object, $r) = @_; |
|
960
|
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
# print STDERR "# Remapping attributes\n"; |
|
962
|
|
|
|
|
|
|
# use Data::Dumper; print Dumper($att); |
|
963
|
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
# handle the "colorentry 00" entries: |
|
965
|
57
|
|
|
|
|
232
|
for my $key (sort keys %$att) |
|
966
|
|
|
|
|
|
|
{ |
|
967
|
87
|
100
|
|
|
|
197
|
if ($key =~ /^colorentry\s+([0-9]{1,2})/) |
|
968
|
|
|
|
|
|
|
{ |
|
969
|
|
|
|
|
|
|
# put the color into the current color map |
|
970
|
2
|
|
|
|
|
10
|
$self->_vcg_color_map_entry($1, $att->{$key}); |
|
971
|
2
|
|
|
|
|
3
|
delete $att->{$key}; |
|
972
|
2
|
|
|
|
|
5
|
next; |
|
973
|
|
|
|
|
|
|
} |
|
974
|
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
# remap \fi065 to 'A' |
|
976
|
85
|
|
|
|
|
155
|
$att->{$key} =~ s/(\x0c|\\f)i([0-9]{3})/ decode('iso-8859-1', chr($2)); /eg; |
|
|
2
|
|
|
|
|
19
|
|
|
977
|
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
# XXX TDOO: support inline colorations |
|
979
|
|
|
|
|
|
|
# remap \f65 to '' |
|
980
|
85
|
|
|
|
|
233
|
$att->{$key} =~ s/(\x0c|\\f)([0-9]{2})//g; |
|
981
|
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
# remap \c09 to color 09: TODO for now remove |
|
983
|
85
|
|
|
|
|
136
|
$att->{$key} =~ s/(\x0c|\\f)([0-9]{2})//g; |
|
984
|
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
# XXX TODO: support real hor lines |
|
986
|
|
|
|
|
|
|
# insert a fake |
|
987
|
85
|
|
|
|
|
182
|
$att->{$key} =~ s/(\x0c|\\f)-/\\c ---- \\n /g; |
|
988
|
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
} |
|
990
|
57
|
|
|
|
|
452
|
$self->SUPER::_remap_attributes($att,$object,$r); |
|
991
|
|
|
|
|
|
|
} |
|
992
|
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
############################################################################# |
|
994
|
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
sub _parser_cleanup |
|
996
|
|
|
|
|
|
|
{ |
|
997
|
|
|
|
|
|
|
# After initial parsing, do cleanup. |
|
998
|
13
|
|
|
13
|
|
22
|
my ($self) = @_; |
|
999
|
|
|
|
|
|
|
|
|
1000
|
13
|
|
|
|
|
24
|
my $g = $self->{_graph}; |
|
1001
|
13
|
|
|
|
|
26
|
$g->{_warn_on_unknown_attributes} = 0; # reset to die again |
|
1002
|
|
|
|
|
|
|
|
|
1003
|
13
|
|
|
|
|
177
|
delete $g->{_vcg_color_map}; |
|
1004
|
13
|
|
|
|
|
37
|
delete $g->{_vcg_class_names}; |
|
1005
|
|
|
|
|
|
|
|
|
1006
|
13
|
|
|
|
|
31
|
$self; |
|
1007
|
|
|
|
|
|
|
} |
|
1008
|
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
1; |
|
1010
|
|
|
|
|
|
|
__END__ |