prawn-svg 0.35.0 → 0.36.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +3 -5
  3. data/README.md +4 -7
  4. data/lib/prawn/svg/attributes/opacity.rb +23 -8
  5. data/lib/prawn/svg/attributes/stroke.rb +7 -9
  6. data/lib/prawn/svg/attributes/transform.rb +1 -1
  7. data/lib/prawn/svg/calculators/pixels.rb +9 -22
  8. data/lib/prawn/svg/color.rb +58 -59
  9. data/lib/prawn/svg/css/font_parser.rb +46 -0
  10. data/lib/prawn/svg/document.rb +5 -1
  11. data/lib/prawn/svg/elements/base.rb +22 -30
  12. data/lib/prawn/svg/elements/gradient.rb +99 -74
  13. data/lib/prawn/svg/elements/line.rb +1 -1
  14. data/lib/prawn/svg/elements/marker.rb +2 -0
  15. data/lib/prawn/svg/elements/root.rb +1 -1
  16. data/lib/prawn/svg/elements/text_component.rb +3 -3
  17. data/lib/prawn/svg/funciri.rb +14 -0
  18. data/lib/prawn/svg/gradient_renderer.rb +313 -0
  19. data/lib/prawn/svg/length.rb +43 -0
  20. data/lib/prawn/svg/paint.rb +67 -0
  21. data/lib/prawn/svg/percentage.rb +24 -0
  22. data/lib/prawn/svg/properties.rb +208 -104
  23. data/lib/prawn/svg/renderer.rb +5 -0
  24. data/lib/prawn/svg/state.rb +5 -3
  25. data/lib/prawn/svg/transform_parser.rb +19 -13
  26. data/lib/prawn/svg/transform_utils.rb +37 -0
  27. data/lib/prawn/svg/version.rb +1 -1
  28. data/lib/prawn-svg.rb +7 -3
  29. data/prawn-svg.gemspec +4 -4
  30. data/spec/prawn/svg/attributes/opacity_spec.rb +27 -20
  31. data/spec/prawn/svg/attributes/transform_spec.rb +5 -2
  32. data/spec/prawn/svg/calculators/pixels_spec.rb +1 -2
  33. data/spec/prawn/svg/color_spec.rb +22 -52
  34. data/spec/prawn/svg/elements/base_spec.rb +9 -10
  35. data/spec/prawn/svg/elements/gradient_spec.rb +92 -36
  36. data/spec/prawn/svg/elements/marker_spec.rb +13 -15
  37. data/spec/prawn/svg/funciri_spec.rb +59 -0
  38. data/spec/prawn/svg/length_spec.rb +89 -0
  39. data/spec/prawn/svg/paint_spec.rb +96 -0
  40. data/spec/prawn/svg/pathable_spec.rb +3 -3
  41. data/spec/prawn/svg/pdfmatrix_spec.rb +60 -0
  42. data/spec/prawn/svg/percentage_spec.rb +60 -0
  43. data/spec/prawn/svg/properties_spec.rb +124 -107
  44. data/spec/prawn/svg/transform_parser_spec.rb +13 -13
  45. data/spec/sample_svg/gradient_stress_test.svg +115 -0
  46. metadata +25 -7
  47. data/lib/prawn/svg/extensions/additional_gradient_transforms.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0567f606c8d50a83ca8521e9af1a39cda59c570086d624eb08f415e13e2e0623
4
- data.tar.gz: 37e4d144020f202b293fb7106c7e9bcbe47b47bf3dd85ee6f811c757b89e1dc9
3
+ metadata.gz: b833a9af0fae6fd2934c6b5ef37bd6d6d90aba36fa9a161520ac6a9a1c19f9db
4
+ data.tar.gz: 550aa711e413cac65e8af39f029096e3606f84a852b982729ca0252e758805ac
5
5
  SHA512:
