font: web canvas creates a canvas element

This commit is contained in:
Mitchell Hashimoto
2022-12-03 22:11:01 -08:00
parent 21faf0b6fb
commit 940828ed97
4 changed files with 95 additions and 4 deletions

View File

@ -122,6 +122,7 @@ pub fn build(b: *std.build.Builder) !void {
wasm.setOutputDir("zig-out"); wasm.setOutputDir("zig-out");
// Wasm-specific deps // Wasm-specific deps
wasm.addPackage(js.pkg);
wasm.addPackage(tracylib.pkg); wasm.addPackage(tracylib.pkg);
wasm.addPackage(utf8proc.pkg); wasm.addPackage(utf8proc.pkg);
_ = try utf8proc.link(b, wasm); _ = try utf8proc.link(b, wasm);

View File

@ -1,8 +1,8 @@
const builtin = @import("builtin"); const builtin = @import("builtin");
const options = @import("main.zig").options; const options = @import("main.zig").options;
const freetype = @import("face/freetype.zig"); pub const freetype = @import("face/freetype.zig");
const coretext = @import("face/coretext.zig"); pub const coretext = @import("face/coretext.zig");
const web_canvas = @import("face/web_canvas.zig"); pub const web_canvas = @import("face/web_canvas.zig");
/// Face implementation for the compile options. /// Face implementation for the compile options.
pub const Face = switch (options.backend) { pub const Face = switch (options.backend) {

View File

@ -1,11 +1,99 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const assert = std.debug.assert; const assert = std.debug.assert;
const testing = std.testing;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const js = @import("zig-js");
const font = @import("../main.zig"); const font = @import("../main.zig");
const log = std.log.scoped(.font_face); const log = std.log.scoped(.font_face);
pub const Face = struct { pub const Face = struct {
// TODO /// The web canvas face makes use of an allocator when interacting
/// with the JS environment.
alloc: Allocator,
/// The CSS "font" attribute, excluding size.
font_str: []const u8,
/// The size we currently have set.
size: font.face.DesiredSize,
/// The presentation for this font. This is a heuristic since fonts don't have
/// a way to declare this. We just assume a font with color is an emoji font.
presentation: font.Presentation,
/// Metrics for this font face. These are useful for renderers.
metrics: font.face.Metrics,
/// The canvas element that we will reuse to render glyphs
canvas: js.Object,
/// Initialize a web canvas font with a "raw" value. The "raw" value can
/// be any valid value for a CSS "font" property EXCLUDING the size. The
/// size is always added via the `size` parameter.
///
/// The raw value is copied so the caller can free it after it is gone.
pub fn initNamed(
alloc: Allocator,
raw: []const u8,
size: font.face.DesiredSize,
) !Face {
// Copy our font string because we're going to have to reuse it.
const font_str = try alloc.dupe(u8, raw);
errdefer alloc.free(font_str);
// Create our canvas that we're going to continue to reuse.
const doc = try js.global.get(js.Object, "document");
defer doc.deinit();
const canvas = try doc.call(js.Object, "createElement", .{js.string("canvas")});
errdefer canvas.deinit();
return Face{
.alloc = alloc,
.font_str = font_str,
.size = size,
.canvas = canvas,
// TODO: real metrics
.metrics = undefined,
// TODO: figure out how we're going to do emoji with web canvas
.presentation = .text,
};
}
pub fn deinit(self: *Face) void {
self.alloc.free(self.font_str);
self.canvas.deinit();
self.* = undefined;
}
};
/// The wasm-compatible API.
pub const Wasm = struct {
const wasm = @import("../../wasm.zig");
const alloc = wasm.alloc;
export fn face_new(ptr: [*]const u8, len: usize, pts: u16) ?*Face {
return face_new_(ptr, len, pts) catch null;
}
fn face_new_(ptr: [*]const u8, len: usize, pts: u16) !*Face {
var face = try Face.initNamed(alloc, ptr[0..len], .{ .points = pts });
errdefer face.deinit();
var result = try alloc.create(Face);
errdefer alloc.destroy(result);
result.* = face;
return result;
}
export fn face_free(ptr: ?*Face) void {
if (ptr) |v| {
v.deinit();
alloc.destroy(v);
}
}
}; };

View File

@ -17,8 +17,10 @@ pub const Sprite = sprite.Sprite;
pub const Descriptor = discovery.Descriptor; pub const Descriptor = discovery.Descriptor;
pub const Discover = discovery.Discover; pub const Discover = discovery.Discover;
/// If we're targeting wasm then we export some wasm APIs.
pub usingnamespace if (builtin.target.isWasm()) struct { pub usingnamespace if (builtin.target.isWasm()) struct {
pub usingnamespace Atlas.Wasm; pub usingnamespace Atlas.Wasm;
pub usingnamespace face.web_canvas.Wasm;
} else struct {}; } else struct {};
/// Build options /// Build options