| 
									
										
										
										
											2021-09-17 23:12:16 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2022-02-16 16:32:18 +00:00
										 |  |  |  * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> | 
					
						
							| 
									
										
										
										
											2022-02-27 21:00:04 +01:00
										 |  |  |  * Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-09-17 23:12:16 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <AK/Format.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Layout/SVGFormattingContext.h>
 | 
					
						
							| 
									
										
										
										
											2022-02-11 12:37:22 +00:00
										 |  |  | #include <LibWeb/Layout/SVGGeometryBox.h>
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:00:04 +01:00
										 |  |  | #include <LibWeb/SVG/SVGSVGElement.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-17 23:12:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Web::Layout { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  | SVGFormattingContext::SVGFormattingContext(FormattingState& state, Box const& box, FormattingContext* parent) | 
					
						
							| 
									
										
										
										
											2022-02-19 20:13:47 +01:00
										 |  |  |     : FormattingContext(Type::SVG, state, box, parent) | 
					
						
							| 
									
										
										
										
											2021-09-17 23:12:16 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-14 13:21:51 -06:00
										 |  |  | SVGFormattingContext::~SVGFormattingContext() = default; | 
					
						
							| 
									
										
										
										
											2021-09-17 23:12:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  | void SVGFormattingContext::run(Box const& box, LayoutMode) | 
					
						
							| 
									
										
										
										
											2021-09-17 23:12:16 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-27 21:00:04 +01:00
										 |  |  |     box.for_each_in_subtree_of_type<SVGBox>([&](SVGBox const& descendant) { | 
					
						
							| 
									
										
										
										
											2022-02-11 12:37:22 +00:00
										 |  |  |         if (is<SVGGeometryBox>(descendant)) { | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |             auto const& geometry_box = static_cast<SVGGeometryBox const&>(descendant); | 
					
						
							| 
									
										
										
										
											2022-02-27 21:00:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             auto& geometry_box_state = m_state.get_mutable(geometry_box); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             auto& dom_node = const_cast<SVGGeometryBox&>(geometry_box).dom_node(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             SVG::SVGSVGElement* svg_element = dom_node.first_ancestor_of_type<SVG::SVGSVGElement>(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 20:03:52 -07:00
										 |  |  |             if (svg_element->has_attribute(HTML::AttributeNames::width) && svg_element->has_attribute(HTML::AttributeNames::height)) { | 
					
						
							| 
									
										
										
										
											2022-02-27 21:00:04 +01:00
										 |  |  |                 geometry_box_state.offset = { 0, 0 }; | 
					
						
							|  |  |  |                 auto& layout_node = static_cast<Layout::Node&>(*(svg_element->layout_node())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // FIXME: Allow for relative lengths here
 | 
					
						
							|  |  |  |                 geometry_box_state.content_width = layout_node.computed_values().width().value().resolved(layout_node, { 0, CSS::Length::Type::Px }).to_px(layout_node); | 
					
						
							|  |  |  |                 geometry_box_state.content_height = layout_node.computed_values().height().value().resolved(layout_node, { 0, CSS::Length::Type::Px }).to_px(layout_node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return IterationDecision::Continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // FIXME: Allow for one of {width, height} to not be specified}
 | 
					
						
							|  |  |  |             if (svg_element->has_attribute(HTML::AttributeNames::width)) { | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (svg_element->has_attribute(HTML::AttributeNames::height)) { | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             auto& path = dom_node.get_path(); | 
					
						
							|  |  |  |             auto path_bounding_box = path.bounding_box(); | 
					
						
							| 
									
										
										
										
											2022-02-16 15:17:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Stroke increases the path's size by stroke_width/2 per side.
 | 
					
						
							|  |  |  |             auto stroke_width = geometry_box.dom_node().stroke_width().value_or(0); | 
					
						
							| 
									
										
										
										
											2022-02-27 21:00:04 +01:00
										 |  |  |             path_bounding_box.inflate(stroke_width, stroke_width); | 
					
						
							| 
									
										
										
										
											2022-02-16 15:17:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:00:04 +01:00
										 |  |  |             auto& maybe_view_box = svg_element->view_box(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (maybe_view_box.has_value()) { | 
					
						
							|  |  |  |                 auto view_box = maybe_view_box.value(); | 
					
						
							|  |  |  |                 Gfx::FloatPoint viewbox_offset = { view_box.min_x, view_box.min_y }; | 
					
						
							|  |  |  |                 geometry_box_state.offset = path_bounding_box.top_left() + viewbox_offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 geometry_box_state.content_width = view_box.width; | 
					
						
							|  |  |  |                 geometry_box_state.content_height = view_box.height; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return IterationDecision::Continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             geometry_box_state.offset = path_bounding_box.top_left(); | 
					
						
							|  |  |  |             geometry_box_state.content_width = path_bounding_box.width(); | 
					
						
							|  |  |  |             geometry_box_state.content_height = path_bounding_box.height(); | 
					
						
							| 
									
										
										
										
											2021-09-18 00:06:16 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return IterationDecision::Continue; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2021-09-17 23:12:16 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |