2020-04-06 11:09:01 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
									
										
										
										
											2022-02-03 20:01:19 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  ( c )  2020 - 2022 ,  Andreas  Kling  < kling @ serenityos . org > 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  ( c )  2021 - 2022 ,  Linus  Groh  < linusg @ serenityos . org > 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-18 20:10:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  ( c )  2023 ,  MacDue  < macdue @ dueutil . tech > 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-06 11:09:01 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 01:24:48 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  SPDX - License - Identifier :  BSD - 2 - Clause 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-06 11:09:01 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  <AK/OwnPtr.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <LibGfx/Painter.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-04-07 16:52:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibGfx/Quad.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibGfx/Rect.h> 
  
						 
					
						
							
								
									
										
										
										
											2023-02-22 11:48:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibUnicode/Segmentation.h> 
  
						 
					
						
							
								
									
										
										
										
											2023-03-29 18:35:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/Bindings/CanvasRenderingContext2DPrototype.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-09-25 16:38:21 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/Bindings/Intrinsics.h> 
  
						 
					
						
							
								
									
										
										
										
											2020-07-26 15:08:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/HTML/CanvasRenderingContext2D.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <LibWeb/HTML/HTMLCanvasElement.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <LibWeb/HTML/HTMLImageElement.h> 
  
						 
					
						
							
								
									
										
										
										
											2024-04-05 09:15:45 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/HTML/ImageBitmap.h> 
  
						 
					
						
							
								
									
										
										
										
											2020-07-26 15:08:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/HTML/ImageData.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:50:23 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/HTML/Path2D.h> 
  
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/HTML/TextMetrics.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-10-01 18:14:32 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/Infra/CharacterTypes.h> 
  
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/Layout/TextNode.h> 
  
						 
					
						
							
								
									
										
										
										
											2024-01-14 13:46:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/Painting/Paintable.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-09-17 21:25:50 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/Platform/FontPlugin.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-09-25 17:03:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/WebIDL/ExceptionOr.h> 
  
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-28 18:20:36 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								namespace  Web : : HTML  {  
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-19 19:47:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								JS_DEFINE_ALLOCATOR ( CanvasRenderingContext2D ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-13 13:05:26 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								JS : : NonnullGCPtr < CanvasRenderingContext2D >  CanvasRenderingContext2D : : create ( JS : : Realm &  realm ,  HTMLCanvasElement &  element )  
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-08-13 13:05:26 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  realm . heap ( ) . allocate < CanvasRenderingContext2D > ( realm ,  realm ,  element ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 15:53:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-25 16:38:21 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								CanvasRenderingContext2D : : CanvasRenderingContext2D ( JS : : Realm &  realm ,  HTMLCanvasElement &  element )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  PlatformObject ( realm ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-17 00:17:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ,  CanvasPath ( static_cast < Bindings : : PlatformObject & > ( * this ) ,  * this ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 15:53:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ,  m_element ( element ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-14 13:21:51 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								CanvasRenderingContext2D : : ~ CanvasRenderingContext2D ( )  =  default ;  
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 08:41:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : initialize ( JS : : Realm &  realm )  
						 
					
						
							
								
									
										
										
										
											2023-01-10 06:28:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-08-07 08:41:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    Base : : initialize ( realm ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-22 12:55:21 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    set_prototype ( & Bindings : : ensure_web_prototype < Bindings : : CanvasRenderingContext2DPrototype > ( realm ,  " CanvasRenderingContext2D " _fly_string ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 06:28:20 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 15:53:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : visit_edges ( Cell : : Visitor &  visitor )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Base : : visit_edges ( visitor ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-19 16:18:00 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    visitor . visit ( m_element ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 15:53:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-19 19:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								HTMLCanvasElement &  CanvasRenderingContext2D : : canvas_element ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-08-28 13:42:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  * m_element ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-19 19:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								HTMLCanvasElement  const &  CanvasRenderingContext2D : : canvas_element ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-08-28 13:42:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  * m_element ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-19 19:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-28 13:42:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								JS : : NonnullGCPtr < HTMLCanvasElement >  CanvasRenderingContext2D : : canvas_for_binding ( )  const  
						 
					
						
							
								
									
										
										
										
											2022-06-19 19:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-08-28 13:42:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  * m_element ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-19 19:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Gfx : : Path  CanvasRenderingContext2D : : rect_path ( float  x ,  float  y ,  float  width ,  float  height )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto &  drawing_state  =  this - > drawing_state ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  top_left  =  drawing_state . transform . map ( Gfx : : FloatPoint ( x ,  y ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  top_right  =  drawing_state . transform . map ( Gfx : : FloatPoint ( x  +  width ,  y ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  bottom_left  =  drawing_state . transform . map ( Gfx : : FloatPoint ( x ,  y  +  height ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  bottom_right  =  drawing_state . transform . map ( Gfx : : FloatPoint ( x  +  width ,  y  +  height ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Gfx : : Path  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . move_to ( top_left ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . line_to ( top_right ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . line_to ( bottom_right ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . line_to ( bottom_left ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . line_to ( top_left ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 11:22:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : fill_rect ( float  x ,  float  y ,  float  width ,  float  height )  
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:21:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  fill_internal ( rect_path ( x ,  y ,  width ,  height ) ,  Gfx : : WindingRule : : EvenOdd ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-22 21:15:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-15 19:40:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : clear_rect ( float  x ,  float  y ,  float  width ,  float  height )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    draw_clipped ( [ & ] ( auto &  painter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  rect  =  drawing_state ( ) . transform . map ( Gfx : : FloatRect ( x ,  y ,  width ,  height ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        painter . underlying_painter ( ) . clear_rect ( enclosing_int_rect ( rect ) ,  Color ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  rect ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-15 19:40:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-08 11:22:40 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : stroke_rect ( float  x ,  float  y ,  float  width ,  float  height )  
						 
					
						
							
								
									
										
										
										
											2020-04-07 01:09:17 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    stroke_internal ( rect_path ( x ,  y ,  width ,  height ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-07 01:09:17 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-05 20:54:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// 4.12.5.1.14 Drawing images, https://html.spec.whatwg.org/multipage/canvas.html#drawing-images
  
						 
					
						
							
								
									
										
										
										
											2022-09-25 17:03:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								WebIDL : : ExceptionOr < void >  CanvasRenderingContext2D : : draw_image_internal ( CanvasImageSource  const &  image ,  float  source_x ,  float  source_y ,  float  source_width ,  float  source_height ,  float  destination_x ,  float  destination_y ,  float  destination_width ,  float  destination_height )  
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:38:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 1. If any of the arguments are infinite or NaN, then return.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-05 20:54:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! isfinite ( source_x )  | |  ! isfinite ( source_y )  | |  ! isfinite ( source_width )  | |  ! isfinite ( source_height )  | |  ! isfinite ( destination_x )  | |  ! isfinite ( destination_y )  | |  ! isfinite ( destination_width )  | |  ! isfinite ( destination_height ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. Let usability be the result of checking the usability of image.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-22 12:35:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  usability  =  TRY ( check_usability_of_image ( image ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 3. If usability is bad, then return (without drawing anything).
 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-22 12:35:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( usability  = =  CanvasImageSourceUsability : : Bad ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-19 01:08:51 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  const *  bitmap  =  image . visit ( [ ] ( auto  const &  source )  - >  Gfx : : Bitmap  const *  {  return  source - > bitmap ( ) ;  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! bitmap ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:38:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 4. Establish the source and destination rectangles as follows:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    If not specified, the dw and dh arguments must default to the values of sw and sh, interpreted such that one CSS pixel in the image is treated as one unit in the output bitmap's coordinate space.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    If the sx, sy, sw, and sh arguments are omitted, then they must default to 0, 0, the image's intrinsic width in image pixels, and the image's intrinsic height in image pixels, respectively.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    If the image has no intrinsic dimensions, then the concrete object size must be used instead, as determined using the CSS "Concrete Object Size Resolution" algorithm, with the specified size having
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    neither a definite width nor height, nor any additional constraints, the object's intrinsic properties being those of the image argument, and the default object size being the size of the output bitmap.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    The source rectangle is the rectangle whose corners are the four points (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    The destination rectangle is the rectangle whose corners are the four points (dx, dy), (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh).
 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-05 20:54:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // NOTE: Implemented in drawImage() overloads
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    The source rectangle is the rectangle whose corners are the four points (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  source_rect  =  Gfx : : FloatRect  {  source_x ,  source_y ,  source_width ,  source_height  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    The destination rectangle is the rectangle whose corners are the four points (dx, dy), (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  destination_rect  =  Gfx : : FloatRect  {  destination_x ,  destination_y ,  destination_width ,  destination_height  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    When the source rectangle is outside the source image, the source rectangle must be clipped
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    to the source image and the destination rectangle must be clipped in the same proportion.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  clipped_source  =  source_rect . intersected ( bitmap - > rect ( ) . to_type < float > ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  clipped_destination  =  destination_rect ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( clipped_source  ! =  source_rect )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        clipped_destination . set_width ( clipped_destination . width ( )  *  ( clipped_source . width ( )  /  source_rect . width ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        clipped_destination . set_height ( clipped_destination . height ( )  *  ( clipped_source . height ( )  /  source_rect . height ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 5. If one of the sw or sh arguments is zero, then return. Nothing is painted.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-05 20:54:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( source_width  = =  0  | |  source_height  = =  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 6. Paint the region of the image argument specified by the source rectangle on the region of the rendering context's output bitmap specified by the destination rectangle, after applying the current transformation matrix to the destination rectangle.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    draw_clipped ( [ & ] ( auto &  painter )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:10:38 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        auto  scaling_mode  =  Gfx : : ScalingMode : : NearestNeighbor ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( drawing_state ( ) . image_smoothing_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // FIXME: Honor drawing_state().image_smoothing_quality
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:10:38 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            scaling_mode  =  Gfx : : ScalingMode : : BilinearBlend ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-07 16:52:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        painter . underlying_painter ( ) . draw_scaled_bitmap_with_transform ( destination_rect . to_rounded < int > ( ) ,  * bitmap ,  source_rect ,  drawing_state ( ) . transform ,  drawing_state ( ) . global_alpha ,  scaling_mode ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:38:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        // 7. If image is not origin-clean, then set the CanvasRenderingContext2D's origin-clean flag to false.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( image_is_not_origin_clean ( image ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            m_origin_clean  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  destination_rect ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:38:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:38:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-01 20:58:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : did_draw ( Gfx : : FloatRect  const & )  
						 
					
						
							
								
									
										
										
										
											2020-03-22 21:15:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Make use of the rect to reduce the invalidated area when possible.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-14 13:46:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! canvas_element ( ) . paintable ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-22 21:15:49 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-14 13:46:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    canvas_element ( ) . paintable ( ) - > set_needs_display ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-30 00:10:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Gfx : : Painter *  CanvasRenderingContext2D : : painter ( )  
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-06-19 19:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! canvas_element ( ) . bitmap ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ! canvas_element ( ) . create_bitmap ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-30 00:10:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_painter  =  make < Gfx : : Painter > ( * canvas_element ( ) . bitmap ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-15 12:12:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-30 00:10:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  m_painter . ptr ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2020-04-15 12:12:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-30 00:10:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Optional < Gfx : : AntiAliasingPainter >  CanvasRenderingContext2D : : antialiased_painter ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  painter  =  this - > painter ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( painter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Gfx : : AntiAliasingPainter  {  * painter  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Gfx : : Path  CanvasRenderingContext2D : : text_path ( StringView  text ,  float  x ,  float  y ,  Optional < double >  max_width )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( max_width . has_value ( )  & &  max_width . value ( )  < =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto &  drawing_state  =  this - > drawing_state ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  font  =  current_font ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Gfx : : Path  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . move_to ( {  x ,  y  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . text ( Utf8View  {  text  } ,  * font ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  text_width  =  path . bounding_box ( ) . width ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Gfx : : AffineTransform  transform  =  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://html.spec.whatwg.org/multipage/canvas.html#text-preparation-algorithm:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 6. If maxWidth was provided and the hypothetical width of the inline box in the hypothetical line box
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // is greater than maxWidth CSS pixels, then change font to have a more condensed font (if one is
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // available or if a reasonably readable one can be synthesized by applying a horizontal scale
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // factor to the font) or a smaller font, and return to the previous step.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( max_width . has_value ( )  & &  text_width  >  float ( * max_width ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  horizontal_scale  =  float ( * max_width )  /  text_width ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        transform  =  Gfx : : AffineTransform  { } . scale ( {  horizontal_scale ,  1  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        text_width  * =  horizontal_scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Apply text align
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: CanvasTextAlign::Start and CanvasTextAlign::End currently do not nothing for right-to-left languages:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //        https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-textalign-start
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Default alignment of draw_text is left so do nothing by CanvasTextAlign::Start and CanvasTextAlign::Left
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( drawing_state . text_align  = =  Bindings : : CanvasTextAlign : : Center )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        transform  =  Gfx : : AffineTransform  { } . set_translation ( {  - text_width  /  2 ,  0  } ) . multiply ( transform ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( drawing_state . text_align  = =  Bindings : : CanvasTextAlign : : End  | |  drawing_state . text_align  = =  Bindings : : CanvasTextAlign : : Right )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        transform  =  Gfx : : AffineTransform  { } . set_translation ( {  - text_width ,  0  } ) . multiply ( transform ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Apply text baseline
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Implement CanvasTextBasline::Hanging, Bindings::CanvasTextAlign::Alphabetic and Bindings::CanvasTextAlign::Ideographic for real
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //        right now they are just handled as textBaseline = top or bottom.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //        https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-textbaseline-hanging
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Default baseline of draw_text is top so do nothing by CanvasTextBaseline::Top and CanvasTextBasline::Hanging
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( drawing_state . text_baseline  = =  Bindings : : CanvasTextBaseline : : Middle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        transform  =  Gfx : : AffineTransform  { } . set_translation ( {  0 ,  font - > pixel_size ( )  /  2  } ) . multiply ( transform ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( drawing_state . text_baseline  = =  Bindings : : CanvasTextBaseline : : Top  | |  drawing_state . text_baseline  = =  Bindings : : CanvasTextBaseline : : Hanging )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        transform  =  Gfx : : AffineTransform  { } . set_translation ( {  0 ,  font - > pixel_size ( )  } ) . multiply ( transform ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    transform  =  Gfx : : AffineTransform  {  drawing_state . transform  } . multiply ( transform ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path  =  path . copy_transformed ( transform ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : fill_text ( StringView  text ,  float  x ,  float  y ,  Optional < double >  max_width )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:21:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fill_internal ( text_path ( text ,  x ,  y ,  max_width ) ,  Gfx : : WindingRule : : Nonzero ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 19:41:48 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : stroke_text ( StringView  text ,  float  x ,  float  y ,  Optional < double >  max_width )  
						 
					
						
							
								
									
										
										
										
											2022-02-03 20:09:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    stroke_internal ( text_path ( text ,  x ,  y ,  max_width ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-03 20:09:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-16 21:06:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : begin_path ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    path ( ) . clear ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-14 23:29:14 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 17:39:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : stroke_internal ( Gfx : : Path  const &  path )  
						 
					
						
							
								
									
										
										
										
											2020-05-05 06:54:26 +04:30 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    draw_clipped ( [ & ] ( auto &  painter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto &  drawing_state  =  this - > drawing_state ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-07 23:07:06 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( auto  color  =  drawing_state . stroke_style . as_color ( ) ;  color . has_value ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            painter . stroke_path ( path ,  color - > with_opacity ( drawing_state . global_alpha ) ,  drawing_state . line_width ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-07 23:07:06 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            painter . stroke_path ( path ,  drawing_state . stroke_style . to_gfx_paint_style ( ) ,  drawing_state . line_width ,  drawing_state . global_alpha ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-07 23:07:06 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  path . bounding_box ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 17:39:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : stroke ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-06-17 00:17:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    stroke_internal ( path ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 17:39:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : stroke ( Path2D  const &  path )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-08-12 14:00:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  transformed_path  =  path . path ( ) . copy_transformed ( drawing_state ( ) . transform ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 17:39:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    stroke_internal ( transformed_path ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-16 21:06:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:21:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  Gfx : : WindingRule  parse_fill_rule ( StringView  fill_rule )  
						 
					
						
							
								
									
										
										
										
											2020-05-06 11:56:47 +04:30 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( fill_rule  = =  " evenodd " sv ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:21:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  Gfx : : WindingRule : : EvenOdd ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( fill_rule  = =  " nonzero " sv ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:21:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  Gfx : : WindingRule : : Nonzero ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    dbgln ( " Unrecognized fillRule for CRC2D.fill() - this problem goes away once we pass an enum instead of a string " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:21:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  Gfx : : WindingRule : : Nonzero ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2022-08-11 17:39:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:21:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : fill_internal ( Gfx : : Path  const &  path ,  Gfx : : WindingRule  winding_rule )  
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    draw_clipped ( [ & ,  this ] ( auto &  painter )  mutable  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  path_to_fill  =  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        path_to_fill . close_all_subpaths ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-07 23:04:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        auto &  drawing_state  =  this - > drawing_state ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( auto  color  =  drawing_state . fill_style . as_color ( ) ;  color . has_value ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            painter . fill_path ( path_to_fill ,  color - > with_opacity ( drawing_state . global_alpha ) ,  winding_rule ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-07 23:04:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            painter . fill_path ( path_to_fill ,  drawing_state . fill_style . to_gfx_paint_style ( ) ,  drawing_state . global_alpha ,  winding_rule ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-07 23:04:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  path_to_fill . bounding_box ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-06 11:56:47 +04:30 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 19:41:48 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : fill ( StringView  fill_rule )  
						 
					
						
							
								
									
										
										
										
											2020-04-21 23:49:51 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-06-18 18:34:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  fill_internal ( path ( ) ,  parse_fill_rule ( fill_rule ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 17:39:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 19:41:48 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : fill ( Path2D &  path ,  StringView  fill_rule )  
						 
					
						
							
								
									
										
										
										
											2022-08-11 17:39:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2022-08-12 14:00:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  transformed_path  =  path . path ( ) . copy_transformed ( drawing_state ( ) . transform ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 18:34:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  fill_internal ( transformed_path ,  parse_fill_rule ( fill_rule ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-22 18:39:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 23:53:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								WebIDL : : ExceptionOr < JS : : NonnullGCPtr < ImageData > >  CanvasRenderingContext2D : : create_image_data ( int  width ,  int  height ,  Optional < ImageDataSettings >  const &  settings )  const  
						 
					
						
							
								
									
										
										
										
											2020-06-22 18:39:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-05-15 23:53:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  ImageData : : create ( realm ( ) ,  width ,  height ,  settings ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-21 23:49:51 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-getimagedata
  
						 
					
						
							
								
									
										
										
										
											2024-05-15 23:53:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								WebIDL : : ExceptionOr < JS : : GCPtr < ImageData > >  CanvasRenderingContext2D : : get_image_data ( int  x ,  int  y ,  int  width ,  int  height ,  Optional < ImageDataSettings >  const &  settings )  const  
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. If either the sw or sh arguments are zero, then throw an "IndexSizeError" DOMException.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( width  = =  0  | |  height  = =  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 16:03:01 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  WebIDL : : IndexSizeError : : create ( realm ( ) ,  " Width and height must not be zero " _fly_string ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. If the CanvasRenderingContext2D's origin-clean flag is set to false, then throw a "SecurityError" DOMException.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! m_origin_clean ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 16:03:01 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  WebIDL : : SecurityError : : create ( realm ( ) ,  " CanvasRenderingContext2D is not origin-clean " _fly_string ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 3. Let imageData be a new ImageData object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 4. Initialize imageData given sw, sh, settings set to settings, and defaultColorSpace set to this's color space.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-15 23:53:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  image_data  =  TRY ( ImageData : : create ( realm ( ) ,  width ,  height ,  settings ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // NOTE: We don't attempt to create the underlying bitmap here; if it doesn't exist, it's like copying only transparent black pixels (which is a no-op).
 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-19 19:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! canvas_element ( ) . bitmap ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  image_data ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-19 19:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  const &  bitmap  =  * canvas_element ( ) . bitmap ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 5. Let the source rectangle be the rectangle whose corners are the four points (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  source_rect  =  Gfx : : Rect  {  x ,  y ,  width ,  height  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  source_rect_intersected  =  source_rect . intersected ( bitmap . rect ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 6. Set the pixel values of imageData to be the pixels of this's output bitmap in the area specified by the source rectangle in the bitmap's coordinate space units, converted from this's color space to imageData's colorSpace using 'relative-colorimetric' rendering intent.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Can't use a Gfx::Painter + blit() here as it doesn't support ImageData bitmap's RGBA8888 format.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( int  target_y  =  0 ;  target_y  <  source_rect_intersected . height ( ) ;  + + target_y )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-13 12:39:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        auto *  dst  =  image_data - > bitmap ( ) . scanline ( target_y ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  const *  src  =  bitmap . scanline ( target_y  +  y )  +  x ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        memcpy ( dst ,  src ,  source_rect_intersected . width ( )  *  sizeof ( Gfx : : ARGB32 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 7. Set the pixels values of imageData for areas of the source rectangle that are outside of the output bitmap to transparent black.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // NOTE: No-op, already done during creation.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 8. Return imageData.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  image_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-01 20:58:27 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : put_image_data ( ImageData  const &  image_data ,  float  x ,  float  y )  
						 
					
						
							
								
									
										
										
										
											2020-04-21 23:49:51 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    draw_clipped ( [ & ] ( auto &  painter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        painter . underlying_painter ( ) . blit ( Gfx : : IntPoint ( x ,  y ) ,  image_data . bitmap ( ) ,  image_data . bitmap ( ) . rect ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Gfx : : FloatRect ( x ,  y ,  image_data . width ( ) ,  image_data . height ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-21 23:49:51 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-27 14:33:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#reset-the-rendering-context-to-its-default-state
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : reset_to_default_state ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  painter  =  this - > painter ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. Clear canvas's bitmap to transparent black.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( painter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        painter - > clear_rect ( painter - > target ( ) - > rect ( ) ,  Color : : Transparent ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. Empty the list of subpaths in context's current default path.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-11 16:10:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    path ( ) . clear ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-27 14:33:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 3. Clear the context's drawing state stack.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-12 14:00:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    clear_drawing_state_stack ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-27 14:33:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 4. Reset everything that drawing state consists of to their initial values.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-12 14:00:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    reset_drawing_state ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-27 14:33:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( painter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        did_draw ( painter - > target ( ) - > rect ( ) . to_type < float > ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-measuretext
  
						 
					
						
							
								
									
										
										
										
											2023-09-06 19:41:48 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								JS : : NonnullGCPtr < TextMetrics >  CanvasRenderingContext2D : : measure_text ( StringView  text )  
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // The measureText(text) method steps are to run the text preparation
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // algorithm, passing it text and the object implementing the CanvasText
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // interface, and then using the returned inline box must return a new
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // TextMetrics object with members behaving as described in the following
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // list:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  prepared_text  =  prepare_text ( text ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-13 13:05:26 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  metrics  =  TextMetrics : : create ( realm ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // FIXME: Use the font that was used to create the glyphs in prepared_text.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  font  =  current_font ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // width attribute: The width of that inline box, in CSS pixels. (The text's advance width.)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    metrics - > set_width ( prepared_text . bounding_box . width ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // actualBoundingBoxLeft attribute: The distance parallel to the baseline from the alignment point given by the textAlign attribute to the left side of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going left from the given alignment point.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    metrics - > set_actual_bounding_box_left ( - prepared_text . bounding_box . left ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // actualBoundingBoxRight attribute: The distance parallel to the baseline from the alignment point given by the textAlign attribute to the right side of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going right from the given alignment point.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    metrics - > set_actual_bounding_box_right ( prepared_text . bounding_box . right ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // fontBoundingBoxAscent attribute: The distance from the horizontal line indicated by the textBaseline attribute to the ascent metric of the first available font, in CSS pixels; positive numbers indicating a distance going up from the given baseline.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    metrics - > set_font_bounding_box_ascent ( font - > baseline ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // fontBoundingBoxDescent attribute: The distance from the horizontal line indicated by the textBaseline attribute to the descent metric of the first available font, in CSS pixels; positive numbers indicating a distance going down from the given baseline.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    metrics - > set_font_bounding_box_descent ( prepared_text . bounding_box . height ( )  -  font - > baseline ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // actualBoundingBoxAscent attribute: The distance from the horizontal line indicated by the textBaseline attribute to the top of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going up from the given baseline.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    metrics - > set_actual_bounding_box_ascent ( font - > baseline ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // actualBoundingBoxDescent attribute: The distance from the horizontal line indicated by the textBaseline attribute to the bottom of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going down from the given baseline.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    metrics - > set_actual_bounding_box_descent ( prepared_text . bounding_box . height ( )  -  font - > baseline ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // emHeightAscent attribute: The distance from the horizontal line indicated by the textBaseline attribute to the highest top of the em squares in the inline box, in CSS pixels; positive numbers indicating that the given baseline is below the top of that em square (so this value will usually be positive). Zero if the given baseline is the top of that em square; half the font size if the given baseline is the middle of that em square.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    metrics - > set_em_height_ascent ( font - > baseline ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // emHeightDescent attribute: The distance from the horizontal line indicated by the textBaseline attribute to the lowest bottom of the em squares in the inline box, in CSS pixels; positive numbers indicating that the given baseline is above the bottom of that em square. (Zero if the given baseline is the bottom of that em square.)
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    metrics - > set_em_height_descent ( prepared_text . bounding_box . height ( )  -  font - > baseline ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // hangingBaseline attribute: The distance from the horizontal line indicated by the textBaseline attribute to the hanging baseline of the inline box, in CSS pixels; positive numbers indicating that the given baseline is below the hanging baseline. (Zero if the given baseline is the hanging baseline.)
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    metrics - > set_hanging_baseline ( font - > baseline ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // alphabeticBaseline attribute: The distance from the horizontal line indicated by the textBaseline attribute to the alphabetic baseline of the inline box, in CSS pixels; positive numbers indicating that the given baseline is below the alphabetic baseline. (Zero if the given baseline is the alphabetic baseline.)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    metrics - > set_font_bounding_box_ascent ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // ideographicBaseline attribute: The distance from the horizontal line indicated by the textBaseline attribute to the ideographic-under baseline of the inline box, in CSS pixels; positive numbers indicating that the given baseline is below the ideographic-under baseline. (Zero if the given baseline is the ideographic-under baseline.)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    metrics - > set_font_bounding_box_ascent ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  metrics ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								RefPtr < Gfx : : Font  const >  CanvasRenderingContext2D : : current_font ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // When font style value is empty load default font
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! drawing_state ( ) . font_style_value )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 19:41:48 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        set_font ( " 10px sans-serif " sv ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Get current loaded font
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  drawing_state ( ) . current_font ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#text-preparation-algorithm
  
						 
					
						
							
								
									
										
										
										
											2023-12-16 17:49:34 +03:30 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								CanvasRenderingContext2D : : PreparedText  CanvasRenderingContext2D : : prepare_text ( ByteString  const &  text ,  float  max_width )  
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. If maxWidth was provided but is less than or equal to zero or equal to NaN, then return an empty array.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( max_width  < =  0  | |  max_width  ! =  max_width )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. Replace all ASCII whitespace in text with U+0020 SPACE characters.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    StringBuilder  builder  {  text . length ( )  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( auto  c  :  text )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-01 18:14:32 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        builder . append ( Infra : : is_ascii_whitespace ( c )  ?  '   '  :  c ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-05 09:26:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  replaced_text  =  builder . string_view ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 3. Let font be the current font of target, as given by that object's font attribute.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  font  =  current_font ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 4. Apply the appropriate step from the following list to determine the value of direction:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   4.1. If the target object's direction attribute has the value "ltr": Let direction be 'ltr'.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   4.2. If the target object's direction attribute has the value "rtl": Let direction be 'rtl'.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   4.3. If the target object's font style source object is an element: Let direction be the directionality of the target object's font style source object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   4.4. If the target object's font style source object is a Document with a non-null document element: Let direction be the directionality of the target object's font style source object's document element.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   4.5. Otherwise: Let direction be 'ltr'.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Once we have CanvasTextDrawingStyles, implement directionality.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 5. Form a hypothetical infinitely-wide CSS line box containing a single inline box containing the text text, with its CSS properties set as follows:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   'direction'         -> direction
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   'font'              -> font
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   'font-kerning'      -> target's fontKerning
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   'font-stretch'      -> target's fontStretch
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   'font-variant-caps' -> target's fontVariantCaps
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   'letter-spacing'    -> target's letterSpacing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   SVG text-rendering  -> target's textRendering
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   'white-space'       -> 'pre'
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   'word-spacing'      -> target's wordSpacing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // ...and with all other properties set to their initial values.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Actually use a LineBox here instead of, you know, using the default font and measuring its size (which is not the spec at all).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Once we have CanvasTextDrawingStyles, add the CSS attributes.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-27 21:33:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    size_t  width  =  font - > width ( text . view ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    size_t  height  =  font - > pixel_size ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-22 11:48:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Utf8View  replaced_text_view  {  replaced_text  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 6. If maxWidth was provided and the hypothetical width of the inline box in the hypothetical line box is greater than maxWidth CSS pixels, then change font to have a more condensed font (if one is available or if a reasonably readable one can be synthesized by applying a horizontal scale factor to the font) or a smaller font, and return to the previous step.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Record the font size used for this piece of text, and actually retry with a smaller size if needed.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 7. The anchor point is a point on the inline box, and the physical alignment is one of the values left, right, and center. These variables are determined by the textAlign and textBaseline values as follows:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Horizontal position:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   7.1. If textAlign is left, if textAlign is start and direction is 'ltr' or if textAlign is end and direction is 'rtl': Let the anchor point's horizontal position be the left edge of the inline box, and let physical alignment be left.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   7.2. If textAlign is right, if textAlign is end and direction is 'ltr' or if textAlign is start and direction is 'rtl': Let the anchor point's horizontal position be the right edge of the inline box, and let physical alignment be right.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   7.3. If textAlign is center: Let the anchor point's horizontal position be half way between the left and right edges of the inline box, and let physical alignment be center.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Vertical position:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   7.4. If textBaseline is top: Let the anchor point's vertical position be the top of the em box of the first available font of the inline box.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   7.5. If textBaseline is hanging: Let the anchor point's vertical position be the hanging baseline of the first available font of the inline box.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   7.6. If textBaseline is middle: Let the anchor point's vertical position be half way between the bottom and the top of the em box of the first available font of the inline box.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   7.7. If textBaseline is alphabetic: Let the anchor point's vertical position be the alphabetic baseline of the first available font of the inline box.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   7.8. If textBaseline is ideographic: Let the anchor point's vertical position be the ideographic-under baseline of the first available font of the inline box.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   7.9. If textBaseline is bottom: Let the anchor point's vertical position be the bottom of the em box of the first available font of the inline box.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Once we have CanvasTextDrawingStyles, handle the alignment and baseline.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-16 18:07:37 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    [[maybe_unused]]  Gfx : : IntPoint  anchor  {  0 ,  0  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  physical_alignment  =  Gfx : : TextAlignment : : CenterLeft ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 8. Let result be an array constructed by iterating over each glyph in the inline box from left to right (if any), adding to the array, for each glyph, the shape of the glyph as it is in the inline box, positioned on a coordinate space using CSS pixels with its origin is at the anchor point.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    PreparedText  prepared_text  {  { } ,  physical_alignment ,  {  0 ,  0 ,  static_cast < int > ( width ) ,  static_cast < int > ( height )  }  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    prepared_text . glyphs . ensure_capacity ( replaced_text . length ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-22 11:48:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    size_t  previous_grapheme_boundary  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Unicode : : for_each_grapheme_segmentation_boundary ( replaced_text_view ,  [ & ] ( auto  boundary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( boundary  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  IterationDecision : : Continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  glyph_view  =  replaced_text_view . substring_view ( previous_grapheme_boundary ,  boundary  -  previous_grapheme_boundary ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  glyph  =  String : : from_utf8 ( glyph_view . as_string ( ) ) . release_value_but_fixme_should_propagate_errors ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        prepared_text . glyphs . append ( {  move ( glyph ) ,  {  static_cast < int > ( boundary ) ,  0  }  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  IterationDecision : : Continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 9. Return result, physical alignment, and the inline box.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  prepared_text ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-05 10:21:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : clip_internal ( Gfx : : Path &  path ,  Gfx : : WindingRule  winding_rule )  
						 
					
						
							
								
									
										
										
										
											2022-04-10 18:48:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // FIXME: This should calculate the new clip path by intersecting the given path with the current one.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // See: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-clip-dev
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . close_all_subpaths ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( drawing_state ( ) . clip . has_value ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dbgln ( " FIXME: CRC2D: Calculate the new clip path by intersecting the given path with the current one. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-16 22:12:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    drawing_state ( ) . clip  =  Gfx : : ClipPath  {  path ,  winding_rule  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 19:41:48 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : clip ( StringView  fill_rule )  
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  transformed_path  =  path ( ) . copy_transformed ( drawing_state ( ) . transform ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 18:34:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  clip_internal ( transformed_path ,  parse_fill_rule ( fill_rule ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 19:41:48 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : clip ( Path2D &  path ,  StringView  fill_rule )  
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  transformed_path  =  path . path ( ) . copy_transformed ( drawing_state ( ) . transform ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-18 18:34:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  clip_internal ( transformed_path ,  parse_fill_rule ( fill_rule ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-10 18:48:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#check-the-usability-of-the-image-argument
  
						 
					
						
							
								
									
										
										
										
											2022-09-25 17:03:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								WebIDL : : ExceptionOr < CanvasImageSourceUsability >  check_usability_of_image ( CanvasImageSource  const &  image )  
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. Switch on image:
 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-22 12:35:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  usability  =  TRY ( image . visit ( 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        // HTMLOrSVGImageElement
 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-25 17:03:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( JS : : Handle < HTMLImageElement >  const &  image_element )  - >  WebIDL : : ExceptionOr < Optional < CanvasImageSourceUsability > >  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // FIXME: If image's current request's state is broken, then throw an "InvalidStateError" DOMException.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-05 17:08:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // If image is not fully decodable, then return bad.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-28 13:42:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( ! image_element - > bitmap ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-05 17:08:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                return  {  CanvasImageSourceUsability : : Bad  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // If image has an intrinsic width or intrinsic height (or both) equal to zero, then return bad.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-28 13:42:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( image_element - > bitmap ( ) - > width ( )  = =  0  | |  image_element - > bitmap ( ) - > height ( )  = =  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                return  {  CanvasImageSourceUsability : : Bad  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  Optional < CanvasImageSourceUsability >  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // FIXME: HTMLVideoElement
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // If image's readyState attribute is either HAVE_NOTHING or HAVE_METADATA, then return bad.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // HTMLCanvasElement
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // FIXME: OffscreenCanvas
 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-25 17:03:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( JS : : Handle < HTMLCanvasElement >  const &  canvas_element )  - >  WebIDL : : ExceptionOr < Optional < CanvasImageSourceUsability > >  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // If image has either a horizontal dimension or a vertical dimension equal to zero, then throw an "InvalidStateError" DOMException.
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-28 13:42:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( canvas_element - > width ( )  = =  0  | |  canvas_element - > height ( )  = =  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 16:03:01 +12:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                return  WebIDL : : InvalidStateError : : create ( canvas_element - > realm ( ) ,  " Canvas width or height is zero " _fly_string ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  Optional < CanvasImageSourceUsability >  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-05 09:15:45 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // ImageBitmap
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // FIXME: VideoFrame
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        [ ] ( JS : : Handle < ImageBitmap >  const &  image_bitmap )  - >  WebIDL : : ExceptionOr < Optional < CanvasImageSourceUsability > >  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( image_bitmap - > is_detached ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  WebIDL : : InvalidStateError : : create ( image_bitmap - > realm ( ) ,  " Image bitmap is detached " _fly_string ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  Optional < CanvasImageSourceUsability >  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-22 12:35:54 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( usability . has_value ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  usability . release_value ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. Return good.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  {  CanvasImageSourceUsability : : Good  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#the-image-argument-is-not-origin-clean
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  image_is_not_origin_clean ( CanvasImageSource  const &  image )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // An object image is not origin-clean if, switching on image's type:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  image . visit ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // HTMLOrSVGImageElement
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-28 13:42:07 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( JS : : Handle < HTMLImageElement >  const & )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // FIXME: image's current request's image data is CORS-cross-origin.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // FIXME: HTMLVideoElement
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // image's media data is CORS-cross-origin.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // HTMLCanvasElement
 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-05 09:15:45 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( OneOf < JS : : Handle < HTMLCanvasElement > ,  JS : : Handle < ImageBitmap > >  auto  const & )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // FIXME: image's bitmap's origin-clean flag is false.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-03-29 18:35:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								bool  CanvasRenderingContext2D : : image_smoothing_enabled ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  drawing_state ( ) . image_smoothing_enabled ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_image_smoothing_enabled ( bool  enabled )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    drawing_state ( ) . image_smoothing_enabled  =  enabled ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Bindings : : ImageSmoothingQuality  CanvasRenderingContext2D : : image_smoothing_quality ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  drawing_state ( ) . image_smoothing_quality ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_image_smoothing_quality ( Bindings : : ImageSmoothingQuality  quality )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    drawing_state ( ) . image_smoothing_quality  =  quality ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								float  CanvasRenderingContext2D : : global_alpha ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  drawing_state ( ) . global_alpha ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-globalalpha
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_global_alpha ( float  alpha )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. If the given value is either infinite, NaN, or not in the range 0.0 to 1.0, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! isfinite ( alpha )  | |  alpha  <  0.0f  | |  alpha  >  1.0f )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. Otherwise, set this's global alpha to the given value.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    drawing_state ( ) . global_alpha  =  alpha ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}