CanvasFillStrokeStyles.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * Copyright (c) 2020-2022, Andreas Kling <andreas@ladybird.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/CSS/Parser/Parser.h>
  12. #include <LibWeb/HTML/Canvas/CanvasState.h>
  13. #include <LibWeb/HTML/CanvasGradient.h>
  14. #include <LibWeb/HTML/CanvasPattern.h>
  15. namespace Web::HTML {
  16. // https://html.spec.whatwg.org/multipage/canvas.html#canvasfillstrokestyles
  17. template<typename IncludingClass>
  18. class CanvasFillStrokeStyles {
  19. public:
  20. ~CanvasFillStrokeStyles() = default;
  21. using FillOrStrokeStyleVariant = Variant<String, GC::Root<CanvasGradient>, GC::Root<CanvasPattern>>;
  22. void set_fill_style(FillOrStrokeStyleVariant style)
  23. {
  24. auto& realm = static_cast<IncludingClass&>(*this).realm();
  25. // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-fillstyle
  26. style.visit(
  27. // 1. If the given value is a string, then:
  28. [&](String const& string) {
  29. // 1. Let context be this's canvas attribute's value, if that is an element; otherwise null.
  30. auto parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), string);
  31. // 2. Let parsedValue be the result of parsing the given value with context if non-null.
  32. // FIXME: Parse a color value
  33. // https://drafts.csswg.org/css-color/#parse-a-css-color-value
  34. auto style_value = parser.parse_as_css_value(CSS::PropertyID::Color);
  35. if (style_value && style_value->has_color()) {
  36. auto parsedValue = style_value->to_color(OptionalNone());
  37. // 4. Set this's fill style to parsedValue.
  38. my_drawing_state().fill_style = parsedValue;
  39. } else {
  40. // 3. If parsedValue is failure, then return.
  41. return;
  42. }
  43. // 5. Return.
  44. return;
  45. },
  46. [&](auto fill_or_stroke_style) {
  47. // 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.
  48. // 3. Set this's fill style to the given value.
  49. my_drawing_state().fill_style = fill_or_stroke_style;
  50. });
  51. }
  52. FillOrStrokeStyleVariant fill_style() const
  53. {
  54. return my_drawing_state().fill_style.to_js_fill_or_stroke_style();
  55. }
  56. void set_stroke_style(FillOrStrokeStyleVariant style)
  57. {
  58. auto& realm = static_cast<IncludingClass&>(*this).realm();
  59. // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-strokestyle
  60. style.visit(
  61. // 1. If the given value is a string, then:
  62. [&](String const& string) {
  63. // 1. Let context be this's canvas attribute's value, if that is an element; otherwise null.
  64. auto parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), string);
  65. // 2. Let parsedValue be the result of parsing the given value with context if non-null.
  66. // FIXME: Parse a color value
  67. // https://drafts.csswg.org/css-color/#parse-a-css-color-value
  68. auto style_value = parser.parse_as_css_value(CSS::PropertyID::Color);
  69. if (style_value && style_value->has_color()) {
  70. auto parsedValue = style_value->to_color(OptionalNone());
  71. // 4. Set this's stroke style to parsedValue.
  72. my_drawing_state().stroke_style = parsedValue;
  73. } else {
  74. // 3. If parsedValue is failure, then return.
  75. return;
  76. }
  77. // 5. Return.
  78. return;
  79. },
  80. [&](auto fill_or_stroke_style) {
  81. // 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.
  82. // 3. Set this's stroke style to the given value.
  83. my_drawing_state().fill_style = fill_or_stroke_style;
  84. });
  85. }
  86. FillOrStrokeStyleVariant stroke_style() const
  87. {
  88. return my_drawing_state().stroke_style.to_js_fill_or_stroke_style();
  89. }
  90. WebIDL::ExceptionOr<GC::Ref<CanvasGradient>> create_radial_gradient(double x0, double y0, double r0, double x1, double y1, double r1)
  91. {
  92. auto& realm = static_cast<IncludingClass&>(*this).realm();
  93. return CanvasGradient::create_radial(realm, x0, y0, r0, x1, y1, r1);
  94. }
  95. GC::Ref<CanvasGradient> create_linear_gradient(double x0, double y0, double x1, double y1)
  96. {
  97. auto& realm = static_cast<IncludingClass&>(*this).realm();
  98. return CanvasGradient::create_linear(realm, x0, y0, x1, y1).release_value_but_fixme_should_propagate_errors();
  99. }
  100. GC::Ref<CanvasGradient> create_conic_gradient(double start_angle, double x, double y)
  101. {
  102. auto& realm = static_cast<IncludingClass&>(*this).realm();
  103. return CanvasGradient::create_conic(realm, start_angle, x, y).release_value_but_fixme_should_propagate_errors();
  104. }
  105. WebIDL::ExceptionOr<GC::Ptr<CanvasPattern>> create_pattern(CanvasImageSource const& image, StringView repetition)
  106. {
  107. auto& realm = static_cast<IncludingClass&>(*this).realm();
  108. return CanvasPattern::create(realm, image, repetition);
  109. }
  110. protected:
  111. CanvasFillStrokeStyles() = default;
  112. private:
  113. CanvasState::DrawingState& my_drawing_state() { return reinterpret_cast<IncludingClass&>(*this).drawing_state(); }
  114. CanvasState::DrawingState const& my_drawing_state() const { return reinterpret_cast<IncludingClass const&>(*this).drawing_state(); }
  115. };
  116. }