prawn 0.1.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.
Files changed (120) hide show
  1. data/COPYING +340 -0
  2. data/LICENSE +56 -0
  3. data/README +30 -0
  4. data/Rakefile +83 -0
  5. data/data/fonts/Activa.ttf +0 -0
  6. data/data/fonts/Chalkboard.ttf +0 -0
  7. data/data/fonts/Courier-Bold.afm +342 -0
  8. data/data/fonts/Courier-BoldOblique.afm +342 -0
  9. data/data/fonts/Courier-Oblique.afm +342 -0
  10. data/data/fonts/Courier.afm +342 -0
  11. data/data/fonts/DejaVuSans.ttf +0 -0
  12. data/data/fonts/Dustismo_Roman.ttf +0 -0
  13. data/data/fonts/Helvetica-Bold.afm +2827 -0
  14. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  15. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  16. data/data/fonts/Helvetica.afm +3051 -0
  17. data/data/fonts/MustRead.html +19 -0
  18. data/data/fonts/Symbol.afm +213 -0
  19. data/data/fonts/Times-Bold.afm +2588 -0
  20. data/data/fonts/Times-BoldItalic.afm +2384 -0
  21. data/data/fonts/Times-Italic.afm +2667 -0
  22. data/data/fonts/Times-Roman.afm +2419 -0
  23. data/data/fonts/ZapfDingbats.afm +225 -0
  24. data/data/fonts/comicsans.ttf +0 -0
  25. data/data/fonts/gkai00mp.ttf +0 -0
  26. data/data/images/dice.png +0 -0
  27. data/data/images/pigs.jpg +0 -0
  28. data/data/images/ruport.png +0 -0
  29. data/data/images/ruport_data.dat +0 -0
  30. data/data/images/ruport_transparent.png +0 -0
  31. data/data/images/stef.jpg +0 -0
  32. data/data/shift_jis_text.txt +1 -0
  33. data/examples/addressbook.csv +6 -0
  34. data/examples/alignment.rb +16 -0
  35. data/examples/bounding_boxes.pdf +62 -0
  36. data/examples/bounding_boxes.rb +30 -0
  37. data/examples/canvas.pdf +81 -0
  38. data/examples/canvas.rb +12 -0
  39. data/examples/cell.rb +27 -0
  40. data/examples/currency.csv +1834 -0
  41. data/examples/curves.rb +10 -0
  42. data/examples/fancy_table.rb +48 -0
  43. data/examples/font_size.rb +19 -0
  44. data/examples/hexagon.rb +14 -0
  45. data/examples/image.pdf +0 -0
  46. data/examples/image.rb +23 -0
  47. data/examples/image2.rb +13 -0
  48. data/examples/inline_styles.pdf +117 -0
  49. data/examples/kerning.rb +27 -0
  50. data/examples/line.rb +31 -0
  51. data/examples/multi_page_layout.rb +14 -0
  52. data/examples/on_page_start.rb +17 -0
  53. data/examples/page_geometry.rb +28 -0
  54. data/examples/polygons.rb +16 -0
  55. data/examples/ruport_formatter.rb +47 -0
  56. data/examples/ruport_helpers.rb +17 -0
  57. data/examples/russian_boxes.rb +34 -0
  58. data/examples/simple_text.rb +15 -0
  59. data/examples/simple_text_ttf.rb +16 -0
  60. data/examples/sjis.rb +19 -0
  61. data/examples/table.rb +45 -0
  62. data/examples/table_bench.rb +92 -0
  63. data/examples/text_flow.rb +65 -0
  64. data/examples/utf8.rb +12 -0
  65. data/lib/prawn.rb +33 -0
  66. data/lib/prawn/compatibility.rb +33 -0
  67. data/lib/prawn/document.rb +334 -0
  68. data/lib/prawn/document/bounding_box.rb +253 -0
  69. data/lib/prawn/document/page_geometry.rb +78 -0
  70. data/lib/prawn/document/table.rb +253 -0
  71. data/lib/prawn/document/text.rb +346 -0
  72. data/lib/prawn/errors.rb +33 -0
  73. data/lib/prawn/font.rb +5 -0
  74. data/lib/prawn/font/cmap.rb +59 -0
  75. data/lib/prawn/font/metrics.rb +414 -0
  76. data/lib/prawn/font/wrapping.rb +45 -0
  77. data/lib/prawn/graphics.rb +285 -0
  78. data/lib/prawn/graphics/cell.rb +226 -0
  79. data/lib/prawn/images.rb +241 -0
  80. data/lib/prawn/images/jpg.rb +43 -0
  81. data/lib/prawn/images/png.rb +178 -0
  82. data/lib/prawn/pdf_object.rb +64 -0
  83. data/lib/prawn/reference.rb +47 -0
  84. data/spec/bounding_box_spec.rb +120 -0
  85. data/spec/box_calculation_spec.rb +17 -0
  86. data/spec/document_spec.rb +152 -0
  87. data/spec/graphics_spec.rb +250 -0
  88. data/spec/images_spec.rb +42 -0
  89. data/spec/jpg_spec.rb +25 -0
  90. data/spec/metrics_spec.rb +60 -0
  91. data/spec/pdf_object_spec.rb +102 -0
  92. data/spec/png_spec.rb +35 -0
  93. data/spec/reference_spec.rb +29 -0
  94. data/spec/spec_helper.rb +29 -0
  95. data/spec/table_spec.rb +145 -0
  96. data/spec/text_spec.rb +190 -0
  97. data/vendor/font_ttf/ttf.rb +20 -0
  98. data/vendor/font_ttf/ttf/datatypes.rb +189 -0
  99. data/vendor/font_ttf/ttf/encodings.rb +140 -0
  100. data/vendor/font_ttf/ttf/exceptions.rb +28 -0
  101. data/vendor/font_ttf/ttf/file.rb +290 -0
  102. data/vendor/font_ttf/ttf/fontchunk.rb +77 -0
  103. data/vendor/font_ttf/ttf/table/cmap.rb +408 -0
  104. data/vendor/font_ttf/ttf/table/cvt.rb +49 -0
  105. data/vendor/font_ttf/ttf/table/fpgm.rb +48 -0
  106. data/vendor/font_ttf/ttf/table/gasp.rb +88 -0
  107. data/vendor/font_ttf/ttf/table/glyf.rb +452 -0
  108. data/vendor/font_ttf/ttf/table/head.rb +86 -0
  109. data/vendor/font_ttf/ttf/table/hhea.rb +96 -0
  110. data/vendor/font_ttf/ttf/table/hmtx.rb +98 -0
  111. data/vendor/font_ttf/ttf/table/kern.rb +186 -0
  112. data/vendor/font_ttf/ttf/table/loca.rb +75 -0
  113. data/vendor/font_ttf/ttf/table/maxp.rb +81 -0
  114. data/vendor/font_ttf/ttf/table/name.rb +222 -0
  115. data/vendor/font_ttf/ttf/table/os2.rb +172 -0
  116. data/vendor/font_ttf/ttf/table/post.rb +120 -0
  117. data/vendor/font_ttf/ttf/table/prep.rb +27 -0
  118. data/vendor/font_ttf/ttf/table/vhea.rb +45 -0
  119. data/vendor/font_ttf/ttf/table/vmtx.rb +36 -0
  120. metadata +180 -0
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ # wrapping.rb : Implementation of naive text wrap
4
+ #
5
+ # Copyright May 2008, Michael Daines. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+ module Prawn
9
+ module Font #:nodoc:
10
+ module Wrapping #:nodoc:
11
+
12
+ # TODO: Replace with TeX optimal algorithm
13
+ def naive_wrap(string, line_width, font_size, options = {})
14
+ output = ""
15
+ string.lines.each do |line|
16
+ accumulated_width = 0
17
+ segments = line.scan(/\S+|\s+/)
18
+
19
+ segments.each do |segment|
20
+ segment_width = string_width(segment, font_size,
21
+ :kerning => options[:kerning])
22
+
23
+ if (accumulated_width + segment_width).round > line_width.round
24
+ output << "\n"
25
+
26
+ if segment =~ /\s/
27
+ accumulated_width = 0
28
+ else
29
+ output << segment
30
+ accumulated_width = segment_width
31
+ end
32
+ else
33
+ output << segment
34
+ accumulated_width += segment_width
35
+ end
36
+ end
37
+ end
38
+
39
+ output
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,285 @@
1
+ # encoding: utf-8
2
+
3
+ # graphics.rb : Implements PDF drawing primitives
4
+ #
5
+ # Copyright April 2008, Gregory Brown. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ require "enumerator"
10
+ require "prawn/graphics/cell"
11
+
12
+ module Prawn
13
+
14
+ # Implements the drawing facilities for Prawn::Document.
15
+ # Use this to draw the most beautiful imaginable things.
16
+ #
17
+ # This file lifts and modifies several of PDF::Writer's graphics functions
18
+ # ruby-pdf.rubyforge.org
19
+ #
20
+ module Graphics
21
+
22
+
23
+ #######################################################################
24
+ # Low level drawing operations must translate to absolute coords! #
25
+ #######################################################################
26
+
27
+ # Moves the drawing position to a given point. The point can be
28
+ # specified as a tuple or a flattened argument list
29
+ #
30
+ # pdf.move_to [100,50]
31
+ # pdf.move_to(100,50)
32
+ #
33
+ def move_to(*point)
34
+ x,y = translate(point)
35
+ add_content("%.3f %.3f m" % [ x, y ])
36
+ end
37
+
38
+ # Draws a line from the current drawing position to the specified point.
39
+ # The destination may be described as a tuple or a flattened list:
40
+ #
41
+ # pdf.line_to [50,50]
42
+ # pdf.line_to(50,50)
43
+ #
44
+ def line_to(*point)
45
+ x,y = translate(point)
46
+ add_content("%.3f %.3f l" % [ x, y ])
47
+ end
48
+
49
+ # Draws a Bezier curve from the current drawing position to the
50
+ # specified point, bounded by two additional points.
51
+ #
52
+ # pdf.curve_to [100,100], :bounds => [[90,90],[75,75]]
53
+ #
54
+ def curve_to(dest,options={})
55
+ options[:bounds] or raise Prawn::Errors::InvalidGraphicsPath,
56
+ "Bounding points for bezier curve must be specified "+
57
+ "as :bounds => [[x1,y1],[x2,y2]]"
58
+
59
+ curve_points = (options[:bounds] << dest).map { |e| translate(e) }
60
+ add_content("%.3f %.3f %.3f %.3f %.3f %.3f c" %
61
+ curve_points.flatten )
62
+ end
63
+
64
+ # Draws a rectangle given <tt>point</tt>, <tt>width</tt> and
65
+ # <tt>height</tt>. The rectangle is bounded by its upper-left corner.
66
+ #
67
+ # pdf.rectangle [300,300], 100, 200
68
+ #
69
+ def rectangle(point,width,height)
70
+ x,y = translate(point)
71
+ add_content("%.3f %.3f %.3f %.3f re" % [ x, y - height, width, height ])
72
+ end
73
+
74
+ ###########################################################
75
+ # Higher level functions: May use relative coords #
76
+ ###########################################################
77
+
78
+ # Sets line thickness to the <tt>width</tt> specified.
79
+ #
80
+ def line_width=(width)
81
+ @line_width = width
82
+ add_content("#{width} w")
83
+ end
84
+
85
+ # The current line thickness
86
+ #
87
+ def line_width
88
+ @line_width || 1
89
+ end
90
+
91
+ # Draws a line from one point to another. Points may be specified as
92
+ # tuples or flattened argument list:
93
+ #
94
+ # pdf.line [100,100], [200,250]
95
+ # pdf.line(100,100,200,250)
96
+ #
97
+ def line(*points)
98
+ x0,y0,x1,y1 = points.flatten
99
+ move_to(x0, y0)
100
+ line_to(x1, y1)
101
+ end
102
+
103
+ # Draws a horizontal line from <tt>x1</tt> to <tt>x2</tt> at the
104
+ # current <tt>y</tt> position.
105
+ #
106
+ def horizontal_line(x1,x2)
107
+ line(x1,y,x2,y)
108
+ end
109
+
110
+ # Draws a horizontal line from the left border to the right border of the
111
+ # bounding box at the current <tt>y</tt> position.
112
+ #
113
+ def horizontal_rule
114
+ horizontal_line(bounds.left, bounds.right)
115
+ end
116
+
117
+ # Draws a vertical line at the given x position from y1 to y2.
118
+ #
119
+ def vertical_line_at(x,y1,y2)
120
+ line(x,y1,x,y2)
121
+ end
122
+
123
+ # Draws a Bezier curve between two points, bounded by two additional
124
+ # points
125
+ #
126
+ # pdf.curve [50,100], [100,100], :bounds => [[90,90],[75,75]]
127
+ #
128
+ def curve(origin,dest, options={})
129
+ move_to *origin
130
+ curve_to(dest,options)
131
+ end
132
+
133
+ # This constant is used to approximate a symmetrical arc using a cubic
134
+ # Bezier curve.
135
+ #
136
+ KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0)
137
+
138
+ # Draws a circle of radius <tt>:radius</tt> with the centre-point at <tt>point</tt>
139
+ # as a complete subpath. The drawing point will be moved to the
140
+ # centre-point upon completion of the drawing the circle.
141
+ #
142
+ # pdf.circle_at [100,100], :radius => 25
143
+ #
144
+ def circle_at(point, options)
145
+ x,y = point
146
+ ellipse_at [x, y], options[:radius]
147
+ end
148
+
149
+ # Draws an ellipse of +x+ radius <tt>r1</tt> and +y+ radius <tt>r2</tt>
150
+ # with the centre-point at <tt>point</tt> as a complete subpath. The
151
+ # drawing point will be moved to the centre-point upon completion of the
152
+ # drawing the ellipse.
153
+ #
154
+ # # draws an ellipse with x-radius 25 and y-radius 50
155
+ # pdf.ellipse_at [100,100], 25, 50
156
+ #
157
+ def ellipse_at(point, r1, r2 = r1)
158
+ x, y = point
159
+ l1 = r1 * KAPPA
160
+ l2 = r2 * KAPPA
161
+
162
+ move_to(x + r1, y)
163
+
164
+ # Upper right hand corner
165
+ curve_to [x, y + r2],
166
+ :bounds => [[x + r1, y + l1], [x + l2, y + r2]]
167
+
168
+ # Upper left hand corner
169
+ curve_to [x - r1, y],
170
+ :bounds => [[x - l2, y + r2], [x - r1, y + l1]]
171
+
172
+ # Lower left hand corner
173
+ curve_to [x, y - r2],
174
+ :bounds => [[x - r1, y - l1], [x - l2, y - r2]]
175
+
176
+ # Lower right hand corner
177
+ curve_to [x + r1, y],
178
+ :bounds => [[x + l2, y - r2], [x + r1, y - l1]]
179
+
180
+ move_to(x, y)
181
+ end
182
+
183
+ # Draws a polygon from the specified points.
184
+ #
185
+ # # draws a snazzy triangle
186
+ # pdf.polygon [100,100], [100,200], [200,200]
187
+ #
188
+ def polygon(*points)
189
+ move_to points[0]
190
+ (points << points[0]).each_cons(2) do |p1,p2|
191
+ line_to(*p2)
192
+ end
193
+ end
194
+
195
+ # Sets the fill color. 6 digit HTML color codes are used.
196
+ #
197
+ # pdf.fill_color "f0ffc1"
198
+ #
199
+ def fill_color(color=nil)
200
+ return @fill_color unless color
201
+ @fill_color = color
202
+ set_fill_color
203
+ end
204
+
205
+ alias_method :fill_color=, :fill_color
206
+
207
+ # Sets the line stroking color. 6 digit HTML color codes are used.
208
+ #
209
+ # pdf.stroke_color "cc2fde"
210
+ #
211
+ def stroke_color(color=nil)
212
+ return @stroke_color unless color
213
+ @stroke_color = color
214
+ set_stroke_color
215
+ end
216
+
217
+ alias_method :stroke_color=, :stroke_color
218
+
219
+ # Strokes and closes the current path.
220
+ #
221
+ def stroke
222
+ yield if block_given?
223
+ add_content "S"
224
+ end
225
+
226
+ # Fills and closes the current path
227
+ #
228
+ def fill
229
+ yield if block_given?
230
+ add_content "f"
231
+ end
232
+
233
+ # Fills, strokes, and closes the current path.
234
+ #
235
+ def fill_and_stroke
236
+ yield if block_given?
237
+ add_content "b"
238
+ end
239
+
240
+ # Provides the following shortcuts:
241
+ #
242
+ # stroke_some_method(*args) #=> some_method(*args); stroke
243
+ # fill_some_method(*args) #=> some_method(*args); fill
244
+ #
245
+ def method_missing(id,*args,&block)
246
+ case(id.to_s)
247
+ when /^fill_and_stroke_(.*)/
248
+ send($1,*args,&block); fill_and_stroke
249
+ when /^stroke_(.*)/
250
+ send($1,*args,&block); stroke
251
+ when /^fill_(.*)/
252
+ send($1,*args,&block); fill
253
+ else
254
+ super
255
+ end
256
+ end
257
+
258
+ private
259
+
260
+ def translate(*point)
261
+ x,y = point.flatten
262
+ [@bounding_box.absolute_left + x, @bounding_box.absolute_bottom + y]
263
+ end
264
+
265
+ def set_fill_color
266
+ r,g,b = [@fill_color[0..1], @fill_color[2..3], @fill_color[4..5]].
267
+ map { |e| e.to_i(16) }
268
+ add_content "%.3f %.3f %.3f rg" % [r / 255.0, g / 255.0, b / 255.0]
269
+ end
270
+
271
+ def set_stroke_color
272
+ r,g,b = [@stroke_color[0..1], @stroke_color[2..3], @stroke_color[4..5]].
273
+ map { |e| e.to_i(16) }
274
+ add_content "%.3f %.3f %.3f RG" % [r / 255.0, g / 255.0, b / 255.0]
275
+ end
276
+
277
+ def update_colors
278
+ @fill_color ||= "000000"
279
+ @stroke_color ||= "000000"
280
+ set_fill_color
281
+ set_stroke_color
282
+ end
283
+
284
+ end
285
+ end
@@ -0,0 +1,226 @@
1
+ # encoding: utf-8
2
+
3
+ module Prawn
4
+
5
+ class Document
6
+ # Builds and renders a Graphics::Cell. A cell is essentially a
7
+ # special-purpose bounding box designed for flowing text within a bordered
8
+ # area. For available options, see Graphics::Cell#new.
9
+ #
10
+ # Prawn::Document.generate("cell.pdf") do
11
+ # cell [100,500],
12
+ # :width => 200,
13
+ # :text => "The rain in Spain falls mainly on the plains"
14
+ # end
15
+ #
16
+ def cell(point, options={})
17
+ Prawn::Graphics::Cell.new(
18
+ options.merge(:document => self, :point => point)).draw
19
+ end
20
+ end
21
+
22
+ module Graphics
23
+ # A cell is a special-purpose bounding box designed to flow text within a
24
+ # bordered area. This is used by Prawn's Document::Table implementation but
25
+ # can also be used standalone for drawing text boxes via Document#cell
26
+ #
27
+ class Cell
28
+
29
+ # Creates a new cell object. Generally used indirectly via Document#cell
30
+ #
31
+ # Of the available options listed below, <tt>:point</tt>, <tt>:width</tt>,
32
+ # and <tt>:text</tt> must be provided. If you are not using the
33
+ # Document#cell shortcut, the <tt>:document</tt> must also be provided.
34
+ #
35
+ # <tt>:point</tt>:: Absolute [x,y] coordinate of the top-left corner of the cell.
36
+ # <tt>:document</tt>:: The Prawn::Document object to render on.
37
+ # <tt>:text</tt>:: The text to be flowed within the cell
38
+ # <tt>:width</tt>:: The width in PDF points of the cell.
39
+ # <tt>:border</tt>:: The border line width. If omitted, no border will be drawn.
40
+ # <tt>:horizontal_padding</tt>:: The horizontal padding in PDF points
41
+ # <tt>:vertical_padding</tt>:: The vertical padding in PDF points
42
+ # <tt>:padding</tt>:: Overrides both horizontal and vertical padding
43
+ # <tt>:border_style</tt>:: One of <tt>:all</tt>, <tt>:no_top</tt>, <tt>:no_bottom</tt>, <tt>:sides</tt>
44
+ # <tt>:align</tt>:: One of <tt>:left</tt>, <tt>:right</tt>, <tt>:center</tt>
45
+ #
46
+ def initialize(options={})
47
+ @point = options[:point]
48
+ @document = options[:document]
49
+ @text = options[:text].to_s
50
+ @width = options[:width]
51
+ @border = options[:border] || 1
52
+ @border_style = options[:border_style] || :all
53
+ @background_color = options[:background_color]
54
+ @align = options[:align] || :left
55
+
56
+ @horizontal_padding = options[:horizontal_padding] || 0
57
+ @vertical_padding = options[:vertical_padding] || 0
58
+
59
+ if options[:padding]
60
+ @horizontal_padding = @vertical_padding = options[:padding]
61
+ end
62
+ end
63
+
64
+ attr_accessor :point, :border_style, :border, :background_color,
65
+ :document, :horizontal_padding, :vertical_padding,
66
+ :align
67
+ attr_writer :height, :width #:nodoc:
68
+
69
+ # Returns the cell's text as a string.
70
+ #
71
+ def to_s
72
+ @text
73
+ end
74
+
75
+ # The width of the text area excluding the horizonal padding
76
+ #
77
+ def text_area_width
78
+ width - 2*@horizontal_padding
79
+ end
80
+
81
+ # The width of the cell in PDF points
82
+ #
83
+ def width
84
+ @width || (@document.font_metrics.string_width(@text,
85
+ @document.font_size)) + 2*@horizontal_padding
86
+ end
87
+
88
+ # The height of the cell in PDF points
89
+ #
90
+ def height
91
+ @height || text_area_height + 2*@vertical_padding
92
+ end
93
+
94
+ # The height of the text area excluding the vertical padding
95
+ #
96
+ def text_area_height
97
+ @document.font_metrics.string_height(@text,
98
+ :font_size => @document.font_size,
99
+ :line_width => text_area_width)
100
+ end
101
+
102
+ # Draws the cell onto the PDF document
103
+ #
104
+ def draw
105
+ rel_point = @point
106
+
107
+ if @background_color
108
+ @document.mask(:fill_color) do
109
+ @document.fill_color @background_color
110
+ h = borders.include?(:bottom) ? height - border : height + border / 2.0
111
+ @document.fill_rectangle [rel_point[0] + border / 2.0,
112
+ rel_point[1] - border / 2.0 ],
113
+ width - border, h
114
+ end
115
+ end
116
+
117
+ if @border > 0
118
+ @document.mask(:line_width) do
119
+ @document.line_width = @border
120
+
121
+ if borders.include?(:left)
122
+ @document.stroke_line [rel_point[0], rel_point[1] + (@border / 2.0)],
123
+ [rel_point[0], rel_point[1] - height - @border / 2.0 ]
124
+ end
125
+
126
+ if borders.include?(:right)
127
+ @document.stroke_line(
128
+ [rel_point[0] + width, rel_point[1] + (@border / 2.0)],
129
+ [rel_point[0] + width, rel_point[1] - height - @border / 2.0] )
130
+ end
131
+
132
+ if borders.include?(:top)
133
+ @document.stroke_line(
134
+ [ rel_point[0] + @border / 2.0, rel_point[1] ],
135
+ [ rel_point[0] - @border / 2.0 + width, rel_point[1] ])
136
+ end
137
+
138
+ if borders.include?(:bottom)
139
+ @document.stroke_line [rel_point[0], rel_point[1] - height ],
140
+ [rel_point[0] + width, rel_point[1] - height]
141
+ end
142
+
143
+ end
144
+
145
+ borders
146
+
147
+ end
148
+
149
+ @document.bounding_box( [@point[0] + @horizontal_padding,
150
+ @point[1] - @vertical_padding],
151
+ :width => text_area_width,
152
+ :height => height - @vertical_padding) do
153
+ @document.text @text, :align => @align
154
+ end
155
+ end
156
+
157
+ private
158
+
159
+ def borders
160
+ @borders ||= case @border_style
161
+ when :all
162
+ [:top,:left,:right,:bottom]
163
+ when :sides
164
+ [:left,:right]
165
+ when :no_top
166
+ [:left,:right,:bottom]
167
+ when :no_bottom
168
+ [:left,:right,:top]
169
+ end
170
+ end
171
+
172
+ end
173
+
174
+ class CellBlock #:nodoc:
175
+
176
+ # Not sure if this class is something I want to expose in the public API.
177
+
178
+ def initialize(document)
179
+ @document = document
180
+ @cells = []
181
+ @width = 0
182
+ @height = 0
183
+ end
184
+
185
+ attr_reader :width, :height
186
+ attr_accessor :background_color
187
+
188
+ def <<(cell)
189
+ @cells << cell
190
+ @height = cell.height if cell.height > @height
191
+ @width += cell.width
192
+ self
193
+ end
194
+
195
+ def draw
196
+ y = @document.y
197
+ x = @document.bounds.absolute_left
198
+
199
+ @cells.each do |e|
200
+ e.point = [x - @document.bounds.absolute_left,
201
+ y - @document.bounds.absolute_bottom]
202
+ e.height = @height
203
+ e.background_color ||= @background_color
204
+ e.draw
205
+ x += e.width
206
+ end
207
+
208
+ @document.y = y - @height
209
+ end
210
+
211
+ def border
212
+ @cells[0].border
213
+ end
214
+
215
+ def border_style=(s)
216
+ @cells.each { |e| e.border_style = s }
217
+ end
218
+
219
+ def border_style
220
+ @cells[0].border_style
221
+ end
222
+
223
+ end
224
+ end
225
+
226
+ end