dyi 1.1.2 → 1.2.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.
data/CHANGES CHANGED
@@ -1,5 +1,13 @@
1
1
  = DYI Changelog
2
2
 
3
+ == Version 1.2.0 / 2012-04-02
4
+ * Minor Enhancement
5
+ * Marker support.
6
+ * LineChart support markers.
7
+ * Bug Fixes
8
+ * Factory method of Animation is invalid.
9
+ * Event handers are not attached properly.
10
+
3
11
  == Version 1.1.2 / 2012-03-01
4
12
  * Bug Fixes
5
13
  * Calls data_label_format property instead of baloon_format when it draws the baloon of PieChart.
data/lib/dyi.rb CHANGED
@@ -24,7 +24,7 @@
24
24
  module DYI
25
25
 
26
26
  # DYI program version
27
- VERSION = '1.1.2'
27
+ VERSION = '1.2.0'
28
28
 
29
29
  # URL of DYI Project
30
30
  # @since 0.0.2
data/lib/dyi/animation.rb CHANGED
@@ -243,15 +243,15 @@ module DYI
243
243
  new(shape, :scale, options)
244
244
  end
245
245
 
246
- def scale(rotate, options)
246
+ def rotate(shape, options)
247
247
  new(shape, :rotate, options)
248
248
  end
249
249
 
250
- def skew_x(rotate, options)
250
+ def skew_x(shape, options)
251
251
  new(shape, :skewX, options)
252
252
  end
253
253
 
254
- def skew_y(rotate, options)
254
+ def skew_y(shape, options)
255
255
  new(shape, :skewY, options)
256
256
  end
257
257
  end
data/lib/dyi/canvas.rb CHANGED
@@ -259,7 +259,7 @@ module DYI
259
259
  if @init_script
260
260
  @init_script.append_body(script_body)
261
261
  else
262
- @init_script = Script::EcmaScript::EventListener.new(script_body, 'init')
262
+ @init_script = Script::EcmaScript::EventListener.new(script_body)
263
263
  add_event_listener(:load, @init_script)
264
264
  end
265
265
  end
@@ -243,6 +243,10 @@ module DYI
243
243
  # Returns or sets the CSS class of the image body of the chart.
244
244
  opt_accessor :canvas_css_class, :type => :string
245
245
 
246
+ # Returns or sets whether to output chart's data as metadata in a SVG file.
247
+ # @since 1.2.0
248
+ opt_accessor :output_chart_data, :type => :boolean, :default => false
249
+
246
250
  # @param [Length] width width of the chart image
247
251
  # @param [Length] height height of the chart image
248
252
  # @param [Hash{Symbol => Object}] options the options to creat the chart
@@ -373,6 +377,7 @@ module DYI
373
377
  @canvas.add_css_class(canvas_css_class) if canvas_css_class && !canvas_css_class.empty?
374
378
  @canvas.add_script(script_body) if script_body && !script_body.empty?
375
379
  @canvas.add_stylesheet(css_body) if css_body && !css_body.empty?
380
+ @canvas.metadata = data if output_chart_data?
376
381
  script_files && script_files.each do |script_file|
377
382
  @canvas.reference_script_file(script_file)
378
383
  end
@@ -29,7 +29,13 @@ module DYI
29
29
  include AxisUtil
30
30
  include Legend
31
31
  CHART_TYPES = [:line, :area, :bar, :stackedbar]
32
+
33
+ # @since 1.2.0
34
+ DEFAULT_MARKERS = [:circle, :square, :traiangle, :pentagon, :rhombus, :inverted_triangle]
35
+
32
36
  attr_reader :axis_back_canvas, :chart_back_canvas, :scale_canvas, :chart_front_canvas, :axis_front_canvas, :legend_canvas
37
+ # @since 1.2.0
38
+ attr_reader :x_scale_canvas, :y_scale_canvas, :guid_front_canvas, :chart_region
33
39
 
34
40
  opt_accessor :chart_margins, {:type => :hash, :default => {}, :keys => [:top,:right,:bottom,:left], :item_type => :length}
35
41
  opt_accessor :chart_colors, {:type => :array, :item_type => :color}
@@ -56,7 +62,19 @@ module DYI
56
62
  opt_accessor :use_effect, {:type => :boolean, :default => true}
57
63
  opt_accessor :bar_seriese_interval, {:type => :float, :default => 0.3}
58
64
  opt_accessor :color_columns, {:type => :array, :item_type => :integer}
59
-
65
+
66
+ # Returns or sets whether to show marker on the line chart.
67
+ # @since 1.2.0
68
+ opt_accessor :show_markers, :type => :boolean
69
+
70
+ # Returns or sets marker types on the line-chart.
71
+ # @since 1.2.0
72
+ opt_accessor :markers, {:type => :array, :item_type => :symbol}
73
+
74
+ # Returns or sets a marker size on the line-chart.
75
+ # @since 1.2.0
76
+ opt_accessor :marker_size, {:type => :float, :default => 2.5}
77
+
60
78
  def margin_top
61
79
  chart_margins[:top] || Length.new(16)
62
80
  end
@@ -196,18 +214,30 @@ module DYI
196
214
  def init_container
197
215
  # mask = Drawing::ColorEffect::Mask.new(@canvas)
198
216
  # mask.add_shapes(Shape::Rectangle.new(Drawing::Brush.new(:color => '#FFFFFF'), [margin_left, margin_top], chart_width, chart_height))
199
- @axis_back_canvas = Shape::ShapeGroup.draw_on(@canvas) unless @axis_back_canvas
217
+ @back_canvas = Shape::ShapeGroup.draw_on(@canvas)
218
+ @axis_back_canvas = Shape::ShapeGroup.draw_on(@canvas)
200
219
  # @chart_front_canvas = Shape::ShapeGroup.draw_on(@canvas, :mask => "url(##{mask.id})") unless @chart_front_canvas
201
- @chart_back_canvas = Shape::ShapeGroup.draw_on(@canvas) unless @chart_back_canvas
220
+ chart_clip = Drawing::Clipping.new(Shape::Rectangle.new([margin_left, margin_top], width - margin_left - margin_right, height - margin_top - margin_bottom))
221
+ unless @chart_back_canvas
222
+ clip_container = Shape::ShapeGroup.draw_on(@canvas)
223
+ @chart_back_canvas = Shape::ShapeGroup.draw_on(clip_container)
224
+ clip_container.set_clipping(chart_clip)
225
+ end
202
226
  @scale_canvas = Shape::ShapeGroup.draw_on(@canvas) unless @scale_canvas
203
- @chart_front_canvas = Shape::ShapeGroup.draw_on(@canvas) unless @chart_front_canvas
227
+ unless @chart_front_canvas
228
+ clip_container = Shape::ShapeGroup.draw_on(@canvas)
229
+ @chart_front_canvas = Shape::ShapeGroup.draw_on(clip_container)
230
+ clip_container.set_clipping(chart_clip)
231
+ @chart_region = Shape::Rectangle.new([margin_left, margin_top], width - margin_left - margin_right, height - margin_top - margin_bottom, :painting => {:stroke_width => 0})
232
+ @chart_region.draw_on(clip_container)
233
+ @guid_front_canvas = Shape::ShapeGroup.draw_on(clip_container)
234
+ end
235
+ @x_scale_canvas = Shape::ShapeGroup.draw_on(@canvas) unless @x_scale_canvas
236
+ @y_scale_canvas = Shape::ShapeGroup.draw_on(@canvas) unless @y_scale_canvas
204
237
  @axis_front_canvas = Shape::ShapeGroup.draw_on(@canvas) unless @axis_front_canvas
