diff --git a/build.py b/build.py index fad3f15..c3de841 100644 --- a/build.py +++ b/build.py @@ -28,6 +28,18 @@ build_config = { "family_name": "Maple Mono", # whether to use hinted ttf as base font "use_hinted": True, + "feature_freeze": { + "cv01": "ignore", + "cv02": "ignore", + "cv03": "ignore", + "cv04": "ignore", + "cv98": "ignore", + "cv99": "ignore", + "ss01": "ignore", + "ss02": "ignore", + "ss03": "ignore", + "ss04": "ignore", + }, # nerd font settings "nerd_font": { # whether to enable Nerd Font @@ -283,6 +295,53 @@ def add_cv98(font): lang_sys_rec.LangSys.FeatureIndex.append(feature_index) +def freeze_feature(font: TTFont): + # check feature list + feature_record = font["GSUB"].table.FeatureList.FeatureRecord + feature_dict = { + feature.FeatureTag: feature.Feature + for feature in feature_record + if feature.FeatureTag != "calt" + } + + calt_features = [ + feature.Feature for feature in feature_record if feature.FeatureTag == "calt" + ] + + # Process features + for feature_tag, status in build_config["feature_freeze"].items(): + feature = feature_dict.get(feature_tag) + if not feature or status == "ignore": + continue + + if status == "disable": + feature.LookupListIndex = [] + continue + + if feature_tag in ["ss03"]: + # Enable by moving rules into "calt" + for calt_feat in calt_features: + calt_feat.LookupListIndex.extend(feature.LookupListIndex) + else: + # Enable by replacing data in glyf and hmtx tables + glyph_dict = font["glyf"].glyphs + hmtx_dict = font["hmtx"].metrics + for index in feature.LookupListIndex: + lookup = font["GSUB"].table.LookupList.Lookup[index] + for old_key, new_key in lookup.SubTable[0].mapping.items(): + if ( + old_key in glyph_dict + and old_key in hmtx_dict + and new_key in glyph_dict + and new_key in hmtx_dict + ): + glyph_dict[old_key] = glyph_dict[new_key] + hmtx_dict[old_key] = hmtx_dict[new_key] + else: + print(f"{old_key} or {new_key} does not exist") + return + + def build_mono(f: str): _path = path.join(output_ttf, f) font = TTFont(_path) @@ -314,6 +373,8 @@ def build_mono(f: str): elif style_name1 == " ExtraLight": font["OS/2"].usWeightClass = 275 + freeze_feature(font) + font.save(_path) font.close() run(f"ftcli converter ttf2otf {_path} -out {output_otf}") diff --git a/config.json b/config.json index 606a52e..1665a08 100644 --- a/config.json +++ b/config.json @@ -2,6 +2,18 @@ "$schema": "./source/schema.json", "family_name": "Maple Mono", "use_hinted": true, + "feature_freeze": { + "cv01": "ignore", + "cv02": "ignore", + "cv03": "ignore", + "cv04": "ignore", + "cv98": "ignore", + "cv99": "ignore", + "ss01": "ignore", + "ss02": "ignore", + "ss03": "ignore", + "ss04": "ignore" + }, "nerd_font": { "enable": true, "version": "3.2.1", diff --git a/source/schema.json b/source/schema.json index 24df689..3fdd866 100644 --- a/source/schema.json +++ b/source/schema.json @@ -18,6 +18,111 @@ "description": "Whether to use hinted TTF as base font", "default": true }, + "feature_freeze": { + "type": "object", + "description": "Freeze some font features \n enable: enable font features by default \n disable: remove some font features \n ignore: skip handle target font features", + "properties": { + "cv01": { + "type": "string", + "description": "Classic '@', '$', '&', 'Q', '=>', '->'", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "cv02": { + "type": "string", + "description": "Alternative 'a' (with top alarm)", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "cv03": { + "type": "string", + "description": "Alternative 'i' (without bottom left bar)", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "cv04": { + "type": "string", + "description": "Alternative 'l' (with bottom left bar) and '1' (without bottom bar)", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "cv98": { + "type": "string", + "description": "full width '…'(ellipsis) and '—'(emdash) support for Maple Mono NF CN", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "cv99": { + "type": "string", + "description": "Traditional punctuations support for Maple Mono NF CN", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "ss01": { + "type": "string", + "description": "Non-cursive italic style", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "ss02": { + "type": "string", + "description": "Disable ligautures on equals like '==', '!=', '<='", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "ss03": { + "type": "string", + "description": "Ignore cases on all tags", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "ss04": { + "type": "string", + "description": "Disable ligatures on '__', '#__', '***'", + "enum": [ + "ignore", + "disable", + "enable" + ] + }, + "zero": { + "type": "string", + "description": "Dot style '0'", + "enum": [ + "ignore", + "disable", + "enable" + ] + } + } + }, "nerd_font": { "type": "object", "description": "Config for Nerd Font", @@ -47,7 +152,9 @@ "items": { "type": "string" }, - "default": ["--complete"], + "default": [ + "--complete" + ], "description": "Symbol Fonts settings. if is not [\"--complete\"], will use font-patcher to generate fonts. Full args: https://github.com/ryanoasis/nerd-fonts?tab=readme-ov-file#font-patcher" }, "extra_args": {