prawn 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -0
- data.tar.gz.sig +0 -0
- data/Gemfile +1 -9
- data/Rakefile +12 -22
- data/lib/prawn.rb +29 -48
- data/lib/prawn/document.rb +148 -123
- data/lib/prawn/document/bounding_box.rb +33 -26
- data/lib/prawn/document/column_box.rb +5 -7
- data/lib/prawn/document/internals.rb +6 -6
- data/lib/prawn/document/span.rb +20 -17
- data/lib/prawn/encoding.rb +65 -67
- data/lib/prawn/errors.rb +10 -7
- data/lib/prawn/font.rb +78 -62
- data/lib/prawn/font/afm.rb +93 -66
- data/lib/prawn/font/dfont.rb +2 -10
- data/lib/prawn/font/ttc.rb +34 -0
- data/lib/prawn/font/ttf.rb +73 -65
- data/lib/prawn/font_metric_cache.rb +9 -8
- data/lib/prawn/graphics.rb +110 -70
- data/lib/prawn/graphics/blend_mode.rb +7 -8
- data/lib/prawn/graphics/cap_style.rb +2 -4
- data/lib/prawn/graphics/color.rb +23 -26
- data/lib/prawn/graphics/dash.rb +22 -12
- data/lib/prawn/graphics/join_style.rb +8 -4
- data/lib/prawn/graphics/patterns.rb +185 -96
- data/lib/prawn/graphics/transformation.rb +11 -9
- data/lib/prawn/graphics/transparency.rb +15 -13
- data/lib/prawn/grid.rb +20 -20
- data/lib/prawn/image_handler.rb +4 -6
- data/lib/prawn/images.rb +22 -15
- data/lib/prawn/images/image.rb +0 -1
- data/lib/prawn/images/jpg.rb +26 -22
- data/lib/prawn/images/png.rb +60 -57
- data/lib/prawn/measurement_extensions.rb +8 -9
- data/lib/prawn/measurements.rb +14 -15
- data/lib/prawn/outline.rb +96 -78
- data/lib/prawn/repeater.rb +12 -10
- data/lib/prawn/security.rb +66 -48
- data/lib/prawn/security/arcfour.rb +1 -3
- data/lib/prawn/soft_mask.rb +23 -25
- data/lib/prawn/stamp.rb +16 -12
- data/lib/prawn/text.rb +59 -45
- data/lib/prawn/text/box.rb +9 -8
- data/lib/prawn/text/formatted.rb +4 -6
- data/lib/prawn/text/formatted/arranger.rb +51 -30
- data/lib/prawn/text/formatted/box.rb +112 -88
- data/lib/prawn/text/formatted/fragment.rb +10 -15
- data/lib/prawn/text/formatted/line_wrap.rb +118 -61
- data/lib/prawn/text/formatted/parser.rb +134 -110
- data/lib/prawn/text/formatted/wrap.rb +42 -32
- data/lib/prawn/transformation_stack.rb +3 -4
- data/lib/prawn/utilities.rb +6 -21
- data/lib/prawn/version.rb +1 -3
- data/lib/prawn/view.rb +4 -2
- data/manual/basic_concepts/adding_pages.rb +4 -7
- data/manual/basic_concepts/basic_concepts.rb +29 -22
- data/manual/basic_concepts/creation.rb +8 -11
- data/manual/basic_concepts/cursor.rb +2 -5
- data/manual/basic_concepts/measurement.rb +3 -6
- data/manual/basic_concepts/origin.rb +3 -6
- data/manual/basic_concepts/other_cursor_helpers.rb +9 -12
- data/manual/basic_concepts/view.rb +20 -16
- data/manual/bounding_box/bounding_box.rb +27 -24
- data/manual/bounding_box/bounds.rb +9 -12
- data/manual/bounding_box/canvas.rb +2 -5
- data/manual/bounding_box/creation.rb +4 -7
- data/manual/bounding_box/indentation.rb +12 -15
- data/manual/bounding_box/nesting.rb +22 -17
- data/manual/bounding_box/russian_boxes.rb +8 -9
- data/manual/bounding_box/stretchy.rb +10 -13
- data/manual/contents.rb +26 -22
- data/manual/cover.rb +22 -20
- data/manual/document_and_page_options/background.rb +9 -13
- data/manual/document_and_page_options/document_and_page_options.rb +23 -20
- data/manual/document_and_page_options/metadata.rb +16 -16
- data/manual/document_and_page_options/page_margins.rb +16 -20
- data/manual/document_and_page_options/page_size.rb +11 -12
- data/manual/document_and_page_options/print_scaling.rb +15 -15
- data/manual/example_helper.rb +2 -4
- data/manual/graphics/blend_mode.rb +10 -9
- data/manual/graphics/circle_and_ellipse.rb +2 -5
- data/manual/graphics/color.rb +5 -9
- data/manual/graphics/common_lines.rb +5 -8
- data/manual/graphics/fill_and_stroke.rb +2 -5
- data/manual/graphics/fill_rules.rb +7 -10
- data/manual/graphics/gradients.rb +25 -21
- data/manual/graphics/graphics.rb +49 -43
- data/manual/graphics/helper.rb +10 -9
- data/manual/graphics/line_width.rb +5 -7
- data/manual/graphics/lines_and_curves.rb +5 -8
- data/manual/graphics/polygon.rb +4 -8
- data/manual/graphics/rectangle.rb +2 -5
- data/manual/graphics/rotate.rb +4 -7
- data/manual/graphics/scale.rb +12 -15
- data/manual/graphics/soft_masks.rb +1 -4
- data/manual/graphics/stroke_cap.rb +3 -6
- data/manual/graphics/stroke_dash.rb +9 -12
- data/manual/graphics/stroke_join.rb +2 -5
- data/manual/graphics/translate.rb +7 -10
- data/manual/graphics/transparency.rb +5 -8
- data/manual/how_to_read_this_manual.rb +4 -6
- data/manual/images/absolute_position.rb +4 -7
- data/manual/images/fit.rb +5 -8
- data/manual/images/horizontal.rb +6 -9
- data/manual/images/images.rb +25 -23
- data/manual/images/plain_image.rb +3 -6
- data/manual/images/scale.rb +7 -10
- data/manual/images/vertical.rb +10 -13
- data/manual/images/width_and_height.rb +8 -11
- data/manual/layout/boxes.rb +3 -6
- data/manual/layout/content.rb +5 -8
- data/manual/layout/layout.rb +16 -16
- data/manual/layout/simple_grid.rb +4 -7
- data/manual/outline/add_subsection_to.rb +18 -21
- data/manual/outline/insert_section_after.rb +13 -16
- data/manual/outline/outline.rb +19 -17
- data/manual/outline/sections_and_pages.rb +15 -18
- data/manual/repeatable_content/alternate_page_numbering.rb +19 -17
- data/manual/repeatable_content/page_numbering.rb +15 -16
- data/manual/repeatable_content/repeatable_content.rb +23 -19
- data/manual/repeatable_content/repeater.rb +12 -15
- data/manual/repeatable_content/stamp.rb +12 -15
- data/manual/security/encryption.rb +7 -10
- data/manual/security/permissions.rb +17 -14
- data/manual/security/security.rb +17 -16
- data/manual/table.rb +2 -4
- data/manual/text/alignment.rb +14 -17
- data/manual/text/color.rb +10 -11
- data/manual/text/column_box.rb +5 -8
- data/manual/text/fallback_fonts.rb +23 -21
- data/manual/text/font.rb +9 -12
- data/manual/text/font_size.rb +11 -14
- data/manual/text/font_style.rb +4 -7
- data/manual/text/formatted_callbacks.rb +23 -21
- data/manual/text/formatted_text.rb +31 -25
- data/manual/text/free_flowing_text.rb +18 -21
- data/manual/text/inline.rb +16 -19
- data/manual/text/kerning_and_character_spacing.rb +12 -15
- data/manual/text/leading.rb +5 -8
- data/manual/text/line_wrapping.rb +33 -17
- data/manual/text/paragraph_indentation.rb +11 -14
- data/manual/text/positioned_text.rb +13 -16
- data/manual/text/registering_families.rb +16 -19
- data/manual/text/rendering_and_color.rb +7 -10
- data/manual/text/right_to_left_text.rb +24 -19
- data/manual/text/rotation.rb +26 -23
- data/manual/text/single_usage.rb +6 -9
- data/manual/text/text.rb +56 -52
- data/manual/text/text_box_excess.rb +18 -17
- data/manual/text/text_box_extensions.rb +16 -15
- data/manual/text/text_box_overflow.rb +15 -18
- data/manual/text/utf8.rb +9 -12
- data/manual/text/win_ansi_charset.rb +18 -19
- data/prawn.gemspec +37 -27
- data/spec/extensions/encoding_helpers.rb +0 -2
- data/spec/manual_spec.rb +33 -0
- data/spec/prawn/document/bounding_box_spec.rb +546 -0
- data/spec/prawn/document/column_box_spec.rb +73 -0
- data/spec/prawn/document/security_spec.rb +173 -0
- data/spec/prawn/document_annotations_spec.rb +74 -0
- data/spec/prawn/document_destinations_spec.rb +13 -0
- data/spec/prawn/document_grid_spec.rb +96 -0
- data/spec/prawn/document_reference_spec.rb +25 -0
- data/spec/prawn/document_span_spec.rb +34 -0
- data/spec/prawn/document_spec.rb +751 -0
- data/spec/prawn/font_metric_cache_spec.rb +52 -0
- data/spec/prawn/font_spec.rb +513 -0
- data/spec/prawn/graphics/blend_mode_spec.rb +61 -0
- data/spec/prawn/graphics/transparency_spec.rb +79 -0
- data/spec/prawn/graphics_spec.rb +817 -0
- data/spec/prawn/graphics_stroke_styles_spec.rb +227 -0
- data/spec/{image_handler_spec.rb → prawn/image_handler_spec.rb} +13 -15
- data/spec/prawn/images/jpg_spec.rb +18 -0
- data/spec/prawn/images/png_spec.rb +281 -0
- data/spec/prawn/images_spec.rb +170 -0
- data/spec/prawn/measurements_extensions_spec.rb +22 -0
- data/spec/prawn/outline_spec.rb +408 -0
- data/spec/prawn/repeater_spec.rb +163 -0
- data/spec/prawn/soft_mask_spec.rb +72 -0
- data/spec/prawn/stamp_spec.rb +168 -0
- data/spec/prawn/text/box_spec.rb +1113 -0
- data/spec/prawn/text/formatted/arranger_spec.rb +464 -0
- data/spec/prawn/text/formatted/box_spec.rb +825 -0
- data/spec/prawn/text/formatted/fragment_spec.rb +341 -0
- data/spec/prawn/text/formatted/line_wrap_spec.rb +491 -0
- data/spec/prawn/text/formatted/parser_spec.rb +667 -0
- data/spec/prawn/text_draw_text_spec.rb +147 -0
- data/spec/prawn/text_rendering_mode_spec.rb +42 -0
- data/spec/prawn/text_spacing_spec.rb +93 -0
- data/spec/prawn/text_spec.rb +601 -0
- data/spec/prawn/text_with_inline_formatting_spec.rb +33 -0
- data/spec/{transformation_stack_spec.rb → prawn/transformation_stack_spec.rb} +21 -20
- data/spec/prawn/view_spec.rb +45 -0
- data/spec/spec_helper.rb +16 -16
- metadata +96 -151
- metadata.gz.sig +1 -0
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.color +0 -0
- data/data/images/16bit.png +0 -0
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/blend_modes_bottom_layer.jpg +0 -0
- data/data/images/blend_modes_top_layer.jpg +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.color +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/dice_interlaced.png +0 -0
- data/data/images/fractal.jpg +0 -0
- data/data/images/indexed_color.dat +0 -0
- data/data/images/indexed_color.png +0 -0
- data/data/images/indexed_transparency.png +0 -0
- data/data/images/indexed_transparency_alpha.dat +0 -0
- data/data/images/indexed_transparency_color.dat +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/data/images/license.md +0 -8
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.color +0 -0
- data/data/images/page_white_text.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/prawn.png +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/ruport_type0.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/images/tru256.bmp +0 -0
- data/data/images/web-links.dat +0 -1
- data/data/images/web-links.png +0 -0
- data/data/pdfs/complex_template.pdf +0 -0
- data/data/pdfs/contains_ttf_font.pdf +0 -0
- data/data/pdfs/encrypted.pdf +0 -0
- data/data/pdfs/form.pdf +1 -819
- data/data/pdfs/hexagon.pdf +0 -61
- data/data/pdfs/indirect_reference.pdf +0 -86
- data/data/pdfs/multipage_template.pdf +0 -127
- data/data/pdfs/nested_pages.pdf +0 -118
- data/data/pdfs/page_without_mediabox.pdf +0 -193
- data/data/pdfs/resources_as_indirect_object.pdf +0 -83
- data/data/pdfs/two_hexagons.pdf +0 -90
- data/data/pdfs/version_1_6.pdf +0 -61
- data/data/shift_jis_text.txt +0 -1
- data/spec/acceptance/png_spec.rb +0 -35
- data/spec/annotations_spec.rb +0 -67
- data/spec/blend_mode_spec.rb +0 -71
- data/spec/bounding_box_spec.rb +0 -501
- data/spec/column_box_spec.rb +0 -59
- data/spec/destinations_spec.rb +0 -13
- data/spec/document_spec.rb +0 -738
- data/spec/font_metric_cache_spec.rb +0 -52
- data/spec/font_spec.rb +0 -475
- data/spec/formatted_text_arranger_spec.rb +0 -452
- data/spec/formatted_text_box_spec.rb +0 -716
- data/spec/formatted_text_fragment_spec.rb +0 -299
- data/spec/graphics_spec.rb +0 -705
- data/spec/grid_spec.rb +0 -95
- data/spec/images_spec.rb +0 -167
- data/spec/inline_formatted_text_parser_spec.rb +0 -568
- data/spec/jpg_spec.rb +0 -23
- data/spec/line_wrap_spec.rb +0 -366
- data/spec/measurement_units_spec.rb +0 -22
- data/spec/outline_spec.rb +0 -409
- data/spec/png_spec.rb +0 -257
- data/spec/reference_spec.rb +0 -25
- data/spec/repeater_spec.rb +0 -154
- data/spec/security_spec.rb +0 -151
- data/spec/soft_mask_spec.rb +0 -78
- data/spec/span_spec.rb +0 -43
- data/spec/stamp_spec.rb +0 -179
- data/spec/stroke_styles_spec.rb +0 -208
- data/spec/text_at_spec.rb +0 -142
- data/spec/text_box_spec.rb +0 -1042
- data/spec/text_rendering_mode_spec.rb +0 -45
- data/spec/text_spacing_spec.rb +0 -93
- data/spec/text_spec.rb +0 -543
- data/spec/text_with_inline_formatting_spec.rb +0 -35
- data/spec/transparency_spec.rb +0 -91
- data/spec/view_spec.rb +0 -42
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
#
|
3
1
|
# transformation.rb: Implements rotate, translate, skew, scale and a generic
|
4
2
|
# transformation_matrix
|
5
3
|
#
|
@@ -48,7 +46,7 @@ module Prawn
|
|
48
46
|
if options[:origin].nil?
|
49
47
|
transformation_matrix(cos, sin, -sin, cos, 0, 0, &block)
|
50
48
|
else
|
51
|
-
|
49
|
+
raise Prawn::Errors::BlockRequired unless block_given?
|
52
50
|
x = options[:origin][0] + bounds.absolute_left
|
53
51
|
y = options[:origin][1] + bounds.absolute_bottom
|
54
52
|
x_prime = x * cos - y * sin
|
@@ -59,8 +57,8 @@ module Prawn
|
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
62
|
-
# Translate the user space. If a block is not provided, then you must
|
63
|
-
# and restore the graphics state yourself.
|
60
|
+
# Translate the user space. If a block is not provided, then you must
|
61
|
+
# save and restore the graphics state yourself.
|
64
62
|
#
|
65
63
|
# Example without a block: move the text up and over 10
|
66
64
|
#
|
@@ -117,7 +115,7 @@ module Prawn
|
|
117
115
|
if options[:origin].nil?
|
118
116
|
transformation_matrix(factor, 0, 0, factor, 0, 0, &block)
|
119
117
|
else
|
120
|
-
|
118
|
+
raise Prawn::Errors::BlockRequired unless block_given?
|
121
119
|
x = options[:origin][0] + bounds.absolute_left
|
122
120
|
y = options[:origin][1] + bounds.absolute_bottom
|
123
121
|
x_prime = factor * x
|
@@ -142,11 +140,15 @@ module Prawn
|
|
142
140
|
# Transform the user space (see notes for rotate regarding graphics state)
|
143
141
|
# Generally, one would use the rotate, scale, translate, and skew
|
144
142
|
# convenience methods instead of calling transformation_matrix directly
|
145
|
-
def transformation_matrix(
|
146
|
-
|
143
|
+
def transformation_matrix(*matrix)
|
144
|
+
if matrix.length != 6
|
145
|
+
raise ArgumentError,
|
146
|
+
'Transformation matrix must have exacty 6 elements'
|
147
|
+
end
|
148
|
+
values = matrix.map { |x| format '%.5f', x }.join(' ')
|
147
149
|
save_graphics_state if block_given?
|
148
150
|
|
149
|
-
add_to_transformation_stack(
|
151
|
+
add_to_transformation_stack(*matrix)
|
150
152
|
|
151
153
|
renderer.add_content "#{values} cm"
|
152
154
|
if block_given?
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
#
|
3
1
|
# transparency.rb : Implements transparency
|
4
2
|
#
|
5
3
|
# Copyright October 2009, Daniel Nelson. All Rights Reserved.
|
@@ -51,14 +49,16 @@ module Prawn
|
|
51
49
|
# pdf.fill_and_stroke_circle([x, y], 25)
|
52
50
|
# end
|
53
51
|
#
|
54
|
-
def transparent(opacity, stroke_opacity = opacity
|
52
|
+
def transparent(opacity, stroke_opacity = opacity)
|
55
53
|
renderer.min_version(1.4)
|
56
54
|
|
57
|
-
opacity
|
55
|
+
opacity = [[opacity, 0.0].max, 1.0].min
|
58
56
|
stroke_opacity = [[stroke_opacity, 0.0].max, 1.0].min
|
59
57
|
|
60
58
|
save_graphics_state
|
61
|
-
renderer.add_content
|
59
|
+
renderer.add_content(
|
60
|
+
"/#{opacity_dictionary_name(opacity, stroke_opacity)} gs"
|
61
|
+
)
|
62
62
|
yield
|
63
63
|
restore_graphics_state
|
64
64
|
end
|
@@ -77,21 +77,23 @@ module Prawn
|
|
77
77
|
key = "#{opacity}_#{stroke_opacity}"
|
78
78
|
|
79
79
|
if opacity_dictionary_registry[key]
|
80
|
-
dictionary =
|
81
|
-
dictionary_name =
|
80
|
+
dictionary = opacity_dictionary_registry[key][:obj]
|
81
|
+
dictionary_name = opacity_dictionary_registry[key][:name]
|
82
82
|
else
|
83
83
|
dictionary = ref!(
|
84
|
-
:
|
85
|
-
:
|
86
|
-
:
|
84
|
+
Type: :ExtGState,
|
85
|
+
CA: stroke_opacity,
|
86
|
+
ca: opacity
|
87
87
|
)
|
88
88
|
|
89
89
|
dictionary_name = "Tr#{next_opacity_dictionary_id}"
|
90
|
-
opacity_dictionary_registry[key] = {
|
91
|
-
|
90
|
+
opacity_dictionary_registry[key] = {
|
91
|
+
name: dictionary_name,
|
92
|
+
obj: dictionary
|
93
|
+
}
|
92
94
|
end
|
93
95
|
|
94
|
-
page.ext_gstates
|
96
|
+
page.ext_gstates[dictionary_name] = dictionary
|
95
97
|
dictionary_name
|
96
98
|
end
|
97
99
|
end
|
data/lib/prawn/grid.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
# grid.rb: Provides a basic grid layout system for Prawn
|
4
2
|
#
|
5
3
|
# Contributed by Andrew O'Brien in March 2009
|
@@ -40,7 +38,8 @@ module Prawn
|
|
40
38
|
else
|
41
39
|
g1, g2 = args
|
42
40
|
|
43
|
-
if g1.
|
41
|
+
if g1.is_a?(Array) && g2.is_a?(Array) && g1.length == 2 &&
|
42
|
+
g2.length == 2
|
44
43
|
@boxes[args] = multi_box(single_box(*g1), single_box(*g2))
|
45
44
|
else
|
46
45
|
@boxes[args] = single_box(g1, g2)
|
@@ -63,7 +62,7 @@ module Prawn
|
|
63
62
|
@pdf = pdf
|
64
63
|
@columns = options[:columns]
|
65
64
|
@rows = options[:rows]
|
66
|
-
|
65
|
+
apply_gutter(options)
|
67
66
|
end
|
68
67
|
|
69
68
|
# Calculates the base width of boxes.
|
@@ -77,9 +76,9 @@ module Prawn
|
|
77
76
|
end
|
78
77
|
|
79
78
|
# Diagnostic tool to show all of the grids. Defaults to gray.
|
80
|
-
def show_all(color =
|
81
|
-
|
82
|
-
|
79
|
+
def show_all(color = 'CCCCCC')
|
80
|
+
rows.times do |i|
|
81
|
+
columns.times do |j|
|
83
82
|
pdf.grid(i, j).show(color)
|
84
83
|
end
|
85
84
|
end
|
@@ -91,12 +90,13 @@ module Prawn
|
|
91
90
|
(total.to_f - (gutter * (num - 1).to_f)) / num.to_f
|
92
91
|
end
|
93
92
|
|
94
|
-
def
|
93
|
+
def apply_gutter(options)
|
95
94
|
if options.key?(:gutter)
|
96
95
|
@gutter = options[:gutter].to_f
|
97
|
-
@row_gutter
|
96
|
+
@row_gutter = @gutter
|
97
|
+
@column_gutter = @gutter
|
98
98
|
else
|
99
|
-
@row_gutter
|
99
|
+
@row_gutter = options[:row_gutter].to_f
|
100
100
|
@column_gutter = options[:column_gutter].to_f
|
101
101
|
@gutter = 0
|
102
102
|
end
|
@@ -121,7 +121,7 @@ module Prawn
|
|
121
121
|
# col_num, row_num
|
122
122
|
#
|
123
123
|
def name
|
124
|
-
"#{@i
|
124
|
+
"#{@i},#{@j}"
|
125
125
|
end
|
126
126
|
|
127
127
|
# :nodoc
|
@@ -186,16 +186,16 @@ module Prawn
|
|
186
186
|
|
187
187
|
# Creates a standard bounding box based on the grid box.
|
188
188
|
def bounding_box(&blk)
|
189
|
-
pdf.bounding_box(top_left, :
|
189
|
+
pdf.bounding_box(top_left, width: width, height: height, &blk)
|
190
190
|
end
|
191
191
|
|
192
192
|
# Diagnostic method
|
193
|
-
def show(grid_color =
|
194
|
-
|
193
|
+
def show(grid_color = 'CCCCCC')
|
194
|
+
bounding_box do
|
195
195
|
original_stroke_color = pdf.stroke_color
|
196
196
|
|
197
197
|
pdf.stroke_color = grid_color
|
198
|
-
pdf.text
|
198
|
+
pdf.text name
|
199
199
|
pdf.stroke_bounds
|
200
200
|
|
201
201
|
pdf.stroke_color = original_stroke_color
|
@@ -219,7 +219,7 @@ module Prawn
|
|
219
219
|
end
|
220
220
|
|
221
221
|
def name
|
222
|
-
@bs.map(&:name).join(
|
222
|
+
@bs.map(&:name).join(':')
|
223
223
|
end
|
224
224
|
|
225
225
|
def total_height
|
@@ -257,19 +257,19 @@ module Prawn
|
|
257
257
|
private
|
258
258
|
|
259
259
|
def left_box
|
260
|
-
@left_box ||= @bs.
|
260
|
+
@left_box ||= @bs.min_by(&:left)
|
261
261
|
end
|
262
262
|
|
263
263
|
def right_box
|
264
|
-
@right_box ||= @bs.
|
264
|
+
@right_box ||= @bs.max_by(&:right)
|
265
265
|
end
|
266
266
|
|
267
267
|
def top_box
|
268
|
-
@top_box ||= @bs.
|
268
|
+
@top_box ||= @bs.max_by(&:top)
|
269
269
|
end
|
270
270
|
|
271
271
|
def bottom_box
|
272
|
-
@bottom_box ||= @bs.
|
272
|
+
@bottom_box ||= @bs.min_by(&:bottom)
|
273
273
|
end
|
274
274
|
end
|
275
275
|
|
data/lib/prawn/image_handler.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
# ImageHandler provides a way to register image processors with Prawn
|
4
2
|
#
|
5
3
|
# Contributed by Evan Sharp in November 2013.
|
@@ -29,16 +27,16 @@ module Prawn
|
|
29
27
|
end
|
30
28
|
|
31
29
|
def unregister(handler)
|
32
|
-
@handlers.reject!{ |h| h == handler }
|
30
|
+
@handlers.reject! { |h| h == handler }
|
33
31
|
end
|
34
32
|
|
35
33
|
def find(image_blob)
|
36
|
-
handler = @handlers.find{ |h| h.can_render? image_blob }
|
34
|
+
handler = @handlers.find { |h| h.can_render? image_blob }
|
37
35
|
|
38
36
|
return handler if handler
|
39
37
|
|
40
|
-
|
41
|
-
|
38
|
+
raise Prawn::Errors::UnsupportedImageType,
|
39
|
+
'image file is an unrecognised format'
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
data/lib/prawn/images.rb
CHANGED
@@ -17,16 +17,19 @@ module Prawn
|
|
17
17
|
# images with alpha channels can be processor and memory intensive.)
|
18
18
|
#
|
19
19
|
# Arguments:
|
20
|
-
# <tt>file</tt>:: path to file or an object that responds to #read and
|
20
|
+
# <tt>file</tt>:: path to file or an object that responds to #read and
|
21
|
+
# #rewind
|
21
22
|
#
|
22
23
|
# Options:
|
23
|
-
# <tt>:at</tt>:: an array [x,y] with the location of the top left corner of
|
24
|
+
# <tt>:at</tt>:: an array [x,y] with the location of the top left corner of
|
25
|
+
# the image.
|
24
26
|
# <tt>:position</tt>:: One of (:left, :center, :right) or an x-offset
|
25
|
-
# <tt>:vposition</tt>:: One of (:top, :center, :
|
27
|
+
# <tt>:vposition</tt>:: One of (:top, :center, :bottom) or an y-offset
|
26
28
|
# <tt>:height</tt>:: the height of the image [actual height of the image]
|
27
29
|
# <tt>:width</tt>:: the width of the image [actual width of the image]
|
28
30
|
# <tt>:scale</tt>:: scale the dimensions of the image proportionally
|
29
|
-
# <tt>:fit</tt>:: scale the dimensions of the image proportionally to fit
|
31
|
+
# <tt>:fit</tt>:: scale the dimensions of the image proportionally to fit
|
32
|
+
# inside [width,height]
|
30
33
|
#
|
31
34
|
# Prawn::Document.generate("image2.pdf", :page_layout => :landscape) do
|
32
35
|
# pigs = "#{Prawn::DATADIR}/images/pigs.jpg"
|
@@ -52,7 +55,7 @@ module Prawn
|
|
52
55
|
# require "open-uri"
|
53
56
|
#
|
54
57
|
# Prawn::Document.generate("remote_images.pdf") do
|
55
|
-
# image open("http://
|
58
|
+
# image open("http://prawnpdf.org/media/prawn_logo.png")
|
56
59
|
# end
|
57
60
|
#
|
58
61
|
# This method returns an image info object which can be used to check the
|
@@ -60,8 +63,10 @@ module Prawn
|
|
60
63
|
# (See also: Prawn::Images::PNG , Prawn::Images::JPG)
|
61
64
|
#
|
62
65
|
def image(file, options = {})
|
63
|
-
Prawn.verify_options [
|
64
|
-
|
66
|
+
Prawn.verify_options [
|
67
|
+
:at, :position, :vposition, :height,
|
68
|
+
:width, :scale, :fit
|
69
|
+
], options
|
65
70
|
|
66
71
|
pdf_obj, info = build_image_object(file)
|
67
72
|
embed_image(pdf_obj, info, options)
|
@@ -87,11 +92,13 @@ module Prawn
|
|
87
92
|
info = Prawn.image_handler.find(image_content).new(image_content)
|
88
93
|
|
89
94
|
# Bump PDF version if the image requires it
|
90
|
-
|
95
|
+
if info.respond_to?(:min_pdf_version)
|
96
|
+
renderer.min_version(info.min_pdf_version)
|
97
|
+
end
|
91
98
|
|
92
99
|
# Add the image to the PDF and register it in case we see it again.
|
93
100
|
image_obj = info.build_pdf_object(self)
|
94
|
-
image_registry[image_sha1] = { :
|
101
|
+
image_registry[image_sha1] = { obj: image_obj, info: info }
|
95
102
|
end
|
96
103
|
|
97
104
|
[image_obj, info]
|
@@ -117,9 +124,9 @@ module Prawn
|
|
117
124
|
# add a reference to the image object to the current page
|
118
125
|
# resource list and give it a label
|
119
126
|
label = "I#{next_image_id}"
|
120
|
-
state.page.xobjects
|
127
|
+
state.page.xobjects[label] = pdf_obj
|
121
128
|
|
122
|
-
cm_params = PDF::Core.real_params([
|
129
|
+
cm_params = PDF::Core.real_params([w, 0, 0, h, x, y - h])
|
123
130
|
renderer.add_content("\nq\n#{cm_params} cm\n/#{label} Do\nQ")
|
124
131
|
end
|
125
132
|
|
@@ -139,7 +146,7 @@ module Prawn
|
|
139
146
|
end
|
140
147
|
# String or Pathname
|
141
148
|
io_or_path = Pathname.new(io_or_path)
|
142
|
-
|
149
|
+
raise ArgumentError, "#{io_or_path} not found" unless io_or_path.file?
|
143
150
|
io = io_or_path.open('rb')
|
144
151
|
io
|
145
152
|
end
|
@@ -171,18 +178,18 @@ module Prawn
|
|
171
178
|
options[:position] + bounds.left_side
|
172
179
|
end
|
173
180
|
|
174
|
-
|
181
|
+
[x, y]
|
175
182
|
end
|
176
183
|
|
177
184
|
def determine_y_with_page_flow(h)
|
178
185
|
if overruns_page?(h)
|
179
186
|
bounds.move_past_bottom
|
180
187
|
end
|
181
|
-
|
188
|
+
y
|
182
189
|
end
|
183
190
|
|
184
191
|
def overruns_page?(h)
|
185
|
-
(
|
192
|
+
(y - h) < reference_bounds.absolute_bottom
|
186
193
|
end
|
187
194
|
|
188
195
|
def image_registry
|
data/lib/prawn/images/image.rb
CHANGED
data/lib/prawn/images/jpg.rb
CHANGED
@@ -19,10 +19,13 @@ module Prawn
|
|
19
19
|
attr_reader :width, :height, :bits, :channels
|
20
20
|
attr_accessor :scaled_width, :scaled_height
|
21
21
|
|
22
|
-
JPEG_SOF_BLOCKS = [
|
22
|
+
JPEG_SOF_BLOCKS = [
|
23
|
+
0xC0, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE,
|
24
|
+
0xCF
|
25
|
+
].freeze
|
23
26
|
|
24
27
|
def self.can_render?(image_blob)
|
25
|
-
image_blob[0, 3].unpack(
|
28
|
+
image_blob[0, 3].unpack('C*') == [255, 216, 255]
|
26
29
|
end
|
27
30
|
|
28
31
|
# Process a new JPG image
|
@@ -35,13 +38,13 @@ module Prawn
|
|
35
38
|
d.binmode
|
36
39
|
|
37
40
|
c_marker = 0xff # Section marker.
|
38
|
-
d.seek(2)
|
41
|
+
d.seek(2) # Skip the first two bytes of JPEG identifier.
|
39
42
|
loop do
|
40
43
|
marker, code, length = d.read(4).unpack('CCn')
|
41
|
-
|
44
|
+
raise 'JPEG marker not found!' if marker != c_marker
|
42
45
|
|
43
46
|
if JPEG_SOF_BLOCKS.include?(code)
|
44
|
-
@bits, @height, @width, @channels = d.read(6).unpack(
|
47
|
+
@bits, @height, @width, @channels = d.read(6).unpack('CnnC')
|
45
48
|
break
|
46
49
|
end
|
47
50
|
|
@@ -53,31 +56,32 @@ module Prawn
|
|
53
56
|
# a Reference to it.
|
54
57
|
#
|
55
58
|
def build_pdf_object(document)
|
56
|
-
color_space =
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
59
|
+
color_space =
|
60
|
+
case channels
|
61
|
+
when 1
|
62
|
+
:DeviceGray
|
63
|
+
when 3
|
64
|
+
:DeviceRGB
|
65
|
+
when 4
|
66
|
+
:DeviceCMYK
|
67
|
+
else
|
68
|
+
raise ArgumentError, 'JPG uses an unsupported number of channels'
|
69
|
+
end
|
66
70
|
|
67
71
|
obj = document.ref!(
|
68
|
-
:
|
69
|
-
:
|
70
|
-
:
|
71
|
-
:
|
72
|
-
:
|
73
|
-
:
|
72
|
+
Type: :XObject,
|
73
|
+
Subtype: :Image,
|
74
|
+
ColorSpace: color_space,
|
75
|
+
BitsPerComponent: bits,
|
76
|
+
Width: width,
|
77
|
+
Height: height
|
74
78
|
)
|
75
79
|
|
76
80
|
# add extra decode params for CMYK images. By swapping the
|
77
81
|
# min and max values from the default, we invert the colours. See
|
78
82
|
# section 4.8.4 of the spec.
|
79
83
|
if color_space == :DeviceCMYK
|
80
|
-
obj.data[:Decode] = [
|
84
|
+
obj.data[:Decode] = [1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]
|
81
85
|
end
|
82
86
|
|
83
87
|
obj.stream << @data
|
data/lib/prawn/images/png.rb
CHANGED
@@ -26,7 +26,7 @@ module Prawn
|
|
26
26
|
attr_accessor :scaled_width, :scaled_height
|
27
27
|
|
28
28
|
def self.can_render?(image_blob)
|
29
|
-
image_blob[0, 8].unpack(
|
29
|
+
image_blob[0, 8].unpack('C*') == [137, 80, 78, 71, 13, 10, 26, 10]
|
30
30
|
end
|
31
31
|
|
32
32
|
# Process a new PNG image
|
@@ -36,28 +36,28 @@ module Prawn
|
|
36
36
|
def initialize(data)
|
37
37
|
data = StringIO.new(data.dup)
|
38
38
|
|
39
|
-
data.read(8)
|
39
|
+
data.read(8) # Skip the default header
|
40
40
|
|
41
|
-
@palette
|
42
|
-
@img_data =
|
41
|
+
@palette = ''
|
42
|
+
@img_data = ''
|
43
43
|
@transparency = {}
|
44
44
|
|
45
45
|
loop do
|
46
|
-
chunk_size
|
47
|
-
section
|
46
|
+
chunk_size = data.read(4).unpack('N')[0]
|
47
|
+
section = data.read(4)
|
48
48
|
case section
|
49
49
|
when 'IHDR'
|
50
50
|
# we can grab other interesting values from here (like width,
|
51
51
|
# height, etc)
|
52
|
-
values = data.read(chunk_size).unpack(
|
52
|
+
values = data.read(chunk_size).unpack('NNCCCCC')
|
53
53
|
|
54
|
-
@width
|
55
|
-
@height
|
56
|
-
@bits
|
57
|
-
@color_type
|
54
|
+
@width = values[0]
|
55
|
+
@height = values[1]
|
56
|
+
@bits = values[2]
|
57
|
+
@color_type = values[3]
|
58
58
|
@compression_method = values[4]
|
59
|
-
@filter_method
|
60
|
-
@interlace_method
|
59
|
+
@filter_method = values[5]
|
60
|
+
@interlace_method = values[6]
|
61
61
|
when 'PLTE'
|
62
62
|
@palette << data.read(chunk_size)
|
63
63
|
when 'IDAT'
|
@@ -72,11 +72,11 @@ module Prawn
|
|
72
72
|
when 0
|
73
73
|
# Greyscale. Corresponding to entries in the PLTE chunk.
|
74
74
|
# Grey is two bytes, range 0 .. (2 ^ bit-depth) - 1
|
75
|
-
grayval = data.read(chunk_size).unpack(
|
75
|
+
grayval = data.read(chunk_size).unpack('n').first
|
76
76
|
@transparency[:grayscale] = grayval
|
77
77
|
when 2
|
78
78
|
# True colour with proper alpha channel.
|
79
|
-
@transparency[:rgb] = data.read(chunk_size).unpack(
|
79
|
+
@transparency[:rgb] = data.read(chunk_size).unpack('nnn')
|
80
80
|
end
|
81
81
|
when 'IEND'
|
82
82
|
# we've got everything we need, exit the loop
|
@@ -86,7 +86,7 @@ module Prawn
|
|
86
86
|
data.seek(data.pos + chunk_size)
|
87
87
|
end
|
88
88
|
|
89
|
-
data.read(4)
|
89
|
+
data.read(4) # Skip the CRC
|
90
90
|
end
|
91
91
|
|
92
92
|
@img_data = Zlib::Inflate.inflate(@img_data)
|
@@ -95,7 +95,7 @@ module Prawn
|
|
95
95
|
# number of color components to each pixel
|
96
96
|
#
|
97
97
|
def colors
|
98
|
-
case
|
98
|
+
case color_type
|
99
99
|
when 0, 3, 4
|
100
100
|
return 1
|
101
101
|
when 2, 6
|
@@ -128,18 +128,18 @@ module Prawn
|
|
128
128
|
#
|
129
129
|
def build_pdf_object(document)
|
130
130
|
if compression_method != 0
|
131
|
-
|
132
|
-
|
131
|
+
raise Errors::UnsupportedImageType,
|
132
|
+
'PNG uses an unsupported compression method'
|
133
133
|
end
|
134
134
|
|
135
135
|
if filter_method != 0
|
136
|
-
|
137
|
-
|
136
|
+
raise Errors::UnsupportedImageType,
|
137
|
+
'PNG uses an unsupported filter method'
|
138
138
|
end
|
139
139
|
|
140
140
|
if interlace_method != 0
|
141
|
-
|
142
|
-
|
141
|
+
raise Errors::UnsupportedImageType,
|
142
|
+
'PNG uses unsupported interlace method'
|
143
143
|
end
|
144
144
|
|
145
145
|
# some PNG types store the colour and alpha channel data together,
|
@@ -152,28 +152,28 @@ module Prawn
|
|
152
152
|
when 3
|
153
153
|
color = :DeviceRGB
|
154
154
|
else
|
155
|
-
|
156
|
-
|
155
|
+
raise Errors::UnsupportedImageType,
|
156
|
+
"PNG uses an unsupported number of colors (#{png.colors})"
|
157
157
|
end
|
158
158
|
|
159
159
|
# build the image dict
|
160
160
|
obj = document.ref!(
|
161
|
-
:
|
162
|
-
:
|
163
|
-
:
|
164
|
-
:
|
165
|
-
:
|
161
|
+
Type: :XObject,
|
162
|
+
Subtype: :Image,
|
163
|
+
Height: height,
|
164
|
+
Width: width,
|
165
|
+
BitsPerComponent: bits
|
166
166
|
)
|
167
167
|
|
168
168
|
# append the actual image data to the object as a stream
|
169
169
|
obj << img_data
|
170
170
|
|
171
171
|
obj.stream.filters << {
|
172
|
-
:
|
173
|
-
:
|
174
|
-
:
|
175
|
-
:
|
176
|
-
:
|
172
|
+
FlateDecode: {
|
173
|
+
Predictor: 15,
|
174
|
+
Colors: colors,
|
175
|
+
BitsPerComponent: bits,
|
176
|
+
Columns: width
|
177
177
|
}
|
178
178
|
}
|
179
179
|
|
@@ -186,10 +186,12 @@ module Prawn
|
|
186
186
|
palette_obj << palette
|
187
187
|
|
188
188
|
# build the color space array for the image
|
189
|
-
obj.data[:ColorSpace] = [
|
190
|
-
|
191
|
-
|
192
|
-
|
189
|
+
obj.data[:ColorSpace] = [
|
190
|
+
:Indexed,
|
191
|
+
:DeviceRGB,
|
192
|
+
(palette.size / 3) - 1,
|
193
|
+
palette_obj
|
194
|
+
]
|
193
195
|
end
|
194
196
|
|
195
197
|
# *************************************
|
@@ -213,27 +215,28 @@ module Prawn
|
|
213
215
|
obj.data[:Mask] = rgb.collect { |x| [x, x] }.flatten
|
214
216
|
end
|
215
217
|
|
216
|
-
# For PNG color types 4 and 6, the transparency data is stored as
|
217
|
-
# channel mixed in with the main image data. The PNG class
|
218
|
-
# it out for us and makes it available via the alpha_channel
|
218
|
+
# For PNG color types 4 and 6, the transparency data is stored as
|
219
|
+
# a alpha channel mixed in with the main image data. The PNG class
|
220
|
+
# seperates it out for us and makes it available via the alpha_channel
|
221
|
+
# attribute
|
219
222
|
if alpha_channel?
|
220
223
|
smask_obj = document.ref!(
|
221
|
-
:
|
222
|
-
:
|
223
|
-
:
|
224
|
-
:
|
225
|
-
:
|
226
|
-
:
|
227
|
-
:
|
224
|
+
Type: :XObject,
|
225
|
+
Subtype: :Image,
|
226
|
+
Height: height,
|
227
|
+
Width: width,
|
228
|
+
BitsPerComponent: bits,
|
229
|
+
ColorSpace: :DeviceGray,
|
230
|
+
Decode: [0, 1]
|
228
231
|
)
|
229
232
|
smask_obj.stream << alpha_channel
|
230
233
|
|
231
234
|
smask_obj.stream.filters << {
|
232
|
-
:
|
233
|
-
:
|
234
|
-
:
|
235
|
-
:
|
236
|
-
:
|
235
|
+
FlateDecode: {
|
236
|
+
Predictor: 15,
|
237
|
+
Colors: 1,
|
238
|
+
BitsPerComponent: bits,
|
239
|
+
Columns: width
|
237
240
|
}
|
238
241
|
}
|
239
242
|
obj.data[:SMask] = smask_obj
|
@@ -261,9 +264,9 @@ module Prawn
|
|
261
264
|
alpha_bytes = bits / 8
|
262
265
|
color_bytes = colors * bits / 8
|
263
266
|
|
264
|
-
scanline_length
|
267
|
+
scanline_length = (color_bytes + alpha_bytes) * width + 1
|
265
268
|
scanlines = @img_data.bytesize / scanline_length
|
266
|
-
pixels =
|
269
|
+
pixels = width * height
|
267
270
|
|
268
271
|
data = StringIO.new(@img_data)
|
269
272
|
data.binmode
|
@@ -284,7 +287,7 @@ module Prawn
|
|
284
287
|
color.putc filter
|
285
288
|
alpha.putc filter
|
286
289
|
|
287
|
-
|
290
|
+
width.times do
|
288
291
|
color.write data.read(color_bytes)
|
289
292
|
alpha.write data.read(alpha_bytes)
|
290
293
|
end
|