6
- metadata.gz: 89263ec912e718bb6405d0b4fd6b963665c1165bcedd8ec62226f7cfc4f8a80e9be771ceb55cfec45a65320e718724763f82dce20c274a6258da78f23394d91b
7
- data.tar.gz: b87dfa3862f6679c530e2dfce0fcf9ef7a1e942cc2dff68f54bc6c053dd1b66915d2cae096a5d82e9905f35d3348a4e3a64bf02c0bb8491ef17826c890465e15
6
+ metadata.gz: 9a522f7b4aa8f713fc453cc3d6061968fce1a28ab60e58f6c321b92979bcb909748a81b8c9cb9a373f918d152e969ea7d0974afd975c8fba7ae70c03cec18a25
7
+ data.tar.gz: 537a912b7daab1581662cabfc5de5776ebe771d15e448e99a7c7d6125eb29644bbc40de6508429f5a3451f16ebb226f53402320ef4430118b16d05913cd3ede4
data/Gemfile.lock CHANGED
@@ -1,11 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prawn-svg (0.34.2)
4
+ prawn-svg (0.36.0)
5
5
  css_parser (~> 1.6)
6
6
  matrix (~> 0.4.2)
7
7
  prawn (>= 0.11.1, < 3)
8
- rexml (~> 3.2)
8
+ rexml (>= 3.3.9, < 4)
9
9
 
10
10
  GEM
11
11
  remote: http://rubygems.org/
@@ -34,8 +34,7 @@ GEM
34
34
  rainbow (3.1.1)
35
35
  rake (13.2.1)
36
36
  regexp_parser (2.9.2)
37
- rexml (3.3.0)
38
- strscan
37
+ rexml (3.4.0)
39
38
  rspec (3.13.0)
40
39
  rspec-core (~> 3.13.0)
41
40
  rspec-expectations (~> 3.13.0)
@@ -63,7 +62,6 @@ GEM
63
62
  rubocop-ast (1.31.3)
64
63
  parser (>= 3.3.1.0)
65
64
  ruby-progressbar (1.13.0)
66
- strscan (3.1.0)
67
65
  ttfunk (1.8.0)
68
66
  bigdecimal (~> 3.1)
69
67
  unicode-display_width (2.5.0)
data/README.md CHANGED
@@ -62,7 +62,7 @@ prawn-svg supports most but not all of the full SVG 1.1 specification. It curre
62
62
  implementation of elliptical arc is a bit rough at the moment.
63
63
 
64
64
  - `<text>`, `<tspan>` and `<tref>` with attributes `x`, `y`, `dx`, `dy`, `rotate`, `textLength`, `lengthAdjust`,
65
- and with extra properties `text-anchor`, `text-decoration` (underline only), `font-size`, `font-family`,
65
+ and with extra properties `text-anchor`, `text-decoration` (underline only), `font`, `font-size`, `font-family`,
66
66
  `font-weight`, `font-style`, `letter-spacing`, `dominant-baseline` (middle only)
67
67
 
68
68
  - `<svg>`, `<g>` and `<symbol>`
@@ -80,13 +80,14 @@ prawn-svg supports most but not all of the full SVG 1.1 specification. It curre
80
80
  - `<marker>`
81
81
 
82
82
  - `<linearGradient>` and `<radialGradient>` are implemented on Prawn 2.2.0+ with attributes `gradientUnits` and
83
- `gradientTransform` (`spreadMethod` and `stop-opacity` are unimplemented.)
83
+ `gradientTransform`
84
84
 
85
85
  - `<switch>` and `<foreignObject>`, although prawn-svg cannot handle any data that is not SVG so `<foreignObject>`
86
86
  tags are always ignored.
87
87
 
88
88
  - properties: `clip-path`, `color`, `display`, `fill`, `fill-opacity`, `fill-rule`, `opacity`, `overflow`,
89
- `stroke`, `stroke-dasharray`, `stroke-linecap`, `stroke-linejoin`, `stroke-opacity`, `stroke-width`
89
+ `stroke`, `stroke-dasharray`, `stroke-linecap`, `stroke-linejoin`, `stroke-opacity`, `stroke-width`,
90
+ `visibility`
90
91
 
91
92
  - properties on lines, polylines, polygons and paths: `marker-end`, `marker-mid`, `marker-start`
92
93
 
@@ -114,10 +115,6 @@ In CSS selectors you can use element names, IDs, classes, attributes (existence,
114
115
  and all combinators (` `, `>`, `+`, `~`).
115
116
  The pseudo-classes `:first-child`, `:last-child` and `:nth-child(n)` (where n is a number) also work.
116
117
 
117
- Warning: Ruby versions less than 2.6.0 have a bug in the REXML XPath implementation which means under some
118
- conditions the `+` combinator will not pick up all matching elements. See `stylesheets_spec.rb` for an
119
- explanation if you're stuck on an old version of Ruby.
120
-
121
118
  Pseudo-elements and the other pseudo-classes are not supported. Specificity ordering is
122
119
  implemented, but `!important` is not.
123
120
 
@@ -1,15 +1,30 @@
1
1
  module Prawn::SVG::Attributes::Opacity
2
2
  def parse_opacity_attributes_and_call
3
- # We can't do nested opacities quite like the SVG requires, but this is close enough.
4
- opacity = properties.opacity.to_f.clamp(0, 1) if properties.opacity
5
- fill_opacity = properties.fill_opacity.to_f.clamp(0, 1) if properties.fill_opacity
6
- stroke_opacity = properties.stroke_opacity.to_f.clamp(0, 1) if properties.stroke_opacity
3
+ # The opacity property is not inherited, but the opacity applies to all children underneath the element.
4
+ #
5
+ # Having an opacity property on a parent, and again on a child, multiplies the parent and child's opacities
6
+ # when drawing the children.
7
+ #
8
+ # The fill-opacity and stroke-opacity properties are inherited, but children which have a different value
9
+ # are displayed at that opacity rather than multiplying the parent's fill/stroke opacity with the child's.
10
+ #
11
+ # opacity and fill/stroke opacity can both be applied to the same element, and they multiply together.
7
12
 
8
- if opacity || fill_opacity || stroke_opacity
9
- state.fill_opacity *= [opacity || 1, fill_opacity || 1].min
10
- state.stroke_opacity *= [opacity || 1, stroke_opacity || 1].min
13
+ opacity = computed_properties.opacity&.to_f&.clamp(0, 1)
14
+ fill_opacity = computed_properties.fill_opacity.to_f.clamp(0, 1)
15
+ stroke_opacity = computed_properties.stroke_opacity.to_f.clamp(0, 1)
11
16
 
12
- add_call_and_enter 'transparent', state.fill_opacity, state.stroke_opacity
17
+ state.opacity *= opacity if opacity
18
+
19
+ fill_opacity = (fill_opacity || 1) * state.opacity
20
+ stroke_opacity = (stroke_opacity || 1) * state.opacity
21
+
22
+ fill_opacity = stroke_opacity = 0 if computed_properties.visibility != 'visible'
23
+
24
+ if state.last_fill_opacity != fill_opacity || state.last_stroke_opacity != stroke_opacity
25
+ state.last_fill_opacity = fill_opacity
26
+ state.last_stroke_opacity = stroke_opacity
27
+ add_call_and_enter 'transparent', fill_opacity, stroke_opacity
13
28
  end
14
29
  end
15
30
  end
@@ -23,19 +23,17 @@ module Prawn::SVG::Attributes::Stroke
23
23
  # don't do anything
24
24
  when 'none'
25
25
  add_call('undash')
26
- else
27
- array = dasharray.split(Prawn::SVG::Elements::COMMA_WSP_REGEXP)
28
- array *= 2 if array.length.odd?
29
- number_array = array.map { |value| pixels(value) }
26
+ when Array
27
+ dasharray *= 2 if dasharray.length.odd?
28
+ values = dasharray.map { |value| pixels(value) }
30
29
 
31
- if number_array.any?(&:negative?)
32
- @document.warnings << "stroke-dasharray cannot have negative numbers; treating as 'none'"
33
- add_call('undash')
34
- elsif number_array.inject(0) { |a, b| a + b }.zero?
30
+ if values.inject(0) { |a, b| a + b }.zero?
35
31
  add_call('undash')
36
32
  else
37
- add_call('dash', number_array)
33
+ add_call('dash', values)
38
34
  end
35
+ else
36
+ raise "Unknown dasharray value: #{dasharray.inspect}"
39
37
  end
40
38
  end
41
39
  end
@@ -2,7 +2,7 @@ module Prawn::SVG::Attributes::Transform
2
2
  def parse_transform_attribute_and_call
3
3
  return unless (transform = attributes['transform'])
4
4
 
5
- matrix = parse_transform_attribute(transform)
5
+ matrix = matrix_for_pdf(parse_transform_attribute(transform))
6
6
  add_call_and_enter 'transformation_matrix', *matrix unless matrix == [1, 0, 0, 1, 0, 0]
7
7
  end
8
8
  end
@@ -1,25 +1,12 @@
1
1
  module Prawn::SVG::Calculators::Pixels
2
2
  class Measurement
3
- extend Prawn::Measurements
4
-
5
3
  def self.to_pixels(value, axis_length = nil, font_size: Prawn::SVG::Properties::EM)
6
- if value.is_a?(String)
7
- if (match = value.match(/\d(em|ex|pc|cm|mm|in)$/))
8
- case match[1]
9
- when 'em'
10
- value.to_f * font_size
11
- when 'ex'
12
- value.to_f * (font_size / 2.0) # we don't have access to the x-height, so this is an approximation approved by the CSS spec
13
- when 'pc'
14
- value.to_f * 15 # according to http://www.w3.org/TR/SVG11/coords.html
15
- else
16
- send("#{match[1]}2pt", value.to_f)
17
- end
18
- elsif value[-1..] == '%'
19
- value.to_f * axis_length / 100.0
20
- else
21
- value.to_f
22
- end
4
+ if value.respond_to?(:to_pixels)
5
+ value.to_pixels(axis_length, font_size)
6
+ elsif value.is_a?(String)
7
+ value = value.strip
8
+ value = Prawn::SVG::Length.parse(value) || Prawn::SVG::Percentage.parse(value)
9
+ value&.to_pixels(axis_length, font_size) || 0.0
23
10
  elsif value
24
11
  value.to_f
25
12
  end
@@ -40,16 +27,16 @@ module Prawn::SVG::Calculators::Pixels
40
27
 
41
28
  def pixels(value)
42
29
  value && Measurement.to_pixels(value, state.viewport_sizing.viewport_diagonal,
43
- font_size: computed_properties.numerical_font_size)
30
+ font_size: computed_properties.numeric_font_size)
44
31
  end
