dyi 0.0.2 → 1.0.0

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.
@@ -64,13 +64,13 @@ module DYI #:nodoc:
64
64
 
65
65
  def puts(io=$>)
66
66
  StringFormat.set_default_formats(:color=>['%.3f %.3f %.3f', true], :length=>'0.### U', :coordinate=>'x y') {
67
- if @canvas.root_node?
67
+ if @canvas.root_element?
68
68
  io << header_comment
69
69
  io << prolog
70
70
  io << base_transform
71
71
  end
72
72
  @canvas.write_as(self, io)
73
- if @canvas.root_node?
73
+ if @canvas.root_element?
74
74
  io << footer_comment
75
75
  end
76
76
  }
@@ -25,11 +25,15 @@ module DYI #:nodoc:
25
25
  module Formatter #:nodoc:
26
26
 
27
27
  class SvgFormatter < XmlFormatter
28
+ include DYI::Script::EcmaScript::DomLevel2
28
29
 
29
30
  def initialize(canvas, indent=0, level=0, version='1.1')
30
31
  super(canvas, indent, level)
31
- raise ArgumentError, "version `#{version}' is unknown version" unless ['1.0', '1.1'].include?(@version = version.to_s)
32
+ unless ['1.0', '1.1'].include?(@version = version.to_s)
33
+ raise ArgumentError, "version `#{version}' is unknown version"
34
+ end
32
35
  @defs = {}
36
+ @text_border_elements = []
33
37
  end
34
38
 
35
39
  def declaration
@@ -47,21 +51,62 @@ module DYI #:nodoc:
47
51
 
48
52
  def write_canvas(canvas, io)
49
53
  @defs = {}
54
+ @xmlns = {:xmlns => "http://www.w3.org/2000/svg"}
55
+ pre_write
56
+ unless @text_border_elements.empty?
57
+ @canvas.add_initialize_script(draw_text_border(*@text_border_elements))
58
+ end
59
+ attrs = @xmlns.merge(:version => @version,
60
+ :width => canvas.real_width,
61
+ :height => canvas.real_height,
62
+ :viewBox => canvas.view_box,
63
+ :preserveAspectRatio => canvas.preserve_aspect_ratio)
64
+ attrs[:'pointer-events'] = 'none' if canvas.receive_event?
65
+ attrs[:class] = canvas.css_class if canvas.css_class
66
+ canvas.event_listeners.each do |event_name, listeners|
67
+ unless listeners.empty?
68
+ methods = listeners.map do |listener|
69
+ if listener.name
70
+ "#{listener.name}(#{listener.arguments.join(',')})"
71
+ end
72
+ end
73
+ attrs["on#{event_name}"] = methods.compact.join(';')
74
+ end
75
+ end
50
76
  sio = StringIO.new
