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
@@ -7,26 +7,26 @@
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
9
  module Prawn
10
- class Document
11
-
10
+ class Document
11
+
12
12
  # This module exposes a few low-level PDF features for those who want
13
13
  # to extend Prawn's core functionality. If you are not comfortable with
14
14
  # low level PDF functionality as defined by Adobe's specification, chances
15
- # are you won't need anything you find here.
15
+ # are you won't need anything you find here.
16
16
  #
17
- module Internals
18
-
17
+ module Internals
18
+
19
19
  # Creates a new Prawn::Reference and adds it to the Document's object
20
- # list. The +data+ argument is anything that Prawn::PdfObject() can convert.
20
+ # list. The +data+ argument is anything that Prawn::PdfObject() can convert.
21
+ #
22
+ # Returns the identifier which points to the reference in the ObjectStore
21
23
  #
22
- # Returns the identifier which points to the reference in the ObjectStore
23
- #
24
24
  def ref(data)
25
25
  ref!(data).identifier
26
- end
26
+ end
27
27
 
28
28
  # Like ref, but returns the actual reference instead of its identifier.
29
- #
29
+ #
30
30
  # While you can use this to build up nested references within the object
31
31
  # tree, it is recommended to persist only identifiers, and them provide
32
32
  # helper methods to look up the actual references in the ObjectStore
@@ -42,21 +42,21 @@ module Prawn
42
42
  # of if it's hidden behind a Prawn::Reference, wrap it in deref().
43
43
  #
44
44
  def deref(obj)
45
- obj.is_a?(Prawn::Core::Reference) ? obj.data : obj
45
+ obj.is_a?(PDF::Core::Reference) ? obj.data : obj
46
46
  end
47
47
 
48
48
  # Appends a raw string to the current page content.
49
- #
50
- # # Raw line drawing example:
49
+ #
50
+ # # Raw line drawing example:
51
51
  # x1,y1,x2,y2 = 100,500,300,550
52
- # pdf.add_content("%.3f %.3f m" % [ x1, y1 ]) # move
52
+ # pdf.add_content("%.3f %.3f m" % [ x1, y1 ]) # move
53
53
  # pdf.add_content("%.3f %.3f l" % [ x2, y2 ]) # draw path
54
- # pdf.add_content("S") # stroke
54
+ # pdf.add_content("S") # stroke
55
55
  #
56
56
  def add_content(str)
57
57
  save_graphics_state if graphic_state.nil?
58
58
  state.page.content << str << "\n"
59
- end
59
+ end
60
60
 
61
61
  # The Name dictionary (PDF spec 3.6.3) for this document. It is
62
62
  # lazily initialized, so that documents that do not need a name
@@ -67,7 +67,7 @@ module Prawn
67
67
  end
68
68
 
69
69
  # Returns true if the Names dictionary is in use for this document.
70
- #
70
+ #
71
71
  def names?
72
72
  state.store.root.data[:Names]
73
73
  end
@@ -87,8 +87,8 @@ module Prawn
87
87
  state.on_page_create_callback = nil
88
88
  end
89
89
  end
90
-
91
- private
90
+
91
+ private
92
92
 
93
93
  # adds a new, empty content stream to each page. Used in templating so
94
94
  # that imported content streams can be left pristine
@@ -100,6 +100,7 @@ module Prawn
100
100
  apply_margin_options(options)
101
101
  generate_margin_box
102
102
  use_graphic_settings(options[:template])
103
+ forget_text_rendering_mode!
103
104
  end
104
105
  end
105
106
 
@@ -156,18 +157,18 @@ module Prawn
156
157
  # Write out the PDF Trailer, as per spec 3.4.4
157
158
  #
158
159
  def render_trailer(output)
159
- trailer_hash = {:Size => state.store.size + 1,
160
+ trailer_hash = {:Size => state.store.size + 1,
160
161
  :Root => state.store.root,
161
162
  :Info => state.store.info}
162
163
  trailer_hash.merge!(state.trailer) if state.trailer
163
164
 
164
165
  output << "trailer\n"
165
- output << Prawn::Core::PdfObject(trailer_hash) << "\n"
166
- output << "startxref\n"
166
+ output << PDF::Core::PdfObject(trailer_hash) << "\n"
167
+ output << "startxref\n"
167
168
  output << @xref_offset << "\n"
168
169
  output << "%%EOF" << "\n"
169
170
  end
170
-
171
+
171
172
  end
172
173
  end
173
174
  end
@@ -27,7 +27,7 @@ module Prawn
27
27
  # +rollback+ is called or a RollbackTransaction exception is raised
28
28
  # inside the block, all actions taken inside the block will be rolled
29
29
  # back (with the exception of y-position, which you must restore
30
- # yourself).
30
+ # yourself).
31
31
  #
32
32
  # Returns true on success, or false if the transaction was rolled back.
33
33
  #
@@ -41,7 +41,7 @@ module Prawn
41
41
  end
42
42
 
43
43
  private
44
-
44
+
45
45
  # Takes a current snapshot of the document's state, sufficient to
46
46
  # reconstruct it after it was amended.
47
47
  #
@@ -50,12 +50,11 @@ module Prawn
50
50
  # monotonically as data is added to the document, so we share that
51
51
  # between the old and new copies.
52
52
  {:page_content => state.page.content.deep_copy,
53
- :current_page => state.page.dictionary.deep_copy(share=[:Parent]),
53
+ :current_page => state.page.dictionary.deep_copy([:Parent]),
54
54
  :bounds => bounds.deep_copy,
55
55
  :page_number => page_number,
56
- :page_kids => state.store.pages.data[:Kids].map{|kid| kid.identifier},
57
- :dests => names? &&
58
- Marshal.load(Marshal.dump(names.data[:Dests]))}
56
+ :page_kids => state.store.pages.data[:Kids].compact.map{|kid| kid.identifier},
57
+ :dests => names? && names.data[:Dests].deep_copy}
59
58
  end
60
59
 
61
60
  # Rolls the page state back to the state of the given snapshot.
@@ -81,7 +80,7 @@ module Prawn
81
80
  self.bounds = BoundingBox.restore_deep_copy(shot[:bounds], self)
82
81
 
83
82
  if shot[:dests]
84
- names.data[:Dests] = shot[:dests]
83
+ names.data[:Dests] = shot[:dests]
85
84
  end
86
85
  end
87
86
 
@@ -8,8 +8,8 @@
8
8
 
9
9
  module Prawn
10
10
  class Document
11
- # A span is a special purpose bounding box that allows a column of
12
- # elements to be positioned relative to the margin_box.
11
+ # A span is a special purpose bounding box that allows a column of
12
+ # elements to be positioned relative to the margin_box.
13
13
  #
14
14
  # Arguments:
15
15
  # +width+:: The width of the column in PDF points
@@ -17,23 +17,23 @@ module Prawn
17
17
  # Options:
18
18
  # <tt>:position</tt>:: One of :left, :center, :right or an x offset
19
19
  #
20
- # This method is typically used for flowing a column of text from one
20
+ # This method is typically used for flowing a column of text from one
21
21
  # page to the next.
22
22
  #
23
23
  # span(350, :position => :center) do
24
24
  # text "Here's some centered text in a 350 point column. " * 100
25
25
  # end
26
- #
26
+ #
27
27
  def span(width, options={})
28
28
  Prawn.verify_options [:position], options
29
- original_position = self.y
30
-
29
+ original_position = self.y
30
+
31
31
  # FIXME: Any way to move this upstream?
32
32
  left_boundary = case(options[:position] || :left)
33
33
  when :left
34
34
  margin_box.absolute_left
35
35
  when :center
36
- margin_box.absolute_left + margin_box.width / 2.0 - width /2.0
36
+ margin_box.absolute_left + margin_box.width / 2.0 - width / 2.0
37
37
  when :right
38
38
  margin_box.absolute_right - width
39
39
  when Numeric
@@ -41,15 +41,15 @@ module Prawn
41
41
  else
42
42
  raise ArgumentError, "Invalid option for :position"
43
43
  end
44
-
44
+
45
45
  # we need to bust out of whatever nested bounding boxes we're in.
46
46
  canvas do
