r2dsvg 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 218f3f75c56256cfbf3ccd9f0755d31bfad7ec53ae8a235e32103118de2fc8e9
4
- data.tar.gz: 21aba9150ca1a85bfe48352c02e5bac17b276de41133b97d4e887a823bd85a2d
3
+ metadata.gz: 77a1f9080662cecab28ea1d9c25339855890367e95769b10d4232d5378ca8609
4
+ data.tar.gz: a7a1411bf0797a7312c368665e1f3d259f58d326fe551515686715bf9ef6b81a
5
5
  SHA512:
6
- metadata.gz: 0250d7a5f4a76af1811e16ad9d38a9e9be12a13708abf20698876a5a94d22fa293ce94bb879d19f900fa802e78b85e73c8eedc455418cf7dd7685f70938a9181
7
- data.tar.gz: 8fe0f560dddc4f193338019384356665170fb130a08f03407a3dda0709d03e4b91ed3fbf40c7cb2a0911344a915ab0aa6b9d92b6c28db584e3654a7c1c349200
6
+ metadata.gz: 9c33d412244025915719fe9a16cd2ac2b948d20be3560c4211c028e6f603da19d6bcc7479e58c89eb3255142b5ed224ea330d1933510df42f342f4d08b673dce
7
+ data.tar.gz: de8edc84cac33d6c3bb857709bc4ca63152a3ae5560dcce0c766f5440d9a94fe7dc22e08f01036a87c64cd9a0341a98bcfae55eaeb3403d34f01af6c85d7cf16
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.0
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