205
238
  @legend_canvas = Shape::ShapeGroup.draw_on(@canvas) unless @legend_canvas
206
239
  @chart_options = {}
207
240
  # @chart_options[:filter] = "url(##{Drawing::Filter::DropShadow.new(@canvas, dropshadow_blur_std, dropshadow_dx, dropshadow_dy).id})" if show_dropshadow?
208
- chart_clip = Drawing::Clipping.new(Shape::Rectangle.new([margin_left, margin_top], width - margin_left - margin_right, height - margin_top - margin_bottom))
209
- @chart_back_canvas.set_clipping(chart_clip)
210
- @chart_front_canvas.set_clipping(chart_clip)
211
241
  end
212
242
 
213
243
  def draw_axis(settings, sub_settings)
@@ -241,7 +271,7 @@ module DYI
241
271
  y = value_position_on_chart(margin_top, settings, settings[:min], true)
242
272
  if use_y_second_axis? || main_y_axis == :left
243
273
  text_pen.draw_text(
244
- @axis_front_canvas,
274
+ @y_scale_canvas,
245
275
  [margin_left - text_margin, y],
246
276
  main_y_axis == :left ? settings[:min] : sub_settings[:min],
247
277
  :text_anchor=>'end',
@@ -249,7 +279,7 @@ module DYI
249
279
  end
250
280
  if use_y_second_axis? || main_y_axis == :right
251
281
  text_pen.draw_text(
252
- @axis_front_canvas,
282
+ @y_scale_canvas,
253
283
  [width - margin_right + text_margin, y],
254
284
  main_y_axis == :right ? settings[:min] : sub_settings[:min],
255
285
  :format => (main_y_axis == :right ? axis_format : second_axis_format))
@@ -294,7 +324,7 @@ module DYI
294
324
 
295
325
  if use_y_second_axis? || main_y_axis == :left
296
326
  text_pen.draw_text(
297
- @axis_back_canvas,
327
+ @y_scale_canvas,
298
328
  [margin_left - text_margin, y],
299
329
  main_y_axis == :left ? value : sub_axis_value,
300
330
  :alignment_baseline=>'middle',
@@ -305,7 +335,7 @@ module DYI
305
335
 
306
336
  if use_y_second_axis? || main_y_axis == :right
307
337
  text_pen.draw_text(
308
- @axis_front_canvas,
338
+ @y_scale_canvas,
309
339
  [width - margin_right + text_margin, y],
310
340
  main_y_axis == :right ? value : sub_axis_value,
311
341
  :alignment_baseline=>'middle',
@@ -333,13 +363,13 @@ module DYI
333
363
  text_x = order_position_on_chart(margin_left, chart_width, data.records_size, i, x_axis_type)
334
364
  scale_x = x_axis_type == :range ? order_position_on_chart(margin_left, chart_width, data.records_size + 1, i) : text_x
335
365
  text_pen.draw_text(
336
- @axis_front_canvas,
366
+ @x_scale_canvas,
337
367
  [text_x, height - margin_bottom + text_margin],
338
368
  format_x_label(data.name_values[i]),
339
369
  :text_anchor => 'middle', :alignment_baseline => 'top') if show_x_labels?
340
370
 
341
371
  sub_pen.draw_line_on_direction(
342
- @axis_front_canvas,
372
+ @guid_front_canvas,
343
373
  [scale_x, height - margin_bottom],
344
374
  0,
345
375
  -(axis_font ? axis_font.draw_size : Font::DEFAULT_SIZE) * 0.5) if i > 0 && i < data.records_size - (x_axis_type == :range ? 0 : 1)
@@ -365,13 +395,17 @@ module DYI
365
395
  x = order_position_on_chart(margin_left, chart_width, values.size, first_index, x_axis_type)
366
396
  y = value_position_on_chart(margin_top, settings, values[first_index], true)
367
397
  pen.linejoin = 'bevel'
368
- pen.draw_polyline(@chart_front_canvas, [x, y], @chart_options) {|polyline|
369
- ((first_index + 1)...values.size).each do |i|
370
- x = order_position_on_chart(margin_left, chart_width, values.size, i, x_axis_type)
371
- y = value_position_on_chart(margin_top, settings, values[i], true)
372
- polyline.line_to([x, y])
373
- end
374
- }
398
+ polyline = pen.draw_polyline(@chart_front_canvas, [x, y], @chart_options) {|polyline|
399
+ ((first_index + 1)...values.size).each do |i|
400
+ x = order_position_on_chart(margin_left, chart_width, values.size, i, x_axis_type)
401
+ y = value_position_on_chart(margin_top, settings, values[i], true)
402
+ polyline.line_to([x, y])
403
+ end
404
+ }
405
+ if show_markers?
406
+ marker_type = (markers && markers[id % markers.size]) || DEFAULT_MARKERS[id % DEFAULT_MARKERS.size]
407
+ polyline.set_marker(:all, marker_type, :size => marker_size)
408
+ end
375
409
  pen.linejoin = 'bevel'
376
410
  end
377
411
 
data/lib/dyi/element.rb CHANGED
@@ -163,7 +163,7 @@ module DYI
163
163
  @event_listeners ||= {}
164
164
  end
165
165
 
166
- # Adds a animation of painting to the element.
166
+ # Sets an event to this element.
167
167
  # @param [Event] event an event that is set to the element
168
168
  # @return [String] id for this element
169
169
  def set_event(event)
@@ -172,34 +172,43 @@ module DYI
172
172
  publish_id
173
173
  end
174
174
 
175
+ # Registers event listeners on this element.
176
+ # @param [String] event_name an event name for which the user is registering
177
+ # @param [Script::EcmaScript::EventListener, ] event_listener an event name for which the user is registering
178
+ # @return [String] id for this element
179
+ def add_event_listener(event_name, event_listener)
180
+
181
+ end
182
+
175
183
  # Returns whether an event is set to the element.
176
184
  # @return [Boolean] true if an event is set to the element, false otherwise
177
185
  def event_target?
178
186
  !(@events.nil? || @events.empty?)
179
187
  end
180
188
 
181
- # Associates the element with a event listener.
182
- # @param [Symbol] event_name a event name
183
- # @param [Script::SimpleScript] event_listener a event listener
184
- def add_event_listener(event_name, event_listener)
185
- event_listener.related_to(DYI::Event.new(event_name, self))
189
+ # Registers event listeners on this element.
190
+ # @param [Symbol] event_name an event name for which the user is registering
191
+ # @param [Script::SimpleScript] listener an event listener which contains
192
+ # the methods to be called when the event occurs.
193
+ def add_event_listener(event_name, listener)
194
+ listener.related_to(DYI::Event.new(event_name, self))
186
195
  if event_listeners.key?(event_name)
187
- unless event_listeners[event_name].include?(event_listener)
188
- event_listeners[event_name] << event_listener
189
- canvas.add_script(event_listener)
196
+ unless event_listeners[event_name].include?(listener)
197
+ event_listeners[event_name] << listener
198
+ canvas.add_script(listener)
190
199
  end
191
200
  else
192
- event_listeners[event_name] = [event_listener]
193
- canvas.add_script(event_listener)
201
+ event_listeners[event_name] = [listener]
202
+ canvas.add_script(listener)
194
203
  end
195
204
  end
196
205
 
197
- # Removes asociation with given event listener
198
- # @param [Symbol] event_name a event name
199
- # @param [Script::SimpleScript] event_listener a event listener
200
- def remove_event_listener(event_name, event_listener)
206
+ # Removes event listeners from this element.
207
+ # @param [Symbol] event_name an event name for which the user is registering
208
+ # @param [Script::SimpleScript] listener an event listener to be removed
209
+ def remove_event_listener(event_name, listener)
201
210
  if event_listeners.key?(event_name)
202
- event_listeners[event_name].delete(event_listener)
211
+ event_listeners[event_name].delete(listener)
203
212
  end
204
213
  end
205
214
  end
@@ -75,7 +75,8 @@ module DYI
75
75
  "#{listener.name}(evt)"
76
76
  end
77
77
  end
78
- attrs["on#{event_name}"] = methods.compact.join(';')
78
+ methods.compact!
79
+ attrs["on#{event_name}"] = methods.join(';') unless methods.empty?
79
80
  end
80
81
  end
81
82
  sio = StringIO.new
@@ -357,6 +358,23 @@ module DYI
357
358
  }
358
359
  end
359
360
 
361
+ # @since 1.2.0
362
+ def write_marker(marker, io)
363
+ attrs = {:id => marker.id,
364
+ :viewBox => marker.view_box,
365
+ :refX => marker.ref_point.x,
366
+ :refY => marker.ref_point.y,
367
+ :markerUnits => marker.marker_units,
368
+ :markerWidth => marker.width,
369
+ :markerHeight => marker.height}
370
+ attrs[:orient] = marker.orient.to_s if marker.orient
371
+ create_node(io, 'marker', attrs) {
372
+ marker.shapes.each_with_index do |shape, i|
373
+ shape.write_as(self, io)
374
+ end
375
+ }
376
+ end
377
+
360
378
  # @since 1.0.0
361
379
  def write_painting_animation(anim, shape, io)
362
380
  anim.animation_attributes.each do |anim_attr, (from_value, to_value)|
@@ -556,6 +574,14 @@ module DYI
556
574
  if element.respond_to?(:attributes) && element.attributes[:show_border]
557
575
  @text_border_elements << element
558
576
  end
577
+ if element.respond_to?(:has_marker?)
578
+ [:start, :mid, :end].each do |point_type|
579
+ if element.has_marker?(point_type) && !@defs.value?(element.marker(point_type))
580
+ def_id = element.marker(point_type).id
581
+ @defs[def_id] = element.marker(point_type)
582
+ end
583
+ end
584
+ end
559
585
  element.child_elements.each do |child_element|
560
586
  examin_descendant_elements(child_element)
561
587
  end
@@ -619,8 +645,11 @@ module DYI
619
645
  transform = create_transform(shape)
620
646
  attributes[:transform] = transform if transform
621
647
  attributes[:'clip-path'] = "url(##{shape.clipping.id})" if shape.clipping
648
+ attributes[:'marker-start'] = "url(##{shape.marker(:start).id})" if shape.has_marker?(:start)
649
+ attributes[:'marker-mid'] = "url(##{shape.marker(:mid).id})" if shape.has_marker?(:mid)
650
+ attributes[:'marker-end'] = "url(##{shape.marker(:end).id})" if shape.has_marker?(:end)
622
651
  attributes[:id] = shape.id if shape.inner_id
623
- attributes[:'pointer-events'] = 'all' if shape.event_target?
652
+ attributes[:'pointer-events'] = 'visible' if shape.event_target?
624
653
  attributes
625
654
  end
626
655
 
@@ -330,11 +330,19 @@ EOS
330
330
  # Class representing a function of ECMAScript. The scripting becomes
331
331
  # effective only when it is output by SVG format.
332
332
  class Function < SimpleScript
333
- attr_reader :name, :arguments
334
333
 
335
- # @param [String] body body of client scripting
336
- # @param [String] name a function name
337
- # @param [Array] arguments a list of argument's name
334
+ # Returns a function identifier on ECMAScript.
335
+ # @return [String, nil] a function identifier if the function has a
336
+ # identifier on ECMAScript, nil otherwise
337
+ attr_reader :name
338
+ # Returns an array of formal parameter identifiers on ECMAScript.
339
+ # @return [Array<String>] an array of formal parameter identifiers
340
+ attr_reader :arguments
341
+
342
+ # @param [String] body function body on ECMAScript
343
+ # @param [String] name a function identifier on ECMAScript
344
+ # @param [Array<String>] arguments a list of formal parameter
345
+ # identifiers on ECMAScript
338
346
  def initialize(body, name=nil, *arguments)
339
347
  super(body)
340
348
  if name && name !~ /\A[\$A-Z_a-z][\$0-9A-Z_a-z]*\z/
@@ -349,6 +357,8 @@ EOS
349
357
  end
350
358
  end
351
359
 
360
+ # Returns string expression of this function in ECMAScript
361
+ # @return [String] expression in ECMAScript
352
362
  # @since 1.0.3
353
363
  def contents
354
364
  parts = []
@@ -356,9 +366,9 @@ EOS
356
366
  parts << " #{name}" if name
357
367
  parts << '('
358
368
  parts << arguments.join(', ')
359
- parts << ") {\n"
369
+ parts << "){\n"
360
370
  parts << @body
361
- parts << "}\n"
371
+ parts << "\n}"
362
372
  parts.join
363
373
  end
364
374
  end
@@ -389,17 +399,19 @@ EOS
389
399
  @events.delete(event)
390
400
  end
391
401
 
402
+ # Returns string expression of this function in ECMAScript
403
+ # @return [String] expression in ECMAScript
392
404
  # @since 1.0.3
393
405
  def contents
394
406
  if name
395
407
  super
396
408
  else
397
409
  parts = []
398
- parts << "addEventListener(\"load\", function(evt) {\n"
410
+ parts << "document.addEventListener(\"DOMContentLoaded\", function(evt){\n"
399
411
  @events.each do |event|
400
412
  if event.event_name == :load
401
413
  parts << @body
402
- elsif
414
+ else
403
415
  if event.target.root_element?
404
416
  parts << ' document.documentElement.addEventListener("'
405
417
  else
@@ -408,14 +420,12 @@ EOS
408
420
  parts << '").addEventListener("'
409
421
  end
410
422
  parts << event.event_name
411
- parts << '", function('
412
- parts << arguments.join(', ')
413
- parts << ") {\n"
414
- parts << @body
415
- parts << " }, false);\n"
423
+ parts << '", '
424
+ parts << super
425
+ parts << ", false);\n"
416
426
  end
417
427
  end
418
- parts << "}, false);\n"
428
+ parts << "\n}, false);\n"
419
429
  parts.join
420
430
  end
421
431
  end
data/lib/dyi/shape.rb CHANGED
@@ -23,6 +23,7 @@
23
23
 
24
24
  base
25
25
  path
26
+ marker
26
27
 
27
28
  ).each do |file_name|
28
29
  require File.join(File.dirname(__FILE__), 'shape', file_name)
@@ -24,6 +24,95 @@ require 'enumerator'
24
24
  module DYI
25
25
  module Shape
26
26
 
27
+ # This module defines the method to attach a marker symbol to the lines,
28
+ # the polylines, the polygons or the paths.
29
+ # @since 1.2.0
30
+ module Markable
31
+
32
+ # Returns a marker symbol at the specified position.
33
+ # @param [Symbol] position the position where a marker symbol is drawn.
34
+ # Specifies the following values: +:start+, +:mid+, +:end+
35
+ # @return [Marker] a marker symbol at the specified position
36
+ def marker(position)
37
+ @marker[position]
38
+ end
39
+
40
+ # Attaches a marker symbol to the shape.
41
+ # @overload set_marker(position, marker)
42
+ # Attaches the specified marker symbol at the specified position.
43
+ # @param [Symbol] position the position where a marker symbol is drawn.
44
+ # Specifies the following values: +:start+, +:mid+, +:end+,
45
+ # +:start_end+, +:start_mid+, +:mid_end+, +:all+
46
+ # @param [Marker] marker the marker symbol that is attached
47
+ # @overload set_marker(position, marker_type, options = {})
48
+ # Attaches a pre-defined marker symbol at the specified position.
49
+ # @param [Symbol] position the position where a marker symbol is drawn.
50
+ # Specifies the following values: +:start+, +:mid+, +:end+,
51
+ # +:start_end+, +:start_mid+, +:mid_end+, +:all+
52
+ # @param [Symbol] marker_type the type of pre-defined marker symbol that
53
+ # +:square+ is attached. Specifies the following values: +:circle+,
54
+ # +:triangle+, +:rhombus+, +:pentagon+, +:hexagon+
55
+ # @param [Hash] options a customizable set of options
56
+ # @option options [Number] :size size of the marker symbol. Specifies
57
+ # the relative size to line width
58
+ # @option options [Painting] :painting painting of the marker symbol
59
+ # @option options [Number, "auto"] :orient how the marker is rotated.
60
+ # Specifies a rotated angle or <tt>"auto"</tt>. <tt>"auto"</tt> means
61
+ # the marker symbol rotate the orientation of the line
62
+ def set_marker(position, *args)
63
+ pos = case position
64
+ when :start then 0x1
65
+ when :mid then 0x2
66
+ when :end then 0x4
67
+ when :start_mid then 0x3
68
+ when :start_end then 0x5
69
+ when :mid_end then 0x6
70
+ when :all then 0x7
71
+ else raise ArgumentError, "illegal argument: #{position.inspect}"
72
+ end
73
+ case args.first
74
+ when Symbol
75
+ opts = args[1].clone || {}
76
+ opts[:painting] ||= Painting.new(:fill => painting.stroke,
77
+ :fill_opacity => painting.stroke_opacity,
78
+ :opacity => painting.opacity)
79
+ if opts[:orient] == 'auto'
80
+ opts[:direction] = position == :end ? :to_end : :to_start
81
+ end
82
+ marker = Marker.new(args.first, opts)
83
+ when Marker
84
+ marker = args.first
85
+ else
86
+ raise TypeError, "illegal argument: #{value}"
87
+ end
88
+ marker.set_canvas(canvas)
89
+ @marker[:start] = marker if pos & 0x01 != 0
90
+ @marker[:mid] = marker if pos & 0x02 != 0
91
+ if pos & 0x04 != 0
92
+ if pos & 0x01 != 0 && args.first.is_a?(Symbol) && opts[:orient] == 'auto'
93
+ opts[:painting] ||= Painting.new(:fill => painting.stroke,
94
+ :fill_opacity => painting.stroke_opacity,
95
+ :opacity => painting.opacity)
96
+ opts[:direction] = :to_end
97
+ marker = Marker.new(args.first, opts)
98
+ marker.set_canvas(canvas)
99
+ @marker[:end] = marker
100
+ else
101
+ @marker[:end] = marker
102
+ end
103
+ end
104
+ end
105
+
106
+ # Returns whether this shape has a marker symbol.
107
+ # @param [Symbol] position the position where a marker symbol is drawn.
108
+ # Specifies the following values: +:start+, +:mid+, +:end+
109
+ # @return [Boolean] true if the shape has a marker at the cpecified point,
110
+ # false otherwise
111
+ def has_marker?(position)
112
+ !@marker[position].nil?
113
+ end
114
+ end
115
+
27
116
  # Base class of all graphical shapes.
28
117
  # @abstract
29
118
  # @since 0.0.0
@@ -201,6 +290,14 @@ module DYI
201
290
  set_clipping(Drawing::Clipping.new(*shapes))
202
291
  end
203
292
 
293
+ # Returns whether this shape has a marker symbol.
294
+ # @param [Symbol] position the position where a marker symbol is drawn.
295
+ # Specifies the following values: +:start+, +:mid+, +:end+
296
+ # @return [Boolean] always false
297
+ def has_marker?(position)
298
+ return false
299
+ end
300
+
204
301
  # Returns registed animations.
205
302
  # @return [Array<Animation::Base>] amination list.
206
303
  # since 1.0.0
@@ -505,12 +602,14 @@ module DYI
505
602
  end
506
603
 
507
604
  class Line < Base
605
+ include Markable
508
606
  attr_coordinate :start_point, :end_point
509
607
 
510
608
  def initialize(start_point, end_point, options={})
511
609
  @start_point = Coordinate.new(start_point)
512
610
  @end_point = Coordinate.new(end_point)
513
611
  @attributes = init_attributes(options)
612
+ @marker = {}
514
613
  end
515
614
 
516
615
  def left
@@ -550,10 +649,12 @@ module DYI
550
649
  end
551
650
 
552
651
  class Polyline < Base
652
+ include Markable
553
653
 
554
654
  def initialize(start_point, options={})
555
655
  @points = [Coordinate.new(start_point)]
556
656
  @attributes = init_attributes(options)
657
+ @marker = {}
557
658
  end
558
659
 
559
660
  def line_to(*points)
@@ -0,0 +1,296 @@
1
+ # -*- encoding: UTF-8 -*-
2
+
3
+ # Copyright (c) 2009-2012 Sound-F Co., Ltd. All rights reserved.
4
+ #
5
+ # Author:: Mamoru Yuo
6
+ #
7
+ # This file is part of DYI.
8
+ #
9
+ # DYI is free software: you can redistribute it and/or modify it
10
+ # under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # DYI is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with DYI. If not, see <http://www.gnu.org/licenses/>.
21
+
22
+ #
23
+ module DYI
24
+ module Shape
25
+ # Marker object represents a symbol at One or more vertices of the lines.
26
+ #
27
+ # Marker provides some pre-defined shapes and a custom marker defined freely.
28
+ # @since 1.2.0
29
+ class Marker < Element
30
+
31
+ attr_accessor :view_box, :ref_point, :marker_units, :width, :height, :orient, :shapes, :canvas
32
+
33
+ @@predefined_markers = {
34
+ :circle => {
35
+ :view_box => "-1 -1 2 2",
36
+ :magnify => 1.0,
37
+ :creator => proc{|painting, direction|
38
+ Shape::Circle.new([0, 0], 1, :painting => painting)
39
+ }},
40
+ :triangle => {
41
+ :view_box => "-1 -1 2 2",
42
+ :magnify => 1.1954339629,
43
+ :creator => proc{|painting, direction|
44
+ case direction
45
+ when :to_end
46
+ shape = Shape::Polygon.new([1, 0], :painting => painting)
47
+ shape.line_to([-0.5, 0.8660254038], [-0.5, -0.8660254038])
48
+ when :to_start
49
+ shape = Shape::Polygon.new([-1, 0], :painting => painting)
50
+ shape.line_to([0.5, -0.8660254038], [0.5, 0.8660254038])
51
+ else
52
+ shape = Shape::Polygon.new([0, -1], :painting => painting)
53
+ shape.line_to([0.8660254038, 0.5], [-0.8660254038, 0.5])
54
+ end
55
+ shape
56
+ }},
57
+ :square => {
58
+ :view_box => "-1 -1 2 2",
59
+ :magnify => 0.8862269255,
60
+ :creator => proc{|painting, direction|
61
+ Shape::Rectangle.new([-1, -1], 2, 2, :painting => painting)
62
+ }},
63
+ :rhombus => {
64
+ :view_box => "-1 -1 2 2",
65
+ :magnify => 1.2533141373,
66
+ :creator => proc{|painting, direction|
67
+ shape = Shape::Polygon.new([1, 0], :painting => painting)
68
+ shape.line_to([0, 1], [-1, 0], [0, -1])
69
+ shape
70
+ }},
71
+ :pentagon => {
72
+ :view_box => "-1 -1 2 2",
73
+ :magnify => 1.1494809262,
74
+ :creator => proc{|painting, direction|
75
+ case direction
76
+ when :to_end
77
+ shape = Shape::Polygon.new([1, 0], :painting => painting)
78
+ shape.line_to([0.3090169944, 0.9510565163],
79
+ [-0.8090169944, 0.5877852523],
80
+ [-0.8090169944, -0.5877852523],
81
+ [0.3090169944, -0.9510565163])
82
+ when :to_start
83
+ shape = Shape::Polygon.new([-1, 0], :painting => painting)
84
+ shape.line_to([-0.3090169944, -0.9510565163],
85
+ [0.8090169944, -0.5877852523],
86
+ [0.8090169944, 0.5877852523],
87
+ [-0.3090169944, 0.9510565163])
88
+ else
89
+ shape = Shape::Polygon.new([0, -1], :painting => painting)
90
+ shape.line_to([0.9510565163, -0.3090169944],
91
+ [0.5877852523, 0.8090169944],
92
+ [-0.5877852523, 0.8090169944],
93
+ [-0.9510565163, -0.3090169944])
94
+ end
95
+ shape
96
+ }},
97
+ :hexagon => {
98
+ :view_box => "-1 -1 2 2",
99
+ :magnify => 1.0996361108,
100
+ :creator => proc{|painting, direction|
101
+ case direction
102
+ when :to_end, :to_start
103
+ shape = Shape::Polygon.new([1, 0], :painting => painting)
104
+ shape.line_to([0.5, 0.8660254038],
105
+ [-0.5, 0.8660254038],
106
+ [-1, 0],
107
+ [-0.5, -0.8660254038],
108
+ [0.5, -0.8660254038])
109
+ else
110
+ shape = Shape::Polygon.new([0, -1], :painting => painting)
111
+ shape.line_to([0.8660254038, -0.5],
112
+ [0.8660254038, 0.5],
113
+ [0, 1],
114
+ [-0.8660254038, 0.5],
115
+ [-0.8660254038, -0.5])
116
+ end
117
+ shape
118
+ }}}
119
+ =begin
120
+ @@predefined_arrows = {
121
+ :triangle => {
122
+ :view_box => {:to_end => "0 -3 8 6", :to_start => "-8 -3 8 6"},
123
+ :magnify => {:width => 4.0 / 3.0, :height => 1.0},
124
+ :creator => proc{|painting, direction|
125
+ if direction == :to_start
126
+ shape = Shape::Polygon.new([-8, 0], :painting => painting)
127
+ shape.line_to([0, -3], [0, 3])
128
+ else
129
+ shape = Shape::Polygon.new([8, 0], :painting => painting)
130
+ shape.line_to([0, -3], [0, 3])
131
+ end
132
+ shape
133
+ },
134
+ :ref_point_getter => proc{|size, direction|
135
+ Coordinate.new(direction == :to_start ? (1 - size) : (size - 1), 0)
136
+ }},
137
+ :open => {
138
+ :view_box => {:to_end => "0 -3 8 6", :to_start => "-8 -3 8 6"},
139
+ :magnify => {:width => 4.0 / 3.0, :height => 1.0},
140
+ :creator => proc{|painting, direction|
141
+ if direction == :to_start
142
+ shape = Shape::Polygon.new([-8, 0], :painting => painting)
143
+ shape.line_to([0, -3], [0, 3])
144
+ else
145
+ shape = Shape::Polygon.new([8, 0], :painting => painting)
146
+ shape.line_to([0, -3], [0, 3])
147
+ end
148
+ shape
149
+ },
150
+ :ref_point_getter => proc{|size, direction|
151
+ Coordinate.new(direction == :to_start ? (1 - size) : (size - 1), 0)
152
+ }},
153
+ :stealth => {
154
+ :view_box => {:to_end => "0 -3 8 6", :to_start => "-8 -3 8 6"},
155
+ :magnify => {:width => 4.0 / 3.0, :height => 1.0},
156
+ :creator => proc{|painting, direction|
157
+ if direction == :to_start
158
+ shape = Shape::Polygon.new([-8, 0], :painting => painting)
159
+ shape.line_to([0, -3], [-1, -0.5], [-1, 0.5], [0, 3])
160
+ else
161
+ shape = Shape::Polygon.new([8, 0], :painting => painting)
162
+ shape.line_to([0, -3], [1, -0.5], [1, 0.5], [0, 3])
163
+ end
164
+ shape
165
+ },
166
+ :ref_point_getter => proc{|size, direction|
167
+ Coordinate.new(direction == :to_start ? (1 - size) : (size - 1), 0)
168
+ }}}
169
+ =end
170
+
171
+ # @overload initialize(marker_type, options = {})
172
+ # Creates a new pre-defined marker.
173
+ # @param [Symbol] marker_type a type of the marker. Specifies the
174
+ # following: +:circle+, +:triangle+, +:inverted_triangle+, +:square+,
175
+ # +:rhombus+, +:inverted_pentagon+, +:hexagon+
176
+ # @option options [Number] :size size of the marker. Specifies the
177
+ # relative size to line width
178
+ # @option options [Painting] :painting painting of the marker
179
+ # @option options [Number, "auto"] :orient how the marker is rotated.
180
+ # Specifies a rotated angle or <tt>"auto"</tt>. <tt>"auto"</tt> means
181
+ # the marker rotate the orientation of the line
182
+ # @option options [Symbol] :direction a direction of the marker. This
183
+ # option is valid if option +:orient+ value is <tt>"auto"</tt>.
184
+ # Specifies the following: +:to_start+, +:to_end+
185
+ # @overload initialize(shapes, options = {})
186
+ # Creates a new custom marker.
187
+ # @param [Shape::Base, Array<Shape::Base>] shapes a shape that represents
188
+ # marker
189
+ # @option options [String] :units a setting to define the coordinate
190
+ # system of the custom marker.
191
+ # @option options [String] :view_box
192
+ # @option options [Coordinate] :ref_point
193
+ # @option options [Length] :width
194
+ # @option options [Length] :height
195
+ # @option options [Number, nil] :orient
196
+ # @raise [ArgumentError]
197
+ def initialize(shape, options={})
198
+ case shape
199
+ when Symbol
200
+ inverted = !!(shape.to_s =~ /^inverted_/)
201
+ marker_source = @@predefined_markers[inverted ? $'.to_sym : shape]
202
+ raise ArgumentError, "`#{shape}' is unknown marker" unless marker_source
203
+ @ref_point = Coordinate::ZERO
204
+ if options[:orient] == 'auto'
205
+ direction = (inverted ^ (options[:direction] == :to_start)) ? :to_start : :to_end
206
+ @orient = 'auto'
207
+ else
208
+ direction = nil
209
+ @orient = (options[:orient] || 0) + (inverted ? 180 : 0)
210
+ end
211
+ @shapes = [marker_source[:creator].call(options[:painting] || {}, direction)]
212
+ @view_box = marker_source[:view_box]
213
+ @marker_units = 'strokeWidth'
214
+ @width = @height = Length.new(options[:size] || 3) * marker_source[:magnify]
215
+ when Shape::Base, Array
216
+ @ref_point = options[:ref_point] || Coordinate::ZERO
217
+ @shapes = shape.is_a?(Shape::Base) ? [shape] : shape
218
+ @view_box = options[:view_box] || "0 0 3 3"
219
+ @marker_units = options[:units] || 'strokeWidth'
220
+ @width = Length.new(options[:width] || 3)
221
+ @height = Length.new(options[:height] || 3)
222
+ @orient = options[:orient]
223
+ else
224
+ raise ArgumentError, "argument is a wrong class"
225
+ end
226
+ end
227
+
228
+ def set_canvas(canvas)
229
+ if @canvas.nil?
230
+ @canvas = canvas
231
+ elsif @canvas != canvas
232
+ raise Arguments, "the clipping is registered to another canvas"
233
+ end
234
+ end
235
+
236
+ def child_elements
237
+ @shapes
238
+ end
239
+
240
+ def write_as(formatter, io=$>)
241
+ formatter.write_marker(self, io)
242
+ end
243
+
244
+ class << self
245
+ =begin
246
+ # @overload new_arrow(options = {})
247
+ # Creates a new pre-defined triangle-arrow-marker.
248
+ # @option options [Number] :size size of the marker. Specifies the
249
+ # relative size to line width
250
+ # @option options [Painting] :painting painting of the marker
251
+ # @option options [Symbol] :direction a direction of the marker.
252
+ # Specifies the following: +:to_start+, +:to_end+
253
+ # @overload new_arrow(arrow_type, options = {})
254
+ # Creates a new pre-defined arrow-marker.
255
+ # @param [Symbol] arrow_type a type of the arrow-marker. Specifies the
256
+ # following: +:triangle+, +:open+, +:stealth+
257
+ # @option options [Number] :size size of the marker. Specifies the
258
+ # relative size to line width
259
+ # @option options [Painting] :painting painting of the marker
260
+ # @option options [Symbol] :direction a direction of the marker.
261
+ # Specifies the following: +:to_start+, +:to_end+
262
+ # @raise [ArgumentError]
263
+ def new_arrow(*args)
264
+ arrow_type = :triangle
265
+ options = {}
266
+ case args.first
267
+ when Symbol
268
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 2)" if 2 < args.size
269
+ arrow_type = args.first
270
+ if args.size == 2
271
+ options = args[1]
272
+ end
273
+ when nil
274
+ raise ArgumentError, "arrow_type is nil" if args.size != 0
275
+ else
276
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 1)" if args.size != 1
277
+ arrow_type = :triangle
278
+ options = args.first
279
+ end
280
+
281
+ marker_source = @@predefined_arrows[arrow_type]
282
+ direction = options[:direction] == :to_start ? :to_start : :to_end
283
+ size = options[:size] || 3
284
+ raise ArgumentError, "option `size' must be greater than 1" if size < 1
285
+ new(marker_source[:creator].call(options[:painting] || {}, direction),
286
+ :ref_point => marker_source[:ref_point_getter].call(size, direction),
287
+ :view_box => marker_source[:view_box][direction],
288
+ :width => Length.new(marker_source[:magnify][:width]) * size,
289
+ :height => Length.new(marker_source[:magnify][:height]) * size,
290
+ :orient => 'auto')
291
+ end
292
+ =end
293
+ end
294
+ end
295
+ end
296
+ end
@@ -55,6 +55,7 @@ module DYI
55
55
  #
