prawn 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (282) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +2 -2
  3. data/Gemfile +18 -0
  4. data/LICENSE +1 -1
  5. data/README.md +17 -4
  6. data/Rakefile +18 -22
  7. data/data/images/indexed_color.dat +0 -0
  8. data/data/images/indexed_color.png +0 -0
  9. data/data/pdfs/nested_pages.pdf +13 -13
  10. data/lib/pdf/core.rb +35 -0
  11. data/lib/{prawn → pdf}/core/annotations.rb +6 -7
  12. data/lib/{prawn → pdf}/core/byte_string.rb +1 -1
  13. data/lib/{prawn → pdf}/core/destinations.rb +23 -23
  14. data/lib/{prawn → pdf}/core/document_state.rb +8 -8
  15. data/lib/pdf/core/filter_list.rb +51 -0
  16. data/lib/pdf/core/filters.rb +36 -0
  17. data/lib/pdf/core/graphics_state.rb +68 -0
  18. data/lib/{prawn → pdf}/core/literal_string.rb +1 -1
  19. data/lib/{prawn → pdf}/core/name_tree.rb +14 -2
  20. data/lib/{prawn → pdf}/core/object_store.rb +80 -24
  21. data/lib/pdf/core/outline.rb +315 -0
  22. data/lib/{prawn → pdf}/core/page.rb +23 -26
  23. data/lib/{prawn/document → pdf/core}/page_geometry.rb +11 -21
  24. data/lib/{prawn → pdf}/core/pdf_object.rb +48 -32
  25. data/lib/{prawn → pdf}/core/reference.rb +35 -44
  26. data/lib/pdf/core/stream.rb +98 -0
  27. data/lib/{prawn → pdf}/core/text.rb +24 -17
  28. data/lib/prawn.rb +95 -17
  29. data/lib/prawn/compatibility.rb +66 -26
  30. data/lib/prawn/document.rb +48 -30
  31. data/lib/prawn/document/bounding_box.rb +3 -3
  32. data/lib/prawn/document/column_box.rb +46 -8
  33. data/lib/prawn/document/graphics_state.rb +10 -73
  34. data/lib/prawn/document/internals.rb +24 -23
  35. data/lib/prawn/document/snapshot.rb +6 -7
  36. data/lib/prawn/document/span.rb +10 -10
  37. data/lib/prawn/encoding.rb +7 -7
  38. data/lib/prawn/errors.rb +18 -29
  39. data/lib/prawn/font.rb +64 -28
  40. data/lib/prawn/font/afm.rb +32 -74
  41. data/lib/prawn/font/dfont.rb +2 -2
  42. data/lib/prawn/font/ttf.rb +28 -57
  43. data/lib/prawn/font_metric_cache.rb +45 -0
  44. data/lib/prawn/graphics.rb +307 -41
  45. data/lib/prawn/graphics/cap_style.rb +3 -3
  46. data/lib/prawn/graphics/color.rb +12 -5
  47. data/lib/prawn/graphics/dash.rb +52 -31
  48. data/lib/prawn/graphics/join_style.rb +7 -7
  49. data/lib/prawn/graphics/patterns.rb +137 -0
  50. data/lib/prawn/graphics/transformation.rb +9 -9
  51. data/lib/prawn/graphics/transparency.rb +1 -1
  52. data/lib/prawn/image_handler.rb +30 -0
  53. data/lib/prawn/images.rb +86 -105
  54. data/lib/prawn/images/image.rb +48 -0
  55. data/lib/prawn/images/jpg.rb +14 -10
  56. data/lib/prawn/images/png.rb +50 -37
  57. data/lib/prawn/layout.rb +2 -2
  58. data/lib/prawn/layout/grid.rb +51 -51
  59. data/lib/prawn/measurement_extensions.rb +5 -5
  60. data/lib/prawn/measurements.rb +25 -21
  61. data/lib/prawn/outline.rb +4 -308
  62. data/lib/prawn/repeater.rb +8 -8
  63. data/lib/prawn/security.rb +50 -36
  64. data/lib/prawn/soft_mask.rb +94 -0
  65. data/lib/prawn/stamp.rb +3 -3
  66. data/lib/prawn/table.rb +292 -118
  67. data/lib/prawn/table/cell.rb +272 -45
  68. data/lib/prawn/table/cell/image.rb +70 -0
  69. data/lib/prawn/table/cell/in_table.rb +2 -2
  70. data/lib/prawn/table/cell/span_dummy.rb +92 -0
  71. data/lib/prawn/table/cell/subtable.rb +2 -2
  72. data/lib/prawn/table/cell/text.rb +42 -24
  73. data/lib/prawn/table/cells.rb +137 -48
  74. data/lib/prawn/text.rb +35 -23
  75. data/lib/prawn/text/box.rb +18 -5
  76. data/lib/prawn/text/formatted.rb +5 -4
  77. data/lib/prawn/text/formatted/arranger.rb +292 -0
  78. data/lib/prawn/text/formatted/box.rb +52 -13
  79. data/lib/prawn/text/formatted/fragment.rb +37 -22
  80. data/lib/prawn/text/formatted/line_wrap.rb +286 -0
  81. data/lib/prawn/text/formatted/parser.rb +14 -6
  82. data/lib/prawn/text/formatted/wrap.rb +151 -0
  83. data/lib/prawn/utilities.rb +44 -0
  84. data/manual/basic_concepts/adding_pages.rb +27 -0
  85. data/manual/basic_concepts/basic_concepts.rb +34 -0
  86. data/manual/basic_concepts/creation.rb +39 -0
  87. data/manual/basic_concepts/cursor.rb +33 -0
  88. data/manual/basic_concepts/measurement.rb +25 -0
  89. data/manual/basic_concepts/origin.rb +38 -0
  90. data/manual/basic_concepts/other_cursor_helpers.rb +40 -0
  91. data/manual/bounding_box/bounding_box.rb +39 -0
  92. data/manual/bounding_box/bounds.rb +49 -0
  93. data/manual/bounding_box/canvas.rb +24 -0
  94. data/manual/bounding_box/creation.rb +23 -0
  95. data/manual/bounding_box/indentation.rb +46 -0
  96. data/manual/bounding_box/nesting.rb +45 -0
  97. data/manual/bounding_box/russian_boxes.rb +40 -0
  98. data/manual/bounding_box/stretchy.rb +31 -0
  99. data/manual/document_and_page_options/background.rb +27 -0
  100. data/manual/document_and_page_options/document_and_page_options.rb +31 -0
  101. data/manual/document_and_page_options/metadata.rb +23 -0
  102. data/manual/document_and_page_options/page_margins.rb +38 -0
  103. data/manual/document_and_page_options/page_size.rb +34 -0
  104. data/manual/example_file.rb +116 -0
  105. data/manual/example_helper.rb +411 -0
  106. data/manual/example_package.rb +53 -0
  107. data/manual/example_section.rb +46 -0
  108. data/manual/graphics/circle_and_ellipse.rb +22 -0
  109. data/manual/graphics/color.rb +24 -0
  110. data/manual/graphics/common_lines.rb +28 -0
  111. data/manual/graphics/fill_and_stroke.rb +42 -0
  112. data/manual/graphics/fill_rules.rb +37 -0
  113. data/manual/graphics/gradients.rb +37 -0
  114. data/manual/graphics/graphics.rb +58 -0
  115. data/manual/graphics/helper.rb +24 -0
  116. data/manual/graphics/line_width.rb +35 -0
  117. data/manual/graphics/lines_and_curves.rb +41 -0
  118. data/manual/graphics/polygon.rb +29 -0
  119. data/manual/graphics/rectangle.rb +21 -0
  120. data/manual/graphics/rotate.rb +28 -0
  121. data/manual/graphics/scale.rb +41 -0
  122. data/manual/graphics/soft_masks.rb +46 -0
  123. data/manual/graphics/stroke_cap.rb +31 -0
  124. data/manual/graphics/stroke_dash.rb +48 -0
  125. data/manual/graphics/stroke_join.rb +30 -0
  126. data/manual/graphics/translate.rb +29 -0
  127. data/manual/graphics/transparency.rb +35 -0
  128. data/manual/images/absolute_position.rb +23 -0
  129. data/manual/images/fit.rb +21 -0
  130. data/manual/images/horizontal.rb +25 -0
  131. data/manual/images/images.rb +40 -0
  132. data/manual/images/plain_image.rb +18 -0
  133. data/manual/images/scale.rb +22 -0
  134. data/manual/images/vertical.rb +28 -0
  135. data/manual/images/width_and_height.rb +25 -0
  136. data/manual/layout/boxes.rb +27 -0
  137. data/manual/layout/content.rb +25 -0
  138. data/manual/layout/layout.rb +28 -0
  139. data/manual/layout/simple_grid.rb +23 -0
  140. data/manual/manual/cover.rb +35 -0
  141. data/manual/manual/foreword.rb +85 -0
  142. data/manual/manual/how_to_read_this_manual.rb +41 -0
  143. data/manual/manual/manual.rb +35 -0
  144. data/manual/outline/add_subsection_to.rb +61 -0
  145. data/manual/outline/insert_section_after.rb +47 -0
  146. data/manual/outline/outline.rb +32 -0
  147. data/manual/outline/sections_and_pages.rb +67 -0
  148. data/manual/repeatable_content/page_numbering.rb +54 -0
  149. data/manual/repeatable_content/repeatable_content.rb +31 -0
  150. data/manual/repeatable_content/repeater.rb +55 -0
  151. data/manual/repeatable_content/stamp.rb +41 -0
  152. data/manual/security/encryption.rb +31 -0
  153. data/manual/security/permissions.rb +38 -0
  154. data/manual/security/security.rb +28 -0
  155. data/manual/syntax_highlight.rb +52 -0
  156. data/manual/table/basic_block.rb +53 -0
  157. data/manual/table/before_rendering_page.rb +26 -0
  158. data/manual/table/cell_border_lines.rb +24 -0
  159. data/manual/table/cell_borders_and_bg.rb +31 -0
  160. data/manual/table/cell_dimensions.rb +30 -0
  161. data/manual/table/cell_text.rb +38 -0
  162. data/manual/table/column_widths.rb +30 -0
  163. data/manual/table/content_and_subtables.rb +39 -0
  164. data/manual/table/creation.rb +27 -0
  165. data/manual/table/filtering.rb +36 -0
  166. data/manual/table/flow_and_header.rb +17 -0
  167. data/manual/table/image_cells.rb +33 -0
  168. data/manual/table/position.rb +29 -0
  169. data/manual/table/row_colors.rb +20 -0
  170. data/manual/table/span.rb +30 -0
  171. data/manual/table/style.rb +22 -0
  172. data/manual/table/table.rb +52 -0
  173. data/manual/table/width.rb +27 -0
  174. data/manual/templates/full_template.rb +25 -0
  175. data/manual/templates/page_template.rb +48 -0
  176. data/manual/templates/templates.rb +27 -0
  177. data/manual/text/alignment.rb +44 -0
  178. data/manual/text/color.rb +24 -0
  179. data/manual/text/column_box.rb +32 -0
  180. data/manual/text/fallback_fonts.rb +37 -0
  181. data/manual/text/font.rb +41 -0
  182. data/manual/text/font_size.rb +45 -0
  183. data/manual/text/font_style.rb +23 -0
  184. data/manual/text/formatted_callbacks.rb +60 -0
  185. data/manual/text/formatted_text.rb +54 -0
  186. data/manual/text/free_flowing_text.rb +51 -0
  187. data/manual/text/group.rb +29 -0
  188. data/manual/text/inline.rb +43 -0
  189. data/manual/text/kerning_and_character_spacing.rb +39 -0
  190. data/manual/text/leading.rb +25 -0
  191. data/manual/text/line_wrapping.rb +41 -0
  192. data/manual/text/paragraph_indentation.rb +26 -0
  193. data/manual/text/positioned_text.rb +38 -0
  194. data/manual/text/registering_families.rb +48 -0
  195. data/manual/text/rendering_and_color.rb +37 -0
  196. data/manual/text/right_to_left_text.rb +43 -0
  197. data/manual/text/rotation.rb +43 -0
  198. data/manual/text/single_usage.rb +37 -0
  199. data/manual/text/text.rb +75 -0
  200. data/manual/text/text_box_excess.rb +32 -0
  201. data/manual/text/text_box_extensions.rb +45 -0
  202. data/manual/text/text_box_overflow.rb +44 -0
  203. data/manual/text/utf8.rb +28 -0
  204. data/{examples/m17n → manual/text}/win_ansi_charset.rb +14 -10
  205. data/prawn.gemspec +18 -12
  206. data/spec/acceptance/png.rb +23 -0
  207. data/spec/annotations_spec.rb +16 -32
  208. data/spec/bounding_box_spec.rb +128 -15
  209. data/spec/cell_spec.rb +169 -38
  210. data/spec/column_box_spec.rb +33 -0
  211. data/spec/destinations_spec.rb +5 -5
  212. data/spec/document_spec.rb +150 -104
  213. data/spec/extensions/encoding_helpers.rb +10 -0
  214. data/spec/extensions/mocha.rb +1 -0
  215. data/spec/filters_spec.rb +34 -0
  216. data/spec/font_metric_cache_spec.rb +52 -0
  217. data/spec/font_spec.rb +183 -97
  218. data/spec/formatted_text_arranger_spec.rb +43 -43
  219. data/spec/formatted_text_box_spec.rb +30 -20
  220. data/spec/formatted_text_fragment_spec.rb +8 -8
  221. data/spec/graphics_spec.rb +158 -69
  222. data/spec/grid_spec.rb +15 -15
  223. data/spec/image_handler_spec.rb +42 -0
  224. data/spec/images_spec.rb +49 -24
  225. data/spec/inline_formatted_text_parser_spec.rb +73 -19
  226. data/spec/jpg_spec.rb +4 -4
  227. data/spec/line_wrap_spec.rb +26 -26
  228. data/spec/measurement_units_spec.rb +6 -6
  229. data/spec/name_tree_spec.rb +21 -21
  230. data/spec/object_store_spec.rb +39 -39
  231. data/spec/outline_spec.rb +93 -53
  232. data/spec/pdf_object_spec.rb +88 -86
  233. data/spec/png_spec.rb +31 -28
  234. data/spec/reference_spec.rb +32 -32
  235. data/spec/repeater_spec.rb +25 -11
  236. data/spec/security_spec.rb +44 -12
  237. data/spec/snapshot_spec.rb +8 -9
  238. data/spec/soft_mask_spec.rb +117 -0
  239. data/spec/span_spec.rb +10 -15
  240. data/spec/spec_helper.rb +25 -8
  241. data/spec/stamp_spec.rb +29 -30
  242. data/spec/stream_spec.rb +58 -0
  243. data/spec/stroke_styles_spec.rb +36 -18
  244. data/spec/table/span_dummy_spec.rb +17 -0
  245. data/spec/table_spec.rb +697 -105
  246. data/spec/template_spec.rb +108 -54
  247. data/spec/text_at_spec.rb +18 -17
  248. data/spec/text_box_spec.rb +111 -62
  249. data/spec/text_rendering_mode_spec.rb +5 -5
  250. data/spec/text_spacing_spec.rb +4 -4
  251. data/spec/text_spec.rb +57 -49
  252. data/spec/transparency_spec.rb +5 -5
  253. metadata +421 -213
  254. data/data/fonts/Action Man.dfont +0 -0
  255. data/data/fonts/Activa.ttf +0 -0
  256. data/data/fonts/Chalkboard.ttf +0 -0
  257. data/data/fonts/DejaVuSans.ttf +0 -0
  258. data/data/fonts/Dustismo_Roman.ttf +0 -0
  259. data/data/fonts/comicsans.ttf +0 -0
  260. data/data/fonts/gkai00mp.ttf +0 -0
  261. data/data/images/rails.dat +0 -0
  262. data/data/images/rails.png +0 -0
  263. data/examples/bounding_box/russian_boxes.rb +0 -37
  264. data/examples/example_helper.rb +0 -11
  265. data/examples/general/context_sensitive_headers.rb +0 -38
  266. data/examples/graphics/cmyk.rb +0 -13
  267. data/examples/graphics/gradient.rb +0 -23
  268. data/examples/graphics/png_types.rb +0 -23
  269. data/examples/graphics/remote_images.rb +0 -13
  270. data/examples/m17n/full_win_ansi_character_list.rb +0 -20
  271. data/examples/m17n/sjis.rb +0 -29
  272. data/examples/table/bill.rb +0 -54
  273. data/examples/table/header.rb +0 -15
  274. data/examples/text/font_calculations.rb +0 -92
  275. data/examples/text/hyphenation.rb +0 -45
  276. data/examples/text/indent_paragraphs.rb +0 -24
  277. data/lib/prawn/core.rb +0 -85
  278. data/lib/prawn/core/text/formatted/arranger.rb +0 -294
  279. data/lib/prawn/core/text/formatted/line_wrap.rb +0 -273
  280. data/lib/prawn/core/text/formatted/wrap.rb +0 -153
  281. data/lib/prawn/graphics/gradient.rb +0 -84
  282. data/lib/prawn/security/arcfour.rb +0 -51
