switch to pure Zig font atlas

This commit is contained in:
Mitchell Hashimoto
2022-04-05 19:54:13 -07:00
parent d51ed2536c
commit 388c0056c9
3 changed files with 37 additions and 30 deletions

View File

@ -4,12 +4,18 @@
const App = @This(); const App = @This();
const std = @import("std"); const std = @import("std");
const Allocator = std.mem.Allocator;
const glfw = @import("glfw"); const glfw = @import("glfw");
const gl = @import("opengl.zig"); 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; const log = std.log;
alloc: Allocator,
window: glfw.Window, window: glfw.Window,
text: TextRenderer, text: TextRenderer,
@ -17,7 +23,7 @@ text: TextRenderer,
/// Initialize the main app instance. This creates the main window, sets /// Initialize the main app instance. This creates the main window, sets
/// up the renderer state, compiles the shaders, etc. This is the primary /// up the renderer state, compiles the shaders, etc. This is the primary
/// "startup" logic. /// "startup" logic.
pub fn init(alloc: std.mem.Allocator) !App { pub fn init(alloc: Allocator) !App {
// Create our window // Create our window
const window = try glfw.Window.create(640, 480, "ghostty", null, null, .{ const window = try glfw.Window.create(640, 480, "ghostty", null, null, .{
.context_version_major = 3, .context_version_major = 3,
@ -57,13 +63,14 @@ pub fn init(alloc: std.mem.Allocator) !App {
}).callback); }).callback);
return App{ return App{
.alloc = alloc,
.window = window, .window = window,
.text = texter, .text = texter,
}; };
} }
pub fn deinit(self: *App) void { pub fn deinit(self: *App) void {
self.text.deinit(); self.text.deinit(self.alloc);
self.window.destroy(); self.window.destroy();
self.* = undefined; self.* = undefined;
} }

View File

@ -104,7 +104,7 @@ pub fn loadFaceFromMemory(self: *FontAtlas, source: [:0]const u8, size: u32) !vo
} }
/// Get the glyph for the given codepoint. /// 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 utf32 = codepoint(v);
const entry = self.glyphs.getEntry(utf32) orelse return null; const entry = self.glyphs.getEntry(utf32) orelse return null;
return entry.value_ptr; 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), .t0 = @intToFloat(f32, region.y) / @intToFloat(f32, self.atlas.size),
.s1 = @intToFloat(f32, region.x + tgt_w) / @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), .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. /// Returns the UTF-32 codepoint for the given value.

View File

@ -4,12 +4,14 @@ const std = @import("std");
const ftc = @import("freetype/c.zig"); const ftc = @import("freetype/c.zig");
const gl = @import("opengl.zig"); const gl = @import("opengl.zig");
const gb = @import("gb_math.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, alloc: std.mem.Allocator,
projection: gb.gbMat4 = undefined, projection: gb.gbMat4 = undefined,
font: *ftgl.texture_font_t,
atlas: *ftgl.texture_atlas_t, font: FontAtlas,
atlas: Atlas,
program: gl.Program, program: gl.Program,
tex: gl.Texture, tex: gl.Texture,
@ -23,25 +25,16 @@ const Char = struct {
}; };
pub fn init(alloc: std.mem.Allocator) !TextRenderer { pub fn init(alloc: std.mem.Allocator) !TextRenderer {
const atlas = ftgl.texture_atlas_new(512, 512, 1); var atlas = try Atlas.init(alloc, 512);
if (atlas == null) return error.FontAtlasFail; errdefer atlas.deinit(alloc);
errdefer ftgl.texture_atlas_delete(atlas); var font = try FontAtlas.init(atlas);
const font = ftgl.texture_font_new_from_memory( errdefer font.deinit(alloc);
atlas, try font.loadFaceFromMemory(face_ttf, 48);
48,
face_ttf,
face_ttf.len,
);
if (font == null) return error.FontInitFail;
errdefer ftgl.texture_font_delete(font);
// Load all visible ASCII characters. // Load all visible ASCII characters.
var i: u8 = 32; var i: u8 = 32;
while (i < 127) : (i += 1) { while (i < 127) : (i += 1) {
// Load the character try font.addGlyph(alloc, i);
if (ftgl.texture_font_load_glyph(font, &i) == 0) {
return error.GlyphLoadFailed;
}
} }
// Build our texture // Build our texture
@ -55,12 +48,12 @@ pub fn init(alloc: std.mem.Allocator) !TextRenderer {
try binding.image2D( try binding.image2D(
0, 0,
.Red, .Red,
@intCast(c_int, atlas.*.width), @intCast(c_int, atlas.size),
@intCast(c_int, atlas.*.height), @intCast(c_int, atlas.size),
0, 0,
.Red, .Red,
.UnsignedByte, .UnsignedByte,
atlas.*.data, atlas.data.ptr,
); );
// Create our shader // Create our shader
@ -84,9 +77,9 @@ pub fn init(alloc: std.mem.Allocator) !TextRenderer {
return res; return res;
} }
pub fn deinit(self: *TextRenderer) void { pub fn deinit(self: *TextRenderer, alloc: std.mem.Allocator) void {
ftgl.texture_font_delete(self.font); self.font.deinit(alloc);
ftgl.texture_atlas_delete(self.atlas); self.atlas.deinit(alloc);
self.* = undefined; self.* = undefined;
} }
@ -125,7 +118,7 @@ pub fn render(
var curx: f32 = x; var curx: f32 = x;
for (text) |c, i| { 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 glyph = glyph_ptr.*;
const kerning = 0; // for now const kerning = 0; // for now
curx += kerning; curx += kerning;