56
56
  # @since 0.0.0
57
57
  class Path < Base
58
+ include Markable
58
59
 
59
60
  def initialize(start_point, options={})
60
61
  @path_data = case start_point
@@ -69,66 +70,156 @@ module DYI
69
70
  # coordinate. The new current points become the given point.
70
71
  #
71
72
  # When multiple points is given as arguments, starts a new sub-path at the
72
- # first point and draws straight line to the subsequent points. (i.e.
73
- # <tt>path.move_to(pt1,pt2,pt3,...)</tt> equals to <tt>path.move_to(pt1);
74
- # path.line_to(pt2,pt3,...)</tt>)
73
+ # first point and draws straight line to the subsequent points. see
74
+ # example.
75
75
  # @param [Coordinate] point the absolute coordinate of the start point of
76
76
  # the new sub-path. The second and subsequent arguments are the absolute
77
77
  # point to which the line is drawn from previous point
78
+ # @example
79
+ # canvas = DYI::Canvas.new(100,100)
80
+ # pen = DYI::Drawing::Pen.black_pen
81
+ # pen.draw_path(canvas, [20, 20]) {|path|
82
+ # path.line_to([20, 50])
83
+ # path.move_to([30, 20], [30, 50], [40, 50])
84
+ # # The last expression equals to following expressions
85
+ # # path.move_to([30, 20])
86
+ # # path.line_to([30, 50])
87
+ # # path.line_to([40, 50])
88
+ # }
78
89
  # @see #rmove_to
