mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 06:12:43 +00:00 
			
		
		
		
	LibWeb: Support preserveAspectRatio=none for SVGs
				
					
				
			This is very easy now all transforms are computed during layout.
This commit is contained in:
		
							parent
							
								
									190a8f948e
								
							
						
					
					
						commit
						05f42efc06
					
				
					 2 changed files with 18 additions and 10 deletions
				
			
		|  | @ -46,7 +46,8 @@ CSSPixels SVGFormattingContext::automatic_content_height() const | |||
| 
 | ||||
| struct ViewBoxTransform { | ||||
|     CSSPixelPoint offset; | ||||
|     double scale_factor; | ||||
|     double scale_factor_x; | ||||
|     double scale_factor_y; | ||||
| }; | ||||
| 
 | ||||
| // https://svgwg.org/svg2-draft/coords.html#PreserveAspectRatioAttribute
 | ||||
|  | @ -55,20 +56,27 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio | |||
| { | ||||
|     ViewBoxTransform viewbox_transform {}; | ||||
| 
 | ||||
|     if (preserve_aspect_ratio.align == SVG::PreserveAspectRatio::Align::None) { | ||||
|         viewbox_transform.scale_factor_x = viewbox_scale.width(); | ||||
|         viewbox_transform.scale_factor_y = viewbox_scale.height(); | ||||
|         viewbox_transform.offset = {}; | ||||
|         return viewbox_transform; | ||||
|     } | ||||
| 
 | ||||
|     switch (preserve_aspect_ratio.meet_or_slice) { | ||||
|     case SVG::PreserveAspectRatio::MeetOrSlice::Meet: | ||||
|         // meet (the default) - Scale the graphic such that:
 | ||||
|         // - aspect ratio is preserved
 | ||||
|         // - the entire ‘viewBox’ is visible within the SVG viewport
 | ||||
|         // - the ‘viewBox’ is scaled up as much as possible, while still meeting the other criteria
 | ||||
|         viewbox_transform.scale_factor = min(viewbox_scale.width(), viewbox_scale.height()); | ||||
|         viewbox_transform.scale_factor_x = viewbox_transform.scale_factor_y = min(viewbox_scale.width(), viewbox_scale.height()); | ||||
|         break; | ||||
|     case SVG::PreserveAspectRatio::MeetOrSlice::Slice: | ||||
|         // slice - Scale the graphic such that:
 | ||||
|         // aspect ratio is preserved
 | ||||
|         // the entire SVG viewport is covered by the ‘viewBox’
 | ||||
|         // the ‘viewBox’ is scaled down as much as possible, while still meeting the other criteria
 | ||||
|         viewbox_transform.scale_factor = max(viewbox_scale.width(), viewbox_scale.height()); | ||||
|         viewbox_transform.scale_factor_x = viewbox_transform.scale_factor_y = max(viewbox_scale.width(), viewbox_scale.height()); | ||||
|         break; | ||||
|     default: | ||||
|         VERIFY_NOT_REACHED(); | ||||
|  | @ -93,13 +101,13 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio | |||
|         case SVG::PreserveAspectRatio::Align::xMidYMid: | ||||
|         case SVG::PreserveAspectRatio::Align::xMidYMax: | ||||
|             // Align the midpoint X value of the element's ‘viewBox’ with the midpoint X value of the SVG viewport.
 | ||||
|             viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor)) / 2, 0); | ||||
|             viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor_x)) / 2, 0); | ||||
|             break; | ||||
|         case SVG::PreserveAspectRatio::Align::xMaxYMin: | ||||
|         case SVG::PreserveAspectRatio::Align::xMaxYMid: | ||||
|         case SVG::PreserveAspectRatio::Align::xMaxYMax: | ||||
|             // Align the <min-x>+<width> of the element's ‘viewBox’ with the maximum X value of the SVG viewport.
 | ||||
|             viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor)), 0); | ||||
|             viewbox_transform.offset.translate_by((svg_box_state.content_width() - CSSPixels::nearest_value_for(view_box.width * viewbox_transform.scale_factor_x)), 0); | ||||
|             break; | ||||
|         default: | ||||
|             VERIFY_NOT_REACHED(); | ||||
|  | @ -124,13 +132,13 @@ static ViewBoxTransform scale_and_align_viewbox_content(SVG::PreserveAspectRatio | |||
|         case SVG::PreserveAspectRatio::Align::xMidYMid: | ||||
|         case SVG::PreserveAspectRatio::Align::xMaxYMid: | ||||
|             // Align the midpoint Y value of the element's ‘viewBox’ with the midpoint Y value of the SVG viewport.
 | ||||
|             viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor)) / 2); | ||||
|             viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor_y)) / 2); | ||||
|             break; | ||||
|         case SVG::PreserveAspectRatio::Align::xMinYMax: | ||||
|         case SVG::PreserveAspectRatio::Align::xMidYMax: | ||||
|         case SVG::PreserveAspectRatio::Align::xMaxYMax: | ||||
|             // Align the <min-y>+<height> of the element's ‘viewBox’ with the maximum Y value of the SVG viewport.
 | ||||
|             viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor))); | ||||
|             viewbox_transform.offset.translate_by(0, (svg_box_state.content_height() - CSSPixels::nearest_value_for(view_box.height * viewbox_transform.scale_factor_y))); | ||||
|             break; | ||||
|         default: | ||||
|             VERIFY_NOT_REACHED(); | ||||
|  | @ -232,7 +240,7 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available | |||
|         CSSPixelPoint offset = viewbox_offset_and_scale.offset; | ||||
|         return Gfx::AffineTransform { m_parent_viewbox_transform }.multiply(Gfx::AffineTransform {} | ||||
|                                                                                 .translate(offset.to_type<float>()) | ||||
|                                                                                 .scale(viewbox_offset_and_scale.scale_factor, viewbox_offset_and_scale.scale_factor) | ||||
|                                                                                 .scale(viewbox_offset_and_scale.scale_factor_x, viewbox_offset_and_scale.scale_factor_y) | ||||
|                                                                                 .translate({ -viewbox->min_x, -viewbox->min_y })); | ||||
|     }(); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 MacDue
						MacDue