| 
									
										
										
										
											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
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 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!
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-10 15:54:49 +02:00
										 |  |  |  | float color_stop_step(ColorStop const& previous_stop, ColorStop const& next_stop, float position) | 
					
						
							| 
									
										
										
										
											2023-01-10 01:07:06 +00:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |     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’s location as a percentage of the distance between the two color stops.
 | 
					
						
							|  |  |  |  |     // 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-05-02 22:43:46 +01:00
										 |  |  |  | void SVGGradientPaintStyle::set_gradient_transform(AffineTransform transform) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     // Note: The scaling is removed so enough points on the gradient line are generated.
 | 
					
						
							|  |  |  |  |     // Otherwise, if you scale a tiny path the gradient looks pixelated.
 | 
					
						
							|  |  |  |  |     m_scale = 1.0f; | 
					
						
							|  |  |  |  |     if (auto inverse = transform.inverse(); inverse.has_value()) { | 
					
						
							|  |  |  |  |         auto transform_scale = transform.scale(); | 
					
						
							|  |  |  |  |         m_scale = max(transform_scale.x(), transform_scale.y()); | 
					
						
							|  |  |  |  |         m_inverse_transform = AffineTransform {}.scale(m_scale, m_scale).multiply(*inverse); | 
					
						
							|  |  |  |  |     } else { | 
					
						
							|  |  |  |  |         m_inverse_transform = OptionalNone {}; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-10 01:07:06 +00:00
										 |  |  |  | } |