| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2023-01-19 19:10:00 +01:00
										 |  |  |  * Copyright (c) 2023, MacDue <macdue@dueutil.tech> | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-05 15:16:35 +01:00
										 |  |  | #include <AK/QuickSort.h>
 | 
					
						
							| 
									
										
										
										
											2022-09-25 16:38:21 -06:00
										 |  |  | #include <LibWeb/Bindings/Intrinsics.h>
 | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | #include <LibWeb/HTML/CanvasGradient.h>
 | 
					
						
							| 
									
										
										
										
											2022-09-25 17:03:42 +01:00
										 |  |  | #include <LibWeb/WebIDL/ExceptionOr.h>
 | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Web::HTML { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 00:05:10 +00:00
										 |  |  | // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createradialgradient
 | 
					
						
							|  |  |  | WebIDL::ExceptionOr<JS::NonnullGCPtr<CanvasGradient>> CanvasGradient::create_radial(JS::Realm& realm, double x0, double y0, double r0, double x1, double y1, double r1) | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-28 00:05:10 +00:00
										 |  |  |     // If either of r0 or r1 are negative, then an "IndexSizeError" DOMException must be thrown.
 | 
					
						
							|  |  |  |     if (r0 < 0) | 
					
						
							|  |  |  |         return WebIDL::IndexSizeError::create(realm, "The r0 passed is less than 0"); | 
					
						
							|  |  |  |     if (r1 < 0) | 
					
						
							|  |  |  |         return WebIDL::IndexSizeError::create(realm, "The r1 passed is less than 0"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-01 23:01:59 +00:00
										 |  |  |     auto radial_gradient = TRY_OR_THROW_OOM(realm.vm(), Gfx::CanvasRadialGradientPaintStyle::create(Gfx::FloatPoint { x0, y0 }, r0, Gfx::FloatPoint { x1, y1 }, r1)); | 
					
						
							| 
									
										
										
										
											2023-08-13 13:05:26 +02:00
										 |  |  |     return realm.heap().allocate<CanvasGradient>(realm, realm, *radial_gradient); | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 00:10:54 +00:00
										 |  |  | // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createlineargradient
 | 
					
						
							| 
									
										
										
										
											2023-02-15 08:46:39 +01:00
										 |  |  | WebIDL::ExceptionOr<JS::NonnullGCPtr<CanvasGradient>> CanvasGradient::create_linear(JS::Realm& realm, double x0, double y0, double x1, double y1) | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-01 23:01:59 +00:00
										 |  |  |     auto linear_gradient = TRY_OR_THROW_OOM(realm.vm(), Gfx::CanvasLinearGradientPaintStyle::create(Gfx::FloatPoint { x0, y0 }, Gfx::FloatPoint { x1, y1 })); | 
					
						
							| 
									
										
										
										
											2023-08-13 13:05:26 +02:00
										 |  |  |     return realm.heap().allocate<CanvasGradient>(realm, realm, *linear_gradient); | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 00:10:54 +00:00
										 |  |  | // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createconicgradient
 | 
					
						
							| 
									
										
										
										
											2023-02-15 08:46:39 +01:00
										 |  |  | WebIDL::ExceptionOr<JS::NonnullGCPtr<CanvasGradient>> CanvasGradient::create_conic(JS::Realm& realm, double start_angle, double x, double y) | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-01 23:01:59 +00:00
										 |  |  |     auto conic_gradient = TRY_OR_THROW_OOM(realm.vm(), Gfx::CanvasConicGradientPaintStyle::create(Gfx::FloatPoint { x, y }, start_angle)); | 
					
						
							| 
									
										
										
										
											2023-08-13 13:05:26 +02:00
										 |  |  |     return realm.heap().allocate<CanvasGradient>(realm, realm, *conic_gradient); | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 19:10:00 +01:00
										 |  |  | CanvasGradient::CanvasGradient(JS::Realm& realm, Gfx::GradientPaintStyle& gradient) | 
					
						
							| 
									
										
										
										
											2022-09-25 16:38:21 -06:00
										 |  |  |     : PlatformObject(realm) | 
					
						
							| 
									
										
										
										
											2023-01-19 19:10:00 +01:00
										 |  |  |     , m_gradient(gradient) | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-14 13:21:51 -06:00
										 |  |  | CanvasGradient::~CanvasGradient() = default; | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-07 08:41:28 +02:00
										 |  |  | void CanvasGradient::initialize(JS::Realm& realm) | 
					
						
							| 
									
										
										
										
											2023-01-10 06:28:20 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-07 08:41:28 +02:00
										 |  |  |     Base::initialize(realm); | 
					
						
							| 
									
										
										
										
											2023-01-10 06:28:20 -05:00
										 |  |  |     set_prototype(&Bindings::ensure_web_prototype<Bindings::CanvasGradientPrototype>(realm, "CanvasGradient")); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-05 15:16:35 +01:00
										 |  |  | // https://html.spec.whatwg.org/multipage/canvas.html#dom-canvasgradient-addcolorstop
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:02:33 +00:00
										 |  |  | WebIDL::ExceptionOr<void> CanvasGradient::add_color_stop(double offset, DeprecatedString const& color) | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-05 15:16:35 +01:00
										 |  |  |     // 1. If the offset is less than 0 or greater than 1, then throw an "IndexSizeError" DOMException.
 | 
					
						
							|  |  |  |     if (offset < 0 || offset > 1) | 
					
						
							| 
									
										
										
										
											2022-09-25 16:38:21 -06:00
										 |  |  |         return WebIDL::IndexSizeError::create(realm(), "CanvasGradient color stop offset out of bounds"); | 
					
						
							| 
									
										
										
										
											2022-02-05 15:16:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 2. Let parsed color be the result of parsing color.
 | 
					
						
							|  |  |  |     auto parsed_color = Color::from_string(color); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 3. If parsed color is failure, throw a "SyntaxError" DOMException.
 | 
					
						
							|  |  |  |     if (!parsed_color.has_value()) | 
					
						
							| 
									
										
										
										
											2022-09-25 16:38:21 -06:00
										 |  |  |         return WebIDL::SyntaxError::create(realm(), "Could not parse color for CanvasGradient"); | 
					
						
							| 
									
										
										
										
											2022-02-05 15:16:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // 4. Place a new stop on the gradient, at offset offset relative to the whole gradient, and with the color parsed color.
 | 
					
						
							| 
									
										
										
										
											2023-03-01 23:02:27 +00:00
										 |  |  |     TRY_OR_THROW_OOM(realm().vm(), m_gradient->add_color_stop(offset, parsed_color.value())); | 
					
						
							| 
									
										
										
										
											2022-02-05 15:16:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // FIXME: If multiple stops are added at the same offset on a gradient, then they must be placed in the order added,
 | 
					
						
							|  |  |  |     //        with the first one closest to the start of the gradient, and each subsequent one infinitesimally further along
 | 
					
						
							|  |  |  |     //        towards the end point (in effect causing all but the first and last stop added at each point to be ignored).
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2022-02-03 20:08:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |