mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
switch to pure Zig font atlas
This commit is contained in:
13
src/App.zig
13
src/App.zig
@ -4,12 +4,18 @@
|
||||
const App = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const glfw = @import("glfw");
|
||||
const gl = @import("opengl.zig");
|
||||
const TextRenderer = @import("TextRenderer.zig");
|
||||
const TextRenderer = if (true)
|
||||
@import("TextRenderer.zig")
|
||||
else
|
||||
@import("TextRenderer2.zig");
|
||||
|
||||
const log = std.log;
|
||||
|
||||
alloc: Allocator,
|
||||
|
||||
window: glfw.Window,
|
||||
|
||||
text: TextRenderer,
|
||||
@ -17,7 +23,7 @@ text: TextRenderer,
|
||||
/// Initialize the main app instance. This creates the main window, sets
|
||||
/// up the renderer state, compiles the shaders, etc. This is the primary
|
||||
/// "startup" logic.
|
||||
pub fn init(alloc: std.mem.Allocator) !App {
|
||||
pub fn init(alloc: Allocator) !App {
|
||||
// Create our window
|
||||
const window = try glfw.Window.create(640, 480, "ghostty", null, null, .{
|
||||
.context_version_major = 3,
|
||||
@ -57,13 +63,14 @@ pub fn init(alloc: std.mem.Allocator) !App {
|
||||
}).callback);
|
||||
|
||||
return App{
|
||||
.alloc = alloc,
|
||||
.window = window,
|
||||
.text = texter,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *App) void {
|
||||
self.text.deinit();
|
||||
self.text.deinit(self.alloc);
|
||||
self.window.destroy();
|
||||
self.* = undefined;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ pub fn loadFaceFromMemory(self: *FontAtlas, source: [:0]const u8, size: u32) !vo
|
||||
}
|
||||
|
||||
/// Get the glyph for the given codepoint.
|
||||
pub fn getGlyph(self: *FontAtlas, v: anytype) ?*Glyph {
|
||||
pub fn getGlyph(self: FontAtlas, v: anytype) ?*Glyph {
|
||||
const utf32 = codepoint(v);
|
||||
const entry = self.glyphs.getEntry(utf32) orelse return null;
|
||||
return entry.value_ptr;
|
||||
@ -170,8 +170,15 @@ pub fn addGlyph(self: *FontAtlas, alloc: Allocator, v: anytype) !void {
|
||||
.t0 = @intToFloat(f32, region.y) / @intToFloat(f32, self.atlas.size),
|
||||
.s1 = @intToFloat(f32, region.x + tgt_w) / @intToFloat(f32, self.atlas.size),
|
||||
.t1 = @intToFloat(f32, region.y + tgt_h) / @intToFloat(f32, self.atlas.size),
|
||||
.advance_x = @intToFloat(f32, glyph.*.advance.x),
|
||||
.advance_x = f26dot6ToFloat(glyph.*.advance.x),
|
||||
};
|
||||
|
||||
log.debug("loaded glyph codepoint={} glyph={}", .{ utf32, gop.value_ptr.* });
|
||||
}
|
||||
|
||||
/// Convert 26.6 pixel format to f32
|
||||
fn f26dot6ToFloat(v: ftc.FT_F26Dot6) f32 {
|
||||
return @intToFloat(f32, v) / 64.0;
|
||||
}
|
||||
|
||||
/// Returns the UTF-32 codepoint for the given value.
|
||||
|
@ -4,12 +4,14 @@ const std = @import("std");
|
||||
const ftc = @import("freetype/c.zig");
|
||||
const gl = @import("opengl.zig");
|
||||
const gb = @import("gb_math.zig");
|
||||
const ftgl = @import("freetype-gl/c.zig");
|
||||
const Atlas = @import("Atlas.zig");
|
||||
const FontAtlas = @import("FontAtlas.zig");
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
projection: gb.gbMat4 = undefined,
|
||||
font: *ftgl.texture_font_t,
|
||||
atlas: *ftgl.texture_atlas_t,
|
||||
|
||||
font: FontAtlas,
|
||||
atlas: Atlas,
|
||||
|
||||
program: gl.Program,
|
||||
tex: gl.Texture,
|
||||
@ -23,25 +25,16 @@ const Char = struct {
|
||||
};
|
||||
|
||||
pub fn init(alloc: std.mem.Allocator) !TextRenderer {
|
||||
const atlas = ftgl.texture_atlas_new(512, 512, 1);
|
||||
if (atlas == null) return error.FontAtlasFail;
|
||||
errdefer ftgl.texture_atlas_delete(atlas);
|
||||
const font = ftgl.texture_font_new_from_memory(
|
||||
atlas,
|
||||
48,
|
||||
face_ttf,
|
||||
face_ttf.len,
|
||||
);
|
||||
if (font == null) return error.FontInitFail;
|
||||
errdefer ftgl.texture_font_delete(font);
|
||||
var atlas = try Atlas.init(alloc, 512);
|
||||
errdefer atlas.deinit(alloc);
|
||||
var font = try FontAtlas.init(atlas);
|
||||
errdefer font.deinit(alloc);
|
||||
try font.loadFaceFromMemory(face_ttf, 48);
|
||||
|
||||
// Load all visible ASCII characters.
|
||||
var i: u8 = 32;
|
||||
while (i < 127) : (i += 1) {
|
||||
// Load the character
|
||||
if (ftgl.texture_font_load_glyph(font, &i) == 0) {
|
||||
return error.GlyphLoadFailed;
|
||||
}
|
||||
try font.addGlyph(alloc, i);
|
||||
}
|
||||
|
||||
// Build our texture
|
||||
@ -55,12 +48,12 @@ pub fn init(alloc: std.mem.Allocator) !TextRenderer {
|
||||
try binding.image2D(
|
||||
0,
|
||||
.Red,
|
||||
@intCast(c_int, atlas.*.width),
|
||||
@intCast(c_int, atlas.*.height),
|
||||
@intCast(c_int, atlas.size),
|
||||
@intCast(c_int, atlas.size),
|
||||
0,
|
||||
.Red,
|
||||
.UnsignedByte,
|
||||
atlas.*.data,
|
||||
atlas.data.ptr,
|
||||
);
|
||||
|
||||
// Create our shader
|
||||
@ -84,9 +77,9 @@ pub fn init(alloc: std.mem.Allocator) !TextRenderer {
|
||||
return res;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *TextRenderer) void {
|
||||
ftgl.texture_font_delete(self.font);
|
||||
ftgl.texture_atlas_delete(self.atlas);
|
||||
pub fn deinit(self: *TextRenderer, alloc: std.mem.Allocator) void {
|
||||
self.font.deinit(alloc);
|
||||
self.atlas.deinit(alloc);
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
@ -125,7 +118,7 @@ pub fn render(
|
||||
|
||||
var curx: f32 = x;
|
||||
for (text) |c, i| {
|
||||
if (ftgl.texture_font_get_glyph(self.font, &c)) |glyph_ptr| {
|
||||
if (self.font.getGlyph(c)) |glyph_ptr| {
|
||||
const glyph = glyph_ptr.*;
|
||||
const kerning = 0; // for now
|
||||
curx += kerning;
|
||||
|
Reference in New Issue
Block a user