maple-font icon indicating copy to clipboard operation
maple-font copied to clipboard

Narrow CN character width

Open subframe7536 opened this issue 1 year ago • 11 comments

Currently only supported in VSCode, have no effect in terminal and IDEA

https://github.com/subframe7536/maple-font/blob/ff02c200623d318c8c0977e7e05212114797d09a/build.py#L534-L550

subframe7536 avatar Sep 20 '24 07:09 subframe7536

Clip_2024-09-20_16-53-46

编辑:这是应该是正常的现象。 VSCode 终端似乎对所有的 CJK 字体做了等宽处理,和 Windows Terminal 一样

subframe7536 avatar Sep 20 '24 08:09 subframe7536

same problem! will also show in browser (e.g. Chrome) and notepad apps

in Notesheet App: Image

in Chrome: Image

alrcatraz avatar Jan 21 '25 15:01 alrcatraz

我认为这是为了对齐中英文宽度?

GrayArashiAI avatar Feb 03 '25 05:02 GrayArashiAI

我认为这是为了对齐中英文宽度?

并不是,有些人对于中英文对齐无感,但是对于中文字符间距过大无法接受,所以打算提供一个构建选项

subframe7536 avatar Feb 03 '25 06:02 subframe7536

我认为这是为了对齐中英文宽度?

应该是中英文字宽的不同导致的。就我所知的话,一般英文字体宽度会是600,而中文是1000,这就导致直接按照1:2排列时中文字符之间会有更大的间距。有一些字体会选择只压缩英文字符宽度,这则会导致英文字符看起来瘦瘦高高。

alrcatraz avatar Feb 03 '25 12:02 alrcatraz

  1. 对于我个人而言,中文的宽度确实有点难以接受。见图的对比。
    • 有3张图,方便的话,请指示构建在public基础上,减少中文间距的版本参数,谢谢。
  2. 对于github action的构建,我不太明白对于build.py的传参和cli指令传参。
    • 我看了workflows的文件,构建时,使用cli,那么config.json?是不是在 build.py里面读取?按道理没有cli指令,默认走config.json。

Image


Image


Image

swoiow avatar Mar 22 '25 12:03 swoiow

@swoiow

  1. 文档
  2. 需要先修改config.json文件再运行Action

subframe7536 avatar Mar 22 '25 13:03 subframe7536

"glyph_width_cn_narrow": 1000, 我看到release里面是,这个值,可实际显示,不如理想,我要缩小到800-900吗?

swoiow avatar Mar 22 '25 13:03 swoiow

目前只在VSCode的编辑器内生效,其他的像terminal或者IDEA都不行。你想要正常使用,就用 Maple Mono Normal NL,然后 IDEA 的 fallback font 设置为其他中文字体

subframe7536 avatar Mar 22 '25 14:03 subframe7536

很喜欢这个字体,如果可以的话非常期待能出一款中文窄间距的release

NoneKnowsMe avatar Mar 24 '25 06:03 NoneKnowsMe

最后,我采用了 @subframe7536 提出的fallback的方法。在一些时间上的考虑,我放弃折腾。不过,字体是支持了。

现在我的自行下载脚本,方便我初始化到每一台电脑。

import shutil
import zipfile
from pathlib import Path

import requests


# 下载函数
def download_file(url: str, dest: Path):
    print(f"Downloading from: {url}")

    # 使用流式下载,避免内存占用过大
    with requests.get(url, stream=True) as resp:
        resp.raise_for_status()
        with open(dest, "wb") as f:
            # 分块下载,逐步写入文件
            for chunk in resp.iter_content(chunk_size=3 * (1024 ** 2)):  # 每次下载8KB
                if chunk:
                    f.write(chunk)
    print(f"Saved to: {dest}")


# 解压函数
def extract_zip(zip_path: Path, extract_to: Path):
    with zipfile.ZipFile(zip_path, "r") as zip_ref:
        zip_ref.extractall(extract_to)
    print(f"Extracted to: {extract_to}")


# 筛选函数
def filter_fonts(src: Path, dst: Path, keep_keywords: list[str]):
    dst.mkdir(parents=True, exist_ok=True)
    for font in src.glob("*.ttf"):
        font_name = font.name.lower()
        if any(k in font_name for k in keep_keywords):
            dest_file = dst / font.name
            font.rename(dest_file)
            print(f"Kept: {dest_file.name}")
    print(f"Filtered fonts saved to: {dst}")


def copy_files(src: Path, dst: Path = Path("C:/Windows/Fonts")):
    for file in src.glob("*.ttf"):
        shutil.copy(file, dst)


