mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 04:34:44 +00:00
Merge pull request #1564 from lightpanda-io/nikneym/create-image-data
Add `createImageData` and `putImageData` to `CanvasRenderingContext2D`
This commit is contained in:
@@ -33,3 +33,58 @@
|
|||||||
testing.expectEqual(ctx.fillStyle, "rgba(255, 0, 0, 0.06)");
|
testing.expectEqual(ctx.fillStyle, "rgba(255, 0, 0, 0.06)");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script id="CanvasRenderingContext2D#createImageData(width, height)">
|
||||||
|
{
|
||||||
|
const element = document.createElement("canvas");
|
||||||
|
const ctx = element.getContext("2d");
|
||||||
|
|
||||||
|
const imageData = ctx.createImageData(100, 200);
|
||||||
|
testing.expectEqual(true, imageData instanceof ImageData);
|
||||||
|
testing.expectEqual(imageData.width, 100);
|
||||||
|
testing.expectEqual(imageData.height, 200);
|
||||||
|
testing.expectEqual(imageData.data.length, 100 * 200 * 4);
|
||||||
|
testing.expectEqual(true, imageData.data instanceof Uint8ClampedArray);
|
||||||
|
|
||||||
|
// All pixels should be initialized to 0.
|
||||||
|
testing.expectEqual(imageData.data[0], 0);
|
||||||
|
testing.expectEqual(imageData.data[1], 0);
|
||||||
|
testing.expectEqual(imageData.data[2], 0);
|
||||||
|
testing.expectEqual(imageData.data[3], 0);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="CanvasRenderingContext2D#createImageData(imageData)">
|
||||||
|
{
|
||||||
|
const element = document.createElement("canvas");
|
||||||
|
const ctx = element.getContext("2d");
|
||||||
|
|
||||||
|
const source = ctx.createImageData(50, 75);
|
||||||
|
const imageData = ctx.createImageData(source);
|
||||||
|
testing.expectEqual(true, imageData instanceof ImageData);
|
||||||
|
testing.expectEqual(imageData.width, 50);
|
||||||
|
testing.expectEqual(imageData.height, 75);
|
||||||
|
testing.expectEqual(imageData.data.length, 50 * 75 * 4);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="CanvasRenderingContext2D#putImageData">
|
||||||
|
{
|
||||||
|
const element = document.createElement("canvas");
|
||||||
|
const ctx = element.getContext("2d");
|
||||||
|
|
||||||
|
const imageData = ctx.createImageData(10, 10);
|
||||||
|
testing.expectEqual(true, imageData instanceof ImageData);
|
||||||
|
// Modify some pixel data.
|
||||||
|
imageData.data[0] = 255;
|
||||||
|
imageData.data[1] = 0;
|
||||||
|
imageData.data[2] = 0;
|
||||||
|
imageData.data[3] = 255;
|
||||||
|
|
||||||
|
// putImageData should not throw.
|
||||||
|
ctx.putImageData(imageData, 0, 0);
|
||||||
|
ctx.putImageData(imageData, 10, 20);
|
||||||
|
// With dirty rect parameters.
|
||||||
|
ctx.putImageData(imageData, 0, 0, 0, 0, 5, 5);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -59,10 +59,6 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id=constructor-invalid-colorspace>
|
|
||||||
testing.expectError("TypeError", () => {
|
|
||||||
new ImageData(5, 5, { colorSpace: "display-p3" });
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id=single-pixel>
|
<script id=single-pixel>
|
||||||
@@ -73,3 +69,7 @@
|
|||||||
testing.expectEqual(1, img.height);
|
testing.expectEqual(1, img.height);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script id=too-large>
|
||||||
|
testing.expectError("IndexSizeError", () => new ImageData(2_147_483_648, 2_147_483_648));
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -58,7 +58,10 @@ pub fn constructor(
|
|||||||
maybe_settings: ?ConstructorSettings,
|
maybe_settings: ?ConstructorSettings,
|
||||||
page: *Page,
|
page: *Page,
|
||||||
) !*ImageData {
|
) !*ImageData {
|
||||||
if (width == 0 or height == 0) {
|
// Though arguments are unsigned long, these are capped to max. i32 on Chrome.
|
||||||
|
// https://github.com/chromium/chromium/blob/main/third_party/blink/renderer/core/html/canvas/image_data.cc#L61
|
||||||
|
const max_i32 = std.math.maxInt(i32);
|
||||||
|
if (width == 0 or width > max_i32 or height == 0 or height > max_i32) {
|
||||||
return error.IndexSizeError;
|
return error.IndexSizeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +73,11 @@ pub fn constructor(
|
|||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size = width * height * 4;
|
var size, var overflown = @mulWithOverflow(width, height);
|
||||||
|
if (overflown == 1) return error.IndexSizeError;
|
||||||
|
size, overflown = @mulWithOverflow(size, 4);
|
||||||
|
if (overflown == 1) return error.IndexSizeError;
|
||||||
|
|
||||||
return page._factory.create(ImageData{
|
return page._factory.create(ImageData{
|
||||||
._width = width,
|
._width = width,
|
||||||
._height = height,
|
._height = height,
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ const js = @import("../../js/js.zig");
|
|||||||
const color = @import("../../color.zig");
|
const color = @import("../../color.zig");
|
||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
|
|
||||||
|
const ImageData = @import("../ImageData.zig");
|
||||||
|
|
||||||
/// This class doesn't implement a `constructor`.
|
/// This class doesn't implement a `constructor`.
|
||||||
/// It can be obtained with a call to `HTMLCanvasElement#getContext`.
|
/// It can be obtained with a call to `HTMLCanvasElement#getContext`.
|
||||||
/// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
|
/// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
|
||||||
@@ -85,6 +87,33 @@ pub fn getTextBaseline(_: *const CanvasRenderingContext2D) []const u8 {
|
|||||||
return "alphabetic";
|
return "alphabetic";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WidthOrImageData = union(enum) {
|
||||||
|
width: u32,
|
||||||
|
image_data: *ImageData,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn createImageData(
|
||||||
|
_: *const CanvasRenderingContext2D,
|
||||||
|
width_or_image_data: WidthOrImageData,
|
||||||
|
/// If `ImageData` variant preferred, this is null.
|
||||||
|
maybe_height: ?u32,
|
||||||
|
/// Can be used if width and height provided.
|
||||||
|
maybe_settings: ?ImageData.ConstructorSettings,
|
||||||
|
page: *Page,
|
||||||
|
) !*ImageData {
|
||||||
|
switch (width_or_image_data) {
|
||||||
|
.width => |width| {
|
||||||
|
const height = maybe_height orelse return error.TypeError;
|
||||||
|
return ImageData.constructor(width, height, maybe_settings, page);
|
||||||
|
},
|
||||||
|
.image_data => |image_data| {
|
||||||
|
return ImageData.constructor(image_data._width, image_data._height, null, page);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn putImageData(_: *const CanvasRenderingContext2D, _: *ImageData, _: f64, _: f64, _: ?f64, _: ?f64, _: ?f64, _: ?f64) void {}
|
||||||
|
|
||||||
pub fn save(_: *CanvasRenderingContext2D) void {}
|
pub fn save(_: *CanvasRenderingContext2D) void {}
|
||||||
pub fn restore(_: *CanvasRenderingContext2D) void {}
|
pub fn restore(_: *CanvasRenderingContext2D) void {}
|
||||||
pub fn scale(_: *CanvasRenderingContext2D, _: f64, _: f64) void {}
|
pub fn scale(_: *CanvasRenderingContext2D, _: f64, _: f64) void {}
|
||||||
@@ -131,6 +160,9 @@ pub const JsApi = struct {
|
|||||||
pub var class_id: bridge.ClassId = undefined;
|
pub var class_id: bridge.ClassId = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const createImageData = bridge.function(CanvasRenderingContext2D.createImageData, .{ .dom_exception = true });
|
||||||
|
pub const putImageData = bridge.function(CanvasRenderingContext2D.putImageData, .{});
|
||||||
|
|
||||||
pub const save = bridge.function(CanvasRenderingContext2D.save, .{});
|
pub const save = bridge.function(CanvasRenderingContext2D.save, .{});
|
||||||
pub const restore = bridge.function(CanvasRenderingContext2D.restore, .{});
|
pub const restore = bridge.function(CanvasRenderingContext2D.restore, .{});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user