gruff 0.12.2 → 0.13.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/.gitignore +1 -0
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +9 -17
- data/CHANGELOG.md +12 -0
- data/README.md +10 -1
- 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 +3 -2
- data/lib/gruff.rb +1 -1
- data/lib/gruff/bar.rb +14 -27
- data/lib/gruff/base.rb +67 -21
- data/lib/gruff/dot.rb +3 -4
- data/lib/gruff/helper/bar_conversion.rb +27 -12
- data/lib/gruff/helper/bar_value_label.rb +68 -0
- data/lib/gruff/renderer/text.rb +10 -2
- data/lib/gruff/scatter.rb +14 -29
- data/lib/gruff/side_bar.rb +31 -34
- data/lib/gruff/side_stacked_bar.rb +5 -6
- data/lib/gruff/stacked_bar.rb +5 -6
- data/lib/gruff/version.rb +1 -1
- metadata +24 -7
- data/lib/gruff/helper/bar_value_label_mixin.rb +0 -33
    
        data/lib/gruff/base.rb
    CHANGED
    
    | @@ -156,9 +156,11 @@ module Gruff | |
| 156 156 | 
             
                # Will be scaled down if graph is smaller than 800px wide.
         | 
| 157 157 | 
             
                attr_writer :legend_box_size
         | 
| 158 158 |  | 
| 159 | 
            -
                #  | 
| 160 | 
            -
                 | 
| 161 | 
            -
             | 
| 159 | 
            +
                # Allow passing lambdas to format labels for x axis.
         | 
| 160 | 
            +
                attr_writer :x_axis_label_format
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                # Allow passing lambdas to format labels for y axis.
         | 
| 163 | 
            +
                attr_writer :y_axis_label_format
         | 
| 162 164 |  | 
| 163 165 | 
             
                # If one numerical argument is given, the graph is drawn at 4/3 ratio
         | 
| 164 166 | 
             
                # according to the given width (+800+ results in 800x600, +400+ gives 400x300,
         | 
| @@ -214,8 +216,8 @@ module Gruff | |
| 214 216 | 
             
                  @sort = false
         | 
| 215 217 | 
             
                  @sorted_drawing = false
         | 
| 216 218 | 
             
                  @title = nil
         | 
| 217 | 
            -
                  @title_font = nil
         | 
| 218 219 |  | 
| 220 | 
            +
                  @title_font = nil
         | 
| 219 221 | 
             
                  @font = nil
         | 
| 220 222 | 
             
                  @bold_title = true
         | 
| 221 223 |  | 
| @@ -238,10 +240,12 @@ module Gruff | |
| 238 240 | 
             
                  @label_max_size = 0
         | 
| 239 241 | 
             
                  @label_truncation_style = :absolute
         | 
| 240 242 |  | 
| 241 | 
            -
                  @use_data_label = false
         | 
| 242 243 | 
             
                  @x_axis_increment = nil
         | 
| 243 244 | 
             
                  @x_axis_label = @y_axis_label = nil
         | 
| 244 245 | 
             
                  @y_axis_increment = nil
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                  @x_axis_label_format = nil
         | 
| 248 | 
            +
                  @y_axis_label_format = nil
         | 
| 245 249 | 
             
                end
         | 
| 246 250 | 
             
                protected :initialize_ivars
         | 
| 247 251 |  | 
| @@ -603,7 +607,7 @@ module Gruff | |
| 603 607 |  | 
| 604 608 | 
             
                    unless @hide_line_numbers
         | 
| 605 609 | 
             
                      marker_label = BigDecimal(index.to_s) * BigDecimal(@increment.to_s) + BigDecimal(minimum_value.to_s)
         | 
| 606 | 
            -
                      label =  | 
| 610 | 
            +
                      label = y_axis_label(marker_label, @increment)
         | 
| 607 611 | 
             
                      text_renderer = Gruff::Renderer::Text.new(label, font: @font, size: @marker_font_size, color: @font_color)
         | 
| 608 612 | 
             
                      text_renderer.add_to_render_queue(@graph_left - LABEL_MARGIN, 1.0, 0.0, y, Magick::EastGravity)
         | 
| 609 613 | 
             
                    end
         | 