@@ -13,8 +13,7 @@ module Prawn
13
13
  module Formatted
14
14
 
15
15
  class Parser
16
-
17
- def self.to_array(string)
16
+ PARSER_REGEX = begin
18
17
  regex_string = "\n|" +
19
18
  "<b>|</b>|" +
20
19
  "<i>|</i>|" +
@@ -29,8 +28,11 @@ module Prawn
29
28
  "<em>|</em>|" +
30
29
  "<a[^>]*>|</a>|" +
31
30
  "[^<\n]+"
32
- regex = Regexp.new(regex_string, Regexp::MULTILINE)
33
- tokens = string.scan(regex)
31
+ Regexp.new(regex_string, Regexp::MULTILINE)
32
+ end
33
+
34
+ def self.format(string, *args)
35
+ tokens = string.gsub(/<br\s*\/?>/, "\n").scan(PARSER_REGEX)
34
36
  self.array_from_tokens(tokens)
35
37
  end
36
38
 
@@ -122,10 +124,11 @@ module Prawn
122
124
  colors = []
123
125
  link = nil
124
126
  anchor = nil
127
+ local = nil
125
128
  fonts = []
126
129
  sizes = []
127
130
  character_spacings = []
128
-
131
+
129
132
  while token = tokens.shift
130
133
  case token
