CanvasFillStrokeStyles.h 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
  4. * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
  5. * Copyright (c) 2023, MacDue <macdue@dueutil.tech>
  6. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #pragma once
  10. #include <AK/String.h>
  11. #include <LibWeb/HTML/Canvas/CanvasState.h>
  12. #include <LibWeb/HTML/CanvasGradient.h>
  13. #include <LibWeb/HTML/CanvasPattern.h>
  14. namespace Web::HTML {
  15. // https://html.spec.whatwg.org/multipage/canvas.html#canvasfillstrokestyles
  16. template<typename IncludingClass>
  17. class CanvasFillStrokeStyles {
  18. public:
  19. ~CanvasFillStrokeStyles() = default;
  20. using FillOrStrokeStyleVariant = Variant<String, JS::Handle<CanvasGradient>, JS::Handle<CanvasPattern>>;
  21. static CanvasState::FillOrStrokeStyle to_canvas_state_fill_or_stroke_style(auto const& style)
  22. {
  23. return style.visit(
  24. [&](String const& string) -> CanvasState::FillOrStrokeStyle {
  25. // FIXME: This should parse color strings the same as CSS
  26. auto color = Gfx::Color::from_string(string);
  27. if (!color.has_value())
  28. dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasFillStrokeStyles: Unsupported canvas fill or stroke style \"{}\". Defaulting to Color::Black.", string);
  29. return color.value_or(Color::Black);
  30. },
  31. [&](auto fill_or_stroke_style) -> CanvasState::FillOrStrokeStyle {
  32. return fill_or_stroke_style;
  33. });
  34. }
  35. void set_fill_style(FillOrStrokeStyleVariant style)
  36. {
  37. // FIXME: 2. If the given value is a CanvasPattern object that is marked as not origin-clean, then set this's origin-clean flag to false.
  38. my_drawing_state().fill_style = to_canvas_state_fill_or_stroke_style(style);
  39. }
  40. FillOrStrokeStyleVariant fill_style() const
  41. {
  42. return my_drawing_state().fill_style.to_js_fill_or_stroke_style();
  43. }
  44. void set_stroke_style(FillOrStrokeStyleVariant style)
  45. {
  46. // FIXME: 2. If the given value is a CanvasPattern object that is marked as not origin-clean, then set this's origin-clean flag to false.
  47. my_drawing_state().stroke_style = to_canvas_state_fill_or_stroke_style(style);
  48. }
  49. FillOrStrokeStyleVariant stroke_style() const
  50. {
  51. return my_drawing_state().stroke_style.to_js_fill_or_stroke_style();
  52. }
  53. WebIDL::ExceptionOr<JS::NonnullGCPtr<CanvasGradient>> create_radial_gradient(double x0, double y0, double r0, double x1, double y1, double r1)
  54. {
  55. auto& realm = static_cast<IncludingClass&>(*this).realm();
  56. return CanvasGradient::create_radial(realm, x0, y0, r0, x1, y1, r1);
  57. }
  58. JS::NonnullGCPtr<CanvasGradient> create_linear_gradient(double x0, double y0, double x1, double y1)
  59. {
  60. auto& realm = static_cast<IncludingClass&>(*this).realm();
  61. return CanvasGradient::create_linear(realm, x0, y0, x1, y1).release_value_but_fixme_should_propagate_errors();
  62. }
  63. JS::NonnullGCPtr<CanvasGradient> create_conic_gradient(double start_angle, double x, double y)
  64. {
  65. auto& realm = static_cast<IncludingClass&>(*this).realm();
  66. return CanvasGradient::create_conic(realm, start_angle, x, y).release_value_but_fixme_should_propagate_errors();
  67. }
  68. WebIDL::ExceptionOr<JS::GCPtr<CanvasPattern>> create_pattern(CanvasImageSource const& image, StringView repetition)
  69. {
  70. auto& realm = static_cast<IncludingClass&>(*this).realm();
  71. return CanvasPattern::create(realm, image, repetition);
  72. }
  73. protected:
  74. CanvasFillStrokeStyles() = default;
  75. private:
  76. CanvasState::DrawingState& my_drawing_state() { return reinterpret_cast<IncludingClass&>(*this).drawing_state(); }
  77. CanvasState::DrawingState const& my_drawing_state() const { return reinterpret_cast<IncludingClass const&>(*this).drawing_state(); }
  78. };
  79. }