mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
"Better Glyph Constraint Logic" follow-up (#7822)
Follow-up to #7809, a handful of small fixes/improvements, explained individually in each commit message. > [!NOTE] > Similar to the inverted "monochrome" ft flag fix from #7809, it was pointed out that "force-autohint" was also inverted, so I did invert that too, this has the same result of no impact on users who haven't explicitly set it, but a breaking behavior change for users who have set it. *These changes definitely need to be pointed out in the 1.2 release notes!*
This commit is contained in:
@ -92,6 +92,30 @@ pub const Format = enum(c_uint) {
|
||||
_,
|
||||
};
|
||||
|
||||
/// Minification filter for textures.
|
||||
pub const MinFilter = enum(c_int) {
|
||||
nearest = c.GL_NEAREST,
|
||||
linear = c.GL_LINEAR,
|
||||
nearest_mipmap_nearest = c.GL_NEAREST_MIPMAP_NEAREST,
|
||||
linear_mipmap_nearest = c.GL_LINEAR_MIPMAP_NEAREST,
|
||||
nearest_mipmap_linear = c.GL_NEAREST_MIPMAP_LINEAR,
|
||||
linear_mipmap_linear = c.GL_LINEAR_MIPMAP_LINEAR,
|
||||
};
|
||||
|
||||
/// Magnification filter for textures.
|
||||
pub const MagFilter = enum(c_int) {
|
||||
nearest = c.GL_NEAREST,
|
||||
linear = c.GL_LINEAR,
|
||||
};
|
||||
|
||||
/// Texture coordinate wrapping mode.
|
||||
pub const Wrap = enum(c_int) {
|
||||
clamp_to_edge = c.GL_CLAMP_TO_EDGE,
|
||||
clamp_to_border = c.GL_CLAMP_TO_BORDER,
|
||||
mirrored_repeat = c.GL_MIRRORED_REPEAT,
|
||||
repeat = c.GL_REPEAT,
|
||||
};
|
||||
|
||||
/// Data type for texture images.
|
||||
pub const DataType = enum(c_uint) {
|
||||
UnsignedByte = c.GL_UNSIGNED_BYTE,
|
||||
|
@ -435,7 +435,7 @@ pub const compatibility = std.StaticStringMap(
|
||||
/// * `hinting` - Enable or disable hinting. Enabled by default.
|
||||
///
|
||||
/// * `force-autohint` - Always use the freetype auto-hinter instead of
|
||||
/// the font's native hinter. Enabled by default.
|
||||
/// the font's native hinter. Disabled by default.
|
||||
///
|
||||
/// * `monochrome` - Instructs renderer to use 1-bit monochrome rendering.
|
||||
/// This will disable anti-aliasing, and probably not look very good unless
|
||||
@ -7084,7 +7084,7 @@ pub const FreetypeLoadFlags = packed struct {
|
||||
// for Freetype itself. Ghostty hasn't made any opinionated changes
|
||||
// to these defaults.
|
||||
hinting: bool = true,
|
||||
@"force-autohint": bool = true,
|
||||
@"force-autohint": bool = false,
|
||||
monochrome: bool = false,
|
||||
autohint: bool = true,
|
||||
};
|
||||
|
@ -356,8 +356,14 @@ pub const Face = struct {
|
||||
const x = glyph_size.x;
|
||||
const y = glyph_size.y;
|
||||
|
||||
const px_width: u32 = @intFromFloat(@ceil(width));
|
||||
const px_height: u32 = @intFromFloat(@ceil(height));
|
||||
// We have to include the fractional pixels that we won't be offsetting
|
||||
// in our width and height calculations, that is, we offset by the floor
|
||||
// of the bearings when we render the glyph, meaning there's still a bit
|
||||
// of extra width to the area that's drawn in beyond just the width of
|
||||
// the glyph itself, so we include that extra fraction of a pixel when
|
||||
// calculating the width and height here.
|
||||
const px_width: u32 = @intFromFloat(@ceil(width + rect.origin.x - @floor(rect.origin.x)));
|
||||
const px_height: u32 = @intFromFloat(@ceil(height + rect.origin.y - @floor(rect.origin.y)));
|
||||
|
||||
// Settings that are specific to if we are rendering text or emoji.
|
||||
const color: struct {
|
||||
|
@ -348,7 +348,7 @@ pub const Face = struct {
|
||||
|
||||
// use options from config
|
||||
.no_hinting = !do_hinting,
|
||||
.force_autohint = !self.load_flags.@"force-autohint",
|
||||
.force_autohint = self.load_flags.@"force-autohint",
|
||||
.no_autohint = !self.load_flags.autohint,
|
||||
|
||||
// NO_SVG set to true because we don't currently support rendering
|
||||
|
@ -140,24 +140,7 @@ pub const Canvas = struct {
|
||||
const region_height = sfc_height -| self.clip_top -| self.clip_bottom;
|
||||
|
||||
// Allocate our texture atlas region
|
||||
const region = region: {
|
||||
// Reserve a region with a 1px margin on the bottom and right edges
|
||||
// so that we can avoid interpolation between adjacent glyphs during
|
||||
// texture sampling.
|
||||
var region = try atlas.reserve(
|
||||
alloc,
|
||||
region_width + 1,
|
||||
region_height + 1,
|
||||
);
|
||||
|
||||
// Modify the region to remove the margin so that we write to the
|
||||
// non-zero location. The data in an Altlas is always initialized
|
||||
// to zero (Atlas.clear) so we don't need to worry about zero-ing
|
||||
// that.
|
||||
region.width -= 1;
|
||||
region.height -= 1;
|
||||
break :region region;
|
||||
};
|
||||
const region = try atlas.reserve(alloc, region_width, region_height);
|
||||
|
||||
if (region.width > 0 and region.height > 0) {
|
||||
const buffer: []u8 = @ptrCast(self.sfc.image_surface_alpha8.buf);
|
||||
|
@ -356,6 +356,10 @@ pub inline fn textureOptions(self: OpenGL) Texture.Options {
|
||||
.format = .rgba,
|
||||
.internal_format = .srgba,
|
||||
.target = .@"2D",
|
||||
.min_filter = .linear,
|
||||
.mag_filter = .linear,
|
||||
.wrap_s = .clamp_to_edge,
|
||||
.wrap_t = .clamp_to_edge,
|
||||
};
|
||||
}
|
||||
|
||||
@ -388,6 +392,16 @@ pub inline fn imageTextureOptions(
|
||||
.format = format.toPixelFormat(),
|
||||
.internal_format = if (srgb) .srgba else .rgba,
|
||||
.target = .@"2D",
|
||||
// TODO: Generate mipmaps for image textures and use
|
||||
// linear_mipmap_linear filtering so that they
|
||||
// look good even when scaled way down.
|
||||
.min_filter = .linear,
|
||||
.mag_filter = .linear,
|
||||
// TODO: Separate out background image options, use
|
||||
// repeating coordinate modes so we don't have
|
||||
// to do the modulus in the shader.
|
||||
.wrap_s = .clamp_to_edge,
|
||||
.wrap_t = .clamp_to_edge,
|
||||
};
|
||||
}
|
||||
|
||||
@ -409,6 +423,10 @@ pub fn initAtlasTexture(
|
||||
.format = format,
|
||||
.internal_format = internal_format,
|
||||
.target = .Rectangle,
|
||||
.min_filter = .nearest,
|
||||
.mag_filter = .nearest,
|
||||
.wrap_s = .clamp_to_edge,
|
||||
.wrap_t = .clamp_to_edge,
|
||||
},
|
||||
atlas.size,
|
||||
atlas.size,
|
||||
|
@ -16,6 +16,10 @@ pub const Options = struct {
|
||||
format: gl.Texture.Format,
|
||||
internal_format: gl.Texture.InternalFormat,
|
||||
target: gl.Texture.Target,
|
||||
min_filter: gl.Texture.MinFilter,
|
||||
mag_filter: gl.Texture.MagFilter,
|
||||
wrap_s: gl.Texture.Wrap,
|
||||
wrap_t: gl.Texture.Wrap,
|
||||
};
|
||||
|
||||
texture: gl.Texture,
|
||||
@ -48,10 +52,10 @@ pub fn init(
|
||||
{
|
||||
const texbind = tex.bind(opts.target) catch return error.OpenGLFailed;
|
||||
defer texbind.unbind();
|
||||
texbind.parameter(.WrapS, gl.c.GL_CLAMP_TO_EDGE) catch return error.OpenGLFailed;
|
||||
texbind.parameter(.WrapT, gl.c.GL_CLAMP_TO_EDGE) catch return error.OpenGLFailed;
|
||||
texbind.parameter(.MinFilter, gl.c.GL_LINEAR) catch return error.OpenGLFailed;
|
||||
texbind.parameter(.MagFilter, gl.c.GL_LINEAR) catch return error.OpenGLFailed;
|
||||
texbind.parameter(.WrapS, @intFromEnum(opts.wrap_s)) catch return error.OpenGLFailed;
|
||||
texbind.parameter(.WrapT, @intFromEnum(opts.wrap_t)) catch return error.OpenGLFailed;
|
||||
texbind.parameter(.MinFilter, @intFromEnum(opts.min_filter)) catch return error.OpenGLFailed;
|
||||
texbind.parameter(.MagFilter, @intFromEnum(opts.mag_filter)) catch return error.OpenGLFailed;
|
||||
texbind.image2D(
|
||||
0,
|
||||
opts.internal_format,
|
||||
|
Reference in New Issue
Block a user