2020-04-06 11:09:01 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  ( c )  2020 - 2024 ,  Andreas  Kling  < andreas @ ladybird . 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 > 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 02:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  ( c )  2024 ,  Aliaksandr  Kalenik  < kalenik . aliaksandr @ gmail . com > 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  ( c )  2024 ,  Lucien  Fiorini  < lucienfiorini @ gmail . com > 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:01:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  ( c )  2025 ,  Jelle  Raaijmakers  < jelle @ ladybird . org > 
							 
						 
					
						
							
								
									
										
										
										
											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> 
  
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibGfx/CompositingAndBlendingOperator.h> 
  
						 
					
						
							
								
									
										
										
										
											2024-09-25 15:44:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibGfx/PainterSkia.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibGfx/Rect.h> 
  
						 
					
						
							
								
									
										
										
										
											2025-05-07 22:13:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibJS/Runtime/ValueInlines.h> 
  
						 
					
						
							
								
									
										
										
										
											2024-06-23 09:14:27 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibUnicode/Segmenter.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> 
  
						 
					
						
							
								
									
										
										
										
											2024-11-29 20:17:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/HTML/TraversableNavigable.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> 
  
						 
					
						
							
								
									
										
										
										
											2024-10-04 14:39:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibWeb/SVG/SVGImageElement.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 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								GC_DEFINE_ALLOCATOR ( CanvasRenderingContext2D ) ;  
						 
					
						
							
								
									
										
										
										
											2023-11-19 19:47:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:01:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								JS : : ThrowCompletionOr < GC : : Ref < CanvasRenderingContext2D > >  CanvasRenderingContext2D : : create ( JS : : Realm &  realm ,  HTMLCanvasElement &  element ,  JS : : Value  options )  
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2025-06-18 02:51:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  context_attributes  =  TRY ( CanvasRenderingContext2DSettings : : from_js_value ( realm . vm ( ) ,  options ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:01:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  realm . create < CanvasRenderingContext2D > ( realm ,  element ,  context_attributes ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 15:53:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:01:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								CanvasRenderingContext2D : : CanvasRenderingContext2D ( JS : : Realm &  realm ,  HTMLCanvasElement &  element ,  CanvasRenderingContext2DSettings  context_attributes )  
						 
					
						
							
								
									
										
										
										
											2022-09-25 16:38:21 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    :  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 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 20:17:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ,  m_size ( element . bitmap_size_for_canvas ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:01:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ,  m_context_attributes ( move ( context_attributes ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 15:53:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											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 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-12 20:56:21 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    set_prototype ( & Bindings : : ensure_web_prototype < Bindings : : CanvasRenderingContext2DPrototype > ( realm ,  " CanvasRenderingContext2D " _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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								GC : : Ref < 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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-08 15:12:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Gfx : : Path  CanvasRenderingContext2D : : rect_path ( float  x ,  float  y ,  float  width ,  float  height )  
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  top_left  =  Gfx : : FloatPoint ( x ,  y ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  top_right  =  Gfx : : FloatPoint ( x  +  width ,  y ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  bottom_left  =  Gfx : : FloatPoint ( x ,  y  +  height ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  bottom_right  =  Gfx : : FloatPoint ( x  +  width ,  y  +  height ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-08 15:12:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    Gfx : : Path  path ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-19 22:42:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    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-08-15 08:18:36 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    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 )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( auto *  painter  =  this - > painter ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  rect  =  Gfx : : FloatRect ( x ,  y ,  width ,  height ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        painter - > clear_rect ( rect ,  clear_color ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        did_draw ( 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  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 15:44:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  bitmap  =  image . visit ( 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < HTMLImageElement >  const &  source )  - >  RefPtr < Gfx : : ImmutableBitmap >  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  source - > immutable_bitmap ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 02:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < SVG : : SVGImageElement >  const &  source )  - >  RefPtr < Gfx : : ImmutableBitmap >  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  source - > current_image_bitmap ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < HTMLCanvasElement >  const &  source )  - >  RefPtr < Gfx : : ImmutableBitmap >  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            auto  surface  =  source - > surface ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( ! surface ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 06:47:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  Gfx : : ImmutableBitmap : : create_snapshot_from_painting_surface ( * surface ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < HTMLVideoElement >  const &  source )  - >  RefPtr < Gfx : : ImmutableBitmap >  {  return  Gfx : : ImmutableBitmap : : create ( * source - > bitmap ( ) ) ;  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < ImageBitmap >  const &  source )  - >  RefPtr < Gfx : : ImmutableBitmap >  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  Gfx : : ImmutableBitmap : : create ( * 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.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  scaling_mode  =  Gfx : : ScalingMode : : NearestNeighbor ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( drawing_state ( ) . image_smoothing_enabled )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // FIXME: Honor drawing_state().image_smoothing_quality
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        scaling_mode  =  Gfx : : ScalingMode : : BilinearBlend ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:38:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( auto *  painter  =  this - > painter ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        painter - > draw_bitmap ( destination_rect ,  * bitmap ,  source_rect . to_rounded < int > ( ) ,  scaling_mode ,  drawing_state ( ) . filter ,  drawing_state ( ) . global_alpha ,  drawing_state ( ) . current_compositing_and_blending_operator ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        did_draw ( destination_rect ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02: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 ; 
							 
						 
					
						
							
								
									
										
										
										
											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-09-02 16:47:32 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    canvas_element ( ) . paintable ( ) - > set_needs_display ( InvalidateDisplayList : : No ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Gfx : : Painter *  CanvasRenderingContext2D : : painter ( )  
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-12-04 16:22:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    allocate_painting_surface_if_needed ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  surface  =  canvas_element ( ) . surface ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! m_painter  & &  surface )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-12 00:49:32 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        canvas_element ( ) . document ( ) . invalidate_display_list ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 15:44:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        m_painter  =  make < Gfx : : PainterSkia > ( * canvas_element ( ) . surface ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 20:17:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_size ( Gfx : : IntSize  const &  size )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_size  = =  size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_size  =  size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_surface  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : allocate_painting_surface_if_needed ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-12-04 16:22:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( m_surface  | |  m_size . is_empty ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 20:17:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:01:47 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: implement context attribute .color_space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: implement context attribute .color_type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: implement context attribute .desynchronized
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: implement context attribute .will_read_frequently
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  color_type  =  m_context_attributes . alpha  ?  Gfx : : BitmapFormat : : BGRA8888  :  Gfx : : BitmapFormat : : BGRx8888 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 20:17:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  skia_backend_context  =  canvas_element ( ) . navigable ( ) - > traversable_navigable ( ) - > skia_backend_context ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    m_surface  =  Gfx : : PaintingSurface : : create_with_size ( skia_backend_context ,  canvas_element ( ) . bitmap_size_for_canvas ( ) ,  color_type ,  Gfx : : AlphaType : : Premultiplied ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://html.spec.whatwg.org/multipage/canvas.html#the-canvas-settings:concept-canvas-alpha
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Thus, the bitmap of such a context starts off as opaque black instead of transparent black;
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // AD-HOC: Skia provides us with a full transparent surface by default; only clear the surface if alpha is disabled.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! m_context_attributes . alpha )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto *  painter  =  this - > painter ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        painter - > clear_rect ( m_surface - > rect ( ) . to_type < float > ( ) ,  clear_color ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-29 20:17:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-08 15:12:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Gfx : : Path  CanvasRenderingContext2D : : text_path ( StringView  text ,  float  x ,  float  y ,  Optional < double >  max_width )  
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( max_width . has_value ( )  & &  max_width . value ( )  < =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto &  drawing_state  =  this - > drawing_state ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 21:36:26 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  const &  font_cascade_list  =  this - > font_cascade_list ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  const &  font  =  font_cascade_list - > first ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  glyph_runs  =  Gfx : : shape_text ( {  x ,  y  } ,  Utf8View ( text ) ,  * font_cascade_list ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-08 15:12:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    Gfx : : Path  path ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 21:36:26 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  ( auto  const &  glyph_run  :  glyph_runs )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        path . glyph_run ( glyph_run ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  text_width  =  path . bounding_box ( ) . width ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Gfx : : AffineTransform  transform  =  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://html.spec.whatwg.org/multipage/canvas.html#text-preparation-algorithm:
 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-14 17:19:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 9. If maxWidth was provided and the hypothetical width of the inline box in the hypothetical line box
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 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
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-07 10:46:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // FIXME: Implement CanvasTextBaseline::Hanging, Bindings::CanvasTextAlign::Alphabetic and Bindings::CanvasTextAlign::Ideographic for real
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    //        right now they are just handled as textBaseline = top or bottom.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //        https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-textbaseline-hanging
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-07 10:46:22 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // Default baseline of draw_text is top so do nothing by CanvasTextBaseline::Top and CanvasTextBaseline::Hanging
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( drawing_state . text_baseline  = =  Bindings : : CanvasTextBaseline : : Middle )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        transform  =  Gfx : : AffineTransform  { } . set_translation ( {  0 ,  font . pixel_size ( )  /  2  } ) . multiply ( transform ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( drawing_state . text_baseline  = =  Bindings : : CanvasTextBaseline : : Top  | |  drawing_state . text_baseline  = =  Bindings : : CanvasTextBaseline : : Hanging )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        transform  =  Gfx : : AffineTransform  { } . set_translation ( {  0 ,  font . pixel_size ( )  } ) . multiply ( transform ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-08 15:12:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  path . copy_transformed ( transform ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-11 17:18:55 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-14 22:28:53 +05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  Gfx : : Path : : CapStyle  to_gfx_cap ( Bindings : : CanvasLineCap  const &  cap_style )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    switch  ( cap_style )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  Bindings : : CanvasLineCap : : Butt : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Gfx : : Path : : CapStyle : : Butt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  Bindings : : CanvasLineCap : : Round : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Gfx : : Path : : CapStyle : : Round ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  Bindings : : CanvasLineCap : : Square : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Gfx : : Path : : CapStyle : : Square ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    VERIFY_NOT_REACHED ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  Gfx : : Path : : JoinStyle  to_gfx_join ( Bindings : : CanvasLineJoin  const &  join_style )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    switch  ( join_style )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  Bindings : : CanvasLineJoin : : Round : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Gfx : : Path : : JoinStyle : : Round ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  Bindings : : CanvasLineJoin : : Bevel : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Gfx : : Path : : JoinStyle : : Bevel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  Bindings : : CanvasLineJoin : : Miter : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Gfx : : Path : : JoinStyle : : Miter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    VERIFY_NOT_REACHED ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#the-canvas-settings:concept-canvas-alpha
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Gfx : : Color  CanvasRenderingContext2D : : clear_color ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  m_context_attributes . alpha  ?  Gfx : : Color : : Transparent  :  Gfx : : Color : : Black ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-08 15:12:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : stroke_internal ( Gfx : : Path  const &  path )  
						 
					
						
							
								
									
										
										
										
											2020-05-05 06:54:26 +04:30 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto *  painter  =  this - > painter ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! painter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-18 01:56:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    paint_shadow_for_stroke_internal ( path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto &  state  =  drawing_state ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-14 22:28:53 +05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  line_cap  =  to_gfx_cap ( state . line_cap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  line_join  =  to_gfx_join ( state . line_join ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-14 15:54:53 +05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // FIXME: Need a Vector<float> for rendering dash_array, but state.dash_list is Vector<double>.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Maybe possible to avoid creating copies?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  dash_array  =  Vector < float >  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dash_array . ensure_capacity ( state . dash_list . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( auto  const &  dash  :  state . dash_list )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dash_array . append ( static_cast < float > ( dash ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    painter - > stroke_path ( path ,  state . stroke_style . to_gfx_paint_style ( ) ,  state . filter ,  state . line_width ,  state . global_alpha ,  state . current_compositing_and_blending_operator ,  line_cap ,  line_join ,  state . miter_limit ,  dash_array ,  state . line_dash_offset ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    did_draw ( 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 )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    stroke_internal ( path . 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-08-08 15:12:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : fill_internal ( Gfx : : Path  const &  path ,  Gfx : : WindingRule  winding_rule )  
						 
					
						
							
								
									
										
										
										
											2023-04-06 20:57:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto *  painter  =  this - > painter ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! painter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-18 01:56:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    paint_shadow_for_fill_internal ( path ,  winding_rule ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  path_to_fill  =  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path_to_fill . close_all_subpaths ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto &  state  =  this - > drawing_state ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    painter - > fill_path ( path_to_fill ,  state . fill_style . to_gfx_paint_style ( ) ,  state . filter ,  state . global_alpha ,  state . current_compositing_and_blending_operator ,  winding_rule ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    did_draw ( path_to_fill . bounding_box ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-08-15 08:18:36 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fill_internal ( path . path ( ) ,  parse_fill_rule ( fill_rule ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-22 18:39:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-13 11:21:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createimagedata
  
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								WebIDL : : ExceptionOr < GC : : Ref < ImageData > >  CanvasRenderingContext2D : : create_image_data ( int  width ,  int  height ,  Optional < ImageDataSettings >  const &  settings )  const  
						 
					
						
							
								
									
										
										
										
											2020-06-22 18:39:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-10-13 11:21:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 1. If one or both of sw and sh are zero, then throw an "IndexSizeError" DOMException.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( width  = =  0  | |  height  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  WebIDL : : IndexSizeError : : create ( realm ( ) ,  " Width and height must not be zero " _string ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  abs_width  =  abs ( width ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  abs_height  =  abs ( height ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. Let newImageData be a new ImageData object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 3. Initialize newImageData given the absolute magnitude of sw, the absolute magnitude of sh, settings set to settings, and defaultColorSpace set to this's color space.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  image_data  =  TRY ( ImageData : : create ( realm ( ) ,  abs_width ,  abs_height ,  settings ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 4. Initialize the image data of newImageData to transparent black.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // ... this is handled by ImageData::create()
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 5. Return newImageData.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  image_data ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-21 23:49:51 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-13 16:12:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createimagedata-imagedata
  
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								WebIDL : : ExceptionOr < GC : : Ref < ImageData > >  CanvasRenderingContext2D : : create_image_data ( ImageData  const &  image_data )  const  
						 
					
						
							
								
									
										
										
										
											2024-10-13 16:12:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. Let newImageData be a new ImageData object.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-20 16:14:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 2. Initialize newImageData given the value of imageData's width attribute, the value of imageData's height attribute, and defaultColorSpace set to the value of imageData's colorSpace attribute.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-13 16:12:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // FIXME: Set defaultColorSpace to the value of image_data's colorSpace attribute
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 3. Initialize the image data of newImageData to transparent black.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // NOTE: No-op, already done during creation.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 4. Return newImageData.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  TRY ( ImageData : : create ( realm ( ) ,  image_data . width ( ) ,  image_data . height ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-getimagedata
  
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								WebIDL : : ExceptionOr < GC : : Ptr < 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 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-12 20:56:21 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  WebIDL : : IndexSizeError : : create ( realm ( ) ,  " Width and height must not be zero " _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 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-12 20:56:21 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  WebIDL : : SecurityError : : create ( realm ( ) ,  " CanvasRenderingContext2D is not origin-clean " _string ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-13 11:35:08 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // ImageData initialization requires positive width and height
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://html.spec.whatwg.org/multipage/canvas.html#initialize-an-imagedata-object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  abs_width  =  abs ( width ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  abs_height  =  abs ( height ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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-10-13 11:35:08 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  image_data  =  TRY ( ImageData : : create ( realm ( ) ,  abs_width ,  abs_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).
 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 15:44:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! canvas_element ( ) . surface ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  image_data ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 06:47:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  const  snapshot  =  Gfx : : ImmutableBitmap : : create_snapshot_from_painting_surface ( * canvas_element ( ) . surface ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											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).
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-13 11:35:08 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  source_rect  =  Gfx : : Rect  {  x ,  y ,  abs_width ,  abs_height  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-13 12:42:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // NOTE: The spec doesn't seem to define this behavior, but MDN does and the WPT tests
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // assume it works this way.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData#sw
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( width  <  0  | |  height  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        source_rect  =  source_rect . translated ( min ( width ,  0 ) ,  min ( height ,  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  source_rect_intersected  =  source_rect . intersected ( snapshot - > rect ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:07:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 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.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-02 13:15:45 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // NOTE: Internally we must use premultiplied alpha, but ImageData should hold unpremultiplied alpha. This conversion
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //       might result in a loss of precision, but is according to spec.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //       See: https://html.spec.whatwg.org/multipage/canvas.html#premultiplied-alpha-and-the-2d-rendering-context
 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-10 13:02:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    VERIFY ( snapshot - > alpha_type ( )  = =  Gfx : : AlphaType : : Premultiplied ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    VERIFY ( image_data - > bitmap ( ) . alpha_type ( )  = =  Gfx : : AlphaType : : Unpremultiplied ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-20 19:39:38 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  painter  =  Gfx : : Painter : : create ( image_data - > bitmap ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-23 20:27:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    painter - > draw_bitmap ( image_data - > bitmap ( ) . rect ( ) . to_type < float > ( ) ,  * snapshot ,  source_rect_intersected ,  Gfx : : ScalingMode : : NearestNeighbor ,  { } ,  1 ,  Gfx : : CompositingAndBlendingOperator : : SourceOver ) ; 
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-02-20 16:14:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-putimagedata-short
  
						 
					
						
							
								
									
										
										
										
											2025-04-15 15:51:27 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : put_image_data ( ImageData &  image_data ,  float  x ,  float  y )  
						 
					
						
							
								
									
										
										
										
											2020-04-21 23:49:51 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2025-02-20 16:14:11 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // The putImageData(imageData, dx, dy) method steps are to put pixels from an ImageData onto a bitmap,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // given imageData, this's output bitmap, dx, dy, 0, 0, imageData's width, and imageData's height.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: "put pixels from an ImageData onto a bitmap" is a spec algorithm.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //        https://html.spec.whatwg.org/multipage/canvas.html#dom-context2d-putimagedata-common
 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( auto *  painter  =  this - > painter ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  dst_rect  =  Gfx : : FloatRect ( x ,  y ,  image_data . width ( ) ,  image_data . height ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-26 16:53:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        painter - > draw_bitmap ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dst_rect , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            Gfx : : ImmutableBitmap : : create ( image_data . bitmap ( ) ,  Gfx : : AlphaType : : Unpremultiplied ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            image_data . bitmap ( ) . rect ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            Gfx : : ScalingMode : : NearestNeighbor , 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            drawing_state ( ) . filter , 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-26 16:53:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            1.0f , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            Gfx : : CompositingAndBlendingOperator : : SourceOver ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 15:36:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        did_draw ( dst_rect ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											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 ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-09-25 15:44:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  surface  =  canvas_element ( ) . surface ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-27 14:33:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. Clear canvas's bitmap to transparent black.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 15:44:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( surface )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 16:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        painter ( ) - > clear_rect ( surface - > rect ( ) . to_type < float > ( ) ,  clear_color ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-18 18:58:20 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-27 14:33:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 15:44:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( surface ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        did_draw ( surface - > rect ( ) . to_type < float > ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-27 14:33:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-measuretext
  
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								GC : : Ref < 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
 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-24 11:18:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // interface, and then using the returned inline box return a new
 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 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.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  const &  font  =  font_cascade_list ( ) - > first ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											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.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +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.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +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.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +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.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +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.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +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.)
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +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.)
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								RefPtr < Gfx : : FontCascadeList  const >  CanvasRenderingContext2D : : font_cascade_list ( )  
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 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
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:34:53 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  drawing_state ( ) . current_font_cascade_list ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 21:48:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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-06-19 09:02:21 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  replaced_text  =  MUST ( builder . to_string ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											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.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-20 01:09:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  glyph_runs  =  Gfx : : shape_text ( {  0 ,  0  } ,  Utf8View ( replaced_text ) ,  * font_cascade_list ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-14 17:19:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // FIXME: 4. Let language be the target's language.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: 5. If language is "inherit":
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //           ...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: 6. If language is the empty string, then set language to explicitly unknown.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-14 17:19:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // FIXME: 7. Apply the appropriate step from the following list to determine the value of direction:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //           ...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 8. Form a hypothetical infinitely-wide CSS line box containing a single inline box containing the text text,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    with the CSS content language set to language, and with its CSS properties set as follows:
 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    //   '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.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-20 01:09:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    float  height  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    float  width  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( auto  const &  glyph_run  :  glyph_runs )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        height  =  max ( height ,  glyph_run - > font ( ) . pixel_size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        width  + =  glyph_run - > width ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-22 11:48:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-14 17:19:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 9. 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.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // FIXME: Record the font size used for this piece of text, and actually retry with a smaller size if needed.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-14 17:19:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // FIXME: 10. 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:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //            ...
 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-22 11:48:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-14 17:19:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 11. 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.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-20 01:09:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    PreparedText  prepared_text  {  move ( glyph_runs ) ,  Gfx : : TextAlignment : : CenterLeft ,  {  0 ,  0 ,  width ,  height  }  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-14 17:19:45 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 12. Return result, physical alignment, and the inline box.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 22:15:38 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  prepared_text ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-08 15:12:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : clip_internal ( Gfx : : Path &  path ,  Gfx : : WindingRule  winding_rule )  
						 
					
						
							
								
									
										
										
										
											2022-04-10 18:48:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:19:25 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto *  painter  =  this - > painter ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! painter ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-08 15:12:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:19:25 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . close_all_subpaths ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    painter - > clip ( 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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    clip_internal ( 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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2024-08-15 07:36:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    clip_internal ( path . path ( ) ,  parse_fill_rule ( fill_rule ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-10 18:48:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-18 10:52:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  bool  is_point_in_path_internal ( Gfx : : Path  path ,  double  x ,  double  y ,  StringView  fill_rule )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  path . contains ( Gfx : : FloatPoint ( x ,  y ) ,  parse_fill_rule ( fill_rule ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  CanvasRenderingContext2D : : is_point_in_path ( double  x ,  double  y ,  StringView  fill_rule )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  is_point_in_path_internal ( path ( ) ,  x ,  y ,  fill_rule ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  CanvasRenderingContext2D : : is_point_in_path ( Path2D  const &  path ,  double  x ,  double  y ,  StringView  fill_rule )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  is_point_in_path_internal ( path . path ( ) ,  x ,  y ,  fill_rule ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < 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.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( ! image_element - > immutable_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.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( image_element - > immutable_bitmap ( ) - > width ( )  = =  0  | |  image_element - > immutable_bitmap ( ) - > height ( )  = =  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                return  {  CanvasImageSourceUsability : : Bad  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  Optional < CanvasImageSourceUsability >  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-04 14:39:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        // FIXME: Don't duplicate this for HTMLImageElement and SVGImageElement.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < SVG : : SVGImageElement >  const &  image_element )  - >  WebIDL : : ExceptionOr < Optional < CanvasImageSourceUsability > >  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-04 14:39:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // FIXME: If image's current request's state is broken, then throw an "InvalidStateError" DOMException.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // If image is not fully decodable, then return bad.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( ! image_element - > current_image_bitmap ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-04 14:39:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                return  {  CanvasImageSourceUsability : : Bad  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // If image has an intrinsic width or intrinsic height (or both) equal to zero, then return bad.
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( image_element - > current_image_bitmap ( ) - > width ( )  = =  0  | |  image_element - > current_image_bitmap ( ) - > height ( )  = =  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-04 14:39:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                return  {  CanvasImageSourceUsability : : Bad  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  Optional < CanvasImageSourceUsability >  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < HTML : : HTMLVideoElement >  const &  video_element )  - >  WebIDL : : ExceptionOr < Optional < CanvasImageSourceUsability > >  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-05 03:38:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // If image's readyState attribute is either HAVE_NOTHING or HAVE_METADATA, then return bad.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( video_element - > ready_state ( )  = =  HTML : : HTMLMediaElement : : ReadyState : : HaveNothing  | |  video_element - > ready_state ( )  = =  HTML : : HTMLMediaElement : : ReadyState : : HaveMetadata )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  {  CanvasImageSourceUsability : : Bad  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  Optional < CanvasImageSourceUsability >  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // HTMLCanvasElement
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // FIXME: OffscreenCanvas
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < 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 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-12 20:56:21 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                return  WebIDL : : InvalidStateError : : create ( canvas_element - > realm ( ) ,  " Canvas width or height is zero " _string ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  Optional < CanvasImageSourceUsability >  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-05 09:15:45 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // ImageBitmap
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // FIXME: VideoFrame
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < ImageBitmap >  const &  image_bitmap )  - >  WebIDL : : ExceptionOr < Optional < CanvasImageSourceUsability > >  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-05 09:15:45 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( image_bitmap - > is_detached ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-12 20:56:21 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                return  WebIDL : : InvalidStateError : : create ( image_bitmap - > realm ( ) ,  " Image bitmap is detached " _string ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-05 09:15:45 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            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
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < HTMLImageElement >  const & )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // FIXME: image's current request's image data is CORS-cross-origin.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < SVG : : SVGImageElement >  const & )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-04 14:39:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // FIXME: image's current request's image data is CORS-cross-origin.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( GC : : Root < HTML : : HTMLVideoElement >  const & )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-05 03:38:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            // FIXME: image's media data is CORS-cross-origin.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } , 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-04 19:02:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        // HTMLCanvasElement
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-15 04:01:23 +13:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        [ ] ( OneOf < GC : : Root < HTMLCanvasElement > ,  GC : : Root < 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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define ENUMERATE_COMPOSITE_OPERATIONS(E)  \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " normal " ,  Normal )                     \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " multiply " ,  Multiply )                 \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " screen " ,  Screen )                     \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " overlay " ,  Overlay )                   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " darken " ,  Darken )                     \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " lighten " ,  Lighten )                   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " color-dodge " ,  ColorDodge )            \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " color-burn " ,  ColorBurn )              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " hard-light " ,  HardLight )              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " soft-light " ,  SoftLight )              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " difference " ,  Difference )             \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " exclusion " ,  Exclusion )               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " hue " ,  Hue )                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " saturation " ,  Saturation )             \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " color " ,  Color )                       \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " luminosity " ,  Luminosity )             \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " clear " ,  Clear )                       \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " copy " ,  Copy )                         \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " source-over " ,  SourceOver )            \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " destination-over " ,  DestinationOver )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " source-in " ,  SourceIn )                \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " destination-in " ,  DestinationIn )      \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " source-out " ,  SourceOut )              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " destination-out " ,  DestinationOut )    \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " source-atop " ,  SourceATop )            \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " destination-atop " ,  DestinationATop )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " xor " ,  Xor )                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " lighter " ,  Lighter )                   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " plus-darker " ,  PlusDarker )            \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    E ( " plus-lighter " ,  PlusLighter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								String  CanvasRenderingContext2D : : global_composite_operation ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  current_compositing_and_blending_operator  =  drawing_state ( ) . current_compositing_and_blending_operator ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    switch  ( current_compositing_and_blending_operator )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef __ENUMERATE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define __ENUMERATE(operation, compositing_and_blending_operator)                \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  Gfx : : CompositingAndBlendingOperator : : compositing_and_blending_operator :  \
							 
						 
					
						
							
								
									
										
										
										
											2025-02-23 20:24:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  operation # # _string ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        ENUMERATE_COMPOSITE_OPERATIONS ( __ENUMERATE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef __ENUMERATE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        VERIFY_NOT_REACHED ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-globalcompositeoperation
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_global_composite_operation ( String  global_composite_operation )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. If the given value is not identical to any of the values that the <blend-mode> or the <composite-mode> properties are defined to take, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. Otherwise, set this's current compositing and blending operator to the given value.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef __ENUMERATE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define __ENUMERATE(operation, compositing_and_blending_operator)                                                                           \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( global_composite_operation  = =  operation # # sv )  {                                                                                       \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        drawing_state ( ) . current_compositing_and_blending_operator  =  Gfx : : CompositingAndBlendingOperator : : compositing_and_blending_operator ;  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ;                                                                                                                              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ENUMERATE_COMPOSITE_OPERATIONS ( __ENUMERATE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef __ENUMERATE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-18 01:56:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								float  CanvasRenderingContext2D : : shadow_offset_x ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  drawing_state ( ) . shadow_offset_x ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_shadow_offset_x ( float  offsetX )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowoffsetx
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    drawing_state ( ) . shadow_offset_x  =  offsetX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								float  CanvasRenderingContext2D : : shadow_offset_y ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  drawing_state ( ) . shadow_offset_y ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_shadow_offset_y ( float  offsetY )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowoffsety
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    drawing_state ( ) . shadow_offset_y  =  offsetY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-03 21:22:44 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								float  CanvasRenderingContext2D : : shadow_blur ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  drawing_state ( ) . shadow_blur ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_shadow_blur ( float  blur_radius )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // On setting, the attribute must be set to the new value,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // except if the value is negative, infinite or NaN, in which case the new value must be ignored.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( blur_radius  <  0  | |  isinf ( blur_radius )  | |  isnan ( blur_radius ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    drawing_state ( ) . shadow_blur  =  blur_radius ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-18 01:56:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								String  CanvasRenderingContext2D : : shadow_color ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowcolor
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  drawing_state ( ) . shadow_color . to_string ( Gfx : : Color : : HTMLCompatibleSerialization : : Yes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_shadow_color ( String  color )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. Let context be this's canvas attribute's value, if that is an element; otherwise null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. Let parsedValue be the result of parsing the given value with context if non-null.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 12:08:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  style_value  =  parse_css_value ( CSS : : Parser : : ParsingParams ( ) ,  color ,  CSS : : PropertyID : : Color ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-18 01:56:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( style_value  & &  style_value - > has_color ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  parsedValue  =  style_value - > to_color ( OptionalNone ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // 4. Set this's shadow color to parsedValue.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        drawing_state ( ) . shadow_color  =  parsedValue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // 3. If parsedValue is failure, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : paint_shadow_for_fill_internal ( Gfx : : Path  const &  path ,  Gfx : : WindingRule  winding_rule )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto *  painter  =  this - > painter ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! painter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  path_to_fill  =  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path_to_fill . close_all_subpaths ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto &  state  =  this - > drawing_state ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( state . current_compositing_and_blending_operator  = =  Gfx : : CompositingAndBlendingOperator : : Copy ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-18 01:56:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    painter - > save ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Gfx : : AffineTransform  transform ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    transform . translate ( state . shadow_offset_x ,  state . shadow_offset_y ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    painter - > set_transform ( transform ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    painter - > fill_path ( path_to_fill ,  state . shadow_color . with_opacity ( state . global_alpha ) ,  winding_rule ,  state . shadow_blur ,  state . current_compositing_and_blending_operator ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-18 01:56:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    painter - > restore ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    did_draw ( path_to_fill . bounding_box ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : paint_shadow_for_stroke_internal ( Gfx : : Path  const &  path )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto *  painter  =  this - > painter ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! painter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto &  state  =  drawing_state ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( state . current_compositing_and_blending_operator  = =  Gfx : : CompositingAndBlendingOperator : : Copy ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-18 01:56:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    painter - > save ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Gfx : : AffineTransform  transform ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    transform . translate ( state . shadow_offset_x ,  state . shadow_offset_y ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    painter - > set_transform ( transform ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    painter - > stroke_path ( path ,  state . shadow_color . with_opacity ( state . global_alpha ) ,  state . line_width ,  state . shadow_blur ,  state . current_compositing_and_blending_operator ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-18 01:56:58 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    painter - > restore ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    did_draw ( path . bounding_box ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								String  CanvasRenderingContext2D : : filter ( )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! drawing_state ( ) . filter_string . has_value ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  String : : from_utf8_without_validation ( " none " sv . bytes ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  drawing_state ( ) . filter_string . value ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-filter
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  CanvasRenderingContext2D : : set_filter ( String  filter )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    drawing_state ( ) . filter . clear ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. If the given value is "none", then set this's current filter to "none" and return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( filter  = =  " none " sv )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        drawing_state ( ) . filter_string . clear ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto &  realm  =  static_cast < CanvasRenderingContext2D & > ( * this ) . realm ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 12:08:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  parser  =  CSS : : Parser : : Parser : : create ( CSS : : Parser : : ParsingParams ( realm ) ,  filter ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. Let parsedValue be the result of parsing the given values as a <filter-value-list>.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    If any property-independent style sheet syntax like 'inherit' or 'initial' is present,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    then this parsing must return failure.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  style_value  =  parser . parse_as_css_value ( CSS : : PropertyID : : Filter ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( style_value  & &  style_value - > is_filter_value_list ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  filter_value_list  =  style_value - > as_filter_value_list ( ) . filter_value_list ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Note: The layout must be updated to make sure the canvas's layout node isn't null.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-05 20:50:05 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        canvas_element ( ) . document ( ) . update_layout ( DOM : : UpdateLayoutReason : : CanvasRenderingContext2DSetFilter ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        auto  layout_node  =  canvas_element ( ) . layout_node ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // 4. Set this's current filter to the given value.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( auto &  item  :  filter_value_list )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // FIXME: Add support for SVG filters when they get implement by the CSS parser.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            item . visit ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ & ] ( CSS : : FilterOperation : : Blur  const &  blur_filter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    float  radius  =  blur_filter . resolved_radius ( * layout_node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    auto  new_filter  =  Gfx : : Filter : : blur ( radius ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    drawing_state ( ) . filter  =  drawing_state ( ) . filter . has_value ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ?  Gfx : : Filter : : compose ( new_filter ,  * drawing_state ( ) . filter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        :  new_filter ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ & ] ( CSS : : FilterOperation : : Color  const &  color )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    float  amount  =  color . resolved_amount ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    auto  new_filter  =  Gfx : : Filter : : color ( color . operation ,  amount ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    drawing_state ( ) . filter  =  drawing_state ( ) . filter . has_value ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ?  Gfx : : Filter : : compose ( new_filter ,  * drawing_state ( ) . filter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        :  new_filter ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ & ] ( CSS : : FilterOperation : : HueRotate  const &  hue_rotate )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    float  angle  =  hue_rotate . angle_degrees ( * layout_node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    auto  new_filter  =  Gfx : : Filter : : hue_rotate ( angle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    drawing_state ( ) . filter  =  drawing_state ( ) . filter . has_value ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ?  Gfx : : Filter : : compose ( new_filter ,  * drawing_state ( ) . filter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        :  new_filter ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ & ] ( CSS : : FilterOperation : : DropShadow  const &  drop_shadow )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    auto  resolution_context  =  CSS : : Length : : ResolutionContext : : for_layout_node ( * layout_node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-22 15:00:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    CSS : : CalculationResolutionContext  calculation_context  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        . length_resolution_context  =  resolution_context , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    auto  zero_px  =  CSS : : Length : : make_px ( 0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-22 15:00:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    float  offset_x  =  static_cast < float > ( drop_shadow . offset_x . resolved ( calculation_context ) . value_or ( zero_px ) . to_px ( resolution_context ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    float  offset_y  =  static_cast < float > ( drop_shadow . offset_y . resolved ( calculation_context ) . value_or ( zero_px ) . to_px ( resolution_context ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    float  radius  =  0.0f ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  ( drop_shadow . radius . has_value ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-22 15:00:13 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        radius  =  static_cast < float > ( drop_shadow . radius - > resolved ( calculation_context ) . value_or ( zero_px ) . to_px ( resolution_context ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    auto  color  =  drop_shadow . color . value_or ( Gfx : : Color  {  0 ,  0 ,  0 ,  255  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    auto  new_filter  =  Gfx : : Filter : : drop_shadow ( offset_x ,  offset_y ,  radius ,  color ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    drawing_state ( ) . filter  =  drawing_state ( ) . filter . has_value ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ?  Gfx : : Filter : : compose ( new_filter ,  * drawing_state ( ) . filter ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        :  new_filter ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-11 12:44:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        drawing_state ( ) . filter_string  =  move ( filter ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 12:26:37 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 3. If parsedValue is failure, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2025-05-13 07:06:33 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 19:07:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}