gruff 0.12.2 → 0.15.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +66 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +34 -27
  5. data/CHANGELOG.md +29 -0
  6. data/README.md +15 -7
  7. data/assets/fonts/LICENSE.txt +202 -0
  8. data/assets/fonts/Roboto-Bold.ttf +0 -0
  9. data/assets/fonts/Roboto-Regular.ttf +0 -0
  10. data/gruff.gemspec +9 -10
  11. data/lib/gruff/accumulator_bar.rb +3 -1
  12. data/lib/gruff/area.rb +5 -8
  13. data/lib/gruff/bar.rb +32 -49
  14. data/lib/gruff/base.rb +199 -115
  15. data/lib/gruff/bezier.rb +4 -6
  16. data/lib/gruff/bullet.rb +12 -11
  17. data/lib/gruff/dot.rb +13 -14
  18. data/lib/gruff/font.rb +39 -0
  19. data/lib/gruff/helper/bar_conversion.rb +27 -12
  20. data/lib/gruff/helper/bar_value_label.rb +71 -0
  21. data/lib/gruff/helper/stacked_mixin.rb +1 -2
  22. data/lib/gruff/histogram.rb +9 -7
  23. data/lib/gruff/line.rb +57 -50
  24. data/lib/gruff/mini/bar.rb +9 -6
  25. data/lib/gruff/mini/legend.rb +12 -8
  26. data/lib/gruff/mini/pie.rb +9 -6
  27. data/lib/gruff/mini/side_bar.rb +9 -6
  28. data/lib/gruff/net.rb +9 -15
  29. data/lib/gruff/patch/rmagick.rb +0 -1
  30. data/lib/gruff/patch/string.rb +1 -1
  31. data/lib/gruff/pie.rb +23 -65
  32. data/lib/gruff/renderer/bezier.rb +8 -9
  33. data/lib/gruff/renderer/circle.rb +8 -9
  34. data/lib/gruff/renderer/dash_line.rb +9 -10
  35. data/lib/gruff/renderer/dot.rb +13 -14
  36. data/lib/gruff/renderer/ellipse.rb +8 -9
  37. data/lib/gruff/renderer/line.rb +8 -9
  38. data/lib/gruff/renderer/polygon.rb +9 -10
  39. data/lib/gruff/renderer/polyline.rb +8 -9
  40. data/lib/gruff/renderer/rectangle.rb +7 -8
  41. data/lib/gruff/renderer/renderer.rb +25 -40
  42. data/lib/gruff/renderer/text.rb +21 -29
  43. data/lib/gruff/scatter.rb +55 -75
  44. data/lib/gruff/scene.rb +28 -18
  45. data/lib/gruff/side_bar.rb +35 -54
  46. data/lib/gruff/side_stacked_bar.rb +14 -17
  47. data/lib/gruff/spider.rb +11 -20
  48. data/lib/gruff/stacked_area.rb +10 -11
  49. data/lib/gruff/stacked_bar.rb +14 -15
  50. data/lib/gruff/store/store.rb +6 -10
  51. data/lib/gruff/store/xy_data.rb +2 -0
  52. data/lib/gruff/themes.rb +6 -6
  53. data/lib/gruff/version.rb +1 -1
  54. data/lib/gruff.rb +68 -55
  55. data/rails_generators/gruff/templates/controller.rb +1 -1
  56. metadata +34 -20
  57. data/.rubocop_todo.yml +0 -190
  58. data/.travis.yml +0 -23
  59. data/assets/plastik/blue.png +0 -0
  60. data/assets/plastik/green.png +0 -0
  61. data/assets/plastik/red.png +0 -0
  62. data/lib/gruff/helper/bar_value_label_mixin.rb +0 -33
  63. data/lib/gruff/photo_bar.rb +0 -93
data/lib/gruff/base.rb CHANGED
@@ -93,15 +93,6 @@ module Gruff
93
93
  # Set the large title of the graph displayed at the top.
94
94
  attr_writer :title
95
95
 