79
90
  def move_to(*points)
80
91
  push_command(:move_to, *points)
81
92
  end
82
93
 
83
94
  # Starts a new sub-path at a given point, which is specified a relative
84
- # coordinate to current point. The new current point becomes the last
95
+ # coordinate to current point. The new current point becomes the finally
85
96
  # given point.
86
97
  #
87
98
  # When multiple points is given as arguments, starts a new sub-path at the
88
- # first point and draws straight line to the subsequent points. (i.e.
89
- # <tt>path.move_to(pt1,pt2,pt3,...)</tt> equals to <tt>path.move_to(pt1);
90
- # path.line_to(pt2,pt3,...)</tt>)
99
+ # first point and draws straight line to the subsequent points. see
100
+ # example.
91
101
  # @param [Coordinate] point the relative coordinate of the start point of
92
102
  # the new sub-path. The second and subsequent arguments are the relative
93
103
  # point to which the line is drawn from previous point
104
+ # @example
105
+ # canvas = DYI::Canvas.new(100,100)
106
+ # pen = DYI::Drawing::Pen.black_pen
107
+ # pen.draw_path(canvas, [20, 20]) {|path|
108
+ # path.rline_to([0, 30])
109
+ # path.rmove_to([10, -30], [0, 30], [10, 0])
110
+ # # The last expression equals to following expressions
111
+ # # path.rmove_to([10, -30])
112
+ # # path.rline_to([0, 30])
113
+ # # path.rline_to([10, 0])
114
+ # }
94
115
  # @see #move_to
95
116
  def rmove_to(*points)
96
117
  push_command(:rmove_to, *points)
97
118
  end
98
119
 
99
- # Draws straight lines from the current point, which is specified a
100
- # absolute coordinate. The new current point becomes the last given point.
120
+ # Draws straight lines from the current point to a given point, which is
121
+ # specified a absolute coordinate. The new current point becomes the
122
+ # finally given point.
101
123
  #
102
- # When multiple points is given as argument, draws a polyline. (i.e.
103
- # <tt>path.line_to(pt1,pt2,pt3,...)</tt> equals to <tt>path.line_to(pt1);
104
- # path.line_to(pt2); path.line_to(pt3); ...</tt>)
124
+ # When multiple points is given as argument, draws a polyline. see
125
+ # example.
105
126
  # @param [Coordinate] point the absolute coordinate which the line is
106
127
  # drawn from current point to
128
+ # @example
129
+ # canvas = DYI::Canvas.new(100,100)
130
+ # pen = DYI::Drawing::Pen.black_pen
131
+ # pen.draw_path(canvas, [20, 20]) {|path|
132
+ # path.line_to([20, 50], [30, 20], [30, 50])
133
+ # # The last expression equals to following expressions
134
+ # # path.line_to([20, 50])
135
+ # # path.line_to([30, 20])
136
+ # # path.line_to([30, 50])
137
+ # }
107
138
  # @see #rline_to
108
139
  def line_to(*points)
109
140
  push_command(:line_to, *points)
110
141
  end
111
142
 
112
- # Draws straight lines from the current point, which is specified a
113
- # relative coordinate to current point. The new current point becomes the
114
- # last given point.
143
+ # Draws straight lines from the current point to a given point, which is
144
+ # specified a relative coordinate to current point. The new current point
145
+ # becomes the finally given point.
115
146
  #
116
- # When multiple points is given as arguments, draws a polyline. (i.e.
117
- # <tt>path.rline_to(pt1,pt2,pt3,...)</tt> equals to <tt>path.rline_to(pt1);
118
- # path.rline_to(pt2); path.rline_to(pt3); ...</tt>)
147
+ # When multiple points is given as arguments, draws a polyline. see
148
+ # example.
119
149
  # @param [Coordinate] point the relavive coordinate which the line is
120
150
  # drawn from current point to
151
+ # @example
152
+ # canvas = DYI::Canvas.new(100,100)
153
+ # pen = DYI::Drawing::Pen.black_pen
154
+ # pen.draw_path(canvas, [20, 20]) {|path|
155
+ # path.rline_to([0, 30], [10, -30], [0, 30])
156
+ # # The last expression equals to following expressions
157
+ # # path.rline_to([0, 30])
158
+ # # path.rline_to([10, -30])
159
+ # # path.rline_to([0, 30])
160
+ # }
121
161
  # @see #line_to
