dyi 1.2.1 → 1.3.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.
@@ -3,25 +3,32 @@
3
3
  require 'rubygems'
4
4
  require 'dyi'
5
5
 
6
- chart = DYI::Chart::PieChart.new 400,500,
7
- :data_label_format => "{?name}\n{?percent}",
8
- :data_label_font => {:size => 20, :font_family=>'Serif'},
9
- :represent_3d => true,
10
- :show_data_label => false,
11
- :show_baloon => true,
12
- :baloon_opacity => 0.3,
13
- :baloon_format => "{?name}\n{?percent}",
14
- # :moved_elements => [0.2,nil,nil,0.5],
15
- # :chart_colors => ['blue', 'red', 'yellow', 'green'],
16
- :_3d_settings => {:dy => 30},
17
- :background_image_opacity => 0.1,
18
- :legend_format => "{?name}\t{!e}{?value:#,##0}\t{!e}({?percent:0.00%})",
19
- :chart_stroke_color => 'white'
6
+ # Nominal GDP of Asian Countries (2010)
7
+ chart_data = [['China', 5878],
8
+ ['Japan', 5459],
9
+ ['India', 1538],
10
+ ['South Koria', 1007],
11
+ ['Other Countries', 2863]]
12
+ reader = DYI::Chart::ArrayReader.read(chart_data, :schema => [:name, :value])
20
13
 
21
- reader = DYI::Chart::ExcelReader.read('data/currency.xlsx', :schema => [:name, :value])
22
- chart.load_data reader
14
+ # Creates the Pie Chart
15
+ chart = DYI::Chart::PieChart.new(500,240,
16
+ :center_point => [130, 130],
17
+ :legend_point => [250, 80],
18
+ :chart_radius_x => 100,
19
+ :show_data_label => false,
20
+ :represent_3d => true,
21
+ :_3d_settings => {:dy => 20},
22
+ :baloon_format => "{?name}\n{?value:#,0}",
23
+ :legend_format => "{?name}\t{!e}{?value:#,0}\t{!e}({?percent:0.0%})",
24
+ :chart_stroke_color => 'white',
25
+ :background_image_file => {:path => 'external_files/asian_map.png', :content_type => 'image/png'},
26
+ :background_image_opacity => 0.3)
27
+ chart.load_data(reader)
28
+ DYI::Drawing::Pen.black_pen.draw_text(chart.canvas,
29
+ [250, 40],
30
+ 'Nominal GDP of Asian Countries (2010)',
31
+ :text_anchor => 'middle',
32
+ :font => {:font_family => 'sans-serif', :size => '14pt', :weight => 'bold'})
23
33
 