96
- # Same as {#font=} but for the title.
97
- attr_writer :title_font
98
-
99
- # Specifies whether to draw the title bolded or not. Default is +true+.
100
- attr_writer :bold_title
101
-
102
- # Specifies the text color.
103
- attr_writer :font_color
104
-
105
96
  # Prevent drawing of line markers. Default is +false+.
106
97
  attr_writer :hide_line_markers
107
98
 
@@ -118,21 +109,9 @@ module Gruff
118
109
  # to +"No Data."+.
119
110
  attr_writer :no_data_message
120
111
 
121
- # Set the font size of the large title at the top of the graph. Default is +36+.
122
- attr_writer :title_font_size
123
-
124
- # Optionally set the size of the font. Based on an 800x600px graph.
125
- # Default is +20+.
126
- #
127
- # Will be scaled down if the graph is smaller than 800px wide.
128
- attr_writer :legend_font_size
129
-
130
112
  # Display the legend under the graph. Default is +false+.
131
113
  attr_writer :legend_at_bottom
132
114
 
133
- # The font size of the labels around the graph. Default is +21+.
134
- attr_writer :marker_font_size
135
-
136
115
  # Set the color of the auxiliary lines.
137
116
  attr_writer :marker_color
138
117
 
@@ -156,9 +135,11 @@ module Gruff
156
135
  # Will be scaled down if graph is smaller than 800px wide.
157
136
  attr_writer :legend_box_size
158
137
 
159
- # With Side Bars use the data label for the marker value to the left of the bar.
160
- # Default is +false+.
161
- attr_writer :use_data_label
138
+ # Allow passing lambdas to format labels for x axis.
139
+ attr_writer :x_axis_label_format
140
+
141
+ # Allow passing lambdas to format labels for y axis.
142
+ attr_writer :y_axis_label_format
162
143
 
163
144
  # If one numerical argument is given, the graph is drawn at 4/3 ratio
164
145
  # according to the given width (+800+ results in 800x600, +400+ gives 400x300,
@@ -179,7 +160,7 @@ module Gruff
179
160
  @rows.freeze
180
161
 
181
162
  initialize_graph_scale
182
- initialize_ivars
163
+ initialize_attributes
183
164
  initialize_store
184
165
 
185
166
  self.theme = Themes::KEYNOTE
@@ -207,21 +188,17 @@ module Gruff
207
188
  #
208
189
  # This makes it possible to set defaults in a subclass but still allow
209
190
  # developers to change this values in their program.
210
- def initialize_ivars
191
+ def initialize_attributes
211
192
  @marker_count = nil
212
193
  @maximum_value = @minimum_value = nil
213
194
  @labels = {}
214
195
  @sort = false
215
196
  @sorted_drawing = false
216
197
  @title = nil
217
- @title_font = nil
218
-
219
- @font = nil
220
- @bold_title = true
221
198
 
222
- @marker_font_size = 21.0
223
- @legend_font_size = 20.0
224
- @title_font_size = 36.0
199
+ @title_font = Gruff::Font.new(size: 36.0, bold: true)
200
+ @marker_font = Gruff::Font.new(size: 21.0)
201
+ @legend_font = Gruff::Font.new(size: 20.0)
225
202
 
226
203
  @top_margin = @bottom_margin = @left_margin = @right_margin = DEFAULT_MARGIN
227
204
  @legend_margin = LEGEND_MARGIN
@@ -238,12 +215,14 @@ module Gruff
238
215
  @label_max_size = 0
239
216
  @label_truncation_style = :absolute
240
217
 
241
- @use_data_label = false
242
218
  @x_axis_increment = nil
243
219
  @x_axis_label = @y_axis_label = nil
244
220
  @y_axis_increment = nil
221
+
222
+ @x_axis_label_format = nil
223
+ @y_axis_label_format = nil
245
224
  end
246
- protected :initialize_ivars
225
+ protected :initialize_attributes
247
226
 
248
227
  # Sets the top, bottom, left and right margins to +margin+.
249
228
  #
