prawn 0.4.1 → 0.5.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.
Files changed (179) hide show
  1. data/lib/prawn.rb +2 -72
  2. metadata +33 -224
  3. data/COPYING +0 -340
  4. data/LICENSE +0 -56
  5. data/README +0 -40
  6. data/Rakefile +0 -79
  7. data/data/encodings/win_ansi.txt +0 -29
  8. data/data/fonts/Action Man.dfont +0 -0
  9. data/data/fonts/Activa.ttf +0 -0
  10. data/data/fonts/Chalkboard.ttf +0 -0
  11. data/data/fonts/Courier-Bold.afm +0 -342
  12. data/data/fonts/Courier-BoldOblique.afm +0 -342
  13. data/data/fonts/Courier-Oblique.afm +0 -342
  14. data/data/fonts/Courier.afm +0 -342
  15. data/data/fonts/DejaVuSans.ttf +0 -0
  16. data/data/fonts/Dustismo_Roman.ttf +0 -0
  17. data/data/fonts/Helvetica-Bold.afm +0 -2827
  18. data/data/fonts/Helvetica-BoldOblique.afm +0 -2827
  19. data/data/fonts/Helvetica-Oblique.afm +0 -3051
  20. data/data/fonts/Helvetica.afm +0 -3051
  21. data/data/fonts/MustRead.html +0 -19
  22. data/data/fonts/Symbol.afm +0 -213
  23. data/data/fonts/Times-Bold.afm +0 -2588
  24. data/data/fonts/Times-BoldItalic.afm +0 -2384
  25. data/data/fonts/Times-Italic.afm +0 -2667
  26. data/data/fonts/Times-Roman.afm +0 -2419
  27. data/data/fonts/ZapfDingbats.afm +0 -225
  28. data/data/fonts/comicsans.ttf +0 -0
  29. data/data/fonts/gkai00mp.ttf +0 -0
  30. data/data/images/arrow.png +0 -0
  31. data/data/images/arrow2.png +0 -0
  32. data/data/images/barcode_issue.png +0 -0
  33. data/data/images/dice.alpha +0 -0
  34. data/data/images/dice.dat +0 -0
  35. data/data/images/dice.png +0 -0
  36. data/data/images/fractal.jpg +0 -0
  37. data/data/images/letterhead.jpg +0 -0
  38. data/data/images/page_white_text.alpha +0 -0
  39. data/data/images/page_white_text.dat +0 -0
  40. data/data/images/page_white_text.png +0 -0
  41. data/data/images/pigs.jpg +0 -0
  42. data/data/images/rails.dat +0 -0
  43. data/data/images/rails.png +0 -0
  44. data/data/images/ruport.png +0 -0
  45. data/data/images/ruport_data.dat +0 -0
  46. data/data/images/ruport_transparent.png +0 -0
  47. data/data/images/ruport_type0.png +0 -0
  48. data/data/images/stef.jpg +0 -0
  49. data/data/images/web-links.dat +0 -1
  50. data/data/images/web-links.png +0 -0
  51. data/data/shift_jis_text.txt +0 -1
  52. data/examples/bounding_box/bounding_boxes.rb +0 -44
  53. data/examples/bounding_box/lazy_bounding_boxes.rb +0 -28
  54. data/examples/bounding_box/padded_box.rb +0 -24
  55. data/examples/bounding_box/russian_boxes.rb +0 -37
  56. data/examples/general/background.rb +0 -20
  57. data/examples/general/canvas.rb +0 -16
  58. data/examples/general/measurement_units.rb +0 -52
  59. data/examples/general/multi_page_layout.rb +0 -17
  60. data/examples/general/page_geometry.rb +0 -32
  61. data/examples/graphics/basic_images.rb +0 -27
  62. data/examples/graphics/cmyk.rb +0 -13
  63. data/examples/graphics/curves.rb +0 -12
  64. data/examples/graphics/hexagon.rb +0 -14
  65. data/examples/graphics/image_fit.rb +0 -16
  66. data/examples/graphics/image_flow.rb +0 -38
  67. data/examples/graphics/image_position.rb +0 -18
  68. data/examples/graphics/line.rb +0 -33
  69. data/examples/graphics/png_types.rb +0 -23
  70. data/examples/graphics/polygons.rb +0 -17
  71. data/examples/graphics/remote_images.rb +0 -12
  72. data/examples/graphics/ruport_style_helpers.rb +0 -20
  73. data/examples/graphics/stroke_bounds.rb +0 -23
  74. data/examples/m17n/chinese_text_wrapping.rb +0 -20
  75. data/examples/m17n/euro.rb +0 -16
  76. data/examples/m17n/sjis.rb +0 -29
  77. data/examples/m17n/utf8.rb +0 -14
  78. data/examples/m17n/win_ansi_charset.rb +0 -55
  79. data/examples/text/alignment.rb +0 -19
  80. data/examples/text/dfont.rb +0 -49
  81. data/examples/text/family_based_styling.rb +0 -25
  82. data/examples/text/flowing_text_with_header_and_footer.rb +0 -37
  83. data/examples/text/font_calculations.rb +0 -92
  84. data/examples/text/font_size.rb +0 -34
  85. data/examples/text/kerning.rb +0 -31
  86. data/examples/text/simple_text.rb +0 -18
  87. data/examples/text/simple_text_ttf.rb +0 -18
  88. data/examples/text/span.rb +0 -30
  89. data/examples/text/text_box.rb +0 -26
  90. data/examples/text/text_flow.rb +0 -68
  91. data/lib/prawn/compatibility.rb +0 -38
  92. data/lib/prawn/document.rb +0 -309
  93. data/lib/prawn/document/annotations.rb +0 -63
  94. data/lib/prawn/document/bounding_box.rb +0 -368
  95. data/lib/prawn/document/destinations.rb +0 -81
  96. data/lib/prawn/document/internals.rb +0 -126
  97. data/lib/prawn/document/page_geometry.rb +0 -79
  98. data/lib/prawn/document/span.rb +0 -55
  99. data/lib/prawn/document/text.rb +0 -185
  100. data/lib/prawn/document/text/box.rb +0 -76
  101. data/lib/prawn/document/text/wrapping.rb +0 -59
  102. data/lib/prawn/encoding.rb +0 -121
  103. data/lib/prawn/errors.rb +0 -40
  104. data/lib/prawn/font.rb +0 -277
  105. data/lib/prawn/font/afm.rb +0 -202
  106. data/lib/prawn/font/dfont.rb +0 -31
  107. data/lib/prawn/font/ttf.rb +0 -326
  108. data/lib/prawn/graphics.rb +0 -257
  109. data/lib/prawn/graphics/color.rb +0 -140
  110. data/lib/prawn/images.rb +0 -339
  111. data/lib/prawn/images/jpg.rb +0 -45
  112. data/lib/prawn/images/png.rb +0 -199
  113. data/lib/prawn/literal_string.rb +0 -14
  114. data/lib/prawn/measurement_extensions.rb +0 -46
  115. data/lib/prawn/measurements.rb +0 -71
  116. data/lib/prawn/name_tree.rb +0 -165
  117. data/lib/prawn/pdf_object.rb +0 -73
  118. data/lib/prawn/reference.rb +0 -59
  119. data/spec/annotations_spec.rb +0 -90
  120. data/spec/bounding_box_spec.rb +0 -141
  121. data/spec/destinations_spec.rb +0 -15
  122. data/spec/document_spec.rb +0 -193
  123. data/spec/font_spec.rb +0 -234
  124. data/spec/graphics_spec.rb +0 -209
  125. data/spec/images_spec.rb +0 -68
  126. data/spec/jpg_spec.rb +0 -25
  127. data/spec/measurement_units_spec.rb +0 -23
  128. data/spec/name_tree_spec.rb +0 -103
  129. data/spec/pdf_object_spec.rb +0 -112
  130. data/spec/png_spec.rb +0 -196
  131. data/spec/reference_spec.rb +0 -42
  132. data/spec/spec_helper.rb +0 -23
  133. data/spec/text_spec.rb +0 -178
  134. data/vendor/pdf-inspector/README +0 -18
  135. data/vendor/pdf-inspector/lib/pdf/inspector.rb +0 -25
  136. data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +0 -80
  137. data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +0 -16
  138. data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +0 -31
  139. data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +0 -19
  140. data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
  141. data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
  142. data/vendor/ttfunk/example.rb +0 -45
  143. data/vendor/ttfunk/lib/ttfunk.rb +0 -102
  144. data/vendor/ttfunk/lib/ttfunk/directory.rb +0 -17
  145. data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +0 -88
  146. data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +0 -69
  147. data/vendor/ttfunk/lib/ttfunk/reader.rb +0 -44
  148. data/vendor/ttfunk/lib/ttfunk/resource_file.rb +0 -78
  149. data/vendor/ttfunk/lib/ttfunk/subset.rb +0 -18
  150. data/vendor/ttfunk/lib/ttfunk/subset/base.rb +0 -141
  151. data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +0 -46
  152. data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +0 -48
  153. data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +0 -63
  154. data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +0 -51
  155. data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +0 -72
  156. data/vendor/ttfunk/lib/ttfunk/table.rb +0 -46
  157. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +0 -34
  158. data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +0 -54
  159. data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +0 -126
  160. data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +0 -79
  161. data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +0 -64
  162. data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +0 -81
  163. data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +0 -37
  164. data/vendor/ttfunk/lib/ttfunk/table/head.rb +0 -44
  165. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +0 -41
  166. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +0 -47
  167. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +0 -79
  168. data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +0 -62
  169. data/vendor/ttfunk/lib/ttfunk/table/loca.rb +0 -43
  170. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +0 -40
  171. data/vendor/ttfunk/lib/ttfunk/table/name.rb +0 -119
  172. data/vendor/ttfunk/lib/ttfunk/table/os2.rb +0 -78
  173. data/vendor/ttfunk/lib/ttfunk/table/post.rb +0 -91
  174. data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +0 -43
  175. data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +0 -35
  176. data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +0 -23
  177. data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +0 -17
  178. data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +0 -17
  179. data/vendor/ttfunk/lib/ttfunk/table/simple.rb +0 -14
@@ -1,45 +0,0 @@
1
- # encoding: ASCII-8BIT
2
-
3
- # jpg.rb : Extracts the data from a JPG that is needed for embedding
4
- #
5
- # Copyright April 2008, James Healy. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
-
9
- require 'stringio'
10
-
11
- module Prawn
12
- module Images
13
- # A convenience class that wraps the logic for extracting the parts
14
- # of a PNG image that we need to embed them in a PDF
15
- class JPG
16
- attr_reader :width, :height, :bits, :channels
17
- attr_accessor :scaled_width, :scaled_height
18
-
19
- JPEG_SOF_BLOCKS = %W(\xc0 \xc1 \xc2 \xc3 \xc5 \xc6 \xc7 \xc9 \xca \xcb \xcd \xce \xcf)
20
- JPEG_APP_BLOCKS = %W(\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef)
21
-
22
- # Process a new JPG image
23
- #
24
- # <tt>:data</tt>:: A string containing a full PNG file
25
- #
26
- def initialize(data)
27
- data = StringIO.new(data.dup)
28
-
29
- c_marker = "\xff" # Section marker.
30
- data.read(2) # Skip the first two bytes of JPEG identifier.
31
- loop do
32
- marker, code, length = data.read(4).unpack('aan')
33
- raise "JPEG marker not found!" if marker != c_marker
34
-
35
- if JPEG_SOF_BLOCKS.include?(code)
36
- @bits, @height, @width, @channels = data.read(6).unpack("CnnC")
37
- break
38
- end
39
-
40
- buffer = data.read(length - 2)
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,199 +0,0 @@
1
- # encoding: ASCII-8BIT
2
-
3
- # png.rb : Extracts the data from a PNG that is needed for embedding
4
- #
5
- # Based on some similar code in PDF::Writer by Austin Ziegler
6
- #
7
- # Copyright April 2008, James Healy. All Rights Reserved.
8
- #
9
- # This is free software. Please see the LICENSE and COPYING files for details.
10
-
11
- require 'stringio'
12
-
13
- module Prawn
14
- module Images
15
- # A convenience class that wraps the logic for extracting the parts
16
- # of a PNG image that we need to embed them in a PDF
17
- class PNG
18
- attr_reader :palette, :img_data, :transparency
19
- attr_reader :width, :height, :bits
20
- attr_reader :color_type, :compression_method, :filter_method
21
- attr_reader :interlace_method, :alpha_channel
22
- attr_accessor :scaled_width, :scaled_height
23
-
24
- # Process a new PNG image
25
- #
26
- # <tt>data</tt>:: A string containing a full PNG file
27
- #
28
- def initialize(data)
29
- data = StringIO.new(data.dup)
30
-
31
- data.read(8) # Skip the default header
32
-
33
- @palette = ""
34
- @img_data = ""
35
- @transparency = {}
36
-
37
- loop do
38
- chunk_size = data.read(4).unpack("N")[0]
39
- section = data.read(4)
40
- case section
41
- when 'IHDR'
42
- # we can grab other interesting values from here (like width,
43
- # height, etc)
44
- values = data.read(chunk_size).unpack("NNCCCCC")
45
-
46
- @width = values[0]
47
- @height = values[1]
48
- @bits = values[2]
49
- @color_type = values[3]
50
- @compression_method = values[4]
51
- @filter_method = values[5]
52
- @interlace_method = values[6]
53
- when 'PLTE'
54
- @palette << data.read(chunk_size)
55
- when 'IDAT'
56
- @img_data << data.read(chunk_size)
57
- when 'tRNS'
58
- # This chunk can only occur once and it must occur after the
59
- # PLTE chunk and before the IDAT chunk
60
- @transparency = {}
61
- case @color_type
62
- when 3
63
- # Indexed colour, RGB. Each byte in this chunk is an alpha for
64
- # the palette index in the PLTE ("palette") chunk up until the
65
- # last non-opaque entry. Set up an array, stretching over all
66
- # palette entries which will be 0 (opaque) or 1 (transparent).
67
- @transparency[:indexed] = data.read(chunk_size).unpack("C*")
68
- short = 255 - @transparency[:indexed].size
69
- @transparency[:indexed] += ([255] * short) if short > 0
70
- when 0
71
- # Greyscale. Corresponding to entries in the PLTE chunk.
72
- # Grey is two bytes, range 0 .. (2 ^ bit-depth) - 1
73
- grayval = data.read(chunk_size).unpack("n").first
74
- @transparency[:grayscale] = grayval
75
- when 2
76
- # True colour with proper alpha channel.
77
- @transparency[:rgb] = data.read(chunk_size).unpack("nnn")
78
- end
79
- when 'IEND'
80
- # we've got everything we need, exit the loop
81
- break
82
- else
83
- # unknown (or un-important) section, skip over it
84
- data.seek(data.pos + chunk_size)
85
- end
86
-
87
- data.read(4) # Skip the CRC
88
- end
89
-
90
- # if our img_data contains alpha channel data, split it out
91
- unfilter_image_data if alpha_channel?
92
- end
93
-
94
- def pixel_bytes
95
- @pixel_bytes ||= case @color_type
96
- when 0, 3, 4 then 1
97
- when 1, 2, 6 then 3
98
- end
99
- end
100
-
101
- private
102
-
103
- def alpha_channel?
104
- @color_type == 4 || @color_type == 6
105
- end
106
-
107
- def unfilter_image_data
108
- data = Zlib::Inflate.inflate(@img_data).unpack 'C*'
109
- @img_data = ""
110
- @alpha_channel = ""
111
-
112
- # each pixel has the color bytes, plus a byte of alpha channel
113
- pixel_length = pixel_bytes + 1
114
- scanline_length = pixel_length * @width + 1 # for filter
115
- row = 0
116
- pixels = []
117
- paeth, pa, pb, pc = nil
118
- until data.empty? do
119
- row_data = data.slice! 0, scanline_length
120
- filter = row_data.shift
121
- case filter
122
- when 0 # None
123
- when 1 # Sub
124
- row_data.each_with_index do |byte, index|
125
- left = index < pixel_length ? 0 : row_data[index - pixel_length]
126
- row_data[index] = (byte + left) % 256
127
- #p [byte, left, row_data[index]]
128
- end
129
- when 2 # Up
130
- row_data.each_with_index do |byte, index|
131
- col = index / pixel_length
132
- upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_length]
133
- row_data[index] = (upper + byte) % 256
134
- end
135
- when 3 # Average
136
- row_data.each_with_index do |byte, index|
137
- col = index / pixel_length
138
- upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_length]
139
- left = index < pixel_length ? 0 : row_data[index - pixel_length]
140
-
141
- row_data[index] = (byte + ((left + upper)/2).floor) % 256
142
- end
143
- when 4 # Paeth
144
- left = upper = upper_left = nil
145
- row_data.each_with_index do |byte, index|
146
- col = index / pixel_length
147
-
148
- left = index < pixel_length ? 0 : row_data[index - pixel_length]
149
- if row.zero?
150
- upper = upper_left = 0
151
- else
152
- upper = pixels[row-1][col][index % pixel_length]
153
- upper_left = col.zero? ? 0 :
154
- pixels[row-1][col-1][index % pixel_length]
155
- end
156
-
157
- p = left + upper - upper_left
158
- pa = (p - left).abs
159
- pb = (p - upper).abs
160
- pc = (p - upper_left).abs
161
-
162
- paeth = if pa <= pb && pa <= pc
163
- left
164
- elsif pb <= pc
165
- upper
166
- else
167
- upper_left
168
- end
169
-
170
- row_data[index] = (byte + paeth) % 256
171
- #p [byte, paeth, row_data[index]]
172
- end
173
- else
174
- raise ArgumentError, "Invalid filter algorithm #{filter}"
175
- end
176
-
177
- s = []
178
- row_data.each_slice pixel_length do |slice|
179
- s << slice
180
- end
181
- pixels << s
182
- row += 1
183
- end
184
-
185
- # convert the pixel data to seperate strings for colours and alpha
186
- pixels.each do |row|
187
- row.each do |pixel|
188
- @img_data << pixel[0,pixel_bytes].pack("C*")
189
- @alpha_channel << pixel.last
190
- end
191
- end
192
-
193
- # compress the data
194
- @img_data = Zlib::Deflate.deflate(@img_data)
195
- @alpha_channel = Zlib::Deflate.deflate(@alpha_channel)
196
- end
197
- end
198
- end
199
- end
@@ -1,14 +0,0 @@
1
- # encoding: utf-8
2
- module Prawn
3
- # This is used to differentiate strings that must be encoded as
4
- # a *literal* string, versus those that can be encoded in
5
- # the PDF hexadecimal format.
6
- #
7
- # Some features of the PDF format appear to require that literal
8
- # strings be used. One such feature is the /Dest key of a link
9
- # annotation; if a hex encoded string is used there, the links
10
- # do not work (as tested in Mac OS X Preview, and Adobe Acrobat
11
- # Reader).
12
- class LiteralString < String #:nodoc:
13
- end
14
- end
@@ -1,46 +0,0 @@
1
- # encoding: utf-8
2
- # measurement_extensions.rb: Core extensions for Prawn::Measurements
3
- #
4
- # Copyright December 2008, Florian Witteler. All Rights Reserved.
5
- #
6
- # This is free software. Please see the LICENSE and COPYING files for details.
7
-
8
- require 'prawn/measurements'
9
-
10
- class Numeric
11
- include Prawn::Measurements
12
- # prawns' basic unit is PostScript-Point
13
- # 72 points per inch
14
-
15
- def mm
16
- return mm2pt(self)
17
- end
18
-
19
- def cm
20
- return cm2pt(self)
21
- end
22
-
23
- def dm
24
- return dm2pt(self)
25
- end
26
-
27
- def m
28
- return m2pt(self)
29
- end
30
-
31
- def in
32
- return in2pt(self)
33
- end
34
-
35
- def yd
36
- return yd2pt(self)
37
- end
38
-
39
- def ft
40
- return ft2pt(self)
41
- end
42
-
43
- def pt
44
- return self
45
- end
46
- end
@@ -1,71 +0,0 @@
1
- # encoding: utf-8
2
- # measurements.rb: Conversions from other measurements to PDF points
3
- #
4
- # Copyright December 2008, Florian Witteler. All Rights Reserved.
5
- #
6
- module Prawn
7
- module Measurements
8
-
9
- # ============================================================================
10
- #metric conversions
11
- def cm2mm(cm)
12
- return cm*10
13
- end
14
-
15
- def dm2mm(dm)
16
- return dm*100
17
- end
18
-
19
- def m2mm(m)
20
- return m*1000
21
- end
22
-
23
- # ============================================================================
24
- # imperial conversions
25
- # from http://en.wikipedia.org/wiki/Imperial_units
26
-
27
- def ft2in(ft)
28
- return ft * 12
29
- end
30
-
31
- def yd2in(yd)
32
- return yd*36
33
- end
34
-
35
-
36
- # ============================================================================
37
- # PostscriptPoint-converisons
38
-
39
- def in2pt(inch)
40
- return inch * 72
41
- end
42
-
43
- def ft2pt(ft)
44
- return in2pt(ft2in(ft))
45
- end
46
-
47
- def yd2pt(yd)
48
- return in2pt(yd2in(yd))
49
- end
50
-
51
- def mm2pt(mm)
52
- return mm*(72 / 25.4)
53
- end
54
-
55
- def cm2pt(cm)
56
- return mm2pt(cm2mm(cm))
57
- end
58
-
59
- def dm2pt(dm)
60
- return mm2pt(dm2mm(dm))
61
- end
62
-
63
- def m2pt(m)
64
- return mm2pt(m2mm(m))
65
- end
66
-
67
- def pt2mm(pt)
68
- return pt * 1 / mm2pt(1)# (25.4 / 72)
69
- end
70
- end
71
- end
@@ -1,165 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # name_tree.rb : Implements NameTree for PDF
4
- #
5
- # Copyright November 2008, Jamis Buck. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
- #
9
- require 'prawn/literal_string'
10
- require 'prawn/reference'
11
-
12
- module Prawn
13
- module NameTree #:nodoc:
14
- class Node #:nodoc:
15
- attr_reader :children
16
- attr_reader :limit
17
- attr_reader :document
18
- attr_accessor :parent
19
- attr_accessor :ref
20
-
21
- def initialize(document, limit, parent=nil)
22
- @document = document
23
- @children = []
24
- @limit = limit
25
- @parent = parent
26
- @ref = nil
27
- end
28
-
29
- def empty?
30
- children.empty?
31
- end
32
-
33
- def size
34
- leaf? ? children.size : children.inject(0) { |sum, child| sum + child.size }
35
- end
36
-
37
- def leaf?
38
- children.empty? || children.first.is_a?(Value)
39
- end
40
-
41
- def add(name, value)
42
- self << Value.new(name, value)
43
- end
44
-
45
- def to_hash
46
- hash = {}
47
-
48
- hash[:Limits] = [least, greatest] if parent
49
- if leaf?
50
- hash[:Names] = children if leaf?
51
- else
52
- hash[:Kids] = children.map { |child| child.ref }
53
- end
54
-
55
- return hash
56
- end
57
-
58
- def least
59
- if leaf?
60
- children.first.name
61
- else
62
- children.first.least
63
- end
64
- end
65
-
66
- def greatest
67
- if leaf?
68
- children.last.name
69
- else
70
- children.last.greatest
71
- end
72
- end
73
-
74
- def <<(value)
75
- if children.empty?
76
- children << value
77
- elsif leaf?
78
- children.insert(insertion_point(value), value)
79
- split! if children.length > limit
80
- else
81
- fit = children.detect { |child| child >= value }
82
- fit << value
83
- end
84
-
85
- value
86
- end
87
-
88
- def >=(value)
89
- children.empty? || children.last >= value
90
- end
91
-
92
- def split!
93
- if parent
94
- parent.split(self)
95
- else
96
- left, right = new_node(self), new_node(self)
97
- split_children(self, left, right)
98
- children.replace([left, right])
99
- end
100
- end
101
-
102
- protected
103
-
104
- def split(node)
105
- new_child = new_node(self)
106
- split_children(node, node, new_child)
107
- index = children.index(node)
108
- children.insert(index+1, new_child)
109
- split! if children.length > limit
110
- end
111
-
112
- private
113
-
114
- def new_node(parent=nil)
115
- node = Node.new(document, limit, parent)
116
- node.ref = document.ref(node)
117
- return node
118
- end
119
-
120
- def split_children(node, left, right)
121
- half = (node.limit+1)/2
122
-
123
- left_children, right_children = node.children[0...half], node.children[half..-1]
124
-
125
- left.children.replace(left_children)
126
- right.children.replace(right_children)
127
-
128
- unless node.leaf?
129
- left_children.each { |child| child.parent = left }
130
- right_children.each { |child| child.parent = right }
131
- end
132
- end
133
-
134
- def insertion_point(value)
135
- children.each_with_index do |child, index|
136
- return index if child >= value
137
- end
138
- return children.length
139
- end
140
- end
141
-
142
- class Value #:nodoc:
143
- include Comparable
144
-
145
- attr_reader :name
146
- attr_reader :value
147
-
148
- def initialize(name, value)
149
- @name, @value = Prawn::LiteralString.new(name), value
150
- end
151
-
152
- def <=>(leaf)
153
- name <=> leaf.name
154
- end
155
-
156
- def inspect
157
- "#<Value: #{name.inspect} : #{value.inspect}>"
158
- end
159
-
160
- def to_s
161
- "#{name} : #{value}"
162
- end
163
- end
164
- end
165
- end