gruff 0.16.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -49,26 +49,4 @@ module Gruff::BarValueLabel
49
49
  yield x, left_y, val, metrics.width, metrics.height
50
50
  end
51
51
  end
52
-
53
- # @private
54
- class StackedBar
55
- def initialize
56
- @bars = []
57
- end
58
-
59
- def add(bar, index)
60
- bars = @bars[index] || []
61
- bars << bar
62
- @bars[index] = bars
63
- end
64
-
65
- def prepare_rendering(format, proc_text_metrics, &block)
66
- @bars.each do |bars|
67
- value = bars.sum(&:value)
68
- bar = bars.last
69
- bar_value_label = bar.class.new(bar.coordinate, value)
70
- bar_value_label.prepare_rendering(format, proc_text_metrics, &block)
71
- end
72
- end
73
- end
74
52
  end
@@ -21,4 +21,20 @@ module Gruff::Base::StackedMixin
21
21
 
22
22
  raise "Can't handle negative values in stacked graph" if minimum_value < 0
23
23
  end
24
+
25
+ def normalized_stacked_bars
26
+ @normalized_stacked_bars ||= begin
27
+ stacked_bars = Array.new(column_count) { [] }
28
+ store.norm_data.each_with_index do |data_row, row_index|
29
+ data_row.points.each_with_index do |data_point, point_index|
30
+ stacked_bars[point_index] << BarData.new(data_point, store.data[row_index].points[point_index], data_row.color)
31
+ end
32
+ end
33
+ stacked_bars
34
+ end
35
+ end
36
+
37
+ # @private
38
+ class BarData < Struct.new(:point, :value, :color)
39
+ end
24
40
  end
@@ -44,11 +44,15 @@ private
44
44
 
45
45
  def setup_data
46
46
  @data.each do |(name, data_points, color)|
47
- bins, freqs = HistogramArray.new(data_points).histogram(bin_width: @bin_width, min: @minimum_bin, max: @maximum_bin)
48
- bins.each_with_index do |bin, index|
49
- @labels[index] = bin
47
+ if data_points.empty?
48
+ store.add(name, [], color)
49
+ else
50
+ bins, freqs = HistogramArray.new(data_points).histogram(bin_width: @bin_width, min: @minimum_bin, max: @maximum_bin)
51
+ bins.each_with_index do |bin, index|
52
+ @labels[index] = bin
53
+ end
54
+ store.add(name, freqs, color)
50
55
  end
51
- store.add(name, freqs, color)
52
56
  end
53
57
 
54
58
  super
data/lib/gruff/line.rb CHANGED
@@ -25,7 +25,7 @@ class Gruff::Line < Gruff::Base
25
25
  attr_writer :line_width
26
26
  attr_writer :dot_radius
27
27
 
28
- # default is +'circle'+, other options include square.
28
+ # default is +'circle'+, other options include +square+ and +diamond+.
29
29
  attr_writer :dot_style
30
30
 
31
31
  # Hide parts of the graph to fit more data points, or for a different appearance.
@@ -273,10 +273,7 @@ private
273
273
  return unless @show_vertical_markers
274
274
 
275
275
  (0..@marker_x_count).each do |index|
276
- x = @graph_left + @graph_width - (index * @graph_width / @marker_x_count)
277
-
278
- Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_bottom, x, @graph_top)
279
- Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x + 1, @graph_bottom, x + 1, @graph_top) if @marker_shadow_color
276
+ draw_marker_vertical_line(@graph_left + @graph_width - (index * @graph_width / @marker_x_count))
280
277
  end
281
278
  end
282
279
 
@@ -21,7 +21,7 @@ module Gruff
21
21
 
22
22
  @legend_labels = store.data.map(&:label)
23
23
 
24
- legend_height = scale_fontsize((store.length * calculate_line_height) + @top_margin + @bottom_margin)
24
+ legend_height = scale((store.length * calculate_line_height) + @top_margin + @bottom_margin)
25
25
 
26
26
  @original_rows = @raw_rows
27
27
  @original_columns = @raw_columns
@@ -32,7 +32,7 @@ module Gruff
32
32
  @columns += calculate_legend_width + @left_margin
33
33
  else
34
34
  font = @legend_font.dup
35
- font.size = scale_fontsize(font.size)
35
+ font.size = scale(font.size)
36
36
  @rows += store.length * calculate_caps_height(font) * 1.7