@@ -258,8 +237,62 @@ module Gruff
258
237
  # @param font_path [String] The path to font.
259
238
  #
260
239
  def font=(font_path)
261
- @font = font_path
262
- Gruff::Renderer.font = @font
240
+ @title_font.path = font_path unless @title_font.path
241
+ @marker_font.path = font_path
242
+ @legend_font.path = font_path
243
+ end
244
+
245
+ # Same as {#font=} but for the title.
246
+ #
247
+ # @param font_path [String] The path to font.
248
+ #
249
+ def title_font=(font_path)
250
+ @title_font.path = font_path
251
+ end
252
+
253
+ # Set the font size of the large title at the top of the graph. Default is +36+.
254
+ #
255
+ # @param value [Numeric] title font size
256
+ #
257
+ def title_font_size=(value)
258
+ @title_font.size = value
259
+ end
260
+
261
+ # The font size of the labels around the graph. Default is +21+.
262
+ #
263
+ # @param value [Numeric] marker font size
264
+ #
265
+ def marker_font_size=(value)
266
+ @marker_font.size = value
267
+ end
268
+
269
+ # Optionally set the size of the font. Based on an 800x600px graph.
270
+ # Default is +20+.
271
+ #
272
+ # Will be scaled down if the graph is smaller than 800px wide.
273
+ #
274
+ # @param value [Numeric] legend font size
275
+ #
276
+ def legend_font_size=(value)
277
+ @legend_font.size = value
278
+ end
279
+
280
+ # Specifies whether to draw the title bolded or not. Default is +true+.
281
+ #
282
+ # @param value [Boolean] specifies whether to draw the title bolded or not.
283
+ #
284
+ def bold_title=(value)
285
+ @title_font.bold = value
286
+ end
287
+
288
+ # Specifies the text color.
289
+ #
290
+ # @param value [String] color
291
+ #
292
+ def font_color=(value)
293
+ @title_font.color = value
294
+ @marker_font.color = value
295
+ @legend_font.color = value
263
296
  end
264
297
 
265
298
  # Add a color to the list of available colors for lines.
@@ -328,12 +361,13 @@ module Gruff
328
361
  }
329
362
  @theme_options = defaults.merge options
330
363
 
364
+ self.marker_color = @theme_options[:marker_color]
365
+ self.font_color = @theme_options[:font_color] || @marker_color
366
+
331
367
  @colors = @theme_options[:colors]
332
- @marker_color = @theme_options[:marker_color]
333
368
  @marker_shadow_color = @theme_options[:marker_shadow_color]
334
- @font_color = @theme_options[:font_color] || @marker_color
335
369
 
336
- Gruff::Renderer.setup(@columns, @rows, @font, @scale, @theme_options)
370
+ @renderer = Gruff::Renderer.new(@columns, @rows, @scale, @theme_options)
337
371
  end
338
372
 
339
373
  # Apply Apple's keynote theme.
@@ -435,8 +469,8 @@ module Gruff
435
469
  def to_image
436
470
  @to_image ||= begin
437
471
  draw
438
- Gruff::Renderer.finish
439
- Gruff::Renderer.instance.image
472
+ renderer.finish
473
+ renderer.image
440
474
  end
441
475
  end
442
476
 
@@ -452,27 +486,29 @@ module Gruff
452
486
  end
453
487
  end
454
488
 
455
- protected
456
-
457
- # Overridden by subclasses to do the actual plotting of the graph.
458
- #
459
- # Subclasses should start by calling super() for this method.
489
+ # Draw a graph.
460
490
  def draw
491
+ setup_data
492
+
461
493
  # Maybe should be done in one of the following functions for more granularity.
462
494
  unless data_given?
463
495
  draw_no_data
464
496
  return
465
497
  end
466
498
 
467
- setup_data
468
499
  setup_drawing
469
500
 
470
501
  draw_legend
471
502
  draw_line_markers
472
503
  draw_axis_labels
473
504
  draw_title
505
+ draw_graph
474
506
  end
475
507
 
508
+ protected
509
+
510
+ attr_reader :renderer
511
+
476
512
  # Perform data manipulation before calculating chart measurements
477
513
  def setup_data # :nodoc:
478
514
  if @y_axis_increment && !@hide_line_markers
@@ -577,13 +613,13 @@ module Gruff
577
613
  x_axis_label_y_coordinate = @graph_bottom + LABEL_MARGIN + @marker_caps_height
578
614
 
579
615
  # TODO: Center between graph area
580
- text_renderer = Gruff::Renderer::Text.new(@x_axis_label, font: @font, size: @marker_font_size, color: @font_color)
616
+ text_renderer = Gruff::Renderer::Text.new(renderer, @x_axis_label, font: @marker_font)
581
617
  text_renderer.add_to_render_queue(@raw_columns, 1.0, 0.0, x_axis_label_y_coordinate)
582
618
  end
583
619
 
584
620
  if @y_axis_label
585
621
  # Y Axis, rotated vertically
586
- text_renderer = Gruff::Renderer::Text.new(@y_axis_label, font: @font, size: @marker_font_size, color: @font_color, rotation: -90)
622
+ text_renderer = Gruff::Renderer::Text.new(renderer, @y_axis_label, font: @marker_font, rotation: -90)
587
623
  text_renderer.add_to_render_queue(1.0, @raw_rows, @left_margin + @marker_caps_height / 2.0, 0.0, Magick::CenterGravity)
588
624
  end
589
625
  end
@@ -598,13 +634,13 @@ module Gruff
598
634
  (0..marker_count).each do |index|
599
635
  y = @graph_top + @graph_height - index.to_f * increment_scaled
600
636
 
601
- line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
637
+ line_renderer = Gruff::Renderer::Line.new(renderer, color: @marker_color, shadow_color: @marker_shadow_color)
602
638
  line_renderer.render(@graph_left, y, @graph_right, y)
603
639
 
604
640
  unless @hide_line_numbers
605
641
  marker_label = BigDecimal(index.to_s) * BigDecimal(@increment.to_s) + BigDecimal(minimum_value.to_s)
606
- label = label(marker_label, @increment)
607
- text_renderer = Gruff::Renderer::Text.new(label, font: @font, size: @marker_font_size, color: @font_color)
642
+ label = y_axis_label(marker_label, @increment)
643
+ text_renderer = Gruff::Renderer::Text.new(renderer, label, font: @marker_font)
608
644
  text_renderer.add_to_render_queue(@graph_left - LABEL_MARGIN, 1.0, 0.0, y, Magick::EastGravity)
609
645
  end
610
646
  end
@@ -627,7 +663,7 @@ module Gruff
627
663
  current_x_offset = center(label_widths.first.sum)
628
664
  current_y_offset = begin
629
665
  if @legend_at_bottom
630
- @graph_height + @title_margin
666
+ @graph_bottom + @legend_margin + @legend_caps_height + LABEL_MARGIN
631
667
  else
632
668
  hide_title? ? @top_margin + @title_margin : @top_margin + @title_margin + @title_caps_height
633
669
  end
@@ -637,17 +673,17 @@ module Gruff
637
673
  next if legend_label.empty?
638
674
 
639
675
  # Draw label
640
- text_renderer = Gruff::Renderer::Text.new(legend_label, font: @font, size: @legend_font_size, color: @font_color)
676
+ text_renderer = Gruff::Renderer::Text.new(renderer, legend_label, font: @legend_font)
641
677
  text_renderer.add_to_render_queue(@raw_columns, 1.0, current_x_offset + (legend_square_width * 1.7), current_y_offset, Magick::WestGravity)
642
678
 
643
679
  # Now draw box with color of this dataset
644
- rect_renderer = Gruff::Renderer::Rectangle.new(color: store.data[index].color)
680
+ rect_renderer = Gruff::Renderer::Rectangle.new(renderer, color: store.data[index].color)
645
681
  rect_renderer.render(current_x_offset,
646
682
  current_y_offset - legend_square_width / 2.0,
647
683
  current_x_offset + legend_square_width,
648
684
  current_y_offset + legend_square_width / 2.0)
