playfair 0.0.1

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.
data/lib/playfair.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "playfair/chart"
2
+ require "playfair/renderer"
3
+ require "playfair/google_chart_renderer"
4
+ require "playfair/pdf_renderer"
5
+
@@ -0,0 +1,30 @@
1
+ module Playfair
2
+ class Chart < Array
3
+
4
+ attr_accessor :title
5
+ attr_accessor :renderer
6
+
7
+ def initialize(&block)
8
+ @renderer = GoogleChartRenderer
9
+ instance_eval &block
10
+ end
11
+
12
+ def value(value,label="")
13
+ push Value.new(value,label)
14
+ end
15
+
16
+ def values
17
+ collect { |value| value.value }
18
+ end
19
+
20
+ def labels
21
+ collect { |value| value.label }
22
+ end
23
+
24
+ def render(type, options={})
25
+ renderer.new(self, options).render(type)
26
+ end
27
+ end
28
+
29
+ Value = Struct.new(:value, :label)
30
+ end
@@ -0,0 +1,38 @@
1
+ require 'cgi'
2
+
3
+ module Playfair
4
+ class GoogleChartRenderer < Renderer
5
+
6
+ API_URL = "http://chart.apis.google.com/chart"
7
+
8
+ render :bar_chart do
9
+ chart_url "cht=bvs&chd=t:#{values.join(',')}&chxt=x,y&chxl=0:|#{labels.join('|')}"
10
+ end
11
+
12
+ render :line_chart do
13
+ chart_url "cht=lc&chd=t:#{values.join(',')}&chxt=x,y&chxl=0:|#{labels.join('|')}"
14
+ end
15
+
16
+ render :pie_chart do
17
+ chart_url "cht=p&chd=t:#{values.join(',')}&chl=#{labels.join('|')}"
18
+ end
19
+
20
+ protected
21
+
22
+ def chart_url(chart_params)
23
+ rendered_chart = "#{API_URL}?#{chart_params}"
24
+ rendered_chart << "&chs=#{width}x#{height}"
25
+ rendered_chart << "&chtt=#{title}" if title
26
+ rendered_chart
27
+ end
28
+
29
+ def labels
30
+ source.collect { |v| CGI.escape(v.label.to_s) }
31
+ end
32
+
33
+ def title
34
+ CGI.escape(super) if super
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,195 @@
1
+ require 'prawn'
2
+
3
+ module Playfair
4
+ class PDFRenderer < Renderer
5
+
6
+ attr_reader :margin, :gutter, :font_size, :label_width, :text_color, :stroke_color, :output_filename
7
+
8
+ COLORS = ["E213A9","F1A637","B55EF0","42D13E", "F50000","DDE93D","7BD2F9","F78A64"]
9
+
10
+ def initialize(chart, options={})
11
+ @margin = options[:margin] || 15
12
+ @gutter = options[:gutter] || 15
13
+ @font_size = options[:font_size] || 7
14
+ @label_width = options[:label_width] || 20
15
+ @text_color = options[:text_color] || "333333"
16
+ @stroke_color = options[:stroke_color] || "333333"
17
+ @output_filename = options[:to] || "chart.pdf"
18
+ super(chart, options)
19
+ end
20
+
21
+ render :bar_chart do
22
+ draw_chart do |pdf|
23
+ x_position = starting_x_position
24
+
25
+ values.each_with_index do |value, i|
26
+ # Draw bar
27
+ pdf.fill_color color(i)
28
+ bar_height = height_for_value(value, values.max)
29
+ pdf.fill_and_stroke_rounded_rectangle [x_position, bar_height + bottom_margin],
30
+ bar_width, bar_height, 2
31
+
32
+ # Draw label
33
+ pdf.fill_color text_color
34
+ text_with_shadow pdf, labels[i],
35
+ :align => :center,
36
+ :at => [x_position, margin + font_size],
37
+ :width => bar_width,
38
+ :overflow => :shrink_to_fit
39
+
40
+ x_position += bar_width + gutter
41
+ end
42
+ end
43
+ end
44
+
45
+ render :line_chart do
46
+ draw_chart do |pdf|
47
+ x_position = starting_x_position
48
+ values.each_with_index do |value, i|
49
+ # Draw line
50
+ if values[i + 1]
51
+ pdf.stroke_line x_position,
52
+ height_for_value(value, values.max) + bottom_margin,
53
+ x_position + point_interval,
54
+ height_for_value(values[i + 1], values.max) + bottom_margin
55
+ x_position += point_interval
56
+ end
57
+ end
58
+
59
+ # Draw points
60
+ x_position = starting_x_position
61
+ values.each do |value|
62
+ pdf.fill_circle_at [x_position, height_for_value(value, values.max) + bottom_margin], :radius => 3
63
+ x_position += point_interval
64
+ end
65
+
66
+ # Draw labels
67
+ x_position = starting_x_position
68
+ values.each_with_index do |value, i|
69
+ pdf.fill_color text_color
70
+ text_with_shadow pdf, labels[i],
71
+ :align => :center,
72
+ :at => [x_position - point_interval/2, margin + font_size],
73
+ :width => point_interval,
74
+ :overflow => :shrink_to_fit
75
+ x_position += point_interval
76
+ end
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def chart_width
83
+ right_margin = margin
84
+
85
+ width - left_margin - right_margin
86
+ end
87
+
88
+ def chart_height
89
+ height - top_margin - bottom_margin
90
+ end
91
+
92
+ def top_margin
93
+ top = margin
94
+ top += font_size + margin if title
95
+ top
96
+ end
97
+
98
+ def left_margin
99
+ margin + label_width + 3
100
+ end
101
+
102
+ def bottom_margin
103
+ margin + font_size + 3
104
+ end
105
+
106
+ def starting_x_position
107
+ left_margin + gutter + ((chart_width - gutter)%values.size)/2
108
+ end
109
+
110
+ def bar_width
111
+ ((chart_width - gutter)/values.size) - gutter
112
+ end
113
+
114
+ def point_interval
115
+ (chart_width - gutter*2)/(values.size - 1)
116
+ end
117
+
118
+ def draw_chart
119
+ pdf = Prawn::Document.new(:page_size => [width, height], :margin => 0)
120
+ pdf.line_width 1.2
121
+ pdf.stroke_color stroke_color
122
+
123
+ draw_title(pdf) if title
124
+ draw_y_axis(pdf)
125
+ yield(pdf)
126
+ draw_x_axis(pdf)
127
+
128
+ pdf.render_file output_filename
129
+ end
130
+
131
+ def draw_title(pdf)
132
+ pdf.font_size font_size * 1.6
133
+ text_with_shadow pdf,
134
+ title,
135
+ :at => [left_margin, height - margin],
136
+ :width => chart_width,
137
+ :align => :center,
138
+ :style => :bold,
139
+ :single_line => true
140
+ pdf.font_size font_size
141
+ end
142
+
143
+ def draw_x_axis(pdf)
144
+ pdf.stroke_line [left_margin, bottom_margin], [left_margin + chart_width, bottom_margin]
145
+ end
146
+
147
+ def draw_y_axis(pdf)
148
+ draw_y_axis_label pdf, "0",
149
+ [margin,bottom_margin+font_size/2.5]
150
+
151
+ max_line_height = chart_height + bottom_margin
152
+ draw_y_axis_label pdf, values.max.to_s,
153
+ [margin, max_line_height + font_size/2.5]
154
+
155
+ halfway_line_height = chart_height/2 + bottom_margin
156
+ halfway_point = values.max / 2
157
+ draw_y_axis_label pdf, halfway_point.to_s,
158
+ [margin, halfway_line_height + font_size/2.5]
159
+
160
+ pdf.transparent(0.3) do
161
+ pdf.dash 2, :space => 1
162
+ pdf.stroke_line [left_margin, max_line_height], [left_margin + chart_width, max_line_height]
163
+ pdf.stroke_line [left_margin, halfway_line_height], [left_margin + chart_width, halfway_line_height]
164
+ pdf.undash
165
+ end
166
+ end
167
+
168
+ def height_for_value(value, max_value)
169
+ ratio = chart_height/max_value.to_f
170
+ (value * ratio).to_i
171
+ end
172
+
173
+ def draw_y_axis_label(pdf, label, point)
174
+ text_with_shadow pdf,
175
+ label,
176
+ :at => point,
177
+ :width => label_width,
178
+ :height => font_size,
179
+ :align => :right,
180
+ :overflow => :shrink_to_fit
181
+ end
182
+
183
+ def text_with_shadow(pdf, text, options={})
184
+ at = options[:at]
185
+ pdf.transparent(0.3) do
186
+ pdf.text_box text, options.merge(:at => [at.first, at.last + pdf.font_size/22.0])
187
+ end
188
+ pdf.text_box text, options
189
+ end
190
+
191
+ def color(index)
192
+ COLORS[index % COLORS.size]
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,36 @@
1
+ module Playfair
2
+ class Renderer
3
+
4
+ attr_reader :source, :width, :height
5
+ @@chart_types = {}
6
+
7
+ def initialize(chart, options={})
8
+ @source = chart
9
+ @width = options[:width] || 330
10
+ @height = options[:height] || 200
11
+ end
12
+
13
+ def self.render(chart_type, &block)
14
+ @@chart_types[self] ||= {}
15
+ @@chart_types[self][chart_type] = block
16
+ end
17
+
18
+ def render(chart_type)
19
+ instance_eval &@@chart_types[self.class][chart_type]
20
+ end
21
+
22
+ protected
23
+
24
+ def values
25
+ source.values
26
+ end
27
+
28
+ def labels
29
+ source.labels
30
+ end
31
+
32
+ def title
33
+ source.title
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ class Playfair
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: playfair
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Chris Dinn
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-24 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email: chrisgdinn@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/playfair.rb
32
+ - lib/playfair/chart.rb
33
+ - lib/playfair/google_chart_renderer.rb
34
+ - lib/playfair/pdf_renderer.rb
35
+ - lib/playfair/renderer.rb
36
+ - lib/playfair/version.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/chrisdinn/playfair
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ hash: 3
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ requirements: []
65
+
66
+ rubyforge_project: "[none]"
67
+ rubygems_version: 1.3.7
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: A Ruby data-visualization library
71
+ test_files: []
72
+