Skip to content

Commit e1ff1e2

Browse files
tcl3gmta
authored andcommitted
LibWeb: Implement CanvasPattern.setTransform()
This method applies the given transformation matrix to a pattern.
1 parent 9312a9f commit e1ff1e2

File tree

10 files changed

+88
-8
lines changed

10 files changed

+88
-8
lines changed

Libraries/LibGfx/PaintStyle.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ class CanvasPatternPaintStyle : public PaintStyle {
9696

9797
RefPtr<ImmutableBitmap> image() const { return m_image; }
9898
Repetition repetition() const { return m_repetition; }
99+
Optional<AffineTransform> const& transform() const { return m_transform; }
100+
void set_transform(AffineTransform const& transform) { m_transform = transform; }
99101

100102
private:
101103
CanvasPatternPaintStyle(RefPtr<ImmutableBitmap> image, Repetition repetition)
@@ -106,6 +108,7 @@ class CanvasPatternPaintStyle : public PaintStyle {
106108

107109
RefPtr<ImmutableBitmap> m_image;
108110
Repetition m_repetition { Repetition::Repeat };
111+
Optional<AffineTransform> m_transform;
109112
};
110113

111114
// The following paint styles implement the gradients required for the HTML canvas.

Libraries/LibGfx/PainterSkia.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,20 @@ static void apply_paint_style(SkPaint& paint, PaintStyle const& style)
103103

104104
// FIXME: Implement sampling configuration.
105105
SkSamplingOptions sk_sampling_options { SkFilterMode::kLinear };
106-
106+
Optional<SkMatrix> transformation_matrix;
107+
108+
if (canvas_pattern->transform().has_value()) {
109+
auto const& transform = canvas_pattern->transform().value();
110+
transformation_matrix = SkMatrix::MakeAll(
111+
transform.a(), transform.c(), transform.e(),
112+
transform.b(), transform.d(), transform.f(),
113+
0, 0, 1);
114+
}
107115
auto shader = sk_image->makeShader(
108116
repeat_x ? SkTileMode::kRepeat : SkTileMode::kDecal,
109117
repeat_y ? SkTileMode::kRepeat : SkTileMode::kDecal,
110-
sk_sampling_options);
111-
paint.setShader(shader);
118+
sk_sampling_options, transformation_matrix.has_value() ? &transformation_matrix.value() : nullptr);
119+
paint.setShader(move(shader));
112120
} else {
113121
dbgln("FIXME: Unsupported PaintStyle");
114122
}

Libraries/LibWeb/HTML/CanvasPattern.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,21 @@ void CanvasPattern::initialize(JS::Realm& realm)
7575
Base::initialize(realm);
7676
}
7777

78+
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvaspattern-settransform
79+
WebIDL::ExceptionOr<void> CanvasPattern::set_transform(Geometry::DOMMatrix2DInit& transform)
80+
{
81+
// 1. Let matrix be the result of creating a DOMMatrix from the 2D dictionary transform.
82+
auto matrix = TRY(Geometry::DOMMatrix::create_from_dom_matrix_2d_init(realm(), transform));
83+
84+
// 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.
85+
if (!isfinite(matrix->m11()) || !isfinite(matrix->m12()) || !isfinite(matrix->m21()) || !isfinite(matrix->m22()) || !isfinite(matrix->m41()) || !isfinite(matrix->m42()))
86+
return {};
87+
88+
// 3. Reset the pattern's transformation matrix to matrix.
89+
Gfx::AffineTransform affine_transform(matrix->a(), matrix->b(), matrix->c(), matrix->d(), matrix->e(), matrix->f());
90+
m_pattern->set_transform(affine_transform);
91+
92+
return {};
93+
}
94+
7895
}

Libraries/LibWeb/HTML/CanvasPattern.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class CanvasPattern final : public Bindings::PlatformObject {
2424
~CanvasPattern();
2525

2626
NonnullRefPtr<Gfx::PaintStyle> to_gfx_paint_style() { return m_pattern; }
27+
WebIDL::ExceptionOr<void> set_transform(Geometry::DOMMatrix2DInit& transform);
2728

2829
private:
2930
CanvasPattern(JS::Realm&, Gfx::CanvasPatternPaintStyle&);
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
#import <Geometry/DOMMatrix.idl>
2+
13
// https://html.spec.whatwg.org/multipage/canvas.html#canvaspattern
24
[Exposed=(Window,Worker)]
35
interface CanvasPattern {
46
// opaque object
5-
[FIXME] undefined setTransform(optional DOMMatrix2DInit transform = {});
7+
undefined setTransform(optional DOMMatrix2DInit transform = {});
68
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<style>
3+
* {
4+
margin: 0;
5+
overflow: hidden;
6+
}
7+
body {
8+
background-color: white;
9+
}
10+
</style>
11+
<img src="../images/canvas-pattern-transform-ref.png">
182 KB
Loading
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<!DOCTYPE html>
2+
<meta name="fuzzy" content="maxDifference=0-93; totalPixels=0-2396">
3+
<link rel="match" href="../expected/canvas-pattern-transform-ref.html" />
4+
<style>
5+
* {
6+
margin: 0;
7+
}
8+
9+
body {
10+
background-color: white;
11+
}
12+
13+
canvas {
14+
border: 2px solid black;
15+
margin: 5px;
16+
padding: 5px;
17+
}
18+
</style>
19+
20+
<canvas data-type="img" data-repeat="repeat" width="250" height="250"></canvas>
21+
<canvas data-type="img" data-repeat="repeat-x" width="250" height="250"></canvas>
22+
<canvas data-type="img" data-repeat="repeat-y" width="250" height="250"></canvas>
23+
<canvas data-type="img" data-repeat="no-repeat" width="250" height="250"></canvas>
24+
25+
<script>
26+
const img = new Image();
27+
img.onload = () => {
28+
for (const canvas of document.querySelectorAll('canvas[data-type=img]')) {
29+
const ctx = canvas.getContext('2d');
30+
const pattern = ctx.createPattern(img, canvas.getAttribute('data-repeat'));
31+
const matrix = new DOMMatrix([1, 0.2, 0.8, 1, 0, 0]);
32+
pattern.setTransform(matrix);
33+
ctx.fillStyle = pattern;
34+
ctx.fillRect(0, 0, canvas.width, canvas.height);
35+
}
36+
};
37+
img.src = '../data/car.png';
38+
</script>

Tests/LibWeb/Text/expected/wpt-import/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.identity.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ Harness status: OK
22

33
Found 1 tests
44

5-
1 Fail
6-
Fail Canvas test: 2d.pattern.transform.identity
5+
1 Pass
6+
Pass Canvas test: 2d.pattern.transform.identity

Tests/LibWeb/Text/expected/wpt-import/html/canvas/element/fill-and-stroke-styles/2d.pattern.transform.infinity.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ Harness status: OK
22

33
Found 1 tests
44

5-
1 Fail
6-
Fail Canvas test: 2d.pattern.transform.infinity
5+
1 Pass
6+
Pass Canvas test: 2d.pattern.transform.infinity

0 commit comments

Comments
 (0)