cairo-graph 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a92ad657c35e87063c2ce8e5dab114ea646fca7e
4
+ data.tar.gz: 8b6f9b0dce0fd8446daf91366cc6f5e07d450ccc
5
+ SHA512:
6
+ metadata.gz: 9fb035333001ca88284f8c1568e95ee8d3de4cbf5c0e7803ffbbe8ac06a12bb385a945f37e4cba6800754aa8f55b78893f80030578f3f0e6e935d6a8d79dad2d
7
+ data.tar.gz: 6262ae14b7a809164ccac83806955d9cbc0be7f8b1a1559096f92a017728668a448e420c62aa7501da58a4bc536b5148b9dd196e4e3298c674f846c75389fd92
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in cairo-graph.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2015 Masafumi Yokoyama <yokoyama@clear-code.com>
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # Cairo::Graph
2
+
3
+ A library that can generate graph easily, by cairo (rcairo) with Ruby.
4
+
5
+ ![](http://myokoym.net/public/graph-by-rcairo.png)
6
+
7
+ ## Dependencies
8
+
9
+ * [rcairo](http://rcairo.github.io/)
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem "cairo-graph"
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install cairo-graph
26
+
27
+ ## Usage
28
+
29
+ See examples.
30
+
31
+ ## Authors
32
+
33
+ * Masafumi Yokoyama `<yokoyama@clear-code.com>`
34
+
35
+ ## License
36
+
37
+ MIT License.
38
+
39
+ See LICENSE.txt for details.
40
+
41
+ ## Contributing
42
+
43
+ 1. Fork it ( https://github.com/myokoym/cairo-graph/fork )
44
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
45
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
46
+ 4. Push to the branch (`git push origin my-new-feature`)
47
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ desc "Run test"
4
+ task :test do
5
+ Bundler::GemHelper.install_tasks
6
+ ruby("test/run-test.rb")
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,27 @@
1
+ lib_dir = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
3
+ require "cairo/graph"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "cairo-graph"
7
+ spec.version = Cairo::Graph::VERSION
8
+ spec.authors = ["Masafumi Yokoyama"]
9
+ spec.email = ["yokoyama@clear-code.com"]
10
+
11
+ spec.summary = %q{Graphing library for rcairo.}
12
+ spec.description = %q{A library that can generate graph easily, by cairo (rcairo) and Ruby.}
13
+ spec.homepage = "https://github.com/myokoym/cairo-graph"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject {|f| f.match(%r{^(test|spec|features)/})}
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f)}
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency("cairo")
22
+
23
+ spec.add_development_dependency("bundler")
24
+ spec.add_development_dependency("rake")
25
+ spec.add_development_dependency("test-unit")
26
+ spec.add_development_dependency("test-unit-notify")
27
+ end
data/examples/basic.rb ADDED
@@ -0,0 +1,35 @@
1
+ require "cairo/graph"
2
+
3
+ rows = [
4
+ [[253, 503, 84, 687, 859, 361, 110, 403], "Senna"],
5
+ [[588, 766, 485, 1039, 862, 1028, 155, 235], "Groonga"],
6
+ [[504, 192, 610, 541, 469, 192, 194, 1072], "Rroonga"],
7
+ [[ 31, 694, 80, 3, 762, 85, 620, 1078], "Mroonga"],
8
+ [[422, 288, 376, 1162, 153, 218, 303, 638], "Nroonga"],
9
+ [[264, 106, 167, 586, 204, 597, 831, 1111], "Droonga"],
10
+ ]
11
+
12
+ columns = [*1..8].collect do |i|
13
+ "5/#{i}"
14
+ end
15
+
16
+ width = 960
17
+ height = 480
18
+
19
+ graph = Cairo::Graph.new(:width => width, :height => height)
20
+ graph.title = "Graph by rcairo"
21
+ graph.unit_name = "(Unit)"
22
+ graph.columns = columns
23
+ #graph.grid_max = 1200
24
+ #graph.grid_step = 200
25
+ rows.each do |row_with_name|
26
+ row, name = *row_with_name
27
+ graph.add(row, name)
28
+ end
29
+
30
+ Cairo::ImageSurface.new(:argb32, width, height) do |surface|
31
+ Cairo::Context.new(surface) do |context|
32
+ context.show_graph(graph)
33
+ end
34
+ surface.write_to_png("graph-by-rcairo.png")
35
+ end
@@ -0,0 +1,287 @@
1
+ require "cairo"
2
+
3
+ module Cairo
4
+ class Context
5
+ def show_graph(graph)
6
+ graph.draw(self)
7
+ end
8
+ end
9
+
10
+ class Graph
11
+ VERSION = "0.0.1"
12
+
13
+ LINE_COLORS = [
14
+ Cairo::Color.parse("#CCCCE6"),
15
+ Cairo::Color.parse("#319DE9"),
16
+ Cairo::Color.parse("#F14040"),
17
+ Cairo::Color.parse("#F9B351"),
18
+ Cairo::Color.parse("#83BE41"),
19
+ Cairo::Color.parse("#E2629C"),
20
+ Cairo::Color::RGB.new(rand, rand, rand),
21
+ Cairo::Color::RGB.new(rand, rand, rand),
22
+ Cairo::Color::RGB.new(rand, rand, rand),
23
+ Cairo::Color::RGB.new(rand, rand, rand),
24
+ ]
25
+
26
+ attr_reader :width
27
+ attr_reader :height
28
+
29
+ attr_accessor :margin_top
30
+ attr_accessor :margin_bottom
31
+ attr_accessor :margin_left
32
+ attr_accessor :margin_right
33
+
34
+ attr_accessor :line_width
35
+ attr_accessor :point_radius
36
+
37
+ attr_accessor :background_top_color
38
+ attr_accessor :background_bottom_color
39
+ attr_accessor :text_color
40
+ attr_accessor :grid_color
41
+
42
+ attr_accessor :title
43
+ attr_accessor :columns
44
+ attr_accessor :unit_name
45
+ attr_accessor :grid_max
46
+ attr_accessor :grid_step
47
+
48
+ def initialize(options={})
49
+ # TODO: validate options
50
+
51
+ @width = options[:width] || 640
52
+ @height = options[:height] || 480
53
+
54
+ @margin_top = @height * 0.3
55
+ @margin_bottom = @height * 0.2
56
+ @margin_left = @width * 0.1 + @height * 0.05
57
+ @margin_right = @width * 0.15 + @height * 0.1
58
+
59
+ @line_width = @height * 0.01
60
+ @point_radius = @height * 0.02
61
+
62
+ @background_top_color = :black
63
+ @background_bottom_color = Cairo::Color.parse("#1A1629")
64
+ @text_color = :white
65
+ @grid_color = :white
66
+
67
+ @title = ""
68
+ @columns = []
69
+ @unit_name = nil
70
+ @grid_max = nil
71
+ @grid_step = nil
72
+
73
+ @rows = []
74
+ @names = []
75
+ @colors = []
76
+ end
77
+
78
+ def add(row, name=nil, color=nil)
79
+ @rows << row
80
+ @names << name
81
+ @colors << color
82
+ end
83
+
84
+ def draw(context)
85
+ draw_background(context)
86
+ draw_title(context)
87
+ draw_grid(context)
88
+ draw_unit_name(context)
89
+ draw_rows(context)
90
+ draw_names(context)
91
+ draw_columns(context)
92
+ end
93
+
94
+ def draw_background(context)
95
+ context.fill do
96
+ context.set_source(background_pattern)
97
+ context.rectangle(0, 0, @width, @height)
98
+ end
99
+ end
100
+
101
+ def draw_title(context)
102
+ context.font_size = @height * 0.1
103
+ extents = context.text_extents(@title)
104
+ x = (@width / 2) - (extents.width / 2 + extents.x_bearing)
105
+ y = @height * 0.13
106
+ context.move_to(x, y)
107
+ context.set_source_color(@text_color)
108
+ context.show_text(@title)
109
+ end
110
+
111
+ def draw_grid(context)
112
+ context.set_source_color(@grid_color)
113
+ context.set_line_width(@line_width * 0.2)
114
+ x1 = @margin_left * 0.9
115
+ x2 = @width - @margin_right * 0.9
116
+ 0.step(grid_max, grid_step) do |value|
117
+ scale = value.to_f / grid_max
118
+ y = @height - (@margin_bottom + (graph_area_height * scale))
119
+ draw_grid_line(context, value, x1, x2, y)
120
+ draw_grid_value(context, value, y)
121
+ end
122
+ end
123
+
124
+ def draw_unit_name(context)
125
+ return unless @unit_name
126
+ font_size = @height * 0.05
127
+ context.font_size = font_size
128
+ extents = context.text_extents(@unit_name)
129
+ x = @margin_left - (extents.width + extents.x_bearing)
130
+ y = @margin_top * 0.7
131
+ context.move_to(x, y)
132
+ context.show_text(@unit_name)
133
+ end
134
+
135
+ def draw_rows(context)
136
+ context.set_line_width(@line_width)
137
+ @rows.size.times do |index|
138
+ draw_row(context, index)
139
+ end
140
+ end
141
+
142
+ def draw_names(context)
143
+ font_size = @height * 0.05
144
+ context.font_size = font_size
145
+ x1 = @width - (@margin_right * 0.85)
146
+ x2 = @width - (@margin_right * 0.1)
147
+ @names.each_with_index do |name, i|
148
+ context.set_source_color(@colors[i] || LINE_COLORS[i])
149
+ text = (@names[i] || (i + 1)).to_s
150
+ y = (@margin_top * 0.7) + (font_size * i * 1.8)
151
+ context.stroke do
152
+ context.move_to(x1, y + font_size * 0.4)
153
+ context.line_to(x2, y + font_size * 0.4)
154
+ end
155
+ context.move_to(x1, y)
156
+ context.show_text(text)
157
+ end
158
+ end
159
+
160
+ def draw_columns(context)
161
+ context.set_source_color(@text_color)
162
+ context.font_size = @height * 0.04
163
+ columns.each_with_index do |column, i|
164
+ extents = context.text_extents(column)
165
+ x = interval_x * i + @margin_left - (extents.width / 2 + extents.x_bearing)
166
+ if column.length > (@width / @height * 4) && i % 2 == 0
167
+ y = @height - (@margin_bottom * 0.4)
168
+ else
169
+ y = @height - (@margin_bottom * 0.6)
170
+ end
171
+ context.move_to(x, y)
172
+ context.show_text(column)
173
+ end
174
+ end
175
+
176
+ private
177
+ def draw_grid_line(context, value, x1, x2, y)
178
+ context.stroke do
179
+ context.move_to(x1, y)
180
+ context.line_to(x2, y)
181
+ end
182
+ end
183
+
184
+ def draw_grid_value(context, value, line_y)
185
+ context.font_size = @height * 0.05
186
+ text = value.to_s
187
+ extents = context.text_extents(text)
188
+ x = @margin_left * 0.8 - (extents.width + extents.x_bearing)
189
+ y = line_y - (extents.height / 2 + extents.y_bearing)
190
+ context.move_to(x, y)
191
+ context.set_source_color(@text_color)
192
+ context.show_text(text)
193
+ end
194
+
195
+ def draw_row(context, index)
196
+ row = @rows[index]
197
+ context.set_source_color(@colors[index] || LINE_COLORS[index])
198
+ points = []
199
+ row.each_with_index do |value, i|
200
+ x = interval_x * i + @margin_left
201
+ y = @height - (value * interval_y + @margin_bottom)
202
+ points << [x, y]
203
+ end
204
+
205
+ context.stroke do
206
+ points.each_with_index do |point, i|
207
+ x, y = *point
208
+ if i == 0
209
+ context.move_to(x, y)
210
+ else
211
+ context.line_to(x, y)
212
+ end
213
+ end
214
+ end
215
+
216
+ points.each do |point|
217
+ x, y = *point
218
+ context.fill do
219
+ context.circle(x, y, @point_radius)
220
+ end
221
+ end
222
+ end
223
+
224
+ def grid_max
225
+ return @grid_max if @grid_max
226
+ base = (data_max - 1).floor.to_s
227
+ case base[0].to_i
228
+ when 0
229
+ 1.0
230
+ when 1
231
+ if base.length > 1 && base[1].to_i < 5
232
+ 10 ** base.length / 8
233
+ else
234
+ 10 ** base.length / 5
235
+ end
236
+ when 2
237
+ 10 ** base.length / 4
238
+ when 3..5
239
+ 10 ** base.length / 2
240
+ else
241
+ 10 ** base.length
242
+ end
243
+ end
244
+
245
+ def grid_step
246
+ return @grid_step if @grid_step
247
+ (grid_max.to_f / 5).round
248
+ end
249
+
250
+ def interval_x
251
+ case data_size
252
+ when 1
253
+ 0
254
+ else
255
+ graph_area_width.to_f / (data_size - 1)
256
+ end
257
+ end
258
+
259
+ def interval_y
260
+ graph_area_height.to_f / grid_max
261
+ end
262
+
263
+ def data_max
264
+ @rows.collect {|row| row.max }.max
265
+ end
266
+
267
+ def data_size
268
+ @rows.max {|row| row.size }.size
269
+ end
270
+
271
+ def graph_area_width
272
+ @width - @margin_left - @margin_right
273
+ end
274
+
275
+ def graph_area_height
276
+ @height - @margin_top - @margin_bottom
277
+ end
278
+
279
+ def background_pattern
280
+ pattern = Cairo::LinearPattern.new(@width / 2, 0,
281
+ @width / 2, @height)
282
+ pattern.add_color_stop(0.0, @background_top_color)
283
+ pattern.add_color_stop(1.0, @background_bottom_color)
284
+ pattern
285
+ end
286
+ end
287
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cairo-graph
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Masafumi Yokoyama
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-03-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cairo
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: test-unit-notify
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: A library that can generate graph easily, by cairo (rcairo) and Ruby.
84
+ email:
85
+ - yokoyama@clear-code.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - Gemfile
92
+ - LICENSE.txt
93
+ - README.md
94
+ - Rakefile
95
+ - cairo-graph.gemspec
96
+ - examples/basic.rb
97
+ - lib/cairo/graph.rb
98
+ homepage: https://github.com/myokoym/cairo-graph
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.2.2
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Graphing library for rcairo.
122
+ test_files: []
123
+ has_rdoc: