2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  Copyright  ( c )  2022 - 2023 ,  MacDue  < macdue @ dueutil . tech > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  SPDX - License - Identifier :  BSD - 2 - Clause 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# include  <AK/Math.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# include  <LibGfx/Gradients.h> 
  
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								# include  <LibGfx/PaintStyle.h> 
  
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# include  <LibGfx/Painter.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# if defined(AK_COMPILER_GCC) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     pragma GCC optimize("O3") 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								namespace  Gfx  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-17 19:52:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// Note: This file implements the CSS/Canvas gradients for LibWeb according to the spec.
  
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								// Please do not make ad-hoc changes that may break spec compliance!
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								static  float  color_stop_step ( ColorStop  const &  previous_stop ,  ColorStop  const &  next_stop ,  float  position )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( position  <  previous_stop . position ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( position  >  next_stop . position ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // For any given point between the two color stops,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								    // determine the point’  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Let this percentage be P.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  stop_length  =  next_stop . position  -  previous_stop . position ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // FIXME: Avoids NaNs... Still not quite correct?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( stop_length  < =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  p  =  ( position  -  previous_stop . position )  /  stop_length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! next_stop . transition_hint . has_value ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  p ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( * next_stop . transition_hint  > =  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( * next_stop . transition_hint  < =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Let C, the color weighting at that point, be equal to P^(logH(.5)).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  c  =  AK : : pow ( p ,  AK : : log < float > ( 0.5 )  /  AK : : log ( * next_stop . transition_hint ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // The color at that point is then a linear blend between the colors of the two color stops,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // blending (1 - C) of the first stop and C of the second stop.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  c ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								enum  class  UsePremultipliedAlpha  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Yes , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    No 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								class  GradientLine  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								public :  
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    GradientLine ( int  gradient_length ,  Span < ColorStop  const >  color_stops ,  Optional < float >  repeat_length ,  UsePremultipliedAlpha  use_premultiplied_alpha  =  UsePremultipliedAlpha : : Yes ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        :  m_repeating  {  repeat_length . has_value ( )  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        ,  m_start_offset  {  round_to < int > ( ( m_repeating  ?  color_stops . first ( ) . position  :  0.0f )  *  gradient_length )  } 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-23 00:35:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        ,  m_color_stops  {  color_stops  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        ,  m_use_premultiplied_alpha  {  use_premultiplied_alpha  } 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // Avoid generating excessive amounts of colors when the not enough shades to fill that length.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  necessary_length  =  min < int > ( ( color_stops . size ( )  -  1 )  *  255 ,  gradient_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        m_sample_scale  =  float ( necessary_length )  /  gradient_length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // Note: color_count will be < gradient_length for repeating gradients.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  color_count  =  round_to < int > ( repeat_length . value_or ( 1.0f )  *  necessary_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        m_gradient_line_colors . resize ( color_count ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        for  ( int  loc  =  0 ;  loc  <  color_count ;  loc + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  relative_loc  =  float ( loc  +  m_start_offset )  /  necessary_length ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								            Color  gradient_color  =  color_blend ( color_stops [ 0 ] . color ,  color_stops [ 1 ] . color , 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                color_stop_step ( color_stops [ 0 ] ,  color_stops [ 1 ] ,  relative_loc ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            for  ( size_t  i  =  1 ;  i  <  color_stops . size ( )  -  1 ;  i + + )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								                gradient_color  =  color_blend ( gradient_color ,  color_stops [ i  +  1 ] . color , 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    color_stop_step ( color_stops [ i ] ,  color_stops [ i  +  1 ] ,  relative_loc ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            m_gradient_line_colors [ loc ]  =  gradient_color ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if  ( gradient_color . alpha ( )  <  255 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                m_requires_blending  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-23 00:35:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    Color  color_blend ( Color  a ,  Color  b ,  float  amount )  const 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // Note: color.mixed_with() performs premultiplied alpha mixing when necessary as defined in:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // https://drafts.csswg.org/css-images/#coloring-gradient-line
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( m_use_premultiplied_alpha  = =  UsePremultipliedAlpha : : Yes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  a . mixed_with ( b ,  amount ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  a . interpolate ( b ,  amount ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Color  get_color ( i64  index )  const 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-23 00:35:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( index  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  m_color_stops . first ( ) . color ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( index  > =  static_cast < i64 > ( m_gradient_line_colors . size ( ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  m_color_stops . last ( ) . color ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  m_gradient_line_colors [ index ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Color  sample_color ( float  loc )  const 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-17 19:52:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( ! isfinite ( loc ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  Color ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( m_sample_scale  ! =  1.0f ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            loc  * =  m_sample_scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  repeat_wrap_if_required  =  [ & ] ( i64  loc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if  ( m_repeating ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                return  ( loc  +  m_start_offset )  %  static_cast < i64 > ( m_gradient_line_colors . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  loc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  int_loc  =  static_cast < i64 > ( floor ( loc ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  blend  =  loc  -  int_loc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  color  =  get_color ( repeat_wrap_if_required ( int_loc ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // Blend between the two neighbouring colors (this fixes some nasty aliasing issues at small angles)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( blend  > =  0.004f ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-23 00:35:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								            color  =  color_blend ( color ,  get_color ( repeat_wrap_if_required ( int_loc  +  1 ) ) ,  blend ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  color ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    void  paint_into_physical_rect ( Painter &  painter ,  IntRect  rect ,  auto  location_transform ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  clipped_rect  =  rect . intersected ( painter . clip_rect ( )  *  painter . scale ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        auto  start_offset  =  clipped_rect . location ( )  -  rect . location ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        for  ( int  y  =  0 ;  y  <  clipped_rect . height ( ) ;  y + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            for  ( int  x  =  0 ;  x  <  clipped_rect . width ( ) ;  x + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                auto  pixel  =  sample_color ( location_transform ( x  +  start_offset . x ( ) ,  y  +  start_offset . y ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                painter . set_physical_pixel ( clipped_rect . location ( ) . translated ( x ,  y ) ,  pixel ,  m_requires_blending ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								private :  
						 
					
						
							
								
									
										
										
										
											2023-01-23 00:35:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    bool  m_repeating  {  false  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    int  m_start_offset  {  0  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    float  m_sample_scale  {  1  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-23 00:35:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    Span < ColorStop  const >  m_color_stops  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    UsePremultipliedAlpha  m_use_premultiplied_alpha  {  UsePremultipliedAlpha : : Yes  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-23 00:35:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    Vector < Color ,  1024 >  m_gradient_line_colors ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    bool  m_requires_blending  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								template < typename  TransformFunction >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								struct  Gradient  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Gradient ( GradientLine  gradient_line ,  TransformFunction  transform_function ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        :  m_gradient_line ( move ( gradient_line ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        ,  m_transform_function ( move ( transform_function ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    void  paint ( Painter &  painter ,  IntRect  rect ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        m_gradient_line . paint_into_physical_rect ( painter ,  rect ,  m_transform_function ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    PaintStyle : : SamplerFunction  sample_function ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  [ this ] ( IntPoint  point )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  m_gradient_line . sample_color ( m_transform_function ( point . x ( ) ,  point . y ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    GradientLine  m_gradient_line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    TransformFunction  m_transform_function ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-29 13:28:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								static  auto  create_linear_gradient ( IntRect  const &  physical_rect ,  Span < ColorStop  const >  color_stops ,  float  angle ,  Optional < float >  repeat_length )  
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    float  normalized_angle  =  normalized_gradient_angle_radians ( angle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    float  sin_angle ,  cos_angle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    AK : : sincos ( normalized_angle ,  sin_angle ,  cos_angle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Full length of the gradient
 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    auto  gradient_length  =  calculate_gradient_length ( physical_rect . size ( ) ,  sin_angle ,  cos_angle ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    IntPoint  offset  {  cos_angle  *  ( gradient_length  /  2 ) ,  sin_angle  *  ( gradient_length  /  2 )  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    auto  center  =  physical_rect . translated ( - physical_rect . location ( ) ) . center ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  start_point  =  center  -  offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Rotate gradient line to be horizontal
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  rotated_start_point_x  =  start_point . x ( )  *  cos_angle  -  start_point . y ( )  *  - sin_angle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    GradientLine  gradient_line ( gradient_length ,  color_stops ,  repeat_length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    return  Gradient  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        move ( gradient_line ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        [ = ] ( int  x ,  int  y )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  ( x  *  cos_angle  -  ( physical_rect . height ( )  -  y )  *  - sin_angle )  -  rotated_start_point_x ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-29 13:28:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								static  auto  create_conic_gradient ( Span < ColorStop  const >  color_stops ,  FloatPoint  center_point ,  float  start_angle ,  Optional < float >  repeat_length ,  UsePremultipliedAlpha  use_premultiplied_alpha  =  UsePremultipliedAlpha : : Yes )  
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // FIXME: Do we need/want sub-degree accuracy for the gradient line?
 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    GradientLine  gradient_line ( 360 ,  color_stops ,  repeat_length ,  use_premultiplied_alpha ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    float  normalized_start_angle  =  ( 360.0f  -  start_angle )  +  90.0f ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // The flooring can make gradients that want soft edges look worse, so only floor if we have hard edges.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Which makes sure the hard edge stay hard edges :^)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    bool  should_floor_angles  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    for  ( size_t  i  =  0 ;  i  <  color_stops . size ( )  -  1 ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( color_stops [ i  +  1 ] . position  -  color_stops [ i ] . position  < =  0.01f )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            should_floor_angles  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    return  Gradient  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        move ( gradient_line ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        [ = ] ( int  x ,  int  y )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  point  =  FloatPoint  {  x ,  y  }  -  center_point ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            // FIXME: We could probably get away with some approximation here:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  loc  =  fmod ( ( AK : : atan2 ( point . y ( ) ,  point . x ( ) )  *  180.0f  /  AK : : Pi < float >  +  360.0f  +  normalized_start_angle ) ,  360.0f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  should_floor_angles  ?  floor ( loc )  :  loc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-29 13:28:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								static  auto  create_radial_gradient ( IntRect  const &  physical_rect ,  Span < ColorStop  const >  color_stops ,  IntPoint  center ,  IntSize  size ,  Optional < float >  repeat_length )  
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // A conservative guesstimate on how many colors we need to generate:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  max_dimension  =  max ( physical_rect . width ( ) ,  physical_rect . height ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  max_visible_gradient  =  max ( max_dimension  /  2 ,  min ( size . width ( ) ,  max_dimension ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    GradientLine  gradient_line ( max_visible_gradient ,  color_stops ,  repeat_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  center_point  =  FloatPoint  {  center  } . translated ( 0.5 ,  0.5 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  Gradient  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        move ( gradient_line ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        [ = ] ( int  x ,  int  y )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            // FIXME: See if there's a more efficient calculation we do there :^)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  point  =  FloatPoint ( x ,  y )  -  center_point ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  gradient_x  =  point . x ( )  /  size . width ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  gradient_y  =  point . y ( )  /  size . height ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  AK : : sqrt ( gradient_x  *  gradient_x  +  gradient_y  *  gradient_y )  *  max_visible_gradient ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-29 13:28:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								void  Painter : : fill_rect_with_linear_gradient ( IntRect  const &  rect ,  Span < ColorStop  const >  color_stops ,  float  angle ,  Optional < float >  repeat_length )  
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  a_rect  =  to_physical ( rect ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( a_rect . intersected ( clip_rect ( )  *  scale ( ) ) . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  linear_gradient  =  create_linear_gradient ( a_rect ,  color_stops ,  angle ,  repeat_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    linear_gradient . paint ( * this ,  a_rect ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								static  FloatPoint  pixel_center ( IntPoint  point )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  point . to_type < float > ( ) . translated ( 0.5f ,  0.5f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-29 13:28:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								void  Painter : : fill_rect_with_conic_gradient ( IntRect  const &  rect ,  Span < ColorStop  const >  color_stops ,  IntPoint  center ,  float  start_angle ,  Optional < float >  repeat_length )  
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  a_rect  =  to_physical ( rect ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( a_rect . intersected ( clip_rect ( )  *  scale ( ) ) . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Translate position/center to the center of the pixel (avoids some funky painting)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  center_point  =  pixel_center ( center  *  scale ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  conic_gradient  =  create_conic_gradient ( color_stops ,  center_point ,  start_angle ,  repeat_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    conic_gradient . paint ( * this ,  a_rect ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-29 13:28:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								void  Painter : : fill_rect_with_radial_gradient ( IntRect  const &  rect ,  Span < ColorStop  const >  color_stops ,  IntPoint  center ,  IntSize  size ,  Optional < float >  repeat_length )  
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  a_rect  =  to_physical ( rect ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( a_rect . intersected ( clip_rect ( )  *  scale ( ) ) . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    auto  radial_gradient  =  create_radial_gradient ( a_rect ,  color_stops ,  center  *  scale ( ) ,  size  *  scale ( ) ,  repeat_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    radial_gradient . paint ( * this ,  a_rect ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-15 22:10:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// TODO: Figure out how to handle scale() here... Not important while not supported by fill_path()
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  LinearGradientPaintStyle : : paint ( IntRect  physical_bounding_box ,  PaintFunction  paint )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    VERIFY ( color_stops ( ) . size ( )  >  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  linear_gradient  =  create_linear_gradient ( physical_bounding_box ,  color_stops ( ) ,  m_angle ,  repeat_length ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    paint ( linear_gradient . sample_function ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  ConicGradientPaintStyle : : paint ( IntRect  physical_bounding_box ,  PaintFunction  paint )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    VERIFY ( color_stops ( ) . size ( )  >  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    ( void ) physical_bounding_box ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  conic_gradient  =  create_conic_gradient ( color_stops ( ) ,  pixel_center ( m_center ) ,  m_start_angle ,  repeat_length ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    paint ( conic_gradient . sample_function ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  RadialGradientPaintStyle : : paint ( IntRect  physical_bounding_box ,  PaintFunction  paint )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    VERIFY ( color_stops ( ) . size ( )  >  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  radial_gradient  =  create_radial_gradient ( physical_bounding_box ,  color_stops ( ) ,  m_center ,  m_size ,  repeat_length ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    paint ( radial_gradient . sample_function ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-17 19:52:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								// The following implements the gradient fill/stoke styles for the HTML canvas: https://html.spec.whatwg.org/multipage/canvas.html#fill-and-stroke-styles
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								static  auto  make_sample_non_relative ( IntPoint  draw_location ,  auto  sample )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  [ = ,  sample  =  move ( sample ) ] ( IntPoint  point )  {  return  sample ( point . translated ( draw_location ) ) ;  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasLinearGradientPaintStyle : : paint ( IntRect  physical_bounding_box ,  PaintFunction  paint )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( m_p0  = =  m_p1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( color_stops ( ) . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( color_stops ( ) . size ( )  <  2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  paint ( [ this ] ( IntPoint )  {  return  color_stops ( ) . first ( ) . color ;  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  delta  =  m_p1  -  m_p0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  angle  =  AK : : atan2 ( delta . y ( ) ,  delta . x ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    float  sin_angle ,  cos_angle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    AK : : sincos ( angle ,  sin_angle ,  cos_angle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    int  gradient_length  =  ceilf ( m_p1 . distance_from ( m_p0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  rotated_start_point_x  =  m_p0 . x ( )  *  cos_angle  -  m_p0 . y ( )  *  - sin_angle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Gradient  linear_gradient  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        GradientLine ( gradient_length ,  color_stops ( ) ,  repeat_length ( ) ,  UsePremultipliedAlpha : : No ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        [ = ] ( int  x ,  int  y )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  ( x  *  cos_angle  -  y  *  - sin_angle )  -  rotated_start_point_x ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    paint ( make_sample_non_relative ( physical_bounding_box . location ( ) ,  linear_gradient . sample_function ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasConicGradientPaintStyle : : paint ( IntRect  physical_bounding_box ,  PaintFunction  paint )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( color_stops ( ) . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( color_stops ( ) . size ( )  <  2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  paint ( [ this ] ( IntPoint )  {  return  color_stops ( ) . first ( ) . color ;  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Follows the same rendering rule as CSS 'conic-gradient' and it is equivalent to CSS
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 'conic-gradient(from adjustedStartAnglerad at xpx ypx, angularColorStopList)'.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //  Here:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //      adjustedStartAngle is given by startAngle + π/2;
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  conic_gradient  =  create_conic_gradient ( color_stops ( ) ,  m_center ,  m_start_angle  +  90.0f ,  repeat_length ( ) ,  UsePremultipliedAlpha : : No ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    paint ( make_sample_non_relative ( physical_bounding_box . location ( ) ,  conic_gradient . sample_function ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								void  CanvasRadialGradientPaintStyle : : paint ( IntRect  physical_bounding_box ,  PaintFunction  paint )  const  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 1. If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint nothing. Return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( m_start_center  = =  m_end_center  & &  m_start_radius  = =  m_end_radius ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( color_stops ( ) . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( color_stops ( ) . size ( )  <  2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  paint ( [ this ] ( IntPoint )  {  return  color_stops ( ) . first ( ) . color ;  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  start_radius  =  m_start_radius ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  start_center  =  m_start_center ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  end_radius  =  m_end_radius ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  end_center  =  m_end_center ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( end_radius  = =  0  & &  start_radius  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( fabs ( start_radius  -  end_radius )  <  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        start_radius  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Needed for the start circle > end circle case, but FIXME, this seems kind of hacky.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    bool  reverse_gradient  =  end_radius  <  start_radius ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( reverse_gradient )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        swap ( end_radius ,  start_radius ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        swap ( end_center ,  start_center ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Spec steps: Useless for writing an actual implementation (give it a go :P):
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 2. Let x(ω) = (x1-x0)ω + x0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //    Let y(ω) = (y1-y0)ω + y0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //    Let r(ω) = (r1-r0)ω + r0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Let the color at ω be the color at that position on the gradient
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // (with the colors coming from the interpolation and extrapolation described above).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // 3. For all values of ω where r(ω) > 0, starting with the value of ω nearest to positive infinity and
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // ending with the value of ω nearest to negative infinity, draw the circumference of the circle with
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // radius r(ω) at position (x(ω), y(ω)), with the color at ω, but only painting on the parts of the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // bitmap that have not yet been painted on by earlier circles in this step for this rendering of the gradient.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  center_delta  =  end_center  -  start_center ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  center_dist  =  end_center . distance_from ( start_center ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    bool  inner_contained  =  ( ( center_dist  +  start_radius )  <  end_radius ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  start_point  =  start_center ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! inner_contained )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // The intersection point of the direct common tangents of the start/end circles.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        start_point  =  FloatPoint  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            ( start_radius  *  end_center . x ( )  -  end_radius  *  start_center . x ( ) )  /  ( start_radius  -  end_radius ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            ( start_radius  *  end_center . y ( )  -  end_radius  *  start_center . y ( ) )  /  ( start_radius  -  end_radius ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // This is just an approximate upperbound (the gradient line class will shorten this if necessary).
 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-23 00:35:57 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    int  gradient_length  =  AK : : ceil ( center_dist  +  end_radius  +  start_radius ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-17 19:52:02 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    GradientLine  gradient_line ( gradient_length ,  color_stops ( ) ,  repeat_length ( ) ,  UsePremultipliedAlpha : : No ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  radius2  =  end_radius  *  end_radius ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    center_delta  =  end_center  -  start_point ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  dx2_factor  =  ( radius2  -  center_delta . y ( )  *  center_delta . y ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    auto  dy2_factor  =  ( radius2  -  center_delta . x ( )  *  center_delta . x ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // If you can simplify this please do, this is "best guess" implementation due to lack of specification.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // It was implemented to visually match chrome/firefox in all cases:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //      - Start circle inside end circle
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //      - Start circle outside end circle
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //      - Start circle radius == end circle radius
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //      - Start circle larger than end circle (inside end circle)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //      - Start circle larger than end circle (outside end circle)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    //      - Start cirlce or end circle radius == 0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Gradient  radial_gradient  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        move ( gradient_line ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        [ = ] ( int  x ,  int  y )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  get_gradient_location  =  [ & ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                FloatPoint  point  {  x ,  y  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                auto  dist  =  point . distance_from ( start_point ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                if  ( dist  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    return  0.0f ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                auto  vec  =  ( point  -  start_point )  /  dist ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                auto  dx2  =  vec . x ( )  *  vec . x ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                auto  dy2  =  vec . y ( )  *  vec . y ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                // This works out the distance to the nearest point on the end circle in the direction of the "vec" vector.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                // The "vec" vector points from the center of the start circle to the current point.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                auto  root  =  sqrtf ( dx2  *  dx2_factor  +  dy2  *  dy2_factor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    +  2  *  vec . x ( )  *  vec . y ( )  *  center_delta . x ( )  *  center_delta . y ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                auto  dot  =  vec . x ( )  *  center_delta . x ( )  +  vec . y ( )  *  center_delta . y ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                // Note: When reversed we always want the farthest point
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                auto  edge_dist  =  ( ( ( inner_contained  | |  reverse_gradient  ?  root  :  - root )  +  dot )  /  ( dx2  +  dy2 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                auto  start_offset  =  inner_contained  ?  start_radius  :  ( edge_dist  /  end_radius )  *  start_radius ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                // FIXME: Returning nan is a hack for "Don't paint me!"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                if  ( edge_dist  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    return  AK : : NaN < float > ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                if  ( edge_dist  -  start_offset  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    return  float ( gradient_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                return  ( ( dist  -  start_offset )  /  ( edge_dist  -  start_offset ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            auto  loc  =  get_gradient_location ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if  ( reverse_gradient ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                loc  =  1.0f  -  loc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            return  loc  *  gradient_length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    paint ( make_sample_non_relative ( physical_bounding_box . location ( ) ,  radial_gradient . sample_function ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-10 01:07:06 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}