rsvgr 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/rsvgr.rb +405 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cd4d756ecd876ced14a6866dd9594a1c93666f6e
4
+ data.tar.gz: d3e3f0d0e9da5624f44ebe704132cf6adfb2a17e
5
+ SHA512:
6
+ metadata.gz: f508fc6214a96e9411ef2830e5e6bd79ae9476425be762854812b0edbf4f79f2e08928e99376f465d718483e9232b27e4d63919fb285f7e2993a7654e90e4098
7
+ data.tar.gz: 37c542277ac4c4f7184458b83820067259ae155c056f24c0dc8d7dfa63794beef0a406ded045f5473972d52f81af941730d0bda0da6fe009b39a5ba25897235e
data/lib/rsvgr.rb ADDED
@@ -0,0 +1,405 @@
1
+ # I don't give a fuck about namespaces, xslt, etc.
2
+ # I don't use any xml library, because I just don't really need it here
3
+ # I don't give a fuck about xslt and other shit
4
+ # I JUST A PSYCHO REDING THIS AND DOING THE EASIEST WAY
5
+
6
+ # http://www.w3.org/TR/SVGTiny12/single-page.html
7
+
8
+
9
+ module RSVGR
10
+
11
+ DEFAULT_SIZE = 100.0
12
+ UNSUPPORTED = ->{ raise "not supported currently" }
13
+
14
+ class Node
15
+ def initialize args = {}
16
+ args[:x1] ||= 0
17
+ args[:y1] ||= 0
18
+ args[:x2] ||= DEFAULT_SIZE
19
+ args[:y2] ||= DEFAULT_SIZE
20
+ args.each{ |k,v| instance_variable_set "@#{k}",v }
21
+ end
22
+ def to_s
23
+ raise "you had to override me, while ascending from #{self.class.name} class"
24
+ end
25
+ end
26
+
27
+ class CanIHazChildren < Node
28
+ def initialize args = {}
29
+ @children = []
30
+ super
31
+ end
32
+ def << x
33
+ @children << x
34
+ self
35
+ end
36
+ def to_s_children additional_child = []
37
+ [*@children, *additional_child].map{ |child|
38
+ child.to_s.gsub(/.+/, ' \0')
39
+ }.join
40
+ end
41
+ def save_as what, where
42
+ File.open(where, "w"){ |f| f.puts what }
43
+ self
44
+ end
45
+ end
46
+
47
+ class Group < CanIHazChildren
48
+ def to_s additional_child = []
49
+ "<g transform=\"" \
50
+ "#{"translate(#{@x || 0},#{@y || 0}) " if @x || @y}" \
51
+ "#{"scale(#{@scale_x || @scale || 1},#{@scale_y || @scale || 1}) " if @scale_x || @scale_y || @scale}" \
52
+ "#{"rotate(#{@rotate})" if @rotate}\"" \
53
+ "#{" id=\"#{@id}\"" if @id}" \
54
+ "#{" fill=\"#{@fill_color}\"" if @fill_color}" \
55
+ "#{" stroke-width=\"#{@stroke_width}\"" if @stroke_width}" \
56
+ "#{" stroke=\"#{@stroke_color}\"" if @stroke_color}" \
57
+ ">\n" + to_s_children(additional_child) + "</g>\n"
58
+ end
59
+ end
60
+
61
+ class Root < CanIHazChildren
62
+ def initialize args = {}
63
+ @fill_color = "silver"
64
+ @stroke_color = "black"
65
+ @stroke_width = DEFAULT_SIZE*0.01
66
+ @stroke_linecap = "round"
67
+ super
68
+ end
69
+ def to_s
70
+ "<?xml version=\"1.0\"?>\n" \
71
+ "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.2\" baseProfile=\"tiny\"" \
72
+ " viewBox=\"#{[@x1, @y1, @x2, @y2].join " "}\"" \
73
+ " fill=\"#{@fill_color}\"" \
74
+ " stroke=\"#{@stroke_color}\"" \
75
+ " stroke-width=\"#{@stroke_width}\"" \
76
+ " stroke-linecap=\"#{@stroke_linecap}\"" \
77
+ " preserveAspectRatio=\"xMidYMid meet\"" \
78
+ ">\n <title>Generated by RubySVGmakeR v0.1 (c) Nakilon</title>\n" +
79
+ to_s_children + "</svg>\n"
80
+ end
81
+ def to_html
82
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" \
83
+ " <head>\n" \
84
+ " <title>#{Time.now}</title>\n" \
85
+ " <style type=\"text/css\" media=\"screen\">\n" \
86
+ " body {\n" \
87
+ " background:lightgrey;\n" \
88
+ " margin:0;\n" \
89
+ " }\n" \
90
+ " svg {\n" \
91
+ " display:block;\n" \
92
+ " border:2px solid grey;\n" \
93
+ " position:absolute;\n" \
94
+ " top:3%;\n" \
95
+ " left:3%;\n" \
96
+ " width:94%;\n" \
97
+ " height:94%;\n" \
98
+ " background:white;\n" \
99
+ " }\n" \
100
+ " </style>\n" \
101
+ " </head>\n" \
102
+ " <body>\n" + to_s + " </body>\n</html>\n"
103
+ end
104
+ def cat
105
+ puts self.to_s
106
+ self
107
+ end
108
+ def save
109
+ save_as to_s, "temp.svg"
110
+ end
111
+ def save_html
112
+ UNSUPPORTED
113
+ save_as to_html, "temp.html"
114
+ end
115
+ def save_as what, where
116
+ UNSUPPORTED
117
+ File.open(where, "w"){ |f| f.puts what }
118
+ self
119
+ end
120
+ def open_with app
121
+ RUBY_PLATFORM["mingw"] ? `#{app} temp.svg` : `open -a #{app} temp.svg`
122
+ end
123
+ end
124
+
125
+
126
+ class Script < CanIHazChildren
127
+ def to_s
128
+ "<script" \
129
+ " type=\"text/ecmascript\"" \
130
+ "#{" id=\"#{@id}\"" if @id}" \
131
+ "><![CDATA[\n" + to_s_children + "]]></script>\n"
132
+ end
133
+ end
134
+
135
+ class Text < CanIHazChildren
136
+ def initialize args = {}
137
+ args[:x] ||= DEFAULT_SIZE/2
138
+ args[:y] ||= DEFAULT_SIZE/2
139
+ args[:size] ||= DEFAULT_SIZE*0.8
140
+ args[:anchor] ||= "middle"
141
+ args[:baseline] ||= "central"
142
+ args[:fill_color] ||= "black"
143
+ super
144
+ end
145
+ def to_s
146
+ "<text" \
147
+ "#{" id=\"#{@id}\"" if @id}" \
148
+ "#{" visibility=\"#{@visibility}\"" if @visibility}" \
149
+ " x=\"#{@x}\"" \
150
+ " y=\"#{@y}\"" \
151
+ " font-size=\"#{@size}\"" \
152
+ " text-anchor=\"#{@anchor}\"" \
153
+ " dominant-baseline=\"#{@baseline}\"" \
154
+ " fill=\"#{@fill_color}\"" \
155
+ "#{" stroke=\"#{@stroke_color}\"" if @stroke_color}" \
156
+ "#{" style=\"#{@style}\"" if @style}" \
157
+ ">\n" + to_s_children + "</text>\n"
158
+ end
159
+ end
160
+
161
+ class Line < Node
162
+ def to_s
163
+ "<line " \
164
+ "x1=\"#{@x1}\" " \
165
+ "x2=\"#{@x2}\" " \
166
+ "y1=\"#{@y1}\" " \
167
+ "y2=\"#{@y2}\" " \
168
+ "#{"stroke=\"#{@stroke_color}\" " if @stroke_color}" \
169
+ "/>\n"
170
+ end
171
+ end
172
+
173
+ class Path < Node
174
+ def initialize args = {}
175
+ args[:d] = "M " + args[:points].map{ |x, y| "#{x} #{y}" }.join(" L ")
176
+ args[:fill_color] ||= "none"
177
+ super
178
+ end
179
+ def to_s
180
+ "<path" \
181
+ " d=\"#{@d}\"" \
182
+ "#{" stroke=\"#{@stroke_color}\"" if @stroke_color}" \
183
+ " fill=\"#{@fill_color}\"" \
184
+ "/>\n"
185
+ end
186
+ end
187
+
188
+ class Circle < Node
189
+ def initialize args = {}
190
+ args[:r] ||= DEFAULT_SIZE*0.5
191
+ super
192
+ end
193
+ def to_s
194
+ "<circle" \
195
+ "#{" cx=\"#{@x}\"" if @x}" \
196
+ "#{" cy=\"#{@y}\"" if @y}" \
197
+ " r=\"#{@r}\"" \
198
+ "#{" fill=\"#{@fill_color}\"" if @fill_color}" \
199
+ "#{" stroke=\"#{@stroke_color}\"" if @stroke_color}" \
200
+ "#{" onmousemove=\"#{@onmousemove}\"" if @onmousemove}" \
201
+ "#{" onmouseout=\"#{@onmouseout}\"" if @onmouseout}" \
202
+ "/>\n"
203
+ end
204
+ end
205
+
206
+ class Rect < Node
207
+ def initialize args = {}
208
+ args[:width] ||= DEFAULT_SIZE
209
+ args[:height] ||= DEFAULT_SIZE
210
+ super
211
+ end
212
+ def to_s
213
+ "<rect" \
214
+ "#{" x=\"#{@x1}\"" if @x1}" \
215
+ "#{" y=\"#{@y1}\"" if @y1}" \
216
+ " width=\"#{@width}\"" \
217
+ " height=\"#{@height}\"" \
218
+ "#{" stroke=\"#{@stroke_color}\"" if @stroke_color}" \
219
+ "#{" stroke-width=\"#{@stroke_width}\"" if @stroke_width}" \
220
+ "#{" fill=\"#{@fill_color}\"" if @fill_color}" \
221
+ "/>\n"
222
+ end
223
+ end
224
+
225
+
226
+ module Samples
227
+ def self.face args = {}
228
+ args[:scale_x] = args[:scale_y] = args[:size]/DEFAULT_SIZE if args[:size]
229
+ args[:fill_color] = "yellow"
230
+ args[:x] = DEFAULT_SIZE/2
231
+ args[:y] = DEFAULT_SIZE/2
232
+ args[:stroke_width] = DEFAULT_SIZE/10
233
+ args[:stroke_color] = :black
234
+ Group.new(args) <<
235
+ Circle.new <<
236
+ Circle.new(x:-0.2*DEFAULT_SIZE, y:-0.2*DEFAULT_SIZE, r:0.1*DEFAULT_SIZE) <<
237
+ Circle.new(x:+0.2*DEFAULT_SIZE, y:-0.2*DEFAULT_SIZE, r:0.1*DEFAULT_SIZE) <<
238
+ Line.new(x1:-0.2*DEFAULT_SIZE, y1:+0.2*DEFAULT_SIZE, x2:+0.2*DEFAULT_SIZE, y2:+0.2*DEFAULT_SIZE)
239
+ end
240
+ class Grid < Group
241
+ def initialize args = {}
242
+ #args[:x2] ||= args[:xn] + args[:x1] ||= 0
243
+ #args[:y2] ||= args[:yn] + args[:y1] ||= 0
244
+ args[:fill_color] = "white"
245
+ super
246
+ if @xn*(@y2-@y1) > (@x2-@x1)*@yn
247
+ y = (@x2-@x1)*@yn/@xn
248
+ @y1 = (DEFAULT_SIZE-y)/2
249
+ @y2 = (DEFAULT_SIZE+y)/2
250
+ else
251
+ x = (@y2-@y1)*@xn/@yn
252
+ @x1 = (DEFAULT_SIZE-x)/2
253
+ @x2 = (DEFAULT_SIZE+x)/2
254
+ end
255
+ w = (@x2 - @x1)/@xn
256
+ h = (@y2 - @y1)/@yn
257
+ [*0...@yn].product([*0...@xn]) do |i,j|
258
+ self << cell = Group.new(
259
+ x: @x1+j*w,
260
+ y: @y1+i*h,
261
+ scale_x: w/DEFAULT_SIZE,
262
+ scale_y: h/DEFAULT_SIZE,
263
+ )
264
+ cell << Rect.new(stroke_color:"silver", stroke_width:DEFAULT_SIZE/10) << inside = Group.new(
265
+ x: DEFAULT_SIZE*0.1,
266
+ y: DEFAULT_SIZE*0.1,
267
+ scale_x: 0.8,
268
+ scale_y: 0.8,
269
+ )
270
+ yield inside,i,j if block_given?
271
+ end
272
+ end
273
+ end
274
+ class Plot < Group
275
+ def initialize args = {}
276
+ args[:stroke_width] = DEFAULT_SIZE * 0.002
277
+ args[:fill_color] = "white"
278
+ super
279
+ @lines = []
280
+ end
281
+ def add_line args = {}
282
+ args[:data_pairs] = Hash[args[:data_pairs].to_a]
283
+ @lines << args
284
+ self
285
+ end
286
+ def to_s
287
+ return @to_s_cached if @to_s_cached
288
+ ticks = lambda do |basics|
289
+ if basics.any?{ |i| ! i.is_a? Integer }
290
+ [
291
+ basics.uniq,
292
+ -> x { DEFAULT_SIZE * basics.index(x) / (basics.size-1) }
293
+ ]
294
+ else
295
+ min, max = basics.minmax
296
+ [
297
+ [min, *(1...8).map{ |i| (max-min)*i/8 }, max],
298
+ -> x { DEFAULT_SIZE * (x - min) / (max - min) }
299
+ ]
300
+ end
301
+ end
302
+ ticks_x, f_x = ticks[ @ticks_x || @lines.flat_map{ |line| line[:data_pairs].keys } ]
303
+ ticks_y, f_y = ticks[ @lines.flat_map{ |line| line[:data_pairs].values } ]
304
+ top, left, scale = 0.05, 0.1
305
+ size = DEFAULT_SIZE * 0.03
306
+ self << field = Group.new(id:"TODOfield", x: DEFAULT_SIZE * left, y: DEFAULT_SIZE * top, scale: 0.7)
307
+ hsv2rgb = lambda do |h,s,v|
308
+ vmin = (100-s)*v/100
309
+ a = (v - vmin)*(h % 60)/60.0
310
+ vinc = vmin + a
311
+ vdec = v - a
312
+ case h/60
313
+ when 0 ; [v, vinc, vmin]
314
+ when 1 ; [vdec, v, vmin]
315
+ when 2 ; [vmin, v, vinc]
316
+ when 3 ; [vmin, vdec, v]
317
+ when 4 ; [vinc, vmin, v]
318
+ when 5 ; [v, vmin, vdec]
319
+ end.map{ |i| (2.55 * i).floor }
320
+ end
321
+ colors = (0...@lines.size).map{ |i| ?# + hsv2rgb[i*360/@lines.size, 100, 100].pack("C*").unpack("H*").first }
322
+ @lines.zip(colors).each_with_index do |(line, color), i|
323
+ #@@id = defined?(@@id) ? @@id + 1 : 0
324
+ field << (Text.new(
325
+ #id: @@id,
326
+ fill_color: "black",# color.tr("0123456789abcdef", "fedcba9876543210"),
327
+ stroke_color: "none",
328
+ size: DEFAULT_SIZE * 0.03,
329
+ x: DEFAULT_SIZE * 0.12,
330
+ y: DEFAULT_SIZE * (0.05 + i * 0.03),
331
+ anchor: "begin",
332
+ baseline: "text-before-edge",
333
+ ) << line[:title])
334
+ field << Rect.new(
335
+ x1: DEFAULT_SIZE * 0.05,
336
+ y1: DEFAULT_SIZE * (0.05 + i * 0.03),
337
+ width: DEFAULT_SIZE * 0.05,
338
+ height: DEFAULT_SIZE * 0.03,
339
+ fill_color: color,
340
+ )
341
+ end
342
+ @lines.zip(colors).each_with_index do |(line, color), i|
343
+ field << Path.new(
344
+ stroke_color: color,
345
+ points: line[:data_pairs].map{ |k,v| [f_x[k], DEFAULT_SIZE-f_y[v]] }
346
+ )
347
+ end
348
+ field << Text.new(
349
+ id: "tooltip",
350
+ visibility: "hidden",
351
+ baseline: "before-edge",
352
+ size: DEFAULT_SIZE * 0.03,
353
+ stroke_color: "none",
354
+ )
355
+ field << (Script.new(id: "TODOscript") << "
356
+ var svg = document.getElementById(\"TODOscript\").ownerSVGElement;
357
+ svg.tooltip = svg.getElementById(\"tooltip\");
358
+ function show_tooltip(evt, text, x, y) {
359
+ var tooltip = evt.target.ownerSVGElement.tooltip;
360
+ tooltip.setAttributeNS(null, \"x\", x);
361
+ tooltip.setAttributeNS(null, \"y\", y);
362
+ tooltip.textContent = text;
363
+ tooltip.setAttributeNS(null, \"visibility\", \"visible\");
364
+ }
365
+ function hide_tooltip(evt) { evt.target.ownerSVGElement.tooltip.setAttributeNS(null, \"visibility\", \"hidden\"); }
366
+ ")
367
+ @lines.zip(colors) do |line, color| line[:data_pairs].each do |k,v|
368
+ x = f_x[k]
369
+ y = DEFAULT_SIZE - f_y[v]
370
+ field << Circle.new(
371
+ fill_color: color,
372
+ stroke_color: color,
373
+ x: x,
374
+ y: y,
375
+ r: DEFAULT_SIZE * 0.005,
376
+ onmousemove: "show_tooltip(evt, '#{k}/#{v} - #{line[:title]}', #{x}, #{y - DEFAULT_SIZE*0.025})",
377
+ onmouseout: "hide_tooltip(evt)",
378
+ )
379
+ end end
380
+ field << Rect.new(fill_color:"none")
381
+ ticks_x.each_with_index{ |tick, i| _ = f_x[tick]
382
+ field << Line.new(y1: DEFAULT_SIZE * 1.025, x1:_, x2:_)
383
+ field << tick_group = Group.new(x: _, y: DEFAULT_SIZE * 1.025, rotate: 90)
384
+ tick_group << (Text.new(x: 0, y: 0, size: size,
385
+ #baseline: "text-before-edge",
386
+ anchor: "begin",
387
+ #style: "writing-mode: tb;",
388
+ ) << tick.to_s)
389
+ }
390
+ ticks_y.each{ |tick| _ = f_y[tick]
391
+ field << Line.new(x2: -DEFAULT_SIZE * 0.025, y1:_, y2:_) <<
392
+ (Text.new(y: DEFAULT_SIZE - _, x: -DEFAULT_SIZE * left * 0.3, size: size, anchor: "end") << tick.to_s)
393
+ }
394
+ @to_s_cached = super
395
+ end
396
+ end
397
+ end
398
+
399
+ end
400
+
401
+
402
+ if __FILE__ == $0
403
+ puts `ruby -Cexamples chart.rb`
404
+ end
405
+
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rsvgr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Victor Maslov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-10 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: not ready for public usage -- uploaded for personal usage
14
+ email: nakilon@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/rsvgr.rb
20
+ homepage: http://rubygems.org/gems/rsvgr
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.0.14
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Ruby SVG Renderer.
44
+ test_files: []