ruby-graphviz_c 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +7 -0
  2. data/.gemrc +0 -0
  3. data/.gitignore +9 -0
  4. data/.travis.yml +7 -0
  5. data/AUTHORS.rdoc +33 -0
  6. data/CHANGELOG.rdoc +287 -0
  7. data/COPYING.rdoc +133 -0
  8. data/Gemfile +4 -0
  9. data/README.rdoc +206 -0
  10. data/Rakefile +71 -0
  11. data/bin/dot2ruby +91 -0
  12. data/bin/gem2gv +165 -0
  13. data/bin/git2gv +167 -0
  14. data/bin/ruby2gv +234 -0
  15. data/bin/xml2gv +96 -0
  16. data/examples/dot/JSP.dot +52 -0
  17. data/examples/dot/balanced.dot +36 -0
  18. data/examples/dot/cluster.dot +30 -0
  19. data/examples/dot/dotgraph.dot +28 -0
  20. data/examples/dot/fsm.dot +20 -0
  21. data/examples/dot/genetic.dot +118 -0
  22. data/examples/dot/hello.dot +1 -0
  23. data/examples/dot/hello_test.rb +33 -0
  24. data/examples/dot/lion_share.dot +103 -0
  25. data/examples/dot/prof.dot +150 -0
  26. data/examples/dot/psg.dot +28 -0
  27. data/examples/dot/rank.dot +6 -0
  28. data/examples/dot/sdh.dot +284 -0
  29. data/examples/dot/siblings.dot +492 -0
  30. data/examples/dot/so-sample001.gv +30 -0
  31. data/examples/dot/so-sample002.gv +33 -0
  32. data/examples/dot/so-sample003.gv +45 -0
  33. data/examples/dot/test.dot +17 -0
  34. data/examples/dot/test_parse.rb +13 -0
  35. data/examples/dot/this_crach_with_dot_2.20.dot +24 -0
  36. data/examples/dot/unix.dot +104 -0
  37. data/examples/graphml/attributes.ext.graphml +12 -0
  38. data/examples/graphml/attributes.graphml +40 -0
  39. data/examples/graphml/cluster.graphml +75 -0
  40. data/examples/graphml/failed_graph.graphml +461 -0
  41. data/examples/graphml/hyper.graphml +29 -0
  42. data/examples/graphml/nested.graphml +54 -0
  43. data/examples/graphml/port.graphml +32 -0
  44. data/examples/graphml/simple.graphml +30 -0
  45. data/examples/hello.png +0 -0
  46. data/examples/rgv/rgv.ps +125 -0
  47. data/examples/rgv/test_rgv.rb +12 -0
  48. data/examples/sample01.rb +32 -0
  49. data/examples/sample02.rb +42 -0
  50. data/examples/sample03.rb +31 -0
  51. data/examples/sample04.rb +22 -0
  52. data/examples/sample05.rb +32 -0
  53. data/examples/sample06.rb +46 -0
  54. data/examples/sample07.rb +23 -0
  55. data/examples/sample08.rb +34 -0
  56. data/examples/sample09.rb +50 -0
  57. data/examples/sample10.rb +50 -0
  58. data/examples/sample11.rb +42 -0
  59. data/examples/sample12.rb +55 -0
  60. data/examples/sample13.rb +48 -0
  61. data/examples/sample14.rb +44 -0
  62. data/examples/sample15.rb +25 -0
  63. data/examples/sample16.rb +8 -0
  64. data/examples/sample17.rb +92 -0
  65. data/examples/sample18.rb +24 -0
  66. data/examples/sample19.rb +59 -0
  67. data/examples/sample20.rb +47 -0
  68. data/examples/sample21.rb +12 -0
  69. data/examples/sample22.rb +10 -0
  70. data/examples/sample23.rb +11 -0
  71. data/examples/sample24.rb +11 -0
  72. data/examples/sample25.rb +11 -0
  73. data/examples/sample26.rb +8 -0
  74. data/examples/sample27.rb +8 -0
  75. data/examples/sample28.rb +12 -0
  76. data/examples/sample29.rb +8 -0
  77. data/examples/sample30.rb +12 -0
  78. data/examples/sample31.rb +10 -0
  79. data/examples/sample32.rb +14 -0
  80. data/examples/sample33.rb +43 -0
  81. data/examples/sample34.rb +29 -0
  82. data/examples/sample35.rb +43 -0
  83. data/examples/sample36.rb +35 -0
  84. data/examples/sample37.rb +87 -0
  85. data/examples/sample38.rb +12 -0
  86. data/examples/sample39.rb +11 -0
  87. data/examples/sample40.rb +17 -0
  88. data/examples/sample41.rb +8 -0
  89. data/examples/sample42.rb +35 -0
  90. data/examples/sample43.rb +26 -0
  91. data/examples/sample44.rb +97 -0
  92. data/examples/sample45.rb +24 -0
  93. data/examples/sample46.rb +43 -0
  94. data/examples/sample47.rb +7 -0
  95. data/examples/sample48.rb +62 -0
  96. data/examples/sample49.rb +10 -0
  97. data/examples/sample50.rb +215 -0
  98. data/examples/sample51.rb +37 -0
  99. data/examples/sample52.rb +62 -0
  100. data/examples/sample53.rb +26 -0
  101. data/examples/sample54.rb +26 -0
  102. data/examples/sample55.rb +9 -0
  103. data/examples/sample56.rb +10 -0
  104. data/examples/sample57.rb +8 -0
  105. data/examples/sample58.rb +33 -0
  106. data/examples/sample59.rb +14 -0
  107. data/examples/sample60.rb +12 -0
  108. data/examples/sample61.rb +12 -0
  109. data/examples/sample62.rb +24 -0
  110. data/examples/sample63.rb +32 -0
  111. data/examples/sample64.rb +31 -0
  112. data/examples/sample65.rb +9 -0
  113. data/examples/sample66.rb +4 -0
  114. data/examples/sample67.rb +10 -0
  115. data/examples/sample68.rb +27 -0
  116. data/examples/sample69.rb +23 -0
  117. data/examples/sample70.rb +9 -0
  118. data/examples/sample99.rb +70 -0
  119. data/examples/sdlshapes/README +2 -0
  120. data/examples/sdlshapes/sdl.ps +655 -0
  121. data/examples/sdlshapes/sdlshapes.dot +78 -0
  122. data/examples/test.xml +26 -0
  123. data/examples/theory/pert.rb +47 -0
  124. data/examples/theory/tests.rb +87 -0
  125. data/lib/ext/gvpr/dot2ruby.g +185 -0
  126. data/lib/graphviz/attrs.rb +73 -0
  127. data/lib/graphviz/constants.rb +294 -0
  128. data/lib/graphviz/core_ext.rb +64 -0
  129. data/lib/graphviz/dot2ruby.rb +59 -0
  130. data/lib/graphviz/dot_script.rb +109 -0
  131. data/lib/graphviz/dsl.rb +67 -0
  132. data/lib/graphviz/edge.rb +197 -0
  133. data/lib/graphviz/elements.rb +39 -0
  134. data/lib/graphviz/ext.rb +17 -0
  135. data/lib/graphviz/family_tree/couple.rb +63 -0
  136. data/lib/graphviz/family_tree/generation.rb +39 -0
  137. data/lib/graphviz/family_tree/person.rb +120 -0
  138. data/lib/graphviz/family_tree/sibling.rb +13 -0
  139. data/lib/graphviz/family_tree.rb +118 -0
  140. data/lib/graphviz/graphml.rb +268 -0
  141. data/lib/graphviz/math/matrix.rb +221 -0
  142. data/lib/graphviz/node.rb +160 -0
  143. data/lib/graphviz/nothugly/nothugly.xsl +321 -0
  144. data/lib/graphviz/nothugly.rb +63 -0
  145. data/lib/graphviz/theory.rb +321 -0
  146. data/lib/graphviz/types/arrow_type.rb +32 -0
  147. data/lib/graphviz/types/color.rb +58 -0
  148. data/lib/graphviz/types/color_list.rb +24 -0
  149. data/lib/graphviz/types/esc_string.rb +20 -0
  150. data/lib/graphviz/types/gv_bool.rb +49 -0
  151. data/lib/graphviz/types/gv_double.rb +32 -0
  152. data/lib/graphviz/types/html_string.rb +18 -0
  153. data/lib/graphviz/types/lbl_string.rb +22 -0
  154. data/lib/graphviz/types/rect.rb +35 -0
  155. data/lib/graphviz/types/spline_type.rb +77 -0
  156. data/lib/graphviz/types.rb +22 -0
  157. data/lib/graphviz/utils/colors.rb +1018 -0
  158. data/lib/graphviz/utils.rb +70 -0
  159. data/lib/graphviz/xml.rb +119 -0
  160. data/lib/graphviz.rb +967 -0
  161. data/lib/ruby-graphviz.rb +1 -0
  162. data/man/dot2ruby.1 +66 -0
  163. data/man/dot2ruby.1.ronn +55 -0
  164. data/man/gem2gv.1 +60 -0
  165. data/man/gem2gv.1.ronn +47 -0
  166. data/man/git2gv.1 +48 -0
  167. data/man/git2gv.1.ronn +40 -0
  168. data/man/ruby2gv.1 +60 -0
  169. data/man/ruby2gv.1.ronn +47 -0
  170. data/man/xml2gv.1 +48 -0
  171. data/man/xml2gv.1.ronn +39 -0
  172. data/ruby-graphviz.gemspec +47 -0
  173. data/setup.rb +1585 -0
  174. data/test/helper.rb +13 -0
  175. data/test/support.rb +95 -0
  176. data/test/test_dot_script.rb +47 -0
  177. data/test/test_examples.rb +151 -0
  178. data/test/test_graph.rb +115 -0
  179. data/test/test_search.rb +29 -0
  180. data/test/test_subgraph.rb +27 -0
  181. data/test/test_theory.rb +98 -0
  182. data/test/test_types.rb +65 -0
  183. data/test/test_utils_colors.rb +52 -0
  184. metadata +301 -0