45
32
 
46
33
  def x_pixels(value)
47
34
  value && Measurement.to_pixels(value, state.viewport_sizing.viewport_width,
48
- font_size: computed_properties.numerical_font_size)
35
+ font_size: computed_properties.numeric_font_size)
49
36
  end
50
37
 
51
38
  def y_pixels(value)
52
39
  value && Measurement.to_pixels(value, state.viewport_sizing.viewport_height,
53
- font_size: computed_properties.numerical_font_size)
40
+ font_size: computed_properties.numeric_font_size)
54
41
  end
55
42
  end
@@ -1,6 +1,28 @@
1
1
  class Prawn::SVG::Color
2
- RGB = Struct.new(:value)
3
- CMYK = Struct.new(:value)
2
+ CMYK = Struct.new(:value) do
3
+ def to_cmyk
4
+ self
5
+ end
6
+ end
7
+
8
+ RGB = Struct.new(:value) do
9
+ def to_rgb
10
+ [value[0..1], value[2..3], value[4..5]].map { |h| h.to_i(16) / 255.0 }
11
+ end
12
+
13
+ def to_cmyk
14
+ r, g, b = rgb = to_rgb
15
+ k = 1 - rgb.max
16
+ if k == 1
17
+ CMYK.new([0, 0, 0, 100])
18
+ else
19
+ c = (1 - r - k) / (1 - k)
20
+ m = (1 - g - k) / (1 - k)
21
+ y = (1 - b - k) / (1 - k)
22
+ CMYK.new([c, m, y, k].map { |v| (v * 100).round })
23
+ end
24
+ end
25
+ end
4
26
 
5
27
  RGB_DEFAULT_COLOR = RGB.new('000000')
6
28
  CMYK_DEFAULT_COLOR = CMYK.new([0, 0, 0, 100])
@@ -156,63 +178,48 @@ class Prawn::SVG::Color
156
178
  }.freeze
157
179
 
158
180
  class << self
159
- def parse(color_string, gradients = nil, color_mode = :rgb)
160
- url_specified = false
181
+ def black
182
+ RGB_DEFAULT_COLOR
183
+ end
161
184
 
162
- values = ::Prawn::SVG::CSS::ValuesParser.parse(color_string)
185
+ def parse(value)
186
+ case value
187
+ in ['rgb', args]
188
+ return unless args.length == 3
163
189
 
164
- result = values.map do |value|
165
- case value
166
- in ['rgb', args]
167
- hex = (0..2).collect do |n|
168
- number = args[n].to_f
169
- number *= 2.55 if args[n][-1..] == '%'
190
+ rgb =
191
+ args.map do |arg|
192
+ number = to_float(arg, 2.55) or break
170
193
  format('%02x', number.round.clamp(0, 255))
