prawn 2.0.2 → 2.3.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 +20 -23
- data/lib/prawn.rb +37 -49
- data/lib/prawn/document.rb +181 -133
- data/lib/prawn/document/bounding_box.rb +41 -29
- data/lib/prawn/document/column_box.rb +7 -7
- data/lib/prawn/document/internals.rb +18 -8
- data/lib/prawn/document/span.rb +21 -16
- data/lib/prawn/encoding.rb +69 -68
- data/lib/prawn/errors.rb +12 -7
- data/lib/prawn/font.rb +115 -69
- data/lib/prawn/font_metric_cache.rb +14 -8
- data/lib/prawn/{font → fonts}/afm.rb +102 -68
- 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 +87 -68
- data/lib/prawn/graphics.rb +120 -80
- data/lib/prawn/graphics/blend_mode.rb +65 -0
- data/lib/prawn/graphics/cap_style.rb +3 -3
- data/lib/prawn/graphics/color.rb +27 -25
- data/lib/prawn/graphics/dash.rb +23 -11
- data/lib/prawn/graphics/join_style.rb +9 -3
- data/lib/prawn/graphics/patterns.rb +197 -67
- data/lib/prawn/graphics/transformation.rb +17 -8
- data/lib/prawn/graphics/transparency.rb +17 -13
- data/lib/prawn/grid.rb +48 -47
- data/lib/prawn/image_handler.rb +5 -5
- data/lib/prawn/images.rb +39 -30
- data/lib/prawn/images/image.rb +2 -1
- data/lib/prawn/images/jpg.rb +28 -22
- data/lib/prawn/images/png.rb +107 -66
- data/lib/prawn/measurement_extensions.rb +10 -9
- data/lib/prawn/measurements.rb +19 -15
- data/lib/prawn/outline.rb +97 -77
- data/lib/prawn/repeater.rb +14 -10
- data/lib/prawn/security.rb +81 -61
- 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 +68 -52
- data/lib/prawn/text/box.rb +11 -8
- data/lib/prawn/text/formatted.rb +5 -5
- data/lib/prawn/text/formatted/arranger.rb +78 -49
- data/lib/prawn/text/formatted/box.rb +134 -100
- data/lib/prawn/text/formatted/fragment.rb +11 -14
- data/lib/prawn/text/formatted/line_wrap.rb +121 -63
- data/lib/prawn/text/formatted/parser.rb +139 -117
- data/lib/prawn/text/formatted/wrap.rb +43 -31
- data/lib/prawn/transformation_stack.rb +44 -0
- 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 +6 -7
- 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 +4 -5
- data/manual/bounding_box/creation.rb +6 -7
- data/manual/bounding_box/indentation.rb +14 -15
- data/manual/bounding_box/nesting.rb +24 -17
- 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 +11 -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 +17 -15
- data/manual/example_helper.rb +5 -4
- data/manual/graphics/blend_mode.rb +52 -0
- 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 +4 -5
- data/manual/graphics/fill_rules.rb +9 -10
- data/manual/graphics/gradients.rb +27 -21
- data/manual/graphics/graphics.rb +48 -39
- data/manual/graphics/helper.rb +12 -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 +4 -5
- data/manual/graphics/stroke_cap.rb +6 -7
- data/manual/graphics/stroke_dash.rb +11 -12
- data/manual/graphics/stroke_join.rb +5 -6
- data/manual/graphics/translate.rb +9 -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 +9 -10
- 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 +13 -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 +19 -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 +7 -8
- data/manual/text/formatted_callbacks.rb +25 -21
- data/manual/text/formatted_text.rb +33 -25
- data/manual/text/free_flowing_text.rb +20 -21
- 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 +13 -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 +28 -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 +18 -19
- data/manual/text/utf8.rb +11 -12
- data/manual/text/win_ansi_charset.rb +21 -19
- data/prawn.gemspec +45 -33
- data/spec/extensions/encoding_helpers.rb +3 -3
- data/spec/prawn/document/bounding_box_spec.rb +546 -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 +36 -0
- data/spec/prawn/document_spec.rb +802 -0
- data/spec/prawn/font_metric_cache_spec.rb +54 -0
- data/spec/prawn/font_spec.rb +542 -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 +837 -0
- data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
- data/spec/prawn/image_handler_spec.rb +53 -0
- data/spec/prawn/images/jpg_spec.rb +20 -0
- data/spec/prawn/images/png_spec.rb +283 -0
- data/spec/prawn/images_spec.rb +224 -0
- data/spec/prawn/measurements_extensions_spec.rb +24 -0
- data/spec/prawn/outline_spec.rb +412 -0
- data/spec/prawn/repeater_spec.rb +165 -0
- data/spec/prawn/soft_mask_spec.rb +74 -0
- data/spec/prawn/stamp_spec.rb +172 -0
- data/spec/prawn/text/box_spec.rb +1112 -0
- data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
- data/spec/prawn/text/formatted/box_spec.rb +846 -0
- data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
- data/spec/prawn/text/formatted/line_wrap_spec.rb +494 -0
- data/spec/prawn/text/formatted/parser_spec.rb +697 -0
- data/spec/prawn/text_draw_text_spec.rb +149 -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/prawn/transformation_stack_spec.rb +66 -0
- data/spec/prawn/view_spec.rb +63 -0
- data/spec/prawn_manual_spec.rb +35 -0
- data/spec/spec_helper.rb +19 -23
- metadata +145 -185
- metadata.gz.sig +4 -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/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/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/pal_bk.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.rb +0 -24
- data/spec/annotations_spec.rb +0 -67
- 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 -742
- data/spec/extensions/mocha.rb +0 -45
- data/spec/font_metric_cache_spec.rb +0 -52
- data/spec/font_spec.rb +0 -475
- data/spec/formatted_text_arranger_spec.rb +0 -423
- data/spec/formatted_text_box_spec.rb +0 -716
- data/spec/formatted_text_fragment_spec.rb +0 -299
- data/spec/graphics_spec.rb +0 -666
- data/spec/grid_spec.rb +0 -95
- data/spec/image_handler_spec.rb +0 -53
- 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 -235
- 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 -1038
- data/spec/text_rendering_mode_spec.rb +0 -45
- data/spec/text_spacing_spec.rb +0 -93
- data/spec/text_spec.rb +0 -549
- data/spec/text_with_inline_formatting_spec.rb +0 -35
- data/spec/transparency_spec.rb +0 -91
- data/spec/view_spec.rb +0 -42
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# blend_mode.rb : Implements blend modes
|
4
|
+
#
|
5
|
+
# Contributed by John Ford. October, 2015
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Prawn
|
11
|
+
module Graphics
|
12
|
+
# The Prawn::BlendMode module is used to change the way
|
13
|
+
# two layers are blended together.
|
14
|
+
#
|
15
|
+
# Passing an array of blend modes is allowed. PDF viewers should
|
16
|
+
# blend layers based on the first recognized blend mode.
|
17
|
+
#
|
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.
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
# pdf.fill_color('0000ff')
|
25
|
+
# pdf.fill_rectangle([x, y+25], 50, 50)
|
26
|
+
# pdf.blend_mode(:Multiply) do
|
27
|
+
# pdf.fill_color('ff0000')
|
28
|
+
# pdf.fill_circle([x, y], 25)
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
module BlendMode
|
32
|
+
# @group Stable API
|
33
|
+
|
34
|
+
def blend_mode(blend_mode = :Normal)
|
35
|
+
renderer.min_version(1.4)
|
36
|
+
|
37
|
+
save_graphics_state if block_given?
|
38
|
+
renderer.add_content "/#{blend_mode_dictionary_name(blend_mode)} gs"
|
39
|
+
if block_given?
|
40
|
+
yield
|
41
|
+
restore_graphics_state
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def blend_mode_dictionary_registry
|
48
|
+
@blend_mode_dictionary_registry ||= {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def blend_mode_dictionary_name(blend_mode)
|
52
|
+
key = Array(blend_mode).join('')
|
53
|
+
dictionary_name = "BM#{key}"
|
54
|
+
|
55
|
+
dictionary = blend_mode_dictionary_registry[dictionary_name] ||= ref!(
|
56
|
+
Type: :ExtGState,
|
57
|
+
BM: blend_mode
|
58
|
+
)
|
59
|
+
|
60
|
+
page.ext_gstates[dictionary_name] = dictionary
|
61
|
+
dictionary_name
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
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,15 +139,19 @@ 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
157
|
operator = case type
|
@@ -148,7 +160,7 @@ module Prawn
|
|
148
160
|
when :stroke
|
149
161
|
'CS'
|
150
162
|
else
|
151
|
-
|
163
|
+
raise ArgumentError, "unknown type '#{type}'"
|
152
164
|
end
|
153
165
|
|
154
166
|
renderer.add_content "/#{color_space} #{operator}"
|
@@ -161,7 +173,7 @@ module Prawn
|
|
161
173
|
when :stroke
|
162
174
|
'SCN'
|
163
175
|
else
|
164
|
-
|
176
|
+
raise ArgumentError, "unknown type '#{type}'"
|
165
177
|
end
|
166
178
|
|
167
179
|
if options[:pattern]
|
@@ -187,8 +199,6 @@ module Prawn
|
|
187
199
|
set_stroke_color
|
188
200
|
end
|
189
201
|
|
190
|
-
private
|
191
|
-
|
192
202
|
def current_color_space(type)
|
193
203
|
graphic_state.color_space[type]
|
194
204
|
end
|
@@ -214,14 +224,6 @@ module Prawn
|
|
214
224
|
graphic_state.stroke_color = color
|
215
225
|
end
|
216
226
|
|
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
227
|
def write_color(color, operator)
|
226
228
|
renderer.add_content "#{color} #{operator}"
|
227
229
|
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,36 +12,83 @@
|
|
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
|
-
#
|
19
|
-
|
20
|
-
|
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' }
|
46
|
+
#
|
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
|
62
|
+
# gradient's co-ordinate space so it matches the current co-ordinate
|
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)
|
21
71
|
end
|
22
72
|
|
23
|
-
# Sets the stroke gradient
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
def stroke_gradient(*args)
|
28
|
-
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)
|
29
77
|
end
|
30
78
|
|
31
79
|
private
|
32
80
|
|
33
|
-
def set_gradient(type, *grad)
|
81
|
+
def set_gradient(type, *grad, **kwargs)
|
82
|
+
gradient = parse_gradient_arguments(*grad, **kwargs)
|
83
|
+
|
34
84
|
patterns = page.resources[:Pattern] ||= {}
|
35
85
|
|
36
|
-
registry_key = gradient_registry_key
|
86
|
+
registry_key = gradient_registry_key gradient
|
37
87
|
|
38
|
-
|
39
|
-
shading =
|
40
|
-
|
41
|
-
|
42
|
-
shading = gradient(*grad)
|
88
|
+
unless patterns.key? "SP#{registry_key}"
|
89
|
+
shading = gradient_registry[registry_key]
|
90
|
+
unless shading
|
91
|
+
shading = create_gradient_pattern(gradient)
|
43
92
|
gradient_registry[registry_key] = shading
|
44
93
|
end
|
45
94
|
|
@@ -52,79 +101,160 @@ module Prawn
|
|
52
101
|
when :stroke
|
53
102
|
'SCN'
|
54
103
|
else
|
55
|
-
|
104
|
+
raise ArgumentError, "unknown type '#{type}'"
|
56
105
|
end
|
57
106
|
|
58
107
|
set_color_space type, :Pattern
|
59
108
|
renderer.add_content "/SP#{registry_key} #{operator}"
|
60
109
|
end
|
61
110
|
|
111
|
+
# rubocop: disable Metrics/ParameterLists
|
112
|
+
def parse_gradient_arguments(
|
113
|
+
*arguments, from: nil, to: nil, r1: nil, r2: nil, stops: nil,
|
114
|
+
apply_transformations: nil
|
115
|
+
)
|
116
|
+
case arguments.length
|
117
|
+
when 0
|
118
|
+
apply_transformations = true if apply_transformations.nil?
|
119
|
+
when 4
|
120
|
+
from, to, *stops = arguments
|
121
|
+
when 6
|
122
|
+
from, r1, to, r2, *stops = arguments
|
123
|
+
else
|
124
|
+
raise ArgumentError, "Unknown type of gradient: #{arguments.inspect}"
|
125
|
+
end
|
126
|
+
|
127
|
+
if stops.length < 2
|
128
|
+
raise ArgumentError, 'At least two stops must be specified'
|
129
|
+
end
|
130
|
+
|
131
|
+
stops = stops.map.with_index do |stop, index|
|
132
|
+
case stop
|
133
|
+
when Array, Hash
|
134
|
+
position, color = stop
|
135
|
+
else
|
136
|
+
position = index / (stops.length.to_f - 1)
|
137
|
+
color = stop
|
138
|
+
end
|
139
|
+
|
140
|
+
unless (0..1).cover?(position)
|
141
|
+
raise ArgumentError, 'position must be between 0 and 1'
|
142
|
+
end
|
143
|
+
|
144
|
+
GradientStop.new(position, normalize_color(color))
|
145
|
+
end
|
146
|
+
|
147
|
+
if stops.first.position != 0
|
148
|
+
raise ArgumentError, 'The first stop must have a position of 0'
|
149
|
+
end
|
150
|
+
if stops.last.position != 1
|
151
|
+
raise ArgumentError, 'The last stop must have a position of 1'
|
152
|
+
end
|
153
|
+
|
154
|
+
if stops.map { |stop| color_type(stop.color) }.uniq.length > 1
|
155
|
+
raise ArgumentError, 'All colors must be of the same color space'
|
156
|
+
end
|
157
|
+
|
158
|
+
Gradient.new(
|
159
|
+
r1 ? :radial : :axial,
|
160
|
+
apply_transformations,
|
161
|
+
stops,
|
162
|
+
from, to,
|
163
|
+
r1, r2
|
164
|
+
)
|
165
|
+
end
|
166
|
+
# rubocop: enable Metrics/ParameterLists
|
167
|
+
|
62
168
|
def gradient_registry_key(gradient)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
gradient[3],
|
75
|
-
gradient[4], gradient[5]
|
76
|
-
]
|
77
|
-
end.hash
|
169
|
+
_x1, _y1, x2, y2, transformation = gradient_coordinates(gradient)
|
170
|
+
|
171
|
+
key = [
|
172
|
+
gradient.type.to_s,
|
173
|
+
transformation,
|
174
|
+
x2, y2,
|
175
|
+
gradient.r1 || -1, gradient.r2 || -1,
|
176
|
+
gradient.stops.length,
|
177
|
+
gradient.stops.map { |s| [s.position, s.color] }
|
178
|
+
].flatten
|
179
|
+
Digest::SHA1.hexdigest(key.join(','))
|
78
180
|
end
|
79
181
|
|
80
182
|
def gradient_registry
|
81
183
|
@gradient_registry ||= {}
|
82
184
|
end
|
83
185
|
|
84
|
-
def gradient
|
85
|
-
if
|
86
|
-
|
186
|
+
def create_gradient_pattern(gradient)
|
187
|
+
if gradient.apply_transformations.nil? &&
|
188
|
+
current_transformation_matrix_with_translation(0, 0) !=
|
189
|
+
[1, 0, 0, 1, 0, 0]
|
190
|
+
warn 'Gradients in Prawn 2.x and lower are not correctly positioned '\
|
191
|
+
'when a transformation has been made to the document. ' \
|
192
|
+
"Pass 'apply_transformations: true' to correctly transform the " \
|
193
|
+
'gradient, or see ' \
|
194
|
+
'https://github.com/prawnpdf/prawn/wiki/Gradient-Transformations ' \
|
195
|
+
'for more information.'
|
87
196
|
end
|
88
197
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
198
|
+
shader_stops = gradient.stops.each_cons(2).map do |first, second|
|
199
|
+
ref!(
|
200
|
+
FunctionType: 2,
|
201
|
+
Domain: [0.0, 1.0],
|
202
|
+
C0: first.color,
|
203
|
+
C1: second.color,
|
204
|
+
N: 1.0
|
205
|
+
)
|
94
206
|
end
|
95
207
|
|
96
|
-
|
97
|
-
|
208
|
+
# If there's only two stops, we can use the single shader.
|
209
|
+
# Otherwise we stitch the multiple shaders together.
|
210
|
+
shader = if shader_stops.length == 1
|
211
|
+
shader_stops.first
|
212
|
+
else
|
213
|
+
ref!(
|
214
|
+
FunctionType: 3, # stitching function
|
215
|
+
Domain: [0.0, 1.0],
|
216
|
+
Functions: shader_stops,
|
217
|
+
Bounds: gradient.stops[1..-2].map(&:position),
|
218
|
+
Encode: [0.0, 1.0] * shader_stops.length
|
219
|
+
)
|
220
|
+
end
|
98
221
|
|
99
|
-
|
100
|
-
:FunctionType => 2,
|
101
|
-
:Domain => [0.0, 1.0],
|
102
|
-
:C0 => color1,
|
103
|
-
:C1 => color2,
|
104
|
-
:N => 1.0
|
105
|
-
)
|
222
|
+
x1, y1, x2, y2, transformation = gradient_coordinates(gradient)
|
106
223
|
|
107
|
-
if
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
224
|
+
coords = if gradient.type == :axial
|
225
|
+
[0, 0, x2 - x1, y2 - y1]
|
226
|
+
else
|
227
|
+
[0, 0, gradient.r1, x2 - x1, y2 - y1, gradient.r2]
|
228
|
+
end
|
112
229
|
|
113
230
|
shading = ref!(
|
114
|
-
:
|
115
|
-
:
|
116
|
-
:
|
117
|
-
:
|
118
|
-
:
|
231
|
+
ShadingType: gradient.type == :axial ? 2 : 3,
|
232
|
+
ColorSpace: color_space(gradient.stops.first.color),
|
233
|
+
Coords: coords,
|
234
|
+
Function: shader,
|
235
|
+
Extend: [true, true]
|
119
236
|
)
|
120
237
|
|
121
238
|
ref!(
|
122
|
-
:
|
123
|
-
:
|
124
|
-
:
|
125
|
-
0, 1] + map_to_absolute(args[0])
|
239
|
+
PatternType: 2, # shading pattern
|
240
|
+
Shading: shading,
|
241
|
+
Matrix: transformation
|
126
242
|
)
|
127
243
|
end
|
244
|
+
|
245
|
+
def gradient_coordinates(gradient)
|
246
|
+
x1, y1 = map_to_absolute(gradient.from)
|
247
|
+
x2, y2 = map_to_absolute(gradient.to)
|
248
|
+
|
249
|
+
transformation =
|
250
|
+
if gradient.apply_transformations
|
251
|
+
current_transformation_matrix_with_translation(x1, y1)
|
252
|
+
else
|
253
|
+
[1, 0, 0, 1, x1, y1]
|
254
|
+
end
|
255
|
+
|
256
|
+
[x1, y1, x2, y2, transformation]
|
257
|
+
end
|
128
258
|
end
|
129
259
|
end
|
130
260
|
end
|