24
- chart.save 'output/pie_chart.svg'
25
- chart.save 'output/pie_chart.xaml', :xaml
26
- chart.save 'output/pie_chart.eps', :eps
27
- chart.save 'output/pie_chart.emf', :emf if defined? IRONRUBY_VERSION
34
+ chart.save('output/pie_chart.svg')
@@ -0,0 +1,31 @@
1
+ # -*- encoding: UTF-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'dyi'
5
+
6
+ canvas = DYI::Canvas.new(500, 280)
7
+ canvas.title = 'Rainbow'
8
+ canvas.description = 'This image is a sample of DYI which uses a radial gradient.'
9
+
10
+ logo_container = DYI::Shape::ShapeGroup.draw_on(canvas)
11
+ DYI.logo(:canvas => logo_container,
12
+ :width => 287,
13
+ :height => 163,
14
+ :top => 100,
15
+ :left => 160)
16
+
17
+ gradient = DYI::Drawing::ColorEffect::RadialGradient.new([1,1.2], 1.2)
18
+ gradient.add_color_opacity(0.72, 'violet', 0)
19
+ gradient.add_color_opacity(0.74, 'violet', 0.5)
20
+ gradient.add_color_opacity(0.78, 'indigo', 0.5)
21
+ gradient.add_color_opacity(0.82, 'blue', 0.5)
22
+ gradient.add_color_opacity(0.86, 'green', 0.5)
23
+ gradient.add_color_opacity(0.9, 'yellow', 0.5)
24
+ gradient.add_color_opacity(0.94, 'orange', 0.5)
25
+ gradient.add_color_opacity(0.98, 'red', 0.5)
26
+ gradient.add_color_opacity(1, 'red', 0)
27
+
28
+ pen = DYI::Drawing::Brush.new(:color => gradient)
29
+ pen.draw_rectangle(canvas, [0,0], 500, 280)
30
+
31
+ canvas.save('output/rainbow.svg')
@@ -0,0 +1,28 @@
1
+ # -*- encoding: UTF-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'dyi'
5
+
6
+ canvas = DYI::Canvas.new(400, 300)
7
+
8
+ rect = DYI::Drawing::Brush.new(:color=>'#51ADE2').draw_rectangle(canvas, [10,10], 300, 200)
9
+ rect.add_painting_animation(:from => {:fill => '#51ADE2'},
10
+ :to => {:fill => 'red'},
11
+ :duration => 3,
12
+ :begin_event => DYI::Event.mouseover(rect),
13
+ :end_event => DYI::Event.mouseout(rect),
14
+ :fill => 'freeze')
15
+ text = DYI::Drawing::Brush.new.draw_text(canvas,
16
+ [100,250],
17
+ 'click me!',
18
+ :show_border => true,
19
+ :border_color=>'#325BA8',
20
+ :padding => 8,
21
+ :border_rx => 10,
22
+ :border_width => 3,
23
+ :background_color=>'#A5C7F8')
24
+ rect.add_painting_animation(:to => {:fill => 'green'},
25
+ :begin_event => DYI::Event.click(text),
26
+ :fill => 'freeze')
27
+
28
+ canvas.save('output/simple_animation.svg')
@@ -0,0 +1,73 @@
1
+ # -*- encoding: UTF-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'dyi'
5
+
6
+ include DYI::Script::EcmaScript::DomLevel2
7
+
8
+ canvas = DYI::Canvas.new(500, 280)
9
+
10
+ base_pen = DYI::Drawing::Pen.new(:font => {:size => '14pt'})
11
+
12
+ symbols = []
13
+
14
+ symbol = DYI::Shape::GraphicalTemplate.new(400,170)
15
+ pen = DYI::Drawing::Pen.new(:color => 'blue', :width => 10)
16
+ pen.draw_rectangle(symbol, [50, 40], 300, 90, :rx => 30)
17
+ base_pen.draw_text(symbol, [200, 25], 'Rounded Rectangle', :text_anchor => 'middle')
18
+ base_pen.draw_text(symbol, [200, 160], 'page 1', :text_anchor => 'middle')
19
+ symbols << symbol
20
+
21
+ symbol = DYI::Shape::GraphicalTemplate.new(400,170)
22
+ pen = DYI::Drawing::Pen.new(:color => 'red', :width => 10)
23
+ pen.draw_ellipse(symbol, [200, 85], 150, 45)
24
+ base_pen.draw_text(symbol, [200, 25], 'Ellipse', :text_anchor => 'middle')
25
+ base_pen.draw_text(symbol, [200, 160], 'page 2', :text_anchor => 'middle')
26
+ symbols << symbol
27
+
28
+ symbol = DYI::Shape::GraphicalTemplate.new(400,170)
29
+ pen = DYI::Drawing::Pen.new(:color => 'green', :width => 10)
30
+ pen.draw_polygon(symbol, [[200, 40], [150, 60], [150, 110], [200, 130], [250, 110], [250, 60]])
31
+ base_pen.draw_text(symbol, [200, 25], 'Hexagon', :text_anchor => 'middle')
32
+ base_pen.draw_text(symbol, [200, 160], 'page 3', :text_anchor => 'middle')
33
+ symbols << symbol
34
+
35
+ symbol = DYI::Shape::GraphicalTemplate.new(400,170)
36
+ pen = DYI::Drawing::Pen.new(:color => 'orange', :width => 10)
37
+ pen.draw_path(symbol, [100, 85]){|path|
38
+ path.quadratic_curve_to([150, 0], [200, 85], [300, 85])
39
+ }
40
+ base_pen.draw_text(symbol, [200, 25], 'Wave', :text_anchor => 'middle')
41
+ base_pen.draw_text(symbol, [200, 160], 'page 4', :text_anchor => 'middle')
42
+ symbols << symbol
43
+
44
+ symbol = DYI::Shape::GraphicalTemplate.new(400,170)
45
+ brush = DYI::Drawing::Brush.cyan_brush
46
+ brush.draw_circle(symbol, [200, 85], 50).add_transform_animation(:translate,
47
+ :from => [-100, 0],
48
+ :relays => [[100,0]],
49
+ :to => [-100, 0],
50
+ :relayTimes => [0.5],
51
+ :duration => 3,
52
+ :calc_mode => 'spline',
53
+ :key_splines => [0.6, 0, 0.4, 1, 0.6, 0, 0.4, 1],
54
+ :repeat_count => 0)
55
+ base_pen.draw_text(symbol, [200, 25], 'Animation Circle', :text_anchor => 'middle')
56
+ base_pen.draw_text(symbol, [200, 160], 'page 5', :text_anchor => 'middle')
57
+ symbols << symbol
58
+
59
+ current_use = symbols.first.instantiate_on(canvas, [50, 10], :width => 400, :height => 170)
60
+ base_pen.draw_rectangle(canvas, [50, 10], 400, 170)
61
+
62
+ symbols.each_with_index do |symbol, i|
63
+ group = DYI::Shape::ShapeGroup.draw_on(canvas)
64
+ rect = base_pen.draw_rectangle(group, [105 + i * 60, 190], 50, 50)
65
+ use = symbol.instantiate_on(group, [105 + i * 60, 190], :width => 50, :height => 50)
66
+ group.skew_y(35, [105 + i * 60, 190])
67
+ rect.add_event_listener(:click, <<-SCRIPT)
68
+ var currentUse = #{get_element(current_use)};
69
+ currentUse.setAttributeNS('http://www.w3.org/1999/xlink', 'href', "##{symbol.id = canvas.publish_shape_id}");
70
+ SCRIPT
71
+ end
72
+
73
+ canvas.save('output/thumbnail.svg')
@@ -0,0 +1,9 @@
1
+ # -*- encoding: UTF-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'dyi'
5
+
6
+ canvas = DYI.logo
7
+ canvas.reference_stylesheet_file('../external_files/xslt.xsl', 'text/xsl')
8
+
9
+ canvas.save('output/xslt.svg')
data/lib/dyi.rb CHANGED
@@ -24,11 +24,80 @@
24
24
  module DYI