171
- end.join
172
-
173
- RGB.new(hex)
174
-
175
- in ['device-cmyk', args]
176
- cmyk = (0..3).collect do |n|
177
- number = args[n].to_f
178
- number *= 100 unless args[n][-1..] == '%'
179
- number.clamp(0, 100)
180
194
  end
181
195
 
182
- CMYK.new(cmyk)
196
+ rgb && RGB.new(rgb.join)
197
+
198
+ in ['device-cmyk', args]
199
+ return unless args.length == 4
183
200
 
184
- in ['url', [url]]
185
- url_specified = true
186
- if url[0] == '#' && gradients && (gradient = gradients[url[1..]])
187
- gradient
201
+ cymk =
202
+ args.map do |arg|
203
+ number = to_float(arg, 0.01) or break
204
+ (number * 100).clamp(0, 100)
188
205
  end
189
206
 
190
- in /\A#([0-9a-f])([0-9a-f])([0-9a-f])\z/i
191
- RGB.new("#{$1 * 2}#{$2 * 2}#{$3 * 2}")
207
+ cymk && CMYK.new(cymk)
192
208
 
193
- in /\A#[0-9a-f]{6}\z/i
194
- RGB.new(value[1..])
209
+ in /\A#([0-9a-f])([0-9a-f])([0-9a-f])\z/i
210
+ RGB.new("#{$1 * 2}#{$2 * 2}#{$3 * 2}")
195
211
 
196
- in String => color
197
- if (hex = HTML_COLORS[color.downcase])
198
- hex_color(hex, color_mode)
199
- end
212
+ in /\A#[0-9a-f]{6}\z/i
213
+ RGB.new(value[1..])
200
214
 
201
- else
202
- nil
215
+ in String => color
216
+ if (hex = HTML_COLORS[color.downcase])
217
+ RGB.new(hex)
203
218
  end
204
- end
205
-
206
- # Generally, we default to black if the colour was unparseable.
207
- # http://www.w3.org/TR/SVG/painting.html section 11.2 says if a URL was
208
- # supplied without a fallback, that's an error.
209
- result << default_color(color_mode) unless url_specified
210
219
 
211
- result.compact
212
- end
213
-
214
- def css_color_to_prawn_color(color)
215
- parse(color).detect { |value| value.is_a?(RGB) || value.is_a?(CMYK) }&.value
220
+ else
221
+ nil
222
+ end
216
223
  end
217
224
 
218
225
  def default_color(color_mode)
@@ -221,20 +228,12 @@ class Prawn::SVG::Color
221
228
 
222
229
  private
223
230
 
224
- def hex_color(hex, color_mode)
225
- if color_mode == :cmyk
226
- r, g, b = [hex[0..1], hex[2..3], hex[4..5]].map { |h| h.to_i(16) / 255.0 }
227
- k = 1 - [r, g, b].max
228
- if k == 1
229
- CMYK.new([0, 0, 0, 100])
230
- else
231
- c = (1 - r - k) / (1 - k)
232
- m = (1 - g - k) / (1 - k)
233
- y = (1 - b - k) / (1 - k)
234
- CMYK.new([c, m, y, k].map { |v| (v * 100).round })
235
- end
231
+ def to_float(string, percentage_multiplier)
232
+ if string[-1] == '%'
233
+ number = Float(string[0..-2], exception: false)
234
+ number && (number * percentage_multiplier)
236
235
  else
237
- RGB.new(hex)
236
+ Float(string, exception: false)
238
237
  end
239
238
  end
240
239
  end
@@ -0,0 +1,46 @@
1
+ module Prawn::SVG::CSS
2
+ class FontParser
3
+ def self.parse(string)
4
+ in_quote = nil
5
+ in_escape = false
6
+ in_list_delimiter = false
7
+ current = nil
8
+ values = []
9
+
10
+ string.each_char do |char|
11
+ if in_escape
12
+ in_escape = false
13
+ if current.nil?
14
+ current = char
15
+ values << current
16
+ else
17
+ current << char
18
+ end
19
+ elsif char == ',' && in_quote.nil? && !in_escape && current
20
+ current << char
21
+ in_list_delimiter = true
22
+ elsif char == '\\'
23
+ in_escape = true
24
+ elsif current.nil?
25
+ if char.match(/\s/).nil?
26
+ in_list_delimiter = false
27
+ current = char
28
+ values << current
29
+ end
30
+ elsif !in_quote && !in_escape && !in_list_delimiter && char.match(/\s/)
31
+ current = nil
32
+ else
33
+ current << char
34
+ end
35
+
36
+ if char == in_quote
37
+ in_quote = nil
38
+ elsif in_quote.nil? && ['"', "'"].include?(char)
39
+ in_quote = char
40
+ end
41
+ end
42
+
43
+ values.map(&:rstrip)
44
+ end
45
+ end
46
+ end
@@ -17,7 +17,11 @@ class Prawn::SVG::Document
17
17
  :color_mode
