From 93d1af38c2b2bed900c45eeab98739312882defb Mon Sep 17 00:00:00 2001 From: Mog Nesbitt Date: Sun, 28 Jan 2024 11:03:02 +1300 Subject: [PATCH] Correctly handle "use"ing symbols The svg spec says to treat "use"d symbols as svg elements, and to transfer the width and height from the use element to the cloned svg element. This fixes a rendering problem reported in issue #157. --- lib/prawn/svg/elements/use.rb | 32 ++++++++++++++++++++------------ spec/sample_svg/symbol.svg | 12 ++++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 spec/sample_svg/symbol.svg diff --git a/lib/prawn/svg/elements/use.rb b/lib/prawn/svg/elements/use.rb index ea14be0..36221f2 100644 --- a/lib/prawn/svg/elements/use.rb +++ b/lib/prawn/svg/elements/use.rb @@ -1,15 +1,12 @@ class Prawn::SVG::Elements::Use < Prawn::SVG::Elements::Base - attr_reader :referenced_element_class - attr_reader :referenced_element_source + attr_reader :referenced_element_class, :referenced_element_source def parse href = href_attribute - if href.nil? - raise SkipElementError, "use tag must have an href or xlink:href" - end + raise SkipElementError, 'use tag must have an href or xlink:href' if href.nil? if href[0..0] != '#' - raise SkipElementError, "use tag has an href that is not a reference to an id; this is not supported" + raise SkipElementError, 'use tag has an href that is not a reference to an id; this is not supported' end id = href[1..-1] @@ -29,14 +26,18 @@ def parse end end - if referenced_element_class.nil? - raise SkipElementError, "no tag with ID '#{id}' was found, referenced by use tag" + raise SkipElementError, "no tag with ID '#{id}' was found, referenced by use tag" if referenced_element_class.nil? + + if referenced_element_source.name == 'symbol' + @referenced_element_class = Prawn::SVG::Elements::Viewport end state.inside_use = true @x = attributes['x'] @y = attributes['y'] + @width = attributes['width'] + @height = attributes['height'] end def container? @@ -45,16 +46,23 @@ def container? def apply if @x || @y - add_call_and_enter "translate", x_pixels(@x || 0), -y_pixels(@y || 0) + add_call_and_enter 'translate', x_pixels(@x || 0), -y_pixels(@y || 0) end end def process_child_elements - add_call "save" + add_call 'save' + + source = referenced_element_source.dup + + if referenced_element_class == Prawn::SVG::Elements::Viewport + source.attributes['width'] = @width || '100%' + source.attributes['height'] = @height || '100%' + end - child = referenced_element_class.new(document, referenced_element_source, calls, state.dup) + child = referenced_element_class.new(document, source, calls, state.dup) child.process - add_call "restore" + add_call 'restore' end end diff --git a/spec/sample_svg/symbol.svg b/spec/sample_svg/symbol.svg new file mode 100644 index 0000000..33eb7aa --- /dev/null +++ b/spec/sample_svg/symbol.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file