mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-09-16 16:01:30 -04:00
webapi: SVG cleanup
This is a follow up to the large SVG change that has landed (1). Most changes are mechanical or superficial (proper license headers, removing "pub" where not needed, ...). But there were also a few finalizer/arena tweaks to tighten lifetimes. (1) https://github.com/lightpanda-io/browser/pull/3012
This commit is contained in:
13 files changed
+141
-55
No files matched your search
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||
//
|
||||
// Francis Bouvier <francis@lightpanda.io>
|
||||
// Pierre Tachoire <pierre@lightpanda.io>
|
||||
|
||||
@@ -21,11 +21,14 @@ const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
const Element = @import("../Element.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Angle = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: std.mem.Allocator,
|
||||
_value: f64 = 0,
|
||||
_unit: Unit = .unspecified,
|
||||
_element: ?*Element = null,
|
||||
@@ -42,7 +45,23 @@ const Unit = enum(u16) {
|
||||
};
|
||||
|
||||
pub fn detached(frame: *Frame) !*Angle {
|
||||
return frame._factory.create(Angle{});
|
||||
const arena = try frame._page.getArena(.tiny, "SVGAngle");
|
||||
errdefer frame._page.releaseArena(arena);
|
||||
const self = try arena.create(Angle);
|
||||
self.* = .{ ._arena = arena };
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Angle, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *Angle) void {
|
||||
self._rc.acquire();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *Angle, page: *Page) void {
|
||||
self._rc.release(self, page);
|
||||
}
|
||||
|
||||
pub fn getUnitType(self: *Angle) u16 {
|
||||
|
||||
@@ -138,7 +138,7 @@ pub fn getOrCreate(element: *Element, kind: Kind, frame: *Frame) !*AnimatedEnume
|
||||
return gop.value_ptr.*;
|
||||
}
|
||||
|
||||
pub fn create(
|
||||
fn create(
|
||||
element: *Element,
|
||||
attr_name: lp.String,
|
||||
entries: []const Entry,
|
||||
|
||||
@@ -208,16 +208,7 @@ pub fn getOrCreate(element: *Element, kind: Kind, frame: *Frame) !*AnimatedLengt
|
||||
return gop.value_ptr.*;
|
||||
}
|
||||
|
||||
pub fn create(element: *Element, attr_name: lp.String, direction: Length.Direction, frame: *Frame) !*AnimatedLength {
|
||||
const base_val = try Length.reflected(element, attr_name, direction, false, frame);
|
||||
const anim_val = try Length.reflected(element, attr_name, direction, true, frame);
|
||||
return frame._factory.create(AnimatedLength{
|
||||
._base_val = base_val,
|
||||
._anim_val = anim_val,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn createConfigured(
|
||||
fn createConfigured(
|
||||
element: *Element,
|
||||
attr_name: lp.String,
|
||||
direction: Length.Direction,
|
||||
|
||||
@@ -39,7 +39,7 @@ pub fn getOrCreate(element: *Element, frame: *Frame) !*AnimatedPreserveAspectRat
|
||||
return gop.value_ptr.*;
|
||||
}
|
||||
|
||||
pub fn create(element: *Element, frame: *Frame) !*AnimatedPreserveAspectRatio {
|
||||
fn create(element: *Element, frame: *Frame) !*AnimatedPreserveAspectRatio {
|
||||
const base_val = try PreserveAspectRatio.create(element, false, frame);
|
||||
const anim_val = try PreserveAspectRatio.create(element, true, frame);
|
||||
return frame._factory.create(AnimatedPreserveAspectRatio{
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||
//
|
||||
// Francis Bouvier <francis@lightpanda.io>
|
||||
// Pierre Tachoire <pierre@lightpanda.io>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
@@ -50,10 +61,6 @@ pub fn getOrCreate(element: *Element, kind: Kind, frame: *Frame) !*AnimatedTrans
|
||||
return gop.value_ptr.*;
|
||||
}
|
||||
|
||||
pub fn create(element: *Element, frame: *Frame) !*AnimatedTransformList {
|
||||
return createForAttribute(element, comptime .wrap("transform"), frame);
|
||||
}
|
||||
|
||||
pub fn createForAttribute(element: *Element, attr_name: lp.String, frame: *Frame) !*AnimatedTransformList {
|
||||
const base_val = try TransformList.createForAttribute(element, attr_name, false, frame);
|
||||
const anim_val = try TransformList.createForAttribute(element, attr_name, true, frame);
|
||||
|
||||
@@ -21,11 +21,17 @@ const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
const Element = @import("../Element.zig");
|
||||
|
||||
const String = lp.String;
|
||||
const Length = @This();
|
||||
|
||||
// A reflected length is created with one ref held by the frame's animated
|
||||
// lookup cache, so a JS wrapper being collected can never free it. Only a
|
||||
// detached length (own arena, zero initial refs) dies with its last wrapper.
|
||||
_rc: lp.RC = .init(1),
|
||||
_arena: ?std.mem.Allocator = null,
|
||||
_value: f64 = 0,
|
||||
_unit: Unit = .number,
|
||||
_element: ?*Element = null,
|
||||
@@ -58,16 +64,23 @@ pub const Unit = enum(u16) {
|
||||
const MAX_ANCESTOR_DEPTH = 32;
|
||||
|
||||
pub fn detached(frame: *Frame) !*Length {
|
||||
return frame._factory.create(Length{});
|
||||
const arena = try frame._page.getArena(.tiny, "SVGLength");
|
||||
errdefer frame._page.releaseArena(arena);
|
||||
const self = try arena.create(Length);
|
||||
self.* = .{ ._rc = .{}, ._arena = arena };
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn reflected(element: *Element, attr_name: String, direction: Direction, read_only: bool, frame: *Frame) !*Length {
|
||||
return frame._factory.create(Length{
|
||||
._element = element,
|
||||
._attr_name = attr_name,
|
||||
._direction = direction,
|
||||
._read_only = read_only,
|
||||
});
|
||||
pub fn deinit(self: *Length, page: *Page) void {
|
||||
page.releaseArena(self._arena.?);
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *Length) void {
|
||||
self._rc.acquire();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *Length, page: *Page) void {
|
||||
self._rc.release(self, page);
|
||||
}
|
||||
|
||||
pub fn reflectedConfigured(
|
||||
|
||||
@@ -17,15 +17,36 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
|
||||
const Number = @This();
|
||||
|
||||
_rc: lp.RC = .{},
|
||||
_arena: std.mem.Allocator,
|
||||
_value: f32 = 0,
|
||||
|
||||
pub fn detached(frame: *Frame) !*Number {
|
||||
return frame._factory.create(Number{});
|
||||
const arena = try frame._page.getArena(.tiny, "SVGNumber");
|
||||
errdefer frame._page.releaseArena(arena);
|
||||
const self = try arena.create(Number);
|
||||
self.* = .{ ._arena = arena };
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Number, page: *Page) void {
|
||||
page.releaseArena(self._arena);
|
||||
}
|
||||
|
||||
pub fn acquireRef(self: *Number) void {
|
||||
self._rc.acquire();
|
||||
}
|
||||
|
||||
pub fn releaseRef(self: *Number, page: *Page) void {
|
||||
self._rc.release(self, page);
|
||||
}
|
||||
|
||||
pub fn getValue(self: *const Number) f32 {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
@@ -138,12 +139,12 @@ pub const Path = struct {
|
||||
try self.segments.append(allocator, .{ .line = .{ .start = start, .end = end } });
|
||||
}
|
||||
|
||||
pub fn appendQuadratic(self: *Path, segment: Quadratic, allocator: Allocator) !void {
|
||||
fn appendQuadratic(self: *Path, segment: Quadratic, allocator: Allocator) !void {
|
||||
if (self.first_point == null) self.first_point = segment.start;
|
||||
try self.segments.append(allocator, .{ .quadratic = segment });
|
||||
}
|
||||
|
||||
pub fn appendCubic(self: *Path, segment: Cubic, allocator: Allocator) !void {
|
||||
fn appendCubic(self: *Path, segment: Cubic, allocator: Allocator) !void {
|
||||
if (self.first_point == null) self.first_point = segment.start;
|
||||
try self.segments.append(allocator, .{ .cubic = segment });
|
||||
}
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||
//
|
||||
// Francis Bouvier <francis@lightpanda.io>
|
||||
// Pierre Tachoire <pierre@lightpanda.io>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||
//
|
||||
// Francis Bouvier <francis@lightpanda.io>
|
||||
// Pierre Tachoire <pierre@lightpanda.io>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
@@ -14,7 +25,7 @@ const Element = @import("../Element.zig");
|
||||
|
||||
const StringList = @This();
|
||||
|
||||
pub const Delimiter = enum { whitespace, comma };
|
||||
const Delimiter = enum { whitespace, comma };
|
||||
|
||||
_element: *Element,
|
||||
_attribute_name: lp.String,
|
||||
|
||||
@@ -66,9 +66,10 @@ pub const Attachment = struct {
|
||||
mutate: *const fn (*anyopaque, *Transform, State) anyerror!void,
|
||||
};
|
||||
|
||||
// The transform owns the matrix arena even when no JS wrapper currently
|
||||
// references `matrix`. Forwarding the transform's bridge lifetime keeps the
|
||||
// stable SameObject pointer valid across garbage collections.
|
||||
// The transform lives in the matrix arena and owns it even when no JS wrapper
|
||||
// currently references `matrix`. Forwarding the transform's bridge lifetime
|
||||
// keeps the stable SameObject pointer valid across garbage collections, and
|
||||
// releasing the last ref frees the transform together with its matrix.
|
||||
pub fn acquireRef(self: *Transform) void {
|
||||
self._matrix._proto.acquireRef();
|
||||
}
|
||||
@@ -80,7 +81,8 @@ pub fn releaseRef(self: *Transform, page: *Page) void {
|
||||
pub fn detached(frame: *Frame) !*Transform {
|
||||
const matrix = try DOMMatrix.create(RO.identity(), true, frame._page);
|
||||
errdefer matrix._proto.deinit(frame._page);
|
||||
const self = try frame._factory.create(Transform{ ._matrix = matrix });
|
||||
const self = try matrix._proto._arena.create(Transform);
|
||||
self.* = .{ ._matrix = matrix };
|
||||
self.attachMatrix();
|
||||
return self;
|
||||
}
|
||||
@@ -89,7 +91,8 @@ pub fn fromMatrix(init: ?DOMMatrix2DInit, frame: *Frame) !*Transform {
|
||||
const parsed = try fixup2D(init orelse .{});
|
||||
const matrix = try DOMMatrix.create(parsed.m, true, frame._page);
|
||||
errdefer matrix._proto.deinit(frame._page);
|
||||
const self = try frame._factory.create(Transform{ ._matrix = matrix });
|
||||
const self = try matrix._proto._arena.create(Transform);
|
||||
self.* = .{ ._matrix = matrix };
|
||||
self.attachMatrix();
|
||||
return self;
|
||||
}
|
||||
@@ -106,13 +109,14 @@ pub fn fromParsed(parsed: RO.ParsedTransform, frame: *Frame) !*Transform {
|
||||
};
|
||||
const matrix = try DOMMatrix.create(parsed.matrix, parsed.is_2d, frame._page);
|
||||
errdefer matrix._proto.deinit(frame._page);
|
||||
const self = try frame._factory.create(Transform{
|
||||
const self = try matrix._proto._arena.create(Transform);
|
||||
self.* = .{
|
||||
._type = typ,
|
||||
._angle = if (typ >= 4) parsed.values[0] else 0,
|
||||
._cx = if (typ == 4 and parsed.count == 3) parsed.values[1] else 0,
|
||||
._cy = if (typ == 4 and parsed.count == 3) parsed.values[2] else 0,
|
||||
._matrix = matrix,
|
||||
});
|
||||
};
|
||||
self.attachMatrix();
|
||||
return self;
|
||||
}
|
||||
@@ -121,13 +125,14 @@ pub fn clone(self: *const Transform, frame: *Frame) !*Transform {
|
||||
const current = self.getState();
|
||||
const matrix = try DOMMatrix.create(current.matrix, current.is_2d, frame._page);
|
||||
errdefer matrix._proto.deinit(frame._page);
|
||||
const cloned = try frame._factory.create(Transform{
|
||||
const cloned = try matrix._proto._arena.create(Transform);
|
||||
cloned.* = .{
|
||||
._type = current.typ,
|
||||
._angle = current.angle,
|
||||
._cx = current.cx,
|
||||
._cy = current.cy,
|
||||
._matrix = matrix,
|
||||
});
|
||||
};
|
||||
cloned.attachMatrix();
|
||||
return cloned;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||
//
|
||||
// Francis Bouvier <francis@lightpanda.io>
|
||||
// Pierre Tachoire <pierre@lightpanda.io>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
@@ -26,10 +37,6 @@ _snapshot: std.ArrayList(u8) = .empty,
|
||||
_items: std.ArrayList(*Transform) = .empty,
|
||||
_retired: std.ArrayList(*Transform) = .empty,
|
||||
|
||||
pub fn create(element: *Element, read_only: bool, frame: *Frame) !*TransformList {
|
||||
return createForAttribute(element, comptime .wrap("transform"), read_only, frame);
|
||||
}
|
||||
|
||||
pub fn createForAttribute(element: *Element, attr_name: lp.String, read_only: bool, frame: *Frame) !*TransformList {
|
||||
return frame._factory.create(TransformList{
|
||||
._frame = frame,
|
||||
|
||||
Reference in new issue
Block a user