r2dsvg 0.5.0 → 0.5.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/r2dsvg/r2dsvg_module.rb +586 -0
- metadata +2 -1
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77a1f9080662cecab28ea1d9c25339855890367e95769b10d4232d5378ca8609
|
4
|
+
data.tar.gz: a7a1411bf0797a7312c368665e1f3d259f58d326fe551515686715bf9ef6b81a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c33d412244025915719fe9a16cd2ac2b948d20be3560c4211c028e6f603da19d6bcc7479e58c89eb3255142b5ed224ea330d1933510df42f342f4d08b673dce
|
7
|
+
data.tar.gz: de8edc84cac33d6c3bb857709bc4ca63152a3ae5560dcce0c766f5440d9a94fe7dc22e08f01036a87c64cd9a0341a98bcfae55eaeb3403d34f01af6c85d7cf16
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
@@ -0,0 +1,586 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# file: r2dsvg_module.rb
|
4
|
+
|
5
|
+
# Description: Experimental gem to render SVG within a Ruby2D application.
|
6
|
+
|
7
|
+
|
8
|
+
#require 'svgle'
|
9
|
+
require 'onedrb'
|
10
|
+
require 'svgle'
|
11
|
+
require 'dom_render'
|
12
|
+
require 'ruby2d' # experimental gem depends upon simple2d binaries
|
13
|
+
|
14
|
+
|
15
|
+
DEFAULT_CSS = <<CSS
|
16
|
+
g {background-color: blue}
|
17
|
+
svg {background-color: white}
|
18
|
+
rect {fill: yellow}
|
19
|
+
line, polyline {stroke: green; stroke-width: 3}
|
20
|
+
text {fill: red, size: 20}
|
21
|
+
|
22
|
+
CSS
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
class Svgle::Shape
|
27
|
+
|
28
|
+
def initialize(*args)
|
29
|
+
super(*args)
|
30
|
+
@attr_map ||= {fill: :color}
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
module SvgleX
|
38
|
+
|
39
|
+
|
40
|
+
refine Svgle::Text do
|
41
|
+
|
42
|
+
def text=(raw_s)
|
43
|
+
|
44
|
+
oldval = @child_elements.first
|
45
|
+
|
46
|
+
r = super(raw_s)
|
47
|
+
self.obj.text = raw_s if oldval != raw_s
|
48
|
+
|
49
|
+
return r
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
module R2dEngine
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
class Render < DomRender
|
62
|
+
|
63
|
+
def audio(e, attributes)
|
64
|
+
|
65
|
+
puts 'inside audio attributes: ' + attributes.inspect if @debug
|
66
|
+
|
67
|
+
h = attributes
|
68
|
+
|
69
|
+
sources = e.xpath('source').map do |x|
|
70
|
+
h = x.attributes.to_h
|
71
|
+
h.delete :style
|
72
|
+
h
|
73
|
+
end
|
74
|
+
|
75
|
+
[:embed_audio, sources, e]
|
76
|
+
end
|
77
|
+
|
78
|
+
def circle(e, attributes)
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
h = attributes
|
83
|
+
|
84
|
+
x, y, radius= %i(cx cy r).map{|x| h[x].to_i }
|
85
|
+
fill = h[:fill]
|
86
|
+
|
87
|
+
|
88
|
+
[:draw_circle, [x, y], radius, fill, attributes, render_all(e)]
|
89
|
+
end
|
90
|
+
|
91
|
+
# not yet implemented
|
92
|
+
#
|
93
|
+
def ellipse(e, attributes)
|
94
|
+
|
95
|
+
h = attributes
|
96
|
+
|
97
|
+
x, y= %i(cx cy).map{|x| h[x].to_i }
|
98
|
+
width = h[:rx].to_i * 2
|
99
|
+
height = h[:ry].to_i * 2
|
100
|
+
|
101
|
+
[:draw_arc, [x, y, width, height], attributes, render_all(e)]
|
102
|
+
end
|
103
|
+
|
104
|
+
def g(e, attributes)
|
105
|
+
|
106
|
+
puts 'inside rect attributes: ' + attributes.inspect if @debug
|
107
|
+
|
108
|
+
h = attributes
|
109
|
+
|
110
|
+
x1, y1, width, height = %i(x y width height).map{|x| h[x].to_i }
|
111
|
+
x2, y2, = x1 + width, y1 + height
|
112
|
+
|
113
|
+
[:draw_rectangle, [x1, y1, x2, y2], attributes, e, render_all(e)]
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
def line(e, attributes)
|
119
|
+
|
120
|
+
|
121
|
+
x1, y1, x2, y2 = %i(x1 y1 x2 y2).map{|x| attributes[x].to_i }
|
122
|
+
|
123
|
+
[:draw_line, [x1, y1, x2, y2], attributes, render_all(e)]
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def image(e, attributes)
|
128
|
+
|
129
|
+
h = attributes
|
130
|
+
|
131
|
+
x, y, width, height = %i(x y width height).map{|x| h[x] ? h[x].to_i : nil }
|
132
|
+
src = h[:'xlink:href']
|
133
|
+
|
134
|
+
[:draw_image, [x, y, width, height], src, attributes, e, render_all(e)]
|
135
|
+
end
|
136
|
+
|
137
|
+
def polygon(e, attributes)
|
138
|
+
|
139
|
+
|
140
|
+
points = attributes[:points].split(/\s+/). \
|
141
|
+
map {|x| x.split(/\s*,\s*/).map(&:to_i)}
|
142
|
+
|
143
|
+
[:draw_polygon, points, attributes, e, render_all(e)]
|
144
|
+
end
|
145
|
+
|
146
|
+
def polyline(e, attributes)
|
147
|
+
|
148
|
+
points = attributes[:points].split(/\s+/). \
|
149
|
+
map {|x| x.split(/\s*,\s*/).map(&:to_i)}
|
150
|
+
|
151
|
+
[:draw_lines, points, attributes, render_all(e)]
|
152
|
+
end
|
153
|
+
|
154
|
+
def rect(e, attributes)
|
155
|
+
|
156
|
+
puts 'inside rect attributes: ' + attributes.inspect if @debug
|
157
|
+
|
158
|
+
h = attributes
|
159
|
+
|
160
|
+
x1, y1, width, height = %i(x y width height).map{|x| h[x].to_i }
|
161
|
+
x2, y2, = x1 + width, y1 + height
|
162
|
+
|
163
|
+
[:draw_rectangle, [x1, y1, x2, y2], attributes, e, render_all(e)]
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
def svg(e, attributes)
|
169
|
+
|
170
|
+
h = attributes
|
171
|
+
width, height = %i(width height).map{|x| h[x].to_i }
|
172
|
+
|
173
|
+
[:draw_rectangle, [0, 0, width, height], attributes, render_all(e)]
|
174
|
+
end
|
175
|
+
|
176
|
+
def text(e, attributes)
|
177
|
+
|
178
|
+
|
179
|
+
attributes.merge!({font_size: '20'})
|
180
|
+
|
181
|
+
x, y = %i(x y).map{|x| attributes[x].to_i }
|
182
|
+
|
183
|
+
[:draw_text, [x, y], e.text, attributes, e, render_all(e)]
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
class DrawingInstructions
|
190
|
+
using ColouredText
|
191
|
+
|
192
|
+
attr_accessor :area
|
193
|
+
|
194
|
+
|
195
|
+
def initialize(window, debug: false)
|
196
|
+
|
197
|
+
@window, @debug = window, debug
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
def draw_arc(args)
|
202
|
+
|
203
|
+
dimensions, style = args
|
204
|
+
|
205
|
+
x, y, width, height = dimensions
|
206
|
+
|
207
|
+
#gc = gc_ini(fill: style[:fill] || :none)
|
208
|
+
#@area.window.draw_arc(gc, 1, x, y, width, height, 0, 64 * 360)
|
209
|
+
end
|
210
|
+
|
211
|
+
def draw_circle(args)
|
212
|
+
|
213
|
+
coords, radius, fill, style, e = args
|
214
|
+
|
215
|
+
x1, y1 = coords
|
216
|
+
|
217
|
+
if @debug then
|
218
|
+
puts 'inside draw_circle'.info
|
219
|
+
puts ('style: ' + style.inspect).debug
|
220
|
+
end
|
221
|
+
|
222
|
+
obj = Circle.new(
|
223
|
+
x: x1, y: y1,
|
224
|
+
radius: radius,
|
225
|
+
sectors: 32,
|
226
|
+
color: style[:fill],
|
227
|
+
z: style[:"z-index"].to_i
|
228
|
+
)
|
229
|
+
e.obj = obj if e.respond_to? :obj=
|
230
|
+
@window.add obj
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
def draw_image(args)
|
235
|
+
|
236
|
+
dimensions, src, style, e = args
|
237
|
+
|
238
|
+
x, y, width, height = dimensions
|
239
|
+
|
240
|
+
filepath = Tempfile.new('r2dsvg').path + File.basename(src)
|
241
|
+
puts 'filepath: ' + filepath.inspect if @debug
|
242
|
+
File.write filepath, RXFHelper.read(src).first
|
243
|
+
|
244
|
+
|
245
|
+
if File.exists? filepath then
|
246
|
+
|
247
|
+
obj = Image.new(
|
248
|
+
filepath,
|
249
|
+
x: x, y: y,
|
250
|
+
width: width, height: height,
|
251
|
+
color: style[:fill],
|
252
|
+
z: style[:"z-index"].to_i
|
253
|
+
)
|
254
|
+
|
255
|
+
e.obj = obj if e.respond_to? :obj=
|
256
|
+
@window.add obj
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def draw_line(args)
|
261
|
+
|
262
|
+
coords, style, e = args
|
263
|
+
|
264
|
+
x1, y1, x2, y2 = coords
|
265
|
+
|
266
|
+
if @debug then
|
267
|
+
puts 'inside draw_rectangle'.info
|
268
|
+
puts ('style: ' + style.inspect).debug
|
269
|
+
end
|
270
|
+
|
271
|
+
obj = Line.new(
|
272
|
+
x1: x1, y1: y1,
|
273
|
+
x2: x2, y2: y2,
|
274
|
+
width: style[:"stroke-width"].to_f,
|
275
|
+
color: style[:"stroke"],
|
276
|
+
z: style[:"z-index"].to_i
|
277
|
+
)
|
278
|
+
|
279
|
+
e.obj = obj if e.respond_to? :obj=
|
280
|
+
@window.add obj
|
281
|
+
|
282
|
+
end
|
283
|
+
|
284
|
+
def draw_polygon(args)
|
285
|
+
|
286
|
+
vertices, style, e = args
|
287
|
+
|
288
|
+
puts ('vertices: ' + vertices.inspect).debug if @debug
|
289
|
+
|
290
|
+
if @debug then
|
291
|
+
puts 'inside draw_polygon'.info
|
292
|
+
puts ('style: ' + style.inspect).debug
|
293
|
+
end
|
294
|
+
|
295
|
+
puts ('vertices: ' + vertices.inspect).debug if @debug
|
296
|
+
|
297
|
+
h = vertices.map.with_index do |coords,i|
|
298
|
+
|
299
|
+
%w(x y).zip(coords).map {|key, c| [(key + (i+1).to_s).to_sym, c] }
|
300
|
+
|
301
|
+
end.flatten(1).to_h
|
302
|
+
puts ('triangle h: ' + h.inspect).debug if @debug
|
303
|
+
|
304
|
+
puts ('triangle h merged: ' + h.inspect).debug if @debug
|
305
|
+
obj = Triangle.new(h.merge({color: style[:fill], z: style[:"z-index"].to_i}))
|
306
|
+
e.obj = obj if e.respond_to? :obj=
|
307
|
+
@window.add obj
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
# not yet implemented
|
312
|
+
#
|
313
|
+
def draw_lines(args)
|
314
|
+
|
315
|
+
coords, width, style, e = args
|
316
|
+
|
317
|
+
x1, y1, x2, y2 = coords
|
318
|
+
|
319
|
+
|
320
|
+
end
|
321
|
+
|
322
|
+
def draw_rectangle(args)
|
323
|
+
|
324
|
+
coords, style, e = args
|
325
|
+
|
326
|
+
x1, y1, x2, y2 = coords
|
327
|
+
|
328
|
+
if @debug then
|
329
|
+
puts 'inside draw_rectangle'.info
|
330
|
+
puts ('style: ' + style.inspect).debug
|
331
|
+
end
|
332
|
+
|
333
|
+
obj = Rectangle.new(
|
334
|
+
x: x1, y: y1,
|
335
|
+
width: x2 - x1, height: y2 - y1,
|
336
|
+
color: style[:fill],
|
337
|
+
z: style[:"z-index"].to_i
|
338
|
+
)
|
339
|
+
e.obj = obj if e.respond_to? :obj=
|
340
|
+
@window.add obj
|
341
|
+
|
342
|
+
end
|
343
|
+
|
344
|
+
def draw_text(args)
|
345
|
+
|
346
|
+
coords, text, style, e = args
|
347
|
+
|
348
|
+
x, y = coords
|
349
|
+
|
350
|
+
if @debug then
|
351
|
+
puts 'inside draw_text'.info
|
352
|
+
puts ('style: ' + style.inspect).debug
|
353
|
+
end
|
354
|
+
|
355
|
+
obj = Text.new(
|
356
|
+
text,
|
357
|
+
x: x, y: y,
|
358
|
+
#font: 'vera.ttf',
|
359
|
+
size: style[:font_size].to_i,
|
360
|
+
color: style[:color],
|
361
|
+
z: style[:"z-index"].to_i
|
362
|
+
)
|
363
|
+
puts 'e: ' + e.inspect
|
364
|
+
e.obj = obj
|
365
|
+
@window.add obj
|
366
|
+
|
367
|
+
end
|
368
|
+
|
369
|
+
# Ruby 2D supports a number of popular audio formats, including WAV,
|
370
|
+
# MP3, Ogg Vorbis, and FLAC.
|
371
|
+
|
372
|
+
def embed_audio(args)
|
373
|
+
|
374
|
+
sources, e = args
|
375
|
+
|
376
|
+
if @debug then
|
377
|
+
puts 'sources: ' + sources.inspect if @debug
|
378
|
+
puts 'inside embed_audio'.info
|
379
|
+
end
|
380
|
+
|
381
|
+
|
382
|
+
audio_files = sources.map do |source|
|
383
|
+
|
384
|
+
filepath = Tempfile.new('r2dsvg').path + File.basename(source[:src])
|
385
|
+
File.write filepath, RXFHelper.read(source[:src]).first
|
386
|
+
filepath
|
387
|
+
end
|
388
|
+
|
389
|
+
audio = audio_files.find {|file| File.exists? file }
|
390
|
+
|
391
|
+
return unless audio
|
392
|
+
|
393
|
+
file = File.exists?(audio) ? audio : nil
|
394
|
+
puts 'file: ' + file.inspect if @debug
|
395
|
+
|
396
|
+
obj = Sound.new(file)
|
397
|
+
e.obj = obj
|
398
|
+
|
399
|
+
def e.play() self.obj.play() end
|
400
|
+
|
401
|
+
end
|
402
|
+
|
403
|
+
def window(args)
|
404
|
+
end
|
405
|
+
|
406
|
+
def render(a)
|
407
|
+
|
408
|
+
stylex, e = a[-3..-2]
|
409
|
+
|
410
|
+
if e.respond_to? :attr_map then
|
411
|
+
|
412
|
+
h = e.attr_map.inject({}) do |r, x|
|
413
|
+
key, value = x
|
414
|
+
r.merge!({value => stylex[key]})
|
415
|
+
end
|
416
|
+
a[-3].merge!(h)
|
417
|
+
end
|
418
|
+
|
419
|
+
|
420
|
+
method(a[0]).call(args=a[1..2])
|
421
|
+
draw a[3]
|
422
|
+
end
|
423
|
+
|
424
|
+
def script(args)
|
425
|
+
|
426
|
+
end
|
427
|
+
|
428
|
+
def style(args)
|
429
|
+
end
|
430
|
+
|
431
|
+
private
|
432
|
+
|
433
|
+
def draw(a)
|
434
|
+
|
435
|
+
#threads = []
|
436
|
+
|
437
|
+
a.each do |rawx|
|
438
|
+
|
439
|
+
#threads << Thread.new do
|
440
|
+
puts 'rawx: ;' + rawx.inspect if @debug
|
441
|
+
x, *remaining = rawx
|
442
|
+
|
443
|
+
puts 'x: ;' + x.inspect if @debug
|
444
|
+
puts 'remaining: ' + remaining.inspect if @debug
|
445
|
+
|
446
|
+
if x.is_a? Symbol then
|
447
|
+
method(x).call(args=remaining)
|
448
|
+
draw(remaining[3])
|
449
|
+
elsif x.is_a? String then
|
450
|
+
draw remaining
|
451
|
+
elsif x.is_a? Array
|
452
|
+
draw remaining
|
453
|
+
else
|
454
|
+
method(x).call(remaining.take 2)
|
455
|
+
end
|
456
|
+
#end
|
457
|
+
|
458
|
+
end
|
459
|
+
|
460
|
+
#threads.join
|
461
|
+
|
462
|
+
end
|
463
|
+
|
464
|
+
end
|
465
|
+
|
466
|
+
|
467
|
+
|
468
|
+
class App
|
469
|
+
|
470
|
+
attr_reader :doc
|
471
|
+
|
472
|
+
|
473
|
+
def clear()
|
474
|
+
@window.clear
|
475
|
+
end
|
476
|
+
|
477
|
+
def read(s, title=@title)
|
478
|
+
@loaded = false
|
479
|
+
@window.clear
|
480
|
+
svg, _ = RXFHelper.read(s)
|
481
|
+
doc = Svgle.new(svg, callback: self, debug: @debug)
|
482
|
+
instructions = Render.new(doc, debug: @debug).to_a
|
483
|
+
|
484
|
+
|
485
|
+
drawing = DrawingInstructions.new @window, debug: @debug
|
486
|
+
puts ('instructions: ' + instructions.inspect).debug if @debug
|
487
|
+
|
488
|
+
@width, @height = %i(width height).map{|x| doc.root.attributes[x].to_i }
|
489
|
+
@window.set title: title, width: @width, height: @height
|
490
|
+
|
491
|
+
threads = []
|
492
|
+
|
493
|
+
threads << Thread.new do
|
494
|
+
doc.root.xpath('//script').each {|x| eval x.text.unescape }
|
495
|
+
drawing.render instructions
|
496
|
+
end
|
497
|
+
|
498
|
+
threads.join
|
499
|
+
|
500
|
+
@loaded = true
|
501
|
+
@doc = doc
|
502
|
+
|
503
|
+
end
|
504
|
+
|
505
|
+
def refresh()
|
506
|
+
puts 'do nothing' if @debug
|
507
|
+
end
|
508
|
+
|
509
|
+
|
510
|
+
private
|
511
|
+
|
512
|
+
def keyboard(action, event)
|
513
|
+
|
514
|
+
doc = @doc
|
515
|
+
|
516
|
+
@doc.root.xpath("//*[@on#{action}]").each do |x|
|
517
|
+
|
518
|
+
if block_given? then
|
519
|
+
valid = yield(x)
|
520
|
+
statement = x.method(('on' + action.to_s).to_sym).call()
|
521
|
+
puts 'statement: ' + statement.inspect if @debug
|
522
|
+
eval statement if valid
|
523
|
+
else
|
524
|
+
statement = x.method(('on' + action.to_s).to_sym).call()
|
525
|
+
puts 'statement: ' + statement.inspect if @debug
|
526
|
+
eval statement
|
527
|
+
end
|
528
|
+
|
529
|
+
end
|
530
|
+
|
531
|
+
@doc.event[action].each {|name| method(name).call event }
|
532
|
+
|
533
|
+
end
|
534
|
+
|
535
|
+
def mouse(action, event)
|
536
|
+
|
537
|
+
doc = @doc
|
538
|
+
|
539
|
+
@doc.root.xpath("//*[@on#{action}]").each do |x|
|
540
|
+
|
541
|
+
#puts 'x.class: ' + x.inspect if @debug
|
542
|
+
if x.obj and x.obj.contains? event.x, event.y then
|
543
|
+
|
544
|
+
|
545
|
+
if not x.active? then
|
546
|
+
x.active = true
|
547
|
+
elsif action == :mouseenter
|
548
|
+
next
|
549
|
+
end
|
550
|
+
|
551
|
+
if block_given? then
|
552
|
+
valid = yield(x)
|
553
|
+
statement = x.method(('on' + action.to_s).to_sym).call()
|
554
|
+
puts 'statement: ' + statement.inspect if @debug
|
555
|
+
eval statement if valid
|
556
|
+
else
|
557
|
+
statement = x.method(('on' + action.to_s).to_sym).call()
|
558
|
+
puts 'statement: ' + statement.inspect if @debug
|
559
|
+
eval statement
|
560
|
+
end
|
561
|
+
|
562
|
+
else
|
563
|
+
|
564
|
+
if x.active? then
|
565
|
+
x.active = false
|
566
|
+
onleave
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
end
|
571
|
+
|
572
|
+
end
|
573
|
+
|
574
|
+
def onleave()
|
575
|
+
|
576
|
+
@doc.root.xpath("//*[@onmouseleave]").each do |x|
|
577
|
+
puts 'onleave'.info if @debug
|
578
|
+
eval x.method(:onmouseleave).call()
|
579
|
+
end
|
580
|
+
|
581
|
+
end
|
582
|
+
|
583
|
+
end
|
584
|
+
|
585
|
+
end
|
586
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: r2dsvg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Robertson
|
@@ -124,6 +124,7 @@ extensions: []
|
|
124
124
|
extra_rdoc_files: []
|
125
125
|
files:
|
126
126
|
- lib/r2dsvg.rb
|
127
|
+
- lib/r2dsvg/r2dsvg_module.rb
|
127
128
|
homepage: https://github.com/jrobertson/r2dsvg
|
128
129
|
licenses:
|
129
130
|
- MIT
|
metadata.gz.sig
CHANGED
Binary file
|