# 处理流程
def main():
    base_dir = Path("fonts_download")
    base_dir.mkdir(exist_ok=True)
    sarasa_dir = base_dir / "sarasa_raw"
    maple_dir = base_dir / "maple_raw"

    sarasa_url_1 = "https://github.com/be5invis/Sarasa-Gothic/releases/download/v1.0.33/SarasaUi-TTF-Unhinted-1.0.33.zip"
    sarasa_url_2 = "https://github.com/be5invis/Sarasa-Gothic/releases/download/v1.0.33/SarasaMono-TTF-Unhinted-1.0.33.zip"
    # maple_url = "https://github.com/subframe7536/maple-font/releases/latest/download/MapleMonoNormalNL-TTF.zip"
    maple_url = "https://github.com/subframe7536/maple-font/releases/latest/download/MapleMonoNormalNL-NF-CN-unhinted.zip"

    # logic
    sarasa_keep = [
        "-regular", "-italic", "-light", "-lightitalic", "-bolditalic", "-bold", "-semibold", "-semibolditalic"
    ]
    sarasa_keep = [f"sc{x}" for x in sarasa_keep]
    for sarasa_url in [sarasa_url_1, sarasa_url_2]:
        sarasa_zip = base_dir / "sarasa.zip"
        download_file(sarasa_url, sarasa_zip)  # 下载
        extract_zip(sarasa_zip, sarasa_dir)  # 解压
        filter_fonts(sarasa_dir, base_dir / "sarasa_filtered", sarasa_keep)
    copy_files(base_dir / "sarasa_filtered")

    maple_keep = ["-regular", "-italic", "-light", "-medium", "-mediumitalic", "-lightitalic"]
    maple_zip = base_dir / "maple.zip"
    download_file(maple_url, maple_zip)  # 下载
    extract_zip(maple_zip, maple_dir)  # 解压
    filter_fonts(maple_dir, base_dir / "maple_filtered", maple_keep)  # 筛选
    copy_files(base_dir / "maple_filtered")


if __name__ == "__main__":
    main()

swoiow avatar Mar 27 '25 06:03 swoiow

"glyph_width_cn_narrow": 1000, 我看到release里面是,这个值,可实际显示,不如理想,我要缩小到800-900吗?

我尝试修改到800,不起作用,只是把字符向左偏移了一点,字符间隔还是一样宽

DreamNya avatar Apr 03 '25 08:04 DreamNya

@DreamNya 这一块的代码还是有问题,但是我不会改。。。1000 已经是正常的宽度了,再小就太挤了

subframe7536 avatar Apr 03 '25 08:04 subframe7536

@subframe7536 我查阅和测试glyph.coordinates.translate((delta, 0)) 为平移字型,设置--cn-narrow相当于左移100,把glyph_width=1000,这样相当于把居中对齐变为左对齐。我尝试修改为#211 中放大的做法。不修改glyph_width,也就是"glyph_width_cn_narrow": 1200还是设置为原来的宽度,然后仅缩放X轴,这样字体会变宽,且glyph.coordinates有小数,但目前符合我自己的要求,放上来给大家参考。

PS:使用过程中发现脚本会把中文标点符号也左对齐,很影响阅读,修改为缩放后居中对齐。经使用发现缩放1.1倍比较舒服(1.2倍有时候遮挡光标)

3帧分别对应github版,缩放X轴1.1倍,缩放X轴1.2倍。 Image

# 修改 self.glyph_width_cn_narrow = 1200
def change_glyph_width(font: TTFont, match_width: int, target_width: int):
    for name in font.getGlyphOrder():
        glyph = font["glyf"][name]
        width, lsb = font["hmtx"][name]
        if width != match_width or glyph.numberOfContours == 0:
            continue

        # 缩放
        scaling_factor = 1.2
        glyph.coordinates.scale((scaling_factor, 1))
        
        # 居中对齐
        xMin, yMin, xMax, yMax = ( glyph.coordinates.calcIntBounds() )
        delta = round( ( (glyph.xMax - glyph.xMin) - (xMax - xMin) ) / 2 )
        glyph.coordinates.translate((delta, 0))
        
        # 更新位置
        glyph.xMin, glyph.yMin, glyph.xMax, glyph.yMax = ( glyph.coordinates.calcIntBounds() )
        font["hmtx"][name] = (width, lsb + delta)

Verdantur avatar Apr 11 '25 04:04 Verdantur

应 @leejch 要求,删除 #417.

原内容:

问题描述 | Description

使用 V7.0 版本构建字体时,参数 --cn-narrow 没有在所有字重(weight)上成功生效,仅在部分字重有效。

When building fonts with the latest V7.0 version, the parameter --cn-narrow doesn't fully take effect across all weights, working only for some weights.

构建命令及结果 | Build Commands and Results

构建命令1 (Maple Mono Normal NF CN)

