prawn-core 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 (186) hide show
  1. data/COPYING +340 -0
  2. data/LICENSE +56 -0
  3. data/README +121 -0
  4. data/Rakefile +74 -0
  5. data/data/encodings/win_ansi.txt +29 -0
  6. data/data/fonts/Action Man.dfont +0 -0
  7. data/data/fonts/Activa.ttf +0 -0
  8. data/data/fonts/Chalkboard.ttf +0 -0
  9. data/data/fonts/Courier-Bold.afm +342 -0
  10. data/data/fonts/Courier-BoldOblique.afm +342 -0
  11. data/data/fonts/Courier-Oblique.afm +342 -0
  12. data/data/fonts/Courier.afm +342 -0
  13. data/data/fonts/DejaVuSans.ttf +0 -0
  14. data/data/fonts/Dustismo_Roman.ttf +0 -0
  15. data/data/fonts/Helvetica-Bold.afm +2827 -0
  16. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  17. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  18. data/data/fonts/Helvetica.afm +3051 -0
  19. data/data/fonts/MustRead.html +19 -0
  20. data/data/fonts/Symbol.afm +213 -0
  21. data/data/fonts/Times-Bold.afm +2588 -0
  22. data/data/fonts/Times-BoldItalic.afm +2384 -0
  23. data/data/fonts/Times-Italic.afm +2667 -0
  24. data/data/fonts/Times-Roman.afm +2419 -0
  25. data/data/fonts/ZapfDingbats.afm +225 -0
  26. data/data/fonts/comicsans.ttf +0 -0
  27. data/data/fonts/gkai00mp.ttf +0 -0
  28. data/data/images/16bit.alpha +0 -0
  29. data/data/images/16bit.dat +0 -0
  30. data/data/images/16bit.png +0 -0
  31. data/data/images/arrow.png +0 -0
  32. data/data/images/arrow2.png +0 -0
  33. data/data/images/barcode_issue.png +0 -0
  34. data/data/images/dice.alpha +0 -0
  35. data/data/images/dice.dat +0 -0
  36. data/data/images/dice.png +0 -0
  37. data/data/images/dice_interlaced.png +0 -0
  38. data/data/images/fractal.jpg +0 -0
  39. data/data/images/letterhead.jpg +0 -0
  40. data/data/images/page_white_text.alpha +0 -0
  41. data/data/images/page_white_text.dat +0 -0
  42. data/data/images/page_white_text.png +0 -0
  43. data/data/images/pigs.jpg +0 -0
  44. data/data/images/rails.dat +0 -0
  45. data/data/images/rails.png +0 -0
  46. data/data/images/ruport.png +0 -0
  47. data/data/images/ruport_data.dat +0 -0
  48. data/data/images/ruport_transparent.png +0 -0
  49. data/data/images/ruport_type0.png +0 -0
  50. data/data/images/stef.jpg +0 -0
  51. data/data/images/tru256.bmp +0 -0
  52. data/data/images/web-links.dat +1 -0
  53. data/data/images/web-links.png +0 -0
  54. data/data/shift_jis_text.txt +1 -0
  55. data/examples/bounding_box/bounding_boxes.rb +44 -0
  56. data/examples/bounding_box/russian_boxes.rb +37 -0
  57. data/examples/column_box/column_box_example.rb +44 -0
  58. data/examples/general/background.rb +20 -0
  59. data/examples/general/canvas.rb +16 -0
  60. data/examples/general/measurement_units.rb +52 -0
  61. data/examples/general/metadata-info.rb +17 -0
  62. data/examples/general/multi_page_layout.rb +17 -0
  63. data/examples/general/page_geometry.rb +32 -0
  64. data/examples/graphics/basic_images.rb +24 -0
  65. data/examples/graphics/cmyk.rb +13 -0
  66. data/examples/graphics/curves.rb +12 -0
  67. data/examples/graphics/hexagon.rb +14 -0
  68. data/examples/graphics/image_fit.rb +16 -0
  69. data/examples/graphics/image_flow.rb +38 -0
  70. data/examples/graphics/image_position.rb +18 -0
  71. data/examples/graphics/line.rb +33 -0
  72. data/examples/graphics/png_types.rb +23 -0
  73. data/examples/graphics/polygons.rb +17 -0
  74. data/examples/graphics/remote_images.rb +12 -0
  75. data/examples/graphics/ruport_style_helpers.rb +20 -0
  76. data/examples/graphics/stroke_bounds.rb +21 -0
  77. data/examples/m17n/chinese_text_wrapping.rb +20 -0
  78. data/examples/m17n/euro.rb +16 -0
  79. data/examples/m17n/sjis.rb +29 -0
  80. data/examples/m17n/utf8.rb +14 -0
  81. data/examples/m17n/win_ansi_charset.rb +55 -0
  82. data/examples/text/alignment.rb +19 -0
  83. data/examples/text/dfont.rb +49 -0
  84. data/examples/text/family_based_styling.rb +25 -0
  85. data/examples/text/font_calculations.rb +92 -0
  86. data/examples/text/font_size.rb +34 -0
  87. data/examples/text/kerning.rb +31 -0
  88. data/examples/text/simple_text.rb +18 -0
  89. data/examples/text/simple_text_ttf.rb +18 -0
  90. data/examples/text/span.rb +30 -0
  91. data/examples/text/text_box.rb +26 -0
  92. data/examples/text/text_flow.rb +68 -0
  93. data/lib/prawn/compatibility.rb +38 -0
  94. data/lib/prawn/core.rb +79 -0
  95. data/lib/prawn/document.rb +399 -0
  96. data/lib/prawn/document/annotations.rb +63 -0
  97. data/lib/prawn/document/bounding_box.rb +377 -0
  98. data/lib/prawn/document/column_box.rb +89 -0
  99. data/lib/prawn/document/destinations.rb +81 -0
  100. data/lib/prawn/document/internals.rb +133 -0
  101. data/lib/prawn/document/page_geometry.rb +149 -0
  102. data/lib/prawn/document/span.rb +55 -0
  103. data/lib/prawn/document/text.rb +186 -0
  104. data/lib/prawn/document/text/box.rb +83 -0
  105. data/lib/prawn/document/text/wrapping.rb +59 -0
  106. data/lib/prawn/encoding.rb +121 -0
  107. data/lib/prawn/errors.rb +49 -0
  108. data/lib/prawn/font.rb +292 -0
  109. data/lib/prawn/font/afm.rb +202 -0
  110. data/lib/prawn/font/dfont.rb +31 -0
  111. data/lib/prawn/font/ttf.rb +327 -0
  112. data/lib/prawn/graphics.rb +257 -0
  113. data/lib/prawn/graphics/color.rb +141 -0
  114. data/lib/prawn/images.rb +339 -0
  115. data/lib/prawn/images/jpg.rb +45 -0
  116. data/lib/prawn/images/png.rb +217 -0
  117. data/lib/prawn/literal_string.rb +14 -0
  118. data/lib/prawn/measurement_extensions.rb +46 -0
  119. data/lib/prawn/measurements.rb +71 -0
  120. data/lib/prawn/name_tree.rb +165 -0
  121. data/lib/prawn/pdf_object.rb +77 -0
  122. data/lib/prawn/reference.rb +59 -0
  123. data/spec/annotations_spec.rb +90 -0
  124. data/spec/bounding_box_spec.rb +141 -0
  125. data/spec/destinations_spec.rb +15 -0
  126. data/spec/document_spec.rb +178 -0
  127. data/spec/font_spec.rb +274 -0
  128. data/spec/graphics_spec.rb +209 -0
  129. data/spec/images_spec.rb +79 -0
  130. data/spec/jpg_spec.rb +25 -0
  131. data/spec/measurement_units_spec.rb +23 -0
  132. data/spec/name_tree_spec.rb +103 -0
  133. data/spec/pdf_object_spec.rb +117 -0
  134. data/spec/png_spec.rb +236 -0
  135. data/spec/reference_spec.rb +42 -0
  136. data/spec/span_spec.rb +45 -0
  137. data/spec/spec_helper.rb +23 -0
  138. data/spec/text_box_spec.rb +83 -0
  139. data/spec/text_spec.rb +178 -0
  140. data/vendor/pdf-inspector/README +18 -0
  141. data/vendor/pdf-inspector/lib/pdf/inspector.rb +25 -0
  142. data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +80 -0
  143. data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +16 -0
  144. data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +31 -0
  145. data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +19 -0
  146. data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
  147. data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
  148. data/vendor/ttfunk/example.rb +45 -0
  149. data/vendor/ttfunk/lib/ttfunk.rb +102 -0
  150. data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
  151. data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
  152. data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
  153. data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
  154. data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
  155. data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
  156. data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
  157. data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +46 -0
  158. data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
  159. data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
  160. data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +51 -0
  161. data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
  162. data/vendor/ttfunk/lib/ttfunk/table.rb +46 -0
  163. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +34 -0
  164. data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
  165. data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
  166. data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +79 -0
  167. data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
  168. data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
  169. data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
  170. data/vendor/ttfunk/lib/ttfunk/table/head.rb +44 -0
  171. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +41 -0
  172. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +47 -0
  173. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +79 -0
  174. data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
  175. data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
  176. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +40 -0
  177. data/vendor/ttfunk/lib/ttfunk/table/name.rb +119 -0
  178. data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
  179. data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
  180. data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
  181. data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
  182. data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
  183. data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
  184. data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
  185. data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
  186. metadata +245 -0
