prawn 0.4.1 → 0.5.0.1

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