| @@ -627,7 +631,7 @@ module Gruff | |
| 627 631 | 
             
                  current_x_offset = center(label_widths.first.sum)
         | 
| 628 632 | 
             
                  current_y_offset = begin
         | 
| 629 633 | 
             
                    if @legend_at_bottom
         | 
| 630 | 
            -
                      @ | 
| 634 | 
            +
                      @graph_bottom + @legend_margin + @legend_caps_height + LABEL_MARGIN
         | 
| 631 635 | 
             
                    else
         | 
| 632 636 | 
             
                      hide_title? ? @top_margin + @title_margin : @top_margin + @title_margin + @title_caps_height
         | 
| 633 637 | 
             
                    end
         | 
| @@ -659,8 +663,6 @@ module Gruff | |
| 659 663 | 
             
                      unless label_widths.empty?
         | 
| 660 664 | 
             
                        # Wrap to next line and shrink available graph dimensions
         | 
| 661 665 | 
             
                        current_y_offset += line_height
         | 
| 662 | 
            -
                        @graph_top += line_height
         | 
| 663 | 
            -
                        @graph_height = @graph_bottom - @graph_top
         | 
| 664 666 | 
             
                      end
         | 
| 665 667 | 
             
                    end
         | 
| 666 668 | 
             
                  end
         | 
| @@ -674,7 +676,7 @@ module Gruff | |
| 674 676 | 
             
                  font_weight = @bold_title ? Magick::BoldWeight : Magick::NormalWeight
         | 
| 675 677 | 
             
                  font_size = @title_font_size
         | 
| 676 678 |  | 
| 677 | 
            -
                  metrics = Renderer::Text.metrics(@title, font_size, font_weight)
         | 
| 679 | 
            +
                  metrics = Renderer::Text.metrics(@title, font, font_size, font_weight)
         | 
| 678 680 | 
             
                  if metrics.width > @raw_columns
         | 
| 679 681 | 
             
                    font_size = font_size * (@raw_columns / metrics.width) * 0.95
         | 
| 680 682 | 
             
                  end
         | 
| @@ -694,11 +696,8 @@ module Gruff | |
| 694 696 | 
             
                    # TODO: See if index.odd? is the best stragegy
         | 
| 695 697 | 
             
                    y_offset += @label_stagger_height if index.odd?
         | 
| 696 698 |  | 
| 697 | 
            -
                    label_text = truncate_label_text(@labels[index].to_s)
         | 
| 698 | 
            -
             | 
| 699 699 | 
             
                    if x_offset >= @graph_left && x_offset <= @graph_right
         | 
| 700 | 
            -
                       | 
| 701 | 
            -
                      text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset, gravity)
         | 
| 700 | 
            +
                      draw_label_at(1.0, 1.0, x_offset, y_offset, @labels[index], gravity)
         | 
| 702 701 | 
             
                    end
         | 
| 703 702 | 
             
                  end
         | 
| 704 703 | 
             
                end
         | 
| @@ -713,6 +712,12 @@ module Gruff | |
| 713 712 | 
             
                  end
         | 
| 714 713 | 
             
                end
         | 
| 715 714 |  | 
| 715 | 
            +
                def draw_label_at(width, height, x, y, text, gravity = Magick::NorthGravity)
         | 
| 716 | 
            +
                  label_text = truncate_label_text(text)
         | 
| 717 | 
            +
                  text_renderer = Gruff::Renderer::Text.new(label_text, font: @font, size: @marker_font_size, color: @font_color)
         | 
| 718 | 
            +
                  text_renderer.add_to_render_queue(width, height, x, y, gravity)
         | 
| 719 | 
            +
                end
         | 
| 720 | 
            +
             | 
| 716 721 | 
             
                # Draws the data value over the data point in bar graphs
         | 
| 717 722 | 
             
                def draw_value_label(x_offset, y_offset, data_point, bar_value = false)
         | 
| 718 723 | 
             
                  return if @hide_line_markers && !bar_value
         | 
| @@ -818,10 +823,10 @@ module Gruff | |
| 818 823 | 
             
                    if @has_left_labels
         | 
| 819 824 | 
             
                      @labels.values.reduce('') { |value, memo| (value.to_s.length > memo.to_s.length) ? value : memo }
         | 