122
162
  def rline_to(*points)
123
163
  push_command(:rline_to, *points)
124
164
  end
125
165
 
166
+ # Draws quadratic Bézier curves from the current point to the second
167
+ # argument point using first argument point as control-point. The
168
+ # control-point and pass-point are specified a absolute coordinate. The
169
+ # new current point becomes the point to specify in second argument.
170
+ #
171
+ # When three or more points is given as the argument, draws
172
+ # polybézier-curves. In this case, the control-point is assumed to be the
173
+ # reflection of the control-point on the previouse quadratic Bézier curve
174
+ # relative to the current point. see example.
175
+ # @param [Coordinate] point0 the absolute coordinate of the control-point
176
+ # of the quadratic Bézier curve
177
+ # @param [Coordinate] point1 the absolute coordinate which the curve is
178
+ # drawn from current point to
179
+ # @example
180
+ # canvas = DYI::Canvas.new(100,100)
181
+ # pen = DYI::Drawing::Pen.black_pen
182
+ # pen.draw_path(canvas, [20, 20]) {|path|
183
+ # path.quadratic_curve_to([40, 20], [60, 50], [60, 80])
184
+ # # The last expression equals to following expressions
185
+ # # path.quadratic_curve_to([40, 20], [60, 50])
186
+ # # path.quadratic_curve_to([80, 80], [60, 80])
187
+ # # control-point [80,80] is reflection of first curve's control-point [40, 20]
188
+ # # across current point [60, 50].
189
+ # }
190
+ # @see #rquadratic_curve_to
126
191
  def quadratic_curve_to(*points)
127
192
  raise ArgumentError, "number of points must be 2 or more" if points.size < 2
128
193
  push_command(:quadratic_curve_to, points[0], points[1])
129
194
  push_command(:shorthand_quadratic_curve_to, *points[2..-1]) if points.size > 2
130
195
  end
131
196
 
197
+ # Draws quadratic Bézier curves from the current point to the second
198
+ # argument point using first argument point as control-point. The
199
+ # control-point and pass-point are specified a relative coordinate to
200
+ # current point. The new current point becomes the point to specify in
201
+ # second argument.
202
+ #
203
+ # When three or more points is given as the argument, draws
204
+ # polybézier-curves. In this case, the control-point is assumed to be the
205
+ # reflection of the control-point on the previouse quadratic Bézier curve
206
+ # relative to the current point. see example.
207
+ # @param [Coordinate] point0 the relative coordinate of the control-point
208
+ # of the quadratic Bézier curve
209
+ # @param [Coordinate] point1 the relative coordinate which the curve is
210
+ # drawn from current point to
211
+ # @example
212
+ # canvas = DYI::Canvas.new(100,100)
213
+ # pen = DYI::Drawing::Pen.black_pen
214
+ # pen.draw_path(canvas, [20, 20]) {|path|
215
+ # path.rquadratic_curve_to([20, 0], [40, 30], [0, 30])
216
+ # # The last expression equals to following expressions
217
+ # # path.quadratic_curve_to([20, 0], [40, 30])
218
+ # # path.quadratic_curve_to([20, 30], [0, 30])
219
+ # # control-point [20, 30] is reflection of first curve's control-point [-20, -30].
220
+ # # (that is relative coordinate to current point. i.e. [20, 0] - [40, 30])
221
+ # }
222
+ # @see #rquadratic_curve_to
132
223
  def rquadratic_curve_to(*points)