37
37
  end
38
38
 
@@ -45,7 +45,7 @@ module Gruff
45
45
 
46
46
  def calculate_legend_width
47
47
  width = @legend_labels.map { |label| calculate_width(@legend_font, label) }.max
48
- scale_fontsize(width + (40 * 1.7))
48
+ scale(width + (40 * 1.7))
49
49
  end
50
50
 
51
51
  ##
@@ -69,9 +69,9 @@ module Gruff
69
69
 
70
70
  @legend_labels.each_with_index do |legend_label, index|
71
71
  # Draw label
72
- label = truncate_legend_label(legend_label)
73
- text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @legend_font)
74
72
  x_offset = current_x_offset + (legend_square_width * 1.7)
73
+ label = truncate_legend_label(legend_label, x_offset)
74
+ text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @legend_font)
75
75
  text_renderer.add_to_render_queue(@raw_columns, 1.0, x_offset, current_y_offset, Magick::WestGravity)
76
76
 
77
77
  # Now draw box with color of this dataset
@@ -90,13 +90,13 @@ module Gruff
90
90
  #
91
91
  # Department of Hu...
92
92
 
93
- def truncate_legend_label(label)
93
+ def truncate_legend_label(label, x_offset)
94
94
  truncated_label = label.to_s
95
95
 
96
96
  font = @legend_font.dup
97
- font.size = scale_fontsize(font.size)
98
- max_width = @columns - @legend_left_margin - @right_margin
99
- while calculate_width(font, truncated_label) > max_width && truncated_label.length > 1
97
+ font.size = scale(font.size)
98
+ max_width = @columns - scale(x_offset) - @right_margin
99
+ while calculate_width(font, "#{truncated_label}...") > max_width && truncated_label.length > 1
100
100
  truncated_label = truncated_label[0..truncated_label.length - 2]
101
101
  end
102
102
  truncated_label + (truncated_label.length < label.to_s.length ? '...' : '')
data/lib/gruff/net.rb CHANGED
@@ -43,6 +43,21 @@ private
43
43
  @marker_font.bold = true
44
44
  end
45
45
 
46
+ def setup_drawing
47
+ @center_labels_over_point = false
48
+ super
49
+ end
50
+
51
+ def setup_graph_measurements
52
+ super
53
+
54
+ @radius = @graph_height / 2.0
55
+ @circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 2.5), 5.0)
56
+ @stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 4.0), 5.0)
57
+ @center_x = @graph_left + (@graph_width / 2.0)
58
+ @center_y = @graph_top + (@graph_height / 2.0) + 10
59
+ end
60
+
46
61
  def draw_graph
47
62
  store.norm_data.each do |data_row|
48
63
  data_row.points.each_with_index do |data_point, index|
@@ -70,16 +85,6 @@ private
70
85
  end
71
86
  end
72
87
 
73
- def setup_drawing
74
- super
75
-
76
- @radius = @graph_height / 2.0
77
- @circle_radius = @dot_radius || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 2.5), 5.0)
78
- @stroke_width = @line_width || clip_value_if_greater_than(@columns / (store.norm_data.first.points.size * 4), 5.0)
79
- @center_x = @graph_left + (@graph_width / 2.0)
80
- @center_y = @graph_top + (@graph_height / 2.0) + 10
81
- end
82
-
83
88
  # the lines connecting in the center, with the first line vertical
84
89
  def draw_line_markers
85
90
  return if @hide_line_markers
@@ -102,6 +107,6 @@ private
102
107
  x = x_offset + ((radius + LABEL_MARGIN) * Math.sin(deg2rad(angle)))
103
108
  y = y_offset - ((radius + LABEL_MARGIN) * Math.cos(deg2rad(angle)))
104
109
 
105
- draw_label_at(1.0, 1.0, x, y, amount, Magick::CenterGravity)
110
+ draw_label_at(1.0, 1.0, x, y, amount, gravity: Magick::CenterGravity)
106
111
  end
107
112
  end
data/lib/gruff/pie.rb CHANGED
@@ -61,6 +61,11 @@ private
61
61
  @label_formatting = ->(value, percentage) { @show_values_as_labels ? value.to_s : "#{percentage}%" }
62
62
  end
63
63
 
64
+ def setup_drawing
65
+ @center_labels_over_point = false
66
+ super
67
+ end
68
+
64
69
  def draw_graph
65
70
  slices.each do |slice|
66
71
  if slice.value > 0
@@ -136,7 +141,7 @@ private
136
141
  if slice.percentage >= @hide_labels_less_than
137
142
  x, y = label_coordinates_for slice
138
143
  label = @label_formatting.call(slice.value, slice.percentage)
139
- draw_label_at(1.0, 1.0, x, y, label, Magick::CenterGravity)
144
+ draw_label_at(1.0, 1.0, x, y, label, gravity: Magick::CenterGravity)
140
145
  end
141
146
  end
142
147
 
@@ -11,31 +11,42 @@ module Gruff
11
11
  @opacity = opacity
12
12
  end
13
13
 
14
- def render(new_x, new_y, circle_radius)
15
- # @renderer.draw.push # TODO
14
+ def render(new_x, new_y, radius)
15
+ @renderer.draw.push
16
16
  @renderer.draw.stroke_width(@width)
17
17
  @renderer.draw.stroke(@color)
18
18
  @renderer.draw.fill(@color)
19
19
  @renderer.draw.fill_opacity(@opacity)
20
- if @style.to_s == 'square'
21
- square(new_x, new_y, circle_radius)
20
+ case @style.to_sym
21
+ when :square
22
+ square(new_x, new_y, radius)
23
+ when :diamond
24
+ diamond(new_x, new_y, radius)
22
25
  else
23
- circle(new_x, new_y, circle_radius)
26
+ circle(new_x, new_y, radius)
24
27
  end
25
- # @renderer.draw.pop # TODO
28
+ @renderer.draw.pop
26
29
  end
27
30
 
28
- def circle(new_x, new_y, circle_radius)
29
- @renderer.draw.circle(new_x, new_y, new_x - circle_radius, new_y)
31
+ def circle(new_x, new_y, radius)
32
+ @renderer.draw.circle(new_x, new_y, new_x - radius, new_y)
30
33
  end
31
34
 
32
- def square(new_x, new_y, circle_radius)
33
- offset = (circle_radius * 0.8).to_i
34
- corner1 = new_x - offset
35
- corner2 = new_y - offset
36
- corner3 = new_x + offset
37
- corner4 = new_y + offset
35
+ def square(new_x, new_y, radius)
36
+ corner1 = new_x - radius
37
+ corner2 = new_y - radius
38
+ corner3 = new_x + radius
39
+ corner4 = new_y + radius
38
40
  @renderer.draw.rectangle(corner1, corner2, corner3, corner4)
39
41
  end
42
+
43
+ def diamond(new_x, new_y, radius)
44
+ polygon = []
45
+ polygon += [new_x - radius, new_y]
46
+ polygon += [new_x, new_y + radius]
47
+ polygon += [new_x + radius, new_y]
48
+ polygon += [new_x, new_y - radius]
49
+ @renderer.draw.polygon(*polygon)
50
+ end
40
51
  end
41
52
  end
@@ -23,10 +23,6 @@ module Gruff
23
23
  end
24
24
  end
25
25
 
26
- def background_image=(image)
27
- @image = image
28
- end
29
-
30
26
  def background(columns, rows, scale, theme_options)
31
27
  case theme_options[:background_colors]
32
28
  when Array
@@ -25,6 +25,7 @@ module Gruff
25
25
  end
26
26
 
27
27
  def render(width, height, x, y, gravity = Magick::NorthGravity)
28
+ @renderer.draw.push
28
29
  @renderer.draw.rotation = @rotation if @rotation
29
30
  @renderer.draw.fill = @font.color
30
31
  @renderer.draw.stroke = 'transparent'
@@ -37,9 +38,11 @@ module Gruff
37
38
  x, y,
38
39
  @text, @renderer.scale)
39
40
  @renderer.draw.rotation = -@rotation if @rotation
41
+ @renderer.draw.pop
40
42
  end
41
43
 
42
44
  def metrics
45
+ @renderer.draw.push
43
46
  @renderer.draw.font = @font.file_path
44
47
  @renderer.draw.font_weight = @font.weight
45
48
  @renderer.draw.pointsize = @font.size
@@ -50,7 +53,10 @@ module Gruff
50
53
  # So, in here, it just escape % in order to avoid SEGV.
51
54
  text = @text.to_s.gsub(/(%+)/) { ('%' * Regexp.last_match(1).size * 2).to_s }
52
55
 
53
- @renderer.draw.get_type_metrics(@renderer.image, text)
56
+ metrics = @renderer.draw.get_type_metrics(@renderer.image, text)
57
+ @renderer.draw.pop
58
+
59
+ metrics
54
60
  end
55
61
  end
56
62
  end
data/lib/gruff/scatter.rb CHANGED
@@ -114,20 +114,9 @@ private
114
114
  @x_label_margin = nil
115
115
  end
116
116
 
117
- def draw_graph
118
- store.norm_data.each do |data_row|
119
- data_row.coordinates.each do |x_value, y_value|
120
- next if y_value.nil? || x_value.nil?
121
-
122
- new_x = get_x_coord(x_value, @graph_width, @graph_left)
123
- new_y = @graph_top + (@graph_height - (y_value * @graph_height))
124
-
125
- # Reset each time to avoid thin-line errors
126
- stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
127
- circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
128
- Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
129
- end
130
- end
117
+ def setup_drawing
118
+ @center_labels_over_point = false
119
+ super
131
120
  end
132
121
 
133
122
  def setup_data
@@ -147,6 +136,22 @@ private
147
136
  super
148
137
  end
149
138
 
139
+ def draw_graph
140
+ store.norm_data.each do |data_row|
141
+ data_row.coordinates.each do |x_value, y_value|
142
+ next if y_value.nil? || x_value.nil?
143
+
144
+ new_x = get_x_coord(x_value, @graph_width, @graph_left)
145
+ new_y = @graph_top + (@graph_height - (y_value * @graph_height))
146
+
147
+ # Reset each time to avoid thin-line errors
148
+ stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
149
+ circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
150
+ Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
151
+ end
152
+ end
153
+ end
154
+
150
155
  def calculate_spread
151
156
  super
152
157
  @x_spread = @maximum_x_value.to_f - @minimum_x_value.to_f
@@ -170,10 +175,7 @@ private
170
175
  (0..marker_x_count).each do |index|
171
176
  # TODO: Fix the vertical lines, and enable them by default. Not pretty when they don't match up with top y-axis line
172
177
  if @show_vertical_markers
173
- x = @graph_left + @graph_width - (index * increment_x_scaled)
174
-
175
- Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_top, x, @graph_bottom)
176
- Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x, @graph_top + 1, x, @graph_bottom + 1) if @marker_shadow_color
178
+ draw_marker_vertical_line(@graph_left + @graph_width - (index * increment_x_scaled))
177
179
  end
178
180
 
179
181
  unless @hide_line_numbers
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'helper/bar_mixin'
4
+
3
5
  # Graph with individual horizontal bars instead of vertical bars.
4
6
  #
5
7
  # Here's how to set up a Gruff::SideBar.
@@ -19,6 +21,8 @@
19
21
  # g.write('sidebar.png')
20
22
  #
21
23
  class Gruff::SideBar < Gruff::Base
24
+ include BarMixin
25
+
22
26
  # Spacing factor applied between bars.
23
27
  attr_writer :bar_spacing
24
28
 
@@ -79,8 +83,6 @@ private
79
83
  return if @hide_line_markers
80
84
 
81
85
  if @show_labels_for_bar_values
82
- proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
83
-
84
86
  if maximum_value >= 0
85
87
  _, metrics = Gruff::BarValueLabel.metrics(maximum_value, @label_formatting, proc_text_metrics)
86
88
  @graph_right -= metrics.width
@@ -109,32 +111,33 @@ private
109
111
  minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
110
112
  )
111
113
 
112
- proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
114
+ group_spacing = @group_spacing * @scale
115
+ group_left_y = @graph_top
113
116
 
114
- store.norm_data.each_with_index do |data_row, row_index|
115
- data_row.points.each_with_index do |data_point, point_index|
116
- group_spacing = @group_spacing * @scale * point_index
117
-
118
- left_y = @graph_top + (bars_width * point_index) + (bar_width * row_index) + padding + group_spacing
117
+ normalized_group_bars.each_with_index do |group_bars, group_index|
118
+ right_y = 0
119
+ group_bars.each_with_index do |bar, index|
120
+ left_y = group_left_y + (bar_width * index) + padding
119
121
  right_y = left_y + (bar_width * @bar_spacing)
120
122
 
