dyi 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +674 -0
- data/README +28 -0
- data/examples/class_diagram.rb +151 -0
- data/examples/data/03311056.xlsx +0 -0
- data/examples/data/currency.xlsx +0 -0
- data/examples/data/money.csv +12 -0
- data/examples/line_and_bar.rb +26 -0
- data/examples/line_chart.rb +30 -0
- data/examples/logo.rb +68 -0
- data/examples/pie_chart.rb +19 -0
- data/examples/simple_shapes.rb +15 -0
- data/lib/dyi.rb +49 -0
- data/lib/dyi/chart.rb +34 -0
- data/lib/dyi/chart/array_reader.rb +136 -0
- data/lib/dyi/chart/base.rb +580 -0
- data/lib/dyi/chart/csv_reader.rb +93 -0
- data/lib/dyi/chart/excel_reader.rb +100 -0
- data/lib/dyi/chart/line_chart.rb +468 -0
- data/lib/dyi/chart/pie_chart.rb +141 -0
- data/lib/dyi/chart/table.rb +201 -0
- data/lib/dyi/color.rb +218 -0
- data/lib/dyi/coordinate.rb +224 -0
- data/lib/dyi/drawing.rb +32 -0
- data/lib/dyi/drawing/canvas.rb +100 -0
- data/lib/dyi/drawing/clipping.rb +61 -0
- data/lib/dyi/drawing/color_effect.rb +118 -0
- data/lib/dyi/drawing/filter.rb +74 -0
- data/lib/dyi/drawing/pen.rb +231 -0
- data/lib/dyi/drawing/pen_3d.rb +270 -0
- data/lib/dyi/font.rb +132 -0
- data/lib/dyi/formatter.rb +36 -0
- data/lib/dyi/formatter/base.rb +245 -0
- data/lib/dyi/formatter/emf_formatter.rb +253 -0
- data/lib/dyi/formatter/eps_formatter.rb +397 -0
- data/lib/dyi/formatter/svg_formatter.rb +260 -0
- data/lib/dyi/formatter/svg_reader.rb +113 -0
- data/lib/dyi/formatter/xaml_formatter.rb +317 -0
- data/lib/dyi/length.rb +399 -0
- data/lib/dyi/matrix.rb +122 -0
- data/lib/dyi/painting.rb +177 -0
- data/lib/dyi/shape.rb +1332 -0
- data/lib/dyi/svg_element.rb +149 -0
- data/lib/dyi/type.rb +104 -0
- data/lib/ironruby.rb +326 -0
- data/lib/util.rb +231 -0
- data/test/path_command_test.rb +217 -0
- data/test/test_length.rb +91 -0
- metadata +114 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
# -*- encoding: UTF-8 -*-
|
2
|
+
|
3
|
+
# Copyright (c) 2009-2011 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
|
+
module DYI #:nodoc:
|
23
|
+
module Drawing #:nodoc:
|
24
|
+
module Filter #:nodoc:
|
25
|
+
|
26
|
+
class DropShadow
|
27
|
+
include DYI::SvgElement
|
28
|
+
attr_reader :id
|
29
|
+
|
30
|
+
def initialize(canvas, blur_std, dx, dy)
|
31
|
+
@canvas = canvas
|
32
|
+
@blur_std = blur_std.to_i
|
33
|
+
@dx = Length.new(dx)
|
34
|
+
@dy = Length.new(dy)
|
35
|
+
@id = @canvas.add_define(self)
|
36
|
+
end
|
37
|
+
|
38
|
+
def child_elements
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
|
42
|
+
def draw_children?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def attributes #:nodoc:
|
49
|
+
{
|
50
|
+
:id => @id,
|
51
|
+
:filterUnits => 'userSpaceOnUse',
|
52
|
+
:x => 0,
|
53
|
+
:y => 0,
|
54
|
+
:width => @canvas.width,
|
55
|
+
:height => @canvas.height,
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def svg_tag #:nodoc:
|
60
|
+
'filter'
|
61
|
+
end
|
62
|
+
|
63
|
+
def child_elements_to_svg(xml) #:nodoc:
|
64
|
+
xml.feGaussianBlur(:in => 'SourceAlpha', :stdDeviation => @blur_std, :result => 'blur')
|
65
|
+
xml.feOffset(:in => 'blur', :dx => @dx, :dy => @dy, :result => 'offsetBlur')
|
66
|
+
xml.feMerge {
|
67
|
+
xml.feMergeNode(:in => 'offsetBlur')
|
68
|
+
xml.feMergeNode(:in => 'SourceGraphic')
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
# -*- encoding: UTF-8 -*-
|
2
|
+
|
3
|
+
# Copyright (c) 2009-2011 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
|
+
module DYI #:nodoc:
|
23
|
+
module Drawing #:nodoc:
|
24
|
+
|
25
|
+
class PenBase
|
26
|
+
extend AttributeCreator
|
27
|
+
DROP_SHADOW_OPTIONS = [:blur_std, :dx, :dy]
|
28
|
+
attr_font :font
|
29
|
+
attr_reader :drop_shadow
|
30
|
+
|
31
|
+
def initialize(options={})
|
32
|
+
@attributes = {}
|
33
|
+
@painting = Painting.new
|
34
|
+
options.each do |key, value|
|
35
|
+
if key.to_sym == :font
|
36
|
+
self.font = value
|
37
|
+
elsif Painting::IMPLEMENT_ATTRIBUTES.include?(key)
|
38
|
+
@painting.__send__("#{key}=", value)
|
39
|
+
else
|
40
|
+
@attributes[key] = value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Painting::IMPLEMENT_ATTRIBUTES.each do |painting_attr|
|
46
|
+
define_method(painting_attr) {| | @painting.__send__(painting_attr)}
|
47
|
+
define_method("#{painting_attr}=".to_sym) {|value|
|
48
|
+
@painting = @painting.dup
|
49
|
+
@painting.__send__("#{painting_attr}=".to_sym, value)
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def drop_shadow=(options)
|
54
|
+
DROP_SHADOW_OPTIONS.each do |key|
|
55
|
+
@drop_shadow[key] = options[key.to_sym] if options[key.to_sym]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def draw_line(canvas, start_point, end_point, options={})
|
60
|
+
Shape::Line.create_on_start_end(start_point, end_point, merge_option(options)).draw_on(canvas)
|
61
|
+
end
|
62
|
+
|
63
|
+
alias draw_line_on_start_end draw_line
|
64
|
+
|
65
|
+
def draw_line_on_direction(canvas, start_point, direction_x, direction_y, options={})
|
66
|
+
Shape::Line.create_on_direction(start_point, direction_x, direction_y, merge_option(options)).draw_on(canvas)
|
67
|
+
end
|
68
|
+
|
69
|
+
def draw_polyline(canvas, point, options={}, &block)
|
70
|
+
polyline = Shape::Polyline.new(point, merge_option(options))
|
71
|
+
yield polyline
|
72
|
+
polyline.draw_on(canvas)
|
73
|
+
end
|
74
|
+
|
75
|
+
def draw_polygon(canvas, point, options={}, &block)
|
76
|
+
polygon = Shape::Polygon.new(point, merge_option(options))
|
77
|
+
yield polygon
|
78
|
+
polygon.draw_on(canvas)
|
79
|
+
end
|
80
|
+
|
81
|
+
def draw_rectangle(canvas, left_top_point, width, height, options={})
|
82
|
+
Shape::Rectangle.create_on_width_height(left_top_point, width, height, merge_option(options)).draw_on(canvas)
|
83
|
+
end
|
84
|
+
|
85
|
+
alias draw_rectangle_on_width_height draw_rectangle
|
86
|
+
|
87
|
+
def draw_rectangle_on_corner(canvas, top, right, bottom, left, options={})
|
88
|
+
Shape::Rectangle.create_on_corner(top, right, bottom, left, merge_option(options)).draw_on(canvas)
|
89
|
+
end
|
90
|
+
|
91
|
+
def draw_path(canvas, point, options={}, &block)
|
92
|
+
Shape::Path.draw(point, merge_option(options), &block).draw_on(canvas)
|
93
|
+
end
|
94
|
+
|
95
|
+
def draw_closed_path(canvas, point, options={}, &block)
|
96
|
+
Shape::Path.draw_and_close(point, merge_option(options), &block).draw_on(canvas)
|
97
|
+
end
|
98
|
+
|
99
|
+
def draw_circle(canvas, center_point, radius, options={})
|
100
|
+
Shape::Circle.create_on_center_radius(center_point, radius, merge_option(options)).draw_on(canvas)
|
101
|
+
end
|
102
|
+
|
103
|
+
def draw_ellipse(canvas, center_point, radius_x, radius_y, options={})
|
104
|
+
Shape::Ellipse.create_on_center_radius(center_point, radius_x, radius_y, merge_option(options)).draw_on(canvas)
|
105
|
+
end
|
106
|
+
|
107
|
+
def draw_sector(canvas, center_point, radius_x, radius_y, start_angle, center_angle, options={})
|
108
|
+
raise ArgumentError, "center_angle is out of range: #{center_angle}" if center_angle.abs > 360
|
109
|
+
center_point = Coordinate.new(center_point)
|
110
|
+
radius_x = Length.new(radius_x)
|
111
|
+
radius_y = Length.new(radius_y)
|
112
|
+
large_arc = (center_angle.abs > 180)
|
113
|
+
|
114
|
+
arc_start_pt = Coordinate.new(radius_x * Math.cos(Math::PI * start_angle / 180), radius_y * Math.sin(Math::PI * start_angle / 180)) + center_point
|
115
|
+
arc_end_pt = Coordinate.new(radius_x * Math.cos(Math::PI * (start_angle + center_angle) / 180), radius_y * Math.sin(Math::PI * (start_angle + center_angle) / 180)) + center_point
|
116
|
+
|
117
|
+
draw_path(canvas, center_point, merge_option(options)) {|path|
|
118
|
+
path.line_to(arc_start_pt)
|
119
|
+
if center_angle.abs > 270
|
120
|
+
transit_pt = center_point * 2 - arc_start_pt
|
121
|
+
path.arc_to(transit_pt, radius_x, radius_y, 0, true)
|
122
|
+
path.arc_to(arc_end_pt, radius_x, radius_y, 0, false)
|
123
|
+
else
|
124
|
+
path.arc_to(arc_end_pt, radius_x, radius_y, 0, large_arc)
|
125
|
+
end
|
126
|
+
path.line_to(center_point)
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
130
|
+
def draw_text(canvas, point, text, options={})
|
131
|
+
Shape::Text.new(point, text, merge_option(options)).draw_on(canvas)
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def merge_option(options)
|
137
|
+
{:painting=>@painting, :font=>@font}.merge(options)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class Pen < PenBase
|
142
|
+
#:stopdoc:
|
143
|
+
ALIAS_ATTRIBUTES =
|
144
|
+
Painting::IMPLEMENT_ATTRIBUTES.inject({}) do |hash, key|
|
145
|
+
hash[$'.empty? ? :color : $'.to_sym] = key if key.to_s =~ /^(stroke_|stroke$)/
|
146
|
+
hash
|
147
|
+
end
|
148
|
+
#:startdoc:
|
149
|
+
|
150
|
+
def initialize(options={})
|
151
|
+
options = options.dup
|
152
|
+
ALIAS_ATTRIBUTES.each do |key, value|
|
153
|
+
options[value] = options.delete(key) if options.key?(key) && !options.key?(value)
|
154
|
+
end
|
155
|
+
options[:stroke] = 'black' unless options.key?(:stroke)
|
156
|
+
super
|
157
|
+
end
|
158
|
+
|
159
|
+
ALIAS_ATTRIBUTES.each do |key, value|
|
160
|
+
alias_method key, value
|
161
|
+
alias_method "#{key}=", "#{value}="
|
162
|
+
end
|
163
|
+
|
164
|
+
def draw_text(canvas, point, text, options={})
|
165
|
+
painting = @painting
|
166
|
+
text_painting = Painting.new(painting)
|
167
|
+
text_painting.fill = painting.stroke
|
168
|
+
text_painting.fill_opacity = painting.stroke_opacity
|
169
|
+
text_painting.stroke = nil
|
170
|
+
text_painting.stroke_width = nil
|
171
|
+
@painting = text_painting
|
172
|
+
shape = super
|
173
|
+
@painting = painting
|
174
|
+
shape
|
175
|
+
end
|
176
|
+
|
177
|
+
class << self
|
178
|
+
def method_missing(method_name, *args, &block) #:nodoc:
|
179
|
+
if method_name.to_s =~ /^([a-z]+)_pen$/
|
180
|
+
if options = args.first
|
181
|
+
self.new(options.merge(:stroke => $1))
|
182
|
+
else
|
183
|
+
self.new(:stroke => $1)
|
184
|
+
end
|
185
|
+
else
|
186
|
+
super
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
class Brush < PenBase
|
193
|
+
#:stopdoc:
|
194
|
+
ALIAS_ATTRIBUTES =
|
195
|
+
Painting::IMPLEMENT_ATTRIBUTES.inject({}) do |hash, key|
|
196
|
+
hash[$'.empty? ? :color : $'.to_sym] = key if key.to_s =~ /^(fill_|fill$)/
|
197
|
+
hash
|
198
|
+
end
|
199
|
+
#:startdoc:
|
200
|
+
|
201
|
+
def initialize(options={})
|
202
|
+
options = options.dup
|
203
|
+
ALIAS_ATTRIBUTES.each do |key, value|
|
204
|
+
options[value] = options.delete(key) if options.key?(key) && !options.key?(value)
|
205
|
+
end
|
206
|
+
options[:stroke_width] = 0 unless options.key?(:stroke_width)
|
207
|
+
options[:fill] = 'black' unless options.key?(:fill)
|
208
|
+
super
|
209
|
+
end
|
210
|
+
|
211
|
+
ALIAS_ATTRIBUTES.each do |key, value|
|
212
|
+
alias_method key, value
|
213
|
+
alias_method "#{key}=", "#{value}="
|
214
|
+
end
|
215
|
+
|
216
|
+
class << self
|
217
|
+
def method_missing(method_name, *args, &block) #:nodoc:
|
218
|
+
if method_name.to_s =~ /([a-z]+)_brush/
|
219
|
+
if options = args.first
|
220
|
+
self.new(options.merge(:fill => $1))
|
221
|
+
else
|
222
|
+
self.new(:fill => $1)
|
223
|
+
end
|
224
|
+
else
|
225
|
+
super
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
# -*- encoding: UTF-8 -*-
|
2
|
+
|
3
|
+
# Copyright (c) 2009-2011 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
|
+
module DYI #:nodoc:
|
23
|
+
module Drawing #:nodoc:
|
24
|
+
|
25
|
+
class CubicPen < Pen
|
26
|
+
POSITION_TYPE_VALUES = [:baseline, :center, :backline]
|
27
|
+
attr_reader :position_type, :background_color, :background_opacity, :dx, :dy
|
28
|
+
|
29
|
+
def initialize(options={})
|
30
|
+
self.position_type = options.delete(:position_type)
|
31
|
+
self.background_color = options.delete(:background_color)
|
32
|
+
self.background_opacity = options.delete(:background_opacity)
|
33
|
+
self.dx = options.delete(:dx)
|
34
|
+
self.dy = options.delete(:dy)
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def position_type=(value)
|
39
|
+
if value.to_s.size != 0
|
40
|
+
raise ArgumentError, "\"#{value}\" is invalid position-type" unless POSITION_TYPE_VALUES.include?(value)
|
41
|
+
@position_type = value
|
42
|
+
else
|
43
|
+
@position_type = nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def background_color=(color)
|
48
|
+
@background_color = Color.new_or_nil(color)
|
49
|
+
end
|
50
|
+
|
51
|
+
def background_opacity=(opacity)
|
52
|
+
@background_opacity = opacity ? opacity.to_f : nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def dx
|
56
|
+
@dx || Length.new(24)
|
57
|
+
end
|
58
|
+
|
59
|
+
def dx=(value)
|
60
|
+
@dx = Length.new_or_nil(value)
|
61
|
+
end
|
62
|
+
|
63
|
+
def dy
|
64
|
+
@dy || Length.new(-8)
|
65
|
+
end
|
66
|
+
|
67
|
+
def dy=(value)
|
68
|
+
@dy = Length.new_or_nil(value)
|
69
|
+
end
|
70
|
+
|
71
|
+
def brush
|
72
|
+
@brush ||= Brush.new(:color => background_color || color, :opacity => background_opacity || nil)
|
73
|
+
end
|
74
|
+
|
75
|
+
def draw_line(canvas, start_point, end_point, options={})
|
76
|
+
group = Shape::ShapeGroup.new
|
77
|
+
draw_background_shape(group, start_point, end_point, options)
|
78
|
+
super(group, start_point, end_point, options)
|
79
|
+
adjust_z_coordinate(group)
|
80
|
+
group.draw_on(canvas)
|
81
|
+
end
|
82
|
+
|
83
|
+
def draw_polyline(canvas, point, options={}, &block)
|
84
|
+
group = Shape::ShapeGroup.new(options)
|
85
|
+
polyline = super(group, point, {}, &block)
|
86
|
+
(1...polyline.points.size).each do |i|
|
87
|
+
draw_background_shape(group, polyline.points[i-1], polyline.points[i], {})
|
88
|
+
end
|
89
|
+
polyline = super(group, point, {}, &block)
|
90
|
+
adjust_z_coordinate(group)
|
91
|
+
group.draw_on(canvas)
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def adjust_z_coordinate(shape) #:nodoc:
|
97
|
+
case position_type
|
98
|
+
when :center then shape.translate(-dx / 2, -dy / 2)
|
99
|
+
when :backline then shape.translate(-dx, -dy)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def draw_background_shape(canvas, start_point, end_point, options={}) #:nodoc:
|
104
|
+
brush.draw_polygon(canvas, start_point, options) {|polygon|
|
105
|
+
polygon.line_to(end_point)
|
106
|
+
polygon.line_to(Coordinate.new(end_point) + Coordinate.new(dx, dy))
|
107
|
+
polygon.line_to(Coordinate.new(start_point) + Coordinate.new(dx, dy))
|
108
|
+
}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class CylinderBrush < Brush
|
113
|
+
|
114
|
+
def initialize(options={})
|
115
|
+
self.ry = options.delete(:ry)
|
116
|
+
super
|
117
|
+
end
|
118
|
+
|
119
|
+
def ry
|
120
|
+
@ry || Length.new(8)
|
121
|
+
end
|
122
|
+
|
123
|
+
def ry=(value)
|
124
|
+
@ry = Length.new_or_nil(value)
|
125
|
+
end
|
126
|
+
|
127
|
+
def fill
|
128
|
+
@painting.fill
|
129
|
+
end
|
130
|
+
|
131
|
+
def fill=(value)
|
132
|
+
if @painting.fill != Color.new_or_nil(value)
|
133
|
+
@painting.fill = Color.new_or_nil(value)
|
134
|
+
end
|
135
|
+
value
|
136
|
+
end
|
137
|
+
|
138
|
+
alias color fill
|
139
|
+
alias color= fill=
|
140
|
+
|
141
|
+
def draw_rectangle(canvas, left_top_point, width, height, options={})
|
142
|
+
radius_x = width.quo(2)
|
143
|
+
radius_y = ry
|
144
|
+
|
145
|
+
shape = Shape::ShapeGroup.draw_on(canvas)
|
146
|
+
top_painting = @painting.dup
|
147
|
+
top_painting.fill = top_color
|
148
|
+
Shape::Ellipse.create_on_center_radius(Coordinate.new(left_top_point) + [width.quo(2), 0], radius_x, radius_y, merge_option(:painting => top_painting)).draw_on(shape)
|
149
|
+
body_painting = @painting.dup
|
150
|
+
body_painting.fill = body_gradient(canvas)
|
151
|
+
Shape::Path.draw(left_top_point, merge_option(:painting => body_painting)) {|path|
|
152
|
+
path.rarc_to([width, 0], radius_x, radius_y, 0, false, false)
|
153
|
+
path.rline_to([0, height])
|
154
|
+
path.rarc_to([-width, 0], radius_x, radius_y, 0, false, true)
|
155
|
+
path.rline_to([0, -height])
|
156
|
+
}.draw_on(shape)
|
157
|
+
shape
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def body_gradient(canvas) #:nodoc:
|
163
|
+
gradient = ColorEffect::LinearGradient.new([0,0],[1,0])
|
164
|
+
gradient.add_color(0, color.merge(Color.white, 0.4))
|
165
|
+
gradient.add_color(0.3, color.merge(Color.white, 0.65))
|
166
|
+
gradient.add_color(0.4, color.merge(Color.white, 0.7))
|
167
|
+
gradient.add_color(0.5, color.merge(Color.white, 0.65))
|
168
|
+
gradient.add_color(0.7, color.merge(Color.white, 0.4))
|
169
|
+
gradient.add_color(1, color)
|
170
|
+
gradient
|
171
|
+
end
|
172
|
+
|
173
|
+
def top_color #:nodoc:
|
174
|
+
color.merge(Color.white, 0.3)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class ColumnBrush < Brush
|
179
|
+
|
180
|
+
def dy
|
181
|
+
@dy || Length.new(16)
|
182
|
+
end
|
183
|
+
|
184
|
+
def dy=(value)
|
185
|
+
@dy = Length.new_or_nil(value)
|
186
|
+
end
|
187
|
+
|
188
|
+
def draw_sector(canvas, center_point, radius_x, radius_y, start_angle, center_angle, options={})
|
189
|
+
@fill = color
|
190
|
+
|
191
|
+
start_angle = (center_angle > 0 ? start_angle : (start_angle + center_angle)) % 360
|
192
|
+
center_angle = center_angle.abs % 360
|
193
|
+
center_point = Coordinate.new(center_point)
|
194
|
+
radius_x = Length.new(radius_x)
|
195
|
+
radius_y = Length.new(radius_y)
|
196
|
+
large_arc = (center_angle > 180)
|
197
|
+
|
198
|
+
arc_start_pt = Coordinate.new(radius_x * Math.cos(Math::PI * start_angle / 180), radius_y * Math.sin(Math::PI * start_angle / 180)) + center_point
|
199
|
+
arc_end_pt = Coordinate.new(radius_x * Math.cos(Math::PI * (start_angle + center_angle) / 180), radius_y * Math.sin(Math::PI * (start_angle + center_angle) / 180)) + center_point
|
200
|
+
|
201
|
+
org_opacity = opacity
|
202
|
+
if org_color = color
|
203
|
+
self.color = color.merge('black', 0.2)
|
204
|
+
else
|
205
|
+
self.color = 'black'
|
206
|
+
self.opacity = 0.2
|
207
|
+
end
|
208
|
+
|
209
|
+
if (90..270).include?(start_angle) && center_angle < 180
|
210
|
+
draw_polygon(canvas, center_point, options) {|polygon|
|
211
|
+
polygon.line_to(center_point + [0, dy])
|
212
|
+
polygon.line_to(arc_end_pt + [0, dy])
|
213
|
+
polygon.line_to(arc_end_pt)
|
214
|
+
}
|
215
|
+
draw_polygon(canvas, center_point, options) {|polygon|
|
216
|
+
polygon.line_to(center_point + [0, dy])
|
217
|
+
polygon.line_to(arc_start_pt + [0, dy])
|
218
|
+
polygon.line_to(arc_start_pt)
|
219
|
+
}
|
220
|
+
else
|
221
|
+
draw_polygon(canvas, center_point, options) {|polygon|
|
222
|
+
polygon.line_to(center_point + [0, dy])
|
223
|
+
polygon.line_to(arc_start_pt + [0, dy])
|
224
|
+
polygon.line_to(arc_start_pt)
|
225
|
+
}
|
226
|
+
draw_polygon(canvas, center_point, options) {|polygon|
|
227
|
+
polygon.line_to(center_point + [0, dy])
|
228
|
+
polygon.line_to(arc_end_pt + [0, dy])
|
229
|
+
polygon.line_to(arc_end_pt)
|
230
|
+
}
|
231
|
+
end
|
232
|
+
if (0..180).include?(start_angle)
|
233
|
+
draw_path(canvas, arc_start_pt, options) {|path|
|
234
|
+
path.line_to(arc_start_pt + [0, dy])
|
235
|
+
if arc_end_pt.y >= center_point.y
|
236
|
+
path.arc_to(arc_end_pt + [0, dy], radius_x, radius_y, 0, false)
|
237
|
+
path.line_to(arc_end_pt)
|
238
|
+
path.arc_to(arc_start_pt, radius_x, radius_y, 0, false, false)
|
239
|
+
else
|
240
|
+
path.arc_to(center_point + [-(radius_x.abs), dy], radius_x, radius_y, 0, false)
|
241
|
+
path.line_to(center_point + [-(radius_x.abs), 0])
|
242
|
+
path.arc_to(arc_start_pt, radius_x, radius_y, 0, false, false)
|
243
|
+
end
|
244
|
+
}
|
245
|
+
elsif (270..360).include?(start_angle) && start_angle + center_angle > 360
|
246
|
+
draw_path(canvas, center_point + [radius_x.abs, 0], options) {|path|
|
247
|
+
path.line_to(center_point + [radius_x.abs, dy])
|
248
|
+
if arc_end_pt.y >= center_point.y
|
249
|
+
path.arc_to(arc_end_pt + [0, dy], radius_x, radius_y, 0, false)
|
250
|
+
path.line_to(arc_end_pt)
|
251
|
+
path.arc_to(center_point + [radius_x.abs, 0], radius_x, radius_y, 0, false, false)
|
252
|
+
else
|
253
|
+
path.arc_to(center_point + [-(radius_x.abs), dy], radius_x, radius_y, 0, false)
|
254
|
+
path.line_to(center_point + [-(radius_x.abs), 0])
|
255
|
+
path.arc_to(center_point + [radius_x.abs, 0], radius_x, radius_y, 0, false, false)
|
256
|
+
end
|
257
|
+
}
|
258
|
+
end
|
259
|
+
self.color = org_color
|
260
|
+
self.opacity = org_opacity
|
261
|
+
|
262
|
+
draw_path(canvas, center_point, options) {|path|
|
263
|
+
path.line_to(arc_start_pt)
|
264
|
+
path.arc_to(arc_end_pt, radius_x, radius_y, 0, large_arc)
|
265
|
+
path.line_to(center_point)
|
266
|
+
}
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|