51
- create_node(sio, 'svg',
52
- :xmlns => "http://www.w3.org/2000/svg",
53
- :version => @version,
54
- :width => canvas.real_width,
55
- :height => canvas.real_height,
56
- :viewBox => canvas.view_box,
57
- :preserveAspectRatio => canvas.preserve_aspect_ratio) {
77
+ create_node(sio, 'svg', attrs) {
58
78
  @root_info = [sio.pos, @level]
79
+ i = 0
80
+ length = canvas.scripts.size
81
+ while i < length
82
+ script = canvas.scripts[i]
83
+ if script.include_external_file?
84
+ create_leaf_node(sio, 'script',
85
+ :'xlink:href' => script.href,
86
+ :type => script.content_type)
87
+ break if length <= (i += 1)
88
+ script = canvas.scripts[i]
89
+ else
90
+ content_type = script.content_type
91
+ create_cdata_node(sio, 'script',
92
+ :type => content_type) {
93
+ sio << script.body
94
+ if (i += 1) < length
95
+ script = canvas.scripts[i]
96
+ while !script.has_uri_reference? && content_type == script.content_type
97
+ sio << script.body
98
+ break if length <= (i += 1)
99
+ script = canvas.scripts[i]
100
+ end
101
+ end
102
+ }
103
+ end
104
+ end
59
105
  canvas.child_elements.each do |element|
60
106
  element.write_as(self, sio)
61
107
  end
62
108
  }
63
-
64
- if @defs.empty?
109
+ if @defs.empty? && !@canvas.stylesheets.any?{|style| !style.include_external_file?}
65
110
  io << sio.string
66
111
  else
67
112
  sio.rewind
@@ -70,6 +115,9 @@ module DYI #:nodoc:
70
115
  _level = @level
71
116
  @level = @root_info[1]
72
117
  create_node(io, 'defs') {
118
+ @canvas.stylesheets.each do |stylesheet|
119
+ stylesheet.write_as(self, io)
120
+ end
73
121
  @defs.each do |def_id, def_item|
74
122
  def_item.write_as(self, io)
75
123
  end
@@ -81,94 +129,198 @@ module DYI #:nodoc:
81
129
  end
82
130
 
83
131
  def write_rectangle(shape, io)
84
- attrs = {:x=>shape.left, :y=>shape.top, :width=>shape.width, :height=>shape.height}
132
+ attrs = {:x=>shape.left,
133
+ :y=>shape.top,
134
+ :width=>shape.width,
135
+ :height=>shape.height}
85
136
  attrs.merge!(common_attributes(shape))
86
137
  attrs[:rx] = shape.attributes[:rx] if shape.attributes[:rx]
87
138
  attrs[:ry] = shape.attributes[:ry] if shape.attributes[:ry]
88
- create_leaf_node(io, 'rect', attrs)
139
+ write_node(shape, io, attrs, 'rect')
89
140
  end
90
141
 
91
142
  def write_circle(shape, io)
92
143
  attrs = {:cx=>shape.center.x, :cy=>shape.center.y, :r=>shape.radius}
93
144
  attrs.merge!(common_attributes(shape))
94
- create_leaf_node(io, 'circle', attrs)
145
+ write_node(shape, io, attrs, 'circle')
95
146
  end
96
147
 
97
148
  def write_ellipse(shape, io)
98
- attrs = {:cx=>shape.center.x, :cy=>shape.center.y, :rx=>shape.radius_x, :ry=>shape.radius_y}
149
+ attrs = {:cx=>shape.center.x,
150
+ :cy=>shape.center.y,
151
+ :rx=>shape.radius_x,
152
+ :ry=>shape.radius_y}
99
153
  attrs.merge!(common_attributes(shape))
100
- create_leaf_node(io, 'ellipse', attrs)
154
+ write_node(shape, io, attrs, 'ellipse')
101
155
  end
102
156
 
103
157
  def write_line(shape, io)
104
- attrs = {:x1 => shape.start_point.x, :y1 => shape.start_point.y, :x2 => shape.end_point.x, :y2 => shape.end_point.y}
158
+ attrs = {:x1 => shape.start_point.x,
159
+ :y1 => shape.start_point.y,
160
+ :x2 => shape.end_point.x,
161
+ :y2 => shape.end_point.y}
105
162
  attrs.merge!(common_attributes(shape))
106
- create_leaf_node(io, 'line', attrs)
163
+ write_node(shape, io, attrs, 'line')
107
164
  end
108
165
 
109
166
  def write_polyline(shape, io)
110
167
  attrs = {:points => shape.points.join(' ')}
111
168
  attrs.merge!(common_attributes(shape))
112
- create_leaf_node(io, 'polyline', attrs)
169
+ write_node(shape, io, attrs, 'polyline')
113
170
  end
114
171
 
115
172
  def write_polygon(shape, io)
116
173
  attrs = {:points => shape.points.join(' ')}
117
174
  attrs.merge!(common_attributes(shape))
118
- create_leaf_node(io, 'polygon', attrs)
175
+ write_node(shape, io, attrs, 'polygon')
119
176
  end
120
177
 
121
178
  def write_path(shape, io)
122
179
  attrs = {:d => shape.concise_path_data}
123
180
  attrs.merge!(common_attributes(shape))
124
- create_leaf_node(io, 'path', attrs)
181
+ write_node(shape, io, attrs, 'path')
125
182
  end
126
183
 
127
- def write_text(shape, io)
128
- attrs = {:x => shape.point.x, :y => shape.point.y}
184
+ # @since 1.0.0
185
+ def write_image(shape, io)
186
+ attrs = {:x=>shape.left,
187
+ :y=>shape.top,
188
+ :width=>shape.width,
189
+ :height=>shape.height}
190
+ if shape.include_external_file?
191
+ attrs[:'xlink:href'] = shape.file_path
192
+ else
193
+ content_type = shape.attributes[:content_type].to_s
194
+ content_type = if content_type.empty?
195
+ shape.file_path =~ /\.([^\.]+)\z/
196
+ case $1
197
+ when 'png'
198
+ 'image/png'
199
+ when 'jpg', 'jpeg'
200
+ 'image/jpeg'
201
+ else
202
+ 'image/svg+xml'
203
+ end
204
+ else
205
+ case content_type
206
+ when 'svg'
207
+ 'image/svg+xml'
208
+ when 'png'
209
+ 'image/png'
210
+ when 'jpeg'
211
+ 'image/jpeg'
212
+ else
213
+ content_type
214
+ end
215
+ end
216
+ open(shape.file_path, 'rb') {|f|
217
+ content = f.read
218
+ attrs[:'xlink:href'] =
219
+ ['data:', content_type, ";base64,\n", [content].pack('m')[0..-2]].join
220
+ }
221
+ end
129
222
  attrs.merge!(common_attributes(shape))
130
- attrs[:"text-decoration"] = shape.attributes[:text_decoration] if shape.attributes[:text_decoration]
131
- # attrs[:"alignment-baseline"] = shape.attributes[:alignment_baseline] if shape.attributes[:alignment_baseline]
132
- case shape.attributes[:alignment_baseline]
133
- when 'top' then attrs[:y] += shape.font_height * 0.85
134
- when 'middle' then attrs[:y] += shape.font_height * 0.35
135
- when 'bottom' then attrs[:y] -= shape.font_height * 0.15
136
- end
137
- attrs[:"text-anchor"] = shape.attributes[:text_anchor] if shape.attributes[:text_anchor]
138
- attrs[:"writing-mode"] = shape.attributes[:writing_mode] if shape.attributes[:writing_mode]
139
- attrs[:textLength] = shape.attributes[:textLength] if shape.attributes[:textLength]
140
- attrs[:lengthAdjust] = shape.attributes[:lengthAdjust] if shape.attributes[:lengthAdjust]
223
+ attrs.reject! do |key, value|
224
+ key.to_s =~ /^(fill|stroke)/
225
+ end
226
+ attrs[:preserveAspectRatio] = shape.attributes[:preserve_aspect_ratio] || 'none'
227
+ write_node(shape, io, attrs, 'image')
228
+ end
229
+
230
+ def write_text(shape, io)
231
+ attrs = common_attributes(shape)
232
+ if shape.attributes[:text_decoration]
233
+ attrs[:"text-decoration"] = shape.attributes[:text_decoration]
234
+ end
235
+ if shape.attributes[:text_anchor]
236
+ attrs[:"text-anchor"] = shape.attributes[:text_anchor]
237
+ end
238
+ if shape.attributes[:writing_mode]
239
+ attrs[:"writing-mode"] = shape.attributes[:writing_mode]
240
+ end
241
+ if shape.attributes[:textLength]
242
+ attrs[:textLength] = shape.attributes[:textLength]
243
+ end
244
+ if shape.attributes[:lengthAdjust]
245
+ attrs[:lengthAdjust] = shape.attributes[:lengthAdjust]
246
+ end
247
+
141
248
  text = shape.formated_text
142
- if text =~ /(\r\n|\n|\r)/
143
- create_node(io, 'text', attrs) {
144
- create_leaf_node(io, 'tspan', $`.strip, :x => shape.point.x)
145
- $'.each_line do |line|
146
- create_leaf_node(io, 'tspan', line.strip, :x => shape.point.x, :dy => shape.dy)
147
- end
249
+ if text =~ /(\r\n|\n|\r)/ || shape.animate? || shape.attributes[:show_border]
250
+ shape.publish_id if shape.attributes[:show_border]
251
+ create_text_group = proc {|tag_name, attrs|
252
+ create_node(io, tag_name, attrs) {
253
+ create_border_node(shape, io)
254
+ line_number = 0
255
+ txt_attrs = {:x => shape.point.x, :y => shape.point.y}
256
+ # FIXME: Implementation of baseline attribute are not suitable
257
+ case shape.attributes[:alignment_baseline]
258
+ when 'top' then txt_attrs[:y] += shape.font_height * 0.85
259
+ when 'middle' then txt_attrs[:y] += shape.font_height * 0.35
260
+ when 'bottom' then txt_attrs[:y] -= shape.font_height * 0.15
261
+ end
262
+ txt_attrs[:id] = shape.id + '_%02d' % line_number if shape.inner_id
263
+ current_line = $` || text
264
+ create_leaf_node(io, 'text', current_line.strip, txt_attrs)
265
+ $'.each_line do |line|
266
+ line_number += 1
267
+ txt_attrs = {:x => txt_attrs[:x], :y => txt_attrs[:y] + shape.dy}
268
+ txt_attrs[:id] = shape.id + '_%02d' % line_number if shape.inner_id
269
+ create_leaf_node(io, 'text', line.strip, txt_attrs)
270
+ end if $'
271
+ write_animations(shape, io)
272
+ }
148
273
  }
274
+ if shape.anchor_href
275
+ attrs[:'xlink:href'] = shape.anchor_href
276
+ attrs[:target] = shape.anchor_target if shape.anchor_target
277
+ create_text_group.call('a', attrs)
278
+ else
279
+ create_text_group.call('g', attrs)
280
+ end
149
281
  else
150
- create_leaf_node(io, 'text', text, attrs)
282
+ create_text_group = proc {
283
+ attrs.merge!(:x => shape.point.x, :y => shape.point.y)
284
+ # FIXME: Implementation of baseline attribute are not suitable
285
+ case shape.attributes[:alignment_baseline]
286
+ when 'top' then attrs[:y] += shape.font_height * 0.85
287
+ when 'middle' then attrs[:y] += shape.font_height * 0.35
288
+ when 'bottom' then attrs[:y] -= shape.font_height * 0.15
289
+ end
290
+ create_leaf_node(io, 'text', text, attrs)
291
+ }
292
+ if shape.anchor_href
293
+ link_attrs = {:'xlink:href' => shape.anchor_href}
294
+ link_attrs[:target] = shape.anchor_target if shape.anchor_target
295
+ create_node(io, 'a', link_attrs) {
296
+ create_text_group.call
297
+ }
298
+ else
299
+ create_text_group.call
300
+ end
151
301
  end
152
302
  end
153
303
 
154
304
  def write_group(shape, io)
155
- create_node(io, 'g', common_attributes(shape)) {
156
- shape.child_elements.each do |element|
157
- element.write_as(self, io)
158
- end
159
- } unless shape.child_elements.empty?
305
+ unless shape.child_elements.empty?
306
+ attrs = common_attributes(shape)
307
+ write_node(shape, io, attrs, 'g') {
308
+ shape.child_elements.each do |element|
309
+ element.write_as(self, io)
310
+ end
311
+ }
312
+ end
160
313
  end
161
314
 
162
315
  def write_linear_gradient(shape, io)
163
- attr = {
164
- :id => @defs.find{|key, value| value==shape}[0],
165
- :gradientUnit => 'objectBoundingBox',
166
- :x1 => shape.start_point[0],
167
- :y1 => shape.start_point[1],
168
- :x2 => shape.stop_point[0],
169
- :y2 => shape.stop_point[1]}
170
- attr[:"spreadMethod"] = shape.spread_method if shape.spread_method
171
- create_node(io, 'linearGradient', attr) {
316
+ attrs = {:id => @defs.find{|key, value| value==shape}[0],
317
+ :gradientUnit => 'objectBoundingBox',
318
+ :x1 => shape.start_point[0],
319
+ :y1 => shape.start_point[1],
320
+ :x2 => shape.stop_point[0],
321
+ :y2 => shape.stop_point[1]}
322
+ attrs[:"spreadMethod"] = shape.spread_method if shape.spread_method
323
+ create_node(io, 'linearGradient', attrs) {
172
324
  shape.child_elements.each do |element|
173
325
  element.write_as(self, io)
174
326
  end
@@ -183,43 +335,232 @@ module DYI #:nodoc:
183
335
  end
184
336
 
185
337
  def write_clipping(clipping, io)
186
- attr = {:id => @defs.find{|key, value| value==clipping}[0]}
187
- create_node(io, 'clipPath', attr) {
338
+ attrs = {:id => clipping.id}
339
+ create_node(io, 'clipPath', attrs) {
188
340
  clipping.shapes.each_with_index do |shape, i|
189
341
  shape.write_as(self, io)
190
342
  end
191
343
  }
192
344
  end
193
345
 
346
+ # @since 1.0.0
347
+ def write_painting_animation(anim, shape, io)
348
+ anim.animation_attributes.each do |anim_attr, (from_value, to_value)|
349
+ attrs = {:attributeName => name_to_attribute(anim_attr),
350
+ :attributeType => 'CSS'}
351
+ attrs[:from] = from_value if from_value
352
+ attrs[:to] = to_value
353
+ merge_anim_attributes(anim, shape, attrs)
354
+ if anim.duration && anim.duration != 0
355
+ create_leaf_node(io, 'animate', attrs)
356
+ else
357
+ create_leaf_node(io, 'set', attrs)
358
+ end
359
+ end
360
+ end
361
+
362
+ # @since 1.0.0
363
+ def write_transform_animation(anim, shape, io)
364
+ attrs = {:attributeName => 'transform',
365
+ :attributeType => 'XML',
366
+ :type => anim.type}
367
+ if anim.from.is_a?(Array)
368
+ attrs[:from] = anim.from.join(',')
369
+ elsif anim.from
370
+ attrs[:from] = anim.from.to_s
371
+ end
372
+ attrs[:to] = anim.to.is_a?(Array) ? anim.to.join(',') : anim.to.to_s
373
+ merge_anim_attributes(anim, shape, attrs)
374
+ if anim.duration && anim.duration != 0
375
+ create_leaf_node(io, 'animateTransform', attrs)
376
+ else
377
+ create_leaf_node(io, 'set', attrs)
378
+ end
379
+ end
380
+
381
+ # @since 1.0.0
382
+ def write_script(script, io)
383
+ if script.include_external_file?
384
+ create_leaf_node(io, 'script',
385
+ :'xlink:href' => script.href,
386
+ :type => script.content_type)
387
+ else
388
+ io << script.body
389
+ end
390
+ end
391
+
392
+ # @since 1.0.0
393
+ def write_style(stylesheet, io)
394
+ unless stylesheet.include_external_file?
395
+ attrs = {:type => stylesheet.content_type}
396
+ attrs[:media] = stylesheet.media if stylesheet.media
397
+ attrs[:title] = stylesheet.title if stylesheet.title
398
+ create_cdata_node(io, 'style', attrs){
399
+ io << stylesheet.body
400
+ }
401
+ end
402
+ end
403
+
194
404
  private
195
405
 
406
+ # @since 1.0.0
407
+ def write_node(shape, io, attrs, tag_name, &create_child_node)
408
+ if shape.anchor_href
409
+ link_attrs = {:'xlink:href' => shape.anchor_href}
410
+ link_attrs[:target] = shape.anchor_target if shape.anchor_target
411
+ create_node(io, 'a', link_attrs) {
412
+ write_shape_node(shape, io, attrs, tag_name, &create_child_node)
413
+ }
414
+ else
415
+ write_shape_node(shape, io, attrs, tag_name, &create_child_node)
416
+ end
417
+ end
418
+
419
+ # @since 1.0.0
420
+ def write_shape_node(shape, io, attrs, tag_name, &create_child_node)
421
+ if shape.animate? || block_given?
422
+ create_node(io, tag_name, attrs) {
423
+ yield if block_given?
424
+ write_animations(shape, io)
425
+ }
426
+ else
427
+ create_leaf_node(io, tag_name, attrs)
428
+ end
429
+ end
430
+
431
+ # @since 1.0.0
432
+ def write_animations(shape, io)
433
+ if shape.animate?
434
+ shape.animations.each do |anim|
435
+ anim.write_as(self, shape, io)
436
+ end
437
+ end
438
+ end
439
+
440
+ # @since 1.0.0
441
+ def create_border_node(shape, io)
442
+ if shape.attributes[:show_border]
443
+ attrs = {:id => shape.id + '_bd', :x => 0, :y => 0, :width => 0, :height => 0}
444
+ attrs[:rx] = shape.attributes[:border_rx] if shape.attributes[:border_rx]
445
+ attrs[:ry] = shape.attributes[:border_ry] if shape.attributes[:border_ry]
446
+ attrs[:fill] = shape.attributes[:background_color] || Color.new('white')
447
+ attrs[:stroke] = shape.attributes[:border_color] || Color.new('black')
448
+ attrs[:'stroke-width'] = shape.attributes[:border_width] || 1
449
+ create_leaf_node(io, 'rect', attrs)
450
+ end
451
+ end
452
+
453
+ # Examines the descendant elements of the canvas to collect the
454
+ # information of the elements.
455
+ # @return [void]
456
+ # @since 1.0.0
457
+ def pre_write
458
+ if @canvas.scripts.any?{|script| script.has_uri_reference?}
459
+ @xmlns[:'xmlns:xlink'] = "http://www.w3.org/1999/xlink"
460
+ end
461
+ examin_descendant_elements(@canvas)
462
+ end
463
+
464
+ # @since 1.0.0
465
+ def examin_descendant_elements(element)
466
+ if element.has_uri_reference?
467
+ @xmlns[:'xmlns:xlink'] = "http://www.w3.org/1999/xlink"
468
+ end
469
+ if element.respond_to?(:clipping) && element.clipping
470
+ unless @defs.value?(element.clipping)
471
+ def_id = element.clipping.id
472
+ @defs[def_id] = element.clipping
473
+ end
474
+ end
475
+ if element.respond_to?(:attributes) && element.attributes[:show_border]
476
+ @text_border_elements << element
477
+ end
478
+ element.child_elements.each do |child_element|
479
+ examin_descendant_elements(child_element)
480
+ end
481
+ end
482
+
483
+ # @since 1.0.0
484
+ def anim_duration(timecount)
485
+ return nil if timecount.nil? || timecount < 0
486
+ return '0s' if timecount == 0
487
+ timecount_ms = (timecount * 1000).to_i
488
+ if timecount_ms % (1000 * 60 * 60) == 0
489
+ '%ih' % (timecount_ms / (1000 * 60 * 60))
490
+ elsif timecount_ms % (1000 * 60) == 0
491
+ '%imin' % (timecount_ms / (1000 * 60))
492
+ elsif timecount_ms % 1000 == 0
493
+ '%is' % (timecount_ms / 1000)
494
+ else
495
+ '%ims' % timecount_ms
496
+ end
497
+ end
498
+
499
+ # @since 1.0.0
500
+ def amin_event(shape, event)
501
+ return nil unless event
502
+ if shape && shape == event.target
503
+ event.event_name.to_s
504
+ else
505
+ [event.target.id.gsub(/([\.\-\:])/, '\\\\\\1'), event.event_name.to_s].join('.')
506
+ end
507
+ end
508
+
509
+ # @since 1.0.0
510
+ def anim_period(shape, event, offset)
511
+ [amin_event(shape, event), anim_duration(offset)].compact.join('+')
512
+ end
513
+
514
+ # @return [void]
515
+ # @since 1.0.0
516
+ def merge_anim_attributes(anim, shape, attrs) #:nodoc:
517
+ attrs[:dur] = anim_duration(anim.duration) if anim.duration && anim.duration != 0
518
+ if anim.begin_event || anim.begin_offset
519
+ attrs[:begin] = anim_period(shape, anim.begin_event, anim.begin_offset)
520
+ else
521
+ attrs[:begin] = '0s'
522
+ end
523
+ if anim.end_event || anim.end_offset
524
+ attrs[:end] = anim_period(shape, anim.end_event, anim.end_offset)
525
+ end
526
+ attrs[:fill] = anim.fill if anim.fill
527
+ attrs[:additive] = anim.additive if anim.additive
528
+ attrs[:restart] = anim.restart if anim.restart
529
+ end
530
+
196
531
  def name_to_attribute(name) #:nodoc:
197
532
  name.to_s.gsub(/_/,'-').to_sym
198
533
  end
199
534
 
200
535
  def common_attributes(shape) #:nodoc:
201
536
  attributes = {}
202
- style = create_style(shape)
537
+ create_style(shape, attributes)
538
+ attributes[:class] = shape.css_class unless shape.css_class.empty?
203
539
  transform = create_transform(shape)
204
- clip_path = create_clip_path(shape)
205
- attributes[:style] = style if style
206
540
  attributes[:transform] = transform if transform
207
- attributes[:'clip-path'] = clip_path if clip_path
541
+ attributes[:'clip-path'] = "url(##{shape.clipping.id})" if shape.clipping
542
+ attributes[:id] = shape.id if shape.inner_id
543
+ attributes[:'pointer-events'] = 'all' if shape.event_target?
208
544
  attributes
209
545
  end
210
546
 
211
- def create_style(shape) #:nodoc:
547
+ def create_style(shape, attributes) #:nodoc:
212
548
  styles = {}
213
- if shape.respond_to?(:font) && shape.font && !shape.font.empty?
549
+ if shape.font && !shape.font.empty?
214
550
  styles.merge!(shape.font.attributes)
215
551
  end
216
- if shape.respond_to?(:painting) && shape.painting && !shape.painting.empty?
217
- attributes = shape.painting.attributes
218
- attributes[:stroke_dasharray] = attributes[:stroke_dasharray].join(',') if attributes.key?(:stroke_dasharray)
219
- attributes[:fill] = 'none' unless attributes.key?(:fill)
220
- styles.merge!(attributes)
552
+ if shape.painting && !shape.painting.empty?
553
+ painting_attrs = shape.painting.attributes
554
+ if painting_attrs.key?(:stroke_dasharray)
555
+ painting_attrs[:stroke_dasharray] =
556
+ painting_attrs[:stroke_dasharray].join(',')
557
+ end
558
+ painting_attrs[:fill] = 'none' unless painting_attrs.key?(:fill)
559
+ styles.merge!(painting_attrs)
560
+ end
561
+ styles.each do |key, value|
562
+ attributes[attribute_name(key)] = attribute_string(value)
221
563
  end
222
- styles.empty? ? nil : styles.map {|key, value| "#{attribute_name(key)}:#{attribute_string(value)}"}.join(';')
223
564
  end
224
565
 
225
566
  def attribute_string(value) #:nodoc:
@@ -232,12 +573,6 @@ module DYI #:nodoc:
232
573
  end
233
574
  end
234
575
 
235
- def create_clip_path(shape) #:nodoc:
236
- if shape.respond_to?(:clipping) && shape.clipping
237
- "url(##{add_defs(shape.clipping)})"
238
- end
239
- end
240
-
241
576
  def add_defs(value) #:nodoc:
242
577
  @defs.each do |def_id, def_item|
243
578
  return def_id if def_item == value
@@ -255,5 +590,26 @@ module DYI #:nodoc:
255
590
  key.to_s.gsub(/_/,'-')
256
591
  end
257
592
  end
593
+
594
+ class PngFormatter
595
+ def save(file_name, options={})
596
+ tmp_svg_file = [file_name, Time.now.strftime('%Y%m%d%H%M%S'), 'tmp'].join('.')
597
+ @svg_formatter.save(tmp_svg_file, options)
598
+ `rsvg-convert -o #{file_name} #{tmp_svg_file}`
599
+ File.delete(tmp_svg_file)
600
+ end
601
+
602
+ def string
603
+ tmp_svg_file = [Time.now.strftime('%Y%m%d%H%M%S'), 'tmp'].join('.')
604
+ @svg_formatter.save(tmp_svg_file)
605
+ png_data = `rsvg-convert #{tmp_svg_file}`
606
+ File.delete(tmp_svg_file)
607
+ png_date
608
+ end
609
+
610
+ def initialize(*args)
611
+ @svg_formatter = SvgFormatter.new(*args)
612
+ end
613
+ end
258
614
  end
259
615
  end