mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:12:45 +00:00 
			
		
		
		
	LibWeb: Use viewbox attribute in SVG symbol element
Previously when a viewBox was passed to a SVG symbol element it would not be taken into account when drawing the SVG.
This commit is contained in:
		
							parent
							
								
									9f73fc87a8
								
							
						
					
					
						commit
						e61fdd1dc6
					
				
					 9 changed files with 67 additions and 4 deletions
				
			
		
							
								
								
									
										20
									
								
								Tests/LibWeb/Layout/expected/svg/svg-symbol-with-viewbox.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								Tests/LibWeb/Layout/expected/svg/svg-symbol-with-viewbox.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| Viewport <#document> at (0,0) content-size 800x600 children: not-inline | ||||
|   BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline | ||||
|     BlockContainer <body> at (8,8) content-size 784x150 children: not-inline | ||||
|       BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline | ||||
|         TextNode <#text> | ||||
|         TextNode <#text> | ||||
|       BlockContainer <div> at (8,8) content-size 784x150 children: inline | ||||
|         line 0 width: 300, height: 150, bottom: 150, baseline: 150 | ||||
|           frag 0 from SVGSVGBox start: 0, length: 0, rect: [8,8 300x150] | ||||
|         TextNode <#text> | ||||
|         SVGSVGBox <svg> at (8,8) content-size 300x150 [SVG] children: inline | ||||
|           TextNode <#text> | ||||
|           InlineNode <use> | ||||
|             InlineNode <symbol#braces> | ||||
|               TextNode <#text> | ||||
|               SVGGeometryBox <path> at (92.375,26.75) content-size 131.25x112.140625 children: inline | ||||
|                 TextNode <#text> | ||||
|               TextNode <#text> | ||||
|           TextNode <#text> | ||||
|         TextNode <#text> | ||||
							
								
								
									
										13
									
								
								Tests/LibWeb/Layout/input/svg/svg-symbol-with-viewbox.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Tests/LibWeb/Layout/input/svg/svg-symbol-with-viewbox.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| <body> | ||||
|   <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> | ||||
|     <symbol id="braces" viewBox="0 0 16 16"> | ||||
|       <path | ||||
|         d="M2.114 8.063V7.9c1.005-.102 1.497-.615 1.497-1.6V4.503c0-1.094.39-1.538 1.354-1.538h.273V2h-.376C3.25 2 2.49 2.759 2.49 4.352v1.524c0 1.094-.376 1.456-1.49 1.456v1.299c1.114 0 1.49.362 1.49 1.456v1.524c0 1.593.759 2.352 2.372 2.352h.376v-.964h-.273c-.964 0-1.354-.444-1.354-1.538V9.663c0-.984-.492-1.497-1.497-1.6zM13.886 7.9v.163c-1.005.103-1.497.616-1.497 1.6v1.798c0 1.094-.39 1.538-1.354 1.538h-.273v.964h.376c1.613 0 2.372-.759 2.372-2.352v-1.524c0-1.094.376-1.456 1.49-1.456V7.332c-1.114 0-1.49-.362-1.49-1.456V4.352C13.51 2.759 12.75 2 11.138 2h-.376v.964h.273c.964 0 1.354.444 1.354 1.538V6.3c0 .984.492 1.497 1.497 1.6z"> | ||||
|       </path> | ||||
|     </symbol> | ||||
|   </svg> | ||||
| 
 | ||||
|   <div> | ||||
|     <svg> | ||||
|       <use xlink:href="#braces"></use> | ||||
|     </svg> | ||||
|  | @ -159,7 +159,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available | |||
|             auto path_transform = dom_node.get_transform(); | ||||
| 
 | ||||
