alphasights-prawn 0.10.0

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 (244) hide show
  1. data/COPYING +340 -0
  2. data/HACKING +50 -0
  3. data/LICENSE +56 -0
  4. data/README +141 -0
  5. data/Rakefile +52 -0
  6. data/data/encodings/win_ansi.txt +29 -0
  7. data/data/fonts/Action Man.dfont +0 -0
  8. data/data/fonts/Activa.ttf +0 -0
  9. data/data/fonts/Chalkboard.ttf +0 -0
  10. data/data/fonts/Courier-Bold.afm +342 -0
  11. data/data/fonts/Courier-BoldOblique.afm +342 -0
  12. data/data/fonts/Courier-Oblique.afm +342 -0
  13. data/data/fonts/Courier.afm +342 -0
  14. data/data/fonts/DejaVuSans.ttf +0 -0
  15. data/data/fonts/Dustismo_Roman.ttf +0 -0
  16. data/data/fonts/Helvetica-Bold.afm +2827 -0
  17. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  18. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  19. data/data/fonts/Helvetica.afm +3051 -0
  20. data/data/fonts/MustRead.html +19 -0
  21. data/data/fonts/Symbol.afm +213 -0
  22. data/data/fonts/Times-Bold.afm +2588 -0
  23. data/data/fonts/Times-BoldItalic.afm +2384 -0
  24. data/data/fonts/Times-Italic.afm +2667 -0
  25. data/data/fonts/Times-Roman.afm +2419 -0
  26. data/data/fonts/ZapfDingbats.afm +225 -0
  27. data/data/fonts/comicsans.ttf +0 -0
  28. data/data/fonts/gkai00mp.ttf +0 -0
  29. data/data/images/16bit.alpha +0 -0
  30. data/data/images/16bit.dat +0 -0
  31. data/data/images/16bit.png +0 -0
  32. data/data/images/arrow.png +0 -0
  33. data/data/images/arrow2.png +0 -0
  34. data/data/images/barcode_issue.png +0 -0
  35. data/data/images/dice.alpha +0 -0
  36. data/data/images/dice.dat +0 -0
  37. data/data/images/dice.png +0 -0
  38. data/data/images/dice_interlaced.png +0 -0
  39. data/data/images/fractal.jpg +0 -0
  40. data/data/images/letterhead.jpg +0 -0
  41. data/data/images/page_white_text.alpha +0 -0
  42. data/data/images/page_white_text.dat +0 -0
  43. data/data/images/page_white_text.png +0 -0
  44. data/data/images/pigs.jpg +0 -0
  45. data/data/images/rails.dat +0 -0
  46. data/data/images/rails.png +0 -0
  47. data/data/images/ruport.png +0 -0
  48. data/data/images/ruport_data.dat +0 -0
  49. data/data/images/ruport_transparent.png +0 -0
  50. data/data/images/ruport_type0.png +0 -0
  51. data/data/images/stef.jpg +0 -0
  52. data/data/images/tru256.bmp +0 -0
  53. data/data/images/web-links.dat +1 -0
  54. data/data/images/web-links.png +0 -0
  55. data/data/pdfs/complex_template.pdf +0 -0
  56. data/data/pdfs/contains_ttf_font.pdf +0 -0
  57. data/data/pdfs/encrypted.pdf +0 -0
  58. data/data/pdfs/hexagon.pdf +61 -0
  59. data/data/pdfs/indirect_reference.pdf +86 -0
  60. data/data/pdfs/nested_pages.pdf +118 -0
  61. data/data/pdfs/resources_as_indirect_object.pdf +83 -0
  62. data/data/pdfs/two_hexagons.pdf +90 -0
  63. data/data/pdfs/version_1_6.pdf +61 -0
  64. data/data/shift_jis_text.txt +1 -0
  65. data/examples/bounding_box/bounding_boxes.rb +43 -0
  66. data/examples/bounding_box/indentation.rb +34 -0
  67. data/examples/bounding_box/russian_boxes.rb +36 -0
  68. data/examples/bounding_box/stretched_nesting.rb +67 -0
  69. data/examples/builder/simple.rb +28 -0
  70. data/examples/example_helper.rb +4 -0
  71. data/examples/general/background.rb +23 -0
  72. data/examples/general/canvas.rb +15 -0
  73. data/examples/general/context_sensitive_headers.rb +37 -0
  74. data/examples/general/float.rb +11 -0
  75. data/examples/general/margin.rb +36 -0
  76. data/examples/general/measurement_units.rb +51 -0
  77. data/examples/general/metadata-info.rb +16 -0
  78. data/examples/general/multi_page_layout.rb +18 -0
  79. data/examples/general/outlines.rb +50 -0
  80. data/examples/general/page_geometry.rb +31 -0
  81. data/examples/general/page_numbering.rb +15 -0
  82. data/examples/general/repeaters.rb +47 -0
  83. data/examples/general/stamp.rb +41 -0
  84. data/examples/general/templates.rb +13 -0
  85. data/examples/graphics/basic_images.rb +23 -0
  86. data/examples/graphics/chunkable.rb +38 -0
  87. data/examples/graphics/cmyk.rb +12 -0
  88. data/examples/graphics/curves.rb +11 -0
  89. data/examples/graphics/hexagon.rb +13 -0
  90. data/examples/graphics/image_fit.rb +15 -0
  91. data/examples/graphics/image_flow.rb +37 -0
  92. data/examples/graphics/image_position.rb +17 -0
  93. data/examples/graphics/line.rb +32 -0
  94. data/examples/graphics/png_types.rb +22 -0
  95. data/examples/graphics/polygons.rb +16 -0
  96. data/examples/graphics/remote_images.rb +12 -0
  97. data/examples/graphics/rounded_polygons.rb +19 -0
  98. data/examples/graphics/rounded_rectangle.rb +20 -0
  99. data/examples/graphics/ruport_style_helpers.rb +19 -0
  100. data/examples/graphics/stroke_bounds.rb +20 -0
  101. data/examples/graphics/stroke_cap_and_join.rb +45 -0
  102. data/examples/graphics/stroke_dash.rb +42 -0
  103. data/examples/graphics/transformations.rb +52 -0
  104. data/examples/graphics/transparency.rb +26 -0
  105. data/examples/m17n/chinese_text_wrapping.rb +17 -0
  106. data/examples/m17n/euro.rb +15 -0
  107. data/examples/m17n/sjis.rb +28 -0
  108. data/examples/m17n/utf8.rb +13 -0
  109. data/examples/m17n/win_ansi_charset.rb +54 -0
  110. data/examples/security/hello_foo.rb +8 -0
  111. data/examples/table/bill.rb +53 -0
  112. data/examples/table/cell.rb +12 -0
  113. data/examples/table/checkerboard.rb +22 -0
  114. data/examples/table/header.rb +14 -0
  115. data/examples/table/inline_format_table.rb +12 -0
  116. data/examples/table/multi_page_table.rb +9 -0
  117. data/examples/table/simple_table.rb +24 -0
  118. data/examples/table/subtable.rb +12 -0
  119. data/examples/table/widths.rb +20 -0
  120. data/examples/text/alignment.rb +18 -0
  121. data/examples/text/character_spacing.rb +12 -0
  122. data/examples/text/dfont.rb +48 -0
  123. data/examples/text/family_based_styling.rb +24 -0
  124. data/examples/text/font_calculations.rb +91 -0
  125. data/examples/text/font_size.rb +33 -0
  126. data/examples/text/hyphenation.rb +45 -0
  127. data/examples/text/indent_paragraphs.rb +22 -0
  128. data/examples/text/inline_format.rb +103 -0
  129. data/examples/text/kerning.rb +30 -0
  130. data/examples/text/rotated.rb +98 -0
  131. data/examples/text/shaped_text_box.rb +31 -0
  132. data/examples/text/simple_text.rb +17 -0
  133. data/examples/text/simple_text_ttf.rb +17 -0
  134. data/examples/text/text_box.rb +88 -0
  135. data/examples/text/text_box_returning_excess.rb +51 -0
  136. data/examples/text/text_flow.rb +67 -0
  137. data/lib/prawn.rb +27 -0
  138. data/lib/prawn/canvas.rb +119 -0
  139. data/lib/prawn/chunkable.rb +37 -0
  140. data/lib/prawn/compatibility.rb +51 -0
  141. data/lib/prawn/core.rb +85 -0
  142. data/lib/prawn/core/annotations.rb +61 -0
  143. data/lib/prawn/core/byte_string.rb +9 -0
  144. data/lib/prawn/core/chunk.rb +36 -0
  145. data/lib/prawn/core/destinations.rb +90 -0
  146. data/lib/prawn/core/document_state.rb +78 -0
  147. data/lib/prawn/core/literal_string.rb +16 -0
  148. data/lib/prawn/core/name_tree.rb +165 -0
  149. data/lib/prawn/core/object_store.rb +236 -0
  150. data/lib/prawn/core/page.rb +179 -0
  151. data/lib/prawn/core/pdf_object.rb +108 -0
  152. data/lib/prawn/core/reference.rb +112 -0
  153. data/lib/prawn/core/text.rb +140 -0
  154. data/lib/prawn/core/text/formatted/arranger.rb +266 -0
  155. data/lib/prawn/core/text/formatted/line_wrap.rb +127 -0
  156. data/lib/prawn/core/text/formatted/wrap.rb +112 -0
  157. data/lib/prawn/core/text/line_wrap.rb +209 -0
  158. data/lib/prawn/core/text/wrap.rb +80 -0
  159. data/lib/prawn/document.rb +573 -0
  160. data/lib/prawn/document/bounding_box.rb +425 -0
  161. data/lib/prawn/document/graphics_state.rb +48 -0
  162. data/lib/prawn/document/internals.rb +170 -0
  163. data/lib/prawn/document/page_geometry.rb +136 -0
  164. data/lib/prawn/document/snapshot.rb +87 -0
  165. data/lib/prawn/document_builder.rb +51 -0
  166. data/lib/prawn/document_builder/command.rb +38 -0
  167. data/lib/prawn/document_builder/constructs.rb +2 -0
  168. data/lib/prawn/document_builder/constructs/flowing_text_construct.rb +18 -0
  169. data/lib/prawn/document_builder/constructs/path_construct.rb +9 -0
  170. data/lib/prawn/document_builder/layout.rb +25 -0
  171. data/lib/prawn/document_builder/modifications.rb +2 -0
  172. data/lib/prawn/document_builder/modifications/layout_modification.rb +9 -0
  173. data/lib/prawn/document_builder/modifications/path_modification.rb +9 -0
  174. data/lib/prawn/encoding.rb +121 -0
  175. data/lib/prawn/errors.rb +94 -0
  176. data/lib/prawn/font.rb +341 -0
  177. data/lib/prawn/font/afm.rb +225 -0
  178. data/lib/prawn/font/dfont.rb +42 -0
  179. data/lib/prawn/font/ttf.rb +350 -0
  180. data/lib/prawn/graphics.rb +325 -0
  181. data/lib/prawn/graphics/cap_style.rb +38 -0
  182. data/lib/prawn/graphics/color.rb +205 -0
  183. data/lib/prawn/graphics/dash.rb +71 -0
  184. data/lib/prawn/graphics/join_style.rb +38 -0
  185. data/lib/prawn/graphics/transformation.rb +156 -0
  186. data/lib/prawn/graphics/transparency.rb +99 -0
  187. data/lib/prawn/images.rb +348 -0
  188. data/lib/prawn/images/jpg.rb +46 -0
  189. data/lib/prawn/images/png.rb +226 -0
  190. data/lib/prawn/measurement_extensions.rb +46 -0
  191. data/lib/prawn/measurements.rb +71 -0
  192. data/lib/prawn/outline.rb +278 -0
  193. data/lib/prawn/repeater.rb +129 -0
  194. data/lib/prawn/security.rb +262 -0
  195. data/lib/prawn/security/arcfour.rb +51 -0
  196. data/lib/prawn/stamp.rb +126 -0
  197. data/lib/prawn/table.rb +421 -0
  198. data/lib/prawn/table/accessors.rb +180 -0
  199. data/lib/prawn/table/cell.rb +350 -0
  200. data/lib/prawn/table/cell/in_table.rb +27 -0
  201. data/lib/prawn/table/cell/subtable.rb +65 -0
  202. data/lib/prawn/table/cell/text.rb +125 -0
  203. data/lib/prawn/text.rb +449 -0
  204. data/lib/prawn/text/box.rb +392 -0
  205. data/lib/prawn/text/formatted.rb +4 -0
  206. data/lib/prawn/text/formatted/box.rb +228 -0
  207. data/lib/prawn/text/formatted/fragment.rb +181 -0
  208. data/lib/prawn/text/formatted/parser.rb +213 -0
  209. data/spec/annotations_spec.rb +90 -0
  210. data/spec/bounding_box_spec.rb +190 -0
  211. data/spec/cell_spec.rb +348 -0
  212. data/spec/destinations_spec.rb +15 -0
  213. data/spec/document_spec.rb +473 -0
  214. data/spec/font_spec.rb +324 -0
  215. data/spec/formatted_text_arranger_spec.rb +426 -0
  216. data/spec/formatted_text_box_spec.rb +756 -0
  217. data/spec/formatted_text_fragment_spec.rb +211 -0
  218. data/spec/graphics_spec.rb +446 -0
  219. data/spec/images_spec.rb +96 -0
  220. data/spec/inline_formatted_text_parser_spec.rb +502 -0
  221. data/spec/jpg_spec.rb +25 -0
  222. data/spec/line_wrap_spec.rb +341 -0
  223. data/spec/measurement_units_spec.rb +23 -0
  224. data/spec/name_tree_spec.rb +112 -0
  225. data/spec/object_store_spec.rb +160 -0
  226. data/spec/outline_spec.rb +269 -0
  227. data/spec/pdf_object_spec.rb +170 -0
  228. data/spec/png_spec.rb +237 -0
  229. data/spec/reference_spec.rb +82 -0
  230. data/spec/repeater_spec.rb +96 -0
  231. data/spec/security_spec.rb +120 -0
  232. data/spec/snapshot_spec.rb +138 -0
  233. data/spec/spec_helper.rb +26 -0
  234. data/spec/stamp_spec.rb +108 -0
  235. data/spec/stroke_styles_spec.rb +163 -0
  236. data/spec/table_spec.rb +598 -0
  237. data/spec/template_spec.rb +158 -0
  238. data/spec/text_at_spec.rb +119 -0
  239. data/spec/text_box_spec.rb +742 -0
  240. data/spec/text_spacing_spec.rb +75 -0
  241. data/spec/text_spec.rb +333 -0
  242. data/spec/text_with_inline_formatting_spec.rb +193 -0
  243. data/spec/transparency_spec.rb +89 -0
  244. metadata +331 -0
