mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
renderer: font size changed event, OpenGL impl
This commit is contained in:
@ -156,22 +156,15 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
var shaper = try font.Shaper.init(shape_buf);
|
var shaper = try font.Shaper.init(shape_buf);
|
||||||
errdefer shaper.deinit();
|
errdefer shaper.deinit();
|
||||||
|
|
||||||
// Get our cell metrics based on a regular font ascii 'M'. Why 'M'?
|
|
||||||
// Doesn't matter, any normal ASCII will do we're just trying to make
|
|
||||||
// sure we use the regular font.
|
|
||||||
const metrics = metrics: {
|
|
||||||
const index = (try options.font_group.indexForCodepoint(alloc, 'M', .regular, .text)).?;
|
|
||||||
const face = try options.font_group.group.faceFromIndex(index);
|
|
||||||
break :metrics face.metrics;
|
|
||||||
};
|
|
||||||
log.debug("cell dimensions={}", .{metrics});
|
|
||||||
|
|
||||||
// Create our shader
|
// Create our shader
|
||||||
const program = try gl.Program.createVF(
|
const program = try gl.Program.createVF(
|
||||||
@embedFile("shaders/cell.v.glsl"),
|
@embedFile("shaders/cell.v.glsl"),
|
||||||
@embedFile("shaders/cell.f.glsl"),
|
@embedFile("shaders/cell.f.glsl"),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Setup our font metrics uniform
|
||||||
|
const metrics = try resetFontMetrics(alloc, program, options.font_group);
|
||||||
|
|
||||||
// Set our cell dimensions
|
// Set our cell dimensions
|
||||||
const pbind = try program.use();
|
const pbind = try program.use();
|
||||||
defer pbind.unbind();
|
defer pbind.unbind();
|
||||||
@ -314,21 +307,26 @@ pub fn deinit(self: *OpenGL) void {
|
|||||||
self.vao.destroy();
|
self.vao.destroy();
|
||||||
self.program.destroy();
|
self.program.destroy();
|
||||||
|
|
||||||
{
|
self.resetCellsLRU();
|
||||||
// Our LRU values are array lists so we need to deallocate those first
|
self.cells_lru.deinit(self.alloc);
|
||||||
var it = self.cells_lru.queue.first;
|
|
||||||
while (it) |node| {
|
|
||||||
it = node.next;
|
|
||||||
node.data.value.deinit(self.alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.cells_lru.deinit(self.alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.cells.deinit(self.alloc);
|
self.cells.deinit(self.alloc);
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resetCellsLRU(self: *OpenGL) void {
|
||||||
|
// Our LRU values are array lists so we need to deallocate those first
|
||||||
|
var it = self.cells_lru.queue.first;
|
||||||
|
while (it) |node| {
|
||||||
|
it = node.next;
|
||||||
|
node.data.value.deinit(self.alloc);
|
||||||
|
}
|
||||||
|
self.cells_lru.deinit(self.alloc);
|
||||||
|
|
||||||
|
// Initialize our new LRU
|
||||||
|
self.cells_lru = CellsLRU.init(0);
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the hints that we want for this
|
/// Returns the hints that we want for this
|
||||||
pub fn windowHints() glfw.Window.Hints {
|
pub fn windowHints() glfw.Window.Hints {
|
||||||
return .{
|
return .{
|
||||||
@ -448,15 +446,69 @@ pub fn threadExit(self: *const OpenGL) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Callback when the focus changes for the terminal this is rendering.
|
/// Callback when the focus changes for the terminal this is rendering.
|
||||||
|
///
|
||||||
|
/// Must be called on the render thread.
|
||||||
pub fn setFocus(self: *OpenGL, focus: bool) !void {
|
pub fn setFocus(self: *OpenGL, focus: bool) !void {
|
||||||
self.focused = focus;
|
self.focused = focus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called to toggle the blink state of the cursor
|
/// Called to toggle the blink state of the cursor
|
||||||
|
///
|
||||||
|
/// Must be called on the render thread.
|
||||||
pub fn blinkCursor(self: *OpenGL, reset: bool) void {
|
pub fn blinkCursor(self: *OpenGL, reset: bool) void {
|
||||||
self.cursor_visible = reset or !self.cursor_visible;
|
self.cursor_visible = reset or !self.cursor_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the new font size.
|
||||||
|
///
|
||||||
|
/// Must be called on the render thread.
|
||||||
|
pub fn setFontSize(self: *OpenGL, size: font.face.DesiredSize) !void {
|
||||||
|
// Set our new size, this will also reset our font atlas.
|
||||||
|
try self.font_group.setSize(size);
|
||||||
|
|
||||||
|
// Invalidate our cell cache.
|
||||||
|
self.resetCellsLRU();
|
||||||
|
|
||||||
|
// Reset our GPU uniforms
|
||||||
|
const metrics = try resetFontMetrics(self.alloc, self.program, self.font_group);
|
||||||
|
|
||||||
|
// Recalculate our cell size. If it is the same as before, then we do
|
||||||
|
// nothing since the grid size couldn't have possibly changed.
|
||||||
|
const new_cell_size = .{ .width = metrics.cell_width, .height = metrics.cell_height };
|
||||||
|
if (std.meta.eql(self.cell_size, new_cell_size)) return;
|
||||||
|
|
||||||
|
// Notify the window that the cell size changed.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reload the font metrics, recalculate cell size, and send that all
|
||||||
|
/// down to the GPU.
|
||||||
|
fn resetFontMetrics(
|
||||||
|
alloc: Allocator,
|
||||||
|
program: gl.Program,
|
||||||
|
font_group: *font.GroupCache,
|
||||||
|
) !font.face.Metrics {
|
||||||
|
// Get our cell metrics based on a regular font ascii 'M'. Why 'M'?
|
||||||
|
// Doesn't matter, any normal ASCII will do we're just trying to make
|
||||||
|
// sure we use the regular font.
|
||||||
|
const metrics = metrics: {
|
||||||
|
const index = (try font_group.indexForCodepoint(alloc, 'M', .regular, .text)).?;
|
||||||
|
const face = try font_group.group.faceFromIndex(index);
|
||||||
|
break :metrics face.metrics;
|
||||||
|
};
|
||||||
|
log.debug("cell dimensions={}", .{metrics});
|
||||||
|
|
||||||
|
// Set our uniforms that rely on metrics
|
||||||
|
const pbind = try program.use();
|
||||||
|
defer pbind.unbind();
|
||||||
|
try program.setUniform("cell_size", @Vector(2, f32){ metrics.cell_width, metrics.cell_height });
|
||||||
|
try program.setUniform("underline_position", metrics.underline_position);
|
||||||
|
try program.setUniform("underline_thickness", metrics.underline_thickness);
|
||||||
|
try program.setUniform("strikethrough_position", metrics.strikethrough_position);
|
||||||
|
try program.setUniform("strikethrough_thickness", metrics.strikethrough_thickness);
|
||||||
|
|
||||||
|
return metrics;
|
||||||
|
}
|
||||||
|
|
||||||
/// The primary render callback that is completely thread-safe.
|
/// The primary render callback that is completely thread-safe.
|
||||||
pub fn render(
|
pub fn render(
|
||||||
self: *OpenGL,
|
self: *OpenGL,
|
||||||
@ -946,7 +998,7 @@ pub fn updateCell(
|
|||||||
|
|
||||||
/// Returns the grid size for a given screen size. This is safe to call
|
/// Returns the grid size for a given screen size. This is safe to call
|
||||||
/// on any thread.
|
/// on any thread.
|
||||||
pub fn gridSize(self: *OpenGL, screen_size: renderer.ScreenSize) renderer.GridSize {
|
fn gridSize(self: *OpenGL, screen_size: renderer.ScreenSize) renderer.GridSize {
|
||||||
return renderer.GridSize.init(
|
return renderer.GridSize.init(
|
||||||
screen_size.subPadding(self.padding.explicit),
|
screen_size.subPadding(self.padding.explicit),
|
||||||
self.cell_size,
|
self.cell_size,
|
||||||
|
@ -275,6 +275,10 @@ fn drainMailbox(self: *Thread) !void {
|
|||||||
_ = try self.cursor_h.again();
|
_ = try self.cursor_h.again();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.font_size => |size| {
|
||||||
|
try self.renderer.setFontSize(size);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
const font = @import("../font/main.zig");
|
||||||
|
|
||||||
/// The messages that can be sent to a renderer thread.
|
/// The messages that can be sent to a renderer thread.
|
||||||
pub const Message = union(enum) {
|
pub const Message = union(enum) {
|
||||||
@ -12,4 +13,9 @@ pub const Message = union(enum) {
|
|||||||
/// Reset the cursor blink by immediately showing the cursor then
|
/// Reset the cursor blink by immediately showing the cursor then
|
||||||
/// restarting the timer.
|
/// restarting the timer.
|
||||||
reset_cursor_blink: void,
|
reset_cursor_blink: void,
|
||||||
|
|
||||||
|
/// Change the font size. This should recalculate the grid size and
|
||||||
|
/// send a grid size change message back to the window thread if
|
||||||
|
/// the size changes.
|
||||||
|
font_size: font.face.DesiredSize,
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const App = @import("../App.zig");
|
const App = @import("../App.zig");
|
||||||
const Window = @import("../Window.zig");
|
const Window = @import("../Window.zig");
|
||||||
|
const renderer = @import("../renderer.zig");
|
||||||
|
|
||||||
/// The message types that can be sent to a single window.
|
/// The message types that can be sent to a single window.
|
||||||
pub const Message = union(enum) {
|
pub const Message = union(enum) {
|
||||||
|
Reference in New Issue
Block a user