25
25
 
26
26
  # DYI program version
27
- VERSION = '1.2.1'
27
+ VERSION = '1.3.0'
28
28
 
29
29
  # URL of DYI Project
30
30
  # @since 0.0.2
31
- URL = 'http://sourceforge.net/projects/dyi/'
31
+ URL = 'http://open-dyi.org/'
32
+
33
+ class << self
34
+
35
+ # Draw a DYI's logo.
36
+ # @option options [Canvas, Shape::ShapeGroup] :canvas a container element
37
+ # of the DYI's logo
38
+ # @option options [Length] :width a width of the logo mark
39
+ # @option options [Length] :height a height of the logo mark
40
+ # @option options [Length] :left a x-coordinate of a left edge of the logo
41
+ # mark
42
+ # @option options [Length] :top a y-coordinate of a top edge of the logo
43
+ # mark
44
+ # @return [Canvas, Shape::ShapeGroup] a new Canvas object which logo mark is
45
+ # draw on if :canvas option is given, otherwise a new Shape::Group object
46
+ # which logo mark is on.
47
+ # @since 1.3.0
48
+ def logo(options = {})
49
+ width = Length.new(options[:width] || 287)
50
+ height = Length.new(options[:height] || 163)
51
+ if options[:canvas]
52
+ canvas = Shape::ShapeGroup.draw_on(options[:canvas])
53
+ canvas.scale(width / 287, height / 163)
54
+ canvas.translate(options[:left] || 0, options[:top] || 0)
55
+ else
56
+ canvas = Canvas.new(width, height)
57
+ end
58
+ Drawing::Brush.new(:color=>'#51ADE2').draw_closed_path(canvas, [287,0]) {|path|
59
+ path.rline_to([0,162.637], [-39.41,0])
60
+ path.rcurve_to([0,-5.191], [-1.729,-107.272], [-1.729,-107.272], [-2.594,102.295], [-2.813,107.272])
61
+ path.rline_to([-3.246,0])
62
+ path.rcurve_to([0,-4.977], [-1.728,-107.272], [-1.728,-107.272], [-2.595,102.513], [-2.595,107.272])
63
+ path.rline_to([-3.245, 0])
64
+ path.rcurve_to([-0.215,-4.54], [-1.729,-107.272], [-1.729,-107.272], [-2.813,102.943], [-2.813,107.272])
65
+ path.rline_to([-3.46, 0], [0, -162.637])
66
+ }
67
+ Drawing::Brush.new(:color=>'#325BA8').draw_closed_path(canvas, [258.471,0]) {|path|
68
+ path.rline_to([-52.793,97.971], [-0.078,64.666], [-57.073,0], [-0.071,-65.106], [-49.789,-97.531],[92.148,0])
69
+ path.rcurve_to([-12.327,25.52], [-35.9,74.829], [-35.9,74.829], [27.034,-50.391], [40.013,-74.829])
70
+ path.rline_to([4.322,0])
71
+ path.rcurve_to([-11.461,24.221], [-37.414,78.289], [-37.414,78.289], [30.206,-55.798], [41.955,-78.289])
72
+ path.rline_to([4.111,0])
73
+ path.rcurve_to([-10.599,21.844], [-39.146,81.75], [-39.146,81.75], [33.306,-62.069], [43.687,-81.75])
74
+ }
75
+ Drawing::Brush.new(:color=>'#51ADE2', :rule => 'evenodd').draw_closed_path(canvas, [149.875,78.938]){|path|
76
+ path.rcurve_to([0,13.193], [-2.379,25.52], [-7.353,36.552], [-11.894,20.114], [-20.112,27.249])
77
+ path.rline_to([-0.216, 0])
78
+ path.rcurve_to([-9.517,7.786], [-20.113,12.76], [-31.144,15.787], [-22.276,4.111], [-33.954,4.111], [-22.276,-0.651], [-28.98,-1.514])
79
+ path.rline_to([-20.113, -2.815])
80
+ path.rcurve_to([12.327,-1.077], [34.17,-4.322], [54.5,-15.784])
81
+ path.rcurve_to([14.921,-8.219], [27.034,-21.627], [32.441,-33.524], [6.271,-20.543], [6.487,-20.543])
82
+ path.rcurve_to([-0.217,0], [-1.08,8.649], [-7.137,20.114], [-18.167,24.654], [-32.873,32.003])
83
+ path.rcurve_to([-25.953,13.411], [-54.067,13.84], [-61.421,13.84])
84
+ path.rline_to([0, -3.241])
85
+ path.rcurve_to([7.137,-0.215], [34.82,-1.729], [58.827,-15.355])
86
+ path.rcurve_to([29.844,-14.921], [35.9,-49.526], [35.035,-48.661])
87
+ path.rcurve_to([0.866,-0.866], [-6.487,33.303], [-36.117,46.714])
88
+ path.rcurve_to([-23.791,12.327], [-50.608,12.976], [-57.745,12.976])
89
+ path.rline_to([0, -3.246])
90
+ path.rcurve_to([6.92,-0.211], [33.307,-1.942], [55.15,-14.488])
91
+ path.rcurve_to([26.168,-13.193], [31.358,-41.955], [31.358,-43.254])
92
+ path.rcurve_to([0,1.299], [-6.487,29.631], [-32.44,41.311])
93
+ path.rcurve_to([-21.628,11.242], [-47.148,12.108], [-54.068,12.108])
94
+ path.rline_to([0,-132.574])
95
+ path.rline_to([27.25, -4.326])
96
+ path.rcurve_to([10.381,-1.731], [22.06,-2.378], [34.604,-2.378], [21.194,0.864], [31.36,3.677], [19.464,6.92], [27.25,12.975], [16.868,16.006], [21.843,26.819], [7.568,22.924], [7.568,35.467])
97
+ }
98
+ canvas
99
+ end
100
+ end
32
101
  end
