使用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函数中添加调试打印:
检查输出是否包含A-F的所有字母及对应路径。print("\n📊 完整字符映射:") for char, path in sorted(char_map.items()): print(f"{char}: {path}")
5. 临时切换颜色格式排查COLRv1问题
Chrome和Firefox对COLRv1的支持细节有差异,可临时切换到SVG_TABLE格式测试:
修复步骤:
- 修改
write_toml函数中的color_format:
若所有字母都能显示,说明COLRv1生成过程存在问题,可进一步排查SVG的颜色层结构。f.write('color_format = "svg_table"\n')
内容的提问来源于stack exchange,提问作者kman99
相关产品推荐
相关产品推荐