47
- bounding_box([left_boundary,
47
+ bounding_box([left_boundary,
48
48
  margin_box.absolute_top], :width => width) do
49
49
  self.y = original_position
50
50
  yield
51
51
  end
52
- end
52
+ end
53
53
  end
54
54
  end
55
55
  end
@@ -18,7 +18,7 @@ module Prawn
18
18
  .notdef .notdef .notdef .notdef
19
19
  .notdef .notdef .notdef .notdef
20
20
  .notdef .notdef .notdef .notdef
21
-
21
+
22
22
  space exclam quotedbl numbersign
23
23
  dollar percent ampersand quotesingle
24
24
  parenleft parenright asterisk plus
@@ -54,7 +54,7 @@ module Prawn
54
54
  quotedblright bullet endash emdash
55
55
  tilde trademark scaron guilsinglright
56
56
  oe .notdef zcaron ydieresis
57
-
57
+
58
58
  space exclamdown cent sterling
59
59
  currency yen brokenbar section
60
60
  dieresis copyright ordfeminine guillemotleft
@@ -81,10 +81,10 @@ module Prawn
81
81
  ocircumflex otilde odieresis divide
82
82
  oslash ugrave uacute ucircumflex
83
83
  udieresis yacute thorn ydieresis
84
- ]
85
-
84
+ ]
85
+
86
86
  def initialize
87
- @mapping_file = "#{Prawn::BASEDIR}/data/encodings/win_ansi.txt"
87
+ @mapping_file = "#{Prawn::DATADIR}/encodings/win_ansi.txt"
88
88
  load_mapping if self.class.mapping.empty?
89
89
  end
90
90
 
@@ -100,7 +100,7 @@ module Prawn
100
100
  # Replace anything else with an underscore
101
101
  self.class.mapping[codepoint] || 95
102
102
  end
103
-
103
+
104
104
  def self.mapping
105
105
  @mapping ||= {}
106
106
  end
@@ -111,7 +111,7 @@ module Prawn
111
111
  RUBY_VERSION >= "1.9" ? mode = "r:BINARY" : mode = "r"
112
112
  File.open(@mapping_file, mode) do |f|
113
113
  f.each do |l|
114
- m, single_byte, unicode = *l.match(/([0-9A-Za-z]+);([0-9A-F]{4})/)
114
+ _, single_byte, unicode = *l.match(/([0-9A-Za-z]+);([0-9A-F]{4})/)
115
115
  self.class.mapping["0x#{unicode}".hex] = "0x#{single_byte}".hex if single_byte
116
116
  end
117
117
  end
@@ -8,25 +8,18 @@
8
8
  #
9
9
  module Prawn
10
10
  module Errors
11
-
12
- # This error is raised when Prawn::PdfObject() encounters a Ruby object it
13
- # cannot convert to PDF
11
+ # Raised when a table is spanned in an impossible way.
14
12
  #
15
- FailedObjectConversion = Class.new(StandardError)
16
-
17
- # This error is raised when Document#page_layout is set to anything
18
- # other than :portrait or :landscape
19
- #
20
- InvalidPageLayout = Class.new(StandardError)
21
-
22
- # This error is raised when a method requiring a current page is called
13
+ InvalidTableSpan = Class.new(StandardError)
14
+
15
+ # This error is raised when a method requiring a current page is called
23
16
  # without being on a page.
24
17
  #
25
18
  NotOnPage = Class.new(StandardError)
26
-
27
- # This error is raised when Prawn cannot find a specified font
19
+
20
+ # This error is raised when Prawn cannot find a specified font
28
21
  #
29
- UnknownFont = Class.new(StandardError)
22
+ UnknownFont = Class.new(StandardError)
30
23
 
31
24
  # Raised when Prawn is asked to draw something into a too-small box
32
25
  #
@@ -35,18 +28,18 @@ module Prawn
35
28
  # Raised if group() is called with a block that is too big to be
36
29
  # rendered in the current context.
37
30
  #
38
- CannotGroup = Class.new(StandardError)
31
+ CannotGroup = Class.new(StandardError)
39
32
 
40
33
  # This error is raised when Prawn is being used on a M17N aware VM,
41
34
  # and the user attempts to add text that isn't compatible with UTF-8
42
35
  # to their document
43
36
  #
44
37
  IncompatibleStringEncoding = Class.new(StandardError)
45
-
38
+
46
39
  # This error is raised when Prawn encounters an unknown key in functions
47
40
  # that accept an options hash. This usually means there is a typo in your
48
41
  # code or that the option you are trying to use has a different name than
49
- # what you have specified.
42
+ # what you have specified.
50
43
  #
51
44
  UnknownOption = Class.new(StandardError)
52
45
 
@@ -66,26 +59,22 @@ module Prawn
66
59
  # This error is raised when an object is attempted to be
67
60
  # referenced by name, but no such name is associated with an object
68
61
  UndefinedObjectName = Class.new(StandardError)
69
-
62
+
70
63
  # This error is raised when a required option has not been set
71
64
  RequiredOption = Class.new(StandardError)
72
-
65
+
73
66
  # This error is raised when a requested outline item with a given title does not exist
74
67
  UnknownOutlineTitle = Class.new(StandardError)
75
68
 
76
69
  # This error is raised when a block is required, but not provided
77
70
  BlockRequired = Class.new(StandardError)
78
-
71
+
79
72
  # This error is rased when a graphics method is called with improper arguments
80
73
  InvalidGraphicsPath = Class.new(StandardError)
81
-
82
- # This error is raised when Prawn fails to load a template file
83
- #
84
- TemplateError = Class.new(StandardError)
85
-
86
- # This error is raise when trying to restore a graphic state that
74
+
75
+ # Raised when unrecognized content is provided for a table cell.
87
76
  #
88
- EmptyGraphicStateStack = Class.new(StandardError)
89
-
77
+ UnrecognizedTableContent = Class.new(StandardError)
78
+
90
79
  end
91
- end
80
+ end
@@ -9,6 +9,7 @@
9
9
  require "prawn/font/afm"
10
10
  require "prawn/font/ttf"
11
11
  require "prawn/font/dfont"
12
+ require "prawn/font_metric_cache"
12
13
 
13
14
  module Prawn
14
15
 
@@ -38,7 +39,7 @@ module Prawn
38
39
  #
39
40
  # If a ttf font is specified, the glyphs necessary to render your document
40
41
  # will be embedded in the rendered PDF. This should be your preferred option
41
- # in most cases. It will increase the size of the resulting file, but also
42
+ # in most cases. It will increase the size of the resulting file, but also
42
43
  # make it more portable.
43
44
  #
44
45
  # The options parameter is an optional hash providing size and style. To use
@@ -49,9 +50,9 @@ module Prawn
49
50
  return((defined?(@font) && @font) || font("Helvetica")) if name.nil?
50
51
 
51
52
  if state.pages.empty? && !state.page.in_stamp_stream?
52
- raise Prawn::Errors::NotOnPage
53
+ raise Prawn::Errors::NotOnPage
53
54
  end
54
-
55
+
55
56
  new_font = find_font(name.to_s, options)
56
57
 
57
58
  if block_given?
@@ -134,18 +135,18 @@ module Prawn
134
135
  # font will be embedded twice. Since we do font subsetting, this double
135
136
  # embedding won't be catastrophic, just annoying.
136
137
  # ++
137
- def find_font(name, options={}) #:nodoc:
138
- if font_families.key?(name)
139
- family, name = name, font_families[name][options[:style] || :normal]
140
- if name.is_a?(Hash)
141
- options = options.merge(name)
142
- name = options[:file]
143
- end
144
- end
145
- key = "#{name}:#{options[:font] || 0}"
146
- font_registry[key] ||= Font.load(self, name, options.merge(:family => family))
147
- end
148
-
138
+ def find_font(name, options={}) #:nodoc:
139
+ if font_families.key?(name)
140
+ family, name = name, font_families[name][options[:style] || :normal]
141
+ if name.is_a?(::Hash)
142
+ options = options.merge(name)
143
+ name = options[:file]
144
+ end
145
+ end
146
+ key = "#{name}:#{options[:font] || 0}"
147
+ font_registry[key] ||= Font.load(self, name, options.merge(:family => family))
148
+ end
149
+
149
150
  # Hash of Font objects keyed by names
