2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								/*
  
						 
					
						
							
								
									
										
										
										
											2024-10-04 13:19:50 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								 *  Copyright  ( c )  2020 - 2022 ,  Andreas  Kling  < andreas @ ladybird . org > 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  Copyright  ( c )  2022 ,  Sam  Atkins  < atkinssj @ serenityos . org > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  SPDX - License - Identifier :  BSD - 2 - Clause 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-18 20:29:09 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								# include  <LibGfx/Vector2.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# include  <LibWeb/HTML/Canvas/CanvasPath.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								namespace  Web : : HTML  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-17 00:17:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								Gfx : : AffineTransform  CanvasPath : : active_transform ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( m_canvas_state . has_value ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  m_canvas_state - > drawing_state ( ) . transform ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:21:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasPath : : ensure_subpath ( float  x ,  float  y )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( m_path . is_empty ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        m_path . move_to ( Gfx : : FloatPoint  {  x ,  y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:21:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasPath : : close_path ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . close ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:20:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-moveto
  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasPath : : move_to ( float  x ,  float  y )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:20:26 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 1. If either of the arguments are infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! isfinite ( x )  | |  ! isfinite ( y ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 2. Create a new subpath with the specified point as its first (and only) point.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . move_to ( Gfx : : FloatPoint  {  x ,  y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:21:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-lineto
  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasPath : : line_to ( float  x ,  float  y )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:21:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 1. If either of the arguments are infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! isfinite ( x )  | |  ! isfinite ( y ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( m_path . is_empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // 2. If the object's path has no subpaths, then ensure there is a subpath for (x, y).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        ensure_subpath ( x ,  y ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // 3. Otherwise, connect the last point in the subpath to the given point (x, y) using a straight line,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // and then add the given point (x, y) to the subpath.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        m_path . line_to ( Gfx : : FloatPoint  {  x ,  y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:21:47 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:26:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-quadraticcurveto
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasPath : : quadratic_curve_to ( float  cpx ,  float  cpy ,  float  x ,  float  y )  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:26:28 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 1. If any of the arguments are infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! isfinite ( cpx )  | |  ! isfinite ( cpy )  | |  ! isfinite ( x )  | |  ! isfinite ( y ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 2. Ensure there is a subpath for (cpx, cpy)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    ensure_subpath ( cpx ,  cpy ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 3. Connect the last point in the subpath to the given point (x, y) using a quadratic Bézier curve with control point (cpx, cpy).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 4. Add the given point (x, y) to the subpath.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . quadratic_bezier_curve_to ( Gfx : : FloatPoint  {  cpx ,  cpy  } ,  Gfx : : FloatPoint  {  x ,  y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:32:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-beziercurveto
  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasPath : : bezier_curve_to ( double  cp1x ,  double  cp1y ,  double  cp2x ,  double  cp2y ,  double  x ,  double  y )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:32:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 1. If any of the arguments are infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! isfinite ( cp1x )  | |  ! isfinite ( cp1y )  | |  ! isfinite ( cp2x )  | |  ! isfinite ( cp2y )  | |  ! isfinite ( x )  | |  ! isfinite ( y ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 2. Ensure there is a subpath for (cp1x, cp1y)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    ensure_subpath ( cp1x ,  cp1y ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-07 10:46:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 3. Connect the last point in the subpath to the given point (x, y) using a cubic Bézier curve with control points (cp1x, cp1y) and (cp2x, cp2y).
 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:32:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 4. Add the point (x, y) to the subpath.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-17 00:17:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . cubic_bezier_curve_to ( 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        Gfx : : FloatPoint  {  cp1x ,  cp1y  } ,  Gfx : : FloatPoint  {  cp2x ,  cp2y  } ,  Gfx : : FloatPoint  {  x ,  y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-25 17:03:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								WebIDL : : ExceptionOr < void >  CanvasPath : : arc ( float  x ,  float  y ,  float  radius ,  float  start_angle ,  float  end_angle ,  bool  counter_clockwise )  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( radius  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 16:03:01 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        return  WebIDL : : IndexSizeError : : create ( m_self - > realm ( ) ,  MUST ( String : : formatted ( " The radius provided ({}) is negative. " ,  radius ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  ellipse ( x ,  y ,  radius ,  radius ,  0 ,  start_angle ,  end_angle ,  counter_clockwise ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:36:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-ellipse
  
						 
					
						
							
								
									
										
										
										
											2022-09-25 17:03:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								WebIDL : : ExceptionOr < void >  CanvasPath : : ellipse ( float  x ,  float  y ,  float  radius_x ,  float  radius_y ,  float  rotation ,  float  start_angle ,  float  end_angle ,  bool  counter_clockwise )  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:36:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 1. If any of the arguments are infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! isfinite ( x )  | |  ! isfinite ( y )  | |  ! isfinite ( radius_x )  | |  ! isfinite ( radius_y )  | |  ! isfinite ( rotation )  | |  ! isfinite ( start_angle )  | |  ! isfinite ( end_angle ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 2. If either radiusX or radiusY are negative, then throw an "IndexSizeError" DOMException.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( radius_x  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 16:03:01 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        return  WebIDL : : IndexSizeError : : create ( m_self - > realm ( ) ,  MUST ( String : : formatted ( " The major-axis radius provided ({}) is negative. " ,  radius_x ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( radius_y  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 16:03:01 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        return  WebIDL : : IndexSizeError : : create ( m_self - > realm ( ) ,  MUST ( String : : formatted ( " The minor-axis radius provided ({}) is negative. " ,  radius_y ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-07 10:50:27 +10:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
										 
							
							
								    // "If counterclockwise is false and endAngle −  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								    // or, if counterclockwise is true and startAngle −  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // then the arc is the whole circumference of this ellipse"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Also draw the full ellipse if making a non-zero whole number of turns.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-20 12:06:26 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( constexpr  float  tau  =  M_PI  *  2 ;  ( ! counter_clockwise  & &  ( end_angle  -  start_angle )  > =  tau ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-07 10:50:27 +10:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        | |  ( counter_clockwise  & &  ( start_angle  -  end_angle )  > =  tau ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        | |  ( start_angle  ! =  end_angle  & &  fmodf ( start_angle  -  end_angle ,  tau )  = =  0 ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        start_angle  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-27 20:18:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        // FIXME: elliptical_arc_to() incorrectly handles the case where the start/end points are very close.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // So we slightly fudge the numbers here to correct for that.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        end_angle  =  tau  *  0.9999f ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-07 10:50:27 +10:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        counter_clockwise  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        start_angle  =  fmodf ( start_angle ,  tau ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        end_angle  =  fmodf ( end_angle ,  tau ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Then, figure out where the ends of the arc are.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // To do so, we can pretend that the center of this ellipse is at (0, 0),
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // and the whole coordinate system is rotated `rotation` radians around the x axis, centered on `center`.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // The sign of the resulting relative positions is just whether our angle is on one of the left quadrants.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-27 20:18:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    float  sin_rotation ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    float  cos_rotation ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    AK : : sincos ( rotation ,  sin_rotation ,  cos_rotation ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  resolve_point_with_angle  =  [ & ] ( float  angle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  tan_relative  =  tanf ( angle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  tan2  =  tan_relative  *  tan_relative ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  ab  =  radius_x  *  radius_y ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  a2  =  radius_x  *  radius_x ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  b2  =  radius_y  *  radius_y ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  sqrt  =  sqrtf ( b2  +  a2  *  tan2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  relative_x_position  =  ab  /  sqrt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  relative_y_position  =  ab  *  tan_relative  /  sqrt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // Make sure to set the correct sign
 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-27 20:18:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        // -1 if 0 ≤ θ < 90° or 270°< θ ≤ 360°
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        //  1 if 90° < θ< 270°
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        float  sn  =  cosf ( angle )  > =  0  ?  1  :  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        relative_x_position  * =  sn ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        relative_y_position  * =  sn ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // Now rotate it (back) around the center point by 'rotation' radians, then move it back to our actual origin.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  relative_rotated_x_position  =  relative_x_position  *  cos_rotation  -  relative_y_position  *  sin_rotation ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  relative_rotated_y_position  =  relative_x_position  *  sin_rotation  +  relative_y_position  *  cos_rotation ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  Gfx : : FloatPoint  {  relative_rotated_x_position  +  x ,  relative_rotated_y_position  +  y  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  start_point  =  resolve_point_with_angle ( start_angle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  end_point  =  resolve_point_with_angle ( end_angle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-07 10:50:27 +10:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    float  delta_theta ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( counter_clockwise )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        delta_theta  =  start_angle  -  end_angle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        delta_theta  =  end_angle  -  start_angle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-24 15:17:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( delta_theta  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        delta_theta  + =  AK : : Pi < float >  *  2 ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:36:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 3. If canvasPath's path has any subpaths, then add a straight line from the last point in the subpath to the start point of the arc.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! m_path . is_empty ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        m_path . line_to ( start_point ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:36:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    else 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        m_path . move_to ( start_point ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:36:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 4. Add the start and end points of the arc to the subpath, and connect them with an arc.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-17 00:17:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . elliptical_arc_to ( 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        Gfx : : FloatPoint  {  end_point  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        Gfx : : FloatSize  {  radius_x ,  radius_y  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        rotation , 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-17 00:17:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        delta_theta  >  AK : : Pi < float > ,  ! counter_clockwise ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-17 05:15:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-arcto
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								WebIDL : : ExceptionOr < void >  CanvasPath : : arc_to ( double  x1 ,  double  y1 ,  double  x2 ,  double  y2 ,  double  radius )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 1. If any of the arguments are infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! isfinite ( x1 )  | |  ! isfinite ( y1 )  | |  ! isfinite ( x2 )  | |  ! isfinite ( y2 )  | |  ! isfinite ( radius ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 2. Ensure there is a subpath for (x1, y1).
 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:38:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    ensure_subpath ( x1 ,  y1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-17 05:15:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 3. If radius is negative, then throw an "IndexSizeError" DOMException.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( radius  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  WebIDL : : IndexSizeError : : create ( m_self - > realm ( ) ,  MUST ( String : : formatted ( " The radius provided ({}) is negative. " ,  radius ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:38:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    auto  transform  =  active_transform ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-17 05:15:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 4. Let the point (x0, y0) be the last point in the subpath,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //    transformed by the inverse of the current transformation matrix
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //    (so that it is in the same coordinate system as the points passed to the method).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Point (x0, y0)
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    auto  p0  =  transform . inverse ( ) . value_or ( Gfx : : AffineTransform ( ) ) . map ( m_path . last_point ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-17 05:15:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // Point (x1, y1)
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    auto  p1  =  Gfx : : FloatPoint  {  x1 ,  y1  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-17 05:15:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // Point (x2, y2)
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    auto  p2  =  Gfx : : FloatPoint  {  x2 ,  y2  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-17 05:15:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 5. If the point (x0, y0) is equal to the point (x1, y1),
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //    or if the point (x1, y1) is equal to the point (x2, y2),
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //    or if radius is zero, then add the point (x1, y1) to the subpath,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //    and connect that point to the previous point (x0, y0) by a straight line.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( p0  = =  p1  | |  p1  = =  p2  | |  radius  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        m_path . line_to ( p1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  v1  =  Gfx : : FloatVector2  {  p0 . x ( )  -  p1 . x ( ) ,  p0 . y ( )  -  p1 . y ( )  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  v2  =  Gfx : : FloatVector2  {  p2 . x ( )  -  p1 . x ( ) ,  p2 . y ( )  -  p1 . y ( )  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  cos_theta  =  v1 . dot ( v2 )  /  ( v1 . length ( )  *  v2 . length ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 6. Otherwise, if the points (x0, y0), (x1, y1), and (x2, y2) all lie on a single straight line,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //    then add the point (x1, y1) to the subpath,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //    and connect that point to the previous point (x0, y0) by a straight line.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( - 1  = =  cos_theta  | |  1  = =  cos_theta )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        m_path . line_to ( p1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 7. Otherwise, let The Arc be the shortest arc given by circumference of the circle that has radius radius,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // and that has one point tangent to the half-infinite line that crosses the point (x0, y0) and ends at the point (x1, y1),
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // and that has a different point tangent to the half-infinite line that ends at the point (x1, y1) and crosses the point (x2, y2).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // The points at which this circle touches these two lines are called the start and end tangent points respectively.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  adjacent  =  radius  /  static_cast < double > ( tan ( acos ( cos_theta )  /  2 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  factor1  =  adjacent  /  static_cast < double > ( v1 . length ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  x3  =  static_cast < double > ( p1 . x ( ) )  +  factor1  *  static_cast < double > ( p0 . x ( )  -  p1 . x ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  y3  =  static_cast < double > ( p1 . y ( ) )  +  factor1  *  static_cast < double > ( p0 . y ( )  -  p1 . y ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  start_tangent  =  Gfx : : FloatPoint  {  x3 ,  y3  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  factor2  =  adjacent  /  static_cast < double > ( v2 . length ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  x4  =  static_cast < double > ( p1 . x ( ) )  +  factor2  *  static_cast < double > ( p2 . x ( )  -  p1 . x ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  y4  =  static_cast < double > ( p1 . y ( ) )  +  factor2  *  static_cast < double > ( p2 . y ( )  -  p1 . y ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  end_tangent  =  Gfx : : FloatPoint  {  x4 ,  y4  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Connect the point (x0, y0) to the start tangent point by a straight line, adding the start tangent point to the subpath.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . line_to ( start_tangent ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    bool  const  large_arc  =  false ;  // always small since tangent points define arc endpoints and lines meet at (x1, y1)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  cross_product  =  v1 . x ( )  *  v2 . y ( )  -  v1 . y ( )  *  v2 . x ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    bool  const  sweep  =  cross_product  <  0 ;  // right-hand rule, true means clockwise
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // and then connect the start tangent point to the end tangent point by The Arc, adding the end tangent point to the subpath.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . arc_to ( end_tangent ,  radius ,  large_arc ,  sweep ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-04 15:26:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-rect
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasPath : : rect ( double  x ,  double  y ,  double  w ,  double  h )  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-10-04 15:26:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    // 1. If any of the arguments are infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! isfinite ( x )  | |  ! isfinite ( y )  | |  ! isfinite ( w )  | |  ! isfinite ( h ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 2. Create a new subpath containing just the four points (x, y), (x+w, y), (x+w, y+h), (x, y+h), in that order, with those four points connected by straight lines.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . move_to ( Gfx : : FloatPoint  {  x ,  y  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . line_to ( Gfx : : FloatPoint  {  x  +  w ,  y  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . line_to ( Gfx : : FloatPoint  {  x  +  w ,  y  +  h  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . line_to ( Gfx : : FloatPoint  {  x ,  y  +  h  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-04 15:26:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 3. Mark the subpath as closed.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . close ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-04 15:26:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 4. Create a new subpath with the point (x, y) as the only point in the subpath.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . move_to ( Gfx : : FloatPoint  {  x ,  y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-roundrect
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								WebIDL : : ExceptionOr < void >  CanvasPath : : round_rect ( double  x ,  double  y ,  double  w ,  double  h ,  Variant < double ,  Geometry : : DOMPointInit ,  Vector < Variant < double ,  Geometry : : DOMPointInit > > >  radii )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    using  Radius  =  Variant < double ,  Geometry : : DOMPointInit > ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 1. If any of x, y, w, or h are infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! isfinite ( x )  | |  ! isfinite ( y )  | |  ! isfinite ( w )  | |  ! isfinite ( h ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 2. If radii is an unrestricted double or DOMPointInit, then set radii to « radii ».
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( radii . has < double > ( )  | |  radii . has < Geometry : : DOMPointInit > ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        Vector < Radius >  radii_list ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( radii . has < double > ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            radii_list . append ( radii . get < double > ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            radii_list . append ( radii . get < Geometry : : DOMPointInit > ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        radii  =  radii_list ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 3. If radii is not a list of size one, two, three, or four, then throw a RangeError.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( radii . get < Vector < Radius > > ( ) . is_empty ( )  | |  radii . get < Vector < Radius > > ( ) . size ( )  >  4 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  WebIDL : : SimpleException  {  WebIDL : : SimpleExceptionType : : RangeError ,  " roundRect: Can have between 1 and 4 radii " sv  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 4. Let normalizedRadii be an empty list.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Vector < Geometry : : DOMPointInit >  normalized_radii ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 5. For each radius of radii:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    for  ( auto  const &  radius  :  radii . get < Vector < Radius > > ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // 5.1. If radius is a DOMPointInit:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( radius . has < Geometry : : DOMPointInit > ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  const &  radius_as_dom_point  =  radius . get < Geometry : : DOMPointInit > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            // 5.1.1. If radius["x"] or radius["y"] is infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if  ( ! isfinite ( radius_as_dom_point . x )  | |  ! isfinite ( radius_as_dom_point . y ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            // 5.1.2. If radius["x"] or radius["y"] is negative, then throw a RangeError.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if  ( radius_as_dom_point . x  <  0  | |  radius_as_dom_point . y  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                return  WebIDL : : SimpleException  {  WebIDL : : SimpleExceptionType : : RangeError ,  " roundRect: Radius can't be negative " sv  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            // 5.1.3. Otherwise, append radius to normalizedRadii.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            normalized_radii . append ( radius_as_dom_point ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // 5.2. If radius is a unrestricted double:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( radius . has < double > ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  radius_as_double  =  radius . get < double > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            // 5.2.1. If radius is infinite or NaN, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if  ( ! isfinite ( radius_as_double ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            // 5.2.2. If radius is negative, then throw a RangeError.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if  ( radius_as_double  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                return  WebIDL : : SimpleException  {  WebIDL : : SimpleExceptionType : : RangeError ,  " roundRect: Radius can't be negative " sv  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            // 5.2.3. Otherwise append «[ "x" → radius, "y" → radius ]» to normalizedRadii.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            normalized_radii . append ( Geometry : : DOMPointInit  {  radius_as_double ,  radius_as_double  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 6. Let upperLeft, upperRight, lowerRight, and lowerLeft be null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Geometry : : DOMPointInit  upper_left  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Geometry : : DOMPointInit  upper_right  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Geometry : : DOMPointInit  lower_right  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Geometry : : DOMPointInit  lower_left  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 7. If normalizedRadii's size is 4, then set upperLeft to normalizedRadii[0], set upperRight to normalizedRadii[1], set lowerRight to normalizedRadii[2], and set lowerLeft to normalizedRadii[3].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( normalized_radii . size ( )  = =  4 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_left  =  normalized_radii . at ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_right  =  normalized_radii . at ( 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        lower_right  =  normalized_radii . at ( 2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        lower_left  =  normalized_radii . at ( 3 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 8. If normalizedRadii's size is 3, then set upperLeft to normalizedRadii[0], set upperRight and lowerLeft to normalizedRadii[1], and set lowerRight to normalizedRadii[2].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( normalized_radii . size ( )  = =  3 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_left  =  normalized_radii . at ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_right  =  lower_left  =  normalized_radii . at ( 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        lower_right  =  normalized_radii . at ( 2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 9. If normalizedRadii's size is 2, then set upperLeft and lowerRight to normalizedRadii[0] and set upperRight and lowerLeft to normalizedRadii[1].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( normalized_radii . size ( )  = =  2 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_left  =  lower_right  =  normalized_radii . at ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_right  =  lower_left  =  normalized_radii . at ( 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 10. If normalizedRadii's size is 1, then set upperLeft, upperRight, lowerRight, and lowerLeft to normalizedRadii[0].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( normalized_radii . size ( )  = =  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_left  =  upper_right  =  lower_right  =  lower_left  =  normalized_radii . at ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 11. Corner curves must not overlap. Scale all radii to prevent this:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 11.1. Let top be upperLeft["x"] + upperRight["x"].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    double  top  =  upper_left . x  +  upper_right . x ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 11.2. Let right be upperRight["y"] + lowerRight["y"].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    double  right  =  upper_right . y  +  lower_right . y ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 11.3. Let bottom be lowerRight["x"] + lowerLeft["x"].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    double  bottom  =  lower_right . x  +  lower_left . x ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 11.4. Let left be upperLeft["y"] + lowerLeft["y"].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    double  left  =  upper_left . y  +  lower_left . y ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 11.5. Let scale be the minimum value of the ratios w / top, h / right, w / bottom, h / left.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    double  scale  =  AK : : min ( AK : : min ( w  /  top ,  h  /  right ) ,  AK : : min ( w  /  bottom ,  h  /  left ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 11.6. If scale is less than 1, then set the x and y members of upperLeft, upperRight, lowerLeft, and lowerRight to their current values multiplied by scale.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( scale  <  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_left . x  * =  scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_left . y  * =  scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_right . x  * =  scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        upper_right . y  * =  scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        lower_left . x  * =  scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        lower_left . y  * =  scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        lower_right . x  * =  scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        lower_right . y  * =  scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 12. Create a new subpath:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    bool  large_arc  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    bool  sweep  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 12.1. Move to the point (x + upperLeft["x"], y).
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . move_to ( Gfx : : FloatPoint  {  x  +  upper_left . x ,  y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								    // 12.2. Draw a straight line to the point (x + w −  
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . line_to ( Gfx : : FloatPoint  {  x  +  w  -  upper_right . x ,  y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 12.3. Draw an arc to the point (x + w, y + upperRight["y"]).
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . elliptical_arc_to ( Gfx : : FloatPoint  {  x  +  w ,  y  +  upper_right . y  } ,  {  upper_right . x ,  upper_right . y  } ,  0 ,  large_arc ,  sweep ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								    // 12.4. Draw a straight line to the point (x + w, y + h −  
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . line_to ( Gfx : : FloatPoint  {  x  +  w ,  y  +  h  -  lower_right . y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								    // 12.5. Draw an arc to the point (x + w −  
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . elliptical_arc_to ( Gfx : : FloatPoint  {  x  +  w  -  lower_right . x ,  y  +  h  } ,  {  lower_right . x ,  lower_right . y  } ,  0 ,  large_arc ,  sweep ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 12.6. Draw a straight line to the point (x + lowerLeft["x"], y + h).
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . line_to ( Gfx : : FloatPoint  {  x  +  lower_left . x ,  y  +  h  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								    // 12.7. Draw an arc to the point (x, y + h −  
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . elliptical_arc_to ( Gfx : : FloatPoint  {  x ,  y  +  h  -  lower_left . y  } ,  {  lower_left . x ,  lower_left . y  } ,  0 ,  large_arc ,  sweep ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 12.8. Draw a straight line to the point (x, y + upperLeft["y"]).
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . line_to ( Gfx : : FloatPoint  {  x ,  y  +  upper_left . y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 12.9. Draw an arc to the point (x + upperLeft["x"], y).
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . elliptical_arc_to ( Gfx : : FloatPoint  {  x  +  upper_left . x ,  y  } ,  {  upper_left . x ,  upper_left . y  } ,  0 ,  large_arc ,  sweep ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 13. Mark the subpath as closed.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . close ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 14. Create a new subpath with the point (x, y) as the only point in the subpath.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    m_path . move_to ( Gfx : : FloatPoint  {  x ,  y  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-16 17:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}