121
- left_x, right_x = conversion.get_top_bottom_scaled(data_point).sort
122
-
123
- rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
124
- rect_renderer.render(left_x + AXIS_MARGIN, left_y, right_x + AXIS_MARGIN, right_y)
125
-
126
- # Calculate center based on bar_width and current row
127
- label_center = left_y + (bars_width / 2.0)
123
+ bottom_x, top_x = conversion.get_top_bottom_scaled(bar.point).sort
124
+ if bar.point != 0
125
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: bar.color)
126
+ rect_renderer.render(bottom_x + AXIS_MARGIN, left_y, top_x, right_y)
127
+ end
128
128
 
129
- # Subtract half a bar width to center left if requested
130
- draw_label(label_center, point_index)
131
- if @show_labels_for_bar_values
132
- bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
129
+ if @show_labels_for_bar_values && bar.value
130
+ bar_value_label = Gruff::BarValueLabel::SideBar.new([bottom_x, left_y, top_x, right_y], bar.value)
133
131
  bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
134
132
  draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
135
133
  end
136
134
  end
137
135
  end
136
+
137
+ label_center = group_left_y + (bars_width / 2.0)
138
+ draw_label(label_center, group_index)
139
+
140
+ group_left_y = right_y + padding + group_spacing
138
141
  end
139
142
  end
140
143
 
@@ -151,9 +154,7 @@ private
151
154
  (0..number_of_lines).each do |index|
152
155
  line_diff = (@graph_right - @graph_left) / number_of_lines
153
156
  x = @graph_right - (line_diff * index) - 1
154
-
155
- Gruff::Renderer::Line.new(renderer, color: @marker_color).render(x, @graph_bottom, x, @graph_top)
156
- Gruff::Renderer::Line.new(renderer, color: @marker_shadow_color).render(x, @graph_bottom + 1, x, @graph_top + 1) if @marker_shadow_color
157
+ draw_marker_vertical_line(x)
157
158
 
158
159
  unless @hide_line_numbers
159
160
  diff = index - number_of_lines
@@ -170,11 +171,15 @@ private
170
171
 
171
172
  def draw_label(y_offset, index)
172
173
  draw_unique_label(index) do
173
- draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], Magick::EastGravity)
174
+ draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], gravity: Magick::EastGravity)
174
175
  end
175
176
  end
176
177
 
177
178
  def calculate_spacing
178
179
  @scale * @group_spacing * (column_count - 1)
179
180
  end
181
+
182
+ def proc_text_metrics
183
+ ->(text) { text_metrics(@marker_font, text) }
184
+ end
180
185
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'helper/stacked_mixin'
4
+
3
5
  #
4
6
  # New gruff graph type added to enable sideways stacking bar charts
5
7
  # (basically looks like a x/y flip of a standard stacking bar chart)
@@ -66,50 +68,43 @@ private
66
68
  #
67
69
  # Columns sit stacked.
68
70
  bar_width = @graph_height / column_count
69
- height = Array.new(column_count, 0)
70
- length = Array.new(column_count, @graph_left)
71
71
  padding = (bar_width * (1 - @bar_spacing)) / 2
