gruff 0.8.0 → 0.9.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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +18 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +93 -0
- data/.rubocop_todo.yml +23 -810
- data/.travis.yml +4 -4
- data/.yardopts +1 -0
- data/CHANGELOG.md +22 -0
- data/Gemfile +3 -1
- data/README.md +44 -21
- data/Rakefile +2 -206
- data/docker/Dockerfile +14 -0
- data/docker/build.sh +4 -0
- data/docker/launch.sh +4 -0
- data/gruff.gemspec +11 -8
- data/init.rb +2 -0
- data/lib/gruff.rb +23 -0
- data/lib/gruff/accumulator_bar.rb +6 -6
- data/lib/gruff/area.rb +13 -17
- data/lib/gruff/bar.rb +58 -41
- data/lib/gruff/base.rb +243 -566
- data/lib/gruff/bezier.rb +12 -14
- data/lib/gruff/bullet.rb +39 -57
- data/lib/gruff/dot.rb +25 -59
- data/lib/gruff/{bar_conversion.rb → helper/bar_conversion.rb} +13 -12
- data/lib/gruff/helper/bar_value_label_mixin.rb +30 -0
- data/lib/gruff/{stacked_mixin.rb → helper/stacked_mixin.rb} +7 -6
- data/lib/gruff/line.rb +95 -177
- data/lib/gruff/mini/bar.rb +6 -7
- data/lib/gruff/mini/legend.rb +16 -32
- data/lib/gruff/mini/pie.rb +6 -7
- data/lib/gruff/mini/side_bar.rb +4 -5
- data/lib/gruff/net.rb +37 -65
- data/lib/gruff/patch/rmagick.rb +33 -0
- data/lib/gruff/patch/string.rb +8 -0
- data/lib/gruff/photo_bar.rb +19 -19
- data/lib/gruff/pie.rb +22 -73
- data/lib/gruff/renderer/bezier.rb +21 -0
- data/lib/gruff/renderer/circle.rb +21 -0
- data/lib/gruff/renderer/dash_line.rb +22 -0
- data/lib/gruff/renderer/dot.rb +39 -0
- data/lib/gruff/renderer/ellipse.rb +21 -0
- data/lib/gruff/renderer/line.rb +34 -0
- data/lib/gruff/renderer/polygon.rb +23 -0
- data/lib/gruff/renderer/polyline.rb +21 -0
- data/lib/gruff/renderer/rectangle.rb +19 -0
- data/lib/gruff/renderer/renderer.rb +127 -0
- data/lib/gruff/renderer/text.rb +42 -0
- data/lib/gruff/scatter.rb +85 -156
- data/lib/gruff/scene.rb +22 -30
- data/lib/gruff/side_bar.rb +62 -58
- data/lib/gruff/side_stacked_bar.rb +47 -43
- data/lib/gruff/spider.rb +19 -36
- data/lib/gruff/stacked_area.rb +17 -21
- data/lib/gruff/stacked_bar.rb +50 -24
- data/lib/gruff/store/base_data.rb +34 -0
- data/lib/gruff/store/custom_data.rb +34 -0
- data/lib/gruff/store/store.rb +80 -0
- data/lib/gruff/store/xy_data.rb +55 -0
- data/lib/gruff/themes.rb +3 -3
- data/lib/gruff/version.rb +3 -1
- metadata +41 -30
- data/Manifest.txt +0 -81
- data/assets/bubble.png +0 -0
- data/assets/city_scene/background/0000.png +0 -0
- data/assets/city_scene/background/0600.png +0 -0
- data/assets/city_scene/background/2000.png +0 -0
- data/assets/city_scene/clouds/cloudy.png +0 -0
- data/assets/city_scene/clouds/partly_cloudy.png +0 -0
- data/assets/city_scene/clouds/stormy.png +0 -0
- data/assets/city_scene/grass/default.png +0 -0
- data/assets/city_scene/haze/true.png +0 -0
- data/assets/city_scene/number_sample/1.png +0 -0
- data/assets/city_scene/number_sample/2.png +0 -0
- data/assets/city_scene/number_sample/default.png +0 -0
- data/assets/city_scene/sky/0000.png +0 -0
- data/assets/city_scene/sky/0200.png +0 -0
- data/assets/city_scene/sky/0400.png +0 -0
- data/assets/city_scene/sky/0600.png +0 -0
- data/assets/city_scene/sky/0800.png +0 -0
- data/assets/city_scene/sky/1000.png +0 -0
- data/assets/city_scene/sky/1200.png +0 -0
- data/assets/city_scene/sky/1400.png +0 -0
- data/assets/city_scene/sky/1500.png +0 -0
- data/assets/city_scene/sky/1700.png +0 -0
- data/assets/city_scene/sky/2000.png +0 -0
- data/assets/pc306715.jpg +0 -0
- data/lib/gruff/deprecated.rb +0 -38
data/lib/gruff/pie.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'gruff/base'
|
2
4
|
|
3
5
|
##
|
4
6
|
# Here's how to make a Pie graph:
|
@@ -10,31 +12,32 @@ require File.dirname(__FILE__) + '/base'
|
|
10
12
|
# g.write("test/output/pie_keynote.png")
|
11
13
|
#
|
12
14
|
# To control where the pie chart starts creating slices, use #zero_degree.
|
13
|
-
|
14
15
|
class Gruff::Pie < Gruff::Base
|
15
|
-
|
16
16
|
DEFAULT_TEXT_OFFSET_PERCENTAGE = 0.15
|
17
17
|
|
18
18
|
# Can be used to make the pie start cutting slices at the top (-90.0)
|
19
|
-
# or at another angle. Default is 0.0
|
19
|
+
# or at another angle. Default is +0.0+, which starts at 3 o'clock.
|
20
20
|
attr_writer :zero_degree
|
21
21
|
|
22
22
|
# Do not show labels for slices that are less than this percent. Use 0 to always show all labels.
|
23
|
-
# Defaults to 0
|
23
|
+
# Defaults to +0+.
|
24
24
|
attr_writer :hide_labels_less_than
|
25
25
|
|
26
|
-
# Affect the distance between the percentages and the pie chart
|
27
|
-
# Defaults to 0.15
|
26
|
+
# Affect the distance between the percentages and the pie chart.
|
27
|
+
# Defaults to +0.15+.
|
28
28
|
attr_writer :text_offset_percentage
|
29
29
|
|
30
|
-
## Use values instead of percentages
|
30
|
+
## Use values instead of percentages.
|
31
31
|
attr_accessor :show_values_as_labels
|
32
32
|
|
33
33
|
def initialize_ivars
|
34
34
|
super
|
35
35
|
|
36
36
|
@show_values_as_labels = false
|
37
|
+
|
38
|
+
@store = Gruff::Store.new(Gruff::Store::CustomData)
|
37
39
|
end
|
40
|
+
private :initialize_ivars
|
38
41
|
|
39
42
|
def zero_degree
|
40
43
|
@zero_degree ||= 0.0
|
@@ -66,23 +69,21 @@ class Gruff::Pie < Gruff::Base
|
|
66
69
|
|
67
70
|
slices.each do |slice|
|
68
71
|
if slice.value > 0
|
69
|
-
|
70
|
-
|
71
|
-
set_stroke_width
|
72
|
-
set_drawing_points_for slice
|
72
|
+
Gruff::Renderer::Ellipse.new(color: slice.color, width: radius)
|
73
|
+
.render(center_x, center_y, radius / 2.0, radius / 2.0, chart_degrees, chart_degrees + slice.degrees + 0.5)
|
73
74
|
process_label_for slice
|
74
75
|
update_chart_degrees_with slice.degrees
|
75
76
|
end
|
76
77
|
end
|
77
78
|
|
78
|
-
|
79
|
+
Gruff::Renderer.finish
|
79
80
|
end
|
80
81
|
|
81
82
|
private
|
82
83
|
|
83
84
|
def slices
|
84
85
|
@slices ||= begin
|
85
|
-
slices =
|
86
|
+
slices = store.data.map { |data| slice_class.new(data, options) }
|
86
87
|
|
87
88
|
slices.sort_by(&:value) if @sort
|
88
89
|
|
@@ -97,10 +98,6 @@ private
|
|
97
98
|
@hide_line_markers = true
|
98
99
|
end
|
99
100
|
|
100
|
-
def data_given?
|
101
|
-
@has_data
|
102
|
-
end
|
103
|
-
|
104
101
|
def update_chart_degrees_with(degrees)
|
105
102
|
@chart_degrees = chart_degrees + degrees
|
106
103
|
end
|
@@ -115,13 +112,9 @@ private
|
|
115
112
|
@chart_degrees ||= zero_degree
|
116
113
|
end
|
117
114
|
|
118
|
-
|
119
|
-
@graph_height
|
120
|
-
end
|
115
|
+
attr_reader :graph_height
|
121
116
|
|
122
|
-
|
123
|
-
@graph_width
|
124
|
-
end
|
117
|
+
attr_reader :graph_width
|
125
118
|
|
126
119
|
def diameter
|
127
120
|
graph_height
|
@@ -165,7 +158,7 @@ private
|
|
165
158
|
if slice.percentage >= hide_labels_less_than
|
166
159
|
x, y = label_coordinates_for slice
|
167
160
|
|
168
|
-
|
161
|
+
draw_label(x, y, slice.label)
|
169
162
|
end
|
170
163
|
end
|
171
164
|
|
@@ -185,58 +178,14 @@ private
|
|
185
178
|
|
186
179
|
# Drawing-Related Methods
|
187
180
|
|
188
|
-
def set_stroke_width
|
189
|
-
@d.stroke_width(radius)
|
190
|
-
end
|
191
|
-
|
192
|
-
def set_stroke_color(slice)
|
193
|
-
@d = @d.stroke slice.color
|
194
|
-
end
|
195
|
-
|
196
|
-
def set_fill_color
|
197
|
-
@d = @d.fill 'transparent'
|
198
|
-
end
|
199
|
-
|
200
|
-
def set_drawing_points_for(slice)
|
201
|
-
@d = @d.ellipse(
|
202
|
-
center_x,
|
203
|
-
center_y,
|
204
|
-
radius / 2.0,
|
205
|
-
radius / 2.0,
|
206
|
-
chart_degrees,
|
207
|
-
chart_degrees + slice.degrees + 0.5
|
208
|
-
)
|
209
|
-
end
|
210
|
-
|
211
|
-
def trigger_final_draw
|
212
|
-
@d.draw(@base_image)
|
213
|
-
end
|
214
|
-
|
215
|
-
def configure_label_styling
|
216
|
-
@d.fill = @font_color
|
217
|
-
@d.font = @font if @font
|
218
|
-
@d.pointsize = scale_fontsize(@marker_font_size)
|
219
|
-
@d.stroke = 'transparent'
|
220
|
-
@d.font_weight = BoldWeight
|
221
|
-
@d.gravity = CenterGravity
|
222
|
-
end
|
223
|
-
|
224
181
|
def draw_label(x, y, value)
|
225
|
-
|
226
|
-
|
227
|
-
@d.annotate_scaled(
|
228
|
-
@base_image,
|
229
|
-
0,
|
230
|
-
0,
|
231
|
-
x,
|
232
|
-
y,
|
233
|
-
value,
|
234
|
-
@scale
|
235
|
-
)
|
182
|
+
text_renderer = Gruff::Renderer::Text.new(value, font: @font, size: @marker_font_size, color: @font_color, weight: Magick::BoldWeight)
|
183
|
+
text_renderer.render(0, 0, x, y, Magick::CenterGravity)
|
236
184
|
end
|
237
185
|
|
238
186
|
# Helper Classes
|
239
|
-
|
187
|
+
#
|
188
|
+
# @private
|
240
189
|
class PieSlice < Struct.new(:data_array, :options)
|
241
190
|
attr_accessor :total
|
242
191
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gruff
|
4
|
+
class Renderer::Bezier
|
5
|
+
def initialize(args = {})
|
6
|
+
@color = args[:color]
|
7
|
+
@width = args[:width] || 1.0
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(points)
|
11
|
+
draw = Renderer.instance.draw
|
12
|
+
|
13
|
+
draw.push
|
14
|
+
draw.stroke(@color)
|
15
|
+
draw.stroke_width(@width)
|
16
|
+
draw.fill_opacity(0.0)
|
17
|
+
draw.bezier(*points)
|
18
|
+
draw.pop
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gruff
|
4
|
+
class Renderer::Circle
|
5
|
+
def initialize(args = {})
|
6
|
+
@color = args[:color]
|
7
|
+
@width = args[:width] || 1.0
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(origin_x, origin_y, perim_x, perim_y)
|
11
|
+
draw = Renderer.instance.draw
|
12
|
+
|
13
|
+
draw.push
|
14
|
+
draw.fill(@color)
|
15
|
+
draw.stroke(@color)
|
16
|
+
draw.stroke_width(@width)
|
17
|
+
draw.circle(origin_x, origin_y, perim_x, perim_y)
|
18
|
+
draw.pop
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gruff
|
4
|
+
class Renderer::DashLine
|
5
|
+
def initialize(args = {})
|
6
|
+
@color = args[:color]
|
7
|
+
@width = args[:width]
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(start_x, start_y, end_x, end_y)
|
11
|
+
draw = Renderer.instance.draw
|
12
|
+
|
13
|
+
draw.push
|
14
|
+
draw.stroke_color(@color)
|
15
|
+
draw.fill_opacity(0.0)
|
16
|
+
draw.stroke_dasharray(10, 20)
|
17
|
+
draw.stroke_width(@width)
|
18
|
+
draw.line(start_x, start_y, end_x, end_y)
|
19
|
+
draw.pop
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gruff
|
4
|
+
class Renderer::Dot
|
5
|
+
def initialize(style, config)
|
6
|
+
@style = style
|
7
|
+
@color = config[:color]
|
8
|
+
@width = config[:width] || 1.0
|
9
|
+
end
|
10
|
+
|
11
|
+
def render(new_x, new_y, circle_radius)
|
12
|
+
draw = Renderer.instance.draw
|
13
|
+
|
14
|
+
# draw.push # TODO
|
15
|
+
draw.stroke_width(@width)
|
16
|
+
draw.stroke(@color)
|
17
|
+
draw.fill(@color)
|
18
|
+
if @style.to_s == 'square'
|
19
|
+
square(draw, new_x, new_y, circle_radius)
|
20
|
+
else
|
21
|
+
circle(draw, new_x, new_y, circle_radius)
|
22
|
+
end
|
23
|
+
# draw.pop # TODO
|
24
|
+
end
|
25
|
+
|
26
|
+
def circle(draw, new_x, new_y, circle_radius)
|
27
|
+
draw.circle(new_x, new_y, new_x - circle_radius, new_y)
|
28
|
+
end
|
29
|
+
|
30
|
+
def square(draw, new_x, new_y, circle_radius)
|
31
|
+
offset = (circle_radius * 0.8).to_i
|
32
|
+
corner1 = new_x - offset
|
33
|
+
corner2 = new_y - offset
|
34
|
+
corner3 = new_x + offset
|
35
|
+
corner4 = new_y + offset
|
36
|
+
draw.rectangle(corner1, corner2, corner3, corner4)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gruff
|
4
|
+
class Renderer::Ellipse
|
5
|
+
def initialize(args = {})
|
6
|
+
@color = args[:color]
|
7
|
+
@width = args[:width] || 1.0
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(origin_x, origin_y, width, height, arc_start, arc_end)
|
11
|
+
draw = Renderer.instance.draw
|
12
|
+
|
13
|
+
draw.push
|
14
|
+
draw.stroke_width(@width)
|
15
|
+
draw.stroke(@color)
|
16
|
+
draw.fill('transparent')
|
17
|
+
draw.ellipse(origin_x, origin_y, width, height, arc_start, arc_end)
|
18
|
+
draw.pop
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gruff
|
4
|
+
class Renderer::Line
|
5
|
+
EPSILON = 0.001
|
6
|
+
|
7
|
+
def initialize(args = {})
|
8
|
+
@color = args[:color]
|
9
|
+
@width = args[:width]
|
10
|
+
end
|
11
|
+
|
12
|
+
def render(start_x, start_y, end_x, end_y)
|
13
|
+
# FIXME(uwe): Workaround for Issue #66
|
14
|
+
# https://github.com/topfunky/gruff/issues/66
|
15
|
+
# https://github.com/rmagick/rmagick/issues/82
|
16
|
+
# Remove if the issue gets fixed.
|
17
|
+
unless defined?(JRUBY_VERSION)
|
18
|
+
start_x += EPSILON
|
19
|
+
end_x += EPSILON
|
20
|
+
start_y += EPSILON
|
21
|
+
end_y += EPSILON
|
22
|
+
end
|
23
|
+
|
24
|
+
draw = Renderer.instance.draw
|
25
|
+
|
26
|
+
draw.push
|
27
|
+
draw.stroke(@color)
|
28
|
+
draw.fill(@color)
|
29
|
+
draw.stroke_width(@width) if @width
|
30
|
+
draw.line(start_x, start_y, end_x, end_y)
|
31
|
+
draw.pop
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gruff
|
4
|
+
class Renderer::Polygon
|
5
|
+
def initialize(args = {})
|
6
|
+
@color = args[:color]
|
7
|
+
@width = args[:width] || 1.0
|
8
|
+
@opacity = args[:opacity] || 1.0
|
9
|
+
end
|
10
|
+
|
11
|
+
def render(points)
|
12
|
+
draw = Renderer.instance.draw
|
13
|
+
|
14
|
+
draw.push
|
15
|
+
draw.stroke_width(@width)
|
16
|
+
draw.stroke(@color)
|
17
|
+
draw.fill(@color)
|
18
|
+
draw.fill_opacity(@opacity)
|
19
|
+
draw.polygon(*points)
|
20
|
+
draw.pop
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gruff
|
4
|
+
class Renderer::Polyline
|
5
|
+
def initialize(args = {})
|
6
|
+
@color = args[:color]
|
7
|
+
@width = args[:width]
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(points)
|
11
|
+
draw = Renderer.instance.draw
|
12
|
+
|
13
|
+
draw.push
|
14
|
+
draw.stroke(@color)
|
15
|
+
draw.fill('transparent')
|
16
|
+
draw.stroke_width(@width)
|
17
|
+
draw.polyline(*points)
|
18
|
+
draw.pop
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gruff
|
4
|
+
class Renderer::Rectangle
|
5
|
+
def initialize(args = {})
|
6
|
+
@color = args[:color]
|
7
|
+
end
|
8
|
+
|
9
|
+
def render(upper_left_x, upper_left_y, lower_right_x, lower_right_y)
|
10
|
+
draw = Renderer.instance.draw
|
11
|
+
|
12
|
+
draw.push
|
13
|
+
draw.stroke('transparent')
|
14
|
+
draw.fill(@color) if @color
|
15
|
+
draw.rectangle(upper_left_x, upper_left_y, lower_right_x, lower_right_y)
|
16
|
+
draw.pop
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module Gruff
|
6
|
+
# @private
|
7
|
+
class Renderer
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
attr_accessor :draw, :image, :scale
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def setup(columns, rows, font, scale, theme_options)
|
14
|
+
draw = Magick::Draw.new
|
15
|
+
draw.font = font if font
|
16
|
+
# Scale down from 800x600 used to calculate drawing.
|
17
|
+
draw.scale(scale, scale)
|
18
|
+
|
19
|
+
image = Renderer.instance.background(columns, rows, scale, theme_options)
|
20
|
+
|
21
|
+
Renderer.instance.draw = draw
|
22
|
+
Renderer.instance.scale = scale
|
23
|
+
Renderer.instance.image = image
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup_transparent_background(columns, rows)
|
27
|
+
image = Renderer.instance.render_transparent_background(columns, rows)
|
28
|
+
Renderer.instance.image = image
|
29
|
+
end
|
30
|
+
|
31
|
+
def background_image=(image)
|
32
|
+
Renderer.instance.image = image
|
33
|
+
end
|
34
|
+
|
35
|
+
def font=(font)
|
36
|
+
draw = Renderer.instance.draw
|
37
|
+
draw.font = font if font
|
38
|
+
end
|
39
|
+
|
40
|
+
def finish
|
41
|
+
draw = Renderer.instance.draw
|
42
|
+
image = Renderer.instance.image
|
43
|
+
|
44
|
+
draw.draw(image)
|
45
|
+
end
|
46
|
+
|
47
|
+
def write(file_name)
|
48
|
+
Renderer.instance.image.write(file_name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_blob(file_format)
|
52
|
+
Renderer.instance.image.to_blob do
|
53
|
+
self.format = file_format
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def background(columns, rows, scale, theme_options)
|
59
|
+
case theme_options[:background_colors]
|
60
|
+
when Array
|
61
|
+
gradated_background(columns, rows, theme_options[:background_colors][0], theme_options[:background_colors][1], theme_options[:background_direction])
|
62
|
+
when String
|
63
|
+
solid_background(columns, rows, theme_options[:background_colors])
|
64
|
+
else
|
65
|
+
image_background(scale, *theme_options[:background_image])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Make a new image at the current size with a solid +color+.
|
70
|
+
def solid_background(columns, rows, color)
|
71
|
+
Magick::Image.new(columns, rows) do
|
72
|
+
self.background_color = color
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Use with a theme definition method to draw a gradated background.
|
77
|
+
def gradated_background(columns, rows, top_color, bottom_color, direct = :top_bottom)
|
78
|
+
gradient_fill = begin
|
79
|
+
case direct
|
80
|
+
when :bottom_top
|
81
|
+
Magick::GradientFill.new(0, 0, 100, 0, bottom_color, top_color)
|
82
|
+
when :left_right
|
83
|
+
Magick::GradientFill.new(0, 0, 0, 100, top_color, bottom_color)
|
84
|
+
when :right_left
|
85
|
+
Magick::GradientFill.new(0, 0, 0, 100, bottom_color, top_color)
|
86
|
+
when :topleft_bottomright
|
87
|
+
Magick::GradientFill.new(0, 100, 100, 0, top_color, bottom_color)
|
88
|
+
when :topright_bottomleft
|
89
|
+
Magick::GradientFill.new(0, 0, 100, 100, bottom_color, top_color)
|
90
|
+
else
|
91
|
+
Magick::GradientFill.new(0, 0, 100, 0, top_color, bottom_color)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
image = Magick::Image.new(columns, rows, gradient_fill)
|
96
|
+
@gradated_background_retry_count = 0
|
97
|
+
|
98
|
+
image
|
99
|
+
rescue StandardError => e
|
100
|
+
@gradated_background_retry_count ||= 0
|
101
|
+
GC.start
|
102
|
+
|
103
|
+
if @gradated_background_retry_count < 3
|
104
|
+
@gradated_background_retry_count += 1
|
105
|
+
gradated_background(top_color, bottom_color, direct)
|
106
|
+
else
|
107
|
+
raise e
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Use with a theme to use an image (800x600 original) background.
|
112
|
+
def image_background(scale, image_path)
|
113
|
+
image = Magick::Image.read(image_path)
|
114
|
+
if scale != 1.0
|
115
|
+
image[0].resize!(scale) # TODO: Resize with new scale (crop if necessary for wide graph)
|
116
|
+
end
|
117
|
+
image[0]
|
118
|
+
end
|
119
|
+
|
120
|
+
# Use with a theme to make a transparent background
|
121
|
+
def render_transparent_background(columns, rows)
|
122
|
+
Magick::Image.new(columns, rows) do
|
123
|
+
self.background_color = 'transparent'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|