python build.py --feat zero,cv01,cv02,cv03,cv31,cv32,cv34,cv35,cv36,cv37,cv96,cv98,ss01,ss02,ss03,ss04,ss07 --normal --liga --cn-both --cn-narrow --archive
字重 (Weight) 状态 (Status)
Thin
ExtraLight
Light
Regular
Medium
SemiBold
Bold
ExtraBold

构建命令2 (Maple Mono Normal NL NF CN)

python build.py --feat zero,cv01,cv02,cv03,cv31,cv32,cv34,cv35,cv36,cv37,cv96,cv98,ss01,ss02,ss03,ss04,ss07 --normal --no-liga --cn-both --cn-narrow --archive
字重 (Weight) 状态 (Status)
Thin
ExtraLight
Light
Regular
Medium
SemiBold
Bold
ExtraBold

环境 | Environment

  • Python: Python 3.10.16 | packaged by Anaconda, Inc. | (main, Dec 11 2024, 16:19:12)

希望可以确认并修复该问题,感谢!

Would appreciate it if this issue could be investigated and resolved. Thanks!

subframe7536 avatar Apr 17 '25 12:04 subframe7536

唉,作为重度终端用户,选择一款心仪字体实际困难。

世面上成熟的开源字体,大多不考虑中文相性。600 的字母宽度让 1000 宽的汉字在终端里看起来零零散散;而主打瘦高的字体通常为 500 宽,英文看起来吃力不说,中文更是挤作一团。

此外,还有采用小号字母的方案。例如 daddytime 和 lotion,宽度介于 500 到 600 之间,风格也很可爱。但它们往往不够成熟,对连字支持不佳,抑或缺乏字重与手写体,伴随着各种小毛病。

iosevka 倒是能编译 548 字宽的版本,我一直拿它备用;那些 600 宽的字体或许也有压缩版。但我果然还是想要一款颇具风格的、精致的字体,与中文相得益彰。像是 ... maple,之类的 ... 吧 ...

58faf2e2 avatar May 10 '25 00:05 58faf2e2

@58faf2e2 有个550宽度的测试版,下个大版本会上

https://github.com/subframe7536/maple-font/releases/tag/v7.0-beta28.1

subframe7536 avatar May 10 '25 00:05 subframe7536

成了

Image

subframe7536 avatar May 12 '25 07:05 subframe7536

最后,我采用了 @subframe7536 提出的fallback的方法。在一些时间上的考虑,我放弃折腾。不过,字体是支持了。

现在我的自行下载脚本,方便我初始化到每一台电脑。

import zipfile
from pathlib import Path

import requests


# 下载函数
def download_file(url: str, dest: Path):
    print(f"Downloading from: {url}")
    resp = requests.get(url)
    resp.raise_for_status()
    with open(dest, "wb") as f:
        f.write(resp.content)
    print(f"Saved to: {dest}")


# 解压函数
def extract_zip(zip_path: Path, extract_to: Path):
    with zipfile.ZipFile(zip_path, "r") as zip_ref:
        zip_ref.extractall(extract_to)
    print(f"Extracted to: {extract_to}")


# 筛选函数
def filter_fonts(src: Path, dst: Path, keep_keywords: list[str]):
    dst.mkdir(parents=True, exist_ok=True)
    for font in src.glob("*.ttf"):
        font_name = font.name.lower()
        if any(k in font_name for k in keep_keywords):
            dest_file = dst / font.name
            font.rename(dest_file)
            print(f"Kept: {dest_file.name}")
    print(f"Filtered fonts saved to: {dst}")


# 处理流程
def main():
    base_dir = Path("fonts_download")
    #  sarasa_url = "https://github.com/be5invis/Sarasa-Gothic/releases/latest/download/Sarasa-SuperTTC-Unhinted-1.0.29.zip"
    # maple_url = "https://github.com/subframe7536/maple-font/releases/latest/download/MapleMonoNormalNL-TTF.zip"
    maple_url = "https://github.com/subframe7536/maple-font/releases/download/latest/MapleMonoNormalNL-NF.zip"

    # sarasa_zip = base_dir / "sarasa.zip"
    maple_zip = base_dir / "maple.zip"

    # sarasa_dir = base_dir / "sarasa_raw"
    maple_dir = base_dir / "maple_raw"

    # sarasa_keep = ["MonoSC-Regular", "MonoSC-Light", "MonoSC-Bold"]
    maple_keep = ["-regular", "-italic", "-bold", "-bolditalic", "-semibold", "-semibolditalic"]

    base_dir.mkdir(exist_ok=True)

    # 下载
    # download_file(sarasa_url, sarasa_zip)
    download_file(maple_url, maple_zip)

    # 解压
    # extract_zip(sarasa_zip, sarasa_dir)
    extract_zip(maple_zip, maple_dir)

    # 筛选
    # filter_fonts(sarasa_dir, base_dir / "sarasa_filtered", sarasa_keep)
    filter_fonts(maple_dir, base_dir / "maple_filtered", maple_keep)

那请问在我们自己本地化生成时能设定中文的字体大小吗?比如设定字宽或字高这样的

fengsuiyvmin avatar Jun 03 '25 07:06 fengsuiyvmin

@fengsuiyvmin 可以在 config.json 中修改 "cn.scale_factor": 1.1 或者添加命令行参数 --cn-scale-factor 1.1 实现中文字符的缩放

subframe7536 avatar Jun 03 '25 07:06 subframe7536

成了

Image

这个版本中西文宽度分别是多少呢? 好像没有等宽?

snys98 avatar Sep 06 '25 12:09 snys98

这个版本中西文宽度分别是多少呢? 好像没有等宽?

是的,中文1000,英文600

subframe7536 avatar Sep 06 '25 12:09 subframe7536

@58faf2e2 有个550宽度的测试版,下个大版本会上

https://github.com/subframe7536/maple-font/releases/tag/v7.0-beta28.1

550宽度的最新代码是哪一版呀? 有对应的tag或者分支吗? 这款550简直完美, 太需要了!!! 👍

snys98 avatar Sep 06 '25 15:09 snys98

550宽度的最新代码是哪一版呀? 有对应的tag或者分支吗? 这款550简直完美, 太需要了!!! 👍

目前就只有beta版

subframe7536 avatar Sep 06 '25 23:09 subframe7536

@subframe7536 基于最新的v7.7代码,你是如何调出中文1000,英文600(550)?从而减少中文字体的间距?我在另外的分支调了,没成功。看了代码,很多地方用*2,或者/2的方式来处理比例,有些耦合,改不动。

swoiow avatar Oct 16 '25 09:10 swoiow

@subframe7536 基于最新的v7.7代码,你是如何调出中文1000,英文600(550)?从而减少中文字体的间距?我在另外的分支调了,没成功。看了代码,很多地方用*2,或者/2的方式来处理比例,有些耦合,改不动。

--cn-narrow 也不行吗?

subframe7536 avatar Oct 16 '25 09:10 subframe7536

--cn-narrow 也不行吗?

我试试+ --cn-narrow

  • build 指令: build.py --cn --no-nf --no-liga --normal --no-hinted --ttf-only

  • json 文件:

    "use_hinted": false,
    "enable_ligature": false,
    "glyph_width_cn_narrow": 800,
    "enable": false,
    "with_nerd_font": false,
    "use_static_base_font": false,
    "scale_factor": "2.0,1.0"
    
  • build.py:

          new_target_width = font_config.glyph_width_cn_narrow
          print(
              f"!!! match_width:{match_width} "
              f"target_width:{target_width}(new: {new_target_width}) "
              f"scale_factor:{scale_factor}"
          )
          target_width = new_target_width
          change_glyph_width_or_scale(
              font=cn_font,
              match_width=match_width,
              target_width=target_width,
    

change_glyph_width_or_scale 有set值的,但是没你们调得那么窄,我怀疑我打开方式有问题

swoiow avatar Oct 16 '25 12:10 swoiow

--cn-narrow 也不行吗?

我试试+ --cn-narrow

  • build 指令: build.py --cn --no-nf --no-liga --normal --no-hinted --ttf-only

  • json 文件:

    "use_hinted": false,
    "enable_ligature": false,
    "glyph_width_cn_narrow": 800,
    "enable": false,
    "with_nerd_font": false,
    "use_static_base_font": false,
    "scale_factor": "2.0,1.0"
    
  • build.py:

          new_target_width = font_config.glyph_width_cn_narrow
          print(
              f"!!! match_width:{match_width} "
              f"target_width:{target_width}(new: {new_target_width}) "
              f"scale_factor:{scale_factor}"
          )
          target_width = new_target_width
          change_glyph_width_or_scale(
              font=cn_font,
              match_width=match_width,
              target_width=target_width,
    

change_glyph_width_or_scale 有set值的,但是没你们调得那么窄,我怀疑我打开方式有问题

glyph_width_cn_narrow 是脚本内部固定的,配置只会读取 cn.narrowscale_factor 不会修改字符的宽度

subframe7536 avatar Oct 16 '25 12:10 subframe7536

@subframe7536 我没有理解错代码的话,最后是由函数change_glyph_width_or_scale来控制字体的width/scale,对吧?

swoiow avatar Oct 23 '25 07:10 swoiow

@subframe7536 我没有理解错代码的话,最后是由函数change_glyph_width_or_scale来控制字体的width/scale,对吧?

对的,但是宽度是读取 FontConfigglyph_width_cn_narrow,目前是写死的

subframe7536 avatar Oct 23 '25 09:10 subframe7536