|             double viewbox_scale = 1; | ||||
|             auto maybe_view_box = svg_svg_element.view_box(); | ||||
|             auto maybe_view_box = dom_node.view_box(); | ||||
|             if (maybe_view_box.has_value()) { | ||||
|                 // FIXME: This should allow just one of width or height to be specified.
 | ||||
|                 // E.g. We should be able to layout <svg width="100%"> where height is unspecified/auto.
 | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ Optional<Gfx::AffineTransform> SVGGeometryBox::layout_transform() const | |||
|     double scaling = 1; | ||||
|     auto origin = viewbox_origin().to_type<double>().to_type<float>(); | ||||
|     Gfx::FloatPoint paint_offset = {}; | ||||
|     if (svg_box && svg_box->view_box().has_value()) { | ||||
|     if (svg_box && geometry_element.view_box().has_value()) { | ||||
|         // Note: SVGFormattingContext has already done the scaling based on the viewbox,
 | ||||
|         // we now have to derive what it was from the original bounding box size.
 | ||||
|         // FIXME: It would be nice if we could store the transform from layout somewhere, so we don't have to solve for it here.
 | ||||
|  |  | |||
|  | @ -76,7 +76,7 @@ void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const | |||
|     auto offset = context.floored_device_point(svg_element_rect.location()).to_type<int>().to_type<float>(); | ||||
|     painter.translate(offset); | ||||
| 
 | ||||
|     auto maybe_view_box = svg_element->view_box(); | ||||
|     auto maybe_view_box = geometry_element.view_box(); | ||||
| 
 | ||||
|     auto transform = layout_box().layout_transform(); | ||||
|     if (!transform.has_value()) | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ | |||
| #include <LibWeb/SVG/SVGGradientElement.h> | ||||
| #include <LibWeb/SVG/SVGGraphicsElement.h> | ||||
| #include <LibWeb/SVG/SVGSVGElement.h> | ||||
| #include <LibWeb/SVG/SVGSymbolElement.h> | ||||
| 
 | ||||
| namespace Web::SVG { | ||||
| 
 | ||||
|  | @ -230,4 +231,19 @@ Optional<float> SVGGraphicsElement::stroke_width() const | |||
|     return width.to_px(*layout_node(), scaled_viewport_size).to_double(); | ||||
| } | ||||
| 
 | ||||
| Optional<ViewBox> SVGGraphicsElement::view_box() const | ||||
| { | ||||
|     if (auto* svg_svg_element = shadow_including_first_ancestor_of_type<SVGSVGElement>()) { | ||||
|         if (svg_svg_element->view_box().has_value()) | ||||
|             return svg_svg_element->view_box(); | ||||
|     } | ||||
| 
 | ||||
|     if (auto* svg_symbol_element = shadow_including_first_ancestor_of_type<SVGSymbolElement>()) { | ||||
|         if (svg_symbol_element->view_box().has_value()) | ||||
|             return svg_symbol_element->view_box(); | ||||
|     } | ||||
| 
 | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ | |||
| #include <LibWeb/SVG/SVGElement.h> | ||||
| #include <LibWeb/SVG/SVGGradientElement.h> | ||||
| #include <LibWeb/SVG/TagNames.h> | ||||
| #include <LibWeb/SVG/ViewBox.h> | ||||
| 
 | ||||
| namespace Web::SVG { | ||||
| 
 | ||||
|  | @ -45,6 +46,8 @@ public: | |||
|     Optional<Gfx::PaintStyle const&> fill_paint_style(SVGPaintContext const&) const; | ||||
|     Optional<Gfx::PaintStyle const&> stroke_paint_style(SVGPaintContext const&) const; | ||||
| 
 | ||||
|     Optional<ViewBox> view_box() const; | ||||
| 
 | ||||
| protected: | ||||
|     SVGGraphicsElement(DOM::Document&, DOM::QualifiedName); | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h> | ||||
| #include <LibWeb/CSS/StyleValues/OverflowStyleValue.h> | ||||
| #include <LibWeb/DOM/ShadowRoot.h> | ||||
| #include <LibWeb/SVG/AttributeNames.h> | ||||
| #include <LibWeb/SVG/SVGSymbolElement.h> | ||||
| #include <LibWeb/SVG/SVGUseElement.h> | ||||
| 
 | ||||
|  | @ -44,8 +45,12 @@ void SVGSymbolElement::apply_presentational_hints(CSS::StyleProperties& style) c | |||
|         // and this declaration must have importance over any other CSS rule or presentation attribute.
 | ||||
|         style.set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::None)).release_value_but_fixme_should_propagate_errors()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|     // TODO: Parse viewBox and apply it in SVGGraphicsElement/SVGGraphicsPaintable
 | ||||
| void SVGSymbolElement::attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) | ||||
| { | ||||
|     if (name.equals_ignoring_ascii_case(SVG::AttributeNames::viewBox)) | ||||
|         m_view_box = try_parse_view_box(value); | ||||
| } | ||||
| 
 | ||||
| bool SVGSymbolElement::is_direct_child_of_use_shadow_tree() const | ||||
|  |  | |||
|  | @ -18,12 +18,18 @@ public: | |||
| 
 | ||||
|     void apply_presentational_hints(CSS::StyleProperties& style) const override; | ||||
| 
 | ||||
|     Optional<ViewBox> view_box() const { return m_view_box; } | ||||
| 
 | ||||
| private: | ||||
|     SVGSymbolElement(DOM::Document&, DOM::QualifiedName); | ||||
| 
 | ||||
|     virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override; | ||||
| 
 | ||||
|     bool is_direct_child_of_use_shadow_tree() const; | ||||
| 
 | ||||
|     virtual void attribute_changed(DeprecatedFlyString const& name, DeprecatedString const& value) override; | ||||
| 
 | ||||
|     Optional<ViewBox> m_view_box; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tom
						Tom