prawn 1.0.0.rc1 → 1.0.0.rc2

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 (203) hide show
  1. data/Gemfile +18 -0
  2. data/README.md +5 -3
  3. data/Rakefile +8 -14
  4. data/data/pdfs/nested_pages.pdf +13 -13
  5. data/lib/prawn.rb +3 -1
  6. data/lib/prawn/compatibility.rb +46 -10
  7. data/lib/prawn/core.rb +3 -1
  8. data/lib/prawn/core/document_state.rb +2 -1
  9. data/lib/prawn/core/object_store.rb +61 -5
  10. data/lib/prawn/core/page.rb +3 -6
  11. data/lib/prawn/core/pdf_object.rb +21 -4
  12. data/lib/prawn/core/reference.rb +6 -2
  13. data/lib/prawn/core/text.rb +4 -4
  14. data/lib/prawn/core/text/formatted/line_wrap.rb +23 -8
  15. data/lib/prawn/document.rb +21 -15
  16. data/lib/prawn/document/bounding_box.rb +3 -3
  17. data/lib/prawn/document/column_box.rb +22 -4
  18. data/lib/prawn/document/snapshot.rb +1 -1
  19. data/lib/prawn/encoding.rb +1 -1
  20. data/lib/prawn/errors.rb +4 -0
  21. data/lib/prawn/font.rb +1 -1
  22. data/lib/prawn/font/afm.rb +30 -72
  23. data/lib/prawn/font/ttf.rb +6 -33
  24. data/lib/prawn/graphics.rb +148 -23
  25. data/lib/prawn/graphics/color.rb +8 -1
  26. data/lib/prawn/graphics/patterns.rb +137 -0
  27. data/lib/prawn/images.rb +25 -19
  28. data/lib/prawn/images/jpg.rb +4 -4
  29. data/lib/prawn/images/png.rb +18 -12
  30. data/lib/prawn/security.rb +6 -4
  31. data/lib/prawn/soft_mask.rb +94 -0
  32. data/lib/prawn/table.rb +136 -31
  33. data/lib/prawn/table/cell.rb +260 -29
  34. data/lib/prawn/table/cell/span_dummy.rb +88 -0
  35. data/lib/prawn/table/cell/text.rb +36 -14
  36. data/lib/prawn/table/cells.rb +91 -41
  37. data/lib/prawn/text.rb +3 -2
  38. data/lib/prawn/text/formatted/box.rb +14 -5
  39. data/lib/prawn/text/formatted/fragment.rb +33 -22
  40. data/lib/prawn/text/formatted/parser.rb +5 -2
  41. data/lib/prawn/utilities.rb +44 -0
  42. data/manual/basic_concepts/adding_pages.rb +27 -0
  43. data/manual/basic_concepts/basic_concepts.rb +34 -0
  44. data/manual/basic_concepts/creation.rb +39 -0
  45. data/manual/basic_concepts/cursor.rb +33 -0
  46. data/manual/basic_concepts/measurement.rb +25 -0
  47. data/manual/basic_concepts/origin.rb +38 -0
  48. data/manual/basic_concepts/other_cursor_helpers.rb +40 -0
  49. data/manual/bounding_box/bounding_box.rb +39 -0
  50. data/manual/bounding_box/bounds.rb +49 -0
  51. data/manual/bounding_box/canvas.rb +24 -0
  52. data/manual/bounding_box/creation.rb +23 -0
  53. data/manual/bounding_box/indentation.rb +46 -0
  54. data/manual/bounding_box/nesting.rb +45 -0
  55. data/manual/bounding_box/russian_boxes.rb +40 -0
  56. data/manual/bounding_box/stretchy.rb +31 -0
  57. data/manual/document_and_page_options/background.rb +27 -0
  58. data/manual/document_and_page_options/document_and_page_options.rb +31 -0
  59. data/manual/document_and_page_options/metadata.rb +23 -0
  60. data/manual/document_and_page_options/page_margins.rb +38 -0
  61. data/manual/document_and_page_options/page_size.rb +34 -0
  62. data/manual/example_file.rb +116 -0
  63. data/manual/example_helper.rb +430 -0
  64. data/manual/example_package.rb +53 -0
  65. data/manual/example_section.rb +46 -0
  66. data/manual/graphics/circle_and_ellipse.rb +22 -0
  67. data/manual/graphics/color.rb +24 -0
  68. data/manual/graphics/common_lines.rb +28 -0
  69. data/manual/graphics/fill_and_stroke.rb +42 -0
  70. data/manual/graphics/fill_rules.rb +37 -0
  71. data/manual/graphics/gradients.rb +37 -0
  72. data/manual/graphics/graphics.rb +58 -0
  73. data/manual/graphics/helper.rb +17 -0
  74. data/manual/graphics/line_width.rb +35 -0
  75. data/manual/graphics/lines_and_curves.rb +41 -0
  76. data/manual/graphics/polygon.rb +29 -0
  77. data/manual/graphics/rectangle.rb +21 -0
  78. data/manual/graphics/rotate.rb +28 -0
  79. data/manual/graphics/scale.rb +41 -0
  80. data/manual/graphics/soft_masks.rb +46 -0
  81. data/manual/graphics/stroke_cap.rb +31 -0
  82. data/manual/graphics/stroke_dash.rb +43 -0
  83. data/manual/graphics/stroke_join.rb +30 -0
  84. data/manual/graphics/translate.rb +29 -0
  85. data/manual/graphics/transparency.rb +35 -0
  86. data/manual/images/absolute_position.rb +23 -0
  87. data/manual/images/fit.rb +21 -0
  88. data/manual/images/horizontal.rb +25 -0
  89. data/manual/images/images.rb +40 -0
  90. data/manual/images/plain_image.rb +18 -0
  91. data/manual/images/scale.rb +22 -0
  92. data/manual/images/vertical.rb +28 -0
  93. data/manual/images/width_and_height.rb +25 -0
  94. data/manual/layout/boxes.rb +27 -0
  95. data/manual/layout/content.rb +25 -0
  96. data/manual/layout/layout.rb +28 -0
  97. data/manual/layout/simple_grid.rb +23 -0
  98. data/manual/manual/cover.rb +26 -0
  99. data/manual/manual/foreword.rb +13 -0
  100. data/manual/manual/how_to_read_this_manual.rb +41 -0
  101. data/manual/manual/manual.rb +36 -0
  102. data/manual/outline/add_subsection_to.rb +61 -0
  103. data/manual/outline/insert_section_after.rb +47 -0
  104. data/manual/outline/outline.rb +32 -0
  105. data/manual/outline/sections_and_pages.rb +67 -0
  106. data/manual/repeatable_content/page_numbering.rb +54 -0
  107. data/manual/repeatable_content/repeatable_content.rb +31 -0
  108. data/manual/repeatable_content/repeater.rb +55 -0
  109. data/manual/repeatable_content/stamp.rb +41 -0
  110. data/manual/security/encryption.rb +31 -0
  111. data/manual/security/permissions.rb +38 -0
  112. data/manual/security/security.rb +28 -0
  113. data/manual/syntax_highlight.rb +52 -0
  114. data/manual/table/basic_block.rb +53 -0
  115. data/manual/table/before_rendering_page.rb +26 -0
  116. data/manual/table/cell_border_lines.rb +24 -0
  117. data/manual/table/cell_borders_and_bg.rb +31 -0
  118. data/manual/table/cell_dimensions.rb +30 -0
  119. data/manual/table/cell_text.rb +38 -0
  120. data/manual/table/column_widths.rb +30 -0
  121. data/manual/table/content_and_subtables.rb +39 -0
  122. data/manual/table/creation.rb +27 -0
  123. data/manual/table/filtering.rb +36 -0
  124. data/manual/table/flow_and_header.rb +17 -0
  125. data/manual/table/image_cells.rb +33 -0
  126. data/manual/table/position.rb +29 -0
  127. data/manual/table/row_colors.rb +20 -0
  128. data/manual/table/span.rb +30 -0
  129. data/manual/table/style.rb +22 -0
  130. data/manual/table/table.rb +52 -0
  131. data/manual/table/width.rb +27 -0
  132. data/manual/templates/full_template.rb +23 -0
  133. data/manual/templates/page_template.rb +47 -0
  134. data/manual/templates/templates.rb +26 -0
  135. data/manual/text/alignment.rb +44 -0
  136. data/manual/text/color.rb +24 -0
  137. data/manual/text/column_box.rb +32 -0
  138. data/manual/text/fallback_fonts.rb +37 -0
  139. data/manual/text/font.rb +41 -0
  140. data/manual/text/font_size.rb +45 -0
  141. data/manual/text/font_style.rb +23 -0
  142. data/manual/text/formatted_callbacks.rb +60 -0
  143. data/manual/text/formatted_text.rb +50 -0
  144. data/manual/text/free_flowing_text.rb +51 -0
  145. data/manual/text/group.rb +29 -0
  146. data/manual/text/inline.rb +43 -0
  147. data/manual/text/kerning_and_character_spacing.rb +39 -0
  148. data/manual/text/leading.rb +25 -0
  149. data/manual/text/line_wrapping.rb +41 -0
  150. data/manual/text/paragraph_indentation.rb +26 -0
  151. data/manual/text/positioned_text.rb +38 -0
  152. data/manual/text/registering_families.rb +48 -0
  153. data/manual/text/rendering_and_color.rb +37 -0
  154. data/manual/text/right_to_left_text.rb +43 -0
  155. data/manual/text/rotation.rb +43 -0
  156. data/manual/text/single_usage.rb +37 -0
  157. data/manual/text/text.rb +75 -0
  158. data/manual/text/text_box_excess.rb +32 -0
  159. data/manual/text/text_box_extensions.rb +45 -0
  160. data/manual/text/text_box_overflow.rb +44 -0
  161. data/manual/text/utf8.rb +28 -0
  162. data/manual/text/win_ansi_charset.rb +59 -0
  163. data/prawn.gemspec +10 -7
  164. data/spec/bounding_box_spec.rb +107 -17
  165. data/spec/cell_spec.rb +66 -40
  166. data/spec/column_box_spec.rb +33 -0
  167. data/spec/document_spec.rb +45 -24
  168. data/spec/extensions/encoding_helpers.rb +6 -0
  169. data/spec/extensions/mocha.rb +1 -0
  170. data/spec/font_spec.rb +71 -53
  171. data/spec/formatted_text_arranger_spec.rb +19 -19
  172. data/spec/formatted_text_box_spec.rb +16 -16
  173. data/spec/formatted_text_fragment_spec.rb +6 -6
  174. data/spec/graphics_spec.rb +96 -31
  175. data/spec/grid_spec.rb +2 -2
  176. data/spec/images_spec.rb +18 -10
  177. data/spec/jpg_spec.rb +1 -1
  178. data/spec/line_wrap_spec.rb +14 -14
  179. data/spec/measurement_units_spec.rb +2 -2
  180. data/spec/name_tree_spec.rb +6 -6
  181. data/spec/object_store_spec.rb +17 -17
  182. data/spec/outline_spec.rb +35 -17
  183. data/spec/pdf_object_spec.rb +3 -1
  184. data/spec/png_spec.rb +22 -19
  185. data/spec/reference_spec.rb +24 -1
  186. data/spec/repeater_spec.rb +9 -9
  187. data/spec/security_spec.rb +3 -3
  188. data/spec/snapshot_spec.rb +3 -3
  189. data/spec/soft_mask_spec.rb +117 -0
  190. data/spec/span_spec.rb +4 -4
  191. data/spec/spec_helper.rb +12 -6
  192. data/spec/stamp_spec.rb +12 -12
  193. data/spec/stroke_styles_spec.rb +5 -5
  194. data/spec/table_spec.rb +458 -88
  195. data/spec/template_spec.rb +108 -54
  196. data/spec/text_at_spec.rb +17 -17
  197. data/spec/text_box_spec.rb +76 -45
  198. data/spec/text_rendering_mode_spec.rb +5 -5
  199. data/spec/text_spacing_spec.rb +4 -4
  200. data/spec/text_spec.rb +44 -40
  201. metadata +419 -250
  202. data/lib/prawn/graphics/gradient.rb +0 -84
  203. data/lib/prawn/security/arcfour.rb +0 -51
