prawn 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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