@@ -0,0 +1,46 @@
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 JPG image that we need to embed them in a PDF
15
+ #
16
+ class JPG
17
+ attr_reader :width, :height, :bits, :channels
18
+ attr_accessor :scaled_width, :scaled_height
19
+
20
+ JPEG_SOF_BLOCKS = %W(\xc0 \xc1 \xc2 \xc3 \xc5 \xc6 \xc7 \xc9 \xca \xcb \xcd \xce \xcf)
21
+ JPEG_APP_BLOCKS = %W(\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef)
22
+
23
+ # Process a new JPG image
24
+ #
25
+ # <tt>:data</tt>:: A binary string of JPEG data
26
+ #
27
+ def initialize(data)
28
+ data = StringIO.new(data.dup)
29
+
30
+ c_marker = "\xff" # Section marker.
31
+ data.read(2) # Skip the first two bytes of JPEG identifier.
32
+ loop do
33
+ marker, code, length = data.read(4).unpack('aan')
34
+ raise "JPEG marker not found!" if marker != c_marker
35
+
36
+ if JPEG_SOF_BLOCKS.include?(code)
37
+ @bits, @height, @width, @channels = data.read(6).unpack("CnnC")
38
+ break
39
+ end
40
+
41
+ buffer = data.read(length - 2)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,226 @@
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
+ require 'enumerator'
13
+
14
+ module Prawn
15
+ module Images
16
+ # A convenience class that wraps the logic for extracting the parts
17
+ # of a PNG image that we need to embed them in a PDF
18
+ #
19
+ class PNG
20
+ attr_reader :palette, :img_data, :transparency
21
+ attr_reader :width, :height, :bits
22
+ attr_reader :color_type, :compression_method, :filter_method
23
+ attr_reader :interlace_method, :alpha_channel
24
+ attr_accessor :scaled_width, :scaled_height
25
+
26
+ # Process a new PNG image
27
+ #
28
+ # <tt>data</tt>:: A binary string of PNG data
29
+ #
30
+ def initialize(data)
31
+ data = StringIO.new(data.dup)
32
+
33
+ data.read(8) # Skip the default header
34
+
35
+ @palette = ""
36
+ @img_data = ""
37
+ @transparency = {}
38
+
39
+ loop do
40
+ chunk_size = data.read(4).unpack("N")[0]
41
+ section = data.read(4)
42
+ case section
43
+ when 'IHDR'
44
+ # we can grab other interesting values from here (like width,
45
+ # height, etc)
46
+ values = data.read(chunk_size).unpack("NNCCCCC")
47
+
48
+ @width = values[0]
49
+ @height = values[1]
50
+ @bits = values[2]
51
+ @color_type = values[3]
52
+ @compression_method = values[4]
53
+ @filter_method = values[5]
54
+ @interlace_method = values[6]
55
+ when 'PLTE'
56
+ @palette << data.read(chunk_size)
57
+ when 'IDAT'
58
+ @img_data << data.read(chunk_size)
59
+ when 'tRNS'
60
+ # This chunk can only occur once and it must occur after the
61
+ # PLTE chunk and before the IDAT chunk
62
+ @transparency = {}
63
+ case @color_type
64
+ when 3
65
+ # Indexed colour, RGB. Each byte in this chunk is an alpha for
66
+ # the palette index in the PLTE ("palette") chunk up until the
67
+ # last non-opaque entry. Set up an array, stretching over all
68
+ # palette entries which will be 0 (opaque) or 1 (transparent).
69
+ @transparency[:indexed] = data.read(chunk_size).unpack("C*")
70
+ short = 255 - @transparency[:indexed].size
71
+ @transparency[:indexed] += ([255] * short) if short > 0
72
+ when 0
73
+ # Greyscale. Corresponding to entries in the PLTE chunk.
74
+ # Grey is two bytes, range 0 .. (2 ^ bit-depth) - 1
75
+ grayval = data.read(chunk_size).unpack("n").first
76
+ @transparency[:grayscale] = grayval
77
+ when 2
78
+ # True colour with proper alpha channel.
79
+ @transparency[:rgb] = data.read(chunk_size).unpack("nnn")
80
+ end
81
+ when 'IEND'
82
+ # we've got everything we need, exit the loop
83
+ break
84
+ else
85
+ # unknown (or un-important) section, skip over it
86
+ data.seek(data.pos + chunk_size)
87
+ end
88
+
89
+ data.read(4) # Skip the CRC
90
+ end
91
+ end
92
+
93
+ # number of color components to each pixel
94
+ #
95
+ def colors
96
+ case self.color_type
97
+ when 0, 3, 4
98
+ return 1
99
+ when 2, 6
100
+ return 3
101
+ end
102
+ end
103
+
104
+ # number of bits used per pixel
105
+ #
106
+ def pixel_bitlength
107
+ if alpha_channel?
108
+ self.bits * (self.colors + 1)
109
+ else
110
+ self.bits * self.colors
111
+ end
112
+ end
113
+
114
+ # split the alpha channel data from the raw image data in images
115
+ # where it's required.
116
+ #
117
+ def split_alpha_channel!
118
+ unfilter_image_data if alpha_channel?
119
+ end
120
+
121
+ def alpha_channel?
122
+ @color_type == 4 || @color_type == 6
123
+ end
124
+
125
+ # Adobe Reader can't handle 16-bit png channels -- chop off the second
126
+ # byte (least significant)
127
+ #
128
+ def alpha_channel_bits
129
+ 8
130
+ end
131
+
132
+ private
133
+
134
+ def unfilter_image_data
135
+ data = Zlib::Inflate.inflate(@img_data).unpack 'C*'
136
+ @img_data = ""
137
+ @alpha_channel = ""
138
+
139
+ pixel_bytes = pixel_bitlength / 8
140
+ scanline_length = pixel_bytes * self.width + 1
141
+ row = 0
142
+ pixels = []
143
+ paeth, pa, pb, pc = nil
144
+ until data.empty? do
145
+ row_data = data.slice! 0, scanline_length
146
+ filter = row_data.shift
147
+ case filter
148
+ when 0 # None
149
+ when 1 # Sub
150
+ row_data.each_with_index do |byte, index|
151
+ left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
152
+ row_data[index] = (byte + left) % 256
153
+ #p [byte, left, row_data[index]]
154
+ end
155
+ when 2 # Up
156
+ row_data.each_with_index do |byte, index|
157
+ col = index / pixel_bytes
158
+ upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_bytes]
159
+ row_data[index] = (upper + byte) % 256
160
+ end
161
+ when 3 # Average
162
+ row_data.each_with_index do |byte, index|
163
+ col = index / pixel_bytes
164
+ upper = row == 0 ? 0 : pixels[row-1][col][index % pixel_bytes]
165
+ left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
166
+
167
+ row_data[index] = (byte + ((left + upper)/2).floor) % 256
168
+ end
169
+ when 4 # Paeth
170
+ left = upper = upper_left = nil
171
+ row_data.each_with_index do |byte, index|
172
+ col = index / pixel_bytes
173
+
174
+ left = index < pixel_bytes ? 0 : row_data[index - pixel_bytes]
175
+ if row.zero?
176
+ upper = upper_left = 0
177
+ else
178
+ upper = pixels[row-1][col][index % pixel_bytes]
179
+ upper_left = col.zero? ? 0 :
180
+ pixels[row-1][col-1][index % pixel_bytes]
181
+ end
182
+
183
+ p = left + upper - upper_left
184
+ pa = (p - left).abs
185
+ pb = (p - upper).abs
186
+ pc = (p - upper_left).abs
187
+
188
+ paeth = if pa <= pb && pa <= pc
189
+ left
190
+ elsif pb <= pc
191
+ upper
192
+ else
193
+ upper_left
194
+ end
195
+
196
+ row_data[index] = (byte + paeth) % 256
197
+ end
198
+ else
199
+ raise ArgumentError, "Invalid filter algorithm #{filter}"
200
+ end
201
+
202
+ s = []
203
+ row_data.each_slice pixel_bytes do |slice|
204
+ s << slice
205
+ end
206
+ pixels << s
207
+ row += 1
208
+ end
209
+
210
+ # convert the pixel data to seperate strings for colours and alpha
211
+ color_byte_size = self.colors * self.bits / 8
212
+ alpha_byte_size = alpha_channel_bits / 8
213
+ pixels.each do |this_row|
214
+ this_row.each do |pixel|
215
+ @img_data << pixel[0, color_byte_size].pack("C*")
216
+ @alpha_channel << pixel[color_byte_size, alpha_byte_size].pack("C*")
217
+ end
218
+ end
219
+
220
+ # compress the data
221
+ @img_data = Zlib::Deflate.deflate(@img_data)
222
+ @alpha_channel = Zlib::Deflate.deflate(@alpha_channel)
223
+ end
224
+ end
225
+ end
226
+ 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,278 @@
1
+ # encoding: utf-8
2
+ #
3
+ # generates outline dictionary and items for document
4
+ #
5
+ # Author Jonathan Greenberg
6
+
7
+ require 'forwardable'
8
+
9
+ module Prawn
10
+
11
+ class Document
12
+
13
+ # See Outline#define below for documentation
14
+ def define_outline(&block)
15
+ outline.define(&block)
16
+ end
17
+
18
+ # The Outline dictionary (12.3.3) for this document. It is
19
+ # lazily initialized, so that documents that do not have an outline
20
+ # do not incur the additional overhead.
21
+ def outline_root(outline_root)
22
+ state.store.root.data[:Outlines] ||= ref!(outline_root)
23
+ end
24
+
25
+ # Lazily instantiates an Outline object for document. This is used as point of entry
26
+ # to methods to build the outline tree.
27
+ def outline
28
+ @outline ||= Outline.new(self)
29
+ end
30
+
31
+ end
32
+
33
+ # The Outline class organizes the outline tree items for the document.
34
+ # Note that the prev and parent instance variables are adjusted while navigating
35
+ # through the nested blocks. These variables along with the presence or absense
36
+ # of blocks are the primary means by which the relations for the various
37
+ # OutlineItems and the OutlineRoot are set. Unfortunately, the best way to
38
+ # understand how this works is to follow the method calls through a real example.
39
+ #
40
+ # Some ideas for the organization of this class were gleaned from name_tree. In
41
+ # particular the way in which the OutlineItems are finally rendered into document
42
+ # objects in PdfObject through a hash.
43
+ #
44
+ class Outline
45
+
46
+ extend Forwardable
47
+ def_delegator :@document, :page_number
48
+
49
+ attr_accessor :parent
50
+ attr_accessor :prev
51
+ attr_accessor :document
52
+ attr_accessor :outline_root
53
+ attr_accessor :items
54
+
55
+ def initialize(document)
56
+ @document = document
57
+ @outline_root = document.outline_root(OutlineRoot.new)
58
+ @parent = outline_root
59
+ @prev = nil
60
+ @items = {}
61
+ end
62
+
63
+ # Defines an outline for the document.
64
+ # The outline is an optional nested index that appears on the side of a PDF
65
+ # document usually with direct links to pages. The outline DSL is defined by nested
66
+ # blocks involving two methods: section and page.
67
+ #
68
+ # section(title, options{}, &block)
69
+ # title: the outline text that appears for the section.
70
+ # options: page - optional integer defining the page number for a destination link.
71
+ # - currently only :FIT destination supported with link to top of page.
72
+ # closed - whether the section should show its nested outline elements.
73
+ # - defaults to false.
74
+ # page(page, options{})
75
+ # page: integer defining the page number for the destination link.
76
+ # currently only :FIT destination supported with link to top of page.
77
+ # set to nil if destination link is not desired.
78
+ # options: title - the outline text that appears for the section.
79
+ # closed - whether the section should show its nested outline elements.
80
+ # - defaults to false.
81
+ #
82
+ # The syntax is best illustrated with an example:
83
+ #
84
+ # Prawn::Document.generate(outlined document) do
85
+ # text "Page 1. This is the first Chapter. "
86
+ # start_new_page
87
+ # text "Page 2. More in the first Chapter. "
88
+ # start_new_page
89
+ # define_outline do
90
+ # section 'Chapter 1', :page => 1, :closed => true do
91
+ # page 1, :title => 'Page 1'
92
+ # page 2, :title => 'Page 2'
93
+ # end
94
+ # end
95
+ # end
96
+ #
97
+ # It should be noted that not defining a title for a page element will raise
98
+ # a RequiredOption error
99
+ #
100
+ def define(&block)
101
+ if block
102
+ block.arity < 1 ? instance_eval(&block) : block[self]
103
+ end
104
+ end
105
+
106
+ # Adds an outine section to the outline tree (see define_outline).
107
+ # Although you will probably choose to exclusively use define_outline so
108
+ # that your outline tree is contained and easy to manage, this method
109
+ # gives you the option to add sections to the outline tree at any point
110
+ # during document generation. Note that the section will be added at the
111
+ # top level at the end of the outline. For more a more flexible API try
112
+ # using outline.insert_section_after.
113
+ #
114
+ # block uses the same DSL syntax as define_outline, for example:
115
+ #
116
+ # outline.add_section do
117
+ # section 'Added Section', :page => 3 do
118
+ # page 3, :title => 'Page 3'
119
+ # end
120
+ # end
121
+ def add_section(&block)
122
+ @parent = outline_root
123
+ @prev = outline_root.data.last
124
+ if block
125
+ block.arity < 1 ? instance_eval(&block) : block[self]
126
+ end
127
+ end
128
+
129
+ # Inserts an outline section to the outline tree (see define_outline).
130
+ # Although you will probably choose to exclusively use define_outline so
131
+ # that your outline tree is contained and easy to manage, this method
132
+ # gives you the option to insert sections to the outline tree at any point
133
+ # during document generation. Unlike outline.add_section, this method allows
134
+ # you to enter a section after any other item at any level in the outline tree.
135
+ # Currently the only way to locate the place of entry is with the title for the
136
+ # item. If your titles names are not unique consider using define_outline.
137
+ #
138
+ # block uses the same DSL syntax as define_outline, for example:
139
+ #
140
+ # go_to_page 2
141
+ # start_new_page
142
+ # text "Inserted Page"
143
+ # outline.insert_section_after :title => 'Page 2' do
144
+ # page page_number, :title => "Inserted Page"
145
+ # end
146
+ #
147
+ def insert_section_after(title, &block)
148
+ @prev = items[title]
149
+ if @prev
150
+ @parent = @prev.data.parent
151
+ nxt = @prev.data.next
152
+ if block
153
+ block.arity < 1 ? instance_eval(&block) : block[self]
154
+ end
155
+ adjust_relations(nxt)
156
+ else
157
+ raise Prawn::Errors::UnknownOutlineTitle,
158
+ "\n No outline item with title: '#{title}' exists in the outline tree"
159
+ end
160
+ end
161
+
162
+ private
163
+
164
+ def section(title, options = {}, &block)
165
+ add_outline_item(title, options, &block)
166
+ end
167
+
168
+ def page(page = nil, options = {})
169
+ if options[:title]
170
+ title = options[:title]
171
+ options[:page] = page
172
+ else
173
+ raise Prawn::Errors::RequiredOption,
174
+ "\nTitle is a required option for page"
175
+ end
176
+ add_outline_item(title, options)
177
+ end
178
+
179
+ def add_outline_item(title, options, &block)
180
+ outline_item = create_outline_item(title, options)
181
+ set_relations(outline_item)
182
+ increase_count
183
+ set_variables_for_block(outline_item, block)
184
+ block.call if block
185
+ reset_parent(outline_item)
186
+ end
187
+
188
+ def create_outline_item(title, options)
189
+ outline_item = OutlineItem.new(title, parent, options)
190
+
191
+ if options[:page]
192
+ page_index = options[:page] - 1
193
+ outline_item.dest = [document.state.pages[page_index].dictionary, :Fit]
194
+ end
195
+
196
+ outline_item.prev = prev if @prev
197
+ items[title] = document.ref!(outline_item)
198
+ end
199
+
200
+ def set_relations(outline_item)
201
+ prev.data.next = outline_item if prev
202
+ parent.data.first = outline_item unless prev
203
+ parent.data.last = outline_item
204
+ end
205
+
206
+ def increase_count
207
+ counting_parent = parent
208
+ while counting_parent
209
+ counting_parent.data.count += 1
210
+ if counting_parent == outline_root
211
+ counting_parent = nil
212
+ else
213
+ counting_parent = counting_parent.data.parent
214
+ end
215
+ end
216
+ end
217
+
218
+ def set_variables_for_block(outline_item, block)
219
+ self.prev = block ? nil : outline_item
220
+ self.parent = outline_item if block
221
+ end
222
+
223
+ def reset_parent(outline_item)
224
+ if parent == outline_item
225
+ self.prev = outline_item
226
+ self.parent = outline_item.data.parent
227
+ end
228
+ end
229
+
230
+ def adjust_relations(nxt)
231
+ if nxt
232
+ nxt.data.prev = @prev
233
+ @prev.data.next = nxt
234
+ @parent.data.last = nxt
235
+ else
236
+ @parent.data.last = @prev
237
+ end
238
+ end
239
+
240
+ end
241
+
242
+ class OutlineRoot #:nodoc:
243
+ attr_accessor :count, :first, :last
244
+
245
+ def initialize
246
+ @count = 0
247
+ end
248
+
249
+ def to_hash
250
+ {:Type => :Outlines, :Count => count, :First => first, :Last => last}
251
+ end
252
+ end
253
+
254
+ class OutlineItem #:nodoc:
255
+ attr_accessor :count, :first, :last, :next, :prev, :parent, :title, :dest, :closed
256
+
257
+ def initialize(title, parent, options)
258
+ @closed = options[:closed]
259
+ @title = title
260
+ @parent = parent
261
+ @count = 0
262
+ end
263
+
264
+ def to_hash
265
+ hash = { :Title => title,
266
+ :Parent => parent,
267
+ :Count => closed ? -count : count }
268
+ [{:First => first}, {:Last => last}, {:Next => @next},
269
+ {:Prev => prev}, {:Dest => dest}].each do |h|
270
+ unless h.values.first.nil?
271
+ hash.merge!(h)
272
+ end
273
+ end
274
+ hash
275
+ end
276
+ end
277
+ end
278
+