prawn 2.1.0 → 2.4.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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/GPLv2 +20 -21
- data/Gemfile +3 -9
- data/Rakefile +9 -41
- data/lib/prawn.rb +37 -49
- data/lib/prawn/document.rb +193 -141
- data/lib/prawn/document/bounding_box.rb +50 -30
- data/lib/prawn/document/column_box.rb +7 -7
- data/lib/prawn/document/internals.rb +8 -6
- data/lib/prawn/document/span.rb +22 -16
- data/lib/prawn/encoding.rb +69 -68
- data/lib/prawn/errors.rb +12 -7
- data/lib/prawn/font.rb +104 -69
- data/lib/prawn/font_metric_cache.rb +20 -13
- data/lib/prawn/{font → fonts}/afm.rb +108 -72
- data/lib/prawn/{font → fonts}/dfont.rb +5 -11
- data/lib/prawn/fonts/otf.rb +11 -0
- data/lib/prawn/fonts/ttc.rb +36 -0
- data/lib/prawn/{font → fonts}/ttf.rb +126 -81
- data/lib/prawn/graphics.rb +119 -81
- data/lib/prawn/graphics/blend_mode.rb +9 -8
- data/lib/prawn/graphics/cap_style.rb +3 -3
- data/lib/prawn/graphics/color.rb +43 -39
- data/lib/prawn/graphics/dash.rb +23 -11
- data/lib/prawn/graphics/join_style.rb +9 -3
- data/lib/prawn/graphics/patterns.rb +204 -102
- data/lib/prawn/graphics/transformation.rb +15 -9
- data/lib/prawn/graphics/transparency.rb +17 -13
- data/lib/prawn/grid.rb +84 -48
- data/lib/prawn/image_handler.rb +5 -5
- data/lib/prawn/images.rb +60 -49
- data/lib/prawn/images/image.rb +2 -1
- data/lib/prawn/images/jpg.rb +31 -22
- data/lib/prawn/images/png.rb +67 -63
- data/lib/prawn/measurement_extensions.rb +10 -9
- data/lib/prawn/measurements.rb +19 -15
- data/lib/prawn/outline.rb +98 -77
- data/lib/prawn/repeater.rb +15 -11
- data/lib/prawn/security.rb +93 -70
- data/lib/prawn/security/arcfour.rb +2 -2
- data/lib/prawn/soft_mask.rb +26 -26
- data/lib/prawn/stamp.rb +20 -13
- data/lib/prawn/text.rb +76 -60
- data/lib/prawn/text/box.rb +18 -14
- data/lib/prawn/text/formatted.rb +5 -5
- data/lib/prawn/text/formatted/arranger.rb +80 -40
- data/lib/prawn/text/formatted/box.rb +140 -101
- data/lib/prawn/text/formatted/fragment.rb +11 -14
- data/lib/prawn/text/formatted/line_wrap.rb +128 -67
- data/lib/prawn/text/formatted/parser.rb +147 -123
- data/lib/prawn/text/formatted/wrap.rb +48 -32
- data/lib/prawn/transformation_stack.rb +7 -5
- data/lib/prawn/utilities.rb +7 -22
- data/lib/prawn/version.rb +2 -2
- data/lib/prawn/view.rb +17 -7
- data/manual/basic_concepts/adding_pages.rb +6 -7
- data/manual/basic_concepts/basic_concepts.rb +31 -22
- data/manual/basic_concepts/creation.rb +10 -11
- data/manual/basic_concepts/cursor.rb +4 -5
- data/manual/basic_concepts/measurement.rb +7 -8
- data/manual/basic_concepts/origin.rb +5 -6
- data/manual/basic_concepts/other_cursor_helpers.rb +11 -12
- data/manual/basic_concepts/view.rb +22 -16
- data/manual/bounding_box/bounding_box.rb +29 -24
- data/manual/bounding_box/bounds.rb +11 -12
- data/manual/bounding_box/canvas.rb +7 -8
- data/manual/bounding_box/creation.rb +6 -7
- data/manual/bounding_box/indentation.rb +14 -15
- data/manual/bounding_box/nesting.rb +25 -18
- data/manual/bounding_box/russian_boxes.rb +14 -13
- data/manual/bounding_box/stretchy.rb +12 -13
- data/manual/contents.rb +28 -22
- data/manual/cover.rb +33 -28
- data/manual/document_and_page_options/background.rb +15 -13
- data/manual/document_and_page_options/document_and_page_options.rb +25 -20
- data/manual/document_and_page_options/metadata.rb +18 -16
- data/manual/document_and_page_options/page_margins.rb +18 -20
- data/manual/document_and_page_options/page_size.rb +13 -12
- data/manual/document_and_page_options/print_scaling.rb +18 -15
- data/manual/example_helper.rb +5 -4
- data/manual/graphics/blend_mode.rb +12 -9
- data/manual/graphics/circle_and_ellipse.rb +4 -5
- data/manual/graphics/color.rb +7 -9
- data/manual/graphics/common_lines.rb +7 -8
- data/manual/graphics/fill_and_stroke.rb +5 -6
- data/manual/graphics/fill_rules.rb +10 -10
- data/manual/graphics/gradients.rb +27 -21
- data/manual/graphics/graphics.rb +48 -40
- data/manual/graphics/helper.rb +19 -9
- data/manual/graphics/line_width.rb +8 -7
- data/manual/graphics/lines_and_curves.rb +7 -8
- data/manual/graphics/polygon.rb +6 -8
- data/manual/graphics/rectangle.rb +4 -5
- data/manual/graphics/rotate.rb +6 -7
- data/manual/graphics/scale.rb +14 -15
- data/manual/graphics/soft_masks.rb +3 -4
- data/manual/graphics/stroke_cap.rb +6 -7
- data/manual/graphics/stroke_dash.rb +15 -16
- data/manual/graphics/stroke_join.rb +5 -6
- data/manual/graphics/translate.rb +10 -10
- data/manual/graphics/transparency.rb +7 -8
- data/manual/how_to_read_this_manual.rb +6 -6
- data/manual/images/absolute_position.rb +6 -7
- data/manual/images/fit.rb +7 -8
- data/manual/images/horizontal.rb +10 -11
- data/manual/images/images.rb +28 -24
- data/manual/images/plain_image.rb +5 -6
- data/manual/images/scale.rb +9 -10
- data/manual/images/vertical.rb +16 -14
- data/manual/images/width_and_height.rb +10 -11
- data/manual/layout/boxes.rb +5 -6
- data/manual/layout/content.rb +7 -8
- data/manual/layout/layout.rb +18 -16
- data/manual/layout/simple_grid.rb +6 -7
- data/manual/outline/add_subsection_to.rb +20 -21
- data/manual/outline/insert_section_after.rb +15 -16
- data/manual/outline/outline.rb +21 -17
- data/manual/outline/sections_and_pages.rb +17 -18
- data/manual/repeatable_content/alternate_page_numbering.rb +21 -17
- data/manual/repeatable_content/page_numbering.rb +17 -16
- data/manual/repeatable_content/repeatable_content.rb +25 -19
- data/manual/repeatable_content/repeater.rb +14 -15
- data/manual/repeatable_content/stamp.rb +14 -15
- data/manual/security/encryption.rb +9 -10
- data/manual/security/permissions.rb +21 -14
- data/manual/security/security.rb +19 -16
- data/manual/table.rb +3 -3
- data/manual/text/alignment.rb +16 -17
- data/manual/text/color.rb +12 -11
- data/manual/text/column_box.rb +9 -10
- data/manual/text/fallback_fonts.rb +25 -21
- data/manual/text/font.rb +11 -12
- data/manual/text/font_size.rb +13 -14
- data/manual/text/font_style.rb +10 -8
- data/manual/text/formatted_callbacks.rb +33 -24
- data/manual/text/formatted_text.rb +36 -25
- data/manual/text/free_flowing_text.rb +22 -23
- data/manual/text/inline.rb +18 -19
- data/manual/text/kerning_and_character_spacing.rb +14 -15
- data/manual/text/leading.rb +7 -8
- data/manual/text/line_wrapping.rb +37 -18
- data/manual/text/paragraph_indentation.rb +12 -14
- data/manual/text/positioned_text.rb +15 -16
- data/manual/text/registering_families.rb +20 -21
- data/manual/text/rendering_and_color.rb +9 -10
- data/manual/text/right_to_left_text.rb +26 -19
- data/manual/text/rotation.rb +33 -23
- data/manual/text/single_usage.rb +8 -9
- data/manual/text/text.rb +57 -52
- data/manual/text/text_box_excess.rb +20 -17
- data/manual/text/text_box_extensions.rb +18 -15
- data/manual/text/text_box_overflow.rb +20 -19
- data/manual/text/utf8.rb +11 -12
- data/manual/text/win_ansi_charset.rb +27 -25
- data/prawn.gemspec +41 -34
- data/spec/extensions/encoding_helpers.rb +3 -3
- data/spec/prawn/document/bounding_box_spec.rb +550 -0
- data/spec/prawn/document/column_box_spec.rb +75 -0
- data/spec/prawn/document/security_spec.rb +176 -0
- data/spec/prawn/document_annotations_spec.rb +76 -0
- data/spec/prawn/document_destinations_spec.rb +15 -0
- data/spec/prawn/document_grid_spec.rb +99 -0
- data/spec/prawn/document_reference_spec.rb +27 -0
- data/spec/prawn/document_span_spec.rb +44 -0
- data/spec/prawn/document_spec.rb +805 -0
- data/spec/prawn/font_metric_cache_spec.rb +54 -0
- data/spec/prawn/font_spec.rb +544 -0
- data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
- data/spec/prawn/graphics/transparency_spec.rb +81 -0
- data/spec/prawn/graphics_spec.rb +872 -0
- data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
- data/spec/{image_handler_spec.rb → prawn/image_handler_spec.rb} +14 -14
- data/spec/prawn/images/jpg_spec.rb +20 -0
- data/spec/prawn/images/png_spec.rb +283 -0
- data/spec/prawn/images_spec.rb +229 -0
- data/spec/prawn/measurements_extensions_spec.rb +24 -0
- data/spec/prawn/outline_spec.rb +512 -0
- data/spec/prawn/repeater_spec.rb +166 -0
- data/spec/prawn/soft_mask_spec.rb +74 -0
- data/spec/prawn/stamp_spec.rb +173 -0
- data/spec/prawn/text/box_spec.rb +1110 -0
- data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
- data/spec/prawn/text/formatted/box_spec.rb +849 -0
- data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
- data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
- data/spec/prawn/text/formatted/parser_spec.rb +697 -0
- data/spec/prawn/text_draw_text_spec.rb +150 -0
- data/spec/prawn/text_rendering_mode_spec.rb +48 -0
- data/spec/prawn/text_spacing_spec.rb +95 -0
- data/spec/prawn/text_spec.rb +603 -0
- data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
- data/spec/{transformation_stack_spec.rb → prawn/transformation_stack_spec.rb} +22 -19
- data/spec/prawn/view_spec.rb +63 -0
- data/spec/prawn_manual_spec.rb +35 -0
- data/spec/spec_helper.rb +18 -19
- metadata +102 -222
- metadata.gz.sig +0 -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,5 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
# blend_mode.rb : Implements blend modes
|
4
4
|
#
|
5
5
|
# Contributed by John Ford. October, 2015
|
@@ -15,9 +15,10 @@ module Prawn
|
|
15
15
|
# Passing an array of blend modes is allowed. PDF viewers should
|
16
16
|
# blend layers based on the first recognized blend mode.
|
17
17
|
#
|
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
|
18
|
+
# Valid blend modes in v1.4 of the PDF spec include :Normal, :Multiply,
|
19
|
+
# :Screen, :Overlay, :Darken, :Lighten, :ColorDodge, :ColorBurn, :HardLight,
|
20
|
+
# :SoftLight, :Difference, :Exclusion, :Hue, :Saturation, :Color, and
|
21
|
+
# :Luminosity.
|
21
22
|
#
|
22
23
|
# Example:
|
23
24
|
# pdf.fill_color('0000ff')
|
@@ -52,11 +53,11 @@ module Prawn
|
|
52
53
|
dictionary_name = "BM#{key}"
|
53
54
|
|
54
55
|
dictionary = blend_mode_dictionary_registry[dictionary_name] ||= ref!(
|
55
|
-
:
|
56
|
-
:
|
56
|
+
Type: :ExtGState,
|
57
|
+
BM: blend_mode
|
57
58
|
)
|
58
59
|
|
59
|
-
page.ext_gstates
|
60
|
+
page.ext_gstates[dictionary_name] = dictionary
|
60
61
|
dictionary_name
|
61
62
|
end
|
62
63
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# cap_style.rb : Implements stroke cap styling
|
4
4
|
#
|
@@ -11,7 +11,7 @@ module Prawn
|
|
11
11
|
module CapStyle
|
12
12
|
# @group Stable API
|
13
13
|
|
14
|
-
CAP_STYLES = { :
|
14
|
+
CAP_STYLES = { butt: 0, round: 1, projecting_square: 2 }.freeze
|
15
15
|
|
16
16
|
# Sets the cap style for stroked lines and curves
|
17
17
|
#
|
@@ -27,7 +27,7 @@ module Prawn
|
|
27
27
|
write_stroke_cap_style
|
28
28
|
end
|
29
29
|
|
30
|
-
|
30
|
+
alias cap_style= cap_style
|
31
31
|
|
32
32
|
private
|
33
33
|
|
data/lib/prawn/graphics/color.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# color.rb : Implements color handling
|
4
4
|
#
|
@@ -27,11 +27,12 @@ module Prawn
|
|
27
27
|
#
|
28
28
|
def fill_color(*color)
|
29
29
|
return current_fill_color if color.empty?
|
30
|
+
|
30
31
|
self.current_fill_color = process_color(*color)
|
31
32
|
set_fill_color
|
32
33
|
end
|
33
34
|
|
34
|
-
|
35
|
+
alias fill_color= fill_color
|
35
36
|
|
36
37
|
# Sets or returns the line stroking color.
|
37
38
|
#
|
@@ -49,12 +50,13 @@ module Prawn
|
|
49
50
|
#
|
50
51
|
def stroke_color(*color)
|
51
52
|
return current_stroke_color if color.empty?
|
53
|
+
|
52
54
|
color = process_color(*color)
|
53
55
|
self.current_stroke_color = color
|
54
56
|
set_stroke_color(color)
|
55
57
|
end
|
56
58
|
|
57
|
-
|
59
|
+
alias stroke_color= stroke_color
|
58
60
|
|
59
61
|
module_function
|
60
62
|
|
@@ -65,7 +67,7 @@ module Prawn
|
|
65
67
|
# => "ff7808"
|
66
68
|
#
|
67
69
|
def rgb2hex(rgb)
|
68
|
-
rgb.map { |e|
|
70
|
+
rgb.map { |e| format '%<value>02x', value: e }.join
|
69
71
|
end
|
70
72
|
|
71
73
|
# Converts hex string into RGB value array:
|
@@ -74,27 +76,33 @@ module Prawn
|
|
74
76
|
# => [255, 120, 8]
|
75
77
|
#
|
76
78
|
def hex2rgb(hex)
|
77
|
-
r
|
79
|
+
r = hex[0..1]
|
80
|
+
g = hex[2..3]
|
81
|
+
b = hex[4..5]
|
78
82
|
[r, g, b].map { |e| e.to_i(16) }
|
79
83
|
end
|
80
84
|
|
81
85
|
private
|
82
86
|
|
83
87
|
def process_color(*color)
|
84
|
-
case
|
88
|
+
case color.size
|
85
89
|
when 1
|
86
90
|
color[0]
|
87
91
|
when 4
|
88
92
|
color
|
89
93
|
else
|
90
|
-
|
94
|
+
raise ArgumentError, 'wrong number of arguments supplied'
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
94
98
|
def color_type(color)
|
95
99
|
case color
|
96
100
|
when String
|
97
|
-
|
101
|
+
if /\A\h{6}\z/.match?(color)
|
102
|
+
:RGB
|
103
|
+
else
|
104
|
+
raise ArgumentError, "Unknown type of color: #{color.inspect}"
|
105
|
+
end
|
98
106
|
when Array
|
99
107
|
case color.length
|
100
108
|
when 3
|
@@ -102,7 +110,7 @@ module Prawn
|
|
102
110
|
when 4
|
103
111
|
:CMYK
|
104
112
|
else
|
105
|
-
|
113
|
+
raise ArgumentError, "Unknown type of color: #{color.inspect}"
|
106
114
|
end
|
107
115
|
end
|
108
116
|
end
|
@@ -119,7 +127,7 @@ module Prawn
|
|
119
127
|
end
|
120
128
|
|
121
129
|
def color_to_s(color)
|
122
|
-
normalize_color(color)
|
130
|
+
PDF::Core.real_params normalize_color(color)
|
123
131
|
end
|
124
132
|
|
125
133
|
def color_space(color)
|
@@ -131,38 +139,44 @@ module Prawn
|
|
131
139
|
end
|
132
140
|
end
|
133
141
|
|
134
|
-
COLOR_SPACES = [
|
142
|
+
COLOR_SPACES = %i[DeviceRGB DeviceCMYK Pattern].freeze
|
135
143
|
|
136
144
|
def set_color_space(type, color_space)
|
137
145
|
# don't set the same color space again
|
138
|
-
|
146
|
+
if current_color_space(type) == color_space &&
|
147
|
+
!state.page.in_stamp_stream?
|
148
|
+
return
|
149
|
+
end
|
150
|
+
|
139
151
|
set_current_color_space(color_space, type)
|
140
152
|
|
141
153
|
unless COLOR_SPACES.include?(color_space)
|
142
|
-
|
154
|
+
raise ArgumentError, "unknown color space: '#{color_space}'"
|
143
155
|
end
|
144
156
|
|
145
|
-
operator =
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
157
|
+
operator =
|
158
|
+
case type
|
159
|
+
when :fill
|
160
|
+
'cs'
|
161
|
+
when :stroke
|
162
|
+
'CS'
|
163
|
+
else
|
164
|
+
raise ArgumentError, "unknown type '#{type}'"
|
165
|
+
end
|
153
166
|
|
154
167
|
renderer.add_content "/#{color_space} #{operator}"
|
155
168
|
end
|
156
169
|
|
157
170
|
def set_color(type, color, options = {})
|
158
|
-
operator =
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
171
|
+
operator =
|
172
|
+
case type
|
173
|
+
when :fill
|
174
|
+
'scn'
|
175
|
+
when :stroke
|
176
|
+
'SCN'
|
177
|
+
else
|
178
|
+
raise ArgumentError, "unknown type '#{type}'"
|
179
|
+
end
|
166
180
|
|
167
181
|
if options[:pattern]
|
168
182
|
set_color_space type, :Pattern
|
@@ -187,8 +201,6 @@ module Prawn
|
|
187
201
|
set_stroke_color
|
188
202
|
end
|
189
203
|
|
190
|
-
private
|
191
|
-
|
192
204
|
def current_color_space(type)
|
193
205
|
graphic_state.color_space[type]
|
194
206
|
end
|
@@ -214,14 +226,6 @@ module Prawn
|
|
214
226
|
graphic_state.stroke_color = color
|
215
227
|
end
|
216
228
|
|
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
229
|
def write_color(color, operator)
|
226
230
|
renderer.add_content "#{color} #{operator}"
|
227
231
|
end
|
data/lib/prawn/graphics/dash.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# dash.rb : Implements stroke dashing
|
4
4
|
#
|
@@ -28,8 +28,9 @@ module Prawn
|
|
28
28
|
# 3 on, 2 off, 3 on, 2 off, ...
|
29
29
|
#
|
30
30
|
# * If the parameter +length+ is an array, it specifies the
|
31
|
-
# lengths of alternating dashes and gaps. The
|
32
|
-
#
|
31
|
+
# lengths of alternating dashes and gaps. The numbers must be
|
32
|
+
# non-negative and not all zero. The :space option is ignored
|
33
|
+
# in this case.
|
33
34
|
#
|
34
35
|
# Examples:
|
35
36
|
#
|
@@ -37,6 +38,8 @@ module Prawn
|
|
37
38
|
# 2 on, 1 off, 2 on, 1 off, ...
|
38
39
|
# length = [3, 1, 2, 3]
|
39
40
|
# 3 on, 1 off, 2 on, 3 off, 3 on, 1 off, ...
|
41
|
+
# length = [3, 0, 1]
|
42
|
+
# 3 on, 0 off, 1 on, 3 off, 0 on, 1 off, ...
|
40
43
|
#
|
41
44
|
# Options may contain the keys :space and :phase
|
42
45
|
#
|
@@ -55,19 +58,28 @@ module Prawn
|
|
55
58
|
def dash(length = nil, options = {})
|
56
59
|
return current_dash_state if length.nil?
|
57
60
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
+
length = Array(length)
|
62
|
+
|
63
|
+
if length.all?(&:zero?)
|
64
|
+
raise ArgumentError,
|
65
|
+
'Zero length dashes are invalid. Call #undash to disable dashes.'
|
66
|
+
elsif length.any?(&:negative?)
|
67
|
+
raise ArgumentError,
|
68
|
+
'Negative numbers are not allowed for dash lengths.'
|
61
69
|
end
|
62
70
|
|
63
|
-
|
64
|
-
|
65
|
-
|
71
|
+
length = length.first if length.length == 1
|
72
|
+
|
73
|
+
self.current_dash_state = {
|
74
|
+
dash: length,
|
75
|
+
space: length.is_a?(Array) ? nil : options[:space] || length,
|
76
|
+
phase: options[:phase] || 0
|
77
|
+
}
|
66
78
|
|
67
79
|
write_stroke_dash
|
68
80
|
end
|
69
81
|
|
70
|
-
|
82
|
+
alias dash= dash
|
71
83
|
|
72
84
|
# Stops dashing, restoring solid stroked lines and curves
|
73
85
|
#
|
@@ -89,7 +101,7 @@ module Prawn
|
|
89
101
|
end
|
90
102
|
|
91
103
|
def undashed_setting
|
92
|
-
{ :
|
104
|
+
{ dash: nil, space: nil, phase: 0 }
|
93
105
|
end
|
94
106
|
|
95
107
|
def current_dash_state=(dash_options)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# join_style.rb : Implements stroke join styling
|
4
4
|
#
|
@@ -9,7 +9,7 @@
|
|
9
9
|
module Prawn
|
10
10
|
module Graphics
|
11
11
|
module JoinStyle
|
12
|
-
JOIN_STYLES = { :
|
12
|
+
JOIN_STYLES = { miter: 0, round: 1, bevel: 2 }.freeze
|
13
13
|
|
14
14
|
# @group Stable API
|
15
15
|
|
@@ -25,10 +25,16 @@ module Prawn
|
|
25
25
|
|
26
26
|
self.current_join_style = style
|
27
27
|
|
28
|
+
unless JOIN_STYLES.key?(current_join_style)
|
29
|
+
raise Prawn::Errors::InvalidJoinStyle,
|
30
|
+
"#{style} is not a recognized join style. Valid styles are " +
|
31
|
+
JOIN_STYLES.keys.join(', ')
|
32
|
+
end
|
33
|
+
|
28
34
|
write_stroke_join_style
|
29
35
|
end
|
30
36
|
|
31
|
-
|
37
|
+
alias join_style= join_style
|
32
38
|
|
33
39
|
private
|
34
40
|
|
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest/sha1'
|
2
4
|
|
3
5
|
# patterns.rb : Implements axial & radial gradients
|
4
6
|
#
|
@@ -10,154 +12,254 @@
|
|
10
12
|
module Prawn
|
11
13
|
module Graphics
|
12
14
|
module Patterns
|
15
|
+
GradientStop = Struct.new(:position, :color)
|
16
|
+
Gradient = Struct.new(
|
17
|
+
:type, :apply_transformations, :stops, :from, :to, :r1, :r2
|
18
|
+
)
|
19
|
+
|
13
20
|
# @group Stable API
|
14
21
|
|
15
|
-
# Sets the fill gradient
|
16
|
-
# old arguments:
|
17
|
-
#
|
18
|
-
#
|
22
|
+
# Sets the fill gradient.
|
23
|
+
# old arguments:
|
24
|
+
# from, to, color1, color2
|
25
|
+
# or
|
26
|
+
# from, r1, to, r2, color1, color2
|
27
|
+
# new arguments:
|
28
|
+
# from: [x, y]
|
29
|
+
# to: [x, y]
|
30
|
+
# r1: radius
|
31
|
+
# r2: radius
|
32
|
+
# stops: [color, color, ...] or
|
33
|
+
# { position => color, position => color, ... }
|
34
|
+
# apply_transformations: true
|
35
|
+
#
|
36
|
+
# Examples:
|
37
|
+
#
|
38
|
+
# # draws a horizontal axial gradient that starts at red on the left
|
39
|
+
# # and ends at blue on the right
|
40
|
+
# fill_gradient from: [0, 0], to: [100, 0], stops: ['red', 'blue']
|
41
|
+
#
|
42
|
+
# # draws a horizontal radial gradient that starts at red, is green
|
43
|
+
# # 80% of the way through, and finishes blue
|
44
|
+
# fill_gradient from: [0, 0], r1: 0, to: [100, 0], r2: 180,
|
45
|
+
# stops: { 0 => 'red', 0.8 => 'green', 1 => 'blue' }
|
19
46
|
#
|
20
|
-
#
|
47
|
+
# <tt>from</tt> and <tt>to</tt> specify the axis of where the gradient
|
48
|
+
# should be painted.
|
49
|
+
#
|
50
|
+
# <tt>r1</tt> and <tt>r2</tt>, if specified, make a radial gradient with
|
51
|
+
# the starting circle of radius <tt>r1</tt> centered at <tt>from</tt>
|
52
|
+
# and ending at a circle of radius <tt>r2</tt> centered at <tt>to</tt>.
|
53
|
+
# If <tt>r1</tt> is not specified, a axial gradient will be drawn.
|
54
|
+
#
|
55
|
+
# <tt>stops</tt> is an array or hash of stops. Each stop is either just a
|
56
|
+
# string indicating the color, in which case the stops will be evenly
|
57
|
+
# distributed across the gradient, or a hash where the key is
|
58
|
+
# a position between 0 and 1 indicating what distance through the
|
59
|
+
# gradient the color should change, and the value is a color string.
|
60
|
+
#
|
61
|
+
# Option <tt>apply_transformations</tt>, if set true, will transform the
|
21
62
|
# 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
|
-
|
63
|
+
# space of the document. This option will be the default from Prawn v3,
|
64
|
+
# and is default true if you use the new arguments format.
|
65
|
+
# The default for the old arguments format, false, will mean if you
|
66
|
+
# (for example) scale your document by 2 and put a gradient inside, you
|
67
|
+
# will have to manually multiply your co-ordinates by 2 so the gradient
|
68
|
+
# is correctly positioned.
|
69
|
+
def fill_gradient(*args, **kwargs)
|
70
|
+
set_gradient(:fill, *args, **kwargs)
|
28
71
|
end
|
29
72
|
|
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)
|
73
|
+
# Sets the stroke gradient.
|
74
|
+
# See fill_gradient for a description of the arguments to this method.
|
75
|
+
def stroke_gradient(*args, **kwargs)
|
76
|
+
set_gradient(:stroke, *args, **kwargs)
|
43
77
|
end
|
44
78
|
|
45
79
|
private
|
46
80
|
|
47
|
-
def set_gradient(type, *grad)
|
48
|
-
|
81
|
+
def set_gradient(type, *grad, **kwargs)
|
82
|
+
gradient = parse_gradient_arguments(*grad, **kwargs)
|
49
83
|
|
50
84
|
patterns = page.resources[:Pattern] ||= {}
|
51
85
|
|
52
|
-
registry_key = gradient_registry_key
|
86
|
+
registry_key = gradient_registry_key gradient
|
53
87
|
|
54
|
-
|
55
|
-
shading =
|
56
|
-
|
57
|
-
|
58
|
-
shading = gradient(grad, opts)
|
88
|
+
unless patterns.key? "SP#{registry_key}"
|
89
|
+
shading = gradient_registry[registry_key]
|
90
|
+
unless shading
|
91
|
+
shading = create_gradient_pattern(gradient)
|
59
92
|
gradient_registry[registry_key] = shading
|
60
93
|
end
|
61
94
|
|
62
95
|
patterns["SP#{registry_key}"] = shading
|
63
96
|
end
|
64
97
|
|
65
|
-
operator =
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
98
|
+
operator =
|
99
|
+
case type
|
100
|
+
when :fill
|
101
|
+
'scn'
|
102
|
+
when :stroke
|
103
|
+
'SCN'
|
104
|
+
else
|
105
|
+
raise ArgumentError, "unknown type '#{type}'"
|
106
|
+
end
|
73
107
|
|
74
108
|
set_color_space type, :Pattern
|
75
109
|
renderer.add_content "/SP#{registry_key} #{operator}"
|
76
110
|
end
|
77
111
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
transformation,
|
84
|
-
x2, y2,
|
85
|
-
gradient[2], gradient[3]
|
86
|
-
]
|
87
|
-
else # radial
|
88
|
-
[
|
89
|
-
transformation,
|
90
|
-
x2, y2,
|
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
|
112
|
+
# rubocop: disable Metrics/ParameterLists
|
113
|
+
def parse_gradient_arguments(
|
114
|
+
*arguments, from: nil, to: nil, r1: nil, r2: nil, stops: nil,
|
115
|
+
apply_transformations: nil
|
116
|
+
)
|
101
117
|
|
102
|
-
|
103
|
-
|
104
|
-
|
118
|
+
case arguments.length
|
119
|
+
when 0
|
120
|
+
apply_transformations = true if apply_transformations.nil?
|
121
|
+
when 4
|
122
|
+
from, to, *stops = arguments
|
123
|
+
when 6
|
124
|
+
from, r1, to, r2, *stops = arguments
|
125
|
+
else
|
126
|
+
raise ArgumentError, "Unknown type of gradient: #{arguments.inspect}"
|
105
127
|
end
|
106
128
|
|
107
|
-
if
|
108
|
-
|
129
|
+
if stops.length < 2
|
130
|
+
raise ArgumentError, 'At least two stops must be specified'
|
109
131
|
end
|
110
132
|
|
111
|
-
|
112
|
-
|
133
|
+
stops =
|
134
|
+
stops.map.with_index do |stop, index|
|
135
|
+
case stop
|
136
|
+
when Array, Hash
|
137
|
+
position, color = stop
|
138
|
+
else
|
139
|
+
position = index / (stops.length.to_f - 1)
|
140
|
+
color = stop
|
141
|
+
end
|
113
142
|
|
114
|
-
|
115
|
-
|
143
|
+
unless (0..1).cover?(position)
|
144
|
+
raise ArgumentError, 'position must be between 0 and 1'
|
145
|
+
end
|
146
|
+
|
147
|
+
GradientStop.new(position, normalize_color(color))
|
148
|
+
end
|
149
|
+
|
150
|
+
if stops.first.position != 0
|
151
|
+
raise ArgumentError, 'The first stop must have a position of 0'
|
152
|
+
end
|
153
|
+
if stops.last.position != 1
|
154
|
+
raise ArgumentError, 'The last stop must have a position of 1'
|
116
155
|
end
|
117
156
|
|
118
|
-
|
119
|
-
|
157
|
+
if stops.map { |stop| color_type(stop.color) }.uniq.length > 1
|
158
|
+
raise ArgumentError, 'All colors must be of the same color space'
|
159
|
+
end
|
120
160
|
|
121
|
-
|
122
|
-
:
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
161
|
+
Gradient.new(
|
162
|
+
r1 ? :radial : :axial,
|
163
|
+
apply_transformations,
|
164
|
+
stops,
|
165
|
+
from,
|
166
|
+
to,
|
167
|
+
r1,
|
168
|
+
r2
|
127
169
|
)
|
170
|
+
end
|
171
|
+
# rubocop: enable Metrics/ParameterLists
|
128
172
|
|
129
|
-
|
173
|
+
def gradient_registry_key(gradient)
|
174
|
+
_x1, _y1, x2, y2, transformation = gradient_coordinates(gradient)
|
130
175
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
176
|
+
key = [
|
177
|
+
gradient.type.to_s,
|
178
|
+
transformation,
|
179
|
+
x2, y2,
|
180
|
+
gradient.r1 || -1, gradient.r2 || -1,
|
181
|
+
gradient.stops.length,
|
182
|
+
gradient.stops.map { |s| [s.position, s.color] }
|
183
|
+
].flatten
|
184
|
+
Digest::SHA1.hexdigest(key.join(','))
|
185
|
+
end
|
186
|
+
|
187
|
+
def gradient_registry
|
188
|
+
@gradient_registry ||= {}
|
189
|
+
end
|
190
|
+
|
191
|
+
def create_gradient_pattern(gradient)
|
192
|
+
if gradient.apply_transformations.nil? &&
|
193
|
+
current_transformation_matrix_with_translation(0, 0) !=
|
194
|
+
[1, 0, 0, 1, 0, 0]
|
195
|
+
warn 'Gradients in Prawn 2.x and lower are not correctly positioned '\
|
196
|
+
'when a transformation has been made to the document. ' \
|
197
|
+
"Pass 'apply_transformations: true' to correctly transform the " \
|
198
|
+
'gradient, or see ' \
|
199
|
+
'https://github.com/prawnpdf/prawn/wiki/Gradient-Transformations ' \
|
200
|
+
'for more information.'
|
135
201
|
end
|
136
202
|
|
203
|
+
shader_stops =
|
204
|
+
gradient.stops.each_cons(2).map do |first, second|
|
205
|
+
ref!(
|
206
|
+
FunctionType: 2,
|
207
|
+
Domain: [0.0, 1.0],
|
208
|
+
C0: first.color,
|
209
|
+
C1: second.color,
|
210
|
+
N: 1.0
|
211
|
+
)
|
212
|
+
end
|
213
|
+
|
214
|
+
# If there's only two stops, we can use the single shader.
|
215
|
+
# Otherwise we stitch the multiple shaders together.
|
216
|
+
shader =
|
217
|
+
if shader_stops.length == 1
|
218
|
+
shader_stops.first
|
219
|
+
else
|
220
|
+
ref!(
|
221
|
+
FunctionType: 3, # stitching function
|
222
|
+
Domain: [0.0, 1.0],
|
223
|
+
Functions: shader_stops,
|
224
|
+
Bounds: gradient.stops[1..-2].map(&:position),
|
225
|
+
Encode: [0.0, 1.0] * shader_stops.length
|
226
|
+
)
|
227
|
+
end
|
228
|
+
|
229
|
+
x1, y1, x2, y2, transformation = gradient_coordinates(gradient)
|
230
|
+
|
231
|
+
coords =
|
232
|
+
if gradient.type == :axial
|
233
|
+
[0, 0, x2 - x1, y2 - y1]
|
234
|
+
else
|
235
|
+
[0, 0, gradient.r1, x2 - x1, y2 - y1, gradient.r2]
|
236
|
+
end
|
237
|
+
|
137
238
|
shading = ref!(
|
138
|
-
:
|
139
|
-
:
|
140
|
-
:
|
141
|
-
:
|
142
|
-
:
|
239
|
+
ShadingType: gradient.type == :axial ? 2 : 3,
|
240
|
+
ColorSpace: color_space(gradient.stops.first.color),
|
241
|
+
Coords: coords,
|
242
|
+
Function: shader,
|
243
|
+
Extend: [true, true]
|
143
244
|
)
|
144
245
|
|
145
246
|
ref!(
|
146
|
-
:
|
147
|
-
:
|
148
|
-
:
|
247
|
+
PatternType: 2, # shading pattern
|
248
|
+
Shading: shading,
|
249
|
+
Matrix: transformation
|
149
250
|
)
|
150
251
|
end
|
151
252
|
|
152
|
-
def gradient_coordinates(
|
153
|
-
x1, y1 = map_to_absolute(
|
154
|
-
x2, y2 = map_to_absolute(
|
253
|
+
def gradient_coordinates(gradient)
|
254
|
+
x1, y1 = map_to_absolute(gradient.from)
|
255
|
+
x2, y2 = map_to_absolute(gradient.to)
|
155
256
|
|
156
|
-
transformation =
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
257
|
+
transformation =
|
258
|
+
if gradient.apply_transformations
|
259
|
+
current_transformation_matrix_with_translation(x1, y1)
|
260
|
+
else
|
261
|
+
[1, 0, 0, 1, x1, y1]
|
262
|
+
end
|
161
263
|
|
162
264
|
[x1, y1, x2, y2, transformation]
|
163
265
|
end
|