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
|
# blend_mode.rb : Implements blend modes
|
4
2
|
#
|
5
3
|
# Contributed by John Ford. October, 2015
|
@@ -15,9 +13,10 @@ module Prawn
|
|
15
13
|
# Passing an array of blend modes is allowed. PDF viewers should
|
16
14
|
# blend layers based on the first recognized blend mode.
|
17
15
|
#
|
18
|
-
# Valid blend modes in v1.4 of the PDF spec include :Normal, :Multiply,
|
19
|
-
# :Overlay, :Darken, :Lighten, :ColorDodge, :ColorBurn, :HardLight,
|
20
|
-
# :Difference, :Exclusion, :Hue, :Saturation, :Color, and
|
16
|
+
# Valid blend modes in v1.4 of the PDF spec include :Normal, :Multiply,
|
17
|
+
# :Screen, :Overlay, :Darken, :Lighten, :ColorDodge, :ColorBurn, :HardLight,
|
18
|
+
# :SoftLight, :Difference, :Exclusion, :Hue, :Saturation, :Color, and
|
19
|
+
# :Luminosity.
|
21
20
|
#
|
22
21
|
# Example:
|
23
22
|
# pdf.fill_color('0000ff')
|
@@ -52,11 +51,11 @@ module Prawn
|
|
52
51
|
dictionary_name = "BM#{key}"
|
53
52
|
|
54
53
|
dictionary = blend_mode_dictionary_registry[dictionary_name] ||= ref!(
|
55
|
-
:
|
56
|
-
:
|
54
|
+
Type: :ExtGState,
|
55
|
+
BM: blend_mode
|
57
56
|
)
|
58
57
|
|
59
|
-
page.ext_gstates
|
58
|
+
page.ext_gstates[dictionary_name] = dictionary
|
60
59
|
dictionary_name
|
61
60
|
end
|
62
61
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
# cap_style.rb : Implements stroke cap styling
|
4
2
|
#
|
5
3
|
# Contributed by Daniel Nelson. October, 2009
|
@@ -11,7 +9,7 @@ module Prawn
|
|
11
9
|
module CapStyle
|
12
10
|
# @group Stable API
|
13
11
|
|
14
|
-
CAP_STYLES = { :
|
12
|
+
CAP_STYLES = { butt: 0, round: 1, projecting_square: 2 }.freeze
|
15
13
|
|
16
14
|
# Sets the cap style for stroked lines and curves
|
17
15
|
#
|
@@ -27,7 +25,7 @@ module Prawn
|
|
27
25
|
write_stroke_cap_style
|
28
26
|
end
|
29
27
|
|
30
|
-
|
28
|
+
alias cap_style= cap_style
|
31
29
|
|
32
30
|
private
|
33
31
|
|
data/lib/prawn/graphics/color.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
# color.rb : Implements color handling
|
4
2
|
#
|
5
3
|
# Copyright June 2008, Gregory Brown. All Rights Reserved.
|
@@ -31,7 +29,7 @@ module Prawn
|
|
31
29
|
set_fill_color
|
32
30
|
end
|
33
31
|
|
34
|
-
|
32
|
+
alias fill_color= fill_color
|
35
33
|
|
36
34
|
# Sets or returns the line stroking color.
|
37
35
|
#
|
@@ -54,7 +52,7 @@ module Prawn
|
|
54
52
|
set_stroke_color(color)
|
55
53
|
end
|
56
54
|
|
57
|
-
|
55
|
+
alias stroke_color= stroke_color
|
58
56
|
|
59
57
|
module_function
|
60
58
|
|
@@ -65,7 +63,7 @@ module Prawn
|
|
65
63
|
# => "ff7808"
|
66
64
|
#
|
67
65
|
def rgb2hex(rgb)
|
68
|
-
rgb.map { |e|
|
66
|
+
rgb.map { |e| format '%02x', e }.join
|
69
67
|
end
|
70
68
|
|
71
69
|
# Converts hex string into RGB value array:
|
@@ -74,27 +72,33 @@ module Prawn
|
|
74
72
|
# => [255, 120, 8]
|
75
73
|
#
|
76
74
|
def hex2rgb(hex)
|
77
|
-
r
|
75
|
+
r = hex[0..1]
|
76
|
+
g = hex[2..3]
|
77
|
+
b = hex[4..5]
|
78
78
|
[r, g, b].map { |e| e.to_i(16) }
|
79
79
|
end
|
80
80
|
|
81
81
|
private
|
82
82
|
|
83
83
|
def process_color(*color)
|
84
|
-
case
|
84
|
+
case color.size
|
85
85
|
when 1
|
86
86
|
color[0]
|
87
87
|
when 4
|
88
88
|
color
|
89
89
|
else
|
90
|
-
|
90
|
+
raise ArgumentError, 'wrong number of arguments supplied'
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
94
|
def color_type(color)
|
95
95
|
case color
|
96
96
|
when String
|
97
|
-
|
97
|
+
if color =~ /\A[0-F]{6}\z/i
|
98
|
+
:RGB
|
99
|
+
else
|
100
|
+
raise ArgumentError, "Unknown type of color: #{color.inspect}"
|
101
|
+
end
|
98
102
|
when Array
|
99
103
|
case color.length
|
100
104
|
when 3
|
@@ -102,7 +106,7 @@ module Prawn
|
|
102
106
|
when 4
|
103
107
|
:CMYK
|
104
108
|
else
|
105
|
-
|
109
|
+
raise ArgumentError, "Unknown type of color: #{color.inspect}"
|
106
110
|
end
|
107
111
|
end
|
108
112
|
end
|
@@ -119,7 +123,7 @@ module Prawn
|
|
119
123
|
end
|
120
124
|
|
121
125
|
def color_to_s(color)
|
122
|
-
normalize_color(color)
|
126
|
+
PDF::Core.real_params normalize_color(color)
|
123
127
|
end
|
124
128
|
|
125
129
|
def color_space(color)
|
@@ -131,15 +135,18 @@ module Prawn
|
|
131
135
|
end
|
132
136
|
end
|
133
137
|
|
134
|
-
COLOR_SPACES = [:DeviceRGB, :DeviceCMYK, :Pattern]
|
138
|
+
COLOR_SPACES = [:DeviceRGB, :DeviceCMYK, :Pattern].freeze
|
135
139
|
|
136
140
|
def set_color_space(type, color_space)
|
137
141
|
# don't set the same color space again
|
138
|
-
|
142
|
+
if current_color_space(type) == color_space &&
|
143
|
+
!state.page.in_stamp_stream?
|
144
|
+
return
|
145
|
+
end
|
139
146
|
set_current_color_space(color_space, type)
|
140
147
|
|
141
148
|
unless COLOR_SPACES.include?(color_space)
|
142
|
-
|
149
|
+
raise ArgumentError, "unknown color space: '#{color_space}'"
|
143
150
|
end
|
144
151
|
|
145
152
|
operator = case type
|
@@ -148,7 +155,7 @@ module Prawn
|
|
148
155
|
when :stroke
|
149
156
|
'CS'
|
150
157
|
else
|
151
|
-
|
158
|
+
raise ArgumentError, "unknown type '#{type}'"
|
152
159
|
end
|
153
160
|
|
154
161
|
renderer.add_content "/#{color_space} #{operator}"
|
@@ -161,7 +168,7 @@ module Prawn
|
|
161
168
|
when :stroke
|
162
169
|
'SCN'
|
163
170
|
else
|
164
|
-
|
171
|
+
raise ArgumentError, "unknown type '#{type}'"
|
165
172
|
end
|
166
173
|
|
167
174
|
if options[:pattern]
|
@@ -187,8 +194,6 @@ module Prawn
|
|
187
194
|
set_stroke_color
|
188
195
|
end
|
189
196
|
|
190
|
-
private
|
191
|
-
|
192
197
|
def current_color_space(type)
|
193
198
|
graphic_state.color_space[type]
|
194
199
|
end
|
@@ -214,14 +219,6 @@ module Prawn
|
|
214
219
|
graphic_state.stroke_color = color
|
215
220
|
end
|
216
221
|
|
217
|
-
def write_fill_color
|
218
|
-
write_color(current_fill_color, 'scn')
|
219
|
-
end
|
220
|
-
|
221
|
-
def write_stroke_color
|
222
|
-
write_color(current_fill_color, 'SCN')
|
223
|
-
end
|
224
|
-
|
225
222
|
def write_color(color, operator)
|
226
223
|
renderer.add_content "#{color} #{operator}"
|
227
224
|
end
|
data/lib/prawn/graphics/dash.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
# dash.rb : Implements stroke dashing
|
4
2
|
#
|
5
3
|
# Contributed by Daniel Nelson. October, 2009
|
@@ -28,8 +26,9 @@ module Prawn
|
|
28
26
|
# 3 on, 2 off, 3 on, 2 off, ...
|
29
27
|
#
|
30
28
|
# * If the parameter +length+ is an array, it specifies the
|
31
|
-
# lengths of alternating dashes and gaps. The
|
32
|
-
#
|
29
|
+
# lengths of alternating dashes and gaps. The numbers must be
|
30
|
+
# non-negative and not all zero. The :space option is ignored
|
31
|
+
# in this case.
|
33
32
|
#
|
34
33
|
# Examples:
|
35
34
|
#
|
@@ -37,6 +36,8 @@ module Prawn
|
|
37
36
|
# 2 on, 1 off, 2 on, 1 off, ...
|
38
37
|
# length = [3, 1, 2, 3]
|
39
38
|
# 3 on, 1 off, 2 on, 3 off, 3 on, 1 off, ...
|
39
|
+
# length = [3, 0, 1]
|
40
|
+
# 3 on, 0 off, 1 on, 3 off, 0 on, 1 off, ...
|
40
41
|
#
|
41
42
|
# Options may contain the keys :space and :phase
|
42
43
|
#
|
@@ -55,19 +56,28 @@ module Prawn
|
|
55
56
|
def dash(length = nil, options = {})
|
56
57
|
return current_dash_state if length.nil?
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
59
|
+
length = Array(length)
|
60
|
+
|
61
|
+
if length.all?(&:zero?)
|
62
|
+
raise ArgumentError,
|
63
|
+
'Zero length dashes are invalid. Call #undash to disable dashes.'
|
64
|
+
elsif length.any? { |e| e < 0 }
|
65
|
+
raise ArgumentError,
|
66
|
+
'Negative numbers are not allowed for dash lengths.'
|
61
67
|
end
|
62
68
|
|
63
|
-
|
64
|
-
|
65
|
-
|
69
|
+
length = length.first if length.length == 1
|
70
|
+
|
71
|
+
self.current_dash_state = {
|
72
|
+
dash: length,
|
73
|
+
space: length.is_a?(Array) ? nil : options[:space] || length,
|
74
|
+
phase: options[:phase] || 0
|
75
|
+
}
|
66
76
|
|
67
77
|
write_stroke_dash
|
68
78
|
end
|
69
79
|
|
70
|
-
|
80
|
+
alias dash= dash
|
71
81
|
|
72
82
|
# Stops dashing, restoring solid stroked lines and curves
|
73
83
|
#
|
@@ -89,7 +99,7 @@ module Prawn
|
|
89
99
|
end
|
90
100
|
|
91
101
|
def undashed_setting
|
92
|
-
{ :
|
102
|
+
{ dash: nil, space: nil, phase: 0 }
|
93
103
|
end
|
94
104
|
|
95
105
|
def current_dash_state=(dash_options)
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
# join_style.rb : Implements stroke join styling
|
4
2
|
#
|
5
3
|
# Contributed by Daniel Nelson. October, 2009
|
@@ -9,7 +7,7 @@
|
|
9
7
|
module Prawn
|
10
8
|
module Graphics
|
11
9
|
module JoinStyle
|
12
|
-
JOIN_STYLES = { :
|
10
|
+
JOIN_STYLES = { miter: 0, round: 1, bevel: 2 }.freeze
|
13
11
|
|
14
12
|
# @group Stable API
|
15
13
|
|
@@ -25,10 +23,16 @@ module Prawn
|
|
25
23
|
|
26
24
|
self.current_join_style = style
|
27
25
|
|
26
|
+
unless JOIN_STYLES.key?(current_join_style)
|
27
|
+
raise Prawn::Errors::InvalidJoinStyle,
|
28
|
+
"#{style} is not a recognized join style. Valid styles are " +
|
29
|
+
JOIN_STYLES.keys.join(', ')
|
30
|
+
end
|
31
|
+
|
28
32
|
write_stroke_join_style
|
29
33
|
end
|
30
34
|
|
31
|
-
|
35
|
+
alias join_style= join_style
|
32
36
|
|
33
37
|
private
|
34
38
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'digest/sha1'
|
2
2
|
|
3
3
|
# patterns.rb : Implements axial & radial gradients
|
4
4
|
#
|
@@ -10,52 +10,83 @@
|
|
10
10
|
module Prawn
|
11
11
|
module Graphics
|
12
12
|
module Patterns
|
13
|
+
GradientStop = Struct.new(:position, :color)
|
14
|
+
Gradient = Struct.new(
|
15
|
+
:type, :apply_transformations, :stops, :from, :to, :r1, :r2
|
16
|
+
)
|
17
|
+
|
13
18
|
# @group Stable API
|
14
19
|
|
15
|
-
# Sets the fill gradient
|
16
|
-
# old arguments:
|
17
|
-
#
|
18
|
-
#
|
20
|
+
# Sets the fill gradient.
|
21
|
+
# old arguments:
|
22
|
+
# from, to, color1, color2
|
23
|
+
# or
|
24
|
+
# from, r1, to, r2, color1, color2
|
25
|
+
# new arguments:
|
26
|
+
# from: [x, y]
|
27
|
+
# to: [x, y]
|
28
|
+
# r1: radius
|
29
|
+
# r2: radius
|
30
|
+
# stops: [color, color, ...] or
|
31
|
+
# { position => color, position => color, ... }
|
32
|
+
# apply_transformations: true
|
33
|
+
#
|
34
|
+
# Examples:
|
35
|
+
#
|
36
|
+
# # draws a horizontal axial gradient that starts at red on the left
|
37
|
+
# # and ends at blue on the right
|
38
|
+
# fill_gradient from: [0, 0], to: [100, 0], stops: ['red', 'blue']
|
39
|
+
#
|
40
|
+
# # draws a horizontal radial gradient that starts at red, is green
|
41
|
+
# # 80% of the way through, and finishes blue
|
42
|
+
# fill_gradient from: [0, 0], r1: 0, to: [100, 0], r2: 180,
|
43
|
+
# stops: { 0 => 'red', 0.8 => 'green', 1 => 'blue' }
|
44
|
+
#
|
45
|
+
# <tt>from</tt> and <tt>to</tt> specify the axis of where the gradient
|
46
|
+
# should be painted.
|
19
47
|
#
|
20
|
-
#
|
48
|
+
# <tt>r1</tt> and <tt>r2</tt>, if specified, make a radial gradient with
|
49
|
+
# the starting circle of radius <tt>r1</tt> centered at <tt>from</tt>
|
50
|
+
# and ending at a circle of radius <tt>r2</tt> centered at <tt>to</tt>.
|
51
|
+
# If <tt>r1</tt> is not specified, a axial gradient will be drawn.
|
52
|
+
#
|
53
|
+
# <tt>stops</tt> is an array or hash of stops. Each stop is either just a
|
54
|
+
# string indicating the color, in which case the stops will be evenly
|
55
|
+
# distributed across the gradient, or a hash where the key is
|
56
|
+
# a position between 0 and 1 indicating what distance through the
|
57
|
+
# gradient the color should change, and the value is a color string.
|
58
|
+
#
|
59
|
+
# Option <tt>apply_transformations</tt>, if set true, will transform the
|
21
60
|
# gradient's co-ordinate space so it matches the current co-ordinate
|
22
|
-
# space of the document. This option will be the default from Prawn v3
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
|
27
|
-
|
61
|
+
# space of the document. This option will be the default from Prawn v3,
|
62
|
+
# and is default true if you use the new arguments format.
|
63
|
+
# The default for the old arguments format, false, will mean if you
|
64
|
+
# (for example) scale your document by 2 and put a gradient inside, you
|
65
|
+
# will have to manually multiply your co-ordinates by 2 so the gradient
|
66
|
+
# is correctly positioned.
|
67
|
+
def fill_gradient(*args, **kwargs)
|
68
|
+
set_gradient(:fill, *args, **kwargs)
|
28
69
|
end
|
29
70
|
|
30
|
-
# Sets the stroke gradient
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
#
|
35
|
-
# Option :apply_transformations, if set true, will transform the
|
36
|
-
# gradient's co-ordinate space so it matches the current co-ordinate
|
37
|
-
# space of the document. This option will be the default from Prawn v3.
|
38
|
-
# The current default, false, will mean if you (for example) scale your
|
39
|
-
# document by 2 and put a gradient inside, you will have to manually
|
40
|
-
# multiply your co-ordinates by 2 so the gradient is correctly positioned.
|
41
|
-
def stroke_gradient(*args)
|
42
|
-
set_gradient(:stroke, *args)
|
71
|
+
# Sets the stroke gradient.
|
72
|
+
# See fill_gradient for a description of the arguments to this method.
|
73
|
+
def stroke_gradient(*args, **kwargs)
|
74
|
+
set_gradient(:stroke, *args, **kwargs)
|
43
75
|
end
|
44
76
|
|
45
77
|
private
|
46
78
|
|
47
|
-
def set_gradient(type, *grad)
|
48
|
-
|
79
|
+
def set_gradient(type, *grad, **kwargs)
|
80
|
+
gradient = parse_gradient_arguments(*grad, **kwargs)
|
49
81
|
|
50
82
|
patterns = page.resources[:Pattern] ||= {}
|
51
83
|
|
52
|
-
registry_key = gradient_registry_key
|
84
|
+
registry_key = gradient_registry_key gradient
|
53
85
|
|
54
|
-
|
55
|
-
shading =
|
56
|
-
|
57
|
-
|
58
|
-
shading = gradient(grad, opts)
|
86
|
+
unless patterns.key? "SP#{registry_key}"
|
87
|
+
shading = gradient_registry[registry_key]
|
88
|
+
unless shading
|
89
|
+
shading = create_gradient_pattern(gradient)
|
59
90
|
gradient_registry[registry_key] = shading
|
60
91
|
end
|
61
92
|
|
@@ -68,96 +99,154 @@ module Prawn
|
|
68
99
|
when :stroke
|
69
100
|
'SCN'
|
70
101
|
else
|
71
|
-
|
102
|
+
raise ArgumentError, "unknown type '#{type}'"
|
72
103
|
end
|
73
104
|
|
74
105
|
set_color_space type, :Pattern
|
75
106
|
renderer.add_content "/SP#{registry_key} #{operator}"
|
76
107
|
end
|
77
108
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
gradient[1],
|
92
|
-
gradient[3],
|
93
|
-
gradient[4], gradient[5]
|
94
|
-
]
|
95
|
-
end.hash
|
96
|
-
end
|
97
|
-
|
98
|
-
def gradient_registry
|
99
|
-
@gradient_registry ||= {}
|
100
|
-
end
|
101
|
-
|
102
|
-
def gradient(args, opts)
|
103
|
-
if args.length != 4 && args.length != 6
|
104
|
-
fail ArgumentError, "Unknown type of gradient: #{args.inspect}"
|
109
|
+
def parse_gradient_arguments( # rubocop: disable Metrics/ParameterLists
|
110
|
+
*arguments, from: nil, to: nil, r1: nil, r2: nil, stops: nil,
|
111
|
+
apply_transformations: nil
|
112
|
+
)
|
113
|
+
case arguments.length
|
114
|
+
when 0
|
115
|
+
apply_transformations = true if apply_transformations.nil?
|
116
|
+
when 4
|
117
|
+
from, to, *stops = arguments
|
118
|
+
when 6
|
119
|
+
from, r1, to, r2, *stops = arguments
|
120
|
+
else
|
121
|
+
raise ArgumentError, "Unknown type of gradient: #{arguments.inspect}"
|
105
122
|
end
|
106
123
|
|
107
|
-
if
|
108
|
-
|
124
|
+
if stops.length < 2
|
125
|
+
raise ArgumentError, 'At least two stops must be specified'
|
109
126
|
end
|
110
127
|
|
111
|
-
|
112
|
-
|
128
|
+
stops = stops.map.with_index do |stop, index|
|
129
|
+
case stop
|
130
|
+
when Array, Hash
|
131
|
+
position, color = stop
|
132
|
+
else
|
133
|
+
position = index / (stops.length.to_f - 1)
|
134
|
+
color = stop
|
135
|
+
end
|
113
136
|
|
114
|
-
|
115
|
-
|
137
|
+
unless (0..1).cover?(position)
|
138
|
+
raise ArgumentError, 'position must be between 0 and 1'
|
139
|
+
end
|
140
|
+
GradientStop.new(position, normalize_color(color))
|
116
141
|
end
|
117
142
|
|
118
|
-
|
119
|
-
|
143
|
+
if stops.first.position != 0
|
144
|
+
raise ArgumentError, 'The first stop must have a position of 0'
|
145
|
+
end
|
146
|
+
if stops.last.position != 1
|
147
|
+
raise ArgumentError, 'The last stop must have a position of 1'
|
148
|
+
end
|
120
149
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
:
|
150
|
+
if stops.map { |stop| color_type(stop.color) }.uniq.length > 1
|
151
|
+
raise ArgumentError, 'All colors must be of the same color space'
|
152
|
+
end
|
153
|
+
|
154
|
+
Gradient.new(
|
155
|
+
r1 ? :radial : :axial,
|
156
|
+
apply_transformations,
|
157
|
+
stops,
|
158
|
+
from, to,
|
159
|
+
r1, r2
|
127
160
|
)
|
161
|
+
end
|
128
162
|
|
129
|
-
|
163
|
+
def gradient_registry_key(gradient)
|
164
|
+
_x1, _y1, x2, y2, transformation = gradient_coordinates(gradient)
|
165
|
+
|
166
|
+
key = [
|
167
|
+
gradient.type.to_s,
|
168
|
+
transformation,
|
169
|
+
x2, y2,
|
170
|
+
gradient.r1 || -1, gradient.r2 || -1,
|
171
|
+
gradient.stops.length,
|
172
|
+
gradient.stops.map { |s| [s.position, s.color] }
|
173
|
+
].flatten
|
174
|
+
Digest::SHA1.hexdigest(key.pack('HC*'))
|
175
|
+
end
|
130
176
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
177
|
+
def gradient_registry
|
178
|
+
@gradient_registry ||= {}
|
179
|
+
end
|
180
|
+
|
181
|
+
def create_gradient_pattern(gradient)
|
182
|
+
if gradient.apply_transformations.nil? &&
|
183
|
+
current_transformation_matrix_with_translation(0, 0) !=
|
184
|
+
[1, 0, 0, 1, 0, 0]
|
185
|
+
warn 'Gradients in Prawn 2.x and lower are not correctly positioned '\
|
186
|
+
'when a transformation has been made to the document. ' \
|
187
|
+
"Pass 'apply_transformations: true' to correctly transform the " \
|
188
|
+
'gradient, or see ' \
|
189
|
+
'https://github.com/prawnpdf/prawn/wiki/Gradient-Transformations ' \
|
190
|
+
'for more information.'
|
135
191
|
end
|
136
192
|
|
193
|
+
shader_stops = gradient.stops.each_cons(2).map do |first, second|
|
194
|
+
ref!(
|
195
|
+
FunctionType: 2,
|
196
|
+
Domain: [0.0, 1.0],
|
197
|
+
C0: first.color,
|
198
|
+
C1: second.color,
|
199
|
+
N: 1.0
|
200
|
+
)
|
201
|
+
end
|
202
|
+
|
203
|
+
# If there's only two stops, we can use the single shader.
|
204
|
+
# Otherwise we stitch the multiple shaders together.
|
205
|
+
shader = if shader_stops.length == 1
|
206
|
+
shader_stops.first
|
207
|
+
else
|
208
|
+
ref!(
|
209
|
+
FunctionType: 3, # stitching function
|
210
|
+
Domain: [0.0, 1.0],
|
211
|
+
Functions: shader_stops,
|
212
|
+
Bounds: gradient.stops[1..-2].map(&:position),
|
213
|
+
Encode: [0.0, 1.0] * shader_stops.length
|
214
|
+
)
|
215
|
+
end
|
216
|
+
|
217
|
+
x1, y1, x2, y2, transformation = gradient_coordinates(gradient)
|
218
|
+
|
219
|
+
coords = if gradient.type == :axial
|
220
|
+
[0, 0, x2 - x1, y2 - y1]
|
221
|
+
else
|
222
|
+
[0, 0, gradient.r1, x2 - x1, y2 - y1, gradient.r2]
|
223
|
+
end
|
224
|
+
|
137
225
|
shading = ref!(
|
138
|
-
:
|
139
|
-
:
|
140
|
-
:
|
141
|
-
:
|
142
|
-
:
|
226
|
+
ShadingType: gradient.type == :axial ? 2 : 3,
|
227
|
+
ColorSpace: color_space(gradient.stops.first.color),
|
228
|
+
Coords: coords,
|
229
|
+
Function: shader,
|
230
|
+
Extend: [true, true]
|
143
231
|
)
|
144
232
|
|
145
233
|
ref!(
|
146
|
-
:
|
147
|
-
:
|
148
|
-
:
|
234
|
+
PatternType: 2, # shading pattern
|
235
|
+
Shading: shading,
|
236
|
+
Matrix: transformation
|
149
237
|
)
|
150
238
|
end
|
151
239
|
|
152
|
-
def gradient_coordinates(
|
153
|
-
x1, y1 = map_to_absolute(
|
154
|
-
x2, y2 = map_to_absolute(
|
240
|
+
def gradient_coordinates(gradient)
|
241
|
+
x1, y1 = map_to_absolute(gradient.from)
|
242
|
+
x2, y2 = map_to_absolute(gradient.to)
|
155
243
|
|
156
|
-
transformation =
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
244
|
+
transformation =
|
245
|
+
if gradient.apply_transformations
|
246
|
+
current_transformation_matrix_with_translation(x1, y1)
|
247
|
+
else
|
248
|
+
[1, 0, 0, 1, x1, y1]
|
249
|
+
end
|
161
250
|
|
162
251
|
[x1, y1, x2, y2, transformation]
|
163
252
|
end
|