@@ -0,0 +1,63 @@
1
+ # This file use notugly.xsl: An XSL transform to pretty up the SVG output from Graphviz
2
+ #
3
+ # See: http://www.hokstad.com/making-graphviz-output-pretty-with-xsl.html
4
+ # And: http://www.hokstad.com/making-graphviz-output-pretty-with-xsl-updated.html
5
+ #
6
+ # By Vidar Hokstad and Ryan Shea; Contributions by Jonas Tingborn,
7
+ # Earl Cummings, Michael Kennedy (Graphviz 2.20.2 compatibility, bug fixes,
8
+ # testing, lots of gradients)
9
+
10
+ require 'rubygems'
11
+ begin
12
+ require 'xml/xslt'
13
+ XSLT_METHOD = :xml_xslt_transform
14
+ rescue LoadError => e
15
+ require 'libxml'
16
+ require 'libxslt'
17
+ XSLT_METHOD = :libxslt_transform
18
+ end
19
+
20
+ class GraphViz
21
+ # Transform to pretty up the SVG output
22
+ #
23
+ # For more information, see http://www.hokstad.com/making-graphviz-output-pretty-with-xsl.html
24
+ # and http://www.hokstad.com/making-graphviz-output-pretty-with-xsl-updated.html
25
+ #
26
+ # You can use the :nothugly option to GraphViz#output :
27
+ #
28
+ # graph.output( :svg => "myGraph.svg", :nothugly => true )
29
+ #
30
+ # Or directly on an SVG output graph :
31
+ #
32
+ # GraphViz.nothugly( "myGraph.svg" )
33
+ def self.nothugly( file, save = true )
34
+ xsl = File.join( File.dirname(File.expand_path(__FILE__)), "nothugly", "nothugly.xsl" )
35
+ out = self.send(XSLT_METHOD, file, xsl)
36
+
37
+ if save
38
+ fname = File.join( File.dirname(File.expand_path(file)), File.basename(file))
39
+ File.open( fname, "w" ) { |io|
40
+ io.print out
41
+ }
42
+ else
43
+ return out
44
+ end
45
+ end
46
+
47
+ def self.xml_xslt_transform(xml, xsl)
48
+ xslt = XML::XSLT.new()
49
+ xslt.xml = xml
50
+ xslt.xsl = xsl
51
+ xslt.serve()
52
+ end
53
+
54
+ def self.libxslt_transform(xml, xsl)
55
+ LibXML::XML.default_load_external_dtd = false
56
+ LibXML::XML.default_substitute_entities = false
57
+
58
+ stylesheet_doc = LibXML::XML::Document.file(xsl)
59
+ stylesheet = LibXSLT::XSLT::Stylesheet.new(stylesheet_doc)
60
+ xml_doc = LibXML::XML::Document.file(xml)
61
+ stylesheet.apply(xml_doc).to_s
62
+ end
63
+ end
@@ -0,0 +1,321 @@
1
+ require 'graphviz/math/matrix'
2
+
3
+ class GraphViz
4
+ class Theory
5
+ def initialize( graph )
6
+ @graph = graph
7
+ end
8
+
9
+ # Return the adjancy matrix of the graph
10
+ def adjancy_matrix
11
+ matrix = GraphViz::Math::Matrix.new( @graph.node_count, @graph.node_count )
12
+
13
+ @graph.each_edge { |e|
14
+ x = @graph.get_node(e.node_one( false )).index
15
+ y = @graph.get_node(e.node_two( false )).index
16
+ matrix[x+1, y+1] = 1
17
+ matrix[y+1, x+1] = 1 if @graph.type == "graph"
18
+ }
19
+
20
+ return matrix
21
+ end
22
+
23
+ # Return the incidence matrix of the graph
24
+ def incidence_matrix
25
+ tail = (@graph.type == "digraph") ? -1 : 1
26
+ matrix = GraphViz::Math::Matrix.new( @graph.node_count, @graph.edge_count )
27
+
28
+ @graph.each_edge { |e|
29
+ x = e.index
30
+
31
+ nstart = @graph.get_node(e.node_one( false )).index
32
+ nend = @graph.get_node(e.node_two( false )).index
33
+
34
+ matrix[nstart+1, x+1] = 1
35
+ matrix[nend+1, x+1] = tail
36
+ matrix[nend+1, x+1] = 2 if nstart == nend
37
+ }
38
+
39
+ return matrix
40
+ end
41
+
42
+ # Return the degree of the given node
43
+ def degree( node )
44
+ degree = 0
45
+ name = node
46
+ if node.kind_of?(GraphViz::Node)
47
+ name = node.id
48
+ end
49
+
50
+ @graph.each_edge do |e|
51
+ degree += 1 if e.node_one(false) == name or e.node_two(false) == name
52
+ end
53
+
54
+ return degree
55
+ end
56
+
57
+ # Return the laplacian matrix of the graph
58
+ def laplacian_matrix
59
+ return degree_matrix - adjancy_matrix
60
+ end
61
+
62
+ # Return <tt>true</tt> if the graph if symmetric, <tt>false</tt> otherwise
63
+ def symmetric?
64
+ adjancy_matrix == adjancy_matrix.transpose
65
+ end
66
+
67
+ # moore_dijkstra(source, destination)
68
+ def moore_dijkstra( dep, arv )
69
+ dep = @graph.get_node(dep) unless dep.kind_of?(GraphViz::Node)
70
+ arv = @graph.get_node(arv) unless arv.kind_of?(GraphViz::Node)
71
+
72
+ m = distance_matrix
73
+ n = @graph.node_count
74
+ # Table des sommets à choisir
75
+ c = [dep.index]
76
+ # Table des distances
77
+ d = []
78
+ d[dep.index] = 0
79
+
80
+ # Table des predecesseurs
81
+ pred = []
82
+
83
+ @graph.each_node do |name, k|
84
+ if k != dep
85
+ d[k.index] = m[dep.index+1,k.index+1]
86
+ pred[k.index] = dep
87
+ end
88
+ end
89
+
90
+ while c.size < n
91
+ # trouver y tel que d[y] = min{d[k]; k sommet tel que k n'appartient pas à c}
92
+ mini = 1.0/0.0
93
+ y = nil
94
+ @graph.each_node do |name, k|
95
+ next if c.include?(k.index)
96
+ if d[k.index] < mini
97
+ mini = d[k.index]
98
+ y = k
99
+ end
100
+ end
101
+
102
+ # si ce minimum est ∞ alors sortir de la boucle fin si
103
+ break unless mini.to_f.infinite?.nil?
104
+
105
+ c << y.index
106
+ @graph.each_node do |name, k|
107
+ next if c.include?(k.index)
108
+ if d[k.index] > d[y.index] + m[y.index+1,k.index+1]
109
+ d[k.index] = d[y.index] + m[y.index+1,k.index+1]
110
+ pred[k.index] = y
111
+ end
112
+ end
113
+ end
114
+
115
+ # Construction du chemin le plus court
116
+ ch = []
117
+ k = arv
118
+ while k.index != dep.index
119
+ ch.unshift(k)
120
+ k = pred[k.index]
121
+ end
122
+ ch.unshift(dep)
123
+
124
+ if d[arv.index].to_f.infinite?
125
+ return nil
126
+ else
127
+ return( {
128
+ :path => ch,
129
+ :distance => d[arv.index]
130
+ } )
131
+ end
132
+ end
133
+
134
+ # Return a liste of range
135
+ #
136
+ # If the returned array include nil values, there is one or more circuits in the graph
137
+ def range
138
+ matrix = adjancy_matrix
139
+ unseen = (1..matrix.columns).to_a
140
+ result = Array.new(matrix.columns)
141
+ r = 0
142
+
143
+ range_recursion( matrix, unseen, result, r )
144
+ end
145
+
146
+ # Return the critical path for a PERT network
147
+ #
148
+ # If the given graph is not a PERT network, return nul
149
+ def critical_path
150
+ return nil if range.include?(nil) or @graph.type != "digraph"
151
+ r = [ [0, [1]] ]
152
+
153
+ critical_path_recursion( distance_matrix, adjancy_matrix, r, [], 0 ).inject( {:distance => 0, :path => []} ) { |_r, item|
154
+ (_r[:distance] < item[0]) ? { :distance => item[0], :path => item[1] } : _r
155
+ }
156
+ end
157
+
158
+ # Return the PageRank in an directed graph.
159
+ #
160
+ # * damping_factor: PageRank dumping factor.
161
+ # * max_iterations: Maximum number of iterations.
162
+ # * min_delta: Smallest variation required to have a new iteration.
163
+ def pagerank(damping_factor = 0.85, max_iterations = 100, min_delta = 0.00001)
164
+ return nil unless @graph.directed?
165
+
166
+ min_value = (1.0-damping_factor)/@graph.node_count
167
+
168
+ pagerank = {}
169
+ @graph.each_node { |_, node|
170
+ pagerank[node] = 1.0/@graph.node_count
171
+ }
172
+
173
+ max_iterations.times { |_|
174
+ diff = 0
175
+ @graph.each_node { |_, node|
176
+ rank = min_value
177
+ incidents(node).each { |referent|
178
+ rank += damping_factor * pagerank[referent] / neighbors(referent).size
179
+ }
180
+
181
+ diff += (pagerank[node] - rank).abs
182
+ pagerank[node] = rank
183
+ }
184
+ break if diff < min_delta
185
+ }
186
+
187
+ return pagerank
188
+ end
189
+
190
+ # Return the list of nodes that are directly accessible from given node
191
+ def neighbors(node)
192
+ if node.class == String
193
+ @graph.get_node(node).neighbors
194
+ else
195
+ node.neighbors
196
+ end
197
+ end
198
+
199
+ # Return the list of nodes that are incident to the given node (in a directed graph neighbors == incidents)
200
+ def incidents(node)
201
+ if node.class == String
202
+ @graph.get_node(node).incidents
203
+ else
204
+ node.incidents
205
+ end
206
+ end
207
+
208
+ # Breadth First Search
209
+ def bfs(node, &b)
210
+ queue = []
211
+ visited_nodes = []
212
+ node = @graph.get_node(node) if node.kind_of? String
213
+ queue << node
214
+ visited_nodes << node
215
+
216
+ while not queue.empty?
217
+ node = queue.shift
218
+ b.call(node)
219
+ neighbors(node).each do |n|
220
+ unless visited_nodes.include?(n)
221
+ visited_nodes << n
222
+ queue << n
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ # Depth First Search
229
+ def dfs(node, &b)
230
+ visited_nodes = []
231
+ recursive_dfs(node, visited_nodes, &b)
232
+ end
233
+
234
+ private
235
+ def recursive_dfs(node, visited_nodes, &b)
236
+ node = @graph.get_node(node) if node.kind_of? String
237
+ b.call(node)
238
+ visited_nodes << node
239
+ neighbors(node).each do |n|
240
+ recursive_dfs(n, visited_nodes, &b) unless visited_nodes.include?(n)
241
+ end
242
+ end
243
+
244
+ def distance_matrix
245
+ type = @graph.type
246
+ matrix = GraphViz::Math::Matrix.new( @graph.node_count, @graph.node_count, (1.0/0.0) )
247
+
248
+ @graph.each_edge { |e|
249
+ x = @graph.get_node(e.node_one( false )).index
250
+ y = @graph.get_node(e.node_two( false )).index
251
+ unless x == y
252
+ weight = ((e[:weight].nil?) ? 1 : e[:weight].to_f)
253
+ matrix[x+1, y+1] = weight
254
+ matrix[y+1, x+1] = weight if type == "graph"
255
+ end
256
+ }
257
+
258
+ return matrix
259
+ end
260
+
261
+ def degree_matrix
262
+ matrix = GraphViz::Math::Matrix.new( @graph.node_count, @graph.node_count )
263
+ @graph.each_node do |name, node|
264
+ i = node.index
265
+ matrix[i+1, i+1] = degree(node)
266
+ end
267
+ return matrix
268
+ end
269
+
270
+ def range_recursion(matrix, unseen, result, r)
271
+ remove = []
272
+ matrix.columns.times do |c|
273
+ if matrix.sum_of_column(c+1) == 0
274
+ result[unseen[c]-1] = r
275
+ remove.unshift( c + 1 )
276
+ end
277
+ end
278
+
279
+ remove.each do |rem|
280
+ matrix = matrix.remove_line(rem).remove_column(rem)
281
+ unseen.delete_at(rem-1)
282
+ end
283
+
284
+ if matrix.columns == 1 and matrix.lines == 1
285
+ if matrix.sum_of_column(1) == 0
286
+ result[unseen[0]-1] = r+1
287
+ end
288
+ elsif remove.size > 0
289
+ range_recursion( matrix, unseen, result, r+1 )
290
+ end
291
+
292
+ return result
293
+ end
294
+
295
+ def index_of_item( array, item )
296
+ array.inject( [0,[]] ){|a,i|
297
+ a[1] << a[0] if i == item
298
+ a[0] += 1
299
+ a
300
+ }[1]
301
+ end
302
+
303
+ def critical_path_recursion( d, a, r, result, level )
304
+ r.each do |p|
305
+ node = p[1][-1]
306
+ index_of_item( a.line(node), 1 ).each do |c|
307
+ succ = c+1
308
+
309
+ cpath = [ (p[0] + d[node,succ]), (p[1].clone << succ) ]
310
+
311
+ if index_of_item( a.line(succ), 1 ).size > 0
312
+ critical_path_recursion( d, a, [cpath], result, level+1 )
313
+ else
314
+ result << cpath
315
+ end
316
+ end
317
+ end
318
+ return result
319
+ end
320
+ end
321
+ end
@@ -0,0 +1,32 @@
1
+ # >> x = "hello\n\t\\l\"world\""
2
+ # => "hello\n\t\\l\"world\""
3
+ # >> puts x.inspect.gsub( "\\\\", "\\" )
4
+ # "hello\n\t\l\"world\""
5
+ #
6
+ # OR
7
+ #
8
+ # >> x = 'hello\n\t\l"world"'
9
+ # => "hello\\n\\t\\l\"world\""
10
+ # >> puts x.inspect.gsub( "\\\\", "\\" )
11
+ # "hello\n\t\l\"world\""
12
+
13
+ class GraphViz
14
+ class Types
15
+ class ArrowType < Common
16
+ def check(data)
17
+ return data
18
+ end
19
+
20
+ def output
21
+ return @data.to_s.inspect.gsub( "\\\\", "\\" )
22
+ end
23
+
24
+ alias :to_gv :output
25
+ alias :to_s :output
26
+
27
+ def to_ruby
28
+ @data
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,58 @@
1
+ require 'graphviz/utils/colors'
2
+
3
+ class ColorException < RuntimeError
4
+ end
5
+
6
+ class GraphViz
7
+ class Types
8
+ class Color < Common
9
+ HEX_FOR_COLOR = /[0-9a-fA-F]{2}/
10
+ RGBA = /^#(#{HEX_FOR_COLOR})(#{HEX_FOR_COLOR})(#{HEX_FOR_COLOR})(#{HEX_FOR_COLOR})?$/
11
+
12
+ def check(data)
13
+ data = data.to_s if data.is_a?(Symbol)
14
+ return nil if data.empty?
15
+
16
+ if data[0].chr == "#"
17
+ m = RGBA.match(data)
18
+ if m.nil?
19
+ raise ColorException, "Wrong color definition RGBA #{data}"
20
+ end
21
+ @to_ruby = GraphViz::Utils::Colors.rgb(m[1], m[2], m[3], m[4])
22
+ return data
23
+ elsif data.include?(",") or data.include?(" ")
24
+ m = data.split(/(?:\s*,\s*|\s+)/).map { |x| x.to_f }
25
+ if m.size != 3
26
+ raise ColorException, "Wrong color definition HSV #{data}"
27
+ end
28
+ @to_ruby = GraphViz::Utils::Colors.hsv(m[0], m[1], m[2])
29
+ return data
30
+ elsif data.is_a?(Array)
31
+ if data.all? { |x| x.is_a?(String) and x =~ /^#{HEX_FOR_COLOR}$/ } and [3,4].include?(data.size)
32
+ @to_ruby = GraphViz::Utils::Colors.rgb(data[0], data[1], data[2], data[3])
33
+ return data
34
+ elsif data.all? { |x| x.kind_of?(Numeric) } and data.size == 3
35
+ @to_ruby = GraphViz::Utils::Colors.hsv(data[0], data[1], data[2])
36
+ return data
37
+ end
38
+
39
+ raise ColorException, "Wrong color definition Array #{data}"
40
+ else
41
+ @to_ruby = GraphViz::Utils::Colors.name(data)
42
+ return data
43
+ end
44
+ end
45
+
46
+ def output
47
+ return @data.to_s.inspect.gsub( "\\\\", "\\" )
48
+ end
49
+
50
+ alias :to_gv :output
51
+ alias :to_s :output
52
+
53
+ def to_ruby
54
+ @to_ruby
55
+ end
56
+ end
57
+ end
58
+ end