prawn 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|