Handle font_patcher codepoint range overlaps

pull/8847/head
Daniel Wennberg 2025-09-22 00:59:43 -07:00 committed by Mitchell Hashimoto
parent 44951d9b1c
commit 78f1bf1807
2 changed files with 185 additions and 335 deletions

View File

@ -143,18 +143,6 @@ pub fn getConstraint(cp: u21) ?Constraint {
.align_vertical = .center1,
.max_xy_ratio = 0.5,
},
0xe0b8,
0xe0bc,
=> .{
.size = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start,
.align_vertical = .center1,
.pad_left = -0.05,
.pad_right = -0.05,
.pad_top = -0.01,
.pad_bottom = -0.01,
},
0xe0b9,
0xe0bd,
=> .{
@ -163,18 +151,6 @@ pub fn getConstraint(cp: u21) ?Constraint {
.align_horizontal = .start,
.align_vertical = .center1,
},
0xe0ba,
0xe0be,
=> .{
.size = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end,
.align_vertical = .center1,
.pad_left = -0.05,
.pad_right = -0.05,
.pad_top = -0.01,
.pad_bottom = -0.01,
},
0xe0bb,
0xe0bf,
=> .{
@ -1651,35 +1627,25 @@ pub fn getConstraint(cp: u21) ?Constraint {
0xebd7...0xec06,
0xec08...0xec0a,
0xec0d...0xec1e,
0xed00...0xefce,
0xed00...0xedff,
0xee0c...0xefce,
0xf000...0xf004,
0xf006...0xf025,
0xf028...0xf02a,
0xf02c...0xf02f,
0xf02c...0xf030,
0xf034,
0xf036...0xf03c,
0xf03f,
0xf041...0xf043,
0xf036...0xf043,
0xf045,
0xf047,
0xf053...0xf059,
0xf05c...0xf05f,
0xf053...0xf05f,
0xf062,
0xf064...0xf070,
0xf072...0xf076,
0xf079...0xf07a,
0xf07c...0xf07d,
0xf07f...0xf080,
0xf082...0xf088,
0xf08a...0xf08b,
0xf08d...0xf091,
0xf093...0xf0a0,
0xf0a6...0xf0a9,
0xf0ab...0xf0c9,
0xf0cb...0xf0d5,
0xf064...0xf076,
0xf079...0xf07d,
0xf07f...0xf088,
0xf08a...0xf0a3,
0xf0a6...0xf0d6,
0xf0db,
0xf0df...0xf0e6,
0xf0e8...0xf0ff,
0xf0df...0xf0ff,
0xf108...0xf12f,
0xf131...0xf140,
0xf142...0xf152,
@ -1689,30 +1655,9 @@ pub fn getConstraint(cp: u21) ?Constraint {
0xf179...0xf181,
0xf183...0xf220,
0xf223,
0xf22e...0xf245,
0xf247...0xf254,
0xf22e...0xf254,
0xf259,
0xf25c,
0xf25e...0xf269,
0xf26b,
0xf26e...0xf276,
0xf278...0xf27d,
0xf281...0xf286,
0xf289...0xf295,
0xf297...0xf29d,
0xf29f...0xf2a4,
0xf2a6...0xf2a7,
0xf2a9...0xf2ad,
0xf2af...0xf2b8,
0xf2ba...0xf2be,
0xf2c0...0xf2c4,
0xf2c6...0xf2c8,
0xf2ca...0xf2cb,
0xf2cd,
0xf2d2...0xf2d6,
0xf2d8...0xf2ef,
0xf2f1...0xf313,
0xf315...0xf381,
0xf25c...0xf381,
0xf400...0xf418,
0xf41a...0xf42f,
0xf431...0xf43d,
@ -2010,6 +1955,129 @@ pub fn getConstraint(cp: u21) ?Constraint {
.relative_width = 0.8008342022940563,
.relative_x = 0.1991657977059437,
},
0xe0ba,
0xe0be,
0xee00,
0xee03,
=> .{
.size = .stretch,
.max_constraint_width = 1,
.align_horizontal = .end,
.align_vertical = .center1,
.pad_left = -0.05,
.pad_right = -0.05,
.pad_top = -0.01,
.pad_bottom = -0.01,
},
0xee01,
0xee04,
=> .{
.size = .stretch,
.max_constraint_width = 1,
.align_horizontal = .center1,
.align_vertical = .center1,
.pad_left = -0.1,
.pad_right = -0.1,
.pad_top = -0.01,
.pad_bottom = -0.01,
},
0xe0b8,
0xe0bc,
0xee02,
0xee05,
=> .{
.size = .stretch,
.max_constraint_width = 1,
.align_horizontal = .start,
.align_vertical = .center1,
.pad_left = -0.05,
.pad_right = -0.05,
.pad_top = -0.01,
.pad_bottom = -0.01,
},
0xee06,
=> .{
.size = .cover,
.max_constraint_width = 1,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_width = 0.7059415911379657,
.relative_height = 0.2234524408656266,
.relative_x = 0.1470292044310171,
.relative_y = 0.7765475591343735,
.pad_left = 0.03,
.pad_right = 0.03,
.pad_top = 0.03,
.pad_bottom = 0.03,
},
0xee07,
=> .{
.size = .cover,
.max_constraint_width = 1,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_width = 0.5000000000000000,
.relative_height = 0.7498741821841973,
.relative_x = 0.5000000000000000,
.relative_y = 0.2501258178158027,
.pad_left = 0.03,
.pad_right = 0.03,
.pad_top = 0.03,
.pad_bottom = 0.03,
},
0xee08,
=> .{
.size = .cover,
.max_constraint_width = 1,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_width = 0.6299093655589124,
.relative_height = 0.8535480624056366,
.relative_x = 0.3700906344410876,
.pad_left = 0.03,
.pad_right = 0.03,
.pad_top = 0.03,
.pad_bottom = 0.03,
},
0xee09,
=> .{
.size = .cover,
.max_constraint_width = 1,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.4997483643683945,
.pad_left = 0.03,
.pad_right = 0.03,
.pad_top = 0.03,
.pad_bottom = 0.03,
},
0xee0a,
=> .{
.size = .cover,
.max_constraint_width = 1,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_width = 0.6299093655589124,
.relative_height = 0.8535480624056366,
.pad_left = 0.03,
.pad_right = 0.03,
.pad_top = 0.03,
.pad_bottom = 0.03,
},
0xee0b,
=> .{
.size = .cover,
.max_constraint_width = 1,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_width = 0.5000000000000000,
.relative_height = 0.7498741821841973,
.relative_y = 0.2501258178158027,
.pad_left = 0.03,
.pad_right = 0.03,
.pad_top = 0.03,
.pad_bottom = 0.03,
},
0xf005,
=> .{
.size = .fit_cover1,
@ -2037,26 +2105,6 @@ pub fn getConstraint(cp: u21) ?Constraint {
.relative_height = 0.9758052740827267,
.relative_y = 0.0238869355863696,
},
0xf030,
0xf03e,
0xf046,
0xf071,
0xf08c,
0xf153...0xf154,
0xf158,
0xf280,
0xf2a5,
0xf2bf,
0xf2d0,
0xf2d7,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.8751322751322751,
.relative_y = 0.0624338624338624,
},
0xf031...0xf033,
=> .{
.size = .fit_cover1,
@ -2075,25 +2123,6 @@ pub fn getConstraint(cp: u21) ?Constraint {
.relative_height = 0.9989935587761675,
.relative_y = 0.0004025764895330,
},
0xf03d,
0xf0a4...0xf0a5,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.7502645502645503,
.relative_y = 0.1248677248677249,
},
0xf040,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9992749363119733,
.relative_y = 0.0001959631589261,
},
0xf044,
=> .{
.size = .fit_cover1,
@ -2102,6 +2131,17 @@ pub fn getConstraint(cp: u21) ?Constraint {
.align_vertical = .center1,
.relative_height = 0.9925925925925926,
},
0xf046,
0xf153...0xf154,
0xf158,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.8751322751322751,
.relative_y = 0.0624338624338624,
},
0xf048,
0xf04a,
0xf04e,
@ -2159,17 +2199,6 @@ pub fn getConstraint(cp: u21) ?Constraint {
.align_vertical = .center1,
.relative_height = 0.9999748091795350,
},
0xf05a...0xf05b,
0xf0a2,
0xf0aa,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9997176214776941,
.relative_y = 0.0002010014265405,
},
0xf060...0xf061,
=> .{
.size = .fit_cover1,
@ -2206,15 +2235,6 @@ pub fn getConstraint(cp: u21) ?Constraint {
.relative_height = 0.5700483091787439,
.relative_y = 0.1437198067632850,
},
0xf07b,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.8139763779527559,
.relative_y = 0.0930118110236220,
},
0xf07e,
=> .{
.size = .fit_cover1,
@ -2224,16 +2244,6 @@ pub fn getConstraint(cp: u21) ?Constraint {
.relative_height = 0.4989429175475687,
.relative_y = 0.2505285412262157,
},
0xf081,
0xf092,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.8748851565736010,
.relative_y = 0.0626172338785870,
},
0xf089,
=> .{
.size = .fit_cover1,
@ -2243,40 +2253,14 @@ pub fn getConstraint(cp: u21) ?Constraint {
.relative_height = 0.9998488512696494,
.relative_y = 0.0001511487303507,
},
0xf0a1,
0xf0a4...0xf0a5,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9303101594008066,
.relative_y = 0.0349409448818898,
},
0xf0a3,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9998551487695376,
},
0xf0ca,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.8124689241215546,
.relative_y = 0.0938253501046103,
},
0xf0d6,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.6978346456692913,
.relative_y = 0.1510826771653543,
.relative_height = 0.7502645502645503,
.relative_y = 0.1248677248677249,
},
0xf0d7,
=> .{
@ -2336,18 +2320,8 @@ pub fn getConstraint(cp: u21) ?Constraint {
.relative_height = 0.4287439613526570,
.relative_y = 0.5712560386473430,
},
0xf0e7,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9998803756692248,
.relative_y = 0.0001196243307751,
},
0xf100...0xf101,
0xf104...0xf105,
0xf2c5,
=> .{
.size = .fit_cover1,
.height = .icon,
@ -2493,15 +2467,6 @@ pub fn getConstraint(cp: u21) ?Constraint {
.relative_height = 0.6874767744332962,
.relative_y = 0.1560043449675557,
},
0xf246,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9997816982260961,
.relative_y = 0.0002148974577418,
},
0xf255...0xf256,
0xf25a,
=> .{
@ -2537,147 +2502,6 @@ pub fn getConstraint(cp: u21) ?Constraint {
.align_vertical = .center1,
.relative_height = 0.9975006099019084,
},
0xf25d,
0xf26c,
0xf277,
0xf2b9,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9993050939633815,
.relative_y = 0.0004531995890990,
},
0xf26a,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9686385884343465,
.relative_y = 0.0157864523536165,
},
0xf26d,
0xf27e,
0xf29e,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.8745241404314460,
.relative_y = 0.0628436763550668,
},
0xf27f,
0xf288,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9693121693121693,
.relative_y = 0.0153439153439153,
},
0xf287,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.7661375661375661,
.relative_y = 0.1169312169312169,
},
0xf296,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9627792014248586,
.relative_y = 0.0187142907131644,
},
0xf2a8,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9723057045073505,
.relative_y = 0.0137673026561915,
},
0xf2ae,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.8931764276591863,
.relative_y = 0.0534391534391534,
},
0xf2c9,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9228515625000000,
.relative_y = 0.0385742187500000,
},
0xf2cc,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.8076171875000000,
.relative_y = 0.0961914062500000,
},
0xf2ce,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9722222222222222,
.relative_y = 0.0138888888888889,
},
0xf2cf,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9994939038417299,
.relative_y = 0.0005060961582701,
},
0xf2d1,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.0931216931216931,
.relative_y = 0.4534391534391534,
},
0xf2f0,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.9669226518842459,
.relative_y = 0.0165984862232646,
},
0xf314,
=> .{
.size = .fit_cover1,
.height = .icon,
.align_horizontal = .center1,
.align_vertical = .center1,
.relative_height = 0.5486681262543333,
.relative_y = 0.2256704980842912,
},
0xf419,
0xf45a,
=> .{

View File

@ -299,8 +299,11 @@ def generate_zig_switch_arms(
entries: dict[int, PatchSetAttributeEntry] = {}
for entry in patch_sets:
print(f"Info: Extracting rules from patch set '{entry['Name']}'")
patch_set_name = entry["Name"]
print(f"Info: Extracting rules from patch set '{patch_set_name}'")
attributes = entry["Attributes"]
patch_set_entries: dict[int, PatchSetAttributeEntry] = {}
# A glyph's scale rules are specified using its codepoint in
# the original font, which is sometimes different from its
@ -315,10 +318,28 @@ def generate_zig_switch_arms(
if cp_font not in cmap:
print(f"Info: Skipping missing codepoint {hex(cp_font)}")
continue
if cp_rule in attributes:
entries[cp_font] = attributes[cp_rule].copy()
elif cp_font in entries:
# Patch sets sometimes have overlapping codepoint ranges.
# Sometimes a later set is a smaller set filling in a gap
# in the range of a larger, preceding set. Sometimes it's
# the other way around. The best thing we can do is hardcode
# each case.
if patch_set_name == "Font Awesome":
# The Font Awesome range has a gap matching the
# prededing Progress Indicators range.
print(f"Info: Not overwriting existing codepoint {hex(cp_font)}")
continue
elif patch_set_name == "Octicons":
# The fourth Octicons range overlaps with the first.
print(f"Info: Overwriting existing codepoint {hex(cp_font)}")
else:
entries[cp_font] = attributes["default"].copy()
raise ValueError(
f"Unknown case of overlap for codepoint {hex(cp_font)} in patch set '{patch_set_name}'"
)
if cp_rule in attributes:
patch_set_entries[cp_font] = attributes[cp_rule].copy()
else:
patch_set_entries[cp_font] = attributes["default"].copy()
if entry["ScaleRules"] is not None:
if "ScaleGroups" not in entry["ScaleRules"]:
@ -354,28 +375,33 @@ def generate_zig_switch_arms(
cp_font = cp_rule + cp_offset
if (
cp_font not in cmap
or cp_font not in entries
or cp_font not in patch_set_entries
# Codepoints may contribute to the bounding box of multiple groups,
# but should be scaled according to the first group they are found
# in. Hence, to avoid overwriting, we need to skip codepoints that
# have already been assigned a scale group.
or "relative_height" in entries[cp_font]
or "relative_height" in patch_set_entries[cp_font]
):
continue
this_bounds = individual_bounds[cp_font]
this_height = this_bounds[3] - this_bounds[1]
entries[cp_font]["relative_height"] = this_height / group_height
entries[cp_font]["relative_y"] = (
patch_set_entries[cp_font]["relative_height"] = (
this_height / group_height
)
patch_set_entries[cp_font]["relative_y"] = (
this_bounds[1] - yMin
) / group_height
# Horizontal alignment should only be grouped if the group is monospace,
# that is, if all glyphs in the group have the same advance width.
if group_is_monospace:
this_width = this_bounds[2] - this_bounds[0]
entries[cp_font]["relative_width"] = this_width / group_width
entries[cp_font]["relative_x"] = (
patch_set_entries[cp_font]["relative_width"] = (
this_width / group_width
)
patch_set_entries[cp_font]["relative_x"] = (
this_bounds[0] - xMin
) / group_width
entries |= patch_set_entries
# Group codepoints by attribute key
grouped = defaultdict[AttributeHash, list[int]](list)