| 820 825 | 
             
                    else
         | 
| 821 | 
            -
                       | 
| 826 | 
            +
                      y_axis_label(maximum_value.to_f, @increment)
         | 
| 822 827 | 
             
                    end
         | 
| 823 828 | 
             
                  end
         | 
| 824 | 
            -
                  longest_left_label_width = calculate_width(@marker_font_size, text)
         | 
| 829 | 
            +
                  longest_left_label_width = calculate_width(@marker_font_size, truncate_label_text(text))
         | 
| 825 830 | 
             
                  longest_left_label_width *= 1.25 if @has_left_labels
         | 
| 826 831 |  | 
| 827 832 | 
             
                  # Shift graph if left line numbers are hidden
         | 
| @@ -831,17 +836,16 @@ module Gruff | |
| 831 836 | 
             
                end
         | 
| 832 837 |  | 
| 833 838 | 
             
                def setup_top_margin
         | 
| 834 | 
            -
                  return @top_margin if @legend_at_bottom
         | 
| 835 | 
            -
             | 
| 836 839 | 
             
                  # When @hide title, leave a title_margin space for aesthetics.
         | 
| 837 840 | 
             
                  # Same with @hide_legend
         | 
| 838 841 | 
             
                  @top_margin +
         | 
| 839 842 | 
             
                    (hide_title? ? @title_margin : @title_caps_height + @title_margin) +
         | 
