gruff 0.12.2 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +66 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +34 -27
- data/CHANGELOG.md +29 -0
- data/README.md +15 -7
- data/assets/fonts/LICENSE.txt +202 -0
- data/assets/fonts/Roboto-Bold.ttf +0 -0
- data/assets/fonts/Roboto-Regular.ttf +0 -0
- data/gruff.gemspec +9 -10
- data/lib/gruff/accumulator_bar.rb +3 -1
- data/lib/gruff/area.rb +5 -8
- data/lib/gruff/bar.rb +32 -49
- data/lib/gruff/base.rb +199 -115
- data/lib/gruff/bezier.rb +4 -6
- data/lib/gruff/bullet.rb +12 -11
- data/lib/gruff/dot.rb +13 -14
- data/lib/gruff/font.rb +39 -0
- data/lib/gruff/helper/bar_conversion.rb +27 -12
- data/lib/gruff/helper/bar_value_label.rb +71 -0
- data/lib/gruff/helper/stacked_mixin.rb +1 -2
- data/lib/gruff/histogram.rb +9 -7
- data/lib/gruff/line.rb +57 -50
- data/lib/gruff/mini/bar.rb +9 -6
- data/lib/gruff/mini/legend.rb +12 -8
- data/lib/gruff/mini/pie.rb +9 -6
- data/lib/gruff/mini/side_bar.rb +9 -6
- data/lib/gruff/net.rb +9 -15
- data/lib/gruff/patch/rmagick.rb +0 -1
- data/lib/gruff/patch/string.rb +1 -1
- data/lib/gruff/pie.rb +23 -65
- data/lib/gruff/renderer/bezier.rb +8 -9
- data/lib/gruff/renderer/circle.rb +8 -9
- data/lib/gruff/renderer/dash_line.rb +9 -10
- data/lib/gruff/renderer/dot.rb +13 -14
- data/lib/gruff/renderer/ellipse.rb +8 -9
- data/lib/gruff/renderer/line.rb +8 -9
- data/lib/gruff/renderer/polygon.rb +9 -10
- data/lib/gruff/renderer/polyline.rb +8 -9
- data/lib/gruff/renderer/rectangle.rb +7 -8
- data/lib/gruff/renderer/renderer.rb +25 -40
- data/lib/gruff/renderer/text.rb +21 -29
- data/lib/gruff/scatter.rb +55 -75
- data/lib/gruff/scene.rb +28 -18
- data/lib/gruff/side_bar.rb +35 -54
- data/lib/gruff/side_stacked_bar.rb +14 -17
- data/lib/gruff/spider.rb +11 -20
- data/lib/gruff/stacked_area.rb +10 -11
- data/lib/gruff/stacked_bar.rb +14 -15
- data/lib/gruff/store/store.rb +6 -10
- data/lib/gruff/store/xy_data.rb +2 -0
- data/lib/gruff/themes.rb +6 -6
- data/lib/gruff/version.rb +1 -1
- data/lib/gruff.rb +68 -55
- data/rails_generators/gruff/templates/controller.rb +1 -1
- metadata +34 -20
- data/.rubocop_todo.yml +0 -190
- data/.travis.yml +0 -23
- data/assets/plastik/blue.png +0 -0
- data/assets/plastik/green.png +0 -0
- data/assets/plastik/red.png +0 -0
- data/lib/gruff/helper/bar_value_label_mixin.rb +0 -33
- data/lib/gruff/photo_bar.rb +0 -93
data/lib/gruff/mini/side_bar.rb
CHANGED
@@ -23,24 +23,27 @@ module Gruff
|
|
23
23
|
module Mini
|
24
24
|
# A class for drawing a small side bar graph.
|
25
25
|
class SideBar < Gruff::SideBar
|
26
|
+
private
|
27
|
+
|
26
28
|
include Gruff::Mini::Legend
|
27
29
|
|
28
|
-
def
|
30
|
+
def initialize_attributes
|
29
31
|
super
|
30
32
|
@hide_legend = true
|
31
33
|
@hide_title = true
|
32
34
|
@hide_line_numbers = true
|
33
35
|
|
34
|
-
@
|
35
|
-
@
|
36
|
+
@marker_font.size = 50.0
|
37
|
+
@legend_font.size = 50.0
|
36
38
|
end
|
37
|
-
private :initialize_ivars
|
38
39
|
|
39
|
-
def
|
40
|
+
def setup_data
|
40
41
|
expand_canvas_for_vertical_legend
|
41
|
-
|
42
42
|
super
|
43
|
+
end
|
43
44
|
|
45
|
+
def draw_graph
|
46
|
+
super
|
44
47
|
draw_vertical_legend
|
45
48
|
end
|
46
49
|
end
|
data/lib/gruff/net.rb
CHANGED
@@ -30,7 +30,9 @@ class Gruff::Net < Gruff::Base
|
|
30
30
|
attr_writer :line_width
|
31
31
|
attr_writer :dot_radius
|
32
32
|
|
33
|
-
|
33
|
+
private
|
34
|
+
|
35
|
+
def initialize_attributes
|
34
36
|
super
|
35
37
|
|
36
38
|
@hide_dots = false
|
@@ -38,14 +40,10 @@ class Gruff::Net < Gruff::Base
|
|
38
40
|
@dot_radius = nil
|
39
41
|
@hide_line_numbers = true
|
40
42
|
@sorted_drawing = true
|
43
|
+
@marker_font.bold = true
|
41
44
|
end
|
42
|
-
private :initialize_ivars
|
43
|
-
|
44
|
-
def draw
|
45
|
-
super
|
46
|
-
|
47
|
-
return unless data_given?
|
48
45
|
|
46
|
+
def draw_graph
|
49
47
|
store.norm_data.each do |data_row|
|
50
48
|
data_row.points.each_with_index do |data_point, index|
|
51
49
|
next if data_point.nil?
|
@@ -62,18 +60,16 @@ class Gruff::Net < Gruff::Base
|
|
62
60
|
end_x = @center_x + Math.sin(next_rad_pos) * next_point_distance
|
63
61
|
end_y = @center_y - Math.cos(next_rad_pos) * next_point_distance
|
64
62
|
|
65
|
-
Gruff::Renderer::Line.new(color: data_row.color, width: @stroke_width).render(start_x, start_y, end_x, end_y)
|
63
|
+
Gruff::Renderer::Line.new(renderer, color: data_row.color, width: @stroke_width).render(start_x, start_y, end_x, end_y)
|
66
64
|
|
67
65
|
unless @hide_dots
|
68
|
-
circle_renderer = Gruff::Renderer::Circle.new(color: data_row.color, width: @stroke_width)
|
66
|
+
circle_renderer = Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: @stroke_width)
|
69
67
|
circle_renderer.render(start_x, start_y, start_x - @circle_radius, start_y)
|
70
68
|
end
|
71
69
|
end
|
72
70
|
end
|
73
71
|
end
|
74
72
|
|
75
|
-
private
|
76
|
-
|
77
73
|
def setup_drawing
|
78
74
|
super
|
79
75
|
|
@@ -92,7 +88,7 @@ private
|
|
92
88
|
(0..column_count - 1).each do |index|
|
93
89
|
rad_pos = index * Math::PI * 2 / column_count
|
94
90
|
|
95
|
-
Gruff::Renderer::Line.new(color: @marker_color)
|
91
|
+
Gruff::Renderer::Line.new(renderer, color: @marker_color)
|
96
92
|
.render(@center_x, @center_y, @center_x + Math.sin(rad_pos) * @radius, @center_y - Math.cos(rad_pos) * @radius)
|
97
93
|
|
98
94
|
marker_label = @labels[index] ? @labels[index].to_s : '000'
|
@@ -106,8 +102,6 @@ private
|
|
106
102
|
x = x_offset + (radius + LABEL_MARGIN) * Math.sin(deg2rad(angle))
|
107
103
|
y = y_offset - (radius + LABEL_MARGIN) * Math.cos(deg2rad(angle))
|
108
104
|
|
109
|
-
|
110
|
-
text_renderer = Gruff::Renderer::Text.new(amount, font: @font, size: 20, color: @marker_color, weight: Magick::BoldWeight)
|
111
|
-
text_renderer.add_to_render_queue(0, 0, x, y, Magick::CenterGravity)
|
105
|
+
draw_label_at(1.0, 1.0, x, y, amount, Magick::CenterGravity)
|
112
106
|
end
|
113
107
|
end
|
data/lib/gruff/patch/rmagick.rb
CHANGED
data/lib/gruff/patch/string.rb
CHANGED
@@ -5,7 +5,7 @@ module String::GruffCommify
|
|
5
5
|
THOUSAND_SEPARATOR = ','
|
6
6
|
|
7
7
|
refine String do
|
8
|
-
#Taken from http://codesnippets.joyent.com/posts/show/330
|
8
|
+
# Taken from http://codesnippets.joyent.com/posts/show/330
|
9
9
|
def commify(delimiter = THOUSAND_SEPARATOR)
|
10
10
|
gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
|
11
11
|
end
|
data/lib/gruff/pie.rb
CHANGED
@@ -18,6 +18,9 @@ class Gruff::Pie < Gruff::Base
|
|
18
18
|
# or at another angle. Default is +0.0+, which starts at 3 o'clock.
|
19
19
|
attr_writer :zero_degree
|
20
20
|
|
21
|
+
# Set the number output format lambda.
|
22
|
+
attr_writer :label_formatting
|
23
|
+
|
21
24
|
# Do not show labels for slices that are less than this percent. Use 0 to always show all labels.
|
22
25
|
# Defaults to +0+.
|
23
26
|
attr_writer :hide_labels_less_than
|
@@ -29,39 +32,30 @@ class Gruff::Pie < Gruff::Base
|
|
29
32
|
## Use values instead of percentages.
|
30
33
|
attr_writer :show_values_as_labels
|
31
34
|
|
35
|
+
private
|
36
|
+
|
32
37
|
def initialize_store
|
33
38
|
@store = Gruff::Store.new(Gruff::Store::CustomData)
|
34
39
|
end
|
35
|
-
private :initialize_store
|
36
40
|
|
37
|
-
def
|
41
|
+
def initialize_attributes
|
38
42
|
super
|
39
43
|
@zero_degree = 0.0
|
40
44
|
@hide_labels_less_than = 0.0
|
41
45
|
@text_offset_percentage = DEFAULT_TEXT_OFFSET_PERCENTAGE
|
42
46
|
@show_values_as_labels = false
|
43
|
-
|
44
|
-
private :initialize_ivars
|
47
|
+
@marker_font.bold = true
|
45
48
|
|
46
|
-
|
47
|
-
|
48
|
-
zero_degree: @zero_degree,
|
49
|
-
hide_labels_less_than: @hide_labels_less_than,
|
50
|
-
text_offset_percentage: @text_offset_percentage,
|
51
|
-
show_values_as_labels: @show_values_as_labels
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
def draw
|
56
|
-
hide_line_markers
|
57
|
-
|
58
|
-
super
|
49
|
+
@hide_line_markers = true
|
50
|
+
@hide_line_markers.freeze
|
59
51
|
|
60
|
-
|
52
|
+
@label_formatting = ->(value, percentage) { @show_values_as_labels ? value.to_s : "#{percentage}%" }
|
53
|
+
end
|
61
54
|
|
55
|
+
def draw_graph
|
62
56
|
slices.each do |slice|
|
63
57
|
if slice.value > 0
|
64
|
-
Gruff::Renderer::Ellipse.new(color: slice.color, width: radius)
|
58
|
+
Gruff::Renderer::Ellipse.new(renderer, color: slice.color, width: radius)
|
65
59
|
.render(center_x, center_y, radius / 2.0, radius / 2.0, chart_degrees, chart_degrees + slice.degrees + 0.5)
|
66
60
|
process_label_for slice
|
67
61
|
update_chart_degrees_with slice.degrees
|
@@ -69,11 +63,9 @@ class Gruff::Pie < Gruff::Base
|
|
69
63
|
end
|
70
64
|
end
|
71
65
|
|
72
|
-
private
|
73
|
-
|
74
66
|
def slices
|
75
67
|
@slices ||= begin
|
76
|
-
slices = store.data.map { |data|
|
68
|
+
slices = store.data.map { |data| Gruff::Pie::PieSlice.new(data.label, data.points.first, data.color) }
|
77
69
|
|
78
70
|
slices.sort_by(&:value) if @sort
|
79
71
|
|
@@ -84,18 +76,10 @@ private
|
|
84
76
|
|
85
77
|
# General Helper Methods
|
86
78
|
|
87
|
-
def hide_line_markers
|
88
|
-
@hide_line_markers = true
|
89
|
-
end
|
90
|
-
|
91
79
|
def update_chart_degrees_with(degrees)
|
92
80
|
@chart_degrees = chart_degrees + degrees
|
93
81
|
end
|
94
82
|
|
95
|
-
def slice_class
|
96
|
-
PieSlice
|
97
|
-
end
|
98
|
-
|
99
83
|
# Spatial Value-Related Methods
|
100
84
|
|
101
85
|
def chart_degrees
|
@@ -103,13 +87,8 @@ private
|
|
103
87
|
end
|
104
88
|
|
105
89
|
attr_reader :graph_height
|
106
|
-
|
107
90
|
attr_reader :graph_width
|
108
91
|
|
109
|
-
def diameter
|
110
|
-
graph_height
|
111
|
-
end
|
112
|
-
|
113
92
|
def half_width
|
114
93
|
graph_width / 2.0
|
115
94
|
end
|
@@ -147,8 +126,8 @@ private
|
|
147
126
|
def process_label_for(slice)
|
148
127
|
if slice.percentage >= @hide_labels_less_than
|
149
128
|
x, y = label_coordinates_for slice
|
150
|
-
|
151
|
-
|
129
|
+
label = @label_formatting.call(slice.value, slice.percentage)
|
130
|
+
draw_label_at(1.0, 1.0, x, y, label, Magick::CenterGravity)
|
152
131
|
end
|
153
132
|
end
|
154
133
|
|
@@ -166,45 +145,24 @@ private
|
|
166
145
|
center_y + (radius_offset * Math.sin(deg2rad(angle)))
|
167
146
|
end
|
168
147
|
|
169
|
-
# Drawing-Related Methods
|
170
|
-
|
171
|
-
def draw_label(x, y, value)
|
172
|
-
text_renderer = Gruff::Renderer::Text.new(value, font: @font, size: @marker_font_size, color: @font_color, weight: Magick::BoldWeight)
|
173
|
-
text_renderer.add_to_render_queue(0, 0, x, y, Magick::CenterGravity)
|
174
|
-
end
|
175
|
-
|
176
148
|
# Helper Classes
|
177
149
|
#
|
178
150
|
# @private
|
179
|
-
class PieSlice < Struct.new(:
|
151
|
+
class PieSlice < Struct.new(:label, :value, :color)
|
180
152
|
attr_accessor :total
|
181
153
|
|
182
|
-
def name
|
183
|
-
data_array[0]
|
184
|
-
end
|
185
|
-
|
186
|
-
def value
|
187
|
-
data_array[1].first
|
188
|
-
end
|
189
|
-
|
190
|
-
def color
|
191
|
-
data_array[2]
|
192
|
-
end
|
193
|
-
|
194
|
-
def size
|
195
|
-
@size ||= value / total
|
196
|
-
end
|
197
|
-
|
198
154
|
def percentage
|
199
|
-
|
155
|
+
(size * 100.0).round
|
200
156
|
end
|
201
157
|
|
202
158
|
def degrees
|
203
|
-
|
159
|
+
size * 360.0
|
204
160
|
end
|
205
161
|
|
206
|
-
|
207
|
-
|
162
|
+
private
|
163
|
+
|
164
|
+
def size
|
165
|
+
value / total
|
208
166
|
end
|
209
167
|
end
|
210
168
|
end
|
@@ -3,20 +3,19 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Bezier
|
6
|
-
def initialize(color:, width: 1.0)
|
6
|
+
def initialize(renderer, color:, width: 1.0)
|
7
|
+
@renderer = renderer
|
7
8
|
@color = color
|
8
9
|
@width = width
|
9
10
|
end
|
10
11
|
|
11
12
|
def render(points)
|
12
|
-
draw
|
13
|
-
|
14
|
-
draw.
|
15
|
-
draw.
|
16
|
-
draw.
|
17
|
-
draw.
|
18
|
-
draw.bezier(*points)
|
19
|
-
draw.pop
|
13
|
+
@renderer.draw.push
|
14
|
+
@renderer.draw.stroke(@color)
|
15
|
+
@renderer.draw.stroke_width(@width)
|
16
|
+
@renderer.draw.fill_opacity(0.0)
|
17
|
+
@renderer.draw.bezier(*points)
|
18
|
+
@renderer.draw.pop
|
20
19
|
end
|
21
20
|
end
|
22
21
|
end
|
@@ -3,20 +3,19 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Circle
|
6
|
-
def initialize(color:, width: 1.0)
|
6
|
+
def initialize(renderer, color:, width: 1.0)
|
7
|
+
@renderer = renderer
|
7
8
|
@color = color
|
8
9
|
@width = width
|
9
10
|
end
|
10
11
|
|
11
12
|
def render(origin_x, origin_y, perim_x, perim_y)
|
12
|
-
draw
|
13
|
-
|
14
|
-
draw.
|
15
|
-
draw.
|
16
|
-
draw.
|
17
|
-
draw.
|
18
|
-
draw.circle(origin_x, origin_y, perim_x, perim_y)
|
19
|
-
draw.pop
|
13
|
+
@renderer.draw.push
|
14
|
+
@renderer.draw.fill(@color)
|
15
|
+
@renderer.draw.stroke(@color)
|
16
|
+
@renderer.draw.stroke_width(@width)
|
17
|
+
@renderer.draw.circle(origin_x, origin_y, perim_x, perim_y)
|
18
|
+
@renderer.draw.pop
|
20
19
|
end
|
21
20
|
end
|
22
21
|
end
|
@@ -3,21 +3,20 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::DashLine
|
6
|
-
def initialize(color:, width:)
|
6
|
+
def initialize(renderer, color:, width:)
|
7
|
+
@renderer = renderer
|
7
8
|
@color = color
|
8
9
|
@width = width
|
9
10
|
end
|
10
11
|
|
11
12
|
def render(start_x, start_y, end_x, end_y)
|
12
|
-
draw
|
13
|
-
|
14
|
-
draw.
|
15
|
-
draw.
|
16
|
-
draw.
|
17
|
-
draw.
|
18
|
-
draw.
|
19
|
-
draw.line(start_x, start_y, end_x, end_y)
|
20
|
-
draw.pop
|
13
|
+
@renderer.draw.push
|
14
|
+
@renderer.draw.stroke_color(@color)
|
15
|
+
@renderer.draw.fill_opacity(0.0)
|
16
|
+
@renderer.draw.stroke_dasharray(10, 20)
|
17
|
+
@renderer.draw.stroke_width(@width)
|
18
|
+
@renderer.draw.line(start_x, start_y, end_x, end_y)
|
19
|
+
@renderer.draw.pop
|
21
20
|
end
|
22
21
|
end
|
23
22
|
end
|
data/lib/gruff/renderer/dot.rb
CHANGED
@@ -3,38 +3,37 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Dot
|
6
|
-
def initialize(style, color:, width: 1.0)
|
6
|
+
def initialize(renderer, style, color:, width: 1.0)
|
7
|
+
@renderer = renderer
|
7
8
|
@style = style
|
8
9
|
@color = color
|
9
10
|
@width = width
|
10
11
|
end
|
11
12
|
|
12
13
|
def render(new_x, new_y, circle_radius)
|
13
|
-
draw
|
14
|
-
|
15
|
-
|
16
|
-
draw.
|
17
|
-
draw.stroke(@color)
|
18
|
-
draw.fill(@color)
|
14
|
+
# @renderer.draw.push # TODO
|
15
|
+
@renderer.draw.stroke_width(@width)
|
16
|
+
@renderer.draw.stroke(@color)
|
17
|
+
@renderer.draw.fill(@color)
|
19
18
|
if @style.to_s == 'square'
|
20
|
-
square(
|
19
|
+
square(new_x, new_y, circle_radius)
|
21
20
|
else
|
22
|
-
circle(
|
21
|
+
circle(new_x, new_y, circle_radius)
|
23
22
|
end
|
24
|
-
# draw.pop # TODO
|
23
|
+
# @renderer.draw.pop # TODO
|
25
24
|
end
|
26
25
|
|
27
|
-
def circle(
|
28
|
-
draw.circle(new_x, new_y, new_x - circle_radius, new_y)
|
26
|
+
def circle(new_x, new_y, circle_radius)
|
27
|
+
@renderer.draw.circle(new_x, new_y, new_x - circle_radius, new_y)
|
29
28
|
end
|
30
29
|
|
31
|
-
def square(
|
30
|
+
def square(new_x, new_y, circle_radius)
|
32
31
|
offset = (circle_radius * 0.8).to_i
|
33
32
|
corner1 = new_x - offset
|
34
33
|
corner2 = new_y - offset
|
35
34
|
corner3 = new_x + offset
|
36
35
|
corner4 = new_y + offset
|
37
|
-
draw.rectangle(corner1, corner2, corner3, corner4)
|
36
|
+
@renderer.draw.rectangle(corner1, corner2, corner3, corner4)
|
38
37
|
end
|
39
38
|
end
|
40
39
|
end
|
@@ -3,20 +3,19 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Ellipse
|
6
|
-
def initialize(color:, width: 1.0)
|
6
|
+
def initialize(renderer, color:, width: 1.0)
|
7
|
+
@renderer = renderer
|
7
8
|
@color = color
|
8
9
|
@width = width
|
9
10
|
end
|
10
11
|
|
11
12
|
def render(origin_x, origin_y, width, height, arc_start, arc_end)
|
12
|
-
draw
|
13
|
-
|
14
|
-
draw.
|
15
|
-
draw.
|
16
|
-
draw.
|
17
|
-
draw.
|
18
|
-
draw.ellipse(origin_x, origin_y, width, height, arc_start, arc_end)
|
19
|
-
draw.pop
|
13
|
+
@renderer.draw.push
|
14
|
+
@renderer.draw.stroke_width(@width)
|
15
|
+
@renderer.draw.stroke(@color)
|
16
|
+
@renderer.draw.fill('transparent')
|
17
|
+
@renderer.draw.ellipse(origin_x, origin_y, width, height, arc_start, arc_end)
|
18
|
+
@renderer.draw.pop
|
20
19
|
end
|
21
20
|
end
|
22
21
|
end
|
data/lib/gruff/renderer/line.rb
CHANGED
@@ -5,7 +5,8 @@ module Gruff
|
|
5
5
|
class Renderer::Line
|
6
6
|
EPSILON = 0.001
|
7
7
|
|
8
|
-
def initialize(color:, width: nil, shadow_color: nil)
|
8
|
+
def initialize(renderer, color:, width: nil, shadow_color: nil)
|
9
|
+
@renderer = renderer
|
9
10
|
@color = color
|
10
11
|
@width = width
|
11
12
|
@shadow_color = shadow_color
|
@@ -30,14 +31,12 @@ module Gruff
|
|
30
31
|
end_y += EPSILON
|
31
32
|
end
|
32
33
|
|
33
|
-
draw
|
34
|
-
|
35
|
-
draw.
|
36
|
-
draw.
|
37
|
-
draw.
|
38
|
-
draw.
|
39
|
-
draw.line(start_x, start_y, end_x, end_y)
|
40
|
-
draw.pop
|
34
|
+
@renderer.draw.push
|
35
|
+
@renderer.draw.stroke(color)
|
36
|
+
@renderer.draw.fill(color)
|
37
|
+
@renderer.draw.stroke_width(@width) if @width
|
38
|
+
@renderer.draw.line(start_x, start_y, end_x, end_y)
|
39
|
+
@renderer.draw.pop
|
41
40
|
end
|
42
41
|
end
|
43
42
|
end
|
@@ -3,22 +3,21 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Polygon
|
6
|
-
def initialize(color:, width: 1.0, opacity: 1.0)
|
6
|
+
def initialize(renderer, color:, width: 1.0, opacity: 1.0)
|
7
|
+
@renderer = renderer
|
7
8
|
@color = color
|
8
9
|
@width = width
|
9
10
|
@opacity = opacity
|
10
11
|
end
|
11
12
|
|
12
13
|
def render(points)
|
13
|
-
draw
|
14
|
-
|
15
|
-
draw.
|
16
|
-
draw.
|
17
|
-
draw.
|
18
|
-
draw.
|
19
|
-
draw.
|
20
|
-
draw.polygon(*points)
|
21
|
-
draw.pop
|
14
|
+
@renderer.draw.push
|
15
|
+
@renderer.draw.stroke_width(@width)
|
16
|
+
@renderer.draw.stroke(@color)
|
17
|
+
@renderer.draw.fill(@color)
|
18
|
+
@renderer.draw.fill_opacity(@opacity)
|
19
|
+
@renderer.draw.polygon(*points)
|
20
|
+
@renderer.draw.pop
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
@@ -3,20 +3,19 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Polyline
|
6
|
-
def initialize(color:, width:)
|
6
|
+
def initialize(renderer, color:, width:)
|
7
|
+
@renderer = renderer
|
7
8
|
@color = color
|
8
9
|
@width = width
|
9
10
|
end
|
10
11
|
|
11
12
|
def render(points)
|
12
|
-
draw
|
13
|
-
|
14
|
-
draw.
|
15
|
-
draw.
|
16
|
-
draw.
|
17
|
-
draw.
|
18
|
-
draw.polyline(*points)
|
19
|
-
draw.pop
|
13
|
+
@renderer.draw.push
|
14
|
+
@renderer.draw.stroke(@color)
|
15
|
+
@renderer.draw.fill('transparent')
|
16
|
+
@renderer.draw.stroke_width(@width)
|
17
|
+
@renderer.draw.polyline(*points)
|
18
|
+
@renderer.draw.pop
|
20
19
|
end
|
21
20
|
end
|
22
21
|
end
|
@@ -3,18 +3,17 @@
|
|
3
3
|
module Gruff
|
4
4
|
# @private
|
5
5
|
class Renderer::Rectangle
|
6
|
-
def initialize(color: nil)
|
6
|
+
def initialize(renderer, color: nil)
|
7
|
+
@renderer = renderer
|
7
8
|
@color = color
|
8
9
|
end
|
9
10
|
|
10
11
|
def render(upper_left_x, upper_left_y, lower_right_x, lower_right_y)
|
11
|
-
draw
|
12
|
-
|
13
|
-
draw.
|
14
|
-
draw.
|
15
|
-
draw.
|
16
|
-
draw.rectangle(upper_left_x, upper_left_y, lower_right_x, lower_right_y)
|
17
|
-
draw.pop
|
12
|
+
@renderer.draw.push
|
13
|
+
@renderer.draw.stroke('transparent')
|
14
|
+
@renderer.draw.fill(@color) if @color
|
15
|
+
@renderer.draw.rectangle(upper_left_x, upper_left_y, lower_right_x, lower_right_y)
|
16
|
+
@renderer.draw.pop
|
18
17
|
end
|
19
18
|
end
|
20
19
|
end
|
@@ -1,53 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'singleton'
|
4
|
-
|
5
3
|
module Gruff
|
6
4
|
# @private
|
7
5
|
class Renderer
|
8
|
-
|
9
|
-
|
10
|
-
attr_accessor :draw, :image, :scale, :text_renderers
|
11
|
-
|
12
|
-
def self.setup(columns, rows, font, scale, theme_options)
|
13
|
-
draw = Magick::Draw.new
|
14
|
-
draw.font = font if font
|
15
|
-
# Scale down from 800x600 used to calculate drawing.
|
16
|
-
draw.scale(scale, scale)
|
17
|
-
|
18
|
-
image = Renderer.instance.background(columns, rows, scale, theme_options)
|
6
|
+
attr_accessor :text_renderers
|
7
|
+
attr_reader :draw, :image, :scale
|
19
8
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
Renderer.instance.text_renderers = []
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.setup_transparent_background(columns, rows)
|
27
|
-
image = Renderer.instance.render_transparent_background(columns, rows)
|
28
|
-
Renderer.instance.image = image
|
29
|
-
end
|
9
|
+
def initialize(columns, rows, scale, theme_options)
|
10
|
+
@draw = Magick::Draw.new
|
11
|
+
@text_renderers = []
|
30
12
|
|
31
|
-
|
32
|
-
|
13
|
+
@scale = scale
|
14
|
+
@draw.scale(scale, scale)
|
15
|
+
@image = background(columns, rows, scale, theme_options)
|
33
16
|
end
|
34
17
|
|
35
|
-
def
|
36
|
-
draw
|
37
|
-
draw.font = font if font
|
38
|
-
end
|
18
|
+
def finish
|
19
|
+
@draw.draw(@image)
|
39
20
|
|
40
|
-
|
41
|
-
draw = Renderer.instance.draw
|
42
|
-
image = Renderer.instance.image
|
43
|
-
|
44
|
-
draw.draw(image)
|
45
|
-
|
46
|
-
Renderer.instance.text_renderers.each do |renderer|
|
21
|
+
@text_renderers.each do |renderer|
|
47
22
|
renderer.render(renderer.width, renderer.height, renderer.x, renderer.y, renderer.gravity)
|
48
23
|
end
|
49
24
|
end
|
50
25
|
|
26
|
+
def background_image=(image)
|
27
|
+
@image = image
|
28
|
+
end
|
29
|
+
|
51
30
|
def background(columns, rows, scale, theme_options)
|
52
31
|
case theme_options[:background_colors]
|
53
32
|
when Array
|
@@ -59,10 +38,14 @@ module Gruff
|
|
59
38
|
end
|
60
39
|
end
|
61
40
|
|
41
|
+
def transparent_background(columns, rows)
|
42
|
+
@image = render_transparent_background(columns, rows)
|
43
|
+
end
|
44
|
+
|
62
45
|
# Make a new image at the current size with a solid +color+.
|
63
46
|
def solid_background(columns, rows, color)
|
64
|
-
Magick::Image.new(columns, rows) do
|
65
|
-
|
47
|
+
Magick::Image.new(columns, rows) do |img|
|
48
|
+
img.background_color = color
|
66
49
|
end
|
67
50
|
end
|
68
51
|
|
@@ -101,6 +84,8 @@ module Gruff
|
|
101
84
|
end
|
102
85
|
end
|
103
86
|
|
87
|
+
private
|
88
|
+
|
104
89
|
# Use with a theme to use an image (800x600 original) background.
|
105
90
|
def image_background(scale, image_path)
|
106
91
|
image = Magick::Image.read(image_path)
|
@@ -112,8 +97,8 @@ module Gruff
|
|
112
97
|
|
113
98
|
# Use with a theme to make a transparent background
|
114
99
|
def render_transparent_background(columns, rows)
|
115
|
-
Magick::Image.new(columns, rows) do
|
116
|
-
|
100
|
+
Magick::Image.new(columns, rows) do |img|
|
101
|
+
img.background_color = 'transparent'
|
117
102
|
end
|
118
103
|
end
|
119
104
|
end
|