mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb: Implement CanvasPattern.setTransform()
This method applies the given transformation matrix to a pattern.
This commit is contained in:
parent
9312a9f86f
commit
e1ff1e2095
Notes:
github-actions[bot]
2025-10-27 23:42:03 +00:00
Author: https://github.com/tcl3
Commit: e1ff1e2095
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6596
Reviewed-by: https://github.com/gmta ✅
10 changed files with 87 additions and 7 deletions
|
|
@ -96,6 +96,8 @@ public:
|
|||
|
||||
RefPtr<ImmutableBitmap> image() const { return m_image; }
|
||||
Repetition repetition() const { return m_repetition; }
|
||||
Optional<AffineTransform> const& transform() const { return m_transform; }
|
||||
void set_transform(AffineTransform const& transform) { m_transform = transform; }
|
||||
|
||||
private:
|
||||
CanvasPatternPaintStyle(RefPtr<ImmutableBitmap> image, Repetition repetition)
|
||||
|
|
@ -106,6 +108,7 @@ private:
|
|||
|
||||
RefPtr<ImmutableBitmap> m_image;
|
||||
Repetition m_repetition { Repetition::Repeat };
|
||||
Optional<AffineTransform> m_transform;
|
||||
};
|
||||
|
||||
// The following paint styles implement the gradients required for the HTML canvas.
|
||||
|
|
|
|||
|
|
@ -103,12 +103,20 @@ static void apply_paint_style(SkPaint& paint, PaintStyle const& style)
|
|||
|
||||
// FIXME: Implement sampling configuration.
|
||||
SkSamplingOptions sk_sampling_options { SkFilterMode::kLinear };
|
||||
Optional<SkMatrix> transformation_matrix;
|
||||
|
||||
if (canvas_pattern->transform().has_value()) {
|
||||
auto const& transform = canvas_pattern->transform().value();
|
||||
transformation_matrix = SkMatrix::MakeAll(
|
||||
transform.a(), transform.c(), transform.e(),
|
||||
transform.b(), transform.d(), transform.f(),
|
||||
0, 0, 1);
|
||||
}
|
||||
auto shader = sk_image->makeShader(
|
||||
repeat_x ? SkTileMode::kRepeat : SkTileMode::kDecal,
|
||||
repeat_y ? SkTileMode::kRepeat : SkTileMode::kDecal,
|
||||
sk_sampling_options);
|
||||
paint.setShader(shader);
|
||||
sk_sampling_options, transformation_matrix.has_value() ? &transformation_matrix.value() : nullptr);
|
||||
paint.setShader(move(shader));
|
||||
} else {
|
||||
dbgln("FIXME: Unsupported PaintStyle");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,4 +75,21 @@ void CanvasPattern::initialize(JS::Realm& realm)
|
|||
Base::initialize(realm);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvaspattern-settransform
|
||||
WebIDL::ExceptionOr<void> CanvasPattern::set_transform(Geometry::DOMMatrix2DInit& transform)
|
||||
{
|
||||
// 1. Let matrix be the result of creating a DOMMatrix from the 2D dictionary transform.
|
||||
auto matrix = TRY(Geometry::DOMMatrix::create_from_dom_matrix_2d_init(realm(), transform));
|
||||
|
||||
// 2. If one or more of matrix's m11 element, m12 element, m21 element, m22 element, m41 element, or m42 element are infinite or NaN, then return.
|
||||
if (!isfinite(matrix->m11()) || !isfinite(matrix->m12()) || !isfinite(matrix->m21()) || !isfinite(matrix->m22()) || !isfinite(matrix->m41()) || !isfinite(matrix->m42()))
|
||||
return {};
|
||||
|
||||
// 3. Reset the pattern's transformation matrix to matrix.
|
||||
Gfx::AffineTransform affine_transform(matrix->a(), matrix->b(), matrix->c(), matrix->d(), matrix->e(), matrix->f());
|
||||
m_pattern->set_transform(affine_transform);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ public:
|
|||
~CanvasPattern();
|
||||
|
||||
NonnullRefPtr<Gfx::PaintStyle> to_gfx_paint_style() { return m_pattern; }
|
||||
WebIDL::ExceptionOr<void> set_transform(Geometry::DOMMatrix2DInit& transform);
|
||||
|
||||
private:
|
||||
CanvasPattern(JS::Realm&, Gfx::CanvasPatternPaintStyle&);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#import <Geometry/DOMMatrix.idl>
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#canvaspattern
|
||||
[Exposed=(Window,Worker)]
|
||||
interface CanvasPattern {
|
||||
// opaque object
|
||||
[FIXME] undefined setTransform(optional DOMMatrix2DInit transform = {});
|
||||
undefined setTransform(optional DOMMatrix2DInit transform = {});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
body {
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
<img src="../images/canvas-pattern-transform-ref.png">
|
||||
BIN
Tests/LibWeb/Screenshot/images/canvas-pattern-transform-ref.png
Normal file
BIN
Tests/LibWeb/Screenshot/images/canvas-pattern-transform-ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 182 KiB |
38
Tests/LibWeb/Screenshot/input/canvas-pattern-transform.html
Normal file
38
Tests/LibWeb/Screenshot/input/canvas-pattern-transform.html
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<meta name="fuzzy" content="maxDifference=0-93; totalPixels=0-2396">
|
||||
<link rel="match" href="../expected/canvas-pattern-transform-ref.html" />
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
canvas {
|
||||
border: 2px solid black;
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<canvas data-type="img" data-repeat="repeat" width="250" height="250"></canvas>
|
||||
<canvas data-type="img" data-repeat="repeat-x" width="250" height="250"></canvas>
|
||||
<canvas data-type="img" data-repeat="repeat-y" width="250" height="250"></canvas>
|
||||
<canvas data-type="img" data-repeat="no-repeat" width="250" height="250"></canvas>
|
||||
|
||||
<script>
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
for (const canvas of document.querySelectorAll('canvas[data-type=img]')) {
|
||||
const ctx = canvas.getContext('2d');
|
||||
const pattern = ctx.createPattern(img, canvas.getAttribute('data-repeat'));
|
||||
const matrix = new DOMMatrix([1, 0.2, 0.8, 1, 0, 0]);
|
||||
pattern.setTransform(matrix);
|
||||
ctx.fillStyle = pattern;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
};
|
||||
img.src = '../data/car.png';
|
||||
</script>
|
||||
|
|
@ -2,5 +2,5 @@ Harness status: OK
|
|||
|
||||
Found 1 tests
|
||||
|
||||
1 Fail
|
||||
Fail Canvas test: 2d.pattern.transform.identity
|
||||
1 Pass
|
||||
Pass Canvas test: 2d.pattern.transform.identity
|
||||
|
|
@ -2,5 +2,5 @@ Harness status: OK
|
|||
|
||||
Found 1 tests
|
||||
|
||||
1 Fail
|
||||
Fail Canvas test: 2d.pattern.transform.infinity
|
||||
1 Pass
|
||||
Pass Canvas test: 2d.pattern.transform.infinity
|
||||
Loading…
Add table
Add a link
Reference in a new issue