CanvasFillStrokeStyles.h 5.5 KB

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