prawn-svg 0.36.0 → 0.36.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b833a9af0fae6fd2934c6b5ef37bd6d6d90aba36fa9a161520ac6a9a1c19f9db
4
- data.tar.gz: 550aa711e413cac65e8af39f029096e3606f84a852b982729ca0252e758805ac
3
+ metadata.gz: 6e2b791daa33f85948c08bdafec3f1a3ab8dffa8b07dd50ce7bb7a55320d663b
4
+ data.tar.gz: 78e45c7790de4b1cf2d328ad6ec8bbb77bab707cdeb8e75fcf52055410f36fc4
5
5
  SHA512:
6
- metadata.gz: 9a522f7b4aa8f713fc453cc3d6061968fce1a28ab60e58f6c321b92979bcb909748a81b8c9cb9a373f918d152e969ea7d0974afd975c8fba7ae70c03cec18a25
7
- data.tar.gz: 537a912b7daab1581662cabfc5de5776ebe771d15e448e99a7c7d6125eb29644bbc40de6508429f5a3451f16ebb226f53402320ef4430118b16d05913cd3ede4
6
+ metadata.gz: da875e08d850fd7d3b74d9e5a629d4f3125bc933614e0d241ddd4c5122ad75495d6b530c01914ad0bc44dbcbdec41ee5e35196e008c484652bbb99ecb0e66e53
7
+ data.tar.gz: 79f54a51c1acdea4a5d5de5bb72f130b5ca692aed48c72ceb36aced4f16df223be1a81f1152164dbdf3452571b79a676df96a4c38ba825afeedd32748e4f3919
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prawn-svg (0.36.0)
4
+ prawn-svg (0.36.2)
5
5
  css_parser (~> 1.6)
6
6
  matrix (~> 0.4.2)
7
7
  prawn (>= 0.11.1, < 3)
@@ -18,18 +18,9 @@ class Prawn::SVG::Document
18
18
 
19
19
  def initialize(data, bounds, options, font_registry: nil, css_parser: CssParser::Parser.new, attribute_overrides: {})
20
20
  begin
21
- @root = REXML::Document.new(data).root
22
- rescue REXML::ParseException
23
- @root = nil
24
- end
25
-
26
- if @root.nil?
27
- if data.respond_to?(:end_with?) && data.end_with?('.svg')
28
- raise InvalidSVGData,
29
- "The data supplied is not a valid SVG document. It looks like you've supplied a filename instead; use IO.read(filename) to get the data before you pass it to prawn-svg."
30
- else
31
- raise InvalidSVGData, 'The data supplied is not a valid SVG document.'
32
- end
21
+ @root = REXML::Document.new(data).root or raise_parse_error(data)
22
+ rescue REXML::ParseException => e
23
+ raise_parse_error(data, e.message)
33
24
  end
34
25
 
35
26
  @warnings = []
@@ -73,4 +64,16 @@ class Prawn::SVG::Document
73
64
  raise ArgumentError, ':color_mode must be set to :rgb (default) or :cmyk'
74
65
  end
75
66
  end
67
+
68
+ def raise_parse_error(data, exception_message = nil)
69
+ message = 'The data supplied is not a valid SVG document.'
70
+
71
+ if data.respond_to?(:end_with?) && data.end_with?('.svg')
72
+ message += " It looks like you've supplied a filename instead; use File.read(filename) to get the data from the file before you pass it to prawn-svg."
73
+ end
74
+
75
+ message += "\n#{exception_message}" if exception_message
76
+
77
+ raise InvalidSVGData, message
78
+ end
76
79
  end
@@ -262,6 +262,14 @@ class Prawn::SVG::Elements::Base
262
262
  ['hidden', 'scroll'].include?(computed_properties.overflow)
263
263
  end
264
264
 
265
+ def stroke_width
266
+ if computed_properties.stroke.none?
267
+ 0
268
+ else
269
+ pixels(properties.stroke_width) || 1.0
270
+ end
271
+ end
272
+
265
273
  def clone_element_source(source)
266
274
  new_source = source.dup
267
275
  document.element_styles[new_source] = document.element_styles[source]