131
134
  when "<b>", "<strong>"
@@ -155,6 +158,7 @@ module Prawn
155
158
  when "</link>", "</a>"
156
159
  link = nil
157
160
  anchor = nil
161
+ local = nil
158
162
  when "</color>"
159
163
  colors.pop
160
164
  when "</font>"
@@ -168,6 +172,9 @@ module Prawn
168
172
 
169
173
  matches = /anchor="([^"]*)"/.match(token) || /anchor='([^']*)'/.match(token)
170
174
  anchor = matches[1] unless matches.nil?
175
+
176
+ matches = /local="([^"]*)"/.match(token) || /local='([^']*)'/.match(token)
177
+ local = matches[1] unless matches.nil?
171
178
  elsif token =~ /^<color[^>]*>$/
172
179
  matches = /rgb="#?([^"]*)"/.match(token) || /rgb='#?([^']*)'/.match(token)
173
180
  colors << matches[1] if matches
@@ -179,7 +186,7 @@ module Prawn
179
186
  # intend to support rgb="#ffffff" or rgb='#ffffff',
180
187
  # r="255" g="255" b="255" or r='255' g='255' b='255',
181
188
  # and c="100" m="100" y="100" k="100" or
182
- # c='100' m='100' y='100' k='100'
189
+ # c='100' m='100' y='100' k='100'
183
190
  # color = { :rgb => "#ffffff" }
