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 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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user