@@ -0,0 +1,45 @@
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
@@ -0,0 +1,217 @@
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
+ end
90
+
91
+ # number of color components to each pixel
92
+ #
93
+ def colors
94
+ case self.color_type
95
+ when 0, 3, 4
96
+ return 1
97
+ when 2, 6
98
+ return 3
99
+ end
100
+ end
101
+
102
+ # number of bits used per pixel
103
+ #
104
+ def pixel_bitlength
105
+ if alpha_channel?
106
+ self.bits * (self.colors + 1)
107
+ else
108
+ self.bits * self.colors
109
+ end
110
+ end
111
+
112
+ # split the alpha channel data from the raw image data in images
113
+ # where it's required.
114
+ #
115
+ def split_alpha_channel!
116
+ unfilter_image_data if alpha_channel?
117
+ end
118
+
119
+ private
120
+
121
+ def alpha_channel?
122
+ @color_type == 4 || @color_type == 6
123
+ end
124
+
125
+ def unfilter_image_data
126
+ data = Zlib::Inflate.inflate(@img_data).unpack 'C*'
127
+ @img_data = ""
128
+ @alpha_channel = ""
129
+
130
+ pixel_bytes = pixel_bitlength / 8
131
+ scanline_length = pixel_bytes * self.width + 1
132
+ row = 0
133
+ pixels = []
134
+ paeth, pa, pb, pc = nil
135
+ until data.empty? do
136
+ row_data = data.slice! 0, scanline_length
137
+ filter = row_data.shift
138
+ case filter
139
+ when 0 # None
140
+ when 1 # Sub
141
+ row_data.each_with_index do |byte, index|
142
+ left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
143
+ row_data[index] = (byte + left) % 256
144
+ #p [byte, left, row_data[index]]
145
+ end
146
+ when 2 # Up
147
+ row_data.each_with_index do |byte, index|
148
+ col = index / pixel_bytes
149
+ upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_bytes]
150
+ row_data[index] = (upper + byte) % 256
151
+ end
152
+ when 3 # Average
153
+ row_data.each_with_index do |byte, index|
154
+ col = index / pixel_bytes
155
+ upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_bytes]
156
+ left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
157
+
158
+ row_data[index] = (byte + ((left + upper)/2).floor) % 256
159
+ end
160
+ when 4 # Paeth
161
+ left = upper = upper_left = nil
162
+ row_data.each_with_index do |byte, index|
163
+ col = index / pixel_bytes
164
+
165
+ left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
166
+ if row.zero?
167
+ upper = upper_left = 0
168
+ else
169
+ upper = pixels[row-1][col][index % pixel_bytes]
170
+ upper_left = col.zero? ? 0 :
171
+ pixels[row-1][col-1][index % pixel_bytes]
172
+ end
173
+
174
+ p = left + upper - upper_left
175
+ pa = (p - left).abs
176
+ pb = (p - upper).abs
177
+ pc = (p - upper_left).abs
178
+
179
+ paeth = if pa <= pb && pa <= pc
180
+ left
181
+ elsif pb <= pc
182
+ upper
183
+ else
184
+ upper_left
185
+ end
186
+
187
+ row_data[index] = (byte + paeth) % 256
188
+ end
189
+ else
190
+ raise ArgumentError, "Invalid filter algorithm #{filter}"
191
+ end
192
+
193
+ s = []
194
+ row_data.each_slice pixel_bytes do |slice|
195
+ s << slice
196
+ end
197
+ pixels << s
198
+ row += 1
199
+ end
200
+
201
+ # convert the pixel data to seperate strings for colours and alpha
202
+ color_byte_size = self.colors * self.bits / 8
203
+ alpha_byte_size = self.bits / 8
204
+ pixels.each do |row|
205
+ row.each do |pixel|
206
+ @img_data << pixel[0, color_byte_size].pack("C*")
207
+ @alpha_channel << pixel[color_byte_size, alpha_byte_size].pack("C*")
208
+ end
209
+ end
210
+
211
+ # compress the data
212
+ @img_data = Zlib::Deflate.deflate(@img_data)
213
+ @alpha_channel = Zlib::Deflate.deflate(@alpha_channel)
214
+ end
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,14 @@
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
@@ -0,0 +1,46 @@
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
@@ -0,0 +1,71 @@
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
@@ -0,0 +1,165 @@
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