pdf_gen 0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/LICENSE +19 -0
  2. data/README.rdoc +189 -0
  3. data/lib/base_region.rb +95 -0
  4. data/lib/caption.rb +78 -0
  5. data/lib/containers/caption_container.rb +15 -0
  6. data/lib/containers/div_container.rb +14 -0
  7. data/lib/containers/image_container.rb +15 -0
  8. data/lib/containers/span_container.rb +14 -0
  9. data/lib/containers/table_container.rb +14 -0
  10. data/lib/data/ds_ar.rb +31 -0
  11. data/lib/data/ds_base.rb +24 -0
  12. data/lib/data/ds_hash.rb +24 -0
  13. data/lib/div.rb +148 -0
  14. data/lib/document.rb +50 -0
  15. data/lib/fixnum.rb +18 -0
  16. data/lib/float.rb +18 -0
  17. data/lib/image.rb +46 -0
  18. data/lib/modules/base_attributes.rb +86 -0
  19. data/lib/modules/canvas.rb +15 -0
  20. data/lib/modules/composite.rb +54 -0
  21. data/lib/pdf_gen.rb +30 -0
  22. data/lib/smart_table.rb +155 -0
  23. data/lib/span.rb +69 -0
  24. data/lib/table.rb +116 -0
  25. data/lib/writer.rb +30 -0
  26. data/samples/border.rb +15 -0
  27. data/samples/div.rb +23 -0
  28. data/samples/div_illustration.rb +64 -0
  29. data/samples/headerfooter.rb +94 -0
  30. data/samples/image.rb +9 -0
  31. data/samples/ruby_logo.jpg +0 -0
  32. data/samples/sampl1_1.png +0 -0
  33. data/samples/sampl1_2.png +0 -0
  34. data/samples/sampl1_3.png +0 -0
  35. data/samples/simple.rb +7 -0
  36. data/samples/smart_table.rb +98 -0
  37. data/samples/span.rb +12 -0
  38. data/samples/span_illustration.rb +41 -0
  39. data/samples/spanindiv_ill.rb +53 -0
  40. data/samples/table.rb +37 -0
  41. data/samples/table_illustration.rb +177 -0
  42. data/samples/tableindiv_ill.rb +99 -0
  43. data/test/caption_test.rb +99 -0
  44. data/test/container_test.rb +29 -0
  45. data/test/div_test.rb +39 -0
  46. data/test/helpers_for_testing.rb +19 -0
  47. data/test/image_test.rb +54 -0
  48. data/test/shared_examples.rb +68 -0
  49. data/test/span_test.rb +83 -0
  50. data/test/table_test.rb +27 -0
  51. metadata +139 -0
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010, Sphere Consutling Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,189 @@
1
+ == Pdf_gen
2
+ pdf_gen is a high-level wrapper around {PDF::Writer}[https://github.com/sandal/pdf-writer] library which allows to create PDF documents in an easy way with a layout similar to HTML.
3
+
4
+ == Install
5
+ gem install pdf_gen
6
+
7
+ == Usage
8
+ All package entities are located within the PDFGen module.
9
+ PDF file generation can be made in the following way:
10
+
11
+ require "pdf_gen"
12
+
13
+ PDFGen::document PDF::Writer.new, 0.cm do
14
+ # pdf generation code here
15
+ end.save("#{File.basename(__FILE__, ".rb")}.pdf")
16
+
17
+ == Construction Elements
18
+
19
+ === Caption
20
+ An object which allows to represent some parts of the text in PDF file. This object has such properties as width, justification, pad_top (indent from the left side of the page), pad_bottom, pad_left, pad_right, text_color, font_size and border.
21
+ The Border, in its turn, can be characterized by border_color, border_style (solid or dotted) and border_width (in cm or pixels).
22
+ Support Properties:
23
+ pad_top - integer
24
+ pad_bottom - integer
25
+ pad_left - integer
26
+ pad_right - integer
27
+ paddings - integer
28
+ border - true|false
29
+ border_top - true|false
30
+ border_bottom - true|false
31
+ border_left - true|false
32
+ border_right - true|false
33
+ border_style - :solid | :dotted
34
+ border_widht - integer
35
+ border_color - object of color-tools*. Color::RGB::Red|Color::RGB.from_html("#ccc")| other
36
+ background_color - object of color-tools*. Color::RGB::Red|Color::RGB.from_html("#ccc")| other
37
+ width - integer
38
+ height - integer
39
+
40
+ *color-tools http://ruby-pdf.rubyforge.org/color-tools/
41
+
42
+ === Image
43
+ An object which allows to add images with filename extensions *.jpg and *.png in PDF file. This object has such properties as width, pad_top, pad_bottom, pad_left, pad_right and border.
44
+
45
+ require "pdf_gen"
46
+
47
+ PDFGen::document PDF::Writer.new, 2.cm do
48
+ image_data = open(File.expand_path('ruby_logo.jpg'), "rb") { |file| file.read }
49
+ image image_data, :width => 250
50
+ end.save("#{File.basename(__FILE__, ".rb")}.pdf")
51
+
52
+ Support Properties:
53
+ *the same as caption`s properties
54
+
55
+ === Span
56
+ An object which allows setting several objects across the page. This object has such properties as width, pad_top, pad_bottom, pad_left, pad_right, border and background_color.
57
+
58
+ PDFGen::document PDF::Writer.new, 2.cm do
59
+ span :width => 10.cm, :pad_left => 2.cm do
60
+ caption ' first '*50, :width => 4.cm
61
+ caption ' second '*50, :width => 4.cm
62
+ elements :border => true #group set params
63
+ end
64
+ end.save("#{File.basename(__FILE__, ".rb")}.pdf")
65
+
66
+ Support Properties:
67
+ *the same as caption`s properties
68
+ vertical_interval - integer
69
+ vartical_align - true | false
70
+
71
+ === Div
72
+ An object which allows setting several elements in the vertical format. This object has such properties as width, horizontal_interval, pad_top, pad_bottom, pad_left, pad_right, border and background_color.
73
+
74
+ PDFGen::document PDF::Writer.new, 2.cm do
75
+ div :width => 10.cm do
76
+ caption ' first '*50, :width => 4.cm
77
+ caption ' second '*50, :width => 4.cm
78
+ elements :border => true #group set params
79
+ end
80
+ end.save("#{File.basename(__FILE__, ".rb")}.pdf")
81
+
82
+ Support Properties:
83
+ *the same as caption`s properties
84
+ horizontal_interval - integer
85
+ horizontal_align - true | false
86
+
87
+ === Table
88
+ An object which allows creating tables in PDF file. This object has such elements as title, header, body and footer. The columns can be made be adding “spans” inside the body of the table. The table can have borders from specific sides, for example: “:border_right => true” or “:border_right => false”.
89
+
90
+ require "pdf_gen"
91
+
92
+ PDFGen::document PDF::Writer.new, 0.cm do
93
+ table do
94
+ title do
95
+ caption "Transactions and Triggers",
96
+ :text_color => Color::RGB::Red, :border => true, :justification => :center, :pad_bottom => 0.25.cm
97
+ end
98
+ header do
99
+ span do
100
+ caption "Number",
101
+ :width => av_width / 2, :justification => :center, :border => true
102
+ caption "Discription",
103
+ :width => av_width / 2, :justification => :center, :border => true
104
+ end
105
+ end
106
+ body do
107
+ span do
108
+ caption " Trigger ", :width => av_width / 2,
109
+ :border_right => true, :border_left => true, :text_color => Color::RGB::Grey
110
+ caption " - is a ... ", :width => av_width / 2,
111
+ :border_right => true, :border_left => true, :text_color => Color::RGB::Grey
112
+ end
113
+ end
114
+ footer do
115
+ span do
116
+ caption "1", :width => av_width / 2, :justification => :center, :border => true
117
+ caption "2", :width => av_width / 2, :justification => :center, :border => true
118
+ end
119
+ end
120
+ end
121
+ end.save("#{File.basename(__FILE__, ".rb")}.pdf")
122
+
123
+ === Smart Table
124
+ An object which allows creating tables from Hash and ActiveRecord. If necessary, you can define the blocks of the title and footer independently.
125
+ For example:
126
+
127
+ table_data = {:columns =>['id','name','email'],
128
+ :body => [[1,'Valeriy','valeriy@example.com'],
129
+ [2,'Dmitriy','dmitriy@example.com']]}
130
+ PDFGen::document PDF::Writer.new, 0.cm do
131
+ div :paddings => 2 do
132
+ table :data_source => table_data
133
+ end
134
+ end.save("#{File.basename(__FILE__, ".rb")}.pdf")
135
+
136
+ Building a table from ActiveRecord (ROR)
137
+
138
+ table_data = User.all
139
+ PDFGen::document PDF::Writer.new, 0.cm do
140
+ div :paddings => 2 do
141
+ table :data_source => table_data
142
+ end
143
+ end.save("#{File.basename(__FILE__, ".rb")}.pdf")
144
+
145
+ Custom view
146
+
147
+ table_data = {:columns =>['id','name','email'],
148
+ :body => [[1,'Valeriy','valeriy@example.com'],
149
+ [2,'Dmitriy','dmitriy@example.com']]}
150
+ PDFGen::document PDF::Writer.new, 0.cm do
151
+ div :paddings => 2 do
152
+ table :data_source => table_data do
153
+ header do
154
+ row do
155
+ cell "<b>#{ds.columns[0]}</b>", :justification => :center, :text_color => Color::RGB::Green
156
+ cell ds.columns[1], :justification => :center, :text_color => Color::RGB::Green
157
+ cell ds.columns[2], :justification => :center, :text_color => Color::RGB::Green
158
+ end
159
+ end
160
+ body do
161
+ ds.each do |datarow|
162
+ row do
163
+ cell datarow[0]
164
+ cell "<i>#{datarow[1]}</i>"
165
+ cell datarow[2]
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end.save("#{File.basename(__FILE__, ".rb")}.pdf")
172
+
173
+ We can set the width of each column
174
+
175
+ row do
176
+ cell data[0], :width => av_width * 2/4
177
+ cell data[1], :width => av_width * 1/4
178
+ cell data[2], :width => av_width * 1/4
179
+ end
180
+
181
+
182
+ == Credits
183
+
184
+ === Team's line-up
185
+ * Mykhaylo Sorochan, Valeriy Prokopchuk - Project Managers
186
+ * Valeriy Sizov, Dmitriy Landberg - Software Developers
187
+ * Nataliya Shatokhina - Tester
188
+
189
+ Copyright (c) 2010 {Sphere Consulting Inc.}[http://www.sphereinc.com], released under the MIT license (see LICENSE).
@@ -0,0 +1,95 @@
1
+ require "lib/modules/base_attributes"
2
+
3
+ module PDFGen
4
+
5
+ class BaseRegion
6
+ include BaseAttributes
7
+
8
+ def initialize(parent)
9
+ self.var_init
10
+ @parent = parent
11
+ end
12
+
13
+ attr_reader :parent
14
+
15
+ #gets region's document
16
+ def document
17
+ parent ? parent.document : self
18
+ end
19
+
20
+ #gets minimal height that current caption can be written to
21
+ def minimal_height
22
+ @minimal_height ||= calculate_minimal_height
23
+ end
24
+
25
+ def clear_minimal_height
26
+ @minimal_height = nil
27
+ end
28
+
29
+ protected :clear_minimal_height
30
+
31
+ def calculate_minimal_height
32
+ 0
33
+ end
34
+
35
+ protected :calculate_minimal_height
36
+
37
+ def add_border(pos)
38
+ x,y = pos
39
+ if border_top || border_bottom || border_left || border_right
40
+ document.pdf.save_state
41
+
42
+ document.pdf.stroke_color! border_color
43
+ document.pdf.stroke_style! border_params
44
+
45
+ document.pdf.line(x, y, x, y - height).stroke if border_left
46
+ document.pdf.line(x + width, y, x + width, y - height).stroke if border_right
47
+ document.pdf.line(x, y, x + width, y).stroke if border_top
48
+ document.pdf.line(x, y - height, x + width, y - height).stroke if border_bottom
49
+
50
+ document.pdf.restore_state
51
+ end
52
+ end
53
+
54
+ private :add_border
55
+
56
+ #fills caption area with background color
57
+ def fill(pos)
58
+ unless background_color.nil?
59
+ document.pdf.save_state
60
+
61
+ document.pdf.stroke_color! background_color
62
+ document.pdf.stroke_style! PDF::Writer::StrokeStyle::SOLID
63
+ document.pdf.fill_color! background_color
64
+ document.pdf.rectangle(pos[0], pos[1] - height, width, height).fill.stroke
65
+
66
+ document.pdf.restore_state
67
+ end
68
+ end
69
+
70
+ private :fill
71
+
72
+ def render(pos,av_height, test=false)
73
+ fill(pos) unless test
74
+ add_border(pos) unless test
75
+ [pos,true]
76
+ end
77
+
78
+ def check_fit_in_height
79
+ if (self.height >= document.pdf.page_height-document.page_pad_top)
80
+ raise "region`s height is bigger then parent region`s height"
81
+ end
82
+ end
83
+
84
+ def value val
85
+ "<!#{val.to_s}!>"
86
+ end
87
+
88
+ #sets region properties specified as array
89
+ def set_properties(props = {})
90
+ props.each_pair {|name, value| self.send("#{name}=", value)}
91
+ end
92
+
93
+ end
94
+
95
+ end
data/lib/caption.rb ADDED
@@ -0,0 +1,78 @@
1
+ require "lib/base_region"
2
+
3
+
4
+ module PDFGen
5
+
6
+ class Caption < BaseRegion
7
+
8
+ def initialize(parent)
9
+ super
10
+
11
+ @text = ""
12
+ @template = @text
13
+ @justification = :left
14
+ @bold = false
15
+ @font_size = document.pdf.font_size
16
+ self.paddings = 0.2.cm
17
+ end
18
+
19
+ attr_reader :text
20
+
21
+ def text=(value)
22
+ value = value.to_s unless value.is_a?(String)
23
+ if value && @text != value
24
+ @text = value
25
+ @template = value
26
+ clear_minimal_height
27
+ end
28
+ end
29
+
30
+ attr_reader :text_color, :justification, :bold, :font_size
31
+
32
+ common_setter :text_color, :justification, :bold, :font_size
33
+
34
+ def calculate_minimal_height
35
+ add_text_wrap
36
+ end
37
+
38
+ #writes text. return actual text height
39
+ def add_text_wrap(pos=[], test = true)
40
+ x = pos[0] || 0
41
+ y = pos[1] || document.pdf.y
42
+
43
+ res = document.pdf.font_height + pad_top
44
+ txt = bold ? "<b>#{text}</b>" : text
45
+
46
+ document.pdf.save_state
47
+ document.pdf.fill_color text_color if text_color
48
+ document.pdf.stroke_color! text_color if text_color
49
+ until (txt_remain = document.pdf.add_text_wrap(x + pad_left, y - res, width - pad_left - pad_right, txt, font_size,
50
+ justification, 0, test)).empty?
51
+ txt_remain == txt ? raise("text very long for this caption") : txt = txt_remain
52
+ res += document.pdf.font_height(font_size)
53
+ end
54
+ document.pdf.restore_state
55
+
56
+ res + pad_bottom
57
+ end
58
+
59
+ private :add_text_wrap
60
+
61
+ #renders specified text at the specified position
62
+ #returns real position that caption was generated on
63
+ def render(pos, av_height, test=false)
64
+ self.check_fit_in_height
65
+ if av_height >= self.height
66
+ super
67
+ add_text_wrap(pos,test)
68
+ used_height = [add_text_wrap(pos),self.height].max
69
+ [used_height, true]
70
+ else
71
+ [0, false]
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+
@@ -0,0 +1,15 @@
1
+ module PDFGen
2
+
3
+ module CaptionContainer
4
+
5
+ def caption(text = nil, style = nil)
6
+ caption = Caption.new self
7
+ caption.text = text if text
8
+ caption.width = self.width - self.pad_left - self.pad_right
9
+ caption.set_properties style unless style.nil?
10
+ self.add_region(caption)
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,14 @@
1
+ module PDFGen
2
+
3
+ module DivContainer
4
+
5
+ def div(style = nil, &initialization_block)
6
+ div = Div.new(self)
7
+ div.width = self.width - self.pad_left - self.pad_right
8
+ div.set_properties style unless style.nil?
9
+ div.instance_eval(&initialization_block) if initialization_block
10
+ self.add_region(div)
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ require "lib/image"
2
+ module PDFGen
3
+
4
+
5
+ module ImageContainer
6
+
7
+ def image(image_res, style=nil)
8
+ image = Image.new self, image_res
9
+ image.set_properties style unless style.nil?
10
+ self.add_region(image)
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,14 @@
1
+ module PDFGen
2
+
3
+ module SpanContainer
4
+
5
+ def span(style = nil, &initialization_block)
6
+ span = Span.new self
7
+ span.width = self.width - self.pad_left - self.pad_right
8
+ span.set_properties style unless style.nil?
9
+ span.instance_eval(&initialization_block) if initialization_block
10
+ self.add_region(span)
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module PDFGen
2
+
3
+ module TableContainer
4
+
5
+ def table(style = nil, &initialization_block)
6
+ table = (style.is_a?(Hash) and style.has_key?(:data_source)) ?
7
+ SmartTable.new(self) : Table.new(self)
8
+ table.set_properties style unless style.nil?
9
+ table.instance_eval(&initialization_block) if initialization_block
10
+ self.add_region(table)
11
+ end
12
+
13
+ end
14
+ end
data/lib/data/ds_ar.rb ADDED
@@ -0,0 +1,31 @@
1
+ require "lib/data/ds_base"
2
+
3
+ module PDFGen
4
+
5
+ class DsActiveRecord < DsBase
6
+ def initialize(data)
7
+ @data = data
8
+ end
9
+
10
+ def columns
11
+ @data.first.class.columns.map(&:name)
12
+ end
13
+
14
+ def body
15
+ @fields = []
16
+ @data.each do |row|
17
+ @mas = []
18
+ columns.each do |title|
19
+ @mas << row.send(title)
20
+ end
21
+ @fields << @mas
22
+ end
23
+ @fields
24
+ end
25
+
26
+ def each
27
+ self.body.each {|item| yield item}
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,24 @@
1
+ module PDFGen
2
+
3
+ class DsBase
4
+
5
+ include Enumerable
6
+
7
+ def initialize(data)
8
+ raise "Not Implemented"
9
+ end
10
+
11
+ def columns
12
+ raise "Not Implemented"
13
+ end
14
+
15
+ def body
16
+ raise "Not Implemented"
17
+ end
18
+
19
+ def each
20
+ raise "Not Implemented"
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,24 @@
1
+ require "lib/data/ds_base"
2
+
3
+
4
+ module PDFGen
5
+
6
+ class DsHash < DsBase
7
+ def initialize(data)
8
+ @data = data
9
+ end
10
+
11
+ def columns
12
+ @data[:columns]
13
+ end
14
+
15
+ def body
16
+ @data[:body]
17
+ end
18
+
19
+ def each
20
+ self.body.each {|item| yield item}
21
+ end
22
+ end
23
+
24
+ end
data/lib/div.rb ADDED
@@ -0,0 +1,148 @@
1
+ require "lib/base_region"
2
+ require "lib/modules/composite"
3
+ require "lib/containers/div_container"
4
+ require "lib/containers/span_container"
5
+ require "lib/containers/caption_container"
6
+ require "lib/containers/image_container"
7
+ require "lib/containers/table_container"
8
+
9
+
10
+ module PDFGen
11
+
12
+ class Div < BaseRegion
13
+
14
+ include Composite, CaptionContainer, SpanContainer, DivContainer,
15
+ ImageContainer, TableContainer
16
+
17
+ def initialize parent
18
+ super
19
+
20
+ @horizontal_interval = 0
21
+ @horizontal_align = false
22
+ @optional_border = false
23
+ @is_breakable = true
24
+ @count_rendered_region = 0
25
+ @rendered_height = 0
26
+ end
27
+
28
+ attr_accessor :horizontal_interval, :horizontal_align, :optional_border
29
+ attr_accessor :count_rendered_region
30
+
31
+ def add_border_top(x, y)
32
+ add_border(x, y, x + width, y) if border_top
33
+ end
34
+
35
+ def add_border_bottom(x, y)
36
+ add_border(x, y, x + width, y) if border_bottom
37
+ end
38
+
39
+ #border left and right
40
+ def add_border_sides(x, y, y_new)
41
+ add_border(x, y, x, y_new) if border_left
42
+ add_border(x + width, y, x + width, y_new) if border_right
43
+ end
44
+
45
+ def add_border(x, y, x1, y1)
46
+ document.pdf.save_state
47
+ document.pdf.stroke_color! border_color
48
+ document.pdf.stroke_style! border_params
49
+ document.pdf.line(x, y, x1, y1).stroke
50
+ document.pdf.restore_state
51
+ end
52
+
53
+ def add_optional_border(x, y)
54
+ add_border(x, y, x + width, y)
55
+ end
56
+
57
+ def calculate_minimal_height
58
+ height = 0
59
+ regions.each do |region|
60
+ height += region.height
61
+ height += horizontal_interval unless region == regions.last
62
+ end
63
+ height + pad_top + pad_bottom
64
+ end
65
+
66
+ def render_regions(pos, av_height, test=false)
67
+ pos_x, pos_y = pos
68
+ remain_regions = regions.slice(@count_rendered_region..regions.size)
69
+ if @count_rendered_region.zero? && @rendered_height.zero?
70
+ @rendered_height += pad_top
71
+ pos_y -= pad_top
72
+ end
73
+ pos_x += pad_left
74
+
75
+ remain_regions.each do |region|
76
+ self.fit_width(region)
77
+ if pos_y >= region.height
78
+ @count_rendered_region += 1 unless test
79
+
80
+ region_height = region.render([pos_x, pos_y], pos_y, test)[0]
81
+
82
+ @rendered_height += region_height
83
+ pos_y -= region_height
84
+
85
+ @rendered_height += horizontal_interval unless region == regions.last
86
+ pos_y -= horizontal_interval unless region == regions.last
87
+
88
+ if region == regions.last
89
+ pos_y -= pad_bottom
90
+ @rendered_height += pad_bottom
91
+ end
92
+ else
93
+ if region.breakable?
94
+ status = region.render([pos_x, pos_y], pos_y, test)
95
+
96
+ @rendered_height += status[0]
97
+ pos_y -= status[0]
98
+
99
+ @rendered_height += horizontal_interval unless region == regions.last
100
+ pos_y -= horizontal_interval unless region == regions.last
101
+
102
+ if region == regions.last and status[1]
103
+ pos_y -= pad_bottom
104
+ @rendered_height += pad_bottom
105
+ end
106
+
107
+ return [av_height - pos_y, status[1]]
108
+ else
109
+ region.check_fit_in_height
110
+ return [av_height - pos_y, false]
111
+ end
112
+ end
113
+ end
114
+
115
+ [av_height - pos_y, true]
116
+ end
117
+
118
+ def render(pos, av_height, test=false)
119
+ pos_x, pos_y = pos
120
+ fill(pos)
121
+ add_border_top(pos_x, pos_y) if @rendered_height.zero?
122
+ status = render_regions([pos_x, pos_y], av_height, test)
123
+ pos_y -= status[0]
124
+
125
+ if (status[1])
126
+ add_border_bottom(pos_x, pos_y)
127
+ add_border_sides(pos_x, av_height, pos_y)
128
+ else
129
+ add_border_sides(pos_x, av_height, 0)
130
+ end
131
+
132
+ status
133
+ end
134
+
135
+ def fit_width(region)
136
+ if (region.width > (width - pad_left - pad_right)) or horizontal_align
137
+ region.width = width - pad_left - pad_right
138
+ end
139
+ end
140
+
141
+ protected :fit_width
142
+
143
+ def reset_count_rendered_regions
144
+ @count_rendered_region = 0
145
+ end
146
+ end
147
+
148
+ end