gruff 0.13.0-java → 0.14.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +66 -0
  3. data/.rubocop.yml +6 -10
  4. data/.rubocop_todo.yml +19 -85
  5. data/CHANGELOG.md +10 -0
  6. data/README.md +6 -7
  7. data/gruff.gemspec +2 -4
  8. data/lib/gruff.rb +1 -0
  9. data/lib/gruff/accumulator_bar.rb +3 -1
  10. data/lib/gruff/area.rb +5 -8
  11. data/lib/gruff/bar.rb +19 -23
  12. data/lib/gruff/base.rb +134 -96
  13. data/lib/gruff/bezier.rb +4 -6
  14. data/lib/gruff/bullet.rb +11 -10
  15. data/lib/gruff/dot.rb +10 -10
  16. data/lib/gruff/font.rb +39 -0
  17. data/lib/gruff/helper/stacked_mixin.rb +1 -2
  18. data/lib/gruff/histogram.rb +9 -7
  19. data/lib/gruff/line.rb +55 -46
  20. data/lib/gruff/mini/bar.rb +9 -6
  21. data/lib/gruff/mini/legend.rb +12 -8
  22. data/lib/gruff/mini/pie.rb +9 -6
  23. data/lib/gruff/mini/side_bar.rb +9 -6
  24. data/lib/gruff/net.rb +9 -15
  25. data/lib/gruff/patch/string.rb +1 -1
  26. data/lib/gruff/pie.rb +23 -65
  27. data/lib/gruff/renderer/bezier.rb +8 -9
  28. data/lib/gruff/renderer/circle.rb +8 -9
  29. data/lib/gruff/renderer/dash_line.rb +9 -10
  30. data/lib/gruff/renderer/dot.rb +13 -14
  31. data/lib/gruff/renderer/ellipse.rb +8 -9
  32. data/lib/gruff/renderer/line.rb +8 -9
  33. data/lib/gruff/renderer/polygon.rb +9 -10
  34. data/lib/gruff/renderer/polyline.rb +8 -9
  35. data/lib/gruff/renderer/rectangle.rb +7 -8
  36. data/lib/gruff/renderer/renderer.rb +21 -36
  37. data/lib/gruff/renderer/text.rb +21 -37
  38. data/lib/gruff/scatter.rb +41 -46
  39. data/lib/gruff/scene.rb +15 -13
  40. data/lib/gruff/side_bar.rb +14 -30
  41. data/lib/gruff/side_stacked_bar.rb +8 -11
  42. data/lib/gruff/spider.rb +11 -16
  43. data/lib/gruff/stacked_area.rb +10 -11
  44. data/lib/gruff/stacked_bar.rb +9 -9
  45. data/lib/gruff/store/store.rb +6 -10
  46. data/lib/gruff/themes.rb +6 -6
  47. data/lib/gruff/version.rb +1 -1
  48. data/rails_generators/gruff/templates/controller.rb +1 -1
  49. metadata +4 -21
  50. data/.travis.yml +0 -23
  51. data/assets/plastik/blue.png +0 -0
  52. data/assets/plastik/green.png +0 -0
  53. data/assets/plastik/red.png +0 -0
  54. data/lib/gruff/photo_bar.rb +0 -93
@@ -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 = Renderer.instance.draw
13
-
14
- draw.push
15
- draw.stroke_width(@width)
16
- draw.stroke(@color)
17
- draw.fill('transparent')
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
@@ -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 = Renderer.instance.draw
34
-
35
- draw.push
36
- draw.stroke(color)
37
- draw.fill(color)
38
- draw.stroke_width(@width) if @width
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 = Renderer.instance.draw
14
-
15
- draw.push
16
- draw.stroke_width(@width)
17
- draw.stroke(@color)
18
- draw.fill(@color)
19
- draw.fill_opacity(@opacity)
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 = Renderer.instance.draw
13
-
14
- draw.push
15
- draw.stroke(@color)
16
- draw.fill('transparent')
17
- draw.stroke_width(@width)
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 = Renderer.instance.draw
12
-
13
- draw.push
14
- draw.stroke('transparent')
15
- draw.fill(@color) if @color
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
- include Singleton
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
- Renderer.instance.draw = draw
21
- Renderer.instance.scale = scale
22
- Renderer.instance.image = image
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
- def self.background_image=(image)
32
- Renderer.instance.image = image
13
+ @scale = scale
14
+ @draw.scale(scale, scale)
15
+ @image = background(columns, rows, scale, theme_options)
33
16
  end
34
17
 
35
- def self.font=(font)
36
- draw = Renderer.instance.draw
37
- draw.font = font if font
38
- end
18
+ def finish
19
+ @draw.draw(@image)
39
20
 
40
- def self.finish
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,6 +38,10 @@ 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
47
  Magick::Image.new(columns, rows) do
@@ -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)
@@ -5,12 +5,10 @@ module Gruff
5
5
  class Renderer::Text
6
6
  using Magick::GruffAnnotate
7
7
 
8
- def initialize(text, font:, size:, color:, weight: Magick::NormalWeight, rotation: nil)
8
+ def initialize(renderer, text, font:, rotation: nil)
9
+ @renderer = renderer
9
10
  @text = text.to_s
10
11
  @font = font
11
- @font_size = size
12
- @font_color = color
13
- @font_weight = weight
14
12
  @rotation = rotation
15
13
  end
16
14
 
@@ -23,50 +21,36 @@ module Gruff
23
21
  @y = y
24
22
  @gravity = gravity
25
23
 
26
- Renderer.instance.text_renderers << self
24
+ @renderer.text_renderers << self
27
25
  end
28
26
 
29
27
  def render(width, height, x, y, gravity = Magick::NorthGravity)
30
- draw = Renderer.instance.draw
31
- image = Renderer.instance.image
32
- scale = Renderer.instance.scale
33
-
34
- draw.rotation = @rotation if @rotation
35
- draw.fill = @font_color
36
- draw.stroke = 'transparent'
37
- draw.font = @font || Renderer::Text.default_font(@font_weight)
38
- draw.font_weight = @font_weight
39
- draw.pointsize = @font_size * scale
40
- draw.gravity = gravity
41
- draw.annotate_scaled(image,
42
- width, height,
43
- x, y,
44
- @text, scale)
45
- draw.rotation = -@rotation if @rotation
28
+ @renderer.draw.rotation = @rotation if @rotation
29
+ @renderer.draw.fill = @font.color
30
+ @renderer.draw.stroke = 'transparent'
31
+ @renderer.draw.font = @font.file_path
32
+ @renderer.draw.font_weight = @font.weight
33
+ @renderer.draw.pointsize = @font.size * @renderer.scale
34
+ @renderer.draw.gravity = gravity
35
+ @renderer.draw.annotate_scaled(@renderer.image,
36
+ width, height,
37
+ x, y,
38
+ @text, @renderer.scale)
39
+ @renderer.draw.rotation = -@rotation if @rotation
46
40
  end
47
41
 
48
- def self.metrics(text, font, size, font_weight = Magick::NormalWeight)
49
- draw = Renderer.instance.draw
50
- image = Renderer.instance.image
51
-
52
- draw.font = font || Renderer::Text.default_font(font_weight)
53
- draw.font_weight = font_weight
54
- draw.pointsize = size
42
+ def metrics
43
+ @renderer.draw.font = @font.file_path
44
+ @renderer.draw.font_weight = @font.weight
45
+ @renderer.draw.pointsize = @font.size
55
46
 
56
47
  # The old ImageMagick causes SEGV with string which has '%' + alphabet (eg. '%S').
57
48
  # This format is used to embed value into a string using image properties.
58
49
  # However, gruff use plain image as canvas which does not have any property.
59
50
  # So, in here, it just escape % in order to avoid SEGV.
60
- text = text.to_s.gsub(/(%+)/) { ('%' * Regexp.last_match(1).size * 2).to_s }
61
-
62
- draw.get_type_metrics(image, text)
63
- end
64
-
65
- FONT_BOLD = File.expand_path(File.join(__FILE__, '../../../../assets/fonts/Roboto-Bold.ttf'))
66
- FONT_REGULAR = File.expand_path(File.join(__FILE__, '../../../../assets/fonts/Roboto-Regular.ttf'))
51
+ text = @text.to_s.gsub(/(%+)/) { ('%' * Regexp.last_match(1).size * 2).to_s }
67
52
 
68
- def self.default_font(font_weight)
69
- (font_weight == Magick::BoldWeight) ? FONT_BOLD : FONT_REGULAR
53
+ @renderer.draw.get_type_metrics(@renderer.image, text)
70
54
  end
71
55
  end
72
56
  end
data/lib/gruff/scatter.rb CHANGED
@@ -35,27 +35,6 @@ class Gruff::Scatter < Gruff::Base
35
35
  attr_writer :x_label_margin
36
36
  attr_writer :use_vertical_x_labels
37
37
 
38
- def initialize_store
39
- @store = Gruff::Store.new(Gruff::Store::XYData)
40
- end
41
- private :initialize_store
42
-
43
- def initialize_ivars
44
- super
45
-
46
- @baseline_x_color = @baseline_y_color = 'red'
47
- @baseline_x_value = @baseline_y_value = nil
48
- @circle_radius = nil
49
- @disable_significant_rounding_x_axis = false
50
- @show_vertical_markers = false
51
- @marker_x_count = nil
52
- @maximum_x_value = @minimum_x_value = nil
53
- @stroke_width = nil
54
- @use_vertical_x_labels = false
55
- @x_label_margin = nil
56
- end
57
- private :initialize_ivars
58
-
59
38
  # Allow enabling vertical lines. When you have a lot of data, they can work great.
