You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NanoEmoji+Python生成彩色字体仅G-Z正常且跨浏览器显示异常

彩色字体生成异常:仅G-Z字母显示,浏览器表现不一致

问题描述

我用Python脚本结合nanoemoji工具生成彩色字体,但只有字母G-Z(偶尔是E-Z)能正常显示,而且Chrome和Firefox的显示效果不一致。

已确认SVG文件本身无问题——把未显示的字母(A-F,偶尔A-D)的SVG替换到正常显示字母的位置时,能正常展示,但原脚本中这些字母始终无法显示。我通过CSV文件关联字母与对应SVG路径,也尝试过添加Unicode映射文本文件,但都没解决问题。

相关脚本代码:

import os
import shutil
import pandas as pd
import subprocess

# === CONFIGURATION ===
csv_path = r"C:\pathtocsv.csv"
build_dir = "build"
output_dir = r"directory"

def parse_csv(csv_path):
    df = pd.read_csv(csv_path, header=0)
    font_name = df.iloc[0, 0].strip()
    char_map = {}
    for col in df.columns[1:]:
        char = col.strip()
        if len(char) == 1 and char.isalpha() and char.isupper():
            svg_path = df[col].iloc[0]
            if pd.notna(svg_path) and svg_path.strip():
                cleaned_path = svg_path.strip()
                if os.path.exists(cleaned_path):
                    char_map[char] = cleaned_path
                else:
                    print(f"❌ File not found for '{char}': {cleaned_path}")
    return font_name, char_map


def copy_svgs_to_build(char_map):
    os.makedirs(build_dir, exist_ok=True)
    svg_files = []
    debug_map = {}
    for char, src_path in char_map.items():
        hex_code = f"u{ord(char):04X}"
        dest_name = f"{hex_code}-{char}.svg"
        dest_path = os.path.join(build_dir, dest_name)
        shutil.copyfile(src_path, dest_path)
        svg_files.append(dest_path)
        debug_map[char] = src_path  # ✅ Log the original file path for the letter
        print(f"✅ {char} → {dest_path}")
    return svg_files, debug_map



def write_toml(font_name):
    toml_path = os.path.join(build_dir, f"{font_name}.toml")
    with open(toml_path, "w", encoding="utf-8") as f:
        f.write("[build]\n")
        f.write(f'family = "{font_name}"\n')
        f.write('output_format = "woff2"\n')            # <- Export WOFF2
        f.write('color_format = "glyf_colr_1"\n')        # <- Keep color in WOFF2
        f.write('reuse_tolerance = 0\n')
        # Do NOT add 'add_svg_table = true' for COLRv1
    return toml_path




def build_font(font_name, svg_files, toml_path, debug_map):
    output_file = os.path.join(output_dir, f"{font_name}.otf")
    glyphmap_path = r"pathtoglyphmap.txt"
    os.makedirs(output_dir, exist_ok=True)

    # Show mapping from Unicode → original CSV path
    print("\n🧩 Glyphmap Assignments from CSV:")
    with open(glyphmap_path, "r", encoding="utf-8") as f:
        for line in f:
            parts = line.strip().split()
            if len(parts) == 2:
                codepoint, _ = parts
                path = debug_map.get(codepoint.upper())
                if path:
                    print(f"🗂️  {codepoint} → {path}")
                else:
                    print(f"⚠️  {codepoint} → (No path found!)")

    # Run Nanoemoji
    cmd = [
        "nanoemoji",
        "--config_file", toml_path,
        "--glyphmap_file", glyphmap_path,
        "--output_file", output_file
    ] + svg_files

    subprocess.run(cmd, check=True)

    # Optional post-process
    maxcolor_cmd = ["maximum_color", output_file]
    subprocess.run(maxcolor_cmd, check=True)

    print(f"🎨 Post-processed with maximum_color: {output_file}")



def main():
    print("🔍 Reading CSV and preparing files...")
    font_name, char_map = parse_csv(csv_path)

    print(f"🔤 Building font: {font_name}")
    svg_files, debug_map = copy_svgs_to_build(char_map)

    toml_path = write_toml(font_name)

    print("\n🧪 Debug mapping report:")
    for char, original_path in debug_map.items():
        print(f"📄 Letter {char} uses file: {original_path}")

    print("🏗️  Starting build with nanoemoji...")
    build_font(font_name, svg_files, toml_path, debug_map)

    print("✅ Font build complete!")


if __name__ == "__main__":
    main()

问题排查与修复方案

1. 移除冲突的手动Glyphmap映射

你的脚本已经按uXXXX-Char.svg的规则命名SVG文件,nanoemoji可以自动识别这种命名的Unicode映射,无需额外指定glyphmap_file。手动指定的glyphmap可能与实际生成的SVG文件名不匹配,导致A-F的映射失效。

修复步骤:

  • 修改build_font函数中的nanoemoji命令,移除--glyphmap_file参数:
    cmd = [
        "nanoemoji",
        "--config_file", toml_path,
        "--output_file", output_file
    ] + svg_files
    
  • 删除脚本中读取glyphmap的调试代码,避免干扰。

2. 强制按字母顺序处理SVG文件

nanoemoji处理SVG的顺序可能影响字形生成,若A-F的SVG先被处理,可能因隐性冲突被覆盖。

修复步骤:

  • 在build_font函数中,添加排序代码:
    # 按字母顺序排序SVG文件,确保从A到Z处理
    svg_files.sort()
    

3. 统一SVG的viewBox属性

nanoemoji对无viewBox或viewBox不一致的SVG处理容易出问题,这也是浏览器显示差异的常见原因。

修复步骤:

  • 确保所有SVG文件都有统一的viewBox属性,例如:
    <svg viewBox="0 0 1000 1000" ...>
    

4. 调试字符映射完整性

确认A-F的字母确实被正确读取到char_map中,避免CSV解析时被过滤。

修复步骤:

  • 在main函数中添加调试打印:
    print("\n📊 完整字符映射:")
    for char, path in sorted(char_map.items()):
        print(f"{char}: {path}")
    
    检查输出是否包含A-F的所有字母及对应路径。

5. 临时切换颜色格式排查COLRv1问题

Chrome和Firefox对COLRv1的支持细节有差异,可临时切换到SVG_TABLE格式测试:

修复步骤:

  • 修改write_toml函数中的color_format:
    f.write('color_format = "svg_table"\n')
    
    若所有字母都能显示,说明COLRv1生成过程存在问题,可进一步排查SVG的颜色层结构。

内容的提问来源于stack exchange,提问作者kman99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:59:56