133
224
  raise ArgumentError, "number of points must be 2 or more" if points.size < 2
134
225
  push_command(:rquadratic_curve_to, points[0], points[1])
metadata CHANGED
@@ -1,8 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dyi
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 1.1.2
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 2
9
+ - 0
10
+ version: 1.2.0
6
11
  platform: ruby
7
12
  authors:
8
13
  - Mamoru Yuo
@@ -10,7 +15,8 @@ autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
17
 
13
- date: 2012-03-01 00:00:00 Z
18
+ date: 2012-04-03 00:00:00 +09:00
19
+ default_executable:
14
20
  dependencies: []
15
21
 
16
22
  description: " DYI is a 2D graphics library, very rich and expressive.\n DYI have been optimized for SVG format, but it is also possible\n to output other format; for example, EPS.\n"
@@ -22,68 +28,70 @@ extensions: []
22
28
  extra_rdoc_files: []
23
29
 
24
30
  files:
25
- - CHANGES
26
- - COPYING
27
- - examples/animation.rb
28
- - examples/class_diagram.rb
29
- - examples/css.rb
30
- - examples/data/03311056.xlsx
31
- - examples/data/currency.xlsx
32
- - examples/data/money.csv
33
- - examples/line_and_bar.rb
34
- - examples/line_chart.rb
35
- - examples/logo.rb
36
- - examples/pie_chart.rb
37
- - examples/simple_shapes.rb
38
- - lib/dyi/animation.rb
31
+ - lib/ironruby.rb
39
32
  - lib/dyi/canvas.rb
40
- - lib/dyi/chart/array_reader.rb
41
- - lib/dyi/chart/axis_util.rb
42
- - lib/dyi/chart/base.rb
43
- - lib/dyi/chart/csv_reader.rb
44
- - lib/dyi/chart/excel_reader.rb
45
- - lib/dyi/chart/legend.rb
46
- - lib/dyi/chart/line_chart.rb
47
- - lib/dyi/chart/pie_chart.rb
48
- - lib/dyi/chart/table.rb
49
33
  - lib/dyi/chart.rb
50
- - lib/dyi/color.rb
51
- - lib/dyi/coordinate.rb
34
+ - lib/dyi/stylesheet.rb
35
+ - lib/dyi/event.rb
52
36
  - lib/dyi/drawing/clipping.rb
53
- - lib/dyi/drawing/color_effect.rb
54
37
  - lib/dyi/drawing/filter.rb
55
- - lib/dyi/drawing/pen.rb
38
+ - lib/dyi/drawing/color_effect.rb
56
39
  - lib/dyi/drawing/pen_3d.rb
57
- - lib/dyi/drawing.rb
40
+ - lib/dyi/drawing/pen.rb
41
+ - lib/dyi/script/simple_script.rb
42
+ - lib/dyi/script/ecmascript.rb
43
+ - lib/dyi/color.rb
58
44
  - lib/dyi/element.rb
59
- - lib/dyi/event.rb
60
- - lib/dyi/font.rb
61
- - lib/dyi/formatter/base.rb
45
+ - lib/dyi/shape/base.rb
46
+ - lib/dyi/shape/marker.rb
47
+ - lib/dyi/shape/path.rb
62
48
  - lib/dyi/formatter/emf_formatter.rb
63
- - lib/dyi/formatter/eps_formatter.rb
64
- - lib/dyi/formatter/svg_formatter.rb
65
49
  - lib/dyi/formatter/svg_reader.rb
66
50
  - lib/dyi/formatter/xaml_formatter.rb
67
- - lib/dyi/formatter.rb
68
- - lib/dyi/length.rb
69
- - lib/dyi/matrix.rb
70
- - lib/dyi/painting.rb
71
- - lib/dyi/script/ecmascript.rb
72
- - lib/dyi/script/simple_script.rb
51
+ - lib/dyi/formatter/base.rb
52
+ - lib/dyi/formatter/svg_formatter.rb
53
+ - lib/dyi/formatter/eps_formatter.rb
73
54
  - lib/dyi/script.rb
74
- - lib/dyi/shape/base.rb
75
- - lib/dyi/shape/path.rb
55
+ - lib/dyi/drawing.rb
56
+ - lib/dyi/animation.rb
57
+ - lib/dyi/matrix.rb
58
+ - lib/dyi/coordinate.rb
59
+ - lib/dyi/chart/array_reader.rb
60
+ - lib/dyi/chart/csv_reader.rb
61
+ - lib/dyi/chart/table.rb
62
+ - lib/dyi/chart/line_chart.rb
63
+ - lib/dyi/chart/pie_chart.rb
64
+ - lib/dyi/chart/legend.rb
65
+ - lib/dyi/chart/base.rb
66
+ - lib/dyi/chart/axis_util.rb
67
+ - lib/dyi/chart/excel_reader.rb
76
68
  - lib/dyi/shape.rb
77
- - lib/dyi/stylesheet.rb
78
- - lib/dyi/svg_element.rb
79
- - lib/dyi/type.rb
80
69
  - lib/dyi/util.rb
70
+ - lib/dyi/painting.rb
71
+ - lib/dyi/type.rb
72
+ - lib/dyi/length.rb
73
+ - lib/dyi/font.rb
74
+ - lib/dyi/formatter.rb
75
+ - lib/dyi/svg_element.rb
81
76
  - lib/dyi.rb
82
- - lib/ironruby.rb
83
77
  - lib/util.rb
84
- - README
78
+ - CHANGES
85
79
  - test/path_command_test.rb
86
80
  - test/test_length.rb
81
+ - examples/class_diagram.rb
82
+ - examples/line_and_bar.rb
83
+ - examples/line_chart.rb
84
+ - examples/data/money.csv
85
+ - examples/data/currency.xlsx
86
+ - examples/data/03311056.xlsx
87
+ - examples/simple_shapes.rb
88
+ - examples/pie_chart.rb
89
+ - examples/animation.rb
90
+ - examples/css.rb
91
+ - examples/logo.rb
92
+ - README
93
+ - COPYING
94
+ has_rdoc: true
87
95
  homepage: https://sourceforge.net/projects/dyi/
88
96
  licenses:
89
97
  - GPL-3
@@ -97,17 +105,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
105
  requirements:
98
106
  - - ">="
99
107
  - !ruby/object:Gem::Version
108
+ hash: 57
109
+ segments:
110
+ - 1
111
+ - 8
112
+ - 7
100
113
  version: 1.8.7
101
114
  required_rubygems_version: !ruby/object:Gem::Requirement
102
115
  none: false
103
116
  requirements:
104
117
  - - ">="
105
118
  - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
106
122
  version: "0"
107
123
  requirements: []
108
124
 
109
125
  rubyforge_project:
110
- rubygems_version: 1.8.10
126
+ rubygems_version: 1.3.7
111
127
  signing_key:
112
128
  specification_version: 3
113
129
  summary: 2D graphics library