@@ -47,7 +47,7 @@ module Prawn
47
47
  end
48
48
  end * scale
49
49
  else
50
- string.unpack("U*").inject(0) do |s,r|
50
+ string.codepoints.inject(0) do |s,r|
51
51
  s + character_width_by_code(r)
52
52
  end * scale
53
53
  end
@@ -160,44 +160,18 @@ module Prawn
160
160
  end
161
161
 
162
162
  def normalize_encoding(text)
163
- if text.respond_to?(:encode)
164
- # if we're running under a M17n aware VM, ensure the string provided is
165
- # UTF-8 (by converting it if necessary)
166
- begin
167
- text.encode("UTF-8")
168
- rescue
169
- raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " +
170
- "#{text.encoding} can not be transparently converted to UTF-8. " +
171
- "Please ensure the encoding of the string you are attempting " +
172
- "to use is set correctly"
173
- end
174
- else
175
- # on a non M17N aware VM, use unpack as a hackish way to verify the
176
- # string is valid utf-8. I thought it was better than loading iconv
177
- # though.
178
- begin
179
- text.unpack("U*")
180
- return text.dup
181
- rescue
182
- raise Prawn::Errors::IncompatibleStringEncoding, "The string you " +
183
- "are attempting to render is not encoded in valid UTF-8."
184
- end
185
- end
163
+ text.normalize_to_utf8
186
164
  end
187
165
 
188
166
  def glyph_present?(char)
189
- code = char.unpack("U*").first
167
+ code = char.codepoints.first
190
168
  cmap[code] > 0
191
169
  end
192
170
 
193
171
  # Returns the number of characters in +str+ (a UTF-8-encoded string).
194
172
  #
195
173
  def character_count(str)
196
- if str.respond_to?(:encode)
197
- str.length
198
- else
199
- str.unpack("U*").length
200
- end
174
+ str.unicode_length
201
175
  end
202
176
 
203
177
  private
@@ -214,7 +188,7 @@ module Prawn
214
188
  def kern(string)
215
189
  a = []
216
190
 
217
- string.unpack("U*").each do |r|
191
+ string.codepoints do |r|
218
192
  if a.empty?
219
193
  a << [r]
220
194
  elsif (kern = kern_pairs_table[[cmap[a.last.last], cmap[r]]])
@@ -282,8 +256,7 @@ module Prawn
282
256
 
283
257
  compressed_font = Zlib::Deflate.deflate(font_content)
284
258
 
285
- fontfile = @document.ref!(:Length => compressed_font.size,
286
- :Length1 => font_content.size,
259
+ fontfile = @document.ref!(:Length1 => font_content.size,
287
260
  :Filter => :FlateDecode )
288
261
  fontfile << compressed_font
289
262
 
@@ -12,7 +12,7 @@ require "prawn/graphics/cap_style"
12
12
  require "prawn/graphics/join_style"
13
13
  require "prawn/graphics/transparency"
14
14
  require "prawn/graphics/transformation"
15
- require "prawn/graphics/gradient"
15
+ require "prawn/graphics/patterns"
16
16
 
17
17
  module Prawn
18
18
 
@@ -30,7 +30,7 @@ module Prawn
30
30
  include JoinStyle
31
31
  include Transparency
32
32
  include Transformation
33
- include Gradient
33
+ include Patterns
34
34
 
35
35
  #######################################################################
36
36
  # Low level drawing operations must map the point to absolute coords! #
@@ -222,19 +222,19 @@ module Prawn
222
222
 
223
223
  # Upper right hand corner
224
224
  curve_to [x, y + r2],
225
- :bounds => [[x + r1, y + l1], [x + l2, y + r2]]
225
+ :bounds => [[x + r1, y + l2], [x + l1, y + r2]]
226
226
 
227
227
  # Upper left hand corner
228
228
  curve_to [x - r1, y],
229
- :bounds => [[x - l2, y + r2], [x - r1, y + l1]]
229
+ :bounds => [[x - l1, y + r2], [x - r1, y + l2]]
230
230
 
231
231
  # Lower left hand corner
232
232
  curve_to [x, y - r2],
233
- :bounds => [[x - r1, y - l1], [x - l2, y - r2]]
233
+ :bounds => [[x - r1, y - l2], [x - l1, y - r2]]
234
234
 
235
235
  # Lower right hand corner
236
236
  curve_to [x + r1, y],
237
- :bounds => [[x + l2, y - r2], [x + r1, y - l1]]
237
+ :bounds => [[x + l1, y - r2], [x + r1, y - l2]]
238
238
 
239
239
  move_to(x, y)
240
240
  end
@@ -337,23 +337,148 @@ module Prawn
337
337
  add_content "h"
338
338
  end
339
339
 
340
- # Provides the following shortcuts:
341
- #
342
- # stroke_some_method(*args) #=> some_method(*args); stroke
343
- # fill_some_method(*args) #=> some_method(*args); fill
344
- # fill_and_stroke_some_method(*args) #=> some_method(*args); fill_and_stroke
345
- #
346
- def method_missing(id,*args,&block)
347
- case(id.to_s)
348
- when /^fill_and_stroke_(.*)/
349
- send($1,*args,&block); fill_and_stroke
350
- when /^stroke_(.*)/
351
- send($1,*args,&block); stroke
352
- when /^fill_(.*)/
353
- send($1,*args,&block); fill
354
- else
355
- super
356
- end
340
+ ##
341
+ # :method: stroke_rectangle
342
+ # Draws and strokes a rectangle given +point+, +width+ and +height+. The rectangle is bounded by its upper-left corner.
343
+ # :call-seq:
344
+ # stroke_rectangle(point,width,height)
345
+
346
+ ##
347
+ # :method: fill_rectangle
348
+ # Draws and fills ills a rectangle given +point+, +width+ and +height+. The rectangle is bounded by its upper-left corner.
349
+ # :call-seq:
350
+ # fill_rectangle(point,width,height)
351
+
352
+ ##
353
+ # :method: fill_and_stroke_rectangle
354
+ # Draws, fills, and strokes a rectangle given +point+, +width+ and +height+. The rectangle is bounded by its upper-left corner.
355
+ # :call-seq:
356
+ # fill_and_stroke_rectangle(point,width,height)
357
+
358
+ ##
359
+ # :method: stroke_rounded_rectangle
360
+ # Draws and strokes a rounded rectangle given +point+, +width+ and +height+ and +radius+ for the rounded corner. The rectangle is bounded by its upper-left corner.
361
+ # :call-seq:
362
+ # stroke_rounded_rectangle(point,width,height,radius)
363
+
364
+ ##
365
+ # :method: fill_rounded_rectangle
366
+ # Draws and fills a rounded rectangle given +point+, +width+ and +height+ and +radius+ for the rounded corner. The rectangle is bounded by its upper-left corner.
367
+ # :call-seq:
368
+ # fill_rounded_rectangle(point,width,height,radius)
369
+
370
+ ##
371
+ # :method: stroke_and_fill_rounded_rectangle
372
+ # Draws, fills, and strokes a rounded rectangle given +point+, +width+ and +height+ and +radius+ for the rounded corner. The rectangle is bounded by its upper-left corner.
373
+ # :call-seq:
374
+ # stroke_and_fill_rounded_rectangle(point,width,height,radius)
375
+
376
+ ##
377
+ # :method: stroke_line
378
+ # Strokes a line from one point to another. Points may be specified as tuples or flattened argument list.
379
+ # :call-seq:
380
+ # stroke_line(*points)
381
+
382
+ ##
383
+ # :method: stroke_horizontal_line
384
+ # Strokes a horizontal line from +x1+ to +x2+ at the current y position, or the position specified by the :at option.
385
+ # :call-seq:
386
+ # stroke_horizontal_line(x1,x2,options={})
387
+
388
+ ##
389
+ # :method: stroke_horizontal_rule
390
+ # Strokes a horizontal line from the left border to the right border of the bounding box at the current y position.
391
+
392
+ ##
393
+ # :method: stroke_vertical_line
394
+ # Strokes a vertical line at the x coordinate given by :at from y1 to y2.
395
+ # :call-seq:
396
+ # stroke_vertical_line(y1,y2,params)
397
+
398
+ ##
399
+ # :method: stroke_curve
400
+ # Strokes a Bezier curve between two points, bounded by two additional points.
401
+ # :call-seq:
402
+ # stroke_curve(origin,dest,options={})
403
+
404
+ ##
405
+ # :method: stroke_circle
406
+ # Draws and strokes a circle of radius +radius+ with the centre-point at +point+.
407
+ # :call-seq:
408
+ # stroke_circle(center,radius)
409
+
410
+ ##
411
+ # :method: fill_circle
412
+ # Draws and fills a circle of radius +radius+ with the centre-point at +point+.
413
+ # :call-seq:
414
+ # fill_circle(center,radius)
415
+
416
+ ##
417
+ # :method: fill_and_stroke_circle
418
+ # Draws, strokes, and fills a circle of radius +radius+ with the centre-point at +point+.
419
+ # :call-seq:
420
+ # fill_and_stroke_circle(center,radius)
421
+
422
+ ##
423
+ # :method: stroke_ellipse
424
+ # Draws and strokes an ellipse of x radius +r1+ and y radius +r2+ with the centre-point at +point+.
425
+ # :call-seq:
426
+ # stroke_ellipse(point, r1, r2 = r1)
427
+
428
+ ##
429
+ # :method: fill_ellipse
430
+ # Draws and fills an ellipse of x radius +r1+ and y radius +r2+ with the centre-point at +point+.
431
+ # :call-seq:
432
+ # fill_ellipse(point, r1, r2 = r1)
433
+
434
+ ##
435
+ # :method: fill_and_stroke_ellipse
436
+ # Draws, strokes, and fills an ellipse of x radius +r1+ and y radius +r2+ with the centre-point at +point+.
437
+ # :call-seq:
438
+ # fill_and_stroke_ellipse(point, r1, r2 = r1)
439
+
440
+ ##
441
+ # :method: stroke_polygon
442
+ # Draws and strokes a polygon from the specified points.
443
+ # :call-seq:
444
+ # stroke_polygon(*points)
445
+
446
+ ##
447
+ # :method: fill_polygon
448
+ # Draws and fills a polygon from the specified points.
449
+ # :call-seq:
450
+ # fill_polygon(*points)
451
+
452
+ ##
453
+ # :method: fill_and_stroke_polygon
454
+ # Draws, strokes, and fills a polygon from the specified points.
455
+ # :call-seq:
456
+ # fill_and_stroke_polygon(*points)
457
+
458
+ ##
459
+ # :method: stroke_rounded_polygon
460
+ # Draws and strokes a rounded polygon from specified points, using +radius+ to define Bezier curves.
461
+ # :call-seq:
462
+ # stroke_rounded_polygon(radius, *points)
463
+
464
+ ##
465
+ # :method: fill_rounded_polygon
466
+ # Draws and fills a rounded polygon from specified points, using +radius+ to define Bezier curves.
467
+ # :call-seq:
468
+ # fill_rounded_polygon(radius, *points)
469
+
470
+ ##
471
+ # :method: fill_and_stroke_rounded_polygon
472
+ # Draws, strokes, and fills a rounded polygon from specified points, using +radius+ to define Bezier curves.
473
+ # :call-seq:
474
+ # fill_and_stroke_rounded_polygon(radius, *points)
475
+
476
+ ops = %w{fill stroke fill_and_stroke}
477
+ shapes = %w{line_to curve_to rectangle rounded_rectangle line horizontal_line horizontal_rule vertical_line
478
+ curve circle_at circle ellipse_at ellipse polygon rounded_polygon rounded_vertex}
479
+
480
+ ops.product(shapes).each do |operation,shape|
481
+ class_eval "def #{operation}_#{shape}(*args); #{shape}(*args); #{operation}; end"
357
482
  end
358
483
 
359
484
  private
@@ -95,7 +95,14 @@ module Prawn
95
95
  when String
96
96
  :RGB
97
97
  when Array
98
- :CMYK
98
+ case color.length
99
+ when 3
100
+ :RGB
101
+ when 4
102
+ :CMYK
103
+ else
104
+ raise ArgumentError, "Unknown type of color: #{color.inspect}"
105
+ end
99
106
  end
100
107
  end
101
108
 
@@ -0,0 +1,137 @@
1
+ # encoding: utf-8
2
+
3
+ # patterns.rb : Implements axial & radial gradients
4
+ #
5
+ # Originally implemented by Wojciech Piekutowski. November, 2009
6
+ # Copyright September 2012, Alexander Mankuta. All Rights Reserved.
7
+ #
8
+ # This is free software. Please see the LICENSE and COPYING files for details.
9
+ #
10
+ module Prawn
11
+ module Graphics
12
+ module Patterns
13
+
14
+ # Sets the fill gradient from color1 to color2.
15
+ # old arguments: point, width, height, color1, color2, options = {}
16
+ # new arguments: from, to, color1, color1
17
+ # or from, r1, to, r2, color1, color2
18
+ def fill_gradient(*args)
19
+ if args[1].is_a?(Array) || args[2].is_a?(Array)
20
+ set_gradient(:fill, *args)
21
+ else
22
+ warn "[DEPRECATION] 'fill_gradient(point, width, height,...)' is deprecated in favor of 'fill_gradient(from, to,...)'. " +
23
+ "Old arguments will be removed in release 1.1"
24
+ set_gradient :fill, args[0], [args[0].first, args[0].last - args[2]], args[3], args[4]
25
+ end
26
+ end
27
+
28
+ # Sets the stroke gradient from color1 to color2.
29
+ # old arguments: point, width, height, color1, color2, options = {}
30
+ # new arguments: from, to, color1, color2
31
+ # or from, r1, to, r2, color1, color2
32
+ def stroke_gradient(*args)
33
+ if args[1].is_a?(Array) || args[2].is_a?(Array)
34
+ set_gradient(:stroke, *args)
35
+ else
36
+ warn "[DEPRECATION] 'stroke_gradient(point, width, height,...)' is deprecated in favor of 'stroke_gradient(from, to,...)'. " +
37
+ "Old arguments will be removed in release 1.1"
38
+ set_gradient :stroke, args[0], [args[0].first, args[0].last - args[2]], args[3], args[4]
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def set_gradient(type, *grad)
45
+ patterns = page.resources[:Pattern] ||= {}
46
+
47
+ registry_key = gradient_registry_key grad
48
+
49
+ if patterns["SP#{registry_key}"]
50
+ shading = patterns["SP#{registry_key}"]
51
+ else
52
+ unless shading = gradient_registry[registry_key]
53
+ shading = gradient(*grad)
54
+ gradient_registry[registry_key] = shading
55
+ end
56
+
57
+ patterns["SP#{registry_key}"] = shading
58
+ end
59
+
60
+ operator = case type
61
+ when :fill
62
+ 'scn'
63
+ when :stroke
64
+ 'SCN'
65
+ else
66
+ raise ArgumentError, "unknown type '#{type}'"
67
+ end
68
+
69
+ set_color_space type, :Pattern
70
+ add_content "/SP#{registry_key} #{operator}"
71
+ end
72
+
73
+ def gradient_registry_key(gradient)
74
+ if gradient[1].is_a?(Array) # axial
75
+ [
76
+ map_to_absolute(gradient[0]),
77
+ map_to_absolute(gradient[1]),
78
+ gradient[2], gradient[3]
79
+ ]
80
+ else # radial
81
+ [
82
+ map_to_absolute(gradient[0]),
83
+ gradient[1],
84
+ map_to_absolute(gradient[2]),
85
+ gradient[3],
86
+ gradient[4], gradient[5]
87
+ ]
88
+ end.hash
89
+ end
90
+
91
+ def gradient_registry
92
+ @gradient_registry ||= {}
93
+ end
94
+
95
+ def gradient(*args)
96
+ if args.length != 4 && args.length != 6
97
+ raise ArgumentError, "Unknown type of gradient: #{args.inspect}"
98
+ end
99
+
100
+ color1 = normalize_color(args[-2]).dup.freeze
101
+ color2 = normalize_color(args[-1]).dup.freeze
102
+
103
+ if color_type(color1) != color_type(color2)
104
+ raise ArgumentError, "Both colors must be of the same color space: #{color1.inspect} and #{color2.inspect}"
105
+ end
106
+
107
+ process_color color1
108
+ process_color color2
109
+
110
+ shader = ref!({
111
+ :FunctionType => 2,
112
+ :Domain => [0.0, 1.0],
113
+ :C0 => color1,
114
+ :C1 => color2,
115
+ :N => 1.0,
116
+ })
117
+
118
+ shading = ref!({
119
+ :ShadingType => args.length == 4 ? 2 : 3, # axial : radial shading
120
+ :ColorSpace => color_space(color1),
121
+ :Coords => args.length == 4 ?
122
+ [0, 0, args[1].first - args[0].first, args[1].last - args[0].last] :
123
+ [0, 0, args[1], args[2].first - args[0].first, args[2].last - args[0].last, args[3]],
124
+ :Function => shader,
125
+ :Extend => [true, true],
126
+ })
127
+
128
+ shading_pattern = ref!({
129
+ :PatternType => 2, # shading pattern
130
+ :Shading => shading,
131
+ :Matrix => [1, 0,
132
+ 0, 1] + map_to_absolute(args[0]),
133
+ })
134
+ end
135
+ end
136
+ end
137
+ end
@@ -14,8 +14,9 @@ module Prawn
14
14
  # Add the image at filename to the current page. Currently only
15
15
  # JPG and PNG files are supported.
16
16
  #
17
- # NOTE: Prawn is very slow at rendering PNGs with alpha channels. The
18
- # workaround for those who don't mind installing RMagick is to use:
17
+ # NOTE: Prawn is very slow at rendering PNGs with alpha channels, and this
18
+ # uses a lot of RAM. The workaround for those who don't mind installing
19
+ # RMagick is to use:
19
20
  #
20
21
  # http://github.com/amberbit/prawn-fast-png
21
22
  #
@@ -32,10 +33,10 @@ module Prawn
32
33
  # <tt>:fit</tt>:: scale the dimensions of the image proportionally to fit inside [width,height]
33
34
  #
34
35
  # Prawn::Document.generate("image2.pdf", :page_layout => :landscape) do
35
- # pigs = "#{Prawn::BASEDIR}/data/images/pigs.jpg"
36
+ # pigs = "#{Prawn::DATADIR}/images/pigs.jpg"
36
37
  # image pigs, :at => [50,450], :width => 450
37
38
  #
38
- # dice = "#{Prawn::BASEDIR}/data/images/dice.png"
39
+ # dice = "#{Prawn::DATADIR}/images/dice.png"
39
40
  # image dice, :at => [50, 450], :scale => 0.75
40
41
  # end
41
42
  #
@@ -76,6 +77,12 @@ module Prawn
76
77
  # the given image. Return a pair: [pdf_obj, info].
77
78
  #
78
79
  def build_image_object(file)
80
+ # Rewind if the object we're passed is an IO, so that multiple embeds of
81
+ # the same IO object will work
82
+ file.rewind if file.respond_to?(:rewind)
83
+ # read the file as binary so the size is calculated correctly
84
+ file.binmode if file.respond_to?(:binmode)
85
+
79
86
  if file.respond_to?(:read)
80
87
  image_content = file.read
81
88
  else
@@ -139,17 +146,6 @@ module Prawn
139
146
  def image_position(w,h,options)
140
147
  options[:position] ||= :left
141
148
 
142
- x = case options[:position]
143
- when :left
144
- bounds.absolute_left
145
- when :center
146
- bounds.absolute_left + (bounds.width - w) / 2.0
147
- when :right
148
- bounds.absolute_right - w
149
- when Numeric
150
- options[:position] + bounds.absolute_left
151
- end
152
-
153
149
  y = case options[:vposition]
154
150
  when :top
155
151
  bounds.absolute_top
@@ -162,16 +158,26 @@ module Prawn
162
158
  else
163
159
  determine_y_with_page_flow(h)
164
160
  end
161
+
162
+ x = case options[:position]
163
+ when :left
164
+ bounds.left_side
165
+ when :center
166
+ bounds.left_side + (bounds.width - w) / 2.0
167
+ when :right
168
+ bounds.right_side - w
169
+ when Numeric
170
+ options[:position] + bounds.left_side
171
+ end
172
+
165
173
  return [x,y]
166
174
  end
167
175
 
168
176
  def determine_y_with_page_flow(h)
169
177
  if overruns_page?(h)
170
- start_new_page
171
- bounds.absolute_top
172
- else
173
- self.y
178
+ bounds.move_past_bottom
174
179
  end
180
+ self.y
175
181
  end
176
182
 
177
183
  def overruns_page?(h)