| 840 | 
            -
                    (@hide_legend ? @legend_margin :  | 
| 843 | 
            +
                    ((@hide_legend || @legend_at_bottom) ? @legend_margin : calculate_legend_height + @legend_margin)
         | 
| 841 844 | 
             
                end
         | 
| 842 845 |  | 
| 843 846 | 
             
                def setup_bottom_margin
         | 
| 844 847 | 
             
                  graph_bottom_margin = hide_bottom_label_area? ? @bottom_margin : @bottom_margin + @marker_caps_height + LABEL_MARGIN
         | 
| 848 | 
            +
                  graph_bottom_margin += (calculate_legend_height + @legend_margin) if @legend_at_bottom
         | 
| 845 849 |  | 
| 846 850 | 
             
                  x_axis_label_height = @x_axis_label.nil? ? 0.0 : @marker_caps_height + LABEL_MARGIN
         | 
| 847 851 | 
             
                  # FIXME: Consider chart types other than bar
         | 
| @@ -849,6 +853,7 @@ module Gruff | |
| 849 853 | 
             
                end
         | 
| 850 854 |  | 
| 851 855 | 
             
                def truncate_label_text(text)
         | 
| 856 | 
            +
                  text = text.to_s
         | 
| 852 857 | 
             
                  return text if text.size <= @label_max_size
         | 
| 853 858 |  | 
| 854 859 | 
             
                  if @label_truncation_style == :trailing_dots
         | 
| @@ -892,6 +897,22 @@ module Gruff | |
| 892 897 | 
             
                  parts.join('.')
         | 
| 893 898 | 
             
                end
         | 
| 894 899 |  | 
| 900 | 
            +
                def x_axis_label(value, increment)
         | 
| 901 | 
            +
                  if @x_axis_label_format
         | 
| 902 | 
            +
                    @x_axis_label_format.call(value)
         | 
| 903 | 
            +
                  else
         | 
| 904 | 
            +
                    label(value, increment)
         | 
| 905 | 
            +
                  end
         | 
| 906 | 
            +
                end
         | 
| 907 | 
            +
             | 
| 908 | 
            +
                def y_axis_label(value, increment)
         | 
| 909 | 
            +
                  if @y_axis_label_format
         | 
| 910 | 
            +
                    @y_axis_label_format.call(value)
         | 
| 911 | 
            +
                  else
         | 
| 912 | 
            +
                    label(value, increment)
         | 
| 913 | 
            +
                  end
         | 
| 914 | 
            +
                end
         | 
| 915 | 
            +
             | 
| 895 916 | 
             
                def calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
         | 
| 896 917 | 
             
                  # May fix legend drawing problem at small sizes
         | 
| 897 918 | 
             
                  label_widths = [[]] # Used to calculate line wrap
         | 
| @@ -908,13 +929,38 @@ module Gruff | |
| 908 929 | 
             
                  label_widths
         | 
| 909 930 | 
             
                end
         | 
| 910 931 |  | 
| 932 | 
            +
                def calculate_legend_height
         | 
| 933 | 
            +
                  return 0.0 if @hide_legend
         | 
| 934 | 
            +
             | 
| 935 | 
            +
                  legend_labels = store.data.map(&:label)
         | 
| 936 | 
            +
                  legend_square_width = @legend_box_size
         | 
| 937 | 
            +
                  label_widths = calculate_legend_label_widths_for_each_line(legend_labels, legend_square_width)
         | 
| 938 | 
            +
                  legend_height = 0.0
         | 
| 939 | 
            +
             | 
| 940 | 
            +
                  legend_labels.each_with_index do |legend_label, _index|
         | 
| 941 | 
            +
                    next if legend_label.empty?
         | 
| 942 | 
            +
             | 
| 943 | 
            +
                    label_widths.first.shift
         | 
| 944 | 
            +
                    if label_widths.first.empty?
         | 
| 945 | 
            +
                      label_widths.shift
         | 
| 946 | 
            +
                      line_height = [@legend_caps_height, legend_square_width].max + @legend_margin
         | 
| 947 | 
            +
                      unless label_widths.empty?
         | 
| 948 | 
            +
                        # Wrap to next line and shrink available graph dimensions
         | 
| 949 | 
            +
                        legend_height += line_height
         | 
| 950 | 
            +
                      end
         | 
| 951 | 
            +
                    end
         | 
| 952 | 
            +
                  end
         | 
| 953 | 
            +
             | 
| 954 | 
            +
                  legend_height + @legend_caps_height
         | 
| 955 | 
            +
                end
         | 
| 956 | 
            +
             | 
| 911 957 | 
             
                # Returns the height of the capital letter 'X' for the current font and
         | 
| 912 958 | 
             
                # size.
         | 
| 913 959 | 
             
                #
         | 
| 914 960 | 
             
                # Not scaled since it deals with dimensions that the regular scaling will
         | 
| 915 961 | 
             
                # handle.
         | 
| 916 962 | 
             
                def calculate_caps_height(font_size)
         | 
| 917 | 
            -
                  metrics = Renderer::Text.metrics('X', font_size)
         | 
| 963 | 
            +
                  metrics = Renderer::Text.metrics('X', @font, font_size)
         | 
| 918 964 | 
             
                  metrics.height
         | 
| 919 965 | 
             
                end
         | 
| 920 966 |  | 
| @@ -926,7 +972,7 @@ module Gruff | |
| 926 972 | 
             
                  text = text.to_s
         | 
| 927 973 | 
             
                  return 0 if text.empty?
         | 
| 928 974 |  | 
| 929 | 
            -
                  metrics = Renderer::Text.metrics(text, font_size)
         | 
| 975 | 
            +
                  metrics = Renderer::Text.metrics(text, @font, font_size)
         | 
| 930 976 | 
             
                  metrics.width
         | 
| 931 977 | 
             
                end
         | 
| 932 978 |  | 
    
        data/lib/gruff/dot.rb
    CHANGED
    
    | @@ -51,14 +51,14 @@ protected | |
| 51 51 | 
             
                return if @hide_line_markers
         | 
| 52 52 |  | 
| 53 53 | 
             
                (0..marker_count).each do |index|
         | 
| 54 | 
            -
                  marker_label =  | 
| 54 | 
            +
                  marker_label = BigDecimal(index.to_s) * BigDecimal(@increment.to_s) + BigDecimal(minimum_value.to_s)
         | 
| 55 55 | 
             
                  x = @graph_left + (marker_label - minimum_value) * @graph_width / @spread
         | 
| 56 56 |  | 
| 57 57 | 
             
                  line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
         | 
| 58 58 | 
             
                  line_renderer.render(x, @graph_bottom, x, @graph_bottom + 5)
         | 
| 59 59 |  | 
| 60 60 | 
             
                  unless @hide_line_numbers
         | 
| 61 | 
            -
                    label =  | 
| 61 | 
            +
                    label = y_axis_label(marker_label, @increment)
         | 
| 62 62 | 
             
                    text_renderer = Gruff::Renderer::Text.new(label, font: @font, size: @marker_font_size, color: @font_color)
         | 
| 63 63 | 
             
                    text_renderer.add_to_render_queue(0, 0, x, @graph_bottom + (LABEL_MARGIN * 1.5), Magick::CenterGravity)
         | 
| 64 64 | 
             
                  end
         | 
| @@ -70,8 +70,7 @@ protected | |
| 70 70 |  | 
| 71 71 | 
             
              def draw_label(y_offset, index)
         | 
| 72 72 | 
             
                draw_unique_label(index) do
         | 
| 73 | 
            -
                   | 
| 74 | 
            -
                  text_renderer.add_to_render_queue(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, Magick::EastGravity)
         | 
| 73 | 
            +
                  draw_label_at(@graph_left - LABEL_MARGIN, 1.0, 0.0, y_offset, @labels[index], Magick::EastGravity)
         | 
| 75 74 | 
             
                end
         | 
| 76 75 | 
             
              end
         | 
| 77 76 | 
             
            end
         | 
| @@ -14,29 +14,44 @@ | |
| 14 14 | 
             
            # @private
         | 
| 15 15 | 
             
            class Gruff::BarConversion
         | 
| 16 16 | 
             
              attr_writer :mode
         | 
| 17 | 
            -
              attr_writer :zero
         | 
| 18 | 
            -
              attr_writer :graph_top
         | 
| 19 | 
            -
              attr_writer :graph_height
         | 
| 20 | 
            -
              attr_writer :minimum_value
         | 
| 21 | 
            -
              attr_writer :spread
         | 
| 22 17 |  | 
| 23 | 
            -
              def  | 
| 18 | 
            +
              def initialize(top:, bottom:, minimum_value:, maximum_value:, spread:)
         | 
| 19 | 
            +
                @graph_top = top
         | 
| 20 | 
            +
                @graph_height = bottom - top
         | 
| 21 | 
            +
                @spread = spread
         | 
| 22 | 
            +
                @minimum_value = minimum_value
         | 
| 23 | 
            +
                @maximum_value = maximum_value
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                if minimum_value >= 0
         | 
| 26 | 
            +
                  # all bars go from zero to positive
         | 
| 27 | 
            +
                  @mode = 1
         | 
| 28 | 
            +
                elsif maximum_value <= 0
         | 
| 29 | 
            +
                  # all bars go from 0 to negative
         | 
| 30 | 
            +
                  @mode = 2
         | 
| 31 | 
            +
                else
         | 
| 32 | 
            +
                  # bars either go from zero to negative or to positive
         | 
| 33 | 
            +
                  @mode = 3
         | 
| 34 | 
            +
                  @zero = -minimum_value / @spread
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def get_top_bottom_scaled(data_point)
         | 
| 24 39 | 
             
                result = []
         | 
| 25 40 |  | 
| 26 41 | 
             
                case @mode
         | 
| 27 42 | 
             
                when 1
         | 
| 28 43 | 
             
                  # minimum value >= 0 ( only positive values )
         | 
| 29 | 
            -
                  result[0] = @graph_top + @graph_height * (1 - data_point) | 
| 30 | 
            -
                  result[1] = @graph_top + @graph_height | 
| 44 | 
            +
                  result[0] = @graph_top + @graph_height * (1 - data_point)
         | 
| 45 | 
            +
                  result[1] = @graph_top + @graph_height
         | 
| 31 46 | 
             
                when 2
         | 
| 32 47 | 
             
                  # only negative values
         | 
| 33 | 
            -
                  result[0] = @graph_top | 
| 34 | 
            -
                  result[1] = @graph_top + @graph_height * (1 - data_point) | 
| 48 | 
            +
                  result[0] = @graph_top
         | 
| 49 | 
            +
                  result[1] = @graph_top + @graph_height * (1 - data_point)
         | 
| 35 50 | 
             
                when 3
         | 
| 36 51 | 
             
                  # positive and negative values
         | 
| 37 52 | 
             
                  val = data_point - @minimum_value / @spread
         | 
| 38 | 
            -
                  result[0] = @graph_top + @graph_height * (1 - (val - @zero)) | 
| 39 | 
            -
                  result[1] = @graph_top + @graph_height * (1 - @zero) | 
| 53 | 
            +
                  result[0] = @graph_top + @graph_height * (1 - (val - @zero))
         | 
| 54 | 
            +
                  result[1] = @graph_top + @graph_height * (1 - @zero)
         | 
| 40 55 | 
             
                else
         | 
| 41 56 | 
             
                  result[0] = 0.0
         | 
| 42 57 | 
             
                  result[1] = 0.0
         | 
| @@ -0,0 +1,68 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # @private
         | 
| 4 | 
            +
            module Gruff::BarValueLabel
         | 
| 5 | 
            +
              using String::GruffCommify
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              # @private
         | 
| 8 | 
            +
              class Base
         | 
| 9 | 
            +
                attr_reader :coordinate, :value
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def initialize(coordinate, value)
         | 
| 12 | 
            +
                  @coordinate = coordinate
         | 
| 13 | 
            +
                  @value = value
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              # @private
         | 
| 18 | 
            +
              class Bar < Base
         | 
| 19 | 
            +
                def prepare_rendering(format, _bar_width = 0)
         | 
| 20 | 
            +
                  left_x, left_y, right_x, _right_y = @coordinate
         | 
| 21 | 
            +
                  if format.is_a?(Proc)
         | 
| 22 | 
            +
                    val = format.call(@value)
         | 
| 23 | 
            +
                  else
         | 
| 24 | 
            +
                    val = sprintf(format || '%.2f', @value).commify
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  y = @value >= 0 ? left_y - 30 : left_y + 12
         | 
| 28 | 
            +
                  yield left_x + (right_x - left_x) / 2, y, val
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              # @private
         | 
| 33 | 
            +
              class SideBar < Base
         | 
| 34 | 
            +
                def prepare_rendering(format, bar_width = 0)
         | 
| 35 | 
            +
                  left_x, _left_y, right_x, right_y = @coordinate
         | 
| 36 | 
            +
                  if format.is_a?(Proc)
         | 
| 37 | 
            +
                    val = format.call(@value)
         | 
| 38 | 
            +
                  else
         | 
| 39 | 
            +
                    val = sprintf(format || '%.2f', @value).commify
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  x = @value >= 0 ? right_x + 40 : left_x - 40
         | 
| 43 | 
            +
                  yield x, right_y - bar_width / 2, val
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              # @private
         | 
| 48 | 
            +
              class StackedBar
         | 
| 49 | 
            +
                def initialize
         | 
| 50 | 
            +
                  @bars = []
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def add(bar, index)
         | 
| 54 | 
            +
                  bars = @bars[index] || []
         | 
| 55 | 
            +
                  bars << bar
         | 
| 56 | 
            +
                  @bars[index] = bars
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def prepare_rendering(format, bar_width = 0, &block)
         | 
| 60 | 
            +
                  @bars.each do |bars|
         | 
| 61 | 
            +
                    value = bars.sum(&:value)
         | 
| 62 | 
            +
                    bar = bars.last
         | 
| 63 | 
            +
                    bar_value_label = bar.class.new(bar.coordinate, value)
         | 
| 64 | 
            +
                    bar_value_label.prepare_rendering(format, bar_width, &block)
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
    
        data/lib/gruff/renderer/text.rb
    CHANGED
    
    | @@ -34,7 +34,7 @@ module Gruff | |
| 34 34 | 
             
                  draw.rotation = @rotation if @rotation
         | 
| 35 35 | 
             
                  draw.fill = @font_color
         | 
| 36 36 | 
             
                  draw.stroke = 'transparent'
         | 
| 37 | 
            -
                  draw.font = @font  | 
| 37 | 
            +
                  draw.font = @font || Renderer::Text.default_font(@font_weight)
         | 
| 38 38 | 
             
                  draw.font_weight = @font_weight
         | 
| 39 39 | 
             
                  draw.pointsize = @font_size * scale
         | 
| 40 40 | 
             
                  draw.gravity = gravity
         | 
| @@ -45,10 +45,11 @@ module Gruff | |
| 45 45 | 
             
                  draw.rotation = -@rotation if @rotation
         | 
| 46 46 | 
             
                end
         | 
| 47 47 |  | 
| 48 | 
            -
                def self.metrics(text, size, font_weight = Magick::NormalWeight)
         | 
| 48 | 
            +
                def self.metrics(text, font, size, font_weight = Magick::NormalWeight)
         | 
| 49 49 | 
             
                  draw  = Renderer.instance.draw
         | 
| 50 50 | 
             
                  image = Renderer.instance.image
         | 
| 51 51 |  | 
| 52 | 
            +
                  draw.font = font || Renderer::Text.default_font(font_weight)
         | 
| 52 53 | 
             
                  draw.font_weight = font_weight
         | 
| 53 54 | 
             
                  draw.pointsize = size
         | 
| 54 55 |  | 
| @@ -60,5 +61,12 @@ module Gruff | |
| 60 61 |  | 
| 61 62 | 
             
                  draw.get_type_metrics(image, text)
         | 
| 62 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'))
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                def self.default_font(font_weight)
         | 
| 69 | 
            +
                  (font_weight == Magick::BoldWeight) ? FONT_BOLD : FONT_REGULAR
         | 
| 70 | 
            +
                end
         | 
| 63 71 | 
             
              end
         | 
| 64 72 | 
             
            end
         | 
    
        data/lib/gruff/scatter.rb
    CHANGED
    
    | @@ -28,17 +28,13 @@ class Gruff::Scatter < Gruff::Base | |
| 28 28 | 
             
              # This is useful when working with a small range of high values (for example, a date range of months, while seconds as units).
         | 
| 29 29 | 
             
              attr_writer :disable_significant_rounding_x_axis
         | 
| 30 30 |  | 
| 31 | 
            -
              # Allow  | 
| 32 | 
            -
              attr_writer : | 
| 31 | 
            +
              # Allow for vertical marker lines.
         | 
| 32 | 
            +
              attr_writer :show_vertical_markers
         | 
| 33 33 |  | 
| 34 34 | 
             
              # Allow using vertical labels in the X axis (and setting the label margin).
         | 
| 35 35 | 
             
              attr_writer :x_label_margin
         | 
| 36 36 | 
             
              attr_writer :use_vertical_x_labels
         | 
| 37 37 |  | 
| 38 | 
            -
              # Allow passing lambdas to format labels.
         | 
| 39 | 
            -
              attr_writer :y_axis_label_format
         | 
| 40 | 
            -
              attr_writer :x_axis_label_format
         | 
| 41 | 
            -
             | 
| 42 38 | 
             
              def initialize_store
         | 
| 43 39 | 
             
                @store = Gruff::Store.new(Gruff::Store::XYData)
         | 
| 44 40 | 
             
              end
         | 
| @@ -51,17 +47,22 @@ class Gruff::Scatter < Gruff::Base | |
| 51 47 | 
             
                @baseline_x_value = @baseline_y_value = nil
         | 
| 52 48 | 
             
                @circle_radius = nil
         | 
| 53 49 | 
             
                @disable_significant_rounding_x_axis = false
         | 
| 54 | 
            -
                @ | 
| 50 | 
            +
                @show_vertical_markers = false
         | 
| 55 51 | 
             
                @marker_x_count = nil
         | 
| 56 52 | 
             
                @maximum_x_value = @minimum_x_value = nil
         | 
| 57 53 | 
             
                @stroke_width = nil
         | 
| 58 54 | 
             
                @use_vertical_x_labels = false
         | 
| 59 | 
            -
                @x_axis_label_format = nil
         | 
| 60 55 | 
             
                @x_label_margin = nil
         | 
| 61 | 
            -
                @y_axis_label_format = nil
         | 
| 62 56 | 
             
              end
         | 
| 63 57 | 
             
              private :initialize_ivars
         | 
| 64 58 |  | 
| 59 | 
            +
              # Allow enabling vertical lines. When you have a lot of data, they can work great.
         | 
| 60 | 
            +
              # @deprecated Please use +show_vertical_markers+ attribute instead.
         | 
| 61 | 
            +
              def enable_vertical_line_markers=(value)
         | 
| 62 | 
            +
                warn '#enable_vertical_line_markers= is deprecated. Please use `show_vertical_markers` attribute instead'
         | 
| 63 | 
            +
                @show_vertical_markers = value
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 65 66 | 
             
              def draw
         | 
| 66 67 | 
             
                super
         | 
| 67 68 | 
             
                return unless data_given?
         | 
| @@ -191,7 +192,7 @@ private | |
| 191 192 | 
             
                  calculate_spread
         | 
| 192 193 | 
             
                  normalize
         | 
| 193 194 |  | 
| 194 | 
            -
                   | 
| 195 | 
            +
                  @marker_x_count = (@x_spread / @x_axis_increment).to_i
         | 
| 195 196 | 
             
                  @x_increment = @x_axis_increment
         | 
| 196 197 | 
             
                end
         | 
| 197 198 | 
             
                increment_x_scaled = @graph_width.to_f / (@x_spread / @x_increment)
         | 
| @@ -199,7 +200,7 @@ private | |
| 199 200 | 
             
                # Draw vertical line markers and annotate with numbers
         | 
| 200 201 | 
             
                (0..@marker_x_count).each do |index|
         | 
| 201 202 | 
             
                  # TODO: Fix the vertical lines, and enable them by default. Not pretty when they don't match up with top y-axis line
         | 
| 202 | 
            -
                  if @ | 
| 203 | 
            +
                  if @show_vertical_markers
         | 
| 203 204 | 
             
                    x = @graph_left + @graph_width - index.to_f * increment_x_scaled
         | 
| 204 205 |  | 
| 205 206 | 
             
                    line_renderer = Gruff::Renderer::Line.new(color: @marker_color, shadow_color: @marker_shadow_color)
         | 
| @@ -207,11 +208,11 @@ private | |
| 207 208 | 
             
                  end
         | 
| 208 209 |  | 
| 209 210 | 
             
                  unless @hide_line_numbers
         | 
| 210 | 
            -
                    marker_label = index * @x_increment + @minimum_x_value. | 
| 211 | 
            +
                    marker_label = BigDecimal(index.to_s) * BigDecimal(@x_increment.to_s) + BigDecimal(@minimum_x_value.to_s)
         | 
| 211 212 | 
             
                    y_offset = @graph_bottom + (@x_label_margin || LABEL_MARGIN)
         | 
| 212 213 | 
             
                    x_offset = get_x_coord(index.to_f, increment_x_scaled, @graph_left)
         | 
| 213 214 |  | 
| 214 | 
            -
                    label =  | 
| 215 | 
            +
                    label = x_axis_label(marker_label, @x_increment)
         | 
| 215 216 | 
             
                    rotation = -90.0 if @use_vertical_x_labels
         | 
| 216 217 | 
             
                    text_renderer = Gruff::Renderer::Text.new(label, font: @font, size: @marker_font_size, color: @font_color, rotation: rotation)
         | 
| 217 218 | 
             
                    text_renderer.add_to_render_queue(1.0, 1.0, x_offset, y_offset)
         | 
| @@ -219,22 +220,6 @@ private | |
| 219 220 | 
             
                end
         | 
| 220 221 | 
             
              end
         | 
| 221 222 |  | 
| 222 | 
            -
              def label(value, increment)
         | 
| 223 | 
            -
                if @y_axis_label_format
         | 
| 224 | 
            -
                  @y_axis_label_format.call(value)
         | 
| 225 | 
            -
                else
         | 
| 226 | 
            -
                  super
         | 
| 227 | 
            -
                end
         | 
| 228 | 
            -
              end
         | 
| 229 | 
            -
             | 
| 230 | 
            -
              def vertical_label(value, increment)
         | 
| 231 | 
            -
                if @x_axis_label_format
         | 
| 232 | 
            -
                  @x_axis_label_format.call(value)
         | 
| 233 | 
            -
                else
         | 
| 234 | 
            -
                  label(value, increment)
         | 
| 235 | 
            -
                end
         | 
| 236 | 
            -
              end
         | 
| 237 | 
            -
             | 
| 238 223 | 
             
              def get_x_coord(x_data_point, width, offset) #:nodoc:
         | 
| 239 224 | 
             
                x_data_point * width + offset
         | 
| 240 225 | 
             
              end
         |