33
102
 
34
103
  %w(
@@ -32,31 +32,103 @@ module DYI
32
32
 
33
33
  # Base class for animation classes.
34
34
  # @abstract
35
- # @attr [Object] from a starting value of the animation
36
- # @attr [Object] to a ending value of the animation
37
- # @attr [Numeric] duration a simple duration of the animation
38
- # @attr [Numeric] begin_offset a offset that determine the animation begin
39
- # @attr [Event] begin_event an event that determine the element begin
40
- # @attr [Numeric] end_offset a offset that determine the animation end
41
- # @attr [Event] end_event an event that determine the element end
42
- # @attr [String] fill the effect of animation when the animation is over,
43
- # either 'freeze' or 'remove'
44
- # @attr [String] additive a value that means whether or not the animation is
45
- # additive, either 'replace' or 'sum'
46
- # @attr [String] restart a value for the restart, either 'always',
47
- # 'whenNotActive'or 'never'
48
35
  class Base
36
+
49
37
  IMPLEMENT_ATTRIBUTES = [:from, :to, :duration, :begin_offset,
50
38
  :begin_event, :end_offset, :end_event, :fill,
51
- :additive, :restart]
39
+ :additive, :restart, :relays, :relay_times,
40
+ :calc_mode, :repeat_count, :key_splines]
52
41
  VALID_VALUES = {
53
42
  :fill => ['freeze','remove'],
54
43
  :additive => ['replace', 'sum'],
55
- :restart => ['always', 'whenNotActive', 'never']
44
+ :restart => ['always', 'whenNotActive', 'never'],
45
+ :calc_mode => ['discrete', 'linear', 'paced', 'spline']
56
46
  }
