image_paradise 0.1.12

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.

Potentially problematic release.


This version of image_paradise might be problematic. Click here for more details.

Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +38 -0
  3. data/README.md +179 -0
  4. data/USAGE.md +10 -0
  5. data/bin/black_white +10 -0
  6. data/bin/display_text_from_this_image +7 -0
  7. data/bin/image_paradise +7 -0
  8. data/bin/image_paradise_shell +7 -0
  9. data/bin/image_to_ascii +54 -0
  10. data/bin/image_to_pdf +7 -0
  11. data/bin/make_this_image_transparent +7 -0
  12. data/bin/rotate_left +7 -0
  13. data/bin/rotate_right +7 -0
  14. data/doc/README.gen +162 -0
  15. data/doc/TODO_FOR_THE_GTK_GUI.md +1 -0
  16. data/image_paradise.gemspec +50 -0
  17. data/lib/image_paradise.rb +5 -0
  18. data/lib/image_paradise/base/base.rb +91 -0
  19. data/lib/image_paradise/black_white.rb +89 -0
  20. data/lib/image_paradise/confree_generator/class.rb +614 -0
  21. data/lib/image_paradise/confree_generator/constants.rb +61 -0
  22. data/lib/image_paradise/confree_generator/gui/gtk_confree_generator.rb +752 -0
  23. data/lib/image_paradise/confree_generator/gui/insert_button.rb +78 -0
  24. data/lib/image_paradise/confree_generator/reset.rb +61 -0
  25. data/lib/image_paradise/confree_generator/shared/shared.rb +100 -0
  26. data/lib/image_paradise/constants.rb +43 -0
  27. data/lib/image_paradise/constants/image_file_types.rb +21 -0
  28. data/lib/image_paradise/create_animated_gif.rb +47 -0
  29. data/lib/image_paradise/crop/crop.rb +302 -0
  30. data/lib/image_paradise/gm_support.rb +34 -0
  31. data/lib/image_paradise/graphs.rb +36 -0
  32. data/lib/image_paradise/graphs/accumulator_bar.rb +29 -0
  33. data/lib/image_paradise/graphs/area.rb +64 -0
  34. data/lib/image_paradise/graphs/bar.rb +117 -0
  35. data/lib/image_paradise/graphs/bar_conversion.rb +53 -0
  36. data/lib/image_paradise/graphs/base.rb +1392 -0
  37. data/lib/image_paradise/graphs/bezier.rb +45 -0
  38. data/lib/image_paradise/graphs/bullet.rb +115 -0
  39. data/lib/image_paradise/graphs/deprecated.rb +42 -0
  40. data/lib/image_paradise/graphs/dot.rb +129 -0
  41. data/lib/image_paradise/graphs/line.rb +328 -0
  42. data/lib/image_paradise/graphs/mini/bar.rb +42 -0
  43. data/lib/image_paradise/graphs/mini/legend.rb +109 -0
  44. data/lib/image_paradise/graphs/mini/pie.rb +42 -0
  45. data/lib/image_paradise/graphs/mini/side_bar.rb +41 -0
  46. data/lib/image_paradise/graphs/net.rb +133 -0
  47. data/lib/image_paradise/graphs/photo_bar.rb +106 -0
  48. data/lib/image_paradise/graphs/pie.rb +139 -0
  49. data/lib/image_paradise/graphs/scatter.rb +264 -0
  50. data/lib/image_paradise/graphs/scene.rb +216 -0
  51. data/lib/image_paradise/graphs/side_bar.rb +144 -0
  52. data/lib/image_paradise/graphs/side_stacked_bar.rb +116 -0
  53. data/lib/image_paradise/graphs/spider.rb +163 -0
  54. data/lib/image_paradise/graphs/stacked_area.rb +73 -0
  55. data/lib/image_paradise/graphs/stacked_bar.rb +68 -0
  56. data/lib/image_paradise/graphs/stacked_mixin.rb +30 -0
  57. data/lib/image_paradise/graphs/themes.rb +117 -0
  58. data/lib/image_paradise/graphviz/README.md +2 -0
  59. data/lib/image_paradise/graphviz/generate_graphviz_image.rb +274 -0
  60. data/lib/image_paradise/gui/gtk/control_panel.rb +126 -0
  61. data/lib/image_paradise/identify.rb +145 -0
  62. data/lib/image_paradise/image_border.rb +231 -0
  63. data/lib/image_paradise/image_manipulations.rb +320 -0
  64. data/lib/image_paradise/image_paradise.rb +150 -0
  65. data/lib/image_paradise/image_to_ascii/image_to_ascii.rb +187 -0
  66. data/lib/image_paradise/image_to_pdf/image_to_pdf.rb +99 -0
  67. data/lib/image_paradise/label/README.md +2 -0
  68. data/lib/image_paradise/label/simple_label.rb +206 -0
  69. data/lib/image_paradise/optimizer.rb +483 -0
  70. data/lib/image_paradise/project/project.rb +29 -0
  71. data/lib/image_paradise/random_text_to_image.rb +363 -0
  72. data/lib/image_paradise/requires/common_base_requires.rb +17 -0
  73. data/lib/image_paradise/requires/require_colours.rb +9 -0
  74. data/lib/image_paradise/requires/require_gtk_components.rb +8 -0
  75. data/lib/image_paradise/requires/require_image_to_ascii.rb +7 -0
  76. data/lib/image_paradise/requires/require_the_image_paradise_project.rb +24 -0
  77. data/lib/image_paradise/requires/require_toplevel_methods.rb +21 -0
  78. data/lib/image_paradise/rotate/README.md +2 -0
  79. data/lib/image_paradise/rotate/rotate.rb +98 -0
  80. data/lib/image_paradise/shell/interactive.rb +156 -0
  81. data/lib/image_paradise/svg/README.md +5 -0
  82. data/lib/image_paradise/svg/circle.rb +106 -0
  83. data/lib/image_paradise/svg/feature.rb +48 -0
  84. data/lib/image_paradise/svg/rectangle.rb +154 -0
  85. data/lib/image_paradise/svg/svg.rb +102 -0
  86. data/lib/image_paradise/to_gif.rb +91 -0
  87. data/lib/image_paradise/to_jpg.rb +90 -0
  88. data/lib/image_paradise/toplevel_methods/add_black_border_to_this_image.rb +56 -0
  89. data/lib/image_paradise/toplevel_methods/crop.rb +28 -0
  90. data/lib/image_paradise/toplevel_methods/e.rb +16 -0
  91. data/lib/image_paradise/toplevel_methods/esystem.rb +19 -0
  92. data/lib/image_paradise/toplevel_methods/extract_text_from_this_image.rb +56 -0
  93. data/lib/image_paradise/toplevel_methods/file_related_code.rb +25 -0
  94. data/lib/image_paradise/toplevel_methods/flip_image_left_right.rb +32 -0
  95. data/lib/image_paradise/toplevel_methods/greyscale_this_image.rb +59 -0
  96. data/lib/image_paradise/toplevel_methods/help.rb +30 -0
  97. data/lib/image_paradise/toplevel_methods/make_this_image_transparent.rb +30 -0
  98. data/lib/image_paradise/toplevel_methods/menu.rb +92 -0
  99. data/lib/image_paradise/toplevel_methods/merge_these_images.rb +49 -0
  100. data/lib/image_paradise/toplevel_methods/mirror_image.rb +28 -0
  101. data/lib/image_paradise/toplevel_methods/misc.rb +31 -0
  102. data/lib/image_paradise/toplevel_methods/png_to_svg.rb +34 -0
  103. data/lib/image_paradise/toplevel_methods/roebe.rb +17 -0
  104. data/lib/image_paradise/toplevel_methods/to_png.rb +105 -0
  105. data/lib/image_paradise/toplevel_methods/wallpaper.rb +37 -0
  106. data/lib/image_paradise/toplevel_methods/write_this_text.rb +76 -0
  107. data/lib/image_paradise/version/version.rb +19 -0
  108. data/test/16x16_red_square_image_for_testing.png +0 -0
  109. data/test/testing_confree_generator.rb +8 -0
  110. data/test/testing_crop.rb +19 -0
  111. data/test/testing_image_magick_commands.rb +39 -0
  112. data/test/testing_image_paradise.rb +49 -0
  113. data/test/testing_the_svg_component.html +261 -0
  114. data/test/testing_the_svg_component.rb +106 -0
  115. metadata +217 -0
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ require 'image_paradise/graphs/base.rb'
6
+
7
+ ##
8
+ # Graph with individual horizontal bars instead of vertical bars.
9
+
10
+ module ImageParadise
11
+
12
+ class Gruff::SideBar < Gruff::Base
13
+
14
+ # Spacing factor applied between bars
15
+ attr_accessor :bar_spacing
16
+
17
+ def draw
18
+ @has_left_labels = true
19
+ super
20
+
21
+ return unless @has_data
22
+ draw_bars
23
+ end
24
+
25
+ protected
26
+
27
+ def draw_bars
28
+ # Setup spacing.
29
+ #
30
+ @bar_spacing ||= 0.9
31
+
32
+ @bars_width = @graph_height / @column_count.to_f
33
+ @bar_width = @bars_width / @norm_data.size
34
+ @d = @d.stroke_opacity 0.0
35
+ height = Array.new(@column_count, 0)
36
+ length = Array.new(@column_count, @graph_left)
37
+ padding = (@bar_width * (1 - @bar_spacing)) / 2
38
+
39
+ # if we're a side stacked bar then we don't need to draw ourself at all
40
+ # because sometimes (due to different heights/min/max) you can actually
41
+ # see both graphs and it looks like crap
42
+ return if self.is_a?(Gruff::SideStackedBar)
43
+
44
+ @norm_data.each_with_index do |data_row, row_index|
45
+ @d = @d.fill data_row[DATA_COLOR_INDEX]
46
+
47
+ data_row[DATA_VALUES_INDEX].each_with_index do |data_point, point_index|
48
+
49
+ # Using the original calcs from the stacked bar chart
50
+ # to get the difference between
51
+ # part of the bart chart we wish to stack.
52
+ temp1 = @graph_left + (@graph_width - data_point * @graph_width - height[point_index])
53
+ temp2 = @graph_left + @graph_width - height[point_index]
54
+ difference = temp2 - temp1
55
+
56
+ left_x = length[point_index] - 1
57
+ left_y = @graph_top + (@bars_width * point_index) + (@bar_width * row_index) + padding
58
+ right_x = left_x + difference
59
+ right_y = left_y + @bar_width * @bar_spacing
60
+
61
+ height[point_index] += (data_point * @graph_width)
62
+
63
+ @d = @d.rectangle(left_x, left_y, right_x, right_y)
64
+
65
+ # Calculate center based on bar_width and current row
66
+
67
+ if @use_data_label
68
+ label_center = @graph_top + (@bar_width * (row_index+point_index) + @bar_width / 2)
69
+ draw_label(label_center, row_index, @norm_data[row_index][DATA_LABEL_INDEX])
70
+ else
71
+ label_center = @graph_top + (@bars_width * point_index + @bars_width / 2)
72
+ draw_label(label_center, point_index)
73
+ end
74
+ if @show_labels_for_bar_values
75
+ val = (@label_formatting || '%.2f') % @norm_data[row_index][3][point_index]
76
+ draw_value_label(right_x+40, (@graph_top + (((row_index+point_index+1) * @bar_width) - (@bar_width / 2)))-12, val.commify, true)
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+ @d.draw(@base_image)
83
+ end
84
+
85
+ # Instead of base class version, draws vertical background lines and label
86
+ def draw_line_markers
87
+
88
+ return if @hide_line_markers
89
+
90
+ @d = @d.stroke_antialias false
91
+
92
+ # Draw horizontal line markers and annotate with numbers
93
+ @d = @d.stroke(@marker_color)
94
+ @d = @d.stroke_width 1
95
+ number_of_lines = @marker_count || 5
96
+ number_of_lines = 1 if number_of_lines == 0
97
+
98
+ # TODO Round maximum marker value to a round number like 100, 0.1, 0.5, etc.
99
+ increment = significant(@spread.to_f / number_of_lines)
100
+ (0..number_of_lines).each do |index|
101
+
102
+ line_diff = (@graph_right - @graph_left) / number_of_lines
103
+ x = @graph_right - (line_diff * index) - 1
104
+ @d = @d.line(x, @graph_bottom, x, @graph_top)
105
+ diff = index - number_of_lines
106
+ marker_label = diff.abs * increment + @minimum_value
107
+
108
+ unless @hide_line_numbers
109
+ @d.fill = @font_color
110
+ @d.font = @font if @font
111
+ @d.stroke = 'transparent'
112
+ @d.pointsize = scale_fontsize(@marker_font_size)
113
+ @d.gravity = CenterGravity
114
+ # TODO Center text over line
115
+ @d = @d.annotate_scaled(@base_image,
116
+ 0, 0, # Width of box to draw text in
117
+ x, @graph_bottom + (LABEL_MARGIN * 2.0), # Coordinates of text
118
+ marker_label.to_s, @scale)
119
+ end # unless
120
+ @d = @d.stroke_antialias true
121
+ end
122
+ end
123
+
124
+ ##
125
+ # Draw on the Y axis instead of the X
126
+
127
+ def draw_label(y_offset, index, label=nil)
128
+ if !@labels[index].nil? && @labels_seen[index].nil?
129
+ lbl = (@use_data_label) ? label : @labels[index]
130
+ @d.fill = @font_color
131
+ @d.font = @font if @font
132
+ @d.stroke = 'transparent'
133
+ @d.font_weight = NormalWeight
134
+ @d.pointsize = scale_fontsize(@marker_font_size)
135
+ @d.gravity = EastGravity
136
+ @d = @d.annotate_scaled(@base_image,
137
+ 1, 1,
138
+ -@graph_left + LABEL_MARGIN * 2.0, y_offset,
139
+ lbl, @scale)
140
+ @labels_seen[index] = 1
141
+ end
142
+ end
143
+
144
+ end; end
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ require 'image_paradise/graphs/base.rb'
6
+ require 'image_paradise/graphs/side_bar.rb'
7
+ require 'image_paradise/graphs/stacked_mixin.rb'
8
+
9
+ ##
10
+ # New gruff graph type added to enable sideways stacking bar charts
11
+ # (basically looks like a x/y flip of a standard stacking bar chart)
12
+ #
13
+ # alun.eyre@googlemail.com
14
+ module ImageParadise
15
+
16
+ class Gruff::SideStackedBar < Gruff::SideBar
17
+
18
+ include StackedMixin
19
+
20
+ # Spacing factor applied between bars
21
+ attr_accessor :bar_spacing
22
+
23
+ def draw
24
+ @has_left_labels = true
25
+ get_maximum_by_stack
26
+ super
27
+ end
28
+
29
+ protected
30
+
31
+ def draw_bars
32
+ # Setup spacing.
33
+ #
34
+ # Columns sit stacked.
35
+ @bar_spacing ||= 0.9
36
+
37
+ @bar_width = @graph_height / @column_count.to_f
38
+ @d = @d.stroke_opacity 0.0
39
+ height = Array.new(@column_count, 0)
40
+ length = Array.new(@column_count, @graph_left)
41
+ padding = (@bar_width * (1 - @bar_spacing)) / 2
42
+ if @show_labels_for_bar_values
43
+ label_values = Array.new
44
+ 0.upto(@column_count-1) {|i| label_values[i] = {:value => 0, :right_x => 0}}
45
+ end
46
+ @norm_data.each_with_index do |data_row, row_index|
47
+ data_row[DATA_VALUES_INDEX].each_with_index do |data_point, point_index|
48
+ ## using the original calcs from the stacked bar chart to get the difference between
49
+ ## part of the bart chart we wish to stack.
50
+ temp1 = @graph_left + (@graph_width -
51
+ data_point * @graph_width -
52
+ height[point_index]) + 1
53
+ temp2 = @graph_left + @graph_width - height[point_index] - 1
54
+ difference = temp2 - temp1
55
+
56
+ @d = @d.fill data_row[DATA_COLOR_INDEX]
57
+
58
+ left_x = length[point_index] #+ 1
59
+ left_y = @graph_top + (@bar_width * point_index) + padding
60
+ right_x = left_x + difference
61
+ right_y = left_y + @bar_width * @bar_spacing
62
+ length[point_index] += difference
63
+ height[point_index] += (data_point * @graph_width - 2)
64
+
65
+ if @show_labels_for_bar_values
66
+ label_values[point_index][:value] += @norm_data[row_index][3][point_index]
67
+ label_values[point_index][:right_x] = right_x
68
+ end
69
+
70
+ # if a data point is 0 it can result in weird really thing lines
71
+ # that shouldn't even be there being drawn on top of the existing
72
+ # bar - this is bad
73
+ if data_point != 0
74
+ @d = @d.rectangle(left_x, left_y, right_x, right_y)
75
+ # Calculate center based on bar_width and current row
76
+ end
77
+ # we still need to draw the labels
78
+ # Calculate center based on bar_width and current row
79
+ label_center = @graph_top + (@bar_width * point_index) + (@bar_width * @bar_spacing / 2.0)
80
+ draw_label(label_center, point_index)
81
+ end
82
+
83
+ end
84
+ if @show_labels_for_bar_values
85
+ label_values.each_with_index { |data, i|
86
+ val = (@label_formatting || "%.2f") % data[:value]
87
+ draw_value_label(data[:right_x]+40, (@graph_top + (((i+1) * @bar_width) - (@bar_width / 2)))-12, val.commify, true)
88
+ }
89
+ end
90
+ @d.draw(@base_image)
91
+ end
92
+
93
+ # ========================================================================= #
94
+ # === larger_than_max?
95
+ # ========================================================================= #
96
+ def larger_than_max?(data_point, index=0)
97
+ max(data_point, index) > @maximum_value
98
+ end
99
+
100
+ # ========================================================================= #
101
+ # === max
102
+ # ========================================================================= #
103
+ def max(data_point, index)
104
+ puts '---'
105
+ pp data_point
106
+ pp index
107
+ pp @data
108
+ puts '---'
109
+ @data.inject(0) {|sum, item|
110
+ value = item[DATA_VALUES_INDEX][index]
111
+ pp value
112
+ sum + value
113
+ }
114
+ end
115
+
116
+ end; end
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ require 'image_paradise/graphs/base.rb'
6
+
7
+ # =========================================================================== #
8
+ # Experimental!!! See also the Net graph.
9
+ #
10
+ # Submitted by Kevin Clark http://glu.ttono.us/
11
+ # =========================================================================== #
12
+ module ImageParadise
13
+
14
+ class Gruff::Spider < Gruff::Base
15
+
16
+ # Hide all text
17
+ attr_reader :hide_text
18
+ attr_accessor :hide_axes
19
+ attr_reader :transparent_background
20
+ attr_accessor :rotation
21
+
22
+ # ========================================================================= #
23
+ # === initialize
24
+ # ========================================================================= #
25
+ def initialize(max_value, target_width = 800)
26
+ super(target_width)
27
+ @max_value = max_value
28
+ @hide_legend = true;
29
+ @rotation = 0
30
+ end
31
+
32
+ # ========================================================================= #
33
+ # === transparent_background=
34
+ # ========================================================================= #
35
+ def transparent_background=(value)
36
+ @transparent_background = value
37
+ @base_image = render_transparent_background if value
38
+ end
39
+
40
+ # ========================================================================= #
41
+ # === draw
42
+ # ========================================================================= #
43
+ def draw
44
+ @hide_line_markers = true
45
+ super
46
+ return unless @has_data
47
+ # Setup basic positioning
48
+ # diameter = @graph_height # Variable not in use.
49
+ radius = @graph_height / 2.0
50
+ # top_x = @graph_left + (@graph_width - diameter) / 2.0
51
+ center_x = @graph_left + (@graph_width / 2.0)
52
+ center_y = @graph_top + (@graph_height / 2.0) - 25 # Move graph up a bit
53
+
54
+ @unit_length = radius / @max_value
55
+
56
+ # total_sum = sums_for_spider # Not in use.
57
+ # prev_degrees = 0.0 # Not in use.
58
+ additive_angle = (2 * Math::PI)/ @data.size
59
+
60
+ # current_angle = rotation * Math::PI / 180.0 # Not in use.
61
+
62
+ # Draw axes
63
+ draw_axes(center_x, center_y, radius, additive_angle) unless hide_axes
64
+
65
+ # Draw polygon
66
+ draw_polygon(center_x, center_y, additive_angle)
67
+
68
+ @d.draw(@base_image)
69
+ end
70
+
71
+ # ========================================================================= #
72
+ # === hide_text=
73
+ # ========================================================================= #
74
+ def hide_text=(value)
75
+ @hide_title = @hide_text = value
76
+ end
77
+
78
+ private
79
+ # ========================================================================= #
80
+ # === normalize_points
81
+ # ========================================================================= #
82
+ def normalize_points(value)
83
+ value * @unit_length
84
+ end
85
+
86
+ # ========================================================================= #
87
+ # === draw_label
88
+ # ========================================================================= #
89
+ def draw_label(center_x, center_y, angle, radius, amount)
90
+ r_offset = 50 # The distance out from the center of the pie to get point
91
+ x_offset = center_x # The label points need to be tweaked slightly
92
+ y_offset = center_y + 0 # This one doesn't though
93
+ x = x_offset + ((radius + r_offset) * Math.cos(angle))
94
+ y = y_offset + ((radius + r_offset) * Math.sin(angle))
95
+
96
+ # Draw label
97
+ @d.fill = @marker_color
98
+ @d.font = @font if @font
99
+ @d.pointsize = scale_fontsize(legend_font_size)
100
+ @d.stroke = 'transparent'
101
+ @d.font_weight = BoldWeight
102
+ @d.gravity = CenterGravity
103
+ @d.annotate_scaled( @base_image,
104
+ 0, 0,
105
+ x, y,
106
+ amount, @scale)
107
+ end
108
+
109
+ # ========================================================================= #
110
+ # === draw_axes
111
+ # ========================================================================= #
112
+ def draw_axes(center_x, center_y, radius, additive_angle, line_color = nil)
113
+ return if hide_axes
114
+
115
+ current_angle = rotation * Math::PI / 180.0
116
+
117
+ @data.each do |data_row|
118
+ @d.stroke(line_color || data_row[DATA_COLOR_INDEX])
119
+ @d.stroke_width 5.0
120
+
121
+ x_offset = radius * Math.cos(current_angle)
122
+ y_offset = radius * Math.sin(current_angle)
123
+
124
+ @d.line(center_x, center_y,
125
+ center_x + x_offset,
126
+ center_y + y_offset)
127
+
128
+ draw_label(center_x, center_y, current_angle, radius, data_row[DATA_LABEL_INDEX].to_s) unless hide_text
129
+
130
+ current_angle += additive_angle
131
+ end
132
+ end
133
+
134
+ # ========================================================================= #
135
+ # === draw_polygon
136
+ # ========================================================================= #
137
+ def draw_polygon(center_x, center_y, additive_angle, color = nil)
138
+ points = []
139
+ current_angle = rotation * Math::PI / 180.0
140
+
141
+ @data.each { |data_row|
142
+ points << center_x + normalize_points(data_row[DATA_VALUES_INDEX].first) * Math.cos(current_angle)
143
+ points << center_y + normalize_points(data_row[DATA_VALUES_INDEX].first) * Math.sin(current_angle)
144
+ current_angle += additive_angle
145
+ }
146
+
147
+ @d.stroke_width 1.0
148
+ @d.stroke(color || @marker_color)
149
+ @d.fill(color || @marker_color)
150
+ @d.fill_opacity 0.4
151
+ @d.polygon(*points)
152
+ end
153
+
154
+ # ========================================================================= #
155
+ # === sums_for_spider
156
+ # ========================================================================= #
157
+ def sums_for_spider
158
+ @data.inject(0.0) {|sum, data_row|
159
+ sum += data_row[DATA_VALUES_INDEX].first
160
+ }
161
+ end
162
+
163
+ end; end
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ require 'image_paradise/graphs/base.rb'
6
+ require 'image_paradise/graphs/stacked_mixin.rb'
7
+
8
+ module ImageParadise
9
+
10
+ class Gruff::StackedArea < Gruff::Base
11
+
12
+ include StackedMixin
13
+
14
+ attr_accessor :last_series_goes_on_bottom
15
+ # === draw
16
+ def draw
17
+ get_maximum_by_stack
18
+ super
19
+
20
+ return unless @has_data
21
+
22
+ @x_increment = @graph_width / (@column_count - 1).to_f
23
+ @d = @d.stroke 'transparent'
24
+
25
+ height = Array.new(@column_count, 0)
26
+
27
+ data_points = nil
28
+ iterator = last_series_goes_on_bottom ? :reverse_each : :each
29
+ @norm_data.send(iterator) do |data_row|
30
+ prev_data_points = data_points
31
+ data_points = Array.new
32
+
33
+ @d = @d.fill data_row[DATA_COLOR_INDEX]
34
+
35
+ data_row[DATA_VALUES_INDEX].each_with_index do |data_point, index|
36
+ # Use incremented x and scaled y
37
+ new_x = @graph_left + (@x_increment * index)
38
+ new_y = @graph_top + (@graph_height - data_point * @graph_height - height[index])
39
+
40
+ height[index] += (data_point * @graph_height)
41
+
42
+ data_points << new_x
43
+ data_points << new_y
44
+
45
+ draw_label(new_x, index)
46
+
47
+ end
48
+
49
+ if prev_data_points
50
+ poly_points = data_points.dup
51
+ (prev_data_points.length/2 - 1).downto(0) do |i|
52
+ poly_points << prev_data_points[2*i]
53
+ poly_points << prev_data_points[2*i+1]
54
+ end
55
+ poly_points << data_points[0]
56
+ poly_points << data_points[1]
57
+ else
58
+ poly_points = data_points.dup
59
+ poly_points << @graph_right
60
+ poly_points << @graph_bottom - 1
61
+ poly_points << @graph_left
62
+ poly_points << @graph_bottom - 1
63
+ poly_points << data_points[0]
64
+ poly_points << data_points[1]
65
+ end
66
+ @d = @d.polyline(*poly_points)
67
+
68
+ end
69
+
70
+ @d.draw(@base_image)
71
+ end
72
+
73
+ end; end