184
191
  # color = { :r => 255, :g => 255, :b => 255 }
185
192
  # color = { :c => 100, :m => 100, :y => 100, :k => 100 }
@@ -197,6 +204,7 @@ module Prawn
197
204
  array << { :text => string,
198
205
  :styles => styles.dup,
199
206
  :color => colors.last,
207
+ :local => local,
200
208
  :link => link,
201
209
  :anchor => anchor,
202
210
  :font => fonts.last,
@@ -0,0 +1,151 @@
1
+ require_relative "line_wrap"
2
+ require_relative "arranger"
3
+
4
+ module Prawn
5
+ module Text
6
+ module Formatted #:nodoc:
7
+ module Wrap #:nodoc:
8
+
9
+ def initialize(array, options)
10
+ @line_wrap = Prawn::Text::Formatted::LineWrap.new
11
+ @arranger = Prawn::Text::Formatted::Arranger.new(@document,
12
+ :kerning => options[:kerning])
13
+ end
14
+
15
+
16
+ # See the developer documentation for PDF::Core::Text#wrap
17
+ #
18
+ # Formatted#wrap should set the following variables:
19
+ # <tt>@line_height</tt>::
20
+ # the height of the tallest fragment in the last printed line
21
+ # <tt>@descender</tt>::
22
+ # the descender height of the tallest fragment in the last
23
+ # printed line
24
+ # <tt>@ascender</tt>::
25
+ # the ascender heigth of the tallest fragment in the last
26
+ # printed line
27
+ # <tt>@baseline_y</tt>::
28
+ # the baseline of the current line
29
+ # <tt>@nothing_printed</tt>::
30
+ # set to true until something is printed, then false
31
+ # <tt>@everything_printed</tt>::
32
+ # set to false until everything printed, then true
33
+ #
34
+ # Returns any formatted text that was not printed
35
+ #
36
+ def wrap(array) #:nodoc:
37
+ initialize_wrap(array)
38
+
39
+ stop = false
40
+ while !stop
41
+ # wrap before testing if enough height for this line because the
42
+ # height of the highest fragment on this line will be used to
43
+ # determine the line height
44
+ @line_wrap.wrap_line(:document => @document,
45
+ :kerning => @kerning,
46
+ :width => available_width,
47
+ :arranger => @arranger)
48
+
49
+ if enough_height_for_this_line?
50
+ move_baseline_down
51
+ print_line
52
+ else
53
+ stop = true
54
+ end
55
+
56
+ stop ||= @single_line || @arranger.finished?
57
+ end
58
+ @text = @printed_lines.join("\n")
59
+ @everything_printed = @arranger.finished?
60
+ @arranger.unconsumed
61
+ end
62
+
63
+ private
64
+
65
+ def print_line
66
+ @nothing_printed = false
67
+ printed_fragments = []
68
+ fragments_this_line = []
69
+
70
+ word_spacing = word_spacing_for_this_line
71
+ while fragment = @arranger.retrieve_fragment
72
+ fragment.word_spacing = word_spacing
73
+ if fragment.text == "\n"
74
+ printed_fragments << "\n" if @printed_lines.last == ""
75
+ break
76
+ end
77
+ printed_fragments << fragment.text
78
+ fragments_this_line << fragment
79
+ end
80
+
81
+ accumulated_width = 0
82
+ fragments_this_line.reverse! if @direction == :rtl
83
+ fragments_this_line.each do |fragment_this_line|
84
+ fragment_this_line.default_direction = @direction
85
+ format_and_draw_fragment(fragment_this_line, accumulated_width,
86
+ @line_wrap.width, word_spacing)
87
+ accumulated_width += fragment_this_line.width
88
+ end
89
+
90
+ if "".respond_to?(:force_encoding)
91
+ printed_fragments.map! { |s| s.force_encoding("utf-8") }
92
+ end
93
+ @printed_lines << printed_fragments.join
94
+ end
95
+
96
+ def word_spacing_for_this_line
97
+ if @align == :justify &&
98
+ @line_wrap.space_count > 0 &&
99
+ !@line_wrap.paragraph_finished?
100
+ (available_width - @line_wrap.width) / @line_wrap.space_count
101
+ else
102
+ 0
103
+ end
104
+ end
105
+
106
+ def enough_height_for_this_line?
107
+ @line_height = @arranger.max_line_height
108
+ @descender = @arranger.max_descender
109
+ @ascender = @arranger.max_ascender
110
+ if @baseline_y == 0
111
+ diff = @ascender + @descender
112
+ else
113
+ diff = @descender + @line_height + @leading
114
+ end
115
+ require_relatived_total_height = @baseline_y.abs + diff
116
+ if require_relatived_total_height > @height + 0.0001
117
+ # no room for the full height of this line
118
+ @arranger.repack_unretrieved
119
+ false
120
+ else
121
+ true
122
+ end
123
+ end
124
+
125
+ def initialize_wrap(array)
126
+ @text = nil
127
+ @arranger.format_array = array
128
+
129
+ # these values will depend on the maximum value within a given line
130
+ @line_height = 0
131
+ @descender = 0
132
+ @ascender = 0
133
+ @baseline_y = 0
134
+
135
+ @printed_lines = []
136
+ @nothing_printed = true
137
+ @everything_printed = false
138
+ end
139
+
140
+ def format_and_draw_fragment(fragment, accumulated_width,
141
+ line_width, word_spacing)
142
+ @arranger.apply_color_and_font_settings(fragment) do
143
+ draw_fragment(fragment, accumulated_width,
144
+ line_width, word_spacing)
145
+ end
146
+ end
147
+
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ # utilities.rb : General-purpose utility classes which don't fit anywhere else
4
+ #
5
+ # Copyright August 2012, Alex Dowad. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ require 'thread'
10
+
11
+ module Prawn
12
+
13
+ # Throughout the Prawn codebase, repeated calculations which can benefit from caching are made
14
+ # In some cases, caching and reusing results can not only save CPU cycles but also greatly
15
+ # reduce memory requirements
16
+ # But at the same time, we don't want to throw away thread safety
17
+ # We have two interchangeable thread-safe cache implementations:
18
+
19
+ class SynchronizedCache
20
+ # As an optimization, this could access the hash directly on VMs with a global interpreter lock (like MRI)
21
+ def initialize
22
+ @cache = {}
23
+ @mutex = Mutex.new
24
+ end
25
+ def [](key)
26
+ @mutex.synchronize { @cache[key] }
27
+ end
28
+ def []=(key,value)
29
+ @mutex.synchronize { @cache[key] = value }
30
+ end
31
+ end
32
+
33
+ class ThreadLocalCache
34
+ def initialize
35
+ @cache_id = "cache_#{self.object_id}".to_sym
36
+ end
37
+ def [](key)
38
+ (Thread.current[@cache_id] ||= {})[key]
39
+ end
40
+ def []=(key,value)
41
+ (Thread.current[@cache_id] ||= {})[key] = value
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ #
3
+ # A PDF document is a collection of pages. When we create a new document be it
4
+ # with <code>Document.new</code> or on a <code>Document.generate</code> block
5
+ # one initial page is created for us.
6
+ #
7
+ # Some methods might create new pages automatically like <code>text</code> which
8
+ # will create a new page whenever the text string cannot fit on the current
9
+ # page.
10
+ #
11
+ # But what if you want to go to the next page by yourself? That is easy.
12
+ #
13
+ # Just use the <code>start_new_page</code> method and a shiny new page will be
14
+ # created for you just like in the following snippet.
15
+ #
16
+ require File.expand_path(File.join(File.dirname(__FILE__),
17
+ %w[.. example_helper]))
18
+
19
+ filename = File.basename(__FILE__).gsub('.rb', '.pdf')
20
+ Prawn::Example.generate(filename) do
21
+ text "We are still on the initial page for this example. Now I'll ask " +
22
+ "Prawn to gently start a new page. Please follow me to the next page."
23
+
24
+ start_new_page
25
+
26
+ text "See. We've left the previous page behind."
27
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Examples for Prawn basic concepts.
4
+ #
5
+ require File.expand_path(File.join(File.dirname(__FILE__),
6
+ %w[.. example_helper]))
7
+
8
+ Prawn::Example.generate("basic_concepts.pdf", :page_size => "FOLIO") do
9
+
10
+ package "basic_concepts" do |p|
11
+
12
+ p.example "creation", :eval_source => false, :full_source => true
13
+ p.example "origin"
14
+ p.example "cursor"
15
+ p.example "other_cursor_helpers"
16
+ p.example "adding_pages"
17
+ p.example "measurement"
18
+
19
+ p.intro do
20
+ prose("This chapter covers the minimum amount of functionality you'll need to start using Prawn.
21
+
22
+ If you are new to Prawn this is the first chapter to read. Once you are comfortable with the concepts shown here you might want to check the Basics section of the Graphics, Bounding Box and Text sections.
23
+
24
+ The examples show:")
25
+
26
+ list( "How to create new pdf documents in every possible way",
27
+ "Where the origin for the document coordinates is. What are Bounding Boxes and how they interact with the origin",
28
+ "How the cursor behaves",
29
+ "How to start new pages",
30
+ "What the base unit for measurement and coordinates is and how to use other convenient measures"
31
+ )
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ #
3
+ # There are three ways to create a PDF Document in Prawn: creating a new
4
+ # <code>Prawn::Document</code> instance, or using the
5
+ # <code>Prawn::Document.generate</code> method with and without block arguments.
6
+ #
7
+ # The following snippet showcase each way by creating a simple document with
8
+ # some text drawn.
9
+ #
10
+ # When we instantiate the <code>Prawn::Document</code> object the actual pdf
11
+ # document will only be created after we call <code>render_file</code>.
12
+ #
13
+ # The generate method will render the actual pdf object after exiting the block.
14
+ # When we use it without a block argument the provided block is evaluated in the
15
+ # context of a newly created <code>Prawn::Document</code> instance. When we use
16
+ # it with a block argument a <code>Prawn::Document</code> instance is created
17
+ # and passed to the block.
18
+ #
19
+ # The generate method without block arguments requires
20
+ # less typing and defines and renders the pdf document in one shot.
21
+ # Almost all of the examples are coded this way.
22
+ #
23
+ require File.expand_path(File.join(File.dirname(__FILE__),
24
+ %w[.. example_helper]))
25
+
26
+ # Assignment
27
+ pdf = Prawn::Document.new
28
+ pdf.text "Hello World"
29
+ pdf.render_file "assignment.pdf"
30
+
31
+ # Implicit Block
32
+ Prawn::Document.generate("implicit.pdf") do
33
+ text "Hello World"
34
+ end
35
+
36
+ # Explicit Block
37
+ Prawn::Document.generate("explicit.pdf") do |pdf|
38
+ pdf.text "Hello World"
39
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ #
3
+ # We normally write our documents from top to bottom and it is no different with
4
+ # Prawn. Even if the origin is on the bottom left corner we still fill the page
5
+ # from the top to the bottom. In other words the cursor for inserting content
6
+ # starts on the top of the page.
7
+ #
8
+ # Most of the functions that insert content on the page will start at the
9
+ # current cursor position and proceed to the bottom of the page.
10
+ #
11
+ # The following snippet shows how the cursor behaves when we add some text to
12
+ # the page and demonstrates some of the helpers to manage the cursor position.
13
+ # The <code>cursor</code> method returns the current cursor position.
14
+ #
15
+ require File.expand_path(File.join(File.dirname(__FILE__),
16
+ %w[.. example_helper]))
17
+
18
+ filename = File.basename(__FILE__).gsub('.rb', '.pdf')
19
+ Prawn::Example.generate(filename) do
20
+ stroke_axis
21
+
22
+ text "the cursor is here: #{cursor}"
23
+ text "now it is here: #{cursor}"
24
+
25
+ move_down 200
26
+ text "on the first move the cursor went down to: #{cursor}"
27
+
28
+ move_up 100
29
+ text "on the second move the cursor went up to: #{cursor}"
30
+
31
+ move_cursor_to 50
32
+ text "on the last move the cursor went directly to: #{cursor}"
33
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ #
3
+ # The base unit in Prawn is the PDF Point. One PDF Point is equal to 1/72 of
4
+ # an inch.
5
+ #
6
+ # There is no need to waste time converting this measures. Prawn provides
7
+ # helpers for converting from other measurements
8
+ # to PDF Points.
9
+ #
10
+ # Just <code>require "prawn/measurement_extensions"</code> and it will mix some
11
+ # helpers onto <code>Numeric</code> for converting common measurement units to
12
+ # PDF Points.
13
+ #
14
+ require File.expand_path(File.join(File.dirname(__FILE__),
15
+ %w[.. example_helper]))
16
+
17
+ filename = File.basename(__FILE__).gsub('.rb', '.pdf')
18
+ Prawn::Example.generate(filename) do
19
+ require "prawn/measurement_extensions"
20
+
21
+ [:mm, :cm, :dm, :m, :in, :yd, :ft].each do |measurement|
22
+ text "1 #{measurement} in PDF Points: #{1.send(measurement)} pt"
23
+ move_down 5.mm
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This is the most important concept you need to learn about Prawn:
4
+ #
5
+ # PDF documents have the origin <code>[0,0]</code> at the bottom-left corner of
6
+ # the page.
7
+ #
8
+ # A bounding box is a structure which provides boundaries for inserting content.
9
+ # A bounding box also has the property of relocating the origin to its relative
10
+ # bottom-left corner. However, be aware that the location specified when
11
+ # creating a bounding box is its top-left corner, not bottom-left (hence the
12
+ # <code>[100, 300]</code> coordinates below).
13
+ #
14
+ # Even if you never create a bounding box explictly, each document already comes
15
+ # with one called the margin box. This initial bounding box is the one
16
+ # responsible for the document margins.
17
+ #
18
+ # So practically speaking the origin of a page on a default generated document
19
+ # isn't the absolute bottom left corner but the bottom left corner of the margin
20
+ # box.
21
+ #
22
+ # The following snippet strokes a circle on the margin box origin. Then strokes
23
+ # the boundaries of a bounding box and a circle on its origin.
24
+ #
25
+ require File.expand_path(File.join(File.dirname(__FILE__),
26
+ %w[.. example_helper]))
27
+
28
+ filename = File.basename(__FILE__).gsub('.rb', '.pdf')
29
+ Prawn::Example.generate(filename) do
30
+ stroke_axis
31
+
32
+ stroke_circle [0, 0], 10
33
+
34
+ bounding_box([100, 300], :width => 300, :height => 200) do
35
+ stroke_bounds
36
+ stroke_circle [0, 0], 10
37
+ end
38
+ end