57
47
 
48
+ # @attribute from
49
+ # Returns a starting value of the animation.
50
+ # @return [Object] a starting value of the animation
51
+ #+++
52
+ # @attribute to
53
+ # Returns a ending value of the animation.
54
+ # @return [Object] a ending value of the animation
55
+ #+++
56
+ # @attribute duration
57
+ # Returns a simple duration of the animation.
58
+ # @return [Numeric] a simple duration of the animation
59
+ #+++
60
+ # @attribute begin_offset
61
+ # Returns a offset that determine the animation begin.
62
+ # @return [Numeric] a offset that determine the animation begin
63
+ #+++
64
+ # @attribute begin_event
65
+ # Returns an event that determine the element begin.
66
+ # @return [Event] an event that determine the element begin
67
+ #+++
68
+ # @attribute end_offset
69
+ # Returns a offset that determine the animation end
70
+ # @return [Numeric] a offset that determine the animation end
71
+ #+++
72
+ # @attribute end_event
73
+ # Returns an event that determine the element end.
74
+ # @return [Event] an event that determine the element end
75
+ #+++
76
+ # @attribute fill
77
+ # Returns the effect of animation when the animation is over, either
78
+ # <tt>'freeze'</tt> or <tt>'remove'</tt>
79
+ # @return [String] the effect of animation
80
+ #+++
81
+ # @attribute additive
82
+ # Returns a value that means whether or not the animation is additive,
83
+ # either <tt>'replace'</tt> or <tt>'sum'</tt>
84
+ # @return [String] either <tt>'replace'</tt> or <tt>'sum'</tt>
85
+ #+++
86
+ # @attribute restart
87
+ # Returns a value for the restart, either <tt>'always'</tt>,
88
+ # <tt>'whenNotActive'</tt> or <tt>'never'</tt>
89
+ # @return [String] either <tt>'always'</tt>, <tt>'whenNotActive'</tt> or
90
+ # <tt>'never'</tt>
91
+ #+++
92
+ # @attribute relays
93
+ # @return [Array]
94
+ # @since 1.3.0
95
+ #+++
96
+ # @attribute relay_times
97
+ # @return [Array<#to_f>]
98
+ # @since 1.3.0
99
+ #+++
100
+ # @attribute calc_mode
101
+ # @return [String]
102
+ # @since 1.3.0
103
+ #+++
104
+ # @attribute repeat_count
105
+ # @return [Numeric]
106
+ # @since 1.3.0
107
+ #+++
108
+ # @attribute key_splines
109
+ # @return [Array<#to_f>]
110
+ # @since 1.3.0
58
111
  attr_reader *IMPLEMENT_ATTRIBUTES