649
685
 
650
- width = calculate_width(@legend_font_size, legend_label)
686
+ width = calculate_width(@legend_font, legend_label)
651
687
  current_x_offset += width + (legend_square_width * 2.7)
652
688
  label_widths.first.shift
653
689
 
@@ -659,8 +695,6 @@ module Gruff
659
695
  unless label_widths.empty?
660
696
  # Wrap to next line and shrink available graph dimensions
661
697
  current_y_offset += line_height
662
- @graph_top += line_height
663
- @graph_height = @graph_bottom - @graph_top
664
698
  end
665
699
  end
666
700
  end
@@ -670,15 +704,12 @@ module Gruff
670
704
  def draw_title
671
705
  return if hide_title?
672
706
 
673
- font = @title_font || @font
674
- font_weight = @bold_title ? Magick::BoldWeight : Magick::NormalWeight
675
- font_size = @title_font_size
676
-
677
- metrics = Renderer::Text.metrics(@title, font_size, font_weight)
707
+ metrics = Gruff::Renderer::Text.new(renderer, @title, font: @title_font).metrics
678
708
  if metrics.width > @raw_columns
679
- font_size = font_size * (@raw_columns / metrics.width) * 0.95
709
+ @title_font.size = @title_font.size * (@raw_columns / metrics.width) * 0.95
680
710
  end
681
- text_renderer = Gruff::Renderer::Text.new(@title, font: font, size: font_size, color: @font_color, weight: font_weight)
711
+
712
+ text_renderer = Gruff::Renderer::Text.new(renderer, @title, font: @title_font)
682
713
  text_renderer.add_to_render_queue(@raw_columns, 1.0, 0, @top_margin)
683
714
  end
684
715
 
@@ -691,14 +722,11 @@ module Gruff
691
722
 
692
723
  # TESTME
693
724
  # FIXME: Consider chart types other than bar
694
- # TODO: See if index.odd? is the best stragegy
725
+ # TODO: See if index.odd? is the best strategy
695
726
  y_offset += @label_stagger_height if index.odd?
696
727
 
697
- label_text = truncate_label_text(@labels[index].to_s)
698
-
699
728
  if x_offset >= @graph_left && x_offset <= @graph_right
700
- text_renderer = Gruff::Renderer::Text.new(label_text, font: @font, size: @marker_font_size, color: @font_color)
701
- text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset, gravity)
729
+ draw_label_at(1.0, 1.0, x_offset, y_offset, @labels[index], gravity)
702
730
  end
703
731
  end
704
732
  end
@@ -713,20 +741,33 @@ module Gruff
713
741
  end
714
742
  end
715
743
 
744
+ def draw_label_at(width, height, x, y, text, gravity = Magick::NorthGravity)
745
+ label_text = truncate_label_text(text)
746
+ text_renderer = Gruff::Renderer::Text.new(renderer, label_text, font: @marker_font)
747
+ text_renderer.add_to_render_queue(width, height, x, y, gravity)
748
+ end
749
+
716
750
  # Draws the data value over the data point in bar graphs
717
- def draw_value_label(x_offset, y_offset, data_point, bar_value = false)
718
- return if @hide_line_markers && !bar_value
751
+ def draw_value_label(x_offset, y_offset, data_point)
752
+ return if @hide_line_markers
719
753
 
720
- text_renderer = Gruff::Renderer::Text.new(data_point, font: @font, size: @marker_font_size, color: @font_color)
754
+ text_renderer = Gruff::Renderer::Text.new(renderer, data_point, font: @marker_font)
721
755
  text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
722
756
  end
723
757
 
724
758
  # Shows an error message because you have no data.
725
759
  def draw_no_data
726
- text_renderer = Gruff::Renderer::Text.new(@no_data_message, font: @font, size: 80, color: @font_color)
760
+ font = @title_font.dup
761
+ font.size = 80
762
+ font.bold = false
763
+ text_renderer = Gruff::Renderer::Text.new(renderer, @no_data_message, font: font)
727
764
  text_renderer.render(@raw_columns, @raw_rows, 0, 0, Magick::CenterGravity)
728
765
  end
729
766
 
767
+ def draw_graph
768
+ raise 'Should implement this method at inherited class.'
769
+ end
770
+
730
771
  # Resets everything to defaults (except data).
731
772
  def reset_themes
732
773
  @theme_options = {}
@@ -742,7 +783,7 @@ module Gruff
742
783
  end
743
784
 
744
785
  def clip_value_if_greater_than(value, max_value) # :nodoc:
745
- (value > max_value) ? max_value : value
786
+ value > max_value ? max_value : value
746
787
  end
747
788
 
748
789
  def significant(i) # :nodoc:
@@ -789,15 +830,15 @@ module Gruff
789
830
  private
790
831
 
791
832
  def setup_marker_caps_height
792
- hide_bottom_label_area? ? 0 : calculate_caps_height(@marker_font_size)
833
+ hide_bottom_label_area? ? 0 : calculate_caps_height(@marker_font)
793
834
  end
794
835
 
795
836
  def setup_title_caps_height
796
- hide_title? ? 0 : calculate_caps_height(@title_font_size) * @title.lines.to_a.size
837
+ hide_title? ? 0 : calculate_caps_height(@title_font) * @title.lines.to_a.size
797
838
  end
798
839
 
799
840
  def setup_legend_caps_height
800
- @hide_legend ? 0 : calculate_caps_height(@legend_font_size)
841
+ @hide_legend ? 0 : calculate_caps_height(@legend_font)
801
842
  end
802
843
 
803
844
  def graph_right_margin
@@ -808,7 +849,7 @@ module Gruff
808
849
  # Make space for half the width of the rightmost column label.
809
850
  # Might be greater than the number of columns if between-style bar markers are used.
810
851
  last_label = @labels.keys.max.to_i
811
- (last_label >= (column_count - 1) && @center_labels_over_point) ? calculate_width(@marker_font_size, @labels[last_label]) / 2.0 : 0
852
+ last_label >= (column_count - 1) && @center_labels_over_point ? calculate_width(@marker_font, @labels[last_label]) / 2.0 : 0
812
853
  end
813
854
 
814
855
  def setup_left_margin
@@ -816,12 +857,12 @@ module Gruff
816
857
 
817
858
  text = begin
818
859
  if @has_left_labels
