diff --git a/src/App.zig b/src/App.zig index 77e7f7b15..9d1959bab 100644 --- a/src/App.zig +++ b/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; } diff --git a/src/FontAtlas.zig b/src/FontAtlas.zig index 2a48fd1f8..30c440946 100644 --- a/src/FontAtlas.zig +++ b/src/FontAtlas.zig @@ -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. diff --git a/src/TextRenderer.zig b/src/TextRenderer.zig index 3ee001191..a3bf68a57 100644 --- a/src/TextRenderer.zig +++ b/src/TextRenderer.zig @@ -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;