59
112
 
113
+ # Returns whether the animation is cumulative.
114
+ # @return [Boolean] true if the animation is cumulative, false otherwise
115
+ # @since 1.3.0
116
+ def accumulate?
117
+ @accumulate ? true : false
118
+ end
119
+
120
+ # @attribute [w] fill
121
+ # @param [String] value the value of attribute fill
122
+ #+++
123
+ # @attribute [w] additive
124
+ # @param [String] value the value of attribute additive
125
+ #+++
126
+ # @attribute [w] restart
127
+ # @param [String] value the value of attribute restart
128
+ #+++
129
+ # @attribute [w] calc_mode
130
+ # @param [String] value the value of attribute calc_mode
131
+ # @since 1.3.0
60
132
  VALID_VALUES.each do |attr, valid_values|
61
133
  define_method("#{attr.to_s}=") {|value|
62
134
  if (value = value.to_s).size == 0
@@ -71,11 +143,18 @@ module DYI
71
143
  end
72
144
 
73
145
  def duration=(duration)
74
- @duration = duration
146
+ @duration = duration.to_f
147
+ end
148
+
149
+ # @attribute [w] repeat_count
150
+ # @param [#to_f] count
151
+ # @since 1.3.0
152
+ def repeat_count=(count)
153
+ @repeat_count = count.to_f
75
154
  end
76
155
 
77
156
  def begin_offset=(offset)
78
- @begin_offset = offset
157
+ @begin_offset = offset.to_f
79
158
  end
80
159
 
81
160
  def begin_event=(event)
@@ -83,13 +162,33 @@ module DYI
83
162
  end
84
163
 
85
164
  def end_offset=(offset)
86
- @end_offset = offset
165
+ @end_offset = offset.to_f
87
166
  end
88
167
 
89
168
  def end_event=(event)
90
169
  @end_event = event
91
170
  end
92
171
 
172
+ # @attribute [w] relays
173
+ # @param [Array<#to_f>] times
174
+ # @since 1.3.0
175
+ def relay_times=(times)
176
+ @relay_times = times.map{|time| time.to_f}
177
+ end
178
+
179
+ # @attribute [w] key_splines
180
+ # @param [Array<#to_f>] keys
181
+ # @since 1.3.0
182
+ def key_splines=(keys)
183
+ @key_splines = keys.map{|time| time.to_f}
184
+ end
185
+
186
+ # @param [Boolean] value
187
+ # @since 1.3.0
188
+ def accumulate=(value)
189
+ @accumulate = value
190
+ end
191
+
93
192
  # @param [Shape::Base] shape a target element for an animation
94
193
  # @param [Hash] options an option for an animation
95
194
  def initialize(shape, options)
@@ -100,14 +199,17 @@ module DYI
100
199
  __send__("#{attr}=", value)
101
200
  end
102
201
  end
202
+ @relays ||= []
203
+ @relay_times ||= []
103
204
  end
104
205
  end
105
206
 
106
207
  # Class representing an animation of a painting
107
- # @attr [Painting] from a starting value of the animation
108
- # @attr [Painting] to a ending value of the animation
109
208
  class PaintingAnimation < Base
110
209
 
210
+ # @attribute [rw] from
211
+ # Returns a starting value of the animation.
212
+ # @return [Painting] a starting value of the animation
111
213
  def from=(painting)
112
214
  @from = painting && DYI::Painting.new(painting)
113
215
  end
@@ -116,11 +218,19 @@ module DYI
116
218
  @to = DYI::Painting.new(painting)
117
219
  end
118
220
 
221
+ # @attribute relays
222
+ # @return [Array<Painting>]
223
+ # @since 1.3.0
224
+ def relays=(paintings)
225
+ @relays = paintings.map{|painting| DYI::Painting.new(painting)}
226
+ end
227
+
119
228
  def animation_attributes
120
229
  DYI::Painting::IMPLEMENT_ATTRIBUTES.inject({}) do |result, attr|
121
230
  from_attr, to_attr = @from && @from.__send__(attr), @to.__send__(attr)
122
- if to_attr && from_attr != to_attr
123
- result[attr] = [from_attr, to_attr]
231
+ relay_attrs = @relays.map{|relay| relay.__send__(attr)}
232
+ if to_attr && (from_attr != to_attr || relay_attrs.any?{|relay_attr| from_attr != relay_attrs || relay_attr != to_attr})
233
+ result[attr] = [from_attr].push(*relay_attrs).push(to_attr)
124
234
  end
125
235
  result
126
236
  end
@@ -159,69 +269,150 @@ module DYI
159
269
  end
160
270
 
161
271
  def from=(value)
162
- case type
163
- when :translate
164
- case value
165
- when Array
166
- case value.size
167
- when 2 then @from = value.map{|v| v.to_f}
168
- else raise ArgumentError, "illegal size of Array: #{value.size}"
272
+ @from =
273
+ case type
274
+ when :translate
275
+ case value
276
+ when Array
277
+ case value.size
278
+ when 2 then @from = value.map{|v| v.to_f}
279
+ else raise ArgumentError, "illegal size of Array: #{value.size}"
280
+ end
281
+ when Numeric, Length
282
+ [value.to_f, 0]
283
+ when nil
284
+ nil
285
+ else
286
+ raise TypeError, "illegal argument: #{value}"
287
+ end
288
+ when :scale
289
+ case value
290
+ when Array
291
+ case value.size
292
+ when 2 then @from = value.map{|v| v.to_f}
293
+ else raise ArgumentError, "illegal size of Array: #{value.size}"
294
+ end
295
+ when Numeric
296
+ [value.to_f, value.to_f]
297
+ when nil
298
+ nil
299
+ else
300
+ raise TypeError, "illegal argument: #{value}"
301
+ end
302
+ when :rotate
303
+ case value
304
+ when Array
305
+ case value.size
306
+ when 3 then value.map{|v| v.to_f}
307
+ else raise ArgumentError, "illegal size of Array: #{value.size}"
308
+ end
309
+ when Numeric
310
+ value.to_f
311
+ when nil
312
+ nil
313
+ else
314
+ raise TypeError, "illegal argument: #{value}"
315
+ end
316
+ when :skewX, :skewY
317
+ value.nil? ? nil : value.to_f
169
318
  end
170
- when Numeric, Length
171
- @from = [value.to_f, 0]
172
- when nil
173
- @from = nil
174
- else
175
- raise TypeError, "illegal argument: #{value}"
176
- end
177
- when :scale
178
- case value
179
- when Array
180
- case value.size
181
- when 2 then @from = value.map{|v| v.to_f}
182
- else raise ArgumentError, "illegal size of Array: #{value.size}"
183
- end
184
- when Numeric
185
- @from = [value.to_f, value.to_f]
186
- when nil
187
- @from = nil
188
- else
189
- raise TypeError, "illegal argument: #{value}"
190
- end
191
- when :rotate, :skewX, :skewY
192
- @from = value.nil? ? nil : value.to_f
193
- end
194
319
  end
195
320
 
196
321
  def to=(value)
197
- case type
198
- when :translate
199
- case value
200
- when Array
201
- case value.size
202
- when 2 then @to = value.map{|v| v.to_f}
203
- else raise ArgumentError, "illegal size of Array: #{value.size}"
322
+ @to =
323
+ case type
324
+ when :translate
325
+ case value
326
+ when Array
327
+ case value.size
328
+ when 2 then value.map{|v| v.to_f}
329
+ else raise ArgumentError, "illegal size of Array: #{value.size}"
330
+ end
331
+ when Numeric, Length
332
+ @to = [value.to_f, 0]
333
+ else
334
+ raise TypeError, "illegal argument: #{value}"
335
+ end
336
+ when :scale
337
+ case value
338
+ when Array
339
+ case value.size
340
+ when 2 then value.map{|v| v.to_f}
341
+ else raise ArgumentError, "illegal size of Array: #{value.size}"
342
+ end
343
+ when Numeric
344
+ [value.to_f, value.to_f]
345
+ else
346
+ raise TypeError, "illegal argument: #{value}"
347
+ end
348
+ when :rotate
349
+ case value
350
+ when Array
351
+ case value.size
352
+ when 3 then value.map{|v| v.to_f}
353
+ else raise ArgumentError, "illegal size of Array: #{value.size}"
354
+ end
355
+ when Numeric
356
+ value.to_f
357
+ else
358
+ raise TypeError, "illegal argument: #{value}"
359
+ end
360
+ when :skewX, :skewY
361
+ value.to_f
204
362
  end
205
- when Numeric, Length
206
- @to = [value.to_f, 0]
207
- else
208
- raise TypeError, "illegal argument: #{value}"
209
- end
210
- when :scale
211
- case value
212
- when Array
213
- case value.size
214
- when 2 then @to = value.map{|v| v.to_f}
215
- else raise ArgumentError, "illegal size of Array: #{value.size}"
363
+ end
364
+
365
+ # @attribute relays
366
+ # @return [Array]
367
+ # @since 1.3.0
368
+ def relays=(values)
369
+ @relays =
370
+ case type
371
+ when :translate
372
+ values.map do |value|
373
+ case value
374
+ when Array
375
+ case value.size
376
+ when 2 then value.map{|v| v.to_f}
377
+ else raise ArgumentError, "illegal size of Array: #{value.size}"
378
+ end
379
+ when Numeric, Length
380
+ [value.to_f, 0]
381
+ else
382
+ raise TypeError, "illegal argument: #{value}"
383
+ end
384
+ end
385
+ when :scale
386
+ values.map do |value|
387
+ case value
388
+ when Array
389
+ case value.size
390
+ when 2 then value.map{|v| v.to_f}
391
+ else raise ArgumentError, "illegal size of Array: #{value.size}"
392
+ end
393
+ when Numeric
394
+ [value.to_f, value.to_f]
395
+ else
396
+ raise TypeError, "illegal argument: #{value}"
397
+ end
398
+ end
399
+ when :rotate
400
+ values.map do |value|
401
+ case value
402
+ when Array
403
+ case value.size
404
+ when 3 then value.map{|v| v.to_f}
405
+ else raise ArgumentError, "illegal size of Array: #{value.size}"
406
+ end
407
+ when Numeric
408
+ value.to_f
409
+ else
410
+ raise TypeError, "illegal argument: #{value}"
411
+ end
412
+ end
413
+ when :skewX, :skewY
414
+ values.map{|value| value.to_f}
216
415
  end
217
- when Numeric
218
- @to = [value.to_f, value.to_f]
219
- else
220
- raise TypeError, "illegal argument: #{value}"
221
- end
222
- when :rotate, :skewX, :skewY
223
- @to = value.to_f
224
- end
225
416
  end
226
417
 
227
418
  def initialize(shape, type, options)