diff --git a/lib/prawn/svg/css/stylesheets.rb b/lib/prawn/svg/css/stylesheets.rb index e95f558..e7bda50 100644 --- a/lib/prawn/svg/css/stylesheets.rb +++ b/lib/prawn/svg/css/stylesheets.rb @@ -1,5 +1,7 @@ module Prawn::SVG::CSS class Stylesheets + USER_AGENT_STYLESHEET = 'svg, symbol, image, marker, pattern, foreignObject { overflow: hidden }'.freeze + attr_reader :css_parser, :root, :media def initialize(css_parser, root, media = :all) @@ -9,6 +11,7 @@ def initialize(css_parser, root, media = :all) end def load + load_user_agent_stylesheet load_style_elements xpath_styles = gather_xpath_styles associate_xpath_styles_with_elements(xpath_styles) @@ -16,6 +19,10 @@ def load private + def load_user_agent_stylesheet + css_parser.add_block!(USER_AGENT_STYLESHEET) + end + def load_style_elements REXML::XPath.match(root, '//style').each do |source| data = source.texts.map(&:value).join diff --git a/lib/prawn/svg/elements/base.rb b/lib/prawn/svg/elements/base.rb index e8b16d7..f5a1004 100644 --- a/lib/prawn/svg/elements/base.rb +++ b/lib/prawn/svg/elements/base.rb @@ -270,4 +270,14 @@ def extract_element_from_url_id_reference(value, expected_type = nil) def href_attribute attributes['xlink:href'] || attributes['href'] end + + def overflow_hidden? + ['hidden', 'scroll'].include?(computed_properties.overflow) + end + + def clone_element_source(source) + new_source = source.dup + document.element_styles[new_source] = document.element_styles[source] + new_source + end end diff --git a/lib/prawn/svg/elements/marker.rb b/lib/prawn/svg/elements/marker.rb index ff34ff9..65922d4 100644 --- a/lib/prawn/svg/elements/marker.rb +++ b/lib/prawn/svg/elements/marker.rb @@ -46,8 +46,7 @@ def apply_marker(element, point: nil, angle: 0) element.add_call 'transformation_matrix', 1, 0, 0, 1, -ref_x * sizing.x_scale, ref_y * sizing.y_scale - # `overflow: visible` must be on the element - if properties.overflow != 'visible' + if overflow_hidden? point = [sizing.x_offset * sizing.x_scale, y(sizing.y_offset * sizing.y_scale)] element.add_call "rectangle", point, sizing.output_width, sizing.output_height element.add_call "clip" diff --git a/lib/prawn/svg/elements/use.rb b/lib/prawn/svg/elements/use.rb index 36221f2..19bcab9 100644 --- a/lib/prawn/svg/elements/use.rb +++ b/lib/prawn/svg/elements/use.rb @@ -53,7 +53,7 @@ def apply def process_child_elements add_call 'save' - source = referenced_element_source.dup + source = clone_element_source(referenced_element_source) if referenced_element_class == Prawn::SVG::Elements::Viewport source.attributes['width'] = @width || '100%' diff --git a/lib/prawn/svg/elements/viewport.rb b/lib/prawn/svg/elements/viewport.rb index 3f88f67..cec449f 100644 --- a/lib/prawn/svg/elements/viewport.rb +++ b/lib/prawn/svg/elements/viewport.rb @@ -16,8 +16,11 @@ def apply add_call 'transformation_matrix', 1, 0, 0, 1, @x, -@y end - add_call 'rectangle', [0, y(0)], @sizing.output_width, @sizing.output_height - add_call 'clip' + if overflow_hidden? + add_call 'rectangle', [0, y(0)], @sizing.output_width, @sizing.output_height + add_call 'clip' + end + add_call 'transformation_matrix', @sizing.x_scale, 0, 0, @sizing.y_scale, 0, 0 add_call 'transformation_matrix', 1, 0, 0, 1, -@sizing.x_offset, @sizing.y_offset end diff --git a/spec/prawn/svg/css/stylesheets_spec.rb b/spec/prawn/svg/css/stylesheets_spec.rb index 6d5b751..91b935f 100644 --- a/spec/prawn/svg/css/stylesheets_spec.rb +++ b/spec/prawn/svg/css/stylesheets_spec.rb @@ -62,6 +62,7 @@ width_and_styles = result.map { |k, v| [k.attributes["width"].to_i, v] }.sort_by(&:first) expected = [ + [0, [["overflow", "hidden", false]]], [1, [["fill", "#ff0000", false]]], [2, [["fill", "#ff0000", false], ["fill", "#330000", false], ["fill", "#440000", false], ["fill", "#220000", false]]], [3, [["fill", "#ff0000", false], ["fill", "#00ff00", false]]], @@ -114,6 +115,7 @@ it "scans the document for style tags and adds the style information to the css parser" do css_parser = instance_double(CssParser::Parser) + expect(css_parser).to receive(:add_block!).with("svg, symbol, image, marker, pattern, foreignObject { overflow: hidden }") expect(css_parser).to receive(:add_block!).with("a\n before>\n x y\n inside <>>\n k j\n after\nz") expect(css_parser).to receive(:add_block!).with("hello") allow(css_parser).to receive(:each_rule_set) diff --git a/spec/prawn/svg/elements/marker_spec.rb b/spec/prawn/svg/elements/marker_spec.rb index 395ee00..906e848 100644 --- a/spec/prawn/svg/elements/marker_spec.rb +++ b/spec/prawn/svg/elements/marker_spec.rb @@ -18,18 +18,19 @@ end let(:document) { Prawn::SVG::Document.new(svg, [800, 600], {width: 800, height: 600}) } - let(:state) { Prawn::SVG::State.new } - let(:line_element) do - Prawn::SVG::Elements::Line.new(document, document.root.elements[2], [], state) + def new_state + state = Prawn::SVG::State.new + state.viewport_sizing = document.sizing + state end - subject do - Prawn::SVG::Elements::Marker.new(document, document.root.elements[1], [], state) + let(:line_element) do + Prawn::SVG::Elements::Line.new(document, document.root.elements[2], [], new_state) end - before do - state.viewport_sizing = document.sizing + subject do + Prawn::SVG::Elements::Marker.new(document, document.root.elements[1], [], new_state) end describe "#parse" do @@ -70,8 +71,8 @@ ["clip", [], {}, []], ["transformation_matrix", [0.3, 0, 0, 0.3, 0, 0], {}, []], ["transparent", [1.0, 1.0], {}, [ - ["stroke_color", ["000000"], {}, []], - ["line_width", [100.0], {}, []], + ["fill_color", ["000000"], {}, []], + ["line_width", [1.0], {}, []], ["cap_style", [:butt], {}, []], ["join_style", [:miter], {}, []], ["undash", [], {}, []],