150
151
  #
151
152
  def font_registry #:nodoc:
@@ -179,7 +180,7 @@ module Prawn
179
180
  # custom ones, like :thin, and use them in font calls.
180
181
  #
181
182
  def font_families
182
- @font_families ||= Hash.new.merge!(
183
+ @font_families ||= {}.merge!(
183
184
  { "Courier" => { :bold => "Courier-Bold",
184
185
  :italic => "Courier-Oblique",
185
186
  :bold_italic => "Courier-BoldOblique",
@@ -217,8 +218,35 @@ module Prawn
217
218
  # it and redefine the width calculation behavior.
218
219
  #++
219
220
  def width_of(string, options={})
220
- font.compute_width_of(string, options) +
221
- (character_spacing * font.character_count(string))
221
+ if p = options[:inline_format]
222
+ p = [] unless p.is_a?(Array)
223
+
224
+ # Build up an Arranger with the entire string on one line, finalize it,
225
+ # and find its width.
226
+ arranger = Prawn::Text::Formatted::Arranger.new(self, options)
227
+ arranger.consumed = self.text_formatter.format(string, *p)
228
+ arranger.finalize_line
229
+
230
+ arranger.line_width
231
+ else
232
+ width_of_string(string, options)
233
+ end
234
+ end
235
+
236
+ private
237
+
238
+ def width_of_inline_formatted_string(string, options={})
239
+ # Build up an Arranger with the entire string on one line, finalize it,
240
+ # and find its width.
241
+ arranger = Prawn::Text::Formatted::Arranger.new(self, options)
242
+ arranger.consumed = Text::Formatted::Parser.format(string)
243
+ arranger.finalize_line
244
+
245
+ arranger.line_width
246
+ end
247
+
248
+ def width_of_string(string, options={})
249
+ font_metric_cache.width_of( string, options )
222
250
  end
223
251
  end
224
252
 
@@ -240,7 +268,7 @@ module Prawn
240
268
  # will be passed through to Font::AFM.new()
241
269
  #
242
270
  def self.load(document,name,options={})
243
- case name
271
+ case name.to_s
244
272
  when /\.ttf$/i then TTF.new(document, name, options)
245
273
  when /\.dfont$/i then DFont.new(document, name, options)
246
274
  when /\.afm$/i then AFM.new(document, name, options)
@@ -260,7 +288,7 @@ module Prawn
260
288
  @references = {}
261
289
  end
262
290
 
263
- # The size of the font ascender in PDF points
291
+ # The size of the font ascender in PDF points
264
292
  #
265
293
  def ascender
266
294
  @ascender / 1000.0 * size
@@ -278,14 +306,6 @@ module Prawn
278
306
  @line_gap / 1000.0 * size
279
307
  end
280
308
 
281
- def identifier_for(subset)
282
- "#{@identifier}.#{subset}".to_sym
283
- end
284
-
285
- def inspect
286
- "#{self.class.name}< #{name}: #{size} >"
287
- end
288
-
289
309
  # Normalizes the encoding of the string to an encoding supported by the
290
310
  # font. The string is expected to be UTF-8 going in. It will be re-encoded
291
311
  # and the new string will be returned. For an in-place (destructive)
@@ -331,6 +351,22 @@ module Prawn
331
351
  "#{self.class.name}< #{name}: #{size} >"
332
352
  end
333
353
 
354
+ # Return a hash (as in Object#hash) for the font based on the output of
355
+ # #inspect. This is required since font objects are used as keys in hashes
356
+ # that cache certain values (See
357
+ # Prawn::Table::Text#styled_with_of_single_character)
358
+ #
359
+ def hash #:nodoc:
360
+ [ self.class, self.name, self.family, size ].hash
361
+ end
362
+
363
+ # Compliments the #hash implementation above
364
+ #
365
+ def eql?( other ) #:nodoc:
366
+ self.class == other.class && self.name == other.name &&
367
+ self.family == other.family && size == other.send(:size)
368
+ end
369
+
334
370
  private
335
371
 
336
372
  # generate a font identifier that hasn't been used on the curretn page yet