mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
font: add scale groups to nerd font constraints
We do this by characterizing the shared bounding boxes in a static copy of the symbols only nerd font when we're doing the codegen. This allows us to get results of our scaling that are just as good as in a patched font, since related glyphs can now be sized and positioned relative to each other.
This commit is contained in:
@ -144,6 +144,23 @@ 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,
|
||||
|
||||
/// Maximum ratio of width to height when resizing.
|
||||
max_xy_ratio: ?f64 = null,
|
||||
|
||||
@ -245,6 +262,10 @@ pub const RenderOptions = struct {
|
||||
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) {
|
||||
@ -323,6 +344,14 @@ pub const RenderOptions = struct {
|
||||
},
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
@ -34,7 +34,35 @@ pub fn getConstraint(cp: u21) Constraint {
|
||||
.pad_top = 0.1,
|
||||
.pad_bottom = 0.1,
|
||||
},
|
||||
0x276c...0x2771,
|
||||
0x276c...0x276d,
|
||||
=> .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .fit,
|
||||
.max_constraint_width = 1,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.4028056112224450,
|
||||
.group_height = 1.1222570532915361,
|
||||
.group_x = 0.1428571428571428,
|
||||
.group_y = 0.0349162011173184,
|
||||
.pad_top = 0.15,
|
||||
.pad_bottom = 0.15,
|
||||
},
|
||||
0x276e...0x276f,
|
||||
=> .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .fit,
|
||||
.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,
|
||||
.pad_top = 0.15,
|
||||
.pad_bottom = 0.15,
|
||||
},
|
||||
0x2770...0x2771,
|
||||
=> .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .fit,
|
||||
@ -357,8 +385,46 @@ pub fn getConstraint(cp: u21) Constraint {
|
||||
0x2b58,
|
||||
0xe000...0xe0a9,
|
||||
0xe4fa...0xe7ef,
|
||||
0xea60...0xec1e,
|
||||
0xed00...0xf847,
|
||||
0xea60,
|
||||
0xea62...0xea7c,
|
||||
0xea7e...0xea98,
|
||||
0xeaa3...0xeab3,
|
||||
0xeab8...0xead3,
|
||||
0xead7...0xeb42,
|
||||
0xeb44...0xeb6d,
|
||||
0xeb72...0xeb89,
|
||||
0xeb8b...0xeb99,
|
||||
0xeb9b...0xebd4,
|
||||
0xebd6,
|
||||
0xebd8...0xec06,
|
||||
0xec08...0xec0a,
|
||||
0xec0d...0xec1e,
|
||||
0xed00...0xf018,
|
||||
0xf01a...0xf02f,
|
||||
0xf031...0xf03c,
|
||||
0xf041...0xf043,
|
||||
0xf045...0xf049,
|
||||
0xf04b...0xf050,
|
||||
0xf054...0xf059,
|
||||
0xf05c...0xf070,
|
||||
0xf072...0xf077,
|
||||
0xf079...0xf07a,
|
||||
0xf07c...0xf080,
|
||||
0xf082...0xf08b,
|
||||
0xf08d...0xf091,
|
||||
0xf093...0xf09b,
|
||||
0xf09d...0xf09e,
|
||||
0xf0a0,
|
||||
0xf0a5...0xf0a9,
|
||||
0xf0ab...0xf0c9,
|
||||
0xf0cb...0xf0d5,
|
||||
0xf0d7...0xf0dd,
|
||||
0xf0df...0xf0e6,
|
||||
0xf0e8...0xf295,
|
||||
0xf297...0xf2c1,
|
||||
0xf2c6...0xf2ef,
|
||||
0xf2f1...0xf305,
|
||||
0xf307...0xf847,
|
||||
0xf0001...0xf1af0,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
@ -367,6 +433,641 @@ pub fn getConstraint(cp: u21) Constraint {
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
},
|
||||
0xea61,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.3315669947009841,
|
||||
.group_height = 1.0763840224246670,
|
||||
.group_x = 0.0847072200113701,
|
||||
.group_y = 0.0709635416666667,
|
||||
},
|
||||
0xea7d,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1913145539906103,
|
||||
.group_height = 1.1428571428571428,
|
||||
.group_x = 0.0916256157635468,
|
||||
.group_y = 0.0415039062500000,
|
||||
},
|
||||
0xea99,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0639412997903563,
|
||||
.group_height = 2.0940695296523519,
|
||||
.group_x = 0.0295566502463054,
|
||||
.group_y = 0.2270507812500000,
|
||||
},
|
||||
0xea9a,
|
||||
0xeaa1,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.3029525032092426,
|
||||
.group_height = 1.1729667812142039,
|
||||
.group_x = 0.1527093596059113,
|
||||
.group_y = 0.0751953125000000,
|
||||
},
|
||||
0xea9b,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1639908256880733,
|
||||
.group_height = 1.3128205128205128,
|
||||
.group_x = 0.0719211822660099,
|
||||
.group_y = 0.0869140625000000,
|
||||
},
|
||||
0xea9c,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1639908256880733,
|
||||
.group_height = 1.3195876288659794,
|
||||
.group_x = 0.0719211822660099,
|
||||
.group_y = 0.0830078125000000,
|
||||
},
|
||||
0xea9d,
|
||||
0xeaa0,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.4457831325301207,
|
||||
.group_height = 1.9692307692307693,
|
||||
.group_x = 0.2857142857142857,
|
||||
.group_y = 0.2763671875000000,
|
||||
},
|
||||
0xea9e...0xea9f,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.9556840077071291,
|
||||
.group_height = 2.4674698795180725,
|
||||
.group_x = 0.2137931034482759,
|
||||
.group_y = 0.3066406250000000,
|
||||
},
|
||||
0xeaa2,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.2412121212121212,
|
||||
.group_height = 1.0591799039527152,
|
||||
.group_x = 0.0683593750000000,
|
||||
.group_y = 0.0146484375000000,
|
||||
},
|
||||
0xeab4,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0049115913555993,
|
||||
.group_height = 1.8998144712430427,
|
||||
.group_y = 0.2026367187500000,
|
||||
},
|
||||
0xeab5,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.8979591836734695,
|
||||
.group_height = 1.0054000981836033,
|
||||
.group_x = 0.2023460410557185,
|
||||
.group_y = 0.0053710937500000,
|
||||
},
|
||||
0xeab6,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.8979591836734695,
|
||||
.group_height = 1.0054000981836033,
|
||||
.group_x = 0.2707722385141740,
|
||||
},
|
||||
0xeab7,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0049115913555993,
|
||||
.group_height = 1.8980537534754403,
|
||||
.group_x = 0.0048875855327468,
|
||||
.group_y = 0.2709960937500000,
|
||||
},
|
||||
0xead4...0xead5,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.4152542372881356,
|
||||
.group_x = 0.1486118671747414,
|
||||
},
|
||||
0xead6,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.1390433815350389,
|
||||
.group_y = 0.0688476562500000,
|
||||
},
|
||||
0xeb43,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.3635153129161119,
|
||||
.group_height = 1.0002360944082516,
|
||||
.group_x = 0.1992187500000000,
|
||||
.group_y = 0.0002360386808388,
|
||||
},
|
||||
0xeb6e,
|
||||
0xeb71,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 2.0197238658777121,
|
||||
.group_y = 0.2524414062500000,
|
||||
},
|
||||
0xeb6f,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.0098619329388558,
|
||||
.group_x = 0.2492639842983317,
|
||||
},
|
||||
0xeb70,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.0098619329388558,
|
||||
.group_height = 1.0039215686274510,
|
||||
.group_x = 0.2492639842983317,
|
||||
.group_y = 0.0039062500000000,
|
||||
},
|
||||
0xeb8a,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.8826979472140764,
|
||||
.group_height = 2.9804097167804766,
|
||||
.group_x = 0.2634791454730417,
|
||||
.group_y = 0.3314678485576923,
|
||||
},
|
||||
0xeb9a,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1441340782122904,
|
||||
.group_height = 1.0591799039527152,
|
||||
.group_x = 0.0683593750000000,
|
||||
.group_y = 0.0146484375000000,
|
||||
},
|
||||
0xebd5,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0723270440251573,
|
||||
.group_height = 1.0728129910948141,
|
||||
.group_y = 0.0678710937500000,
|
||||
},
|
||||
0xebd7,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.0000418544302916,
|
||||
.group_y = 0.0000418526785714,
|
||||
},
|
||||
0xec07,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.8615369874243446,
|
||||
.group_height = 2.9789458113505249,
|
||||
.group_x = 0.2609446802539727,
|
||||
.group_y = 0.3313029661016949,
|
||||
},
|
||||
0xec0b,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0722513089005237,
|
||||
.group_height = 1.0002360944082516,
|
||||
.group_y = 0.0002360386808388,
|
||||
},
|
||||
0xec0c,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.2487804878048780,
|
||||
.group_x = 0.1992187500000000,
|
||||
},
|
||||
0xf019,
|
||||
0xf08c,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004882812500000,
|
||||
},
|
||||
0xf030,
|
||||
0xf03e,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004882812500000,
|
||||
.group_height = 1.1428571428571428,
|
||||
.group_y = 0.0625000000000000,
|
||||
},
|
||||
0xf03d,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004882812500000,
|
||||
.group_height = 1.5014662756598240,
|
||||
.group_y = 0.1669921875000000,
|
||||
},
|
||||
0xf03f,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.6018762826150690,
|
||||
.group_x = 0.1876220107369448,
|
||||
},
|
||||
0xf040,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0006976906439684,
|
||||
.group_height = 1.0001808776182035,
|
||||
.group_x = 0.0006972042111134,
|
||||
.group_y = 0.0001808449074074,
|
||||
},
|
||||
0xf044,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1029147024980515,
|
||||
.group_height = 1.1024142703367676,
|
||||
.group_x = 0.0463592039005675,
|
||||
.group_y = 0.0430325010461710,
|
||||
},
|
||||
0xf04a,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004882812500000,
|
||||
.group_height = 1.3312975252838291,
|
||||
.group_y = 0.1245571402616279,
|
||||
},
|
||||
0xf051,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.6007812500000000,
|
||||
.group_height = 1.3312170271945341,
|
||||
.group_x = 0.1874084919472914,
|
||||
.group_y = 0.1245117187500000,
|
||||
},
|
||||
0xf052,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1436671384194865,
|
||||
.group_height = 1.1430165816326530,
|
||||
.group_x = 0.0624629273607646,
|
||||
.group_y = 0.0625610266424885,
|
||||
},
|
||||
0xf053,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.8765709864847797,
|
||||
.group_height = 1.0707191397207079,
|
||||
.group_x = 0.2332599943628554,
|
||||
.group_y = 0.0332682382480123,
|
||||
},
|
||||
0xf05a...0xf05b,
|
||||
0xf081,
|
||||
0xf092,
|
||||
0xf0aa,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005935142780173,
|
||||
.group_height = 1.0001395089285714,
|
||||
.group_y = 0.0000697447342726,
|
||||
},
|
||||
0xf071,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0014662756598240,
|
||||
.group_height = 1.1428571428571428,
|
||||
.group_x = 0.0004880429477794,
|
||||
.group_y = 0.0625000000000000,
|
||||
},
|
||||
0xf078,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0717654378877508,
|
||||
.group_height = 1.8757195185766613,
|
||||
.group_x = 0.0331834301604062,
|
||||
.group_y = 0.1670386385827870,
|
||||
},
|
||||
0xf07b,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.1428571428571428,
|
||||
.group_y = 0.0625000000000000,
|
||||
},
|
||||
0xf09c,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.0810546875000000,
|
||||
},
|
||||
0xf09f,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.7506617925122907,
|
||||
.group_height = 1.0810546875000000,
|
||||
.group_x = 0.2143937211981567,
|
||||
},
|
||||
0xf0a1,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0009775171065494,
|
||||
.group_x = 0.0004882812500000,
|
||||
},
|
||||
0xf0a2,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1433271023627367,
|
||||
.group_height = 1.0001395089285714,
|
||||
.group_x = 0.0624235731978609,
|
||||
.group_y = 0.0000697447342726,
|
||||
},
|
||||
0xf0a3,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005760656161586,
|
||||
.group_height = 1.0001220681837999,
|
||||
.group_x = 0.0004792774839344,
|
||||
.group_y = 0.0000610266424885,
|
||||
},
|
||||
0xf0a4,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005935142780173,
|
||||
.group_height = 1.3335193452380951,
|
||||
.group_y = 0.1250523085507044,
|
||||
},
|
||||
0xf0ca,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005935142780173,
|
||||
.group_height = 1.1922501247297521,
|
||||
.group_y = 0.0806249128190822,
|
||||
},
|
||||
0xf0d6,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.5014662756598240,
|
||||
.group_y = 0.1669921875000000,
|
||||
},
|
||||
0xf0de,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.2253421114919656,
|
||||
.group_height = 2.5216400911161729,
|
||||
.group_x = 0.0918898809523810,
|
||||
.group_y = 0.6034327009936766,
|
||||
},
|
||||
0xf0e7,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.3336843856081169,
|
||||
.group_x = 0.1247597299147187,
|
||||
},
|
||||
0xf296,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005148743038617,
|
||||
.group_height = 1.0385966606705219,
|
||||
.group_x = 0.0005146093447336,
|
||||
.group_y = 0.0186218440507742,
|
||||
},
|
||||
0xf2c2...0xf2c3,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0000770970394737,
|
||||
.group_height = 1.2864321608040201,
|
||||
.group_y = 0.1113281250000000,
|
||||
},
|
||||
0xf2c4,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0344231791600214,
|
||||
.group_x = 0.0166002826673519,
|
||||
},
|
||||
0xf2c5,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004538836055876,
|
||||
.group_height = 1.4840579710144928,
|
||||
.group_x = 0.0004536776887225,
|
||||
.group_y = 0.1630859375000000,
|
||||
},
|
||||
0xf2f0,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005935142780173,
|
||||
.group_height = 1.0334438518091393,
|
||||
.group_y = 0.0161807783512345,
|
||||
},
|
||||
0xf306,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.2427184466019416,
|
||||
.group_x = 0.0976562500000000,
|
||||
},
|
||||
else => .none,
|
||||
};
|
||||
}
|
||||
|
@ -7,11 +7,16 @@ attributes and scaling rules.
|
||||
This does include an `eval` call! This is spooky, but we trust the nerd fonts code to
|
||||
be safe and not malicious or anything.
|
||||
|
||||
This script requires Python 3.12 or greater.
|
||||
This script requires Python 3.12 or greater, requires that the `fontTools`
|
||||
python module is installed, and requires that the path to a copy of the
|
||||
SymbolsNerdFontMono font is passed as the first argument to the script.
|
||||
"""
|
||||
|
||||
import ast
|
||||
import sys
|
||||
import math
|
||||
from fontTools.ttLib import TTFont
|
||||
from fontTools.pens.boundsPen import BoundsPen
|
||||
from collections import defaultdict
|
||||
from contextlib import suppress
|
||||
from pathlib import Path
|
||||
@ -19,7 +24,18 @@ from types import SimpleNamespace
|
||||
from typing import Literal, TypedDict, cast
|
||||
|
||||
type PatchSetAttributes = dict[Literal["default"] | int, PatchSetAttributeEntry]
|
||||
type AttributeHash = tuple[str | None, str | None, str, float, float, float]
|
||||
type AttributeHash = tuple[
|
||||
str | None,
|
||||
str | None,
|
||||
str,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
]
|
||||
type ResolvedSymbol = PatchSetAttributes | PatchSetScaleRules | int | None
|
||||
|
||||
|
||||
@ -34,6 +50,11 @@ class PatchSetAttributeEntry(TypedDict):
|
||||
stretch: str
|
||||
params: dict[str, float | bool]
|
||||
|
||||
group_x: float
|
||||
group_y: float
|
||||
group_width: float
|
||||
group_height: float
|
||||
|
||||
|
||||
class PatchSet(TypedDict):
|
||||
SymStart: int
|
||||
@ -137,6 +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)),
|
||||
)
|
||||
|
||||
|
||||
@ -162,6 +187,11 @@ 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)
|
||||
|
||||
overlap = params.get("overlap", 0.0)
|
||||
xy_ratio = params.get("xy-ratio", -1.0)
|
||||
y_padding = params.get("ypadding", 0.0)
|
||||
@ -192,7 +222,6 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
|
||||
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`.
|
||||
@ -204,6 +233,15 @@ 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"
|
||||
|
||||
# `overlap` and `ypadding` are mutually exclusive,
|
||||
# this is asserted in the nerd fonts patcher itself.
|
||||
if overlap:
|
||||
@ -226,16 +264,53 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
|
||||
return s
|
||||
|
||||
|
||||
def generate_zig_switch_arms(patch_sets: list[PatchSet]) -> str:
|
||||
def generate_zig_switch_arms(
|
||||
patch_sets: list[PatchSet],
|
||||
nerd_font: TTFont,
|
||||
) -> str:
|
||||
cmap = nerd_font.getBestCmap()
|
||||
glyphs = nerd_font.getGlyphSet()
|
||||
|
||||
entries: dict[int, PatchSetAttributeEntry] = {}
|
||||
for entry in patch_sets:
|
||||
attributes = entry["Attributes"]
|
||||
|
||||
for cp in range(entry["SymStart"], entry["SymEnd"] + 1):
|
||||
entries[cp] = attributes["default"]
|
||||
entries[cp] = attributes["default"].copy()
|
||||
|
||||
entries |= {k: v for k, v in attributes.items() if isinstance(k, int)}
|
||||
|
||||
if entry["ScaleRules"] is not None and "ScaleGroups" in entry["ScaleRules"]:
|
||||
for group in entry["ScaleRules"]["ScaleGroups"]:
|
||||
xMin = math.inf
|
||||
yMin = math.inf
|
||||
xMax = -math.inf
|
||||
yMax = -math.inf
|
||||
individual_bounds: dict[int, tuple[int, int, int ,int]] = {}
|
||||
for cp in group:
|
||||
if cp not in cmap:
|
||||
continue
|
||||
glyph = glyphs[cmap[cp]]
|
||||
bounds = BoundsPen(glyphSet=glyphs)
|
||||
glyph.draw(bounds)
|
||||
individual_bounds[cp] = bounds.bounds
|
||||
xMin = min(bounds.bounds[0], xMin)
|
||||
yMin = min(bounds.bounds[1], yMin)
|
||||
xMax = max(bounds.bounds[2], xMax)
|
||||
yMax = max(bounds.bounds[3], yMax)
|
||||
group_width = xMax - xMin
|
||||
group_height = yMax - yMin
|
||||
for cp in group:
|
||||
if cp not in cmap or cp not in entries:
|
||||
continue
|
||||
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
|
||||
|
||||
del entries[0]
|
||||
|
||||
# Group codepoints by attribute key
|
||||
@ -256,6 +331,10 @@ def generate_zig_switch_arms(patch_sets: list[PatchSet]) -> str:
|
||||
if __name__ == "__main__":
|
||||
project_root = Path(__file__).resolve().parents[2]
|
||||
|
||||
nf_path = sys.argv[1]
|
||||
|
||||
nerd_font = TTFont(nf_path)
|
||||
|
||||
patcher_path = project_root / "vendor" / "nerd-fonts" / "font-patcher.py"
|
||||
source = patcher_path.read_text(encoding="utf-8")
|
||||
patch_set = extract_patch_set_values(source)
|
||||
@ -275,5 +354,5 @@ const Constraint = @import("face.zig").RenderOptions.Constraint;
|
||||
pub fn getConstraint(cp: u21) Constraint {
|
||||
return switch (cp) {
|
||||
""")
|
||||
f.write(generate_zig_switch_arms(patch_set))
|
||||
f.write(generate_zig_switch_arms(patch_set, nerd_font))
|
||||
f.write("\n else => .none,\n };\n}\n")
|
||||
|
Reference in New Issue
Block a user