72
- stack_bar_value_labels = Gruff::BarValueLabel::StackedBar.new
73
-
74
- store.norm_data.each_with_index do |data_row, row_index|
75
- data_row.points.each_with_index do |data_point, point_index|
76
- ## using the original calculations from the stacked bar chart to get the difference between
77
- ## part of the bart chart we wish to stack.
78
- temp1 = @graph_left + (@graph_width - (data_point * @graph_width) - height[point_index])
79
- temp2 = @graph_left + @graph_width - height[point_index]
80
- difference = temp2 - temp1
81
- difference = 0 if difference < 0
82
-
83
- left_x = length[point_index]
84
- left_y = @graph_top + (bar_width * point_index) + padding
85
- right_x = left_x + difference
86
- right_x -= @segment_spacing if row_index != store.columns - 1
87
- right_y = left_y + (bar_width * @bar_spacing)
88
- length[point_index] += difference
89
- height[point_index] += (data_point * @graph_width)
90
-
91
- bar_value_label = Gruff::BarValueLabel::SideBar.new([left_x, left_y, right_x, right_y], store.data[row_index].points[point_index])
92
- stack_bar_value_labels.add(bar_value_label, point_index)
93
-
94
- # if a data point is 0 it can result in weird really thing lines
95
- # that shouldn't even be there being drawn on top of the existing
96
- # bar - this is bad
97
- if data_point != 0
98
- rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: data_row.color)
99
- rect_renderer.render(left_x, left_y, right_x, right_y)
100
- # Calculate center based on bar_width and current row
101
- end
102
- # we still need to draw the labels
103
- # Calculate center based on bar_width and current row
104
- label_center = left_y + (bar_width / 2.0)
105
- draw_label(label_center, point_index)
72
+
73
+ # Setup the BarConversion Object
74
+ conversion = Gruff::BarConversion.new(
75
+ top: @graph_right, bottom: @graph_left,
76
+ minimum_value: minimum_value, maximum_value: maximum_value, spread: @spread
77
+ )
78
+
79
+ proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
80
+
81
+ normalized_stacked_bars.each_with_index do |stacked_bars, stacked_index|
82
+ total = 0
83
+ left_y = @graph_top + (bar_width * stacked_index) + padding
84
+ right_y = left_y + (bar_width * @bar_spacing)
85
+
86
+ top_x = 0
87
+ stacked_bars.each do |bar|
88
+ next if bar.point == 0
89
+
90
+ bottom_x, = conversion.get_top_bottom_scaled(total)
91
+ bottom_x += @segment_spacing
92
+ top_x, = conversion.get_top_bottom_scaled(total + bar.point)
93
+
94
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: bar.color)
95
+ rect_renderer.render(bottom_x, left_y, top_x, right_y)
96
+
97
+ total += bar.point
106
98
  end
107
- end
108
99
 
109
- if @show_labels_for_bar_values
110
- proc_text_metrics = ->(text) { text_metrics(@marker_font, text) }
111
- stack_bar_value_labels.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
112
- draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
100
+ label_center = left_y + (bar_width / 2.0)
101
+ draw_label(label_center, stacked_index)
102
+
103
+ if @show_labels_for_bar_values
104
+ bar_value_label = Gruff::BarValueLabel::SideBar.new([@graph_left, left_y, top_x, right_y], stacked_bars.sum(&:value))
105
+ bar_value_label.prepare_rendering(@label_formatting, proc_text_metrics) do |x, y, text, text_width, _text_height|
106
+ draw_value_label(text_width, bar_width * @bar_spacing, x, y, text)
107
+ end
113
108
  end
114
109
  end
115
110
  end
data/lib/gruff/spider.rb CHANGED
@@ -46,6 +46,11 @@ private
46
46
  @hide_line_markers.freeze
47
47
  end
48
48
 
49
+ def setup_drawing
50
+ @center_labels_over_point = false
51
+ super
52
+ end
53
+
49
54
  def setup_graph_measurements
50
55
  super
51
56
 
@@ -82,7 +87,7 @@ private
82
87
  end
83
88
 
84
89
  def normalize_points(value)
85
- value * @unit_length
90
+ value.to_f * @unit_length
86
91
  end
87
92
 
88
93
  def draw_label(center_x, center_y, angle, radius, amount)
@@ -107,7 +112,7 @@ private
107
112
  x = x_offset + ((radius + r_offset) * Math.cos(angle))
108
113
  y = y_offset + ((radius + r_offset) * Math.sin(angle))
109
114
 
110
- draw_label_at(metrics.width, metrics.height, x, y, amount, Magick::CenterGravity)
115
+ draw_label_at(metrics.width, metrics.height, x, y, amount, gravity: Magick::CenterGravity)
111
116
  end
112
117
 
113
118
  def draw_axes(center_x, center_y, radius, additive_angle, line_color = nil)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'helper/stacked_mixin'
4
+
3
5
  #
4
6
  # Here's how to set up a Gruff::StackedArea.
5
7
  #
@@ -35,9 +37,10 @@ private
35
37
 
36
38
  height = Array.new(column_count, 0)
37
39
 
38
- data_points = nil
40
+ prev_data_points = nil
39
41
  store.norm_data.each do |data_row|
40
- prev_data_points = data_points
42
+ next if data_row.points.empty?
43
+
41
44
  data_points = []
42
45
 
43
46
  data_row.points.each_with_index do |data_point, index|
@@ -69,6 +72,8 @@ private
69
72
  poly_points << data_points[1]
70
73
 
71
74
  Gruff::Renderer::Polygon.new(renderer, color: data_row.color).render(poly_points)
75
+
76
+ prev_data_points = data_points
72
77
  end
73
78
  end
74
79
  end