mack-pdf_writer 0.8.1 → 0.8.2
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/gems/archive-tar-minitar-0.5.2/bin/minitar +27 -0
- data/lib/gems/archive-tar-minitar-0.5.2/lib/archive/tar/minitar/command.rb +814 -0
- data/lib/gems/archive-tar-minitar-0.5.2/lib/archive/tar/minitar.rb +979 -0
- data/lib/gems/color-1.4.0/lib/color/cmyk.rb +281 -0
- data/lib/gems/color-1.4.0/lib/color/css.rb +30 -0
- data/lib/gems/color-1.4.0/lib/color/grayscale.rb +214 -0
- data/lib/gems/color-1.4.0/lib/color/hsl.rb +223 -0
- data/lib/gems/color-1.4.0/lib/color/palette/adobecolor.rb +274 -0
- data/lib/gems/color-1.4.0/lib/color/palette/gimp.rb +118 -0
- data/lib/gems/color-1.4.0/lib/color/palette/monocontrast.rb +182 -0
- data/lib/gems/color-1.4.0/lib/color/palette.rb +18 -0
- data/lib/gems/color-1.4.0/lib/color/rgb/metallic.rb +45 -0
- data/lib/gems/color-1.4.0/lib/color/rgb-colors.rb +357 -0
- data/lib/gems/color-1.4.0/lib/color/rgb.rb +455 -0
- data/lib/gems/color-1.4.0/lib/color/yiq.rb +86 -0
- data/lib/gems/color-1.4.0/lib/color.rb +147 -0
- data/lib/gems/pdf-writer-1.1.8/bin/techbook +24 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/charts/stddev.rb +430 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/charts.rb +13 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/math.rb +108 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/quickref.rb +332 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/simpletable.rb +947 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/techbook.rb +901 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/arc4.rb +63 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fontmetrics.rb +203 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Courier-Bold.afm +342 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Courier-BoldOblique.afm +342 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Courier-Oblique.afm +342 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Courier.afm +342 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Helvetica-Bold.afm +2827 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Helvetica-BoldOblique.afm +2827 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Helvetica-Oblique.afm +3051 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Helvetica.afm +3051 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/MustRead.html +19 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Symbol.afm +213 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Times-Bold.afm +2588 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Times-BoldItalic.afm +2384 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Times-Italic.afm +2667 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/Times-Roman.afm +2419 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/fonts/ZapfDingbats.afm +225 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/graphics/imageinfo.rb +365 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/graphics.rb +813 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/lang/en.rb +99 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/lang.rb +43 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/action.rb +35 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/annotation.rb +42 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/catalog.rb +39 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/contents.rb +65 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/destination.rb +40 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/encryption.rb +53 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/font.rb +72 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/fontdescriptor.rb +34 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/fontencoding.rb +40 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/image.rb +304 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/info.rb +51 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/outline.rb +30 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/outlines.rb +30 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/page.rb +195 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/pages.rb +115 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/procset.rb +46 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object/viewerpreferences.rb +74 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/object.rb +23 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/ohash.rb +58 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/oreader.rb +25 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/state.rb +48 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer/strokestyle.rb +138 -0
- data/lib/gems/pdf-writer-1.1.8/lib/pdf/writer.rb +2729 -0
- data/lib/gems/transaction-simple-1.4.0/lib/transaction/simple/group.rb +146 -0
- data/lib/gems/transaction-simple-1.4.0/lib/transaction/simple/threadsafe/group.rb +36 -0
- data/lib/gems/transaction-simple-1.4.0/lib/transaction/simple/threadsafe.rb +68 -0
- data/lib/gems/transaction-simple-1.4.0/lib/transaction/simple.rb +486 -0
- data/lib/gems.rb +13 -0
- data/lib/mack-pdf_writer.rb +2 -0
- metadata +111 -16
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# PDF::Writer for Ruby.
|
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
|
7
|
+
# for full licensing information.
|
|
8
|
+
#
|
|
9
|
+
# $Id: stddev.rb 186 2007-12-10 22:58:48Z sandal $
|
|
10
|
+
#++
|
|
11
|
+
require 'pdf/writer'
|
|
12
|
+
require 'pdf/charts'
|
|
13
|
+
require 'ostruct'
|
|
14
|
+
|
|
15
|
+
# Creates a standard deviation chart. This is a type of chart that is
|
|
16
|
+
# effective for the display of survey results or other data that can
|
|
17
|
+
# easily be measured in terms of the average and the standard deviation
|
|
18
|
+
# from that average.
|
|
19
|
+
#
|
|
20
|
+
# The scale of responses is the vertical scale; the average data points
|
|
21
|
+
# and standard deviation values are the horizontal scale.
|
|
22
|
+
class PDF::Charts::StdDev
|
|
23
|
+
|
|
24
|
+
# A data element.
|
|
25
|
+
DataPoint = Struct.new(:label, :average, :stddev)
|
|
26
|
+
|
|
27
|
+
# A label for displaying the scale (vertical) of data in the dataset or
|
|
28
|
+
# the data set identifiers.
|
|
29
|
+
class Label
|
|
30
|
+
def initialize
|
|
31
|
+
yield self if block_given?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# The height of the label, in PDF user units. Ignored for scale
|
|
35
|
+
# labels.
|
|
36
|
+
attr_accessor :height
|
|
37
|
+
# The background color of the label. Ignored for scale labels.
|
|
38
|
+
attr_accessor :background_color
|
|
39
|
+
# The text color of the label.
|
|
40
|
+
attr_accessor :text_color
|
|
41
|
+
# The text size, in points, of the label.
|
|
42
|
+
attr_accessor :text_size
|
|
43
|
+
# The padding of the label. Only used for scale labels.
|
|
44
|
+
attr_accessor :pad
|
|
45
|
+
# The decimal precision of the label. Only used for scale labels.
|
|
46
|
+
attr_accessor :decimal_precision
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The scale of the dataset.
|
|
50
|
+
class Scale
|
|
51
|
+
def initialize(args = { })
|
|
52
|
+
@range = args[:range]
|
|
53
|
+
@step = args[:step]
|
|
54
|
+
@style = args[:style]
|
|
55
|
+
@show_labels = false
|
|
56
|
+
|
|
57
|
+
yield self if block_given?
|
|
58
|
+
|
|
59
|
+
raise TypeError, PDF::Lange[:charts_stddev_scale_norange] if @range.nil?
|
|
60
|
+
raise TypeError, PDF::Lange[:charts_stddev_scale_nostep] if @step.nil?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Range of the scale. This should be a Range object.
|
|
64
|
+
attr_accessor :range
|
|
65
|
+
# The lower end of the range of the scale. The scale range may be
|
|
66
|
+
# modified by changing this value.
|
|
67
|
+
attr_accessor :first
|
|
68
|
+
def first #:nodoc:
|
|
69
|
+
@range.first
|
|
70
|
+
end
|
|
71
|
+
def first=(ff) #:nodoc:
|
|
72
|
+
@range = (ff..@range.last)
|
|
73
|
+
end
|
|
74
|
+
# The upper end of the range of the scale. The scale range may be
|
|
75
|
+
# modified by changing this value.
|
|
76
|
+
attr_accessor :last
|
|
77
|
+
def last #:nodoc:
|
|
78
|
+
@range.last
|
|
79
|
+
end
|
|
80
|
+
def last=(ll) #:nodoc:
|
|
81
|
+
@range = (@range.first..ll)
|
|
82
|
+
end
|
|
83
|
+
# Defines the step of the scale. Each step represents a vertical
|
|
84
|
+
# position on the chart.
|
|
85
|
+
attr_accessor :step
|
|
86
|
+
# Defines the line style for the scale on the chart. If this is unset
|
|
87
|
+
# (+nil+), there will be no horizontal marks across the chart for the
|
|
88
|
+
# steps of the scale.
|
|
89
|
+
attr_accessor :style
|
|
90
|
+
# Shows the scale labels if +true+.
|
|
91
|
+
attr_accessor :show_labels
|
|
92
|
+
# Defines the label options.
|
|
93
|
+
attr_accessor :label
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# This is any line that will be drawn; this is a combination of the line
|
|
97
|
+
# style (which must be a PDF::Writer::StrokeStyle object) and a color.
|
|
98
|
+
class Marker
|
|
99
|
+
def initialize
|
|
100
|
+
yield self if block_given?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# The stroke style of the marker.
|
|
104
|
+
attr_accessor :style
|
|
105
|
+
# The stroke color of the marker.
|
|
106
|
+
attr_accessor :color
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def initialize
|
|
110
|
+
@data = []
|
|
111
|
+
|
|
112
|
+
@scale = Scale.new do |scale|
|
|
113
|
+
scale.range = 0..6
|
|
114
|
+
scale.step = 1
|
|
115
|
+
scale.style = PDF::Writer::StrokeStyle.new(0.25)
|
|
116
|
+
scale.show_labels = false
|
|
117
|
+
scale.label = Label.new do |label|
|
|
118
|
+
label.text_size = 8
|
|
119
|
+
label.text_color = Color::RGB::Black
|
|
120
|
+
label.pad = 2
|
|
121
|
+
label.decimal_precision = 1
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
@leading_gap = 10
|
|
125
|
+
@show_labels = true
|
|
126
|
+
@label = Label.new do |label|
|
|
127
|
+
label.height = 25
|
|
128
|
+
label.background_color = Color::RGB::Black
|
|
129
|
+
label.text_color = Color::RGB::White
|
|
130
|
+
label.text_size = 12
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
@outer_borders = Marker.new do |marker|
|
|
134
|
+
marker.style = PDF::Writer::StrokeStyle.new(1.5)
|
|
135
|
+
marker.color = Color::RGB::Black
|
|
136
|
+
end
|
|
137
|
+
@inner_borders = nil
|
|
138
|
+
|
|
139
|
+
@dot = Marker.new do |marker|
|
|
140
|
+
marker.style = PDF::Writer::StrokeStyle.new(5)
|
|
141
|
+
marker.color = Color::RGB::Black
|
|
142
|
+
end
|
|
143
|
+
@bar = Marker.new do |marker|
|
|
144
|
+
marker.style = PDF::Writer::StrokeStyle.new(0.5)
|
|
145
|
+
marker.color = Color::RGB::Black
|
|
146
|
+
end
|
|
147
|
+
@upper_crossbar = Marker.new do |marker|
|
|
148
|
+
marker.style = PDF::Writer::StrokeStyle.new(1)
|
|
149
|
+
marker.color = Color::RGB::Black
|
|
150
|
+
end
|
|
151
|
+
@lower_crossbar = Marker.new do |marker|
|
|
152
|
+
marker.style = PDF::Writer::StrokeStyle.new(1)
|
|
153
|
+
marker.color = Color::RGB::Black
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
@height = 200
|
|
157
|
+
@maximum_width = 500
|
|
158
|
+
@datapoint_width = 35
|
|
159
|
+
|
|
160
|
+
yield self if block_given?
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# The data used to generate the standard deviation chart. This is an
|
|
164
|
+
# array of DataPoint objects, each containing a +label+, an +average+,
|
|
165
|
+
# and the +stddev+ (standard deviation) from that average.
|
|
166
|
+
attr_reader :data
|
|
167
|
+
# The scale of the chart. All values must be within this range. This
|
|
168
|
+
# will be a Scale object. It defaults to a scale of 0..6 with a step of
|
|
169
|
+
# 1.
|
|
170
|
+
attr_accessor :scale
|
|
171
|
+
|
|
172
|
+
# The minimum gap between the chart and the bottom of the page, in
|
|
173
|
+
# PDF user units.
|
|
174
|
+
attr_accessor :leading_gap
|
|
175
|
+
|
|
176
|
+
# This will be +true+ if labels are to be displayed.
|
|
177
|
+
attr_accessor :show_labels
|
|
178
|
+
# The label style of the labels if they are displayed. This must be a
|
|
179
|
+
# PDF::Charts::StdDev::Label object.
|
|
180
|
+
attr_accessor :label
|
|
181
|
+
|
|
182
|
+
# The inner border style. If +nil+, no inner borders are drawn. This is
|
|
183
|
+
# a PDF::Charts::StdDev::Marker object.
|
|
184
|
+
attr_accessor :inner_borders
|
|
185
|
+
# The outer border style. If +nil+, no inner borders are drawn. This is
|
|
186
|
+
# a PDF::Charts::StdDev::Marker object.
|
|
187
|
+
attr_accessor :outer_borders
|
|
188
|
+
|
|
189
|
+
# The dot marker. A filled circle will be drawn with this information.
|
|
190
|
+
# If +nil+, the dot will not be drawn. This is a
|
|
191
|
+
# PDF::Charts::StdDev::Marker object.
|
|
192
|
+
attr_accessor :dot
|
|
193
|
+
# The standard deviation bar. A line will be drawn through the dot
|
|
194
|
+
# marker (if drawn) from the upper to lower standard deviation.
|
|
195
|
+
# If +nil+, the line will not be drawn. This is a
|
|
196
|
+
# PDF::Charts::StdDev::Marker object.
|
|
197
|
+
attr_accessor :bar
|
|
198
|
+
# The upper crossbar. A line will be drawn across the top of the
|
|
199
|
+
# standard deviation bar to the width of the dot marker. If #dot is
|
|
200
|
+
# +nil+, then the line will be twice as wide as it is thick. If +nil+,
|
|
201
|
+
# the upper crossbar will not be drawn. This is a
|
|
202
|
+
# PDF::Charts::StdDev::Marker object.
|
|
203
|
+
attr_accessor :upper_crossbar
|
|
204
|
+
# The lower crossbar. A line will be drawn across the bottom of the
|
|
205
|
+
# standard deviation bar to the width of the dot marker. If #dot is
|
|
206
|
+
# +nil+, then the line will be twice as wide as it is thick. If +nil+,
|
|
207
|
+
# the lower crossbar will not be drawn. This is a
|
|
208
|
+
# PDF::Charts::StdDev::Marker object.
|
|
209
|
+
attr_accessor :lower_crossbar
|
|
210
|
+
|
|
211
|
+
# The height of the chart in PDF user units. Default 200 units.
|
|
212
|
+
attr_accessor :height
|
|
213
|
+
# The maximum width of the chart in PDF user units. Default 500 units.
|
|
214
|
+
attr_accessor :maximum_width
|
|
215
|
+
# The width of a single datapoint.
|
|
216
|
+
attr_accessor :datapoint_width
|
|
217
|
+
|
|
218
|
+
# Draw the standard deviation chart on the supplied PDF document.
|
|
219
|
+
def render_on(pdf)
|
|
220
|
+
raise TypeError, PDF::Writer::Lang[:charts_stddev_data_empty] if @data.empty?
|
|
221
|
+
data = @data.dup
|
|
222
|
+
leftover_data = nil
|
|
223
|
+
|
|
224
|
+
loop do
|
|
225
|
+
# Set up the scale information.
|
|
226
|
+
scale = []
|
|
227
|
+
|
|
228
|
+
(@scale.first + @scale.step).step(@scale.last, @scale.step) do |ii|
|
|
229
|
+
scale << "%01.#{@scale.label.decimal_precision}f" % ii
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
scales = PDF::Writer::OHash.new
|
|
233
|
+
scale.each_with_index do |gg, ii|
|
|
234
|
+
scales[ii] = OpenStruct.new
|
|
235
|
+
scales[ii].value = gg
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Add information about the scales' locations to the scales
|
|
239
|
+
# hash. Note that the count is one smaller than it should be, so we're
|
|
240
|
+
# increasing it. The first scale is the bottom of the chart.
|
|
241
|
+
scale_count = scale.size + 1
|
|
242
|
+
|
|
243
|
+
label_height_adjuster = 0
|
|
244
|
+
label_height_adjuster = @label.height if @show_labels
|
|
245
|
+
|
|
246
|
+
chart_area_height = @height - label_height_adjuster
|
|
247
|
+
scale_height = chart_area_height / scale_count.to_f
|
|
248
|
+
|
|
249
|
+
scales.each_key do |index|
|
|
250
|
+
this_height = scale_height * (index + 1) + @label.height
|
|
251
|
+
scales[index].line_height = this_height
|
|
252
|
+
if @scale.show_labels
|
|
253
|
+
scales[index].label_height = this_height -
|
|
254
|
+
(@scale.label.text_size / 3.0)
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# How many sections do we need in this chart, and how wide will it
|
|
259
|
+
# need to be?
|
|
260
|
+
chunk_width = @datapoint_width
|
|
261
|
+
num_chunks = data.size
|
|
262
|
+
widest_scale_label = 0
|
|
263
|
+
|
|
264
|
+
if @scale.show_labels
|
|
265
|
+
scales.each_value do |scale|
|
|
266
|
+
this_width = pdf.text_width(scale.value, @scale.label.text_size)
|
|
267
|
+
widest_scale_label = this_width if this_width > widest_scale_label
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
chart_width = chunk_width * num_chunks
|
|
272
|
+
total_width = chart_width + widest_scale_label + @scale.label.pad
|
|
273
|
+
|
|
274
|
+
# What happens if the projected width of the chart is too big?
|
|
275
|
+
# Figure out how to break the chart in pieces.
|
|
276
|
+
if total_width > @maximum_width
|
|
277
|
+
max_column_count = 0
|
|
278
|
+
base_width = widest_scale_label + @scale.label.pad
|
|
279
|
+
(1..(num_chunks + 1)).each do |ii|
|
|
280
|
+
if (base_width + (ii * chunk_width)) > @maximum_width
|
|
281
|
+
break
|
|
282
|
+
else
|
|
283
|
+
max_column_count += 1
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
leftover_data = data.slice!(max_column_count, -1)
|
|
288
|
+
|
|
289
|
+
num_chunks = data.size
|
|
290
|
+
chart_width = chunk_width * num_chunks
|
|
291
|
+
total_width = chart_width + widest_scale_label + @scale.label.pad
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
chart_y = pdf.y - @height + @leading_gap
|
|
295
|
+
chart_y += (@outer_borders.style.width * 2.0) if @outer_borders
|
|
296
|
+
|
|
297
|
+
if chart_y < pdf.bottom_margin
|
|
298
|
+
pdf.start_new_page
|
|
299
|
+
chart_y = pdf.y - @height
|
|
300
|
+
chart_y += (@outer_borders.style.width * 2.0) if @outer_borders
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
chart_x = pdf.absolute_x_middle - (total_width / 2.0) + widest_scale_label
|
|
304
|
+
|
|
305
|
+
# Add labels, if needed.
|
|
306
|
+
if @show_labels
|
|
307
|
+
pdf.save_state
|
|
308
|
+
pdf.fill_color! @label.background_color
|
|
309
|
+
# Draw a rectangle for each label
|
|
310
|
+
num_chunks.times do |ii|
|
|
311
|
+
this_x = chart_x + ii * chunk_width
|
|
312
|
+
pdf.rectangle(this_x, chart_y, chunk_width, @label.height).fill
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Add a border above the label rectangle.
|
|
316
|
+
if @outer_borders
|
|
317
|
+
pdf.stroke_style! @outer_borders.style
|
|
318
|
+
pdf.line(chart_x, chart_y + @label.height, chart_x + chart_width, chart_y + @label.height).stroke
|
|
319
|
+
end
|
|
320
|
+
pdf.fill_color! @label.text_color
|
|
321
|
+
|
|
322
|
+
data.each_with_index do |datum, ii|
|
|
323
|
+
label = datum.label.to_s
|
|
324
|
+
label_width = pdf.text_width(label, @label.text_size)
|
|
325
|
+
this_x = chart_x + (ii * chunk_width) + (chunk_width / 2.0) - (label_width / 2.0)
|
|
326
|
+
this_y = chart_y + (@label.height / 2.0) - (@label.text_size / 3.0)
|
|
327
|
+
pdf.add_text(this_x, this_y, label, @label.text_size)
|
|
328
|
+
end
|
|
329
|
+
pdf.restore_state
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
if @inner_borders
|
|
333
|
+
pdf.save_state
|
|
334
|
+
pdf.stroke_color! @inner_borders.color
|
|
335
|
+
pdf.stroke_style! @inner_borders.style
|
|
336
|
+
(num_chunks - 1).times do |ii|
|
|
337
|
+
this_x = chart_x + (ii * chunk_width) + chunk_width
|
|
338
|
+
pdf.line(this_x, chart_y, this_x, chart_y + @height).stroke
|
|
339
|
+
end
|
|
340
|
+
pdf.restore_state
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
pdf.save_state
|
|
344
|
+
if @outer_borders
|
|
345
|
+
pdf.stroke_color! @outer_borders.color
|
|
346
|
+
pdf.stroke_style! @outer_borders.style
|
|
347
|
+
pdf.rectangle(chart_x, chart_y, chart_width, @height).stroke
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
if @scale.style
|
|
351
|
+
pdf.save_state
|
|
352
|
+
pdf.stroke_style! @scale.style
|
|
353
|
+
scales.each_value do |scale|
|
|
354
|
+
this_y = chart_y + scale.line_height
|
|
355
|
+
pdf.line(chart_x, this_y, chart_x + chart_width, this_y).stroke
|
|
356
|
+
end
|
|
357
|
+
pdf.restore_state
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
if @scale.show_labels
|
|
361
|
+
pdf.save_state
|
|
362
|
+
scales.each_value do |scale|
|
|
363
|
+
this_y = chart_y + scale.label_height
|
|
364
|
+
label_width = pdf.text_width(scale.value, @scale.label.text_size)
|
|
365
|
+
this_x = chart_x - label_width - @scale.label.pad
|
|
366
|
+
pdf.fill_color! @scale.label.text_color
|
|
367
|
+
pdf.add_text(this_x, this_y, scale.value, @scale.label.text_size)
|
|
368
|
+
end
|
|
369
|
+
pdf.restore_state
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
data.each_with_index do |datum, ii|
|
|
373
|
+
avg_height = datum.average * scale_height
|
|
374
|
+
stddev_height = datum.stddev * scale_height
|
|
375
|
+
this_y = chart_y + label_height_adjuster + avg_height
|
|
376
|
+
this_x = chart_x + (ii * chunk_width) + (chunk_width / 2.0)
|
|
377
|
+
line_top_y = this_y + (stddev_height / 2.0)
|
|
378
|
+
line_bot_y = this_y - (stddev_height / 2.0)
|
|
379
|
+
|
|
380
|
+
# Plot the dot
|
|
381
|
+
if @dot
|
|
382
|
+
pdf.stroke_color! @dot.color
|
|
383
|
+
pdf.stroke_style! @dot.style
|
|
384
|
+
pdf.circle_at(this_x, this_y, (@dot.style.width / 2.0)).fill
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# Plot the bar
|
|
388
|
+
if @bar
|
|
389
|
+
pdf.stroke_color! @bar.color
|
|
390
|
+
pdf.stroke_style! @bar.style
|
|
391
|
+
pdf.line(this_x, line_top_y, this_x, line_bot_y).stroke
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
# Plot the crossbars
|
|
395
|
+
if @upper_crossbar
|
|
396
|
+
if @dot
|
|
397
|
+
cb_width = @dot.style.width
|
|
398
|
+
else
|
|
399
|
+
cb_width = @upper_crossbar.style.width
|
|
400
|
+
end
|
|
401
|
+
pdf.stroke_color! @upper_crossbar.color
|
|
402
|
+
pdf.stroke_style! @upper_crossbar.style
|
|
403
|
+
pdf.line(this_x - cb_width, line_top_y, this_x + cb_width, line_top_y).stroke
|
|
404
|
+
end
|
|
405
|
+
if @lower_crossbar
|
|
406
|
+
if @dot
|
|
407
|
+
cb_width = @dot.style.width
|
|
408
|
+
else
|
|
409
|
+
cb_width = @lower_crossbar.style.width
|
|
410
|
+
end
|
|
411
|
+
pdf.stroke_color! @lower_crossbar.color
|
|
412
|
+
pdf.stroke_style! @lower_crossbar.style
|
|
413
|
+
|
|
414
|
+
pdf.line(this_x - cb_width, line_bot_y, this_x + cb_width, line_bot_y).stroke
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
pdf.restore_state
|
|
419
|
+
|
|
420
|
+
pdf.y = chart_y
|
|
421
|
+
|
|
422
|
+
break if leftover_data.nil?
|
|
423
|
+
|
|
424
|
+
data = leftover_data
|
|
425
|
+
leftover_data = nil
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
pdf.y
|
|
429
|
+
end
|
|
430
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# PDF::Writer for Ruby.
|
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
|
7
|
+
# for full licensing information.
|
|
8
|
+
#
|
|
9
|
+
# $Id: charts.rb 50 2005-05-16 03:59:21Z austin $
|
|
10
|
+
#++
|
|
11
|
+
# A namespace for charts that can be drawn on PDF::Writer canvases.
|
|
12
|
+
module PDF::Charts
|
|
13
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# PDF::Writer for Ruby.
|
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
|
7
|
+
# for full licensing information.
|
|
8
|
+
#
|
|
9
|
+
# $Id: math.rb 52 2005-05-16 20:44:34Z austin $
|
|
10
|
+
#++
|
|
11
|
+
# Encapsulate some of the mathematical calculations that need to be
|
|
12
|
+
# performed when working with PDF documents. All angles in PDF::Writer are
|
|
13
|
+
# measured in degrees, but all angles in PDF documents are in radians. The
|
|
14
|
+
# standard conversions between radians, degrees, and gradians are
|
|
15
|
+
# provided.
|
|
16
|
+
#
|
|
17
|
+
# As with the Perl implementations of these conversions, they will be
|
|
18
|
+
# wrapped in the range of the target measurement (0..PI2 for radians,
|
|
19
|
+
# 0..360 for degrees, and 0..400 for gradians). To prevent this wrapping,
|
|
20
|
+
# provide a false value for the +wrap+ parameter.
|
|
21
|
+
#
|
|
22
|
+
# To wrap these values manually, use #rad2rad, #deg2deg, or #grad2grad.
|
|
23
|
+
module PDF::Math
|
|
24
|
+
class << self
|
|
25
|
+
PI2 = ::Math::PI * 2.0
|
|
26
|
+
|
|
27
|
+
# One degree of arc measured in terms of radians.
|
|
28
|
+
DR = PI2 / 360.0
|
|
29
|
+
# One radian of arc, measured in terms of degrees.
|
|
30
|
+
RD = 360 / PI2
|
|
31
|
+
# One degree of arc, measured in terms of gradians.
|
|
32
|
+
DG = 400 / 360.0
|
|
33
|
+
# One gradian of arc, measured in terms of degrees.
|
|
34
|
+
GD = 360 / 400.0
|
|
35
|
+
# One radian of arc, measured in terms of gradians.
|
|
36
|
+
RG = 400 / PI2
|
|
37
|
+
# One gradian of arc, measured in terms of radians.
|
|
38
|
+
GR = PI2 / 400.0
|
|
39
|
+
|
|
40
|
+
# Truncate the remainder.
|
|
41
|
+
def remt(num, den)
|
|
42
|
+
num - den * (num / den.to_f).to_i
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Wrap radian values within the range of radians (0..PI2).
|
|
46
|
+
def rad2rad(rad)
|
|
47
|
+
remt(rad, PI2)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Wrap degree values within the range of degrees (0..360).
|
|
51
|
+
def deg2deg(deg)
|
|
52
|
+
remt(deg, 360)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Wrap gradian values within the range of gradians (0..400).
|
|
56
|
+
def grad2grad(grad)
|
|
57
|
+
remt(grad, 400)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Convert degrees to radians. The value will be constrained to the
|
|
61
|
+
# range of radians (0..PI2) unless +wrap+ is false.
|
|
62
|
+
def deg2rad(deg, wrap = true)
|
|
63
|
+
rad = DR * deg
|
|
64
|
+
rad = rad2rad(rad) if wrap
|
|
65
|
+
rad
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Convert degrees to gradians. The value will be constrained to the
|
|
69
|
+
# range of gradians (0..400) unless +wrap+ is false.
|
|
70
|
+
def deg2grad(deg, wrap = true)
|
|
71
|
+
grad = DG * deg
|
|
72
|
+
grad = grad2grad(grad) if wrap
|
|
73
|
+
grad
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Convert radians to degrees. The value will be constrained to the
|
|
77
|
+
# range of degrees (0..360) unless +wrap+ is false.
|
|
78
|
+
def rad2deg(rad, wrap = true)
|
|
79
|
+
deg = RD * rad
|
|
80
|
+
deg = deg2deg(deg) if wrap
|
|
81
|
+
deg
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Convert radians to gradians. The value will be constrained to the
|
|
85
|
+
# range of gradians (0..400) unless +wrap+ is false.
|
|
86
|
+
def rad2grad(rad, wrap = true)
|
|
87
|
+
grad = RG * rad
|
|
88
|
+
grad = grad2grad(grad) if wrap
|
|
89
|
+
grad
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Convert gradians to degrees. The value will be constrained to the
|
|
93
|
+
# range of degrees (0..360) unless +wrap+ is false.
|
|
94
|
+
def grad2deg(grad, wrap = true)
|
|
95
|
+
deg = GD * grad
|
|
96
|
+
deg = deg2deg(deg) if wrap
|
|
97
|
+
deg
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Convert gradians to radians. The value will be constrained to the
|
|
101
|
+
# range of radians (0..PI2) unless +wrap+ is false.
|
|
102
|
+
def grad2rad(grad, wrap = true)
|
|
103
|
+
rad = GR * grad
|
|
104
|
+
rad = rad2rad(rad) if wrap
|
|
105
|
+
rad
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|