60
39
  # @deprecated Please use +show_vertical_markers+ attribute instead.
61
40
  def enable_vertical_line_markers=(value)
@@ -63,28 +42,6 @@ class Gruff::Scatter < Gruff::Base
63
42
  @show_vertical_markers = value
64
43
  end
65
44
 
66
- def draw
67
- super
68
- return unless data_given?
69
-
70
- # Check to see if more than one datapoint was given. NaN can result otherwise.
71
- @x_increment = (@x_spread > 1) ? (@graph_width / (@x_spread - 1).to_f) : @graph_width
72
-
73
- store.norm_data.each do |data_row|
74
- data_row.coordinates.each do |x_value, y_value|
75
- next if y_value.nil? || x_value.nil?
76
-
77
- new_x = get_x_coord(x_value, @graph_width, @graph_left)
78
- new_y = @graph_top + (@graph_height - y_value * @graph_height)
79
-
80
- # Reset each time to avoid thin-line errors
81
- stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
82
- circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
83
- Gruff::Renderer::Circle.new(color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
84
- end
85
- end
86
- end
87
-
88
45
  # The first parameter is the name of the dataset. The next two are the
89
46
  # x and y axis data points contain in their own array in that respective
90
47
  # order. The final parameter is the color.
@@ -138,6 +95,44 @@ class Gruff::Scatter < Gruff::Base
138
95
 
139
96
  private
140
97
 
98
+ def initialize_store
99
+ @store = Gruff::Store.new(Gruff::Store::XYData)
100
+ end
101
+
102
+ def initialize_attributes
103
+ super
104
+
105
+ @baseline_x_color = @baseline_y_color = 'red'
106
+ @baseline_x_value = @baseline_y_value = nil
107
+ @circle_radius = nil
108
+ @disable_significant_rounding_x_axis = false
109
+ @show_vertical_markers = false
110
+ @marker_x_count = nil
111
+ @maximum_x_value = @minimum_x_value = nil
112
+ @stroke_width = nil
113
+ @use_vertical_x_labels = false
114
+ @x_label_margin = nil
115
+ end
116
+
117
+ def draw_graph
118
+ # Check to see if more than one datapoint was given. NaN can result otherwise.
119
+ @x_increment = (@x_spread > 1) ? (@graph_width / (@x_spread - 1).to_f) : @graph_width
120
+
121
+ store.norm_data.each do |data_row|
122
+ data_row.coordinates.each do |x_value, y_value|
123
+ next if y_value.nil? || x_value.nil?
124
+
125
+ new_x = get_x_coord(x_value, @graph_width, @graph_left)
126
+ new_y = @graph_top + (@graph_height - y_value * @graph_height)
127
+
128
+ # Reset each time to avoid thin-line errors
129
+ stroke_width = @stroke_width || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
130
+ circle_radius = @circle_radius || clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 2.5), 5.0)
131
+ Gruff::Renderer::Circle.new(renderer, color: data_row.color, width: stroke_width).render(new_x, new_y, new_x - circle_radius, new_y)
132
+ end
133
+ end
134
+ end
135
+
141
136
  def setup_data
142
137
  # Update the global min/max values for the x data
143
138
  @maximum_x_value ||= store.max_x
@@ -187,7 +182,7 @@ private
187
182
  end
188
183
  else
189
184
  # TODO: Make this work for negative values
190
- @maximum_x_value = [maximum_value.ceil, @x_axis_increment].max
185
+ @maximum_x_value = [@maximum_x_value.ceil, @x_axis_increment].max
191
186
  @minimum_x_value = @minimum_x_value.floor
192
187
  calculate_spread
193
188
  normalize
@@ -203,7 +198,7 @@ private
203
198
  if @show_vertical_markers
204
199
  x = @graph_left + @graph_width - index.to_f * increment_x_scaled
205
200
 
206
- line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
201
+ line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
207
202
  line_renderer.render(x, @graph_top, x, @graph_bottom)
208
203
  end
209
204
 
@@ -214,7 +209,7 @@ private
214
209
 
215
210
  label = x_axis_label(marker_label, @x_increment)
216
211
  rotation = -90.0 if @use_vertical_x_labels
217
- text_renderer = Gruff::Renderer::Text.new(label, font: @font, size: @marker_font_size, color: @font_color, rotation: rotation)
212
+ text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font, rotation: rotation)
218
213
  text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
219
214
  end
220
215
  end