@@ -28,6 +28,9 @@ class Prawn::SVG::Elements::Gradient < Prawn::SVG::Elements::Base
28
28
  def gradient_arguments(element)
29
29
  bbox = element.bounding_box
30
30
 
31
+ stroke_width = element.stroke_width
32
+ bbox_with_stroke = bbox&.zip([-stroke_width, stroke_width, stroke_width, -stroke_width])&.map(&:sum)
33
+
31
34
  if type == :radial
32
35
  {
33
36
  from: [fx, fy],
@@ -35,18 +38,18 @@ class Prawn::SVG::Elements::Gradient < Prawn::SVG::Elements::Base
35
38
  to: [cx, cy],
36
39
  r2: r,
37
40
  stops: stops,
38
- matrix: matrix_for_bounding_box(*bbox),
41
+ matrix: matrix_for_bounding_box(bbox),
39
42
  wrap: wrap,
40
- bounding_box: bbox
43
+ bounding_box: bbox_with_stroke
41
44
  }
42
45
  else
43
46
  {
44
47
  from: [x1, y1],
45
48
  to: [x2, y2],
46
49
  stops: stops,
47
- matrix: matrix_for_bounding_box(*bbox),
50
+ matrix: matrix_for_bounding_box(bbox),
48
51
  wrap: wrap,
49
- bounding_box: bbox
52
+ bounding_box: bbox_with_stroke
50
53
  }
51
54
  end
52
55
  end
@@ -57,8 +60,10 @@ class Prawn::SVG::Elements::Gradient < Prawn::SVG::Elements::Base
57
60
 
58
61
  private
59
62
 
60
- def matrix_for_bounding_box(bounding_x1, bounding_y1, bounding_x2, bounding_y2)
61
- if units == :bounding_box
63
+ def matrix_for_bounding_box(bbox)
64
+ if bbox && units == :bounding_box
65
+ bounding_x1, bounding_y1, bounding_x2, bounding_y2 = *bbox
66
+
62
67
  width = bounding_x2 - bounding_x1
63
68
  height = bounding_y1 - bounding_y2
64
69
 
@@ -79,10 +79,21 @@ class Prawn::SVG::GradientRenderer
79
79
 
80
80
  repeat_count, repeat_offset, transform = compute_wrapping(wrap, from, to, current_pdf_translation)
81
81
 
