mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-31 05:09:12 +00:00
LibWeb: Parse fill and stroke values
Use the CSS color data type using the CSS parser.
This commit is contained in:
parent
793248aec9
commit
9cbb3fac12
Notes:
github-actions[bot]
2024-07-26 08:15:04 +00:00
Author: https://github.com/doctortheemh
Commit: 9cbb3fac12
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/779
Reviewed-by: https://github.com/AtkinsSJ ✅
5 changed files with 91 additions and 32 deletions
|
@ -18,11 +18,11 @@
|
||||||
ctx.fillRect(0, 0, 500, 100);
|
ctx.fillRect(0, 0, 500, 100);
|
||||||
|
|
||||||
// Decimal numbers
|
// Decimal numbers
|
||||||
ctx.fillStyle = "rgb(0.28813966673057,254.56022744510793,0.2973971574794)";
|
ctx.fillStyle = "rgb(254.56022744510793,0.28813966673057,0.2973971574794)";
|
||||||
ctx.fillRect(0, 100, 500, 100);
|
ctx.fillRect(0, 100, 500, 100);
|
||||||
|
|
||||||
// Numbers below 0 and above 255 should be clamped
|
// Numbers below 0 and above 255 should be clamped
|
||||||
ctx.fillStyle = "rgba(-50,500,-50,1)";
|
ctx.fillStyle = "rgba(-50,-50,500,1)";
|
||||||
ctx.fillRect(0, 200, 500, 100);
|
ctx.fillRect(0, 200, 500, 100);
|
||||||
|
|
||||||
// Percentages
|
// Percentages
|
||||||
|
@ -30,6 +30,8 @@
|
||||||
ctx.fillRect(0, 300, 500, 100);
|
ctx.fillRect(0, 300, 500, 100);
|
||||||
|
|
||||||
// Calc
|
// Calc
|
||||||
ctx.fillStyle = "rgb(0, calc(infinity), 0)";
|
// FIXME: The CSS parser currently chokes on calc expressions, which will
|
||||||
|
// leave the fillStyle as it was (green).
|
||||||
|
ctx.fillStyle = "rgb(calc(infinity), 0, 0)";
|
||||||
ctx.fillRect(0, 400, 500, 100);
|
ctx.fillRect(0, 400, 500, 100);
|
||||||
</script>
|
</script>
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 264 B After Width: | Height: | Size: 566 B |
|
@ -1,5 +1,5 @@
|
||||||
1. "#00ff00ff"
|
1. "#00ff00ff"
|
||||||
2. "#00ff00ff"
|
2. "#ff0000ff"
|
||||||
3. "#00ff00ff"
|
3. "#0000ffff"
|
||||||
4. "#000000ff"
|
4. "#00ff00ff"
|
||||||
5. "#000000ff"
|
5. "#00ff00ff"
|
||||||
|
|
|
@ -17,25 +17,27 @@
|
||||||
|
|
||||||
// 2. Decimals
|
// 2. Decimals
|
||||||
testPart(() => {
|
testPart(() => {
|
||||||
context.fillStyle = "rgb(0.28813966673057,254.56022744510793,0.2973971574794)";
|
context.fillStyle = "rgb(254.56022744510793,0.28813966673057,0.2973971574794)";
|
||||||
return context.fillStyle;
|
return context.fillStyle;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3. Clamp numbers between 0-255
|
// 3. Clamp numbers between 0-255
|
||||||
testPart(() => {
|
testPart(() => {
|
||||||
context.fillStyle = "rgba(-50,500,-50,1)";
|
context.fillStyle = "rgba(-50,-50,500,1)";
|
||||||
return context.fillStyle;
|
return context.fillStyle;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 4. Percentages
|
// 4. Percentages
|
||||||
testPart(() => {
|
testPart(() => {
|
||||||
context.fillStyle = "rgb(0%,100%,0%)";
|
context.fillStyle = "rgb(0%, 100%, 0%)";
|
||||||
return context.fillStyle;
|
return context.fillStyle;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 5. Percentages
|
// 5. Percentages
|
||||||
testPart(() => {
|
testPart(() => {
|
||||||
context.fillStyle = "rgb(0,calc(infinity),0)";
|
// FIXME: The CSS parser currently chokes on calc expressions, which will
|
||||||
|
// leave the fillStyle as it was (green).
|
||||||
|
context.fillStyle = "rgb(calc(infinity), 0, 0)";
|
||||||
return context.fillStyle;
|
return context.fillStyle;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
|
#include <LibWeb/CSS/Parser/Parser.h>
|
||||||
#include <LibWeb/HTML/Canvas/CanvasState.h>
|
#include <LibWeb/HTML/Canvas/CanvasState.h>
|
||||||
#include <LibWeb/HTML/CanvasGradient.h>
|
#include <LibWeb/HTML/CanvasGradient.h>
|
||||||
#include <LibWeb/HTML/CanvasPattern.h>
|
#include <LibWeb/HTML/CanvasPattern.h>
|
||||||
|
@ -23,27 +24,45 @@ public:
|
||||||
~CanvasFillStrokeStyles() = default;
|
~CanvasFillStrokeStyles() = default;
|
||||||
using FillOrStrokeStyleVariant = Variant<String, JS::Handle<CanvasGradient>, JS::Handle<CanvasPattern>>;
|
using FillOrStrokeStyleVariant = Variant<String, JS::Handle<CanvasGradient>, JS::Handle<CanvasPattern>>;
|
||||||
|
|
||||||
static CanvasState::FillOrStrokeStyle to_canvas_state_fill_or_stroke_style(auto const& style)
|
|
||||||
{
|
|
||||||
return style.visit(
|
|
||||||
[&](String const& string) -> CanvasState::FillOrStrokeStyle {
|
|
||||||
// FIXME: This should parse color strings the same as CSS
|
|
||||||
auto color = Gfx::Color::from_string(string);
|
|
||||||
|
|
||||||
if (!color.has_value())
|
|
||||||
dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasFillStrokeStyles: Unsupported canvas fill or stroke style \"{}\". Defaulting to Color::Black.", string);
|
|
||||||
|
|
||||||
return color.value_or(Color::Black);
|
|
||||||
},
|
|
||||||
[&](auto fill_or_stroke_style) -> CanvasState::FillOrStrokeStyle {
|
|
||||||
return fill_or_stroke_style;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_fill_style(FillOrStrokeStyleVariant style)
|
void set_fill_style(FillOrStrokeStyleVariant style)
|
||||||
{
|
{
|
||||||
// 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.
|
auto& realm = static_cast<IncludingClass&>(*this).realm();
|
||||||
my_drawing_state().fill_style = to_canvas_state_fill_or_stroke_style(style);
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-fillstyle
|
||||||
|
style.visit(
|
||||||
|
// 1. If the given value is a string, then:
|
||||||
|
[&](String const& string) {
|
||||||
|
// 1. Let context be this's canvas attribute's value, if that is an element; otherwise null.
|
||||||
|
auto maybe_parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), string);
|
||||||
|
if (maybe_parser.is_error()) {
|
||||||
|
dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasFillStrokeStyles: Failed to create CSS parser.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto parser = maybe_parser.release_value();
|
||||||
|
|
||||||
|
// 2. Let parsedValue be the result of parsing the given value with context if non-null.
|
||||||
|
// FIXME: Parse a color value
|
||||||
|
// https://drafts.csswg.org/css-color/#parse-a-css-color-value
|
||||||
|
auto style_value = parser.parse_as_css_value(CSS::PropertyID::Color);
|
||||||
|
if (style_value && style_value->has_color()) {
|
||||||
|
auto parsedValue = style_value->to_color(OptionalNone());
|
||||||
|
|
||||||
|
// 4. Set this's fill style to parsedValue.
|
||||||
|
my_drawing_state().fill_style = parsedValue;
|
||||||
|
} else {
|
||||||
|
// 3. If parsedValue is failure, then return.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Return.
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
[&](auto fill_or_stroke_style) {
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// 3. Set this's fill style to the given value.
|
||||||
|
my_drawing_state().fill_style = fill_or_stroke_style;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FillOrStrokeStyleVariant fill_style() const
|
FillOrStrokeStyleVariant fill_style() const
|
||||||
|
@ -53,8 +72,44 @@ public:
|
||||||
|
|
||||||
void set_stroke_style(FillOrStrokeStyleVariant style)
|
void set_stroke_style(FillOrStrokeStyleVariant style)
|
||||||
{
|
{
|
||||||
// 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.
|
auto& realm = static_cast<IncludingClass&>(*this).realm();
|
||||||
my_drawing_state().stroke_style = to_canvas_state_fill_or_stroke_style(style);
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-strokestyle
|
||||||
|
|
||||||
|
style.visit(
|
||||||
|
// 1. If the given value is a string, then:
|
||||||
|
[&](String const& string) {
|
||||||
|
// 1. Let context be this's canvas attribute's value, if that is an element; otherwise null.
|
||||||
|
auto maybe_parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), string);
|
||||||
|
if (maybe_parser.is_error()) {
|
||||||
|
dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasFillStrokeStyles: Failed to create CSS parser.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto parser = maybe_parser.release_value();
|
||||||
|
|
||||||
|
// 2. Let parsedValue be the result of parsing the given value with context if non-null.
|
||||||
|
// FIXME: Parse a color value
|
||||||
|
// https://drafts.csswg.org/css-color/#parse-a-css-color-value
|
||||||
|
auto style_value = parser.parse_as_css_value(CSS::PropertyID::Color);
|
||||||
|
if (style_value && style_value->has_color()) {
|
||||||
|
auto parsedValue = style_value->to_color(OptionalNone());
|
||||||
|
|
||||||
|
// 4. Set this's stroke style to parsedValue.
|
||||||
|
my_drawing_state().stroke_style = parsedValue;
|
||||||
|
} else {
|
||||||
|
// 3. If parsedValue is failure, then return.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Return.
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
[&](auto fill_or_stroke_style) {
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// 3. Set this's stroke style to the given value.
|
||||||
|
my_drawing_state().fill_style = fill_or_stroke_style;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FillOrStrokeStyleVariant stroke_style() const
|
FillOrStrokeStyleVariant stroke_style() const
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue