diff --git a/src/config/Config.zig b/src/config/Config.zig index fdea944ad..46eb03fe2 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -416,9 +416,12 @@ pub const compatibility = std.StaticStringMap( /// necessarily force them to be. Decreasing this value will make nerd font /// icons smaller. /// -/// The default value for the icon height is 1.2 times the height of capital -/// letters in your primary font, so something like -16.6% would make icons -/// roughly the same height as capital letters. +/// This value only applies to icons that are constrained to a single cell by +/// neighboring characters. An icon that is free to spread across two cells +/// can always use up to the full line height of the primary font. +/// +/// The default value is 2/3 times the height of capital letters in your primary +/// font plus 1/3 times the font's line height. /// /// See the notes about adjustments in `adjust-cell-width`. /// diff --git a/src/font/Collection.zig b/src/font/Collection.zig index ad9590d70..997c72aa7 100644 --- a/src/font/Collection.zig +++ b/src/font/Collection.zig @@ -1213,6 +1213,9 @@ test "metrics" { // and 1em should be the point size * dpi scale, so 12 * (96/72) // which is 16, and 16 * 1.049 = 16.784, which finally is rounded // to 17. + // + // The icon height is (2 * cap_height + face_height) / 3 + // = (2 * 623 + 1049) / 3 = 765, and 16 * 0.765 = 12.24. .cell_height = 17, .cell_baseline = 3, .underline_position = 17, @@ -1223,7 +1226,10 @@ test "metrics" { .overline_thickness = 1, .box_thickness = 1, .cursor_height = 17, - .icon_height = 11, + .icon_height = 12.24, + .face_width = 8.0, + .face_height = 16.784, + .face_y = @round(3.04) - @as(f64, 3.04), // use f64, not comptime float, for exact match with runtime value }, c.metrics); // Resize should change metrics @@ -1240,7 +1246,10 @@ test "metrics" { .overline_thickness = 2, .box_thickness = 2, .cursor_height = 34, - .icon_height = 23, + .icon_height = 24.48, + .face_width = 16.0, + .face_height = 33.568, + .face_y = @round(6.08) - @as(f64, 6.08), // use f64, not comptime float, for exact match with runtime value }, c.metrics); } diff --git a/src/font/Metrics.zig b/src/font/Metrics.zig index 9f6df9dc3..a0bc047c4 100644 --- a/src/font/Metrics.zig +++ b/src/font/Metrics.zig @@ -36,11 +36,17 @@ cursor_thickness: u32 = 1, cursor_height: u32, /// The constraint height for nerd fonts icons. -icon_height: u32, +icon_height: f64, -/// Original cell width in pixels. This is used to keep -/// glyphs centered if the cell width is adjusted wider. -original_cell_width: ?u32 = null, +/// The unrounded face width, used in scaling calculations. +face_width: f64, + +/// The unrounded face height, used in scaling calculations. +face_height: f64, + +/// The vertical bearing of face within the pixel-rounded +/// and possibly height-adjusted cell +face_y: f64, /// Minimum acceptable values for some fields to prevent modifiers /// from being able to, for example, cause 0-thickness underlines. @@ -53,7 +59,9 @@ const Minimums = struct { const box_thickness = 1; const cursor_thickness = 1; const cursor_height = 1; - const icon_height = 1; + const icon_height = 1.0; + const face_height = 1.0; + const face_width = 1.0; }; /// Metrics extracted from a font face, based on @@ -214,8 +222,10 @@ pub fn calc(face: FaceMetrics) Metrics { // We use the ceiling of the provided cell width and height to ensure // that the cell is large enough for the provided size, since we cast // it to an integer later. - const cell_width = @ceil(face.cell_width); - const cell_height = @ceil(face.lineHeight()); + const face_width = face.cell_width; + const face_height = face.lineHeight(); + const cell_width = @ceil(face_width); + const cell_height = @ceil(face_height); // We split our line gap in two parts, and put half of it on the top // of the cell and the other half on the bottom, so that our text never @@ -224,7 +234,11 @@ pub fn calc(face: FaceMetrics) Metrics { // Unlike all our other metrics, `cell_baseline` is relative to the // BOTTOM of the cell. - const cell_baseline = @round(half_line_gap - face.descent); + const face_baseline = half_line_gap - face.descent; + const cell_baseline = @round(face_baseline); + + // We keep track of the vertical bearing of the face in the cell + const face_y = cell_baseline - face_baseline; // We calculate a top_to_baseline to make following calculations simpler. const top_to_baseline = cell_height - cell_baseline; @@ -237,16 +251,8 @@ pub fn calc(face: FaceMetrics) Metrics { const underline_position = @round(top_to_baseline - face.underlinePosition()); const strikethrough_position = @round(top_to_baseline - face.strikethroughPosition()); - // The calculation for icon height in the nerd fonts patcher - // is two thirds cap height to one third line height, but we - // use an opinionated default of 1.2 * cap height instead. - // - // Doing this prevents fonts with very large line heights - // from having excessively oversized icons, and allows fonts - // with very small line heights to still have roomy icons. - // - // We do cap it at `cell_height` though for obvious reasons. - const icon_height = @min(cell_height, cap_height * 1.2); + // Same heuristic as the font_patcher script + const icon_height = (2 * cap_height + face_height) / 3; var result: Metrics = .{ .cell_width = @intFromFloat(cell_width), @@ -260,7 +266,10 @@ pub fn calc(face: FaceMetrics) Metrics { .overline_thickness = @intFromFloat(underline_thickness), .box_thickness = @intFromFloat(underline_thickness), .cursor_height = @intFromFloat(cell_height), - .icon_height = @intFromFloat(icon_height), + .icon_height = icon_height, + .face_width = face_width, + .face_height = face_height, + .face_y = face_y, }; // Ensure all metrics are within their allowable range. @@ -286,11 +295,6 @@ pub fn apply(self: *Metrics, mods: ModifierSet) void { const new = @max(entry.value_ptr.apply(original), 1); if (new == original) continue; - // Preserve the original cell width if not set. - if (self.original_cell_width == null) { - self.original_cell_width = self.cell_width; - } - // Set the new value @field(self, @tagName(tag)) = new; @@ -307,6 +311,7 @@ pub fn apply(self: *Metrics, mods: ModifierSet) void { const diff = new - original; const diff_bottom = diff / 2; const diff_top = diff - diff_bottom; + self.face_y += @floatFromInt(diff_bottom); self.cell_baseline +|= diff_bottom; self.underline_position +|= diff_top; self.strikethrough_position +|= diff_top; @@ -315,6 +320,7 @@ pub fn apply(self: *Metrics, mods: ModifierSet) void { const diff = original - new; const diff_bottom = diff / 2; const diff_top = diff - diff_bottom; + self.face_y -= @floatFromInt(diff_bottom); self.cell_baseline -|= diff_bottom; self.underline_position -|= diff_top; self.strikethrough_position -|= diff_top; @@ -417,25 +423,35 @@ pub const Modifier = union(enum) { /// Apply a modifier to a numeric value. pub fn apply(self: Modifier, v: anytype) @TypeOf(v) { const T = @TypeOf(v); - const signed = @typeInfo(T).int.signedness == .signed; - return switch (self) { - .percent => |p| percent: { - const p_clamped: f64 = @max(0, p); - const v_f64: f64 = @floatFromInt(v); - const applied_f64: f64 = @round(v_f64 * p_clamped); - const applied_T: T = @intFromFloat(applied_f64); - break :percent applied_T; - }, + const Tinfo = @typeInfo(T); + return switch (comptime Tinfo) { + .int, .comptime_int => switch (self) { + .percent => |p| percent: { + const p_clamped: f64 = @max(0, p); + const v_f64: f64 = @floatFromInt(v); + const applied_f64: f64 = @round(v_f64 * p_clamped); + const applied_T: T = @intFromFloat(applied_f64); + break :percent applied_T; + }, - .absolute => |abs| absolute: { - const v_i64: i64 = @intCast(v); - const abs_i64: i64 = @intCast(abs); - const applied_i64: i64 = v_i64 +| abs_i64; - const clamped_i64: i64 = if (signed) applied_i64 else @max(0, applied_i64); - const applied_T: T = std.math.cast(T, clamped_i64) orelse - std.math.maxInt(T) * @as(T, @intCast(std.math.sign(clamped_i64))); - break :absolute applied_T; + .absolute => |abs| absolute: { + const v_i64: i64 = @intCast(v); + const abs_i64: i64 = @intCast(abs); + const applied_i64: i64 = v_i64 +| abs_i64; + const clamped_i64: i64 = if (Tinfo.int.signedness == .signed) + applied_i64 + else + @max(0, applied_i64); + const applied_T: T = std.math.cast(T, clamped_i64) orelse + std.math.maxInt(T) * @as(T, @intCast(std.math.sign(clamped_i64))); + break :absolute applied_T; + }, }, + .float, .comptime_float => return switch (self) { + .percent => |p| v * @max(0, p), + .absolute => |abs| v + @as(T, @floatFromInt(abs)), + }, + else => {}, }; } @@ -481,7 +497,7 @@ pub const Key = key: { var enumFields: [field_infos.len]std.builtin.Type.EnumField = undefined; var count: usize = 0; for (field_infos, 0..) |field, i| { - if (field.type != u32 and field.type != i32) continue; + if (field.type != u32 and field.type != i32 and field.type != f64) continue; enumFields[i] = .{ .name = field.name, .value = i }; count += 1; } @@ -512,7 +528,10 @@ fn init() Metrics { .overline_thickness = 0, .box_thickness = 0, .cursor_height = 0, - .icon_height = 0, + .icon_height = 0.0, + .face_width = 0.0, + .face_height = 0.0, + .face_y = 0.0, }; } @@ -542,6 +561,7 @@ test "Metrics: adjust cell height smaller" { try set.put(alloc, .cell_height, .{ .percent = 0.75 }); var m: Metrics = init(); + m.face_y = 0.33; m.cell_baseline = 50; m.underline_position = 55; m.strikethrough_position = 30; @@ -549,6 +569,7 @@ test "Metrics: adjust cell height smaller" { m.cell_height = 100; m.cursor_height = 100; m.apply(set); + try testing.expectEqual(-11.67, m.face_y); try testing.expectEqual(@as(u32, 75), m.cell_height); try testing.expectEqual(@as(u32, 38), m.cell_baseline); try testing.expectEqual(@as(u32, 42), m.underline_position); @@ -570,6 +591,7 @@ test "Metrics: adjust cell height larger" { try set.put(alloc, .cell_height, .{ .percent = 1.75 }); var m: Metrics = init(); + m.face_y = 0.33; m.cell_baseline = 50; m.underline_position = 55; m.strikethrough_position = 30; @@ -577,6 +599,7 @@ test "Metrics: adjust cell height larger" { m.cell_height = 100; m.cursor_height = 100; m.apply(set); + try testing.expectEqual(37.33, m.face_y); try testing.expectEqual(@as(u32, 175), m.cell_height); try testing.expectEqual(@as(u32, 87), m.cell_baseline); try testing.expectEqual(@as(u32, 93), m.underline_position); diff --git a/src/font/SharedGrid.zig b/src/font/SharedGrid.zig index e79fd117f..3fd9cf204 100644 --- a/src/font/SharedGrid.zig +++ b/src/font/SharedGrid.zig @@ -270,11 +270,9 @@ pub fn renderGlyph( // Always use these constraints for emoji. if (p == .emoji) { render_opts.constraint = .{ - // Make the emoji as wide as possible, scaling proportionally, - // but then scale it down as necessary if its new size exceeds - // the cell height. - .size_horizontal = .cover, - .size_vertical = .fit, + // Scale emoji to be as large as possible + // while preserving their aspect ratio. + .size = .cover, // Center the emoji in its cells. .align_horizontal = .center, diff --git a/src/font/face.zig b/src/font/face.zig index 9da3c30f6..0f882a77f 100644 --- a/src/font/face.zig +++ b/src/font/face.zig @@ -136,10 +136,8 @@ pub const RenderOptions = struct { /// Don't constrain the glyph in any way. pub const none: Constraint = .{}; - /// Vertical sizing rule. - size_vertical: Size = .none, - /// Horizontal sizing rule. - size_horizontal: Size = .none, + /// Sizing rule. + size: Size = .none, /// Vertical alignment rule. align_vertical: Align = .none, @@ -155,42 +153,40 @@ pub const RenderOptions = struct { /// Bottom padding when resizing. pad_bottom: f64 = 0.0, - // This acts as a multiple of the provided width when applying - // constraints, so if this is 1.6 for example, then a width of - // 10 would be treated as though it were 16. - group_width: f64 = 1.0, - // This acts as a multiple of the provided height when applying - // constraints, so if this is 1.6 for example, then a height of - // 10 would be treated as though it were 16. - group_height: f64 = 1.0, - // This is an x offset for the actual width within the group width. - // If this is 0.5 then the glyph will be offset so that its left - // edge sits at the halfway point of the group width. - group_x: f64 = 0.0, - // This is a y offset for the actual height within the group height. - // If this is 0.5 then the glyph will be offset so that its bottom - // edge sits at the halfway point of the group height. - group_y: f64 = 0.0, + // Size and bearings of the glyph relative + // to the bounding box of its scale group. + relative_width: f64 = 1.0, + relative_height: f64 = 1.0, + relative_x: f64 = 0.0, + relative_y: f64 = 0.0, - /// Maximum ratio of width to height when resizing. + /// Maximum aspect ratio (width/height) to allow when stretching. max_xy_ratio: ?f64 = null, /// Maximum number of cells horizontally to use. max_constraint_width: u2 = 2, - /// What to use as the height metric when constraining the glyph. + /// What to use as the height metric when constraining the glyph and + /// the constraint width is 1, height: Height = .cell, pub const Size = enum { /// Don't change the size of this glyph. none, - /// Move the glyph and optionally scale it down - /// proportionally to fit within the given axis. + /// Scale the glyph down if needed to fit within the bounds, + /// preserving aspect ratio. fit, - /// Move and resize the glyph proportionally to - /// cover the given axis. + /// Scale the glyph up or down to exactly match the bounds, + /// preserving aspect ratio. cover, - /// Same as `cover` but not proportional. + /// Scale the glyph down if needed to fit within the bounds, + /// preserving aspect ratio. If the glyph doesn't cover a + /// single cell, scale up. If the glyph exceeds a single + /// cell but is within the bounds, do nothing. + /// (Nerd Font specific rule.) + fit_cover1, + /// Stretch the glyph to exactly fit the bounds in both + /// directions, disregarding aspect ratio. stretch, }; @@ -205,12 +201,18 @@ pub const RenderOptions = struct { end, /// Move the glyph so that it is centered on this axis. center, + /// Move the glyph so that it is centered on this axis, + /// but always with respect to the first cell even for + /// multi-cell constraints. (Nerd Font specific rule.) + center1, }; pub const Height = enum { - /// Use the full height of the cell for constraining this glyph. + /// Always use the full height of the cell for constraining this glyph. cell, - /// Use the "icon height" from the grid metrics as the height. + /// When the constraint width is 1, use the "icon height" from the grid + /// metrics as the height. (When the constraint width is >1, the + /// constraint height is always the full cell height.) icon, }; @@ -226,9 +228,8 @@ pub const RenderOptions = struct { /// because it neither sizes nor positions the glyph, then this /// returns false. pub inline fn doesAnything(self: Constraint) bool { - return self.size_horizontal != .none or + return self.size != .none or self.align_horizontal != .none or - self.size_vertical != .none or self.align_vertical != .none; } @@ -241,156 +242,202 @@ pub const RenderOptions = struct { /// Number of cells horizontally available for this glyph. constraint_width: u2, ) GlyphSize { - var g = glyph; + if (!self.doesAnything()) return glyph; - const available_width: f64 = @floatFromInt( - metrics.cell_width * @min( - self.max_constraint_width, - constraint_width, - ), - ); - const available_height: f64 = @floatFromInt(switch (self.height) { - .cell => metrics.cell_height, - .icon => metrics.icon_height, - }); + // For extra wide font faces, never stretch glyphs across two cells. + // This mirrors font_patcher. + const min_constraint_width: u2 = if ((self.size == .stretch) and (metrics.face_width > 0.9 * metrics.face_height)) + 1 + else + @min(self.max_constraint_width, constraint_width); - const w = available_width - - self.pad_left * available_width - - self.pad_right * available_width; - const h = available_height - - self.pad_top * available_height - - self.pad_bottom * available_height; - - // Subtract padding from the bearings so that our - // alignment and sizing code works correctly. We - // re-add before returning. - g.x -= self.pad_left * available_width; - g.y -= self.pad_bottom * available_height; - - // Multiply by group width and height for better sizing. - g.width *= self.group_width; - g.height *= self.group_height; - - switch (self.size_horizontal) { - .none => {}, - .fit => if (g.width > w) { - const orig_height = g.height; - // Adjust our height and width to proportionally - // scale them to fit the glyph to the cell width. - g.height *= w / g.width; - g.width = w; - // Set our x to 0 since anything else would mean - // the glyph extends outside of the cell width. - g.x = 0; - // Compensate our y to keep things vertically - // centered as they're scaled down. - g.y += (orig_height - g.height) / 2; - } else if (g.width + g.x > w) { - // If the width of the glyph can fit in the cell but - // is currently outside due to the left bearing, then - // we reduce the left bearing just enough to fit it - // back in the cell. - g.x = w - g.width; - } else if (g.x < 0) { - g.x = 0; - }, - .cover => { - const orig_height = g.height; - - g.height *= w / g.width; - g.width = w; - - g.x = 0; - - g.y += (orig_height - g.height) / 2; - }, - .stretch => { - g.width = w; - g.x = 0; - }, - } - - switch (self.size_vertical) { - .none => {}, - .fit => if (g.height > h) { - const orig_width = g.width; - // Adjust our height and width to proportionally - // scale them to fit the glyph to the cell height. - g.width *= h / g.height; - g.height = h; - // Set our y to 0 since anything else would mean - // the glyph extends outside of the cell height. - g.y = 0; - // Compensate our x to keep things horizontally - // centered as they're scaled down. - g.x += (orig_width - g.width) / 2; - } else if (g.height + g.y > h) { - // If the height of the glyph can fit in the cell but - // is currently outside due to the bottom bearing, then - // we reduce the bottom bearing just enough to fit it - // back in the cell. - g.y = h - g.height; - } else if (g.y < 0) { - g.y = 0; - }, - .cover => { - const orig_width = g.width; - - g.width *= h / g.height; - g.height = h; - - g.y = 0; - - g.x += (orig_width - g.width) / 2; - }, - .stretch => { - g.height = h; - g.y = 0; - }, - } - - // Add group-relative position - g.x += self.group_x * g.width; - g.y += self.group_y * g.height; - - // Divide group width and height back out before we align. - g.width /= self.group_width; - g.height /= self.group_height; - - if (self.max_xy_ratio) |ratio| if (g.width > g.height * ratio) { - const orig_width = g.width; - g.width = g.height * ratio; - g.x += (orig_width - g.width) / 2; + // The bounding box for the glyph's scale group. + // Scaling and alignment rules are calculated for + // this box and then applied to the glyph. + var group: GlyphSize = group: { + const group_width = glyph.width / self.relative_width; + const group_height = glyph.height / self.relative_height; + break :group .{ + .width = group_width, + .height = group_height, + .x = glyph.x - (group_width * self.relative_x), + .y = glyph.y - (group_height * self.relative_y), + }; }; - switch (self.align_horizontal) { - .none => {}, - .start => g.x = 0, - .end => g.x = w - g.width, - .center => g.x = (w - g.width) / 2, + // The new, constrained glyph size + var constrained_glyph = glyph; + + // Apply prescribed scaling + const width_factor, const height_factor = self.scale_factors(group, metrics, min_constraint_width); + constrained_glyph.width *= width_factor; + constrained_glyph.x *= width_factor; + constrained_glyph.height *= height_factor; + constrained_glyph.y *= height_factor; + + // NOTE: font_patcher jumps through a lot of hoops at this + // point to ensure that the glyph remains within the target + // bounding box after rounding to font definition units. + // This is irrelevant here as we're not rounding, we're + // staying in f64 and heading straight to rendering. + + // Align vertically + if (self.align_vertical != .none) { + // Vertically scale group bounding box. + group.height *= height_factor; + group.y *= height_factor; + + // Calculate offset and shift the glyph + constrained_glyph.y += self.offset_vertical(group, metrics); } - switch (self.align_vertical) { - .none => {}, - .start => g.y = 0, - .end => g.y = h - g.height, - .center => g.y = (h - g.height) / 2, + // Align horizontally + if (self.align_horizontal != .none) { + // Horizontally scale group bounding box. + group.width *= width_factor; + group.x *= width_factor; + + // Calculate offset and shift the glyph + constrained_glyph.x += self.offset_horizontal(group, metrics, min_constraint_width); } - // Re-add our padding before returning. - g.x += self.pad_left * available_width; - g.y += self.pad_bottom * available_height; + return constrained_glyph; + } - // If the available height is less than the cell height, we - // add half of the difference to center it in the full height. - // - // If necessary, in the future, we can adjust this to account - // for alignment, but that isn't necessary with any of the nf - // icons afaict. - const cell_height: f64 = @floatFromInt(metrics.cell_height); - g.y += (cell_height - available_height) / 2; + /// Return width and height scaling factors for this scaling group. + fn scale_factors( + self: Constraint, + group: GlyphSize, + metrics: Metrics, + min_constraint_width: u2, + ) struct { f64, f64 } { + if (self.size == .none) { + return .{ 1.0, 1.0 }; + } - return g; + const multi_cell = (min_constraint_width > 1); + + const pad_width_factor = @as(f64, @floatFromInt(min_constraint_width)) - (self.pad_left + self.pad_right); + const pad_height_factor = 1 - (self.pad_bottom + self.pad_top); + + const target_width = pad_width_factor * metrics.face_width; + const target_height = pad_height_factor * switch (self.height) { + .cell => metrics.face_height, + // icon_height only applies with single-cell constraints. + // This mirrors font_patcher. + .icon => if (multi_cell) + metrics.face_height + else + metrics.icon_height, + }; + + var width_factor = target_width / group.width; + var height_factor = target_height / group.height; + + switch (self.size) { + .none => unreachable, + .fit => { + // Scale down to fit if needed + height_factor = @min(1, width_factor, height_factor); + width_factor = height_factor; + }, + .cover => { + // Scale to cover + height_factor = @min(width_factor, height_factor); + width_factor = height_factor; + }, + .fit_cover1 => { + // Scale down to fit or up to cover at least one cell + // NOTE: This is similar to font_patcher's "pa" mode, + // however, font_patcher will only do the upscaling + // part if the constraint width is 1, resulting in + // some icons becoming smaller when the constraint + // width increases. You'd see icons shrinking when + // opening up a space after them. This makes no + // sense, so we've fixed the rule such that these + // icons are scaled to the same size for multi-cell + // constraints as they would be for single-cell. + height_factor = @min(width_factor, height_factor); + if (multi_cell and (height_factor > 1)) { + // Call back into this function with + // constraint width 1 to get single-cell scale + // factors. We use the height factor as width + // could have been modified by max_xy_ratio. + _, const single_height_factor = self.scale_factors(group, metrics, 1); + height_factor = @max(1, single_height_factor); + } + width_factor = height_factor; + }, + .stretch => {}, + } + + // Reduce aspect ratio if required + if (self.max_xy_ratio) |ratio| { + if (group.width * width_factor > group.height * height_factor * ratio) { + width_factor = group.height * height_factor * ratio / group.width; + } + } + + return .{ width_factor, height_factor }; + } + + /// Return vertical offset needed to align this group + fn offset_vertical( + self: Constraint, + group: GlyphSize, + metrics: Metrics, + ) f64 { + // We use face_height and offset by face_y, rather than + // using cell_height directly, to account for the asymmetry + // of the pixel cell around the face (a consequence of + // aligning the baseline with a pixel boundary rather than + // vertically centering the face). + const new_group_y = metrics.face_y + switch (self.align_vertical) { + .none => return 0.0, + .start => self.pad_bottom * metrics.face_height, + .end => end: { + const pad_top_dy = self.pad_top * metrics.face_height; + break :end metrics.face_height - pad_top_dy - group.height; + }, + .center, .center1 => (metrics.face_height - group.height) / 2, + }; + return new_group_y - group.y; + } + + /// Return horizontal offset needed to align this group + fn offset_horizontal( + self: Constraint, + group: GlyphSize, + metrics: Metrics, + min_constraint_width: u2, + ) f64 { + // For multi-cell constraints, we align relative to the span + // from the left edge of the first face cell to the right + // edge of the last face cell as they sit within the rounded + // and adjusted pixel cell (centered if narrower than the + // pixel cell, left-aligned if wider). + const face_x, const full_face_span = facecalcs: { + const cell_width: f64 = @floatFromInt(metrics.cell_width); + const full_width: f64 = @floatFromInt(min_constraint_width * metrics.cell_width); + const cell_margin = cell_width - metrics.face_width; + break :facecalcs .{ @max(0, cell_margin / 2), full_width - cell_margin }; + }; + const pad_left_x = self.pad_left * metrics.face_width; + const new_group_x = face_x + switch (self.align_horizontal) { + .none => return 0.0, + .start => pad_left_x, + .end => end: { + const pad_right_dx = self.pad_right * metrics.face_width; + break :end @max(pad_left_x, full_face_span - pad_right_dx - group.width); + }, + .center => @max(pad_left_x, (full_face_span - group.width) / 2), + // NOTE: .center1 implements the font_patcher rule of centering + // in the first cell even for multi-cell constraints. Since glyphs + // are not allowed to protrude to the left, this results in the + // left-alignment like .start when the glyph is wider than a cell. + .center1 => @max(pad_left_x, (metrics.face_width - group.width) / 2), + }; + return new_group_x - group.x; } }; }; diff --git a/src/font/face/coretext.zig b/src/font/face/coretext.zig index cb9993cbf..8c9611c04 100644 --- a/src/font/face/coretext.zig +++ b/src/font/face/coretext.zig @@ -388,19 +388,16 @@ pub const Face = struct { y = @round(y); } - // If the cell width was adjusted wider, we re-center all glyphs - // in the new width, so that they aren't weirdly off to the left. - if (metrics.original_cell_width) |original| recenter: { - // We don't do this if the constraint has a horizontal alignment, - // since in that case the position was already calculated with the - // new cell width in mind. - if (opts.constraint.align_horizontal != .none) break :recenter; - - // If the original width was wider then we don't do anything. - if (original >= metrics.cell_width) break :recenter; - + // We center all glyphs within the pixel-rounded and adjusted + // cell width if it's larger than the face width, so that they + // aren't weirdly off to the left. + // + // We don't do this if the constraint has a horizontal alignment, + // since in that case the position was already calculated with the + // new cell width in mind. + if ((opts.constraint.align_horizontal == .none) and (metrics.face_width < cell_width)) { // We add half the difference to re-center. - x += (cell_width - @as(f64, @floatFromInt(original))) / 2; + x += (cell_width - metrics.face_width) / 2; } // Our whole-pixel bearings for the final glyph. diff --git a/src/font/face/freetype.zig b/src/font/face/freetype.zig index 82cf107c8..3094d8076 100644 --- a/src/font/face/freetype.zig +++ b/src/font/face/freetype.zig @@ -498,17 +498,14 @@ pub const Face = struct { y = @round(y); } - // If the cell width was adjusted wider, we re-center all glyphs - // in the new width, so that they aren't weirdly off to the left. - if (metrics.original_cell_width) |original| recenter: { - // We don't do this if the constraint has a horizontal alignment, - // since in that case the position was already calculated with the - // new cell width in mind. - if (opts.constraint.align_horizontal != .none) break :recenter; - - // If the original width was wider then we don't do anything. - if (original >= metrics.cell_width) break :recenter; - + // We center all glyphs within the pixel-rounded and adjusted + // cell width if it's larger than the face width, so that they + // aren't weirdly off to the left. + // + // We don't do this if the constraint has a horizontal alignment, + // since in that case the position was already calculated with the + // new cell width in mind. + if ((opts.constraint.align_horizontal == .none) and (metrics.face_width < cell_width)) { // We add half the difference to re-center. // // NOTE: We round this to a whole-pixel amount because under @@ -516,7 +513,7 @@ pub const Face = struct { // the case under CoreText. If we move the outlines by // a non-whole-pixel amount, it completely ruins the // hinting. - x += @round((cell_width - @as(f64, @floatFromInt(original))) / 2); + x += @round((cell_width - metrics.face_width) / 2); } // Now we can render the glyph. @@ -1211,25 +1208,31 @@ test "color emoji" { alloc, &atlas, ft_font.glyphIndex('🥸').?, - .{ .grid_metrics = .{ - .cell_width = 13, - .cell_height = 24, - .cell_baseline = 0, - .underline_position = 0, - .underline_thickness = 0, - .strikethrough_position = 0, - .strikethrough_thickness = 0, - .overline_position = 0, - .overline_thickness = 0, - .box_thickness = 0, - .cursor_height = 0, - .icon_height = 0, - }, .constraint_width = 2, .constraint = .{ - .size_horizontal = .cover, - .size_vertical = .cover, - .align_horizontal = .center, - .align_vertical = .center, - } }, + .{ + .grid_metrics = .{ + .cell_width = 13, + .cell_height = 24, + .cell_baseline = 0, + .underline_position = 0, + .underline_thickness = 0, + .strikethrough_position = 0, + .strikethrough_thickness = 0, + .overline_position = 0, + .overline_thickness = 0, + .box_thickness = 0, + .cursor_height = 0, + .icon_height = 0, + .face_width = 13, + .face_height = 24, + .face_y = 0, + }, + .constraint_width = 2, + .constraint = .{ + .size = .fit, + .align_horizontal = .center, + .align_vertical = .center, + }, + }, ); try testing.expectEqual(@as(u32, 24), glyph.height); } diff --git a/src/font/nerd_font_attributes.zig b/src/font/nerd_font_attributes.zig index 11902d310..04088b1aa 100644 --- a/src/font/nerd_font_attributes.zig +++ b/src/font/nerd_font_attributes.zig @@ -6,16 +6,15 @@ const Constraint = @import("face.zig").RenderOptions.Constraint; -/// Get the a constraints for the provided codepoint. +/// Get the constraints for the provided codepoint. pub fn getConstraint(cp: u21) ?Constraint { return switch (cp) { 0x2500...0x259f, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, - .align_horizontal = .center, - .align_vertical = .center, + .align_horizontal = .center1, + .align_vertical = .center1, .pad_left = -0.02, .pad_right = -0.02, .pad_top = -0.01, @@ -23,12 +22,11 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0x2630, => .{ - .size_horizontal = .cover, - .size_vertical = .fit, + .size = .cover, .height = .icon, .max_constraint_width = 1, - .align_horizontal = .center, - .align_vertical = .center, + .align_horizontal = .center1, + .align_vertical = .center1, .pad_left = 0.1, .pad_right = 0.1, .pad_top = 0.1, @@ -36,49 +34,45 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0x276c...0x276d, => .{ - .size_horizontal = .cover, - .size_vertical = .fit, + .size = .cover, .max_constraint_width = 1, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.3999999999999999, - .group_height = 1.1222570532915361, - .group_x = 0.1428571428571428, - .group_y = 0.0349162011173184, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7142857142857143, + .relative_height = 0.8910614525139665, + .relative_x = 0.1428571428571428, + .relative_y = 0.0349162011173184, .pad_top = 0.15, .pad_bottom = 0.15, }, 0x276e...0x276f, => .{ - .size_horizontal = .cover, - .size_vertical = .fit, + .size = .cover, .max_constraint_width = 1, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0115606936416186, - .group_height = 1.1222570532915361, - .group_x = 0.0057142857142857, - .group_y = 0.0125698324022346, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9885714285714285, + .relative_height = 0.8910614525139665, + .relative_x = 0.0057142857142857, + .relative_y = 0.0125698324022346, .pad_top = 0.15, .pad_bottom = 0.15, }, 0x2770...0x2771, => .{ - .size_horizontal = .cover, - .size_vertical = .fit, + .size = .cover, .max_constraint_width = 1, - .align_horizontal = .center, - .align_vertical = .center, + .align_horizontal = .center1, + .align_vertical = .center1, .pad_top = 0.15, .pad_bottom = 0.15, }, 0xe0b0, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.06, .pad_right = -0.06, .pad_top = -0.01, @@ -87,20 +81,18 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0b1, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .max_xy_ratio = 0.7, }, 0xe0b2, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.06, .pad_right = -0.06, .pad_top = -0.01, @@ -109,20 +101,18 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0b3, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .max_xy_ratio = 0.7, }, 0xe0b4, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.06, .pad_right = -0.06, .pad_top = -0.01, @@ -131,20 +121,18 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0b5, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .max_xy_ratio = 0.5, }, 0xe0b6, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.06, .pad_right = -0.06, .pad_top = -0.01, @@ -153,21 +141,19 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0b7, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .max_xy_ratio = 0.5, }, 0xe0b8, 0xe0bc, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.05, .pad_right = -0.05, .pad_top = -0.01, @@ -176,20 +162,18 @@ pub fn getConstraint(cp: u21) ?Constraint { 0xe0b9, 0xe0bd, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, }, 0xe0ba, 0xe0be, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.05, .pad_right = -0.05, .pad_top = -0.01, @@ -198,19 +182,17 @@ pub fn getConstraint(cp: u21) ?Constraint { 0xe0bb, 0xe0bf, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, }, 0xe0c0, 0xe0c8, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.05, .pad_right = -0.05, .pad_top = -0.01, @@ -218,18 +200,16 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0c1, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, }, 0xe0c2, 0xe0ca, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.05, .pad_right = -0.05, .pad_top = -0.01, @@ -237,17 +217,15 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0c3, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, }, 0xe0c4, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = 0.03, .pad_right = 0.03, .pad_top = 0.03, @@ -256,10 +234,9 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0c5, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = 0.03, .pad_right = 0.03, .pad_top = 0.03, @@ -268,10 +245,9 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0c6, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = 0.03, .pad_right = 0.03, .pad_top = 0.03, @@ -280,10 +256,9 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0c7, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = 0.03, .pad_right = 0.03, .pad_top = 0.03, @@ -292,10 +267,9 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0cc, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.02, .pad_right = -0.02, .pad_top = -0.01, @@ -304,36 +278,32 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0cd, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .max_xy_ratio = 0.865, }, 0xe0ce, 0xe0d0...0xe0d1, => .{ - .size_horizontal = .cover, - .size_vertical = .fit, + .size = .fit_cover1, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, }, 0xe0cf, 0xe0d3, 0xe0d5, => .{ - .size_horizontal = .cover, - .size_vertical = .fit, - .align_horizontal = .center, - .align_vertical = .center, + .size = .fit_cover1, + .align_horizontal = .center1, + .align_vertical = .center1, }, 0xe0d2, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.02, .pad_right = -0.02, .pad_top = -0.01, @@ -342,11 +312,10 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0d4, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.02, .pad_right = -0.02, .pad_top = -0.01, @@ -355,11 +324,10 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0d6, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .start, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.05, .pad_right = -0.05, .pad_top = -0.01, @@ -368,11 +336,10 @@ pub fn getConstraint(cp: u21) ?Constraint { }, 0xe0d7, => .{ - .size_horizontal = .stretch, - .size_vertical = .stretch, + .size = .stretch, .max_constraint_width = 1, .align_horizontal = .end, - .align_vertical = .center, + .align_vertical = .center1, .pad_left = -0.05, .pad_right = -0.05, .pad_top = -0.01, @@ -425,640 +392,583 @@ pub fn getConstraint(cp: u21) ?Constraint { 0xf307...0xf847, 0xf0001...0xf1af0, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, + .align_horizontal = .center1, + .align_vertical = .center1, }, 0xea61, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.3310225303292895, - .group_height = 1.0762439807383628, - .group_x = 0.0846354166666667, - .group_y = 0.0708426547352722, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7513020833333334, + .relative_height = 0.9291573452647278, + .relative_x = 0.0846354166666667, + .relative_y = 0.0708426547352722, }, 0xea7d, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1912058627581612, - .group_height = 1.1426759670259987, - .group_x = 0.0917225950782998, - .group_y = 0.0416204217536071, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8394854586129754, + .relative_height = 0.8751387347391787, + .relative_x = 0.0917225950782998, + .relative_y = 0.0416204217536071, }, 0xea99, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0642857142857143, - .group_height = 2.0929152148664345, - .group_x = 0.0302013422818792, - .group_y = 0.2269700332963374, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9395973154362416, + .relative_height = 0.4778024417314096, + .relative_x = 0.0302013422818792, + .relative_y = 0.2269700332963374, }, 0xea9a, 0xeaa1, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.3032069970845481, - .group_height = 1.1731770833333333, - .group_x = 0.1526845637583893, - .group_y = 0.0754716981132075, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7673378076062640, + .relative_height = 0.8523862375138734, + .relative_x = 0.1526845637583893, + .relative_y = 0.0754716981132075, }, 0xea9b, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1640625000000000, - .group_height = 1.3134110787172011, - .group_x = 0.0721476510067114, - .group_y = 0.0871254162042175, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8590604026845637, + .relative_height = 0.7613762486126526, + .relative_x = 0.0721476510067114, + .relative_y = 0.0871254162042175, }, 0xea9c, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1640625000000000, - .group_height = 1.3201465201465201, - .group_x = 0.0721476510067114, - .group_y = 0.0832408435072142, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8590604026845637, + .relative_height = 0.7574916759156493, + .relative_x = 0.0721476510067114, + .relative_y = 0.0832408435072142, }, 0xea9d, 0xeaa0, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 2.4493150684931506, - .group_height = 1.9693989071038251, - .group_x = 0.2863534675615212, - .group_y = 0.2763596004439512, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.4082774049217002, + .relative_height = 0.5077691453940066, + .relative_x = 0.2863534675615212, + .relative_y = 0.2763596004439512, }, 0xea9e...0xea9f, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.9540983606557376, - .group_height = 2.4684931506849317, - .group_x = 0.2136465324384788, - .group_y = 0.3068812430632630, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.5117449664429530, + .relative_height = 0.4051054384017758, + .relative_x = 0.2136465324384788, + .relative_y = 0.3068812430632630, }, 0xeaa2, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.2405228758169935, - .group_height = 1.0595187680461982, - .group_x = 0.0679662802950474, - .group_y = 0.0147523709167545, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8061116965226555, + .relative_height = 0.9438247156716689, + .relative_x = 0.0679662802950474, + .relative_y = 0.0147523709167545, }, 0xeab4, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0054815974941269, - .group_height = 1.8994082840236686, - .group_y = 0.2024922118380062, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9945482866043613, + .relative_height = 0.5264797507788161, + .relative_y = 0.2024922118380062, }, 0xeab5, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.8994082840236686, - .group_height = 1.0054815974941269, - .group_x = 0.2024922118380062, - .group_y = 0.0054517133956386, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.5264797507788161, + .relative_height = 0.9945482866043613, + .relative_x = 0.2024922118380062, + .relative_y = 0.0054517133956386, }, 0xeab6, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.8994082840236686, - .group_height = 1.0054815974941269, - .group_x = 0.2710280373831775, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.5264797507788161, + .relative_height = 0.9945482866043613, + .relative_x = 0.2710280373831775, }, 0xeab7, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0054815974941269, - .group_height = 1.8994082840236686, - .group_x = 0.0054517133956386, - .group_y = 0.2710280373831775, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9945482866043613, + .relative_height = 0.5264797507788161, + .relative_x = 0.0054517133956386, + .relative_y = 0.2710280373831775, }, 0xead4...0xead5, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.4144620811287478, - .group_x = 0.1483790523690773, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7069825436408977, + .relative_x = 0.1483790523690773, }, 0xead6, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_height = 1.1388535031847133, - .group_y = 0.0687919463087248, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_height = 0.8780760626398211, + .relative_y = 0.0687919463087248, }, 0xeb43, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.3631840796019901, - .group_height = 1.0003813300793167, - .group_x = 0.1991657977059437, - .group_y = 0.0003811847221163, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7335766423357665, + .relative_height = 0.9996188152778837, + .relative_x = 0.1991657977059437, + .relative_y = 0.0003811847221163, }, 0xeb6e, 0xeb71, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_height = 2.0183246073298431, - .group_y = 0.2522697795071336, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_height = 0.4954604409857328, + .relative_y = 0.2522697795071336, }, 0xeb6f, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 2.0104712041884816, - .group_x = 0.2493489583333333, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.4973958333333333, + .relative_x = 0.2493489583333333, }, 0xeb70, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 2.0104712041884816, - .group_height = 1.0039062500000000, - .group_x = 0.2493489583333333, - .group_y = 0.0038910505836576, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.4973958333333333, + .relative_height = 0.9961089494163424, + .relative_x = 0.2493489583333333, + .relative_y = 0.0038910505836576, }, 0xeb8a, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 2.8828125000000000, - .group_height = 2.9818561935339356, - .group_x = 0.2642276422764228, - .group_y = 0.3313050881410256, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.3468834688346883, + .relative_height = 0.3353615785256410, + .relative_x = 0.2642276422764228, + .relative_y = 0.3313050881410256, }, 0xeb9a, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1440626883664857, - .group_height = 1.0595187680461982, - .group_x = 0.0679662802950474, - .group_y = 0.0147523709167545, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8740779768177028, + .relative_height = 0.9438247156716689, + .relative_x = 0.0679662802950474, + .relative_y = 0.0147523709167545, }, 0xebd5, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0727069351230425, - .group_height = 1.0730882652023592, - .group_y = 0.0681102082395584, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9322210636079249, + .relative_height = 0.9318897917604415, + .relative_y = 0.0681102082395584, }, 0xebd6, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_height = 1.0003554839321263, - .group_y = 0.0003553576082064, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_height = 0.9996446423917936, + .relative_y = 0.0003553576082064, }, 0xec07, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 2.8604846818377689, - .group_height = 2.9804665603035656, - .group_x = 0.2615335565120357, - .group_y = 0.3311487268518519, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.3495911047345768, + .relative_height = 0.3355179398148149, + .relative_x = 0.2615335565120357, + .relative_y = 0.3311487268518519, }, 0xec0b, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0721073225265512, - .group_height = 1.0003813300793167, - .group_y = 0.0003811847221163, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9327424400417101, + .relative_height = 0.9996188152778837, + .relative_y = 0.0003811847221163, }, 0xec0c, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.2486979166666667, - .group_x = 0.1991657977059437, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8008342022940563, + .relative_x = 0.1991657977059437, }, 0xf019, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1253968253968254, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8885754583921015, }, 0xf030, 0xf03e, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1253968253968254, - .group_height = 1.1426844014510278, - .group_y = 0.0624338624338624, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8885754583921015, + .relative_height = 0.8751322751322751, + .relative_y = 0.0624338624338624, }, 0xf03d, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_height = 1.3328631875881523, - .group_y = 0.1248677248677249, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_height = 0.7502645502645503, + .relative_y = 0.1248677248677249, }, 0xf03f, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.8003104407193382, - .group_x = 0.0005406676069582, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.5554597570408116, + .relative_x = 0.0005406676069582, }, 0xf040, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1263939384681190, - .group_height = 1.0007255897868335, - .group_x = 0.0003164442515641, - .group_y = 0.0001959631589261, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8877888683953564, + .relative_height = 0.9992749363119733, + .relative_x = 0.0003164442515641, + .relative_y = 0.0001959631589261, }, 0xf044, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0087313432835820, - .group_height = 1.0077472527472529, - .group_y = 0.0002010014265405, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9913442331878375, + .relative_height = 0.9923123057630445, + .relative_y = 0.0002010014265405, }, 0xf04a, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1253968253968254, - .group_height = 1.3321224771947897, - .group_y = 0.1247354497354497, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8885754583921015, + .relative_height = 0.7506817256817256, + .relative_y = 0.1247354497354497, }, 0xf051, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.7994923857868019, - .group_height = 1.3321224771947897, - .group_y = 0.1247354497354497, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.5557122708039492, + .relative_height = 0.7506817256817256, + .relative_y = 0.1247354497354497, }, 0xf052, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1439802384724422, - .group_height = 1.1430071621244535, - .group_y = 0.0626172338785870, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8741409740917385, + .relative_height = 0.8748851565736010, + .relative_y = 0.0626172338785870, }, 0xf053, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 2.0025185185185186, - .group_height = 1.1416267186919362, - .group_y = 0.0620882827561120, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.4993711622401420, + .relative_height = 0.8759430588185509, + .relative_y = 0.0620882827561120, }, 0xf05a...0xf05b, 0xf0aa, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0012592592592593, - .group_height = 1.0002824582824583, - .group_y = 0.0002010014265405, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9987423244802840, + .relative_height = 0.9997176214776941, + .relative_y = 0.0002010014265405, }, 0xf071, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1253968253968254, - .group_height = 1.1426844014510278, - .group_x = 0.0004701457451810, - .group_y = 0.0624338624338624, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8885754583921015, + .relative_height = 0.8751322751322751, + .relative_x = 0.0004701457451810, + .relative_y = 0.0624338624338624, }, 0xf078, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1434320241691844, - .group_height = 2.0026841590612778, - .group_y = 0.1879786499051550, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8745600777856455, + .relative_height = 0.4993298596163721, + .relative_y = 0.1879786499051550, }, 0xf07b, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1253968253968254, - .group_height = 1.2285368802902055, - .group_y = 0.0930118110236220, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8885754583921015, + .relative_height = 0.8139763779527559, + .relative_y = 0.0930118110236220, }, 0xf081, 0xf092, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1441233373639663, - .group_height = 1.1430071621244535, - .group_y = 0.0626172338785870, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8740316426933279, + .relative_height = 0.8748851565736010, + .relative_y = 0.0626172338785870, }, 0xf08c, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.2859733978234582, - .group_height = 1.1426844014510278, - .group_y = 0.0624338624338624, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7776210625293841, + .relative_height = 0.8751322751322751, + .relative_y = 0.0624338624338624, }, 0xf09f, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.7489690176588770, - .group_x = 0.0006952841596131, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.5717654171704958, + .relative_x = 0.0006952841596131, }, 0xf0a1, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1253968253968254, - .group_height = 1.0749103295228757, - .group_y = 0.0349409448818898, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8885754583921015, + .relative_height = 0.9303101594008066, + .relative_y = 0.0349409448818898, }, 0xf0a2, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.1429529187840552, - .group_height = 1.0002824582824583, - .group_x = 0.0001253913778381, - .group_y = 0.0002010014265405, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.8749266777006549, + .relative_height = 0.9997176214776941, + .relative_x = 0.0001253913778381, + .relative_y = 0.0002010014265405, }, 0xf0a3, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0005921977940631, - .group_height = 1.0001448722153810, - .group_x = 0.0005918473033957, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9994081526966043, + .relative_height = 0.9998551487695376, + .relative_x = 0.0005918473033957, }, 0xf0a4, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0012592592592593, - .group_height = 1.3332396658348704, - .group_y = 0.1250334663306335, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9987423244802840, + .relative_height = 0.7500526916695081, + .relative_y = 0.1250334663306335, }, 0xf0ca, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0335226652102676, - .group_height = 1.2308163060897437, - .group_y = 0.0938253501046103, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9675646540335450, + .relative_height = 0.8124689241215546, + .relative_y = 0.0938253501046103, }, 0xf0d6, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_height = 1.4330042313117066, - .group_y = 0.1510826771653543, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_height = 0.6978346456692913, + .relative_y = 0.1510826771653543, }, 0xf0de, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.3984670905653893, - .group_height = 2.6619718309859155, - .group_x = 0.0004030632809351, - .group_y = 0.5708994708994709, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7150686682199350, + .relative_height = 0.3756613756613756, + .relative_x = 0.0004030632809351, + .relative_y = 0.5708994708994709, }, 0xf0e7, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.3348918927786344, - .group_height = 1.0001196386424678, - .group_x = 0.0006021702214782, - .group_y = 0.0001196243307751, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7491243338952770, + .relative_height = 0.9998803756692248, + .relative_x = 0.0006021702214782, + .relative_y = 0.0001196243307751, }, 0xf296, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0005202277820979, - .group_height = 1.0386597451628128, - .group_x = 0.0001795653226322, - .group_y = 0.0187142907131644, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9994800427141276, + .relative_height = 0.9627792014248586, + .relative_x = 0.0001795653226322, + .relative_y = 0.0187142907131644, }, 0xf2c4, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.3292088488938882, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7523272214386461, }, 0xf2c5, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0118264574212998, - .group_height = 1.1664315937940761, - .group_x = 0.0004377219006858, - .group_y = 0.0713422007255139, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9883117728988424, + .relative_height = 0.8573155985489722, + .relative_x = 0.0004377219006858, + .relative_y = 0.0713422007255139, }, 0xf2f0, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.0012592592592593, - .group_height = 1.0342088873926949, - .group_y = 0.0165984862232646, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.9987423244802840, + .relative_height = 0.9669226518842459, + .relative_y = 0.0165984862232646, }, 0xf306, => .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit_cover1, .height = .icon, - .align_horizontal = .center, - .align_vertical = .center, - .group_width = 1.3001222493887530, + .align_horizontal = .center1, + .align_vertical = .center1, + .relative_width = 0.7691584391161260, }, else => null, }; diff --git a/src/font/nerd_font_codegen.py b/src/font/nerd_font_codegen.py index a103a30ac..4965dabe4 100644 --- a/src/font/nerd_font_codegen.py +++ b/src/font/nerd_font_codegen.py @@ -50,10 +50,10 @@ class PatchSetAttributeEntry(TypedDict): stretch: str params: dict[str, float | bool] - group_x: float - group_y: float - group_width: float - group_height: float + relative_x: float + relative_y: float + relative_width: float + relative_height: float class PatchSet(TypedDict): @@ -143,7 +143,7 @@ def parse_alignment(val: str) -> str | None: return { "l": ".start", "r": ".end", - "c": ".center", + "c": ".center1", # font-patcher specific centering rule, see face.zig "": None, }.get(val, ".none") @@ -158,10 +158,10 @@ def attr_key(attr: PatchSetAttributeEntry) -> AttributeHash: float(params.get("overlap", 0.0)), float(params.get("xy-ratio", -1.0)), float(params.get("ypadding", 0.0)), - float(attr.get("group_x", 0.0)), - float(attr.get("group_y", 0.0)), - float(attr.get("group_width", 1.0)), - float(attr.get("group_height", 1.0)), + float(attr.get("relative_x", 0.0)), + float(attr.get("relative_y", 0.0)), + float(attr.get("relative_width", 1.0)), + float(attr.get("relative_height", 1.0)), ) @@ -187,10 +187,10 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry) stretch = attr.get("stretch", "") params = attr.get("params", {}) - group_x = attr.get("group_x", 0.0) - group_y = attr.get("group_y", 0.0) - group_width = attr.get("group_width", 1.0) - group_height = attr.get("group_height", 1.0) + relative_x = attr.get("relative_x", 0.0) + relative_y = attr.get("relative_y", 0.0) + relative_width = attr.get("relative_width", 1.0) + relative_height = attr.get("relative_height", 1.0) overlap = params.get("overlap", 0.0) xy_ratio = params.get("xy-ratio", -1.0) @@ -204,28 +204,30 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry) s = f"{keys}\n => .{{\n" - # These translations don't quite capture the way - # the actual patcher does scaling, but they're a - # good enough compromise. - if "xy" in stretch: - s += " .size_horizontal = .stretch,\n" - s += " .size_vertical = .stretch,\n" - elif "!" in stretch or "^" in stretch: - s += " .size_horizontal = .cover,\n" - s += " .size_vertical = .fit,\n" + # This maps the font_patcher stretch rules to a Constrain instance + # NOTE: some comments in font_patcher indicate that only x or y + # would also be a valid spec, but no icons use it, so we won't + # support it until we have to. + if "pa" in stretch: + if "!" in stretch or overlap: + s += " .size = .cover,\n" + else: + s += " .size = .fit_cover1,\n" + elif "xy" in stretch: + s += " .size = .stretch,\n" else: - s += " .size_horizontal = .fit,\n" - s += " .size_vertical = .fit,\n" + print(f"Warning: Unknown stretch rule {stretch}") - # `^` indicates that scaling should fill - # the whole cell, not just the icon height. + # `^` indicates that scaling should use the + # full cell height, not just the icon height, + # even when the constraint width is 1 if "^" not in stretch: s += " .height = .icon,\n" # There are two cases where we want to limit the constraint width to 1: # - If there's a `1` in the stretch mode string. - # - If the stretch mode is `xy` and there's not an explicit `2`. - if "1" in stretch or ("xy" in stretch and "2" not in stretch): + # - If the stretch mode is not `pa` and there's not an explicit `2`. + if "1" in stretch or ("pa" not in stretch and "2" not in stretch): s += " .max_constraint_width = 1,\n" if align is not None: @@ -233,14 +235,14 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry) if valign is not None: s += f" .align_vertical = {valign},\n" - if group_width != 1.0: - s += f" .group_width = {group_width:.16f},\n" - if group_height != 1.0: - s += f" .group_height = {group_height:.16f},\n" - if group_x != 0.0: - s += f" .group_x = {group_x:.16f},\n" - if group_y != 0.0: - s += f" .group_y = {group_y:.16f},\n" + if relative_width != 1.0: + s += f" .relative_width = {relative_width:.16f},\n" + if relative_height != 1.0: + s += f" .relative_height = {relative_height:.16f},\n" + if relative_x != 0.0: + s += f" .relative_x = {relative_x:.16f},\n" + if relative_y != 0.0: + s += f" .relative_y = {relative_y:.16f},\n" # `overlap` and `ypadding` are mutually exclusive, # this is asserted in the nerd fonts patcher itself. @@ -286,7 +288,7 @@ def generate_zig_switch_arms( yMin = math.inf xMax = -math.inf yMax = -math.inf - individual_bounds: dict[int, tuple[int, int, int ,int]] = {} + individual_bounds: dict[int, tuple[int, int, int, int]] = {} for cp in group: if cp not in cmap: continue @@ -306,10 +308,10 @@ def generate_zig_switch_arms( this_bounds = individual_bounds[cp] this_width = this_bounds[2] - this_bounds[0] this_height = this_bounds[3] - this_bounds[1] - entries[cp]["group_width"] = group_width / this_width - entries[cp]["group_height"] = group_height / this_height - entries[cp]["group_x"] = (this_bounds[0] - xMin) / group_width - entries[cp]["group_y"] = (this_bounds[1] - yMin) / group_height + entries[cp]["relative_width"] = this_width / group_width + entries[cp]["relative_height"] = this_height / group_height + entries[cp]["relative_x"] = (this_bounds[0] - xMin) / group_width + entries[cp]["relative_y"] = (this_bounds[1] - yMin) / group_height del entries[0] @@ -350,7 +352,7 @@ if __name__ == "__main__": const Constraint = @import("face.zig").RenderOptions.Constraint; -/// Get the a constraints for the provided codepoint. +/// Get the constraints for the provided codepoint. pub fn getConstraint(cp: u21) ?Constraint { return switch (cp) { """) diff --git a/src/renderer/generic.zig b/src/renderer/generic.zig index fbc8cab99..802c769a6 100644 --- a/src/renderer/generic.zig +++ b/src/renderer/generic.zig @@ -3093,8 +3093,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type { // its cell(s), we don't modify the alignment at all. .constraint = getConstraint(cp) orelse if (cellpkg.isSymbol(cp)) .{ - .size_horizontal = .fit, - .size_vertical = .fit, + .size = .fit, } else .none, .constraint_width = constraintWidth(cell_pin), },