82
+ x0, y0, x1, y1 = bounding_box || prawn_bounding_box
83
+
84
+ offset_x, offset_y = prawn.bounds.anchor
85
+ x0 += offset_x
86
+ y0 += offset_y
87
+ x1 += offset_x
88
+ y1 += offset_y
89
+
90
+ width = x1 - x0
91
+ height = y0 - y1
92
+
82
93
  transparency_group = prawn.ref!(
83
94
  Type: :XObject,
84
95
  Subtype: :Form,
85
- BBox: prawn.state.page.dimensions,
96
+ BBox: [x0, y1, x1, y0],
86
97
  Group: {
87
98
  Type: :Group,
88
99
  S: :Transparency,
@@ -108,7 +119,7 @@ class Prawn::SVG::GradientRenderer
108
119
  )
109
120
 
110
121
  transparency_group.stream << begin
111
- box = PDF::Core.real_params(prawn.state.page.dimensions)
122
+ box = PDF::Core.real_params([x0, y1, width, height])
112
123
 
113
124
  <<~CMDS.strip
114
125
  /Pattern cs
@@ -1,5 +1,5 @@
1
1
  module Prawn
2
2
  module SVG
3
- VERSION = '0.36.0'.freeze
3
+ VERSION = '0.36.2'.freeze
4
4
  end
5
5
  end
data/lib/prawn-svg.rb CHANGED
@@ -10,7 +10,7 @@ require 'prawn/svg/calculators/arc_to_bezier_curve'
10
10
  require 'prawn/svg/calculators/aspect_ratio'
11
11
  require 'prawn/svg/calculators/document_sizing'
12
12
  require 'prawn/svg/calculators/pixels'
13
- require 'prawn/svg/transform_utils'
13
+ require 'prawn/svg/pdfmatrix'
14
14
  require 'prawn/svg/transform_parser'
15
15
  require 'prawn/svg/url_loader'
16
16
  require 'prawn/svg/loaders/data'
@@ -25,10 +25,22 @@ describe Prawn::SVG::Document do
25
25
  context 'when unparsable XML is provided' do
26
26
  let(:svg) { "this isn't SVG data" }
27
27
 
28
- it 'raises an exception' do
28
+ it "raises an exception, passing on REXML's error message" do
29
29
  expect do
30
30
  Prawn::SVG::Document.new(svg, bounds, options)
31
- end.to raise_error Prawn::SVG::Document::InvalidSVGData, 'The data supplied is not a valid SVG document.'
31
+ end.to raise_error Prawn::SVG::Document::InvalidSVGData,
32
+ /\AThe data supplied is not a valid SVG document.+Malformed.+#{Regexp.escape(svg)}/m
33
+ end
34
+ end
35
+
36
+ context 'when broken XML is provided' do
37
+ let(:svg) { '<svg><g><rect></rect></svg>' }
38
+
39
+ it "raises an exception, passing on REXML's error message" do
40
+ expect do
41
+ Prawn::SVG::Document.new(svg, bounds, options)
42
+ end.to raise_error Prawn::SVG::Document::InvalidSVGData,
43
+ /\AThe data supplied is not a valid SVG document.+Missing end tag for 'g'/m
32
44
  end
33
45
  end
34
46
 
@@ -36,10 +48,12 @@ describe Prawn::SVG::Document do
36
48
  let(:svg) { 'some_file.svg' }
37
49
 
38
50
  it "raises an exception letting them know what they've done" do
51
+ message = "The data supplied is not a valid SVG document. It looks like you've supplied a filename " \
52
+ 'instead; use File.read(filename) to get the data from the file before you pass it to prawn-svg.'
53
+
39
54
  expect do
40
55
  Prawn::SVG::Document.new(svg, bounds, options)
41
- end.to raise_error Prawn::SVG::Document::InvalidSVGData,
42
- "The data supplied is not a valid SVG document. It looks like you've supplied a filename instead; use IO.read(filename) to get the data before you pass it to prawn-svg."
56
+ end.to raise_error Prawn::SVG::Document::InvalidSVGData, /\A#{Regexp.escape(message)}/
43
57
  end
44
58
  end
45
59
  end
@@ -24,8 +24,26 @@ describe Prawn::SVG::Elements::Gradient do
24
24
  expect(document.gradients['flag']).to eq element
25
25
  end
26
26
 
27
+ it 'returns correct gradient arguments for an element with no bounding box' do
28
+ arguments = element.gradient_arguments(double(bounding_box: nil, stroke_width: 0))
29
+ expect(arguments).to eq(
30
+ from: [0.0, 0.0],
31
+ to: [0.2, 1.0],
32
+ wrap: :pad,
33
+ matrix: Matrix[[1.0, 0.0, 0.0], [0.0, -1.0, 600.0], [0.0, 0.0, 1.0]],
34
+ bounding_box: nil,
35
+ stops: [
36
+ { offset: 0, color: 'ff0000', opacity: 1.0 },
37
+ { offset: 0.25, color: 'ff0000', opacity: 1.0 },
38
+ { offset: 0.5, color: 'ffffff', opacity: 1.0 },
39
+ { offset: 0.75, color: '0000ff', opacity: 1.0 },
40
+ { offset: 1, color: '0000ff', opacity: 1.0 }
41
+ ]
42
+ )
43
+ end
44
+
27
45
  it 'returns correct gradient arguments for an element' do
28
- arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0]))
46
+ arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0], stroke_width: 0))
29
47
  expect(arguments).to eq(
30
48
  from: [0.0, 0.0],
31
49
  to: [0.2, 1.0],
@@ -59,7 +77,7 @@ describe Prawn::SVG::Elements::Gradient do
59
77
  end
60
78
 
61
79
  it 'returns correct gradient arguments for an element' do
62
- arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0]))
80
+ arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0], stroke_width: 0))
63
81
  expect(arguments).to eq(
64
82
  from: [0.5, 0.2],
65
83
  to: [0.0, 0.2],
@@ -90,7 +108,7 @@ describe Prawn::SVG::Elements::Gradient do
90
108
  end
91
109
 
92
110
  it 'returns correct gradient arguments for an element' do
93
- arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0]))
111
+ arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0], stroke_width: 0))
94
112
  expect(arguments).to eq(
95
113
  from: [100.0, 500.0],
96
114
  to: [200.0, 600.0],
@@ -113,7 +131,7 @@ describe Prawn::SVG::Elements::Gradient do
113
131
  end
114
132
 
115
133
  it 'returns correct gradient arguments for an element' do
116
- arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0]))
134
+ arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0], stroke_width: 0))
117
135
  expect(arguments).to eq(
118
136
  from: [100.0, 500.0],
119
137
  to: [200.0, 600.0],
@@ -138,7 +156,7 @@ describe Prawn::SVG::Elements::Gradient do
138
156
  end
139
157
 
140
158
  it 'passes in the transform via the apply_transformations option' do
141
- arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0]))
159
+ arguments = element.gradient_arguments(double(bounding_box: [100, 100, 200, 0], stroke_width: 0))
142
160
 
143
161
  expect(arguments).to eq(
144
162
  from: [0.0, 0.0],
@@ -168,7 +186,7 @@ describe Prawn::SVG::Elements::Gradient do
168
186
  end
169
187
 
170
188
  it 'correctly inherits the attributes from the parent element' do
171
- arguments = document.gradients['flag-2'].gradient_arguments(double(bounding_box: [100, 100, 200, 0]))
189
+ arguments = document.gradients['flag-2'].gradient_arguments(double(bounding_box: [100, 100, 200, 0], stroke_width: 0))
172
190
  expect(arguments).to eq(
173
191
  from: [150.0, 500.0],
174
192
  to: [220.0, 600.0],
@@ -178,7 +196,7 @@ describe Prawn::SVG::Elements::Gradient do
178
196
  bounding_box: [100, 100, 200, 0]
179
197
  )
180
198
 
181
- arguments = document.gradients['flag-3'].gradient_arguments(double(bounding_box: [100, 100, 200, 0]))
199
+ arguments = document.gradients['flag-3'].gradient_arguments(double(bounding_box: [100, 100, 200, 0], stroke_width: 0))
182
200
  expect(arguments).to eq(
183
201
  from: [170.0, 500.0],
184
202
  to: [220.0, 600.0],
@@ -0,0 +1,45 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="Illustration" viewBox="0 0 1275 850" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <defs>
4
+ <style>.cls-3{fill:url(#linear-gradient);}.cls-5{fill:url(#linear-gradient-3);}.cls-6{fill:url(#linear-gradient-4);}.cls-7{fill:url(#linear-gradient-2);}</style>
5
+ <linearGradient gradientTransform="translate(3610.94 -4546.2)" gradientUnits="userSpaceOnUse" id="linear-gradient" x1="-3428.66" x2="-2829.15" y1="4803.57" y2="4803.57">
6
+ <stop offset="0" stop-color="orange" stop-opacity="0"/>
7
+ <stop offset=".04" stop-color="orange" stop-opacity=".04"/>
8
+ <stop offset=".12" stop-color="orange" stop-opacity=".16"/>
9
+ <stop offset=".21" stop-color="orange" stop-opacity=".34"/>
10
+ <stop offset=".32" stop-color="orange" stop-opacity=".6"/>
11
+ <stop offset=".44" stop-color="orange" stop-opacity=".92"/>
12
+ <stop offset=".47" stop-color="orange"/>
13
+ <stop offset=".58" stop-color="darksalmon"/>
14
+ <stop offset=".8" stop-color="darksalmon"/>
15
+ <stop offset=".9" stop-color="red"/>
16
+ </linearGradient>
17
+ <linearGradient gradientTransform="translate(5391.8 -3148.45)" gradientUnits="userSpaceOnUse" id="linear-gradient-2" x1="-4854.3" x2="-4254.78" y1="3443.47" y2="3443.47">
18
+ <stop offset=".06" stop-color="orange" stop-opacity="0"/>
19
+ <stop offset=".11" stop-color="orange" stop-opacity=".07"/>
20
+ <stop offset=".19" stop-color="orange" stop-opacity=".26"/>
21
+ <stop offset=".31" stop-color="orange" stop-opacity=".56"/>
22
+ <stop offset=".46" stop-color="orange" stop-opacity=".97"/>
23
+ <stop offset=".47" stop-color="orange"/>
24
+ <stop offset="1" stop-color="red"/>
25
+ </linearGradient>
26
+ <linearGradient gradientTransform="translate(-1037.04 -401.09)" id="linear-gradient-3" x1="1460.82" x2="2060.34" xlink:href="#linear-gradient-2" y1="1006.26" y2="1006.26"/>
27
+ <linearGradient gradientTransform="translate(-295.18 -2362.64)" gradientUnits="userSpaceOnUse" id="linear-gradient-4" x1="610.99" x2="1210.5" y1="2682.84" y2="2682.84">
28
+ <stop offset=".09" stop-color="orange" stop-opacity="0"/>
29
+ <stop offset=".13" stop-color="orange" stop-opacity=".05"/>
30
+ <stop offset=".21" stop-color="orange" stop-opacity=".19"/>
31
+ <stop offset=".31" stop-color="orange" stop-opacity=".41"/>
32
+ <stop offset=".42" stop-color="orange" stop-opacity=".72"/>
33
+ <stop offset=".52" stop-color="orange"/>
34
+ <stop offset=".92" stop-color="red"/>
35
+ </linearGradient>
36
+ <linearGradient gradientTransform="translate(520.38 -911.81)" gradientUnits="userSpaceOnUse" id="linear-gradient-5" x1="-366.91" x2="258.33" y1="1381.44" y2="1381.44">
37
+ <stop offset="0" stop-color="#fff" stop-opacity="0"/>
38
+ <stop offset="1" stop-color="#fff"/>
39
+ </linearGradient>
40
+ </defs>
41
+ <rect class="cls-3" height="138.93" rx="69.47" ry="69.47" transform="translate(1004.69 98.45) rotate(135)" width="599.51" x="182.2" y="187.85"/>
42
+ <rect class="cls-7" height="138.93" rx="69.47" ry="69.47" transform="translate(1637.84 -88.45) rotate(135)" width="599.51" x="537.48" y="225.52"/>
43
+ <rect class="cls-5" height="138.93" rx="69.47" ry="69.47" transform="translate(-216.02 688.88) rotate(-45)" width="599.51" x="423.77" y="535.72"/>
44
+ <rect class="cls-6" height="138.93" rx="69.47" ry="69.47" transform="translate(-46.13 529.06) rotate(-45)" width="599.51" x="315.78" y="250.74"/>
45
+ </svg>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prawn-svg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.36.0
4
+ version: 0.36.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mog Nesbitt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-05 00:00:00.000000000 Z
11
+ date: 2025-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: css_parser
@@ -150,12 +150,12 @@ files:
150
150
  - lib/prawn/svg/loaders/web.rb
151
151
  - lib/prawn/svg/paint.rb
152
152
  - lib/prawn/svg/pathable.rb
153
+ - lib/prawn/svg/pdfmatrix.rb
153
154
  - lib/prawn/svg/percentage.rb
154
155
  - lib/prawn/svg/properties.rb
155
156
  - lib/prawn/svg/renderer.rb
156
157
  - lib/prawn/svg/state.rb
157
158
  - lib/prawn/svg/transform_parser.rb
158
- - lib/prawn/svg/transform_utils.rb
159
159
  - lib/prawn/svg/ttf.rb
160
160
  - lib/prawn/svg/url_loader.rb
161
161
  - lib/prawn/svg/version.rb
@@ -216,6 +216,7 @@ files:
216
216
  - spec/sample_svg/ellipse01.svg
217
217
  - spec/sample_svg/gistfile1.svg
218
218
  - spec/sample_svg/google_charts.svg
219
+ - spec/sample_svg/gradient_offset_transparency.svg
219
220
  - spec/sample_svg/gradient_stress_test.svg
220
221
  - spec/sample_svg/gradient_transform.svg
221
222
  - spec/sample_svg/gradients-cmyk.svg
File without changes