mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
font: web canvas creates a canvas element
This commit is contained in:
@ -122,6 +122,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
wasm.setOutputDir("zig-out");
|
||||
|
||||
// Wasm-specific deps
|
||||
wasm.addPackage(js.pkg);
|
||||
wasm.addPackage(tracylib.pkg);
|
||||
wasm.addPackage(utf8proc.pkg);
|
||||
_ = try utf8proc.link(b, wasm);
|
||||
|
@ -1,8 +1,8 @@
|
||||
const builtin = @import("builtin");
|
||||
const options = @import("main.zig").options;
|
||||
const freetype = @import("face/freetype.zig");
|
||||
const coretext = @import("face/coretext.zig");
|
||||
const web_canvas = @import("face/web_canvas.zig");
|
||||
pub const freetype = @import("face/freetype.zig");
|
||||
pub const coretext = @import("face/coretext.zig");
|
||||
pub const web_canvas = @import("face/web_canvas.zig");
|
||||
|
||||
/// Face implementation for the compile options.
|
||||
pub const Face = switch (options.backend) {
|
||||
|
@ -1,11 +1,99 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const js = @import("zig-js");
|
||||
const font = @import("../main.zig");
|
||||
|
||||
const log = std.log.scoped(.font_face);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -17,8 +17,10 @@ pub const Sprite = sprite.Sprite;
|
||||
pub const Descriptor = discovery.Descriptor;
|
||||
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 Atlas.Wasm;
|
||||
pub usingnamespace face.web_canvas.Wasm;
|
||||
} else struct {};
|
||||
|
||||
/// Build options
|
||||
|
Reference in New Issue
Block a user