18
18
 
19
19
  def initialize(data, bounds, options, font_registry: nil, css_parser: CssParser::Parser.new, attribute_overrides: {})
20
- @root = REXML::Document.new(data).root
20
+ begin
21
+ @root = REXML::Document.new(data).root
22
+ rescue REXML::ParseException
23
+ @root = nil
24
+ end
21
25
 
22
26
  if @root.nil?
23
27
  if data.respond_to?(:end_with?) && data.end_with?('.svg')
@@ -158,8 +158,8 @@ class Prawn::SVG::Elements::Base
158
158
  def apply_drawing_call
159
159
  return if state.disable_drawing || !drawable?
160
160
 
161
- fill = computed_properties.fill != 'none'
162
- stroke = computed_properties.stroke != 'none'
161
+ fill = !computed_properties.fill.none? # rubocop:disable Style/InverseMethods
162
+ stroke = !computed_properties.stroke.none? # rubocop:disable Style/InverseMethods
163
163
 
164
164
  if fill
165
165
  command = stroke ? 'fill_and_stroke' : 'fill'
@@ -178,31 +178,27 @@ class Prawn::SVG::Elements::Base
178
178
 
179
179
  def apply_colors
180
180
  PAINT_TYPES.each do |type|
181
- color = properties.send(type)
181
+ paint = properties.send(type)
182
182
 
183
- next if [nil, 'inherit', 'none'].include?(color)
183
+ case paint
184
+ when nil, 'inherit'
185
+ next
186
+ when Prawn::SVG::Paint
187
+ color = paint.resolve(document.gradients, computed_properties.color, document.color_mode)
184
188
 
185
- color = computed_properties.color if color == 'currentColor'
186
-
187
- results = Prawn::SVG::Color.parse(color, document.gradients, document.color_mode)
188
-
189
- success = results.detect do |result|
190
- case result
189
+ case color
191
190
  when Prawn::SVG::Color::RGB, Prawn::SVG::Color::CMYK
192
- add_call "#{type}_color", result.value
193
- true
191
+ add_call "#{type}_color", color.value
194
192
  when Prawn::SVG::Elements::Gradient
195
- arguments = result.gradient_arguments(self)
196
- if arguments
197
- add_call "#{type}_gradient", **arguments
198
- true
199
- end
193
+ add_call 'svg:render_gradient', type.to_sym, **color.gradient_arguments(self)
194
+ when nil
195
+ nil
196
+ else
197
+ raise "Unknown resolved color type: #{color.inspect}"
200
198
  end
199
+ else
200
+ raise "Unknown paint type: #{paint.inspect}"
201
201
  end
202
-
203
- # If we were unable to find a suitable color candidate,
204
- # we turn off this type of paint.
205
- computed_properties.set(type, 'none') if success.nil?
206
202
  end
207
203
  end
208
204
 
@@ -250,15 +246,11 @@ class Prawn::SVG::Elements::Base
250
246
  end
251
247
  end
252
248
 
253
- def extract_element_from_url_id_reference(values, expected_type = nil)
254
- Prawn::SVG::CSS::ValuesParser.parse(values).detect do |value|
255
- case value
256
- in ['url', [url]]
257
- element = document.elements_by_id[url[1..]] if url.start_with?('#')
258
- break element if element && (expected_type.nil? || element.name == expected_type)
259
- else
260
- nil
261
- end
249
+ def extract_element_from_url_id_reference(value, expected_type = nil)
250
+ case value
251
+ when Prawn::SVG::FuncIRI
252
+ element = document.elements_by_id[value.url[1..]] if value.url.start_with?('#')
253
+ element if element && (expected_type.nil? || element.name == expected_type)
262
254
  end
263
255
  end
264
256