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 +8 -0
- data/lib/dyi.rb +1 -1
- data/lib/dyi/animation.rb +3 -3
- data/lib/dyi/canvas.rb +1 -1
- data/lib/dyi/chart/base.rb +5 -0
- data/lib/dyi/chart/line_chart.rb +54 -20
- data/lib/dyi/element.rb +25 -16
- data/lib/dyi/formatter/svg_formatter.rb +31 -2
- data/lib/dyi/script/ecmascript.rb +24 -14
- data/lib/dyi/shape.rb +1 -0
- data/lib/dyi/shape/base.rb +101 -0
- data/lib/dyi/shape/marker.rb +296 -0
- data/lib/dyi/shape/path.rb +109 -18
- metadata +66 -50
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
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
|
246
|
+
def rotate(shape, options)
|
247
247
|
new(shape, :rotate, options)
|
248
248
|
end
|
249
249
|
|
250
|
-
def skew_x(
|
250
|
+
def skew_x(shape, options)
|
251
251
|
new(shape, :skewX, options)
|
252
252
|
end
|
253
253
|
|
254
|
-
def skew_y(
|
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
|
262
|
+
@init_script = Script::EcmaScript::EventListener.new(script_body)
|
263
263
|
add_event_listener(:load, @init_script)
|
264
264
|
end
|
265
265
|
end
|
data/lib/dyi/chart/base.rb
CHANGED
@@ -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
|
data/lib/dyi/chart/line_chart.rb
CHANGED
@@ -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
|
-
@
|
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
|
-
|
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
|
-
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
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
|
-
#
|
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
|
-
#
|
182
|
-
# @param [Symbol] event_name
|
183
|
-
# @param [Script::SimpleScript]
|
184
|
-
|
185
|
-
|
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?(
|
188
|
-
event_listeners[event_name] <<
|
189
|
-
canvas.add_script(
|
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] = [
|
193
|
-
canvas.add_script(
|
201
|
+
event_listeners[event_name] = [listener]
|
202
|
+
canvas.add_script(listener)
|
194
203
|
end
|
195
204
|
end
|
196
205
|
|
197
|
-
# Removes
|
198
|
-
# @param [Symbol] event_name
|
199
|
-
# @param [Script::SimpleScript]
|
200
|
-
def remove_event_listener(event_name,
|
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(
|
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
|
-
|
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'] = '
|
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
|
-
#
|
336
|
-
# @
|
337
|
-
#
|
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 << ")
|
369
|
+
parts << "){\n"
|
360
370
|
parts << @body
|
361
|
-
parts << "
|
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(\"
|
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
|
-
|
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 << '",
|
412
|
-
parts <<
|
413
|
-
parts << ")
|
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
data/lib/dyi/shape/base.rb
CHANGED
@@ -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
|
data/lib/dyi/shape/path.rb
CHANGED
@@ -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.
|
73
|
-
#
|
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
|
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.
|
89
|
-
#
|
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
|
100
|
-
# absolute coordinate. The new current point becomes the
|
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.
|
103
|
-
#
|
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
|
113
|
-
# relative coordinate to current point. The new current point
|
114
|
-
#
|
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.
|
117
|
-
#
|
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
|
-
|
5
|
-
|
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
|
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
|
-
-
|
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/
|
51
|
-
- lib/dyi/
|
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/
|
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/
|
60
|
-
- lib/dyi/
|
61
|
-
- lib/dyi/
|
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/
|
69
|
-
- lib/dyi/
|
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/
|
75
|
-
- lib/dyi/
|
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
|
-
-
|
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.
|
126
|
+
rubygems_version: 1.3.7
|
111
127
|
signing_key:
|
112
128
|
specification_version: 3
|
113
129
|
summary: 2D graphics library
|