819
- @labels.values.reduce('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }
860
+ @labels.values.reduce('') { |value, memo| value.to_s.length > memo.to_s.length ? value : memo }
820
861
  else
821
- label(maximum_value.to_f, @increment)
862
+ y_axis_label(maximum_value.to_f, @increment)
822
863
  end
823
864
  end
824
- longest_left_label_width = calculate_width(@marker_font_size, text)
865
+ longest_left_label_width = calculate_width(@marker_font, truncate_label_text(text))
825
866
  longest_left_label_width *= 1.25 if @has_left_labels
826
867
 
827
868
  # Shift graph if left line numbers are hidden
@@ -831,17 +872,16 @@ module Gruff
831
872
  end
832
873
 
833
874
  def setup_top_margin
834
- return @top_margin if @legend_at_bottom
835
-
836
875
  # When @hide title, leave a title_margin space for aesthetics.
837
876
  # Same with @hide_legend
838
877
  @top_margin +
839
878
  (hide_title? ? @title_margin : @title_caps_height + @title_margin) +
840
- (@hide_legend ? @legend_margin : @legend_caps_height + @legend_margin)
879
+ (@hide_legend || @legend_at_bottom ? @legend_margin : calculate_legend_height + @legend_margin)
841
880
  end
842
881
 
843
882
  def setup_bottom_margin
844
883
  graph_bottom_margin = hide_bottom_label_area? ? @bottom_margin : @bottom_margin + @marker_caps_height + LABEL_MARGIN
884
+ graph_bottom_margin += (calculate_legend_height + @legend_margin) if @legend_at_bottom
845
885
 
846
886
  x_axis_label_height = @x_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN
847
887
  # FIXME: Consider chart types other than bar
@@ -849,6 +889,7 @@ module Gruff
849
889
  end
850
890
 
851
891
  def truncate_label_text(text)
892
+ text = text.to_s
852
893
  return text if text.size <= @label_max_size
853
894
 
854
895
  if @label_truncation_style == :trailing_dots
@@ -863,40 +904,58 @@ module Gruff
863
904
  # Return a formatted string representing a number value that should be
864
905
  # printed as a label.
865
906
  def label(value, increment)
866
- label = if increment
867
- if increment >= 10 || (increment * 1) == (increment * 1).to_i.to_f
868
- sprintf('%0i', value)
869
- elsif increment >= 1.0 || (increment * 10) == (increment * 10).to_i.to_f
870
- sprintf('%0.1f', value)
871
- elsif increment >= 0.1 || (increment * 100) == (increment * 100).to_i.to_f
872
- sprintf('%0.2f', value)
873
- elsif increment >= 0.01 || (increment * 1000) == (increment * 1000).to_i.to_f
874
- sprintf('%0.3f', value)
875
- elsif increment >= 0.001 || (increment * 10000) == (increment * 10000).to_i.to_f
876
- sprintf('%0.4f', value)
877
- else
878
- value.to_s
879
- end
880
- elsif (@spread.to_f % (marker_count.to_f == 0 ? 1 : marker_count.to_f) == 0) || !@y_axis_increment.nil?
881
- value.to_i.to_s
882
- elsif @spread > 10.0
883
- sprintf('%0i', value)
884
- elsif @spread >= 3.0
885
- sprintf('%0.2f', value)
886
- else
887
- value.to_s
888
- end
907
+ label = begin
908
+ if increment
909
+ if increment >= 10 || (increment * 1) == (increment * 1).to_i.to_f
910
+ sprintf('%0i', value)
911
+ elsif increment >= 1.0 || (increment * 10) == (increment * 10).to_i.to_f
912
+ sprintf('%0.1f', value)
913
+ elsif increment >= 0.1 || (increment * 100) == (increment * 100).to_i.to_f
914
+ sprintf('%0.2f', value)
915
+ elsif increment >= 0.01 || (increment * 1000) == (increment * 1000).to_i.to_f
916
+ sprintf('%0.3f', value)
917
+ elsif increment >= 0.001 || (increment * 10_000) == (increment * 10_000).to_i.to_f
918
+ sprintf('%0.4f', value)
919
+ else
920
+ value.to_s
921
+ end
922
+ elsif (@spread.to_f % (marker_count.to_f == 0 ? 1 : marker_count.to_f) == 0) || !@y_axis_increment.nil?
923
+ value.to_i.to_s
924
+ elsif @spread > 10.0
925
+ sprintf('%0i', value)
926
+ elsif @spread >= 3.0
927
+ sprintf('%0.2f', value)
928
+ else
929
+ value.to_s
930
+ end
931
+ end
889
932
 
890
933
  parts = label.split('.')
891
934
  parts[0] = parts[0].commify
892
935
  parts.join('.')
893
936
  end
894
937
 
938
+ def x_axis_label(value, increment)
939
+ if @x_axis_label_format
940
+ @x_axis_label_format.call(value)
941
+ else
942
+ label(value, increment)
943
+ end
944
+ end
945
+
946
+ def y_axis_label(value, increment)
947
+ if @y_axis_label_format
948
+ @y_axis_label_format.call(value)
949
+ else
950
+ label(value, increment)
951
+ end
952
+ end
953
+
895
954
  def calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
896
955
  # May fix legend drawing problem at small sizes
897
956
  label_widths = [[]] # Used to calculate line wrap
898
957
  legend_labels.each do |label|
899
- width = calculate_width(@legend_font_size, label)
958
+ width = calculate_width(@legend_font, label)
900
959
  label_width = width + legend_square_width * 2.7
901
960
  label_widths.last.push label_width
902
961
 
@@ -908,13 +967,38 @@ module Gruff
908
967
  label_widths
909
968
  end
910
969
 
970
+ def calculate_legend_height
971
+ return 0.0 if @hide_legend
972
+
973
+ legend_labels = store.data.map(&:label)
974
+ legend_square_width = @legend_box_size
975
+ label_widths = calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
976
+ legend_height = 0.0
977
+
978
+ legend_labels.each_with_index do |legend_label, _index|
979
+ next if legend_label.empty?
980
+
981
+ label_widths.first.shift
982
+ if label_widths.first.empty?
983
+ label_widths.shift
984
+ line_height = [@legend_caps_height, legend_square_width].max + @legend_margin
985
+ unless label_widths.empty?
986
+ # Wrap to next line and shrink available graph dimensions
987
+ legend_height += line_height
988
+ end
989
+ end
990
+ end
991
+
992
+ legend_height + @legend_caps_height
993
+ end
994
+
911
995
  # Returns the height of the capital letter 'X' for the current font and
912
996
  # size.
913
997
  #
914
998
  # Not scaled since it deals with dimensions that the regular scaling will
915
999
  # handle.
916
- def calculate_caps_height(font_size)
917
- metrics = Renderer::Text.metrics('X', font_size)
1000
+ def calculate_caps_height(font)
1001
+ metrics = Gruff::Renderer::Text.new(renderer, 'X', font: font).metrics
918
1002
  metrics.height
919
1003
  end
920
1004
 
@@ -922,11 +1006,11 @@ module Gruff
922
1006
  #
923
1007
  # Not scaled since it deals with dimensions that the regular
924
1008
  # scaling will handle.
925
- def calculate_width(font_size, text)
1009
+ def calculate_width(font, text)
926
1010
  text = text.to_s
927
1011
  return 0 if text.empty?
928
1012
 
929
- metrics = Renderer::Text.metrics(text, font_size)
1013
+ metrics = Gruff::Renderer::Text.new(renderer, text, font: font).metrics
930
1014
  metrics.width
931
1015
  end
932
1016
 
@@ -935,7 +1019,7 @@ module Gruff
935
1019
  # Try to use a number of horizontal lines that will come out even.
936
1020
  #
937
1021
  # TODO Do the same for larger numbers...100, 75, 50, 25
938
- @increment = (@spread > 0 && marker_count > 0) ? significant(@spread / marker_count) : 1
1022
+ @increment = @spread > 0 && marker_count > 0 ? significant(@spread / marker_count) : 1
939
1023
  else
940
1024
  # TODO: Make this work for negative values
941
1025
  self.marker_count = (@spread / @y_axis_increment).to_i
data/lib/gruff/bezier.rb CHANGED
@@ -19,11 +19,9 @@
19
19
  # g.write('bezier.png')
20
20
  #
21
21
  class Gruff::Bezier < Gruff::Base
22
- def draw
23
- super
24
-
25
- return unless data_given?
22
+ private
26
23
 
24
+ def draw_graph
27
25
  x_increment = @graph_width / (column_count - 1).to_f
28
26
 
29
27
  store.norm_data.each do |data_row|
@@ -48,9 +46,9 @@ class Gruff::Bezier < Gruff::Base
48
46
  stroke_width = clip_value_if_greater_than(@columns / (store.norm_data.first[1].size * 4), 5.0)
49
47
 
50
48
  if RUBY_PLATFORM == 'java'
51
- Gruff::Renderer::Polyline.new(color: data_row.color, width: stroke_width).render(poly_points)
49
+ Gruff::Renderer::Polyline.new(renderer, color: data_row.color, width: stroke_width).render(poly_points)
52
50
  else
53
- Gruff::Renderer::Bezier.new(color: data_row.color, width: stroke_width).render(poly_points)
51
+ Gruff::Renderer::Bezier.new(renderer, color: data_row.color, width: stroke_width).render(poly_points)
54
52
  end
55
53
  end
56
54
  end