From 38354d23ab88e01ec75316af8474e0ecd5976e48 Mon Sep 17 00:00:00 2001 From: Cyano Hao Date: Tue, 12 May 2020 14:40:58 +0800 Subject: [PATCH] follow Nowar Sans changes --- LICENSE.txt | 6 +- README-Hans.md | 43 +- README-Hant.md | 41 +- README.md | 79 +- configure.py | 1440 +++++++++-------- libotd | 2 +- merge.py | 528 ++++--- opencc_t2s.py | 4030 +++++++++++++++++++++++++++++++++++++++++++++++ set-encoding.py | 21 +- 9 files changed, 5175 insertions(+), 1015 deletions(-) create mode 100644 opencc_t2s.py diff --git a/LICENSE.txt b/LICENSE.txt index de1469b..7544528 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,5 @@ -Copyright © 2018—2020 Cyano Hao and Nowar Typeface, with reserved font name “Nowar”, “有爱”, and “有愛”. +Copyright © 2018—2020 Cyano Hao and Nowar Typeface, with +Reserved Font Name “Nowar”, “Новар”, “Νοωαρ”, “有爱”, and “有愛”. Portions Copyright 2011 Google Inc. @@ -12,7 +13,8 @@ Version 1.1. This license is copied below, and is also available with a FAQ at: https://scripts.sil.org/OFL -Part of the source files, Roboto fonts, were initially released by Google under the Apache License, Version 2.0. The license can be found at: +Part of the source files, Roboto fonts, were initially released by Google +under the Apache License, Version 2.0. The license can be found at: https://www.apache.org/licenses/LICENSE-2.0 ----------------------------------------------------------- diff --git a/README-Hans.md b/README-Hans.md index 0434eef..8bd3147 100644 --- a/README-Hans.md +++ b/README-Hans.md @@ -1,6 +1,6 @@ [English](README.md) **简体中文** [繁體中文](README-Hant.md) -# 有爱新黑(《魔兽世界》字体包) +# 有爱新黑 有爱新黑是《魔兽世界》和《魔兽世界:经典怀旧服》字体包,支持所有语言。有爱新黑是 [Noto Sans](https://github.com/googlei18n/noto-fonts) 和[思源黑体](https://github.com/adobe-fonts/source-han-sans)的合并字体。 @@ -18,7 +18,7 @@ 镜像:[Gitee](https://gitee.com/nowar-fonts/Nowar-Neo-Sans) -有爱新黑有 4 种字重和 7 种地区变体,此外还有若干特性。 +有爱新黑有 4 种字重和 5 种地区变体,此外还有若干特性。 ### 字重 @@ -29,41 +29,36 @@ ### 地区变体 -CN、TW、HK、JP、KR 是 “标准变体”,支持完整的字符集,并遵循各地区的字形标准。 +Bliz 和 Neut 是 “标准变体”,遵循各地区的字形标准。 -| | 西文 | 简体中文 | 繁体中文 | 韩国语 | -| -- | ----------------- | ------------ | -------- | ------------- | -| CN | 中国大陆字形(UI)| 中国大陆字形 | 台湾字形 | 韩国字形(UI)| -| TW | 台湾字形(UI) | 中国大陆字形 | 台湾字形 | 韩国字形(UI)| -| HK | 香港字形(UI) | 中国大陆字形 | 香港字形 | 韩国字形(UI)| -| JP | 日本字形(UI) | 中国大陆字形 | 台湾字形 | 韩国字形(UI)| -| KR | 韩国字形(UI) | 中国大陆字形 | 台湾字形 | 韩国字形(UI)| +| | 西文和韩国语 | 简体中文 | 繁體中文 | 备注 | +| ---- | ----------------- | ------------ | -------- | ------------------------------- | +| Bliz | 中国大陆字形(UI)| 中国大陆字形 | 台湾字形 | 遵从《魔兽世界》默认字体设置。 | +| Neut | 传统字形(UI) | 中国大陆字形 | 台湾字形 | 未指定字形标准时,采用传统字形。| -CL 是 “传统变体”,支持完整的字符集,采用传统印刷字形(即康熙字形)。 +CL 是 “传统变体”,采用传统印刷字形(即康熙字形)。 -| | 西文 | 中文 | 韩国语 | -| --- | ------------- | -------- | ------------- | -| CL | 传统字形(UI)| 传统字形 | 传统字形(UI)| +| | 西文和韩国语 | 中文 | +| -- | ------------- | -------- | +| CL | 传统字形(UI)| 传统字形 | -GB 变体完全覆盖 GB 18030-2000 标准,移除了谚文支持,文件大小得以大幅缩减。 +PSimp、PSimpChat 是针对繁体中文的变体,把繁体字重映射为简化字字形。 -| | 西文 | 中文 | 韩国语 | -| -- | ----------------- | ------------ | ------ | -| GB | 中国大陆字形(UI)| 中国大陆字形 | 不可用 | +| | 通用字体 | 繁体中文文本、战斗、工具提示字体 | 繁体中文聊天字体 | 西文、简体中文、韩国语 | +| --------- | --------------------------| --------------------- | --------------------- | ------ | +| PSimp | 中国大陆字形(UI,重映射)| 中国大陆字形(重映射)| 中国大陆字形 | 不可用 | +| PSimpChat | 中国大陆字形(UI,重映射)| 中国大陆字形(重映射)| 中国大陆字形(重映射)| 不可用 | * 西文:英语、西班牙语(拉丁美洲)、葡萄牙语、德语、西班牙语(欧洲)、法语、意大利语、俄语。 * UI:中西文共用的标点视作西文标点;半角 CJK 标点。 +* 通用字体:`FRIZQT__` 和 `ARIALN`。某些插件硬编码了此字体。 ### 特性 | 标记 | 名称 | 简介 | | ---- | ----------- | ------------------------------------------------- | | OSF | Oldstyle | 不齐线、不等宽的旧式数字。 | -| SC | Smallcaps | 小型大写拉丁、西里尔、希腊字母。 | +| SC | Smallcaps | 小型大写拉丁字母。 | | RP | Roleplaying | `丶`(U+4E36)重映射为 `·`(U+00B7,MIDDLE DOT)。| -预编译的特性变体:`CL,OSF`、`CL,SC`、`CL,OSF,SC`、`GB,RP`。 - -### SharedMedia 字体包 - -有爱新黑也可以以插件的形式安装(**很大!**),启用之后会向 SharedMedia 注册有爱新黑字族。 +预编译的特性变体:`Bliz,OSF`、`Bliz,RP`、`Bliz,SC`。 diff --git a/README-Hant.md b/README-Hant.md index feeb087..94712b1 100644 --- a/README-Hant.md +++ b/README-Hant.md @@ -18,7 +18,7 @@ 鏡像:[Gitee](https://gitee.com/nowar-fonts/Nowar-Neo-Sans) -有 4 種字重和 7 種地區變體,此外還有若干特徵。 +有 4 種字重和 5 種地區變體,此外還有若干特徵。 ### 字重 @@ -29,41 +29,36 @@ ### 地區變體 -CN、TW、HK、JP、KR 是「標準變體」,支援完整的字元集,並遵循各地區的字形標準。 +Bliz 和 Neut 是「標準變體」,遵循各地區的字形標準。 -| | 西文 | 簡體中文 | 繁體中文 | 韓國語 | -| -- | ------------------| ------------ | -------- | ------------- | -| CN | 中國大陸字形(UI)| 中國大陸字形 | 臺灣字形 | 韓國字形(UI)| -| TW | 臺灣字形(UI) | 中國大陸字形 | 臺灣字形 | 韓國字形(UI)| -| HK | 香港字形(UI) | 中國大陸字形 | 香港字形 | 韓國字形(UI)| -| JP | 日本字形(UI) | 中國大陸字形 | 臺灣字形 | 韓國字形(UI)| -| KR | 韓國字形(UI) | 中國大陸字形 | 臺灣字形 | 韓國字形(UI)| +| | 西文和韓國語 | 簡體中文 | 繁體中文 | 備注 | +| ---- | ----------------- | ------------ | -------- | ------------------------------- | +| Bliz | 中國大陸字形(UI)| 中國大陸字形 | 臺灣字形 | 遵從《魔獸世界》預設字型設定。 | +| Neut | 傳統字形(UI) | 中國大陸字形 | 臺灣字形 | 未指定字形標準時,採用傳統字形。| -CL 是「傳統變體」,支援完整的字元集,採用傳統印刷字形(即康熙字形)。 +CL 是「傳統變體」,採用傳統印刷字形(即康熙字形)。 -| | 西文 | 中文 | 韓國語 | -| --- | ------------------------- | -------- | ------------- | -| CL | 傳統字形(UI) | 傳統字形 | 傳統字形(UI)| +| | 西文和韓國語 | 中文 | +| -- | ------------- | -------- | +| CL | 傳統字形(UI)| 傳統字形 | -GB 變體完全覆蓋 GB 18030-2000 標準,移除了諺文支援,文件大小得以大幅縮減。 +PSimp、PSimpChat 是針對繁體中文的變體,把繁體字重對映為簡化字字形。 -| | 西文 | 中文 | 韓國語 | -| -- | ----------------- | ------------ | ------ | -| GB | 中國大陸字形(UI)| 中國大陸字形 | 不適用 | +| | 通用字型 | 繁體中文文本、戰鬥、提示訊息字型 | 繁體中文聊天字型 | 西文、簡體中文、韓國語 | +| --------- | --------------------------| --------------------- | --------------------- | ------ | +| PSimp | 中國大陸字形(UI,重對映)| 中國大陸字形(重對映)| 中國大陸字形 | 不適用 | +| PSimpChat | 中國大陸字形(UI,重對映)| 中國大陸字形(重對映)| 中國大陸字形(重對映)| 不適用 | * 西文:英語、西班牙語(拉丁美洲)、葡萄牙語、德語、西班牙語(歐洲)、法語、義大利語、俄語。 * UI:中西文共用的標點視作西文標點;半形 CJK 標點。 +* 通用字型:`FRIZQT__` 和 `ARIALN`。某些插件硬編碼了此字型。 ### 特徵 | 標記 | 名稱 | 簡介 | | ---- | ----------- | ------------------------------------------------------------------------------- | | OSF | Oldstyle | 不齊線、不等寬的舊樣式數字。 | -| SC | Smallcaps | 小型大寫拉丁、西里爾、希臘字母。 | +| SC | Smallcaps | 小型大寫拉丁字母。 | | RP | Roleplaying | `丶`(U+4E36)重對映為 `·`(U+00B7,MIDDLE DOT;或 U+2027,HYPHENATION POINT)。| -預編譯的特徵變體:`CL,OSF`、`CL,SC`、`CL,OSF,SC`、`GB,RP`。 - -### SharedMedia 字型包 - -有愛新黑也可以以插件的形式安裝(**很大!**),啓用之後會向 SharedMedia 登錄有愛新黑字體。 +預編譯的特徵變體:`Bliz,OSF`、`Bliz,RP`、`Bliz,SC`。 diff --git a/README.md b/README.md index 5f90a06..9381d0c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ **English** [简体中文](README-Hans.md) [繁體中文](README-Hant.md) -# Nowar Neo Sans for _World of Warcraft_ +# Nowar Neo Sans This is Nowar Neo Sans, font packs for _World of Warcraft_ and _WoW Classic_ that support all client languages. Nowar Neo Sans is based on [Roboto](https://github.com/google/roboto) and [Source Han Sans](https://github.com/adobe-fonts/source-han-sans). @@ -18,7 +18,7 @@ This is Nowar Neo Sans, font packs for _World of Warcraft_ and _WoW Classic_ tha Mirrors: [Gitee (release repo)](https://gitee.com/nowar-fonts/Nowar-Neo-Sans) -Nowar Neo Sans is shipped in 4 weights and 7 regional variants, with several features. +Nowar Neo Sans is shipped in 4 weights and 5 regional variants, with several features. ### Weights @@ -29,44 +29,39 @@ Nowar Neo Sans is shipped in 4 weights and 7 regional variants, with several fea ### Regional Variants -CN, TW, HK, JP and KR are “standard variants”, which have full character set support with regional Chinese character orthographies. +Bliz and Neut are “standard variants” with regional Chinese character orthographies. -| | European | 简体中文 | 繁體中文 | 한국어 | -| -- | ------------------- | -------------- | --------- | ------------- | -| CN | Mainland China (UI) | Mainland China | Taiwan | S. Korea (UI) | -| TW | Taiwan (UI) | Mainland China | Taiwan | S. Korea (UI) | -| HK | Hong Kong (UI) | Mainland China | Hong Kong | S. Korea (UI) | -| JP | Japan (UI) | Mainland China | Taiwan | S. Korea (UI) | -| KR | S. Korea (UI) | Mainland China | Taiwan | S. Korea (UI) | +| | European and 한국어 | 简体中文 | 繁體中文 | Note | +| ---- | ------------------- | -------------- | -------- | ------------------------------------------ | +| Bliz | Mainland China (UI) | Mainland China | Taiwan | Acts like WoW’s default fallback setting. | +| Neut | Classical (UI) | Mainland China | Taiwan | Prefers classical orthography on fallback. | -CL, the “classical variant”, have full character set support with classical Chinese character orthography (aka Kāngxī Dictionary forms). +CL is the “classical variant” with classical Chinese character orthography (aka Kāngxī Dictionary forms). -| | European | 中文 | 한국어 | -| --- | -------------- | --------- | -------------- | -| CL | Classical (UI) | Classical | Classical (UI) | +| | European and 한국어 | 中文 | +| -- | ------------------- | --------- | +| CL | Classical (UI) | Classical | -GB is a variant that supports a superset of Chinese national standard GB 18030-2000. The GB distributions aim at smaller size by removing Hangul support. +PSimp and PSimpChat are special variants for 繁體中文 that remap traditional Chinese character to simplified ones. -| | European | 中文 | 한국어 | -| -- | ------------------- | -------------- | ------ | -| GB | Mainland China (UI) | Mainland China | N/A | +| | Common Fonts | 繁體中文 Text, Combat and Tooltip Fonts | 繁體中文 Chat Fonts | European, 简体中文 and 한국어 | +| --------- | ----------------------------- | ------------------------- | ------------------------- | --- | +| PSimp | Mainland China (UI, Remapped) | Mainland China (Remapped) | Mainland China | N/A | +| PSimpChat | Mainland China (UI, Remapped) | Mainland China (Remapped) | Mainland China (Remapped) | N/A | * European: English, Español (AL), Português, Deutsch, Español (EU), Français, Italiano, and Русский. * UI: Ambiguous punctations are treated as Western; CJK puctations are half-width. +* Common fonts: `FRIZQT__` and `ARIALN`, which are hard-coded in some addons. ### Features | Tag | Name | Description | | --- | ----------- | ---------------------------------------------------------------------- | | OSF | Oldstyle | Oldstyle (non-lining), propotional figure. | -| SC | Smallcaps | Small capitals for Latin, Cyrillic and Greek. | | RP | Roleplaying | `丶` (U+4E36) is mapped to the same glyph as `·` (U+00B7, MIDDLE DOT). | +| SC | Smallcaps | Small capitals for Latin. | -Pre-built feature variants: `CL,OSF`, `CL,SC`, `CL,OSF,SC`, `GB,RP`. - -### SharedMedia Font Provider - -Nowar Neo Sans is also avialable as an addon (REALLY HUGE!), to register Nowar Neo Sans typeface to SharedMedia. +Pre-built feature variants: `Bliz,OSF`, `Bliz,RP`, `Bliz,SC`. ## How to Build @@ -80,7 +75,6 @@ Nowar Neo Sans is also avialable as an addon (REALLY HUGE!), to register Nowar N Note: + Choose 64-bit version if possible. 32-bit version may lead to out-of-memory issue. -+ Use POSIX build of GNU Make on Windows ([MSYS2’s](https://www.msys2.org) or [Nowar’s](https://github.com/nowar-fonts/Toolchain-Windows-Build)). ### Build Feature Variant @@ -100,39 +94,46 @@ Then make a specific variant: ```bash make ,- -j ``` -Note: Features must be identically sorted as mentioned above. (`OSF`, `SC`, `RP`). +Note: Features must be sorted alphabetically. (`OSF`, `RP`, `SC`). e.g. ```bash -make CN,OSF,SC,RP-400 -j4 +make CN,OSF,RP-400 -j4 ``` The output is `out/NowarNeoSans-,--.7z`. ### Create Regional Variant + To build exactly what you need, modify `configure.py`: ```python class Config: # put your variant here fontPackRegion = [ ] -# define the variant here. don’t remove pre-defined variants. +# define the variant here. regionalVariant = { ... } ``` -For example, “I enjoy Japna’s orthography, and I’d like to apply it to every language!” +For example, the “CNmulti” multi-orthography variant, + +| | European | 简体中文 | 繁體中文 | 한국어 | +| ------- | ------------------- | -------------- | -------- | ------------- | +| CNmulti | Mainland China (UI) | Mainland China | Taiwan | S. Korea (UI) | + ```python class Config: - fontPackRegion = [ "JPeverywhere" ] + fontPackRegion = [ "CNmulti" ] regionalVariant = { - ..., - "JPeverywhere": { - "Latn": "JP", - "Hans": "JP", - "Hant": "JP", - "ko": "JP", + "CNmulti": { + "base": "CN", + "enUS": True, + "ruRU": True, + "zhCN": "CN", + "zhTW": "TW", + "koKR": "KR", } } ``` @@ -143,8 +144,8 @@ make ,- -j ``` e.g. ```bash -make JPeverywhere-400 -j4 -make JPeverywhere,OSF-400 -j4 +make CNmulti-400 -j4 +make CNmulti,OSF-400 -j4 ``` ## Credit @@ -152,3 +153,5 @@ make JPeverywhere,OSF-400 -j4 Latin, Greek and Cyrillic characters are from [Roboto](https://github.com/google/roboto) by Google. CJK Ideographs, Kana and Hangul are from [Source Han Sans](https://github.com/adobe-fonts/source-han-sans) by Adobe. + +The traditional Chinese to simplified Chinese conversion table is from [Open Chinese Convert project](https://github.com/BYVoid/OpenCC). diff --git a/configure.py b/configure.py index eead22f..94766e1 100644 --- a/configure.py +++ b/configure.py @@ -1,748 +1,820 @@ import json import codecs +import enum +import hashlib from functools import reduce from itertools import product -from types import SimpleNamespace as Namespace + class Config: - version = "0.7.2" - fontRevision = 0.0702 - vendor = "Nowar Typeface" - vendorId = "NOWR" - vendorUrl = "https://github.com/nowar-fonts" - copyright = "Copyright © 2018—2020 Cyano Hao and Nowar Typeface, with reserved font name “Nowar”, “有爱”, and “有愛”. Portions Copyright 2011 Google Inc. Portions © 2014-2019 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'.." - designer = "Cyano Hao (character set definition & modification for World of Warcraft); Christian Robertson (Latin, Greek & Cyrillic); Ryoko NISHIZUKA 西塚涼子 (kana, bopomofo & ideographs); Sandoll Communications 산돌커뮤니케이션, Soo-young JANG 장수영 & Joo-yeon KANG 강주연 (hangul elements, letters & syllables); Dr. Ken Lunde (project architect, glyph set definition & overall production); Masataka HATTORI 服部正貴 (production & ideograph elements)" - designerUrl = "https://github.com/CyanoHao" - license = "This Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software." - licenseUrl = "https://scripts.sil.org/OFL" - - fontPackWeight = [ 300, 400, 500, 700 ] - fontPackRegion = [ "CN", "TW", "HK", "JP", "KR", "CL", "GB" ] - fontPackFeature = [ "OSF", "SC", "RP" ] - # feature tags must be identically ordered as in fontPackFeature - fontPackExportFeature = [ - ("CL", [ "OSF" ]), - ("CL", [ "SC" ]), - ("CL", [ "OSF", "SC" ]), - ("GB", [ "RP" ]), - ] + version = "0.8.0" + fontRevision = 0.0800 + vendor = "Nowar Typeface" + vendorId = "NOWR" + vendorUrl = "https://github.com/nowar-fonts" + copyright = "Copyright © 2018—2020 Cyano Hao and Nowar Typeface, with Reserved Font Name “Nowar”, “Новар”, “Νοωαρ”, “有爱”, and “有愛”. Portions Copyright 2011 Google Inc. Portions © 2014-2019 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'." + designer = "Cyano Hao (character set definition & modification for World of Warcraft); Christian Robertson (Latin, Greek & Cyrillic); Ryoko NISHIZUKA 西塚涼子 (kana, bopomofo & ideographs); Sandoll Communications 산돌커뮤니케이션, Soo-young JANG 장수영 & Joo-yeon KANG 강주연 (hangul elements, letters & syllables); Dr. Ken Lunde (project architect, glyph set definition & overall production); Masataka HATTORI 服部正貴 (production & ideograph elements)" + designerUrl = "https://github.com/CyanoHao" + license = "This Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software." + licenseUrl = "https://scripts.sil.org/OFL" + + fontPackWeight = [300, 400, 500, 700] + fontPackRegion = ["Bliz", "Neut", "CL", "PSimp", "PSimpChat"] + fontPackFeature = ["OSF", "RP", "SC"] + # feature tags must be sorted alphabetically + fontPackExportFeature = [ + ("Bliz", ["OSF"]), + ("Bliz", ["RP"]), + ("Bliz", ["SC"]), + ] + config = Config() +# define Chinese characters orthographies, and feature mods: +# +# base - common fonts, `FRIZQT__` and `ARIALN`; must be defined +# enUS - fonts for languages in Latin script, `skurri` and `MORPHEUS` +# if set to something to be true, the orthography is considered to be same as `base` +# if set to something to be false, fonts will be not overwritten +# ruRU - fonts for Русский; like `enUS` +# zhCN - fonts for 简体中文; can be false +# zhTW - fonts for 繁體中文; can be false +# koKR - fonts for 한국어; can be false +# +# xmod - a list of tuples of feature mod and related parameter list +# available mods: +# PSimp - 伪简体, remap traditional Chinese characters to simplified ones in zhTW text, damage, and note font +# base - also do remapping in common fonts (`FRIZQT__` and `ARIALN`) +# chat - also do remapping in zhTW chat fonts (`arheiuhk_bd` for Battle and `bHEI01B` for Classic) +regionalVariant = { + "Neut": { + "base": "CL", + "enUS": True, + "ruRU": True, + "zhCN": "CN", + "zhTW": "TW", + "koKR": "CL", + }, + "Bliz": { + "base": "CN", + "enUS": True, + "ruRU": True, + "zhCN": "CN", + "zhTW": "TW", + "koKR": "CN", # yes, it is + }, + "CL": { + "base": "CL", + "enUS": True, + "ruRU": True, + "zhCN": "CL", + "zhTW": "CL", + "koKR": "CL", + }, + "PSimp": { + "base": "CN", + "enUS": None, + "ruRU": None, + "zhCN": None, + "zhTW": "CN", + "koKR": None, + "xmod": [("PSimp", ["base"])], + }, + "PSimpChat": { + "base": "CN", + "enUS": None, + "ruRU": None, + "zhCN": None, + "zhTW": "CN", + "koKR": None, + "xmod": [("PSimp", ["base", "chat"])], + }, + "CN": { # deprecated + "base": "CN", + "enUS": True, + "ruRU": True, + "zhCN": "CN", + "zhTW": "TW", + "koKR": "KR", + }, + "TW": { # deprecated + "base": "TW", + "enUS": True, + "ruRU": True, + "zhCN": "CN", + "zhTW": "TW", + "koKR": "KR", + }, + "HK": { # deprecated + "base": "HK", + "enUS": True, + "ruRU": True, + "zhCN": "CN", + "zhTW": "HK", + "koKR": "KR", + }, + "JP": { # deprecated + "base": "JP", + "enUS": True, + "ruRU": True, + "zhCN": "CN", + "zhTW": "TW", + "koKR": "KR", + }, + "KR": { # deprecated + "base": "KR", + "enUS": True, + "ruRU": True, + "zhCN": "CN", + "zhTW": "TW", + "koKR": "KR", + }, + "GB": { # deprecated + "base": "GB", + "enUS": True, + "ruRU": True, + "zhCN": "GB", + "zhTW": "GB", + "koKR": None, + }, +} + + +class LanguageId(enum.IntEnum): + enGB = 0x0809 + enUS = 0x0409 + jaJP = 0x0411 + koKR = 0x0412 + zhCN = 0x0804 + zhHK = 0x0C04 + zhMO = 0x1404 + zhSG = 0x1004 + zhTW = 0x0404 + + +familyLocalization = { + "CN": { + "Latin": True, "Cyrillic": True, "Hellenic": True, + "Chinese": True, "Japanese": True, "Korean": True, + }, + "TW": { + "Latin": True, "Cyrillic": True, "Hellenic": True, + "Chinese": True, "Japanese": True, "Korean": True, + }, + "HK": { + "Latin": True, "Cyrillic": True, "Hellenic": True, + "Chinese": True, "Japanese": True, "Korean": True, + }, + "MO": { + "Latin": True, "Cyrillic": True, "Hellenic": True, + "Chinese": True, "Japanese": True, "Korean": True, + }, + "JP": { + "Latin": True, "Cyrillic": True, "Hellenic": True, + "Chinese": True, "Japanese": True, "Korean": True, + }, + "KR": { + "Latin": True, "Cyrillic": True, "Hellenic": True, + "Chinese": True, "Japanese": True, "Korean": True, + }, + "CL": { + "Latin": True, "Cyrillic": True, "Hellenic": True, + "Chinese": True, "Japanese": True, "Korean": True, + }, + "GB": { + "Latin": True, "Cyrillic": True, "Hellenic": True, + "Chinese": True, "Japanese": True, "Korean": False, + }, +} + + weightMap = { - 100: "Thin", - 200: "ExtraLight", - 300: "Light", - 400: "Regular", - 500: "Medium", - 600: "SemiBold", - 700: "Bold", - 800: "ExtraBold", - 900: "Black", + 100: "Thin", + 200: "ExtraLight", + 300: "Light", + 372: "Normal", + 400: "", + 500: "Medium", + 600: "SemiBold", + 700: "Bold", + 800: "ExtraBold", + 900: "Black", +} + +weightMapShort = { + 100: "Th", + 200: "XLt", + 300: "Lt", + 372: "Nm", + 400: "", + 500: "Md", + 600: "SmBd", + 700: "Bd", + 800: "XBd", + 900: "Bk", } widthMap = { - 3: "Condensed", - 4: "SemiCondensed", - 5: None, - 7: "Extended", + 3: "Condensed", + 4: "SemiCondensed", + 5: None, + 7: "Extended", + 10: "Warcraft", # Warcraft numeral hack } -robotoFamilyMap = { - 3: "RobotoCondensed", - 5: "Roboto", +widthMapShort = { + 3: "Cn", + 4: "SmCn", + 5: None, + 7: "Ex", + 10: "Wc", } -robotoWidthMap = { - 3: 5, - 5: 5, +slantMapShort = { + "Italic": "It", + "Oblique": "Obl", } -morpheusWeightMap = { - 300: 300, - 400: 400, - 500: 500, - 700: 700, +robotoFamilyMap = { + 3: "RobotoCondensed", + 5: "Roboto", } -# define font pack orthographies for diffrent WoW language -# Latn -- Chinese characters in European languages, must be defined. -# Hans -- 简体中文; if set to `None`, the font pack will not override 简体中文 font. -# Hans -- 繁體中文, can be `None`. -# ko -- 漢字 in 한국어, can be `None`. -regionalVariant = { - "CN": { - "Latn": "CN", - "Hans": "CN", - "Hant": "TW", - "ko": "KR", - }, - "TW": { - "Latn": "TW", - "Hans": "CN", - "Hant": "TW", - "ko": "KR", - }, - "HK": { - "Latn": "HK", - "Hans": "CN", - "Hant": "HK", - "ko": "KR", - }, - "JP": { - "Latn": "JP", - "Hans": "CN", - "Hant": "TW", - "ko": "KR", - }, - "KR": { - "Latn": "KR", - "Hans": "CN", - "Hant": "TW", - "ko": "KR", - }, - "CL": { - "Latn": "CL", - "Hans": "CL", - "Hant": "CL", - "ko": "CL", - }, - "GB": { - "Latn": "GB", - "Hans": "GB", - "Hant": "GB", - "ko": None, - }, +robotoWidthMap = { + 3: 5, + 5: 5, } # map orthography to source file -regionSourceMap = { - "CN": "SourceHanSansSC", - "TW": "SourceHanSansTC", - "HK": "SourceHanSansHC", - "JP": "SourceHanSans", - "KR": "SourceHanSansK", - "CL": "SourceHanSansK", - "GB": "SourceHanSansCN", +shsRegionMap = { + "CN": "SourceHanSansSC", + "TW": "SourceHanSansTC", + "HK": "SourceHanSansHC", + "MO": "SourceHanSansMC", + "JP": "SourceHanSans", + "KR": "SourceHanSansK", + "CL": "SourceHanSansK", + "GB": "SourceHanSansCN", } regionNameMap = { - "CN": "CN", - "TW": "TW", - "HK": "HK", - "JP": "JP", - "KR": "KR", - "CL": "Classical", - "GB": "GB18030", + "CN": "CN", + "TW": "TW", + "HK": "HK", + "MO": "MO", + "JP": "JP", + "KR": "KR", + "CL": "Classical", + "GB": "GB18030", +} + +# sorted alphabetically +featureNameMap = { + "OSF": "Oldstyle", + "RP": "Roleplaying", + "SC": "Smallcaps", + "Simp": "Simplified", + "UI": "UI", } -tagNameMap = dict(regionNameMap) -tagNameMap.update({ - "OSF": "Oldstyle", - "SC": "Smallcaps", - "RP": "Roleplaying", -}) - -# set OS/2 encoding to make Windows show font icon in proper language -encoding = [ - "unspec", # 文字美 - "gbk", # 简体字 - "big5", # 繁體字 - "jis", # あア亜 - "korean", # 한글 -] - -def GetRegion(p): - if hasattr(p, "region"): - return p.region - else: - return "" +tagNameMap = {**regionNameMap, **featureNameMap} + def LocalizedFamily(p): - if "nameList" not in LocalizedFamily.__dict__: - LocalizedFamily.nameList = { - "Sans": { - 0x0409: "Nowar Neo Sans", - 0x0804: "有爱新黑", - 0x0404: "有愛新黑", - 0x0C04: "有愛新黑", - 0x0411: "有愛新ゴシック", - 0x0412: "有愛 네오 고딕", - }, - "UI": { - 0x0409: "Nowar Neo UI", - 0x0804: "有爱新黑 UI", - 0x0404: "有愛新黑 UI", - 0x0C04: "有愛新黑 UI", - 0x0411: "有愛新ゴシック UI", - 0x0412: "有愛 네오 고딕 UI", - }, - "WarcraftSans": { - 0x0409: "Nowar Neo Warcraft Sans", - 0x0804: "有爱魔兽黑体", - 0x0404: "有愛魔獸新黑", - 0x0C04: "有愛魔獸新黑", - 0x0411: "有愛ウォークラフト新ゴシック", - 0x0412: "有愛 네오 워크래프트 고딕", - }, - "WarcraftUI": { - 0x0409: "Nowar Neo Warcraft UI", - 0x0804: "有爱魔兽黑体 UI", - 0x0404: "有愛魔獸新黑 UI", - 0x0C04: "有愛魔獸新黑 UI", - 0x0411: "有愛ウォークラフト新ゴシック UI", - 0x0412: "有愛 네오 워크래프트 고딕 UI", - }, - } - - if p.family == "Latin": - return { - 0x0409: "Nowar Neo UI LCG", - 0x0804: "Nowar Neo UI LCG", - 0x0404: "Nowar Neo UI LCG", - 0x0C04: "Nowar Neo UI LCG", - 0x0411: "Nowar Neo UI LCG", - 0x0412: "Nowar Neo UI LCG", - } - - isLocalized = { - 0x0804: bool(regionalVariant[p.region]["Hans"]), - 0x0404: bool(regionalVariant[p.region]["Hant"]), - 0x0C04: bool(regionalVariant[p.region]["Hant"]), - 0x0411: bool(regionalVariant[p.region]["Hans"]), - 0x0412: bool(regionalVariant[p.region]["ko"]), - } - - result = dict(LocalizedFamily.nameList[p.family]) - result.update({ lang: result[0x0409] for lang, local in isLocalized.items() if not local }) - return result - -def GetTagList(p): - if p.family == "Latin": - tagList = p.feature - else: - tagList = [ p.region ] + p.feature - return tagList - -def GetTagStr(p): - tagList = GetTagList(p) - return ",".join(tagList) + result = { + LanguageId.enUS: "Nowar Neo Sans", + LanguageId.enGB: "Nowar Neo Sans", + + LanguageId.jaJP: "有愛新ゴシック", + LanguageId.koKR: "有愛 네오 고딕", + LanguageId.zhCN: "有爱新黑", + LanguageId.zhHK: "有愛新黑", + LanguageId.zhMO: "有愛新黑", + LanguageId.zhSG: "有爱新黑", + LanguageId.zhTW: "有愛新黑", + } + + r = p["region"] + isLocalized = { + LanguageId.enGB: bool(familyLocalization[r]["Latin"]), + LanguageId.jaJP: bool(familyLocalization[r]["Japanese"]), + LanguageId.koKR: bool(familyLocalization[r]["Korean"]), + LanguageId.zhCN: bool(familyLocalization[r]["Chinese"]), + LanguageId.zhHK: bool(familyLocalization[r]["Chinese"]), + LanguageId.zhMO: bool(familyLocalization[r]["Chinese"]), + LanguageId.zhSG: bool(familyLocalization[r]["Chinese"]), + LanguageId.zhTW: bool(familyLocalization[r]["Chinese"]), + } + + result.update({lang: result[LanguageId.enUS] + for lang, local in isLocalized.items() if not local}) + return result + def TagListToStr(lst): - return ",".join(lst) - -def TagStrToList(s): - return s.split(",") - -def GenerateFamily(p): - localizedFamily = LocalizedFamily(p) - tagList = GetTagList(p) - if len(tagList): - return { - lang: localizedFamily[lang] + " " + " ".join([ tagNameMap[tag] for tag in tagList ]) - for lang in localizedFamily - } - else: - return localizedFamily - -def GenerateSubfamily(p): - width = widthMap[p.width] - weight = weightMap[p.weight] - if hasattr(p, "italic") and p.italic: - if p.weight == 400: - return width + " Italic" if width else "Italic" - else: - return ("{} {}".format(width, weight) if width else weight) + " Italic" - else: - if p.weight == 400: - return width if width else "Regular" - else: - return "{} {}".format(width, weight) if width else weight - -def GenerateFriendlyFamily(p): - return { k: "{} {}".format(v, GenerateSubfamily(p)) for k, v in GenerateFamily(p).items() } - -def GenerateLegacySubfamily(p): - width = widthMap[p.width] - weight = weightMap[p.weight] - if hasattr(p, "italic") and p.italic: - if p.weight == 400: - return width or "", "Italic" - elif p.weight == 700: - return width or "", "Bold Italic" - else: - return "{} {}".format(width, weight) if width else weight, "Italic" - else: - if p.weight == 400 or p.weight == 700: - return width or "", weight - else: - return "{} {}".format(width, weight) if width else weight, "Regular" + return ",".join(lst) + + +def GenerateFontName(p): + localizedFamily = LocalizedFamily(p) + region = p["region"] + feature = [*sorted(p["feature"])] + + regionName = regionNameMap[region] + subfamily = [tagNameMap[fea] for fea in feature] + filenameSf = [] + wwsF = [region, *feature] + wwsSf = [] + legacyF = [region, *feature] + legacySf = [] + + width = p["width"] + widthName = widthMap[width] + widthShort = widthMapShort[width] + if widthName: + subfamily.append(widthName) + filenameSf.append(widthName) + legacyF.append(widthShort) + # Warcraft numeral hack + if width == 10: + wwsF.append(widthShort) + elif widthName: + wwsSf.append(widthName) + + weight = p["weight"] + weightName = weightMap[weight] + weightShort = weightMapShort[weight] + if weightName: + subfamily.append(weightName) + filenameSf.append(weightName) + wwsSf.append(weightName) + if weight == 700: + legacySf.append(weightName) + else: + legacyF.append(weightShort) + + if p.get("slant"): + slantName = p["slant"] + slantShort = slantMapShort[slantName] + subfamily.append(slantName) + filenameSf.append(slantName) + wwsSf.append(slantName) + if slantName == "Italic": + legacySf.append(slantName) + else: + legacyF.append(slantShort) + + def formatFamily(f): + return " ".join(f) + + def formatSubfamily(sf): + return " ".join(sf) or "Regular" + + subfamily = formatSubfamily(subfamily) + filenameF = localizedFamily[LanguageId.enUS].replace(" ", "") + filenameTag = TagListToStr([p["region"], *sorted(p["feature"])]) + filenameSf = formatSubfamily(filenameSf).replace(" ", "") + wwsF = formatFamily(wwsF) + wwsSf = formatSubfamily(wwsSf) + legacyF = formatSubfamily(legacyF) + legacySf = formatSubfamily(legacySf) + + return { + "typographic": ({k: "{} {}".format(v, regionName) for k, v in localizedFamily.items()}, subfamily), + "wws": ({k: "{} {}".format(v, wwsF) for k, v in localizedFamily.items()}, wwsSf), + "legacy": ({k: "{} {}".format(v, legacyF) for k, v in localizedFamily.items()}, legacySf), + "friendly": {k: "{} {} {}".format(v, regionName, subfamily) for k, v in localizedFamily.items()}, + "file": "{}-{}-{}".format(filenameF, filenameTag, filenameSf), + # font name can be too long to fit in 63-char PostScript name + # the hashed name makes no sence but is valid + "postscript": "NowarSans-" + hashlib.sha1("{} {}".format(regionName, subfamily).encode()).hexdigest(), + } + def GenerateFilename(p): - if p.family in [ "Sans", "UI", "WarcraftSans", "WarcraftUI" ]: - encodingPrefix = p.encoding + "-" - nameList = { - "Sans": "NowarNeoSans", - "UI": "NowarNeoUI", - "WarcraftSans": "NowarNeoWarcraftSans", - "WarcraftUI": "NowarNeoWarcraftUI", - } - familyName = nameList[p.family] + "-" + GetTagStr(p) - elif p.family == "Latin": - encodingPrefix = "" - nameList = { - "Latin": "NowarNeoLCG", - } - familyName = nameList[p.family] + "-" + GetTagStr(p) - else: - encodingPrefix = "" - nameList = { - "Roboto": lambda p: "Roboto", - "RobotoCondensed": lambda p: "RobotoCondensed", - "Source": lambda p: p.region, - } - familyName = nameList[p.family](p) - return encodingPrefix + familyName + "-" + GenerateSubfamily(p).replace(" ", "") + if p["family"] == "Nowar": + filename = GenerateFontName(p)["file"] + return p["encoding"] + "-" + filename + else: + nameList = { + "Roboto": lambda p: "Roboto", + "RobotoCondensed": lambda p: "RobotoCondensed", + "SHS": lambda p: p["region"], + } + family = nameList[p["family"]](p) + subfamily = ((widthMap[p["width"]] or "") + (weightMap[p["weight"]] or "") + + (p.get("slant") or "")) or "Regular" + return family + "-" + subfamily + def ResolveDependency(p): - result = { - "Latin": Namespace( - family = robotoFamilyMap[p.width], - width = robotoWidthMap[p.width], - weight = p.weight - ) - } - if p.family in [ "WarcraftSans", "WarcraftUI" ]: - result["Numeral"] = Namespace( - family = "RobotoCondensed", - width = 5, - weight = p.weight - ) - if p.family in [ "Sans", "UI", "WarcraftSans", "WarcraftUI" ]: - result["CJK"] = Namespace( - family = "Source", - weight = p.weight, - width = 5, - region = regionSourceMap[p.region] - ) - return result - -def GetMorpheus(weight, feature): - return Namespace( - weight = morpheusWeightMap[weight], - width = 3, - family = "Latin", - feature = feature, - ) - -def GetSkurri(weight, feature): - return Namespace( - weight = weight, - width = 5, - family = "Latin", - feature = feature, - ) + if p["width"] == 10: # Warcraft numeral hack + result = { + "Latin": { + "family": "Roboto", + "width": 5, + "weight": p["weight"], + }, + "Numeral": { + "family": "RobotoCondensed", + "width": 5, + "weight": p["weight"], + }, + } + else: + result = { + "Latin": { + "family": robotoFamilyMap[p["width"]], + "width": robotoWidthMap[p["width"]], + "weight": p["weight"], + }, + } + result["CJK"] = { + "family": "SHS", + "weight": p["weight"], + "width": 5, + "region": shsRegionMap[p["region"]], + } + return result + + +def GetCommonFont(weight, region, feature): + xfea = [] + for mod, params in regionalVariant[region].get("xmod", []): + if mod == "PSimp" and "base" in params: + xfea.append("Simp") + return { + "weight": weight, + "width": 5, + "family": "Nowar", + "region": regionalVariant[region]["base"], + "feature": ["UI"] + feature + xfea, + "encoding": "unspec", + } + + +def GetCommonChatFont(weight, region, feature): + xfea = [] + for mod, params in regionalVariant[region].get("xmod", []): + if mod == "PSimp" and "base" in params: + xfea.append("Simp") + return { + "weight": weight, + "width": 3, + "family": "Nowar", + "region": regionalVariant[region]["base"], + "feature": ["UI"] + feature + xfea, + "encoding": "unspec", + } + def GetLatinFont(weight, region, feature): - return Namespace( - weight = weight, - width = 5, - family = "UI", - region = regionalVariant[region]["Latn"], - feature = feature, - encoding = "unspec" - ) + return { + "weight": weight, + "width": 5, + "family": "Nowar", + "region": regionalVariant[region]["base"], + "feature": ["UI"] + feature, + "encoding": "unspec", + } + def GetLatinChatFont(weight, region, feature): - return Namespace( - weight = weight, - width = 3, - family = "UI", - region = regionalVariant[region]["Latn"], - feature = feature, - encoding = "unspec" - ) + return { + "weight": weight, + "width": 3, + "family": "Nowar", + "region": regionalVariant[region]["base"], + "feature": ["UI"] + feature, + "encoding": "unspec", + } + def GetHansFont(weight, region, feature): - return Namespace( - weight = weight, - width = 5, - family = "WarcraftSans", - region = regionalVariant[region]["Hans"], - feature = feature, - encoding = "gbk" - ) + return { + "weight": weight, + "width": 10, + "family": "Nowar", + "region": regionalVariant[region]["zhCN"], + "feature": feature, + "encoding": "gbk", + } + def GetHansCombatFont(weight, region, feature): - return Namespace( - weight = weight, - width = 5, - family = "Sans", - region = regionalVariant[region]["Hans"], - feature = feature, - encoding = "gbk" - ) + return { + "weight": weight, + "width": 5, + "family": "Nowar", + "region": regionalVariant[region]["zhCN"], + "feature": feature, + "encoding": "gbk", + } + def GetHansChatFont(weight, region, feature): - return Namespace( - weight = weight, - width = 3, - family = "Sans", - region = regionalVariant[region]["Hans"], - feature = feature, - encoding = "gbk" - ) + return { + "weight": weight, + "width": 3, + "family": "Nowar", + "region": regionalVariant[region]["zhCN"], + "feature": feature, + "encoding": "gbk", + } + def GetHantFont(weight, region, feature): - return Namespace( - weight = weight, - width = 5, - family = "WarcraftSans", - region = regionalVariant[region]["Hant"], - feature = feature, - encoding = "big5" - ) + xfea = [] + for mod, _ in regionalVariant[region].get("xmod", []): + if mod == "PSimp": + xfea.append("Simp") + return { + "weight": weight, + "width": 10, + "family": "Nowar", + "region": regionalVariant[region]["zhTW"], + "feature": feature + xfea, + "encoding": "big5", + } + def GetHantCombatFont(weight, region, feature): - return Namespace( - weight = weight, - width = 5, - family = "Sans", - region = regionalVariant[region]["Hant"], - feature = feature, - encoding = "big5" - ) + xfea = [] + for mod, _ in regionalVariant[region].get("xmod", []): + if mod == "PSimp": + xfea.append("Simp") + return { + "weight": weight, + "width": 5, + "family": "Nowar", + "region": regionalVariant[region]["zhTW"], + "feature": feature + xfea, + "encoding": "big5", + } + def GetHantNoteFont(weight, region, feature): - return Namespace( - weight = weight, - width = 5, - family = "Sans", - region = regionalVariant[region]["Hant"], - feature = feature, - encoding = "big5" - ) + xfea = [] + for mod, _ in regionalVariant[region].get("xmod", []): + if mod == "PSimp": + xfea.append("Simp") + return { + "weight": weight, + "width": 5, + "family": "Nowar", + "region": regionalVariant[region]["zhTW"], + "feature": feature + xfea, + "encoding": "big5", + } + def GetHantChatFont(weight, region, feature): - return Namespace( - weight = weight, - width = 3, - family = "Sans", - region = regionalVariant[region]["Hant"], - feature = feature, - encoding = "big5" - ) + xfea = [] + for mod, params in regionalVariant[region].get("xmod", []): + if mod == "PSimp" and "chat" in params: + xfea.append("Simp") + return { + "weight": weight, + "width": 3, + "family": "Nowar", + "region": regionalVariant[region]["zhTW"], + "feature": feature + xfea, + "encoding": "big5", + } def GetKoreanFont(weight, region, feature): - return Namespace( - weight = weight, - width = 5, - family = "UI", - region = regionalVariant[region]["ko"], - feature = feature, - encoding = "korean" - ) + return { + "weight": weight, + "width": 5, + "family": "Nowar", + "region": regionalVariant[region]["koKR"], + "feature": ["UI"] + feature, + "encoding": "korean", + } + def GetKoreanCombatFont(weight, region, feature): - return Namespace( - weight = weight, - width = 5, - family = "UI", - region = regionalVariant[region]["ko"], - feature = feature, - encoding = "korean" - ) + return { + "weight": weight, + "width": 5, + "family": "Nowar", + "region": regionalVariant[region]["koKR"], + "feature": ["UI"] + feature, + "encoding": "korean", + } + def GetKoreanDisplayFont(weight, region, feature): - return Namespace( - weight = weight, - width = 3, - family = "UI", - region = regionalVariant[region]["ko"], - feature = feature, - encoding = "korean" - ) - -def ParamToArgument(conf): - js = json.dumps(conf.__dict__, separators=(',',':')) - return "'{}'".format(js) + return { + "weight": weight, + "width": 3, + "family": "Nowar", + "region": regionalVariant[region]["koKR"], + "feature": ["UI"] + feature, + "encoding": "korean", + } + + +def ParamToArgument(param): + js = json.dumps(param, separators=(',', ':')) + return "'{}'".format(js) + if __name__ == "__main__": - makefile = { - "variable": { - "VERSION": config.version, - }, - "rule": { - ".PHONY": { - "depend": [ "all" ], - }, - "all": { - "depend": [], - }, - "clean": { - "command": [ - "-rm -rf build/", - "-rm -rf out/??*-???/", - ] - } - }, - } - - unique = lambda l: reduce(lambda l, x: l + [ x ] if x not in l else l, l, []) - powerset = lambda lst: reduce(lambda result, x: result + [subset + [x] for subset in result], lst, [[]]) - - # font pack for each regional variant and weight - for r, w, fea in product(config.fontPackRegion, config.fontPackWeight, powerset(config.fontPackFeature)): - tagList = [ r ] + fea - target = "{}-{}".format(TagListToStr(tagList), w) - pack = "out/NowarNeoSans-{}-${{VERSION}}.7z".format(target) - - makefile["rule"][".PHONY"]["depend"].append(target) - makefile["rule"][target] = { - "depend": [ pack ], - } - - if fea == [] or (r, fea) in config.fontPackExportFeature: - makefile["rule"]["all"]["depend"].append(pack) - - fontlist = { - "ARIALN": GetLatinChatFont(w, r, fea), - "FRIZQT__": GetLatinFont(w, r, fea), - "MORPHEUS": GetMorpheus(w, fea), - "skurri": GetSkurri(w, fea), - - "FRIZQT___CYR": GetLatinFont(w, r, fea), - "MORPHEUS_CYR": GetMorpheus(w, fea), - "SKURRI_CYR": GetSkurri(w, fea), - } - - if regionalVariant[r]["Hans"]: - fontlist.update({ - "ARKai_C": GetHansCombatFont(w, r, fea), - "ARKai_T": GetHansFont(w, r, fea), - "ARHei": GetHansChatFont(w, r, fea), - }) - - if regionalVariant[r]["Hant"]: - fontlist.update({ - "arheiuhk_bd": GetHantChatFont(w, r, fea), - "bHEI00M": GetHantNoteFont(w, r, fea), - "bHEI01B": GetHantChatFont(w, r, fea), - "bKAI00M": GetHantCombatFont(w, r, fea), - "blei00d": GetHantFont(w, r, fea), - }) - - if regionalVariant[r]["ko"]: - fontlist.update({ - "2002": GetKoreanFont(w, r, fea), - "2002B": GetKoreanFont(w, r, fea), - "K_Damage": GetKoreanCombatFont(w, r, fea), - "K_Pagetext": GetKoreanDisplayFont(w, r, fea), - }) - - makefile["rule"][pack] = { - "depend": [ "out/{}/Fonts/{}.ttf".format(target, f) for f in fontlist ], - "command": [ - "cd out/{};".format(target) + - "cp ../../LICENSE.txt Fonts/LICENSE.txt;" + - "7z a -t7z -m0=LZMA:d=512m:fb=273 -ms ../../$@ Fonts/" - ] - } - - for f, p in fontlist.items(): - makefile["rule"]["out/{}/Fonts/{}.ttf".format(target, f)] = { - "depend": [ "build/nowar/{}.otf".format(GenerateFilename(p)) ], - "command": [ - "mkdir -p out/{}/Fonts".format(target), - "cp $^ $@", - ] - } - - # Sans, UI - for f, w, wd, r, fea in product([ "Sans", "UI" ], config.fontPackWeight, [3, 5], regionNameMap.keys(), powerset(config.fontPackFeature)): - param = Namespace( - family = f, - weight = w, - width = wd, - region = r, - feature = fea, - encoding = "unspec", - ) - makefile["rule"]["build/nowar/{}.otf".format(GenerateFilename(param))] = { - "depend": ["build/nowar/{}.otd".format(GenerateFilename(param))], - "command": [ "otfccbuild -q -O3 --keep-average-char-width $< -o $@" ] - } - dep = ResolveDependency(param) - makefile["rule"]["build/nowar/{}.otd".format(GenerateFilename(param))] = { - "depend": [ - "build/roboto/{}.otd".format(GenerateFilename(dep["Latin"])), - "build/shs/{}.otd".format(GenerateFilename(dep["CJK"])), - ], - "command": [ - "mkdir -p build/nowar/", - "python merge.py {}".format(ParamToArgument(param)) - ] - } - makefile["rule"]["build/roboto/{}.otd".format(GenerateFilename(dep["Latin"]))] = { - "depend": [ "build/roboto/{}.otf".format(GenerateFilename(dep["Latin"])) ], - "command": [ "otfccdump --glyph-name-prefix latn --ignore-hints $< -o $@" ] - } - makefile["rule"]["build/roboto/{}.otf".format(GenerateFilename(dep["Latin"]))] = { - "depend": [ "source/roboto/{}.ttf".format(GenerateFilename(dep["Latin"])) ], - "command": [ - "mkdir -p build/roboto/", - "otfccdump --ignore-hints $< | otfcc-q2c | otfccbuild -q -O2 -o $@", - ] - } - makefile["rule"]["build/shs/{}.otd".format(GenerateFilename(dep["CJK"]))] = { - "depend": [ "source/shs/{}.otf".format(GenerateFilename(dep["CJK"])) ], - "command": [ - "mkdir -p build/shs/", - "otfccdump --glyph-name-prefix hani --ignore-hints $< -o $@", - ] - } - - # set encoding - for e in [ "gbk", "big5", "jis", "korean" ]: - enc = Namespace( - family = f, - weight = w, - width = wd, - region = r, - feature = fea, - encoding = e, - ) - makefile["rule"]["build/nowar/{}.otf".format(GenerateFilename(enc))] = { - "depend": ["build/nowar/{}.otd".format(GenerateFilename(enc))], - "command": [ "otfccbuild -q -O3 --keep-average-char-width $< -o $@" ] - } - makefile["rule"]["build/nowar/{}.otd".format(GenerateFilename(enc))] = { - "depend": ["build/nowar/{}.otd".format(GenerateFilename(param))], - "command": [ "python set-encoding.py {}".format(ParamToArgument(enc)) ] - } - - # WarcraftSans - for w, r, fea in product(config.fontPackWeight, regionNameMap.keys(), powerset(config.fontPackFeature)): - param = Namespace( - family = "WarcraftSans", - weight = w, - width = 5, - region = r, - feature = fea, - encoding = "unspec", - ) - - makefile["rule"]["build/nowar/{}.otf".format(GenerateFilename(param))] = { - "depend": ["build/nowar/{}.otd".format(GenerateFilename(param))], - "command": [ "otfccbuild -q -O3 --keep-average-char-width $< -o $@" ] - } - dep = ResolveDependency(param) - makefile["rule"]["build/nowar/{}.otd".format(GenerateFilename(param))] = { - "depend": [ - "build/roboto/{}.otd".format(GenerateFilename(dep["Latin"])), - "build/roboto/{}.otd".format(GenerateFilename(dep["Numeral"])), - "build/shs/{}.otd".format(GenerateFilename(dep["CJK"])), - ], - "command": [ - "mkdir -p build/nowar/", - "python merge.py {}".format(ParamToArgument(param)) - ] - } - makefile["rule"]["build/roboto/{}.otd".format(GenerateFilename(dep["Latin"]))] = { - "depend": [ "build/roboto/{}.otf".format(GenerateFilename(dep["Latin"])) ], - "command": [ "otfccdump --glyph-name-prefix latn --ignore-hints $< -o $@" ] - } - makefile["rule"]["build/roboto/{}.otf".format(GenerateFilename(dep["Latin"]))] = { - "depend": [ "source/roboto/{}.ttf".format(GenerateFilename(dep["Latin"])) ], - "command": [ - "mkdir -p build/roboto/", - "otfccdump --ignore-hints $< | otfcc-q2c | otfccbuild -q -O2 -o $@", - ] - } - makefile["rule"]["build/roboto/{}.otd".format(GenerateFilename(dep["Numeral"]))] = { - "depend": [ "build/roboto/{}.otf".format(GenerateFilename(dep["Numeral"])) ], - "command": [ "otfccdump --glyph-name-prefix latn --ignore-hints $< -o $@" ] - } - makefile["rule"]["build/roboto/{}.otf".format(GenerateFilename(dep["Numeral"]))] = { - "depend": [ "source/roboto/{}.ttf".format(GenerateFilename(dep["Numeral"])) ], - "command": [ - "mkdir -p build/roboto/", - "otfccdump --ignore-hints $< | otfcc-q2c | otfccbuild -q -O2 -o $@", - ] - } - makefile["rule"]["build/shs/{}.otd".format(GenerateFilename(dep["CJK"]))] = { - "depend": [ "source/shs/{}.otf".format(GenerateFilename(dep["CJK"])) ], - "command": [ - "mkdir -p build/shs/", - "otfccdump --glyph-name-prefix hani --ignore-hints $< -o $@", - ] - } - - for e in [ "gbk", "big5", "jis", "korean" ]: - enc = Namespace( - family = "WarcraftSans", - weight = w, - width = 5, - region = r, - feature = fea, - encoding = e, - ) - makefile["rule"]["build/nowar/{}.otf".format(GenerateFilename(enc))] = { - "depend": ["build/nowar/{}.otd".format(GenerateFilename(enc))], - "command": [ "otfccbuild -q -O3 --keep-average-char-width $< -o $@" ] - } - makefile["rule"]["build/nowar/{}.otd".format(GenerateFilename(enc))] = { - "depend": ["build/nowar/{}.otd".format(GenerateFilename(param))], - "command": [ "python set-encoding.py {}".format(ParamToArgument(enc)) ] - } - - # Latin - for w, wd, fea in product(config.fontPackWeight + [ morpheusWeightMap[w] for w in config.fontPackWeight ], [3, 5], powerset(config.fontPackFeature)): - param = Namespace( - family = "Latin", - weight = w, - width = wd, - feature = fea, - ) - makefile["rule"]["build/nowar/{}.otf".format(GenerateFilename(param))] = { - "depend": ["build/nowar/{}.otd".format(GenerateFilename(param))], - "command": [ "otfccbuild -q -O3 --keep-average-char-width $< -o $@" ] - } - dep = ResolveDependency(param) - makefile["rule"]["build/nowar/{}.otd".format(GenerateFilename(param))] = { - "depend": [ - "build/roboto/{}.otd".format(GenerateFilename(dep["Latin"])), - ], - "command": [ - "mkdir -p build/nowar/", - "python merge.py {}".format(ParamToArgument(param)) - ] - } - makefile["rule"]["build/roboto/{}.otd".format(GenerateFilename(dep["Latin"]))] = { - "depend": [ "build/roboto/{}.otf".format(GenerateFilename(dep["Latin"])) ], - "command": [ "otfccdump --glyph-name-prefix latn --ignore-hints $< -o $@" ] - } - makefile["rule"]["build/roboto/{}.otf".format(GenerateFilename(dep["Latin"]))] = { - "depend": [ "source/roboto/{}.ttf".format(GenerateFilename(dep["Latin"])) ], - "command": [ - "mkdir -p build/roboto/", - "otfccdump --ignore-hints $< | otfcc-q2c | otfccbuild -q -O2 -o $@", - ] - } - - # dump `makefile` dict to actual “GNU Makefile” - makedump = "" - - for var, val in makefile["variable"].items(): - makedump += "{}={}\n".format(var, val) - - for tar, recipe in makefile["rule"].items(): - dep = recipe["depend"] if "depend" in recipe else [] - makedump += "{}: {}\n".format(tar, " ".join(dep)) - com = recipe["command"] if "command" in recipe else [] - for c in com: - makedump += "\t{}\n".format(c) - - with codecs.open("Makefile", 'w', 'UTF-8') as mf: - mf.write(makedump) + makefile = { + "variable": { + "VERSION": config.version, + }, + "rule": { + ".PHONY": { + "depend": ["all"], + }, + "all": { + "depend": [], + }, + "clean": { + "command": [ + "-rm -rf build/", + "-rm -rf out/??*-???/", + ] + } + }, + } + + def powerset(lst): return reduce(lambda result, x: result + + [subset + [x] for subset in result], lst, [[]]) + + # font pack for each regional variant and weight + for r, w, fea in product(config.fontPackRegion, config.fontPackWeight, powerset(config.fontPackFeature)): + tagList = [r] + fea + target = "{}-{}".format(TagListToStr(tagList), w) + pack = "out/NowarNeoSans-{}-${{VERSION}}.7z".format(target) + + makefile["rule"][".PHONY"]["depend"].append(target) + makefile["rule"][target] = { + "depend": [pack], + } + + if fea == [] or (r, fea) in config.fontPackExportFeature: + makefile["rule"]["all"]["depend"].append(pack) + + fontlist = { + "ARIALN": GetCommonChatFont(w, r, fea), + "FRIZQT__": GetCommonFont(w, r, fea), + } + + if regionalVariant[r]["enUS"]: + fontlist.update({ + "skurri": GetLatinFont(w, r, fea), + "MORPHEUS": GetLatinChatFont(w, r, fea), + }) + + if regionalVariant[r]["ruRU"]: + fontlist.update({ + "FRIZQT___CYR": GetLatinFont(w, r, fea), + "SKURRI_CYR": GetLatinFont(w, r, fea), + "MORPHEUS_CYR": GetLatinChatFont(w, r, fea), + }) + + if regionalVariant[r]["zhCN"]: + fontlist.update({ + "ARKai_C": GetHansCombatFont(w, r, fea), + "ARKai_T": GetHansFont(w, r, fea), + "ARHei": GetHansChatFont(w, r, fea), + }) + + if regionalVariant[r]["zhTW"]: + fontlist.update({ + "arheiuhk_bd": GetHantChatFont(w, r, fea), + "bHEI00M": GetHantNoteFont(w, r, fea), + "bHEI01B": GetHantChatFont(w, r, fea), + "bKAI00M": GetHantCombatFont(w, r, fea), + "blei00d": GetHantFont(w, r, fea), + }) + + if regionalVariant[r]["koKR"]: + fontlist.update({ + "2002": GetKoreanFont(w, r, fea), + "2002B": GetKoreanFont(w, r, fea), + "K_Damage": GetKoreanCombatFont(w, r, fea), + "K_Pagetext": GetKoreanDisplayFont(w, r, fea), + }) + + makefile["rule"][pack] = { + "depend": ["out/{}/Fonts/{}.ttf".format(target, f) for f in fontlist], + "command": [ + "cd out/{};".format(target) + + "cp ../../LICENSE.txt Fonts/LICENSE.txt;" + + "7z a -t7z -m0=LZMA:d=512m:fb=273 -ms ../../$@ Fonts/" + ] + } + + for f, p in fontlist.items(): + makefile["rule"]["out/{}/Fonts/{}.ttf".format(target, f)] = { + "depend": ["build/nowar/{}.otf".format(GenerateFilename(p))], + "command": [ + "mkdir -p out/{}/Fonts".format(target), + "cp $^ $@", + ] + } + + # otf files + for w, wd, r, fea in product(config.fontPackWeight, [3, 5, 10], regionNameMap.keys(), powerset(featureNameMap.keys())): + param = { + "family": "Nowar", + "weight": w, + "width": wd, + "region": r, + "feature": fea, + "encoding": "unspec", + } + makefile["rule"]["build/nowar/{}.otf".format(GenerateFilename(param))] = { + "depend": ["build/nowar/{}.otd".format(GenerateFilename(param))], + "command": ["otfccbuild -q -O3 --keep-average-char-width $< -o $@"] + } + dep = ResolveDependency(param) + makefile["rule"]["build/nowar/{}.otd".format(GenerateFilename(param))] = { + "depend": [ + "build/roboto/{}.otd".format(GenerateFilename(dep["Latin"])), + "build/shs/{}.otd".format( + GenerateFilename(dep["CJK"])), + ] + ([ + "build/roboto/{}.otd".format( + GenerateFilename(dep["Numeral"])) + ] if "Numeral" in dep else []), + "command": [ + "mkdir -p build/nowar/", + "python merge.py {}".format(ParamToArgument(param)) + ] + } + makefile["rule"]["build/roboto/{}.otd".format(GenerateFilename(dep["Latin"]))] = { + "depend": ["build/roboto/{}.otf".format(GenerateFilename(dep["Latin"]))], + "command": [ + "otfccdump --glyph-name-prefix latn --ignore-hints $< -o $@", + ] + } + makefile["rule"]["build/roboto/{}.otf".format(GenerateFilename(dep["Latin"]))] = { + "depend": ["source/roboto/{}.ttf".format(GenerateFilename(dep["Latin"]))], + "command": [ + "mkdir -p build/roboto/", + "otfccdump --ignore-hints $< | otfcc-q2c | otfccbuild -q -O2 -o $@", + ] + } + if "Numeral" in dep: + makefile["rule"]["build/roboto/{}.otd".format(GenerateFilename(dep["Numeral"]))] = { + "depend": ["build/roboto/{}.otf".format(GenerateFilename(dep["Numeral"]))], + "command": [ + "otfccdump --glyph-name-prefix latn --ignore-hints $< -o $@", + ] + } + makefile["rule"]["build/roboto/{}.otf".format(GenerateFilename(dep["Numeral"]))] = { + "depend": ["source/roboto/{}.ttf".format(GenerateFilename(dep["Numeral"]))], + "command": [ + "mkdir -p build/roboto/", + "otfccdump --ignore-hints $< | otfcc-q2c | otfccbuild -q -O2 -o $@", + ] + } + makefile["rule"]["build/shs/{}.otd".format(GenerateFilename(dep["CJK"]))] = { + "depend": ["source/shs/{}.otf".format(GenerateFilename(dep["CJK"]))], + "command": [ + "mkdir -p build/shs/", + "otfccdump --glyph-name-prefix hani --ignore-hints $< -o $@", + ] + } + + # set encoding + for e in ["gbk", "big5", "jis", "korean"]: + enc = { + "family": "Nowar", + "weight": w, + "width": wd, + "region": r, + "feature": fea, + "encoding": e, + } + makefile["rule"]["build/nowar/{}.otf".format(GenerateFilename(enc))] = { + "depend": ["build/nowar/{}.otd".format(GenerateFilename(enc))], + "command": ["otfccbuild -q -O3 --keep-average-char-width $< -o $@"] + } + makefile["rule"]["build/nowar/{}.otd".format(GenerateFilename(enc))] = { + "depend": ["build/nowar/{}.otd".format(GenerateFilename(param))], + "command": ["python set-encoding.py {}".format(ParamToArgument(enc))] + } + + # dump `makefile` dict to actual “GNU Makefile” + makedump = "" + + for var, val in makefile["variable"].items(): + makedump += "{}={}\n".format(var, val) + + for tar, recipe in makefile["rule"].items(): + dep = recipe["depend"] if "depend" in recipe else [] + makedump += "{}: {}\n".format(tar, " ".join(dep)) + com = recipe["command"] if "command" in recipe else [] + for c in com: + makedump += "\t{}\n".format(c) + + with codecs.open("Makefile", 'w', 'UTF-8') as mf: + mf.write(makedump) diff --git a/libotd b/libotd index 3a43b5f..797473a 160000 --- a/libotd +++ b/libotd @@ -1 +1 @@ -Subproject commit 3a43b5f76564e49898b0c22a79cfd45a239d3e37 +Subproject commit 797473a4f3d5501709ce7dcf16af188c785e6302 diff --git a/merge.py b/merge.py index da5408f..1445534 100644 --- a/merge.py +++ b/merge.py @@ -1,267 +1,331 @@ +import datetime import sys import copy import json import codecs -from types import SimpleNamespace as Namespace from libotd.rebase import Rebase +from libotd.dereference import Dereference from libotd.merge import MergeBelow, MergeAbove from libotd.pkana import ApplyPalt, NowarApplyPaltMultiplied from libotd.transform import Transform, ChangeAdvanceWidth from libotd.gsub import GetGsubFlat, ApplyGsubSingle -from libotd.gc import Gc, NowarRemoveFeatures +from libotd.gc import Gc, Consolidate, NowarRemoveFeatures import configure -langIdList = [ 0x0409, 0x0804, 0x0404, 0x0C04, 0x0411, 0x0412 ] def NameFont(param, font): - family = configure.GenerateFamily(param) - subfamily = configure.GenerateSubfamily(param) - friendly = configure.GenerateFriendlyFamily(param) - legacyf, legacysubf = configure.GenerateLegacySubfamily(param) + fontName = configure.GenerateFontName(param) + family, subfamily = fontName["typographic"] + wwsF, wwsSf = fontName["wws"] + legacyF, legacySf = fontName["legacy"] + friendly = fontName["friendly"] + postscript = fontName["postscript"] + enUS = configure.LanguageId.enUS - font['head']['fontRevision'] = configure.config.fontRevision - font['OS_2']['achVendID'] = configure.config.vendorId - font['OS_2']['usWeightClass'] = param.weight - font['OS_2']['usWidthClass'] = param.width - font['name'] = [ - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 0, - "nameString": configure.config.copyright - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 2, - "nameString": legacysubf - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 3, - "nameString": "{} {}".format(friendly[1033], configure.config.version) - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 5, - "nameString": configure.config.version - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 6, - "nameString": friendly[1033].replace(" ", "-") - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 8, - "nameString": configure.config.vendor - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 9, - "nameString": configure.config.designer - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 11, - "nameString": configure.config.vendorUrl - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 12, - "nameString": configure.config.designerUrl - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 13, - "nameString": configure.config.license - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 14, - "nameString": configure.config.licenseUrl - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": 1033, - "nameID": 17, - "nameString": subfamily - }, - ] + sum( - [[ - { - "platformID": 3, - "encodingID": 1, - "languageID": langId, - "nameID": 1, - "nameString": "{} {}".format(family[langId], legacyf).strip() - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": langId, - "nameID": 4, - "nameString": friendly[langId] - }, - { - "platformID": 3, - "encodingID": 1, - "languageID": langId, - "nameID": 16, - "nameString": family[langId] - }, - ] for langId in langIdList], - [] - ) + os_2 = font["OS_2"] + fsSelection = os_2["fsSelection"] + head = font["head"] + macStyle = font["head"]["macStyle"] + weight = param["weight"] + width = param["width"] + slant = param.get("slant") + + head['fontRevision'] = configure.config.fontRevision + os_2['achVendID'] = configure.config.vendorId + os_2['usWeightClass'] = weight + # Warcraft numeral hack + os_2['usWidthClass'] = 5 if width == 10 else width + fsSelection["wws"] = False + + fsSelection["regular"] = (weight == 400) and (not slant) and (width == 5) + if weight == 700: + fsSelection["bold"] = True + macStyle["bold"] = True + if slant == "Italic": + fsSelection["italic"] = True + macStyle["italic"] = True + elif slant == "Oblique": + fsSelection["oblique"] = True + + font['name'] = [ + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 0, + "nameString": configure.config.copyright + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 2, + "nameString": legacySf + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 3, + "nameString": "{}: {} {}".format(configure.config.vendorId, friendly[enUS], configure.config.version) + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 5, + "nameString": configure.config.version + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 6, + "nameString": postscript + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 8, + "nameString": configure.config.vendor + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 9, + "nameString": configure.config.designer + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 11, + "nameString": configure.config.vendorUrl + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 12, + "nameString": configure.config.designerUrl + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 13, + "nameString": configure.config.license + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 14, + "nameString": configure.config.licenseUrl + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 17, + "nameString": subfamily + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": enUS, + "nameID": 22, + "nameString": wwsSf + }, + ] + sum( + [[ + { + "platformID": 3, + "encodingID": 1, + "languageID": langId, + "nameID": 1, + "nameString": legacyF[langId] + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": langId, + "nameID": 4, + "nameString": friendly[langId] + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": langId, + "nameID": 16, + "nameString": family[langId] + }, + { + "platformID": 3, + "encodingID": 1, + "languageID": langId, + "nameID": 21, + "nameString": wwsF[langId] + }, + ] for langId in configure.LanguageId], + [] + ) + + if 'CFF_' in font: + cff = font['CFF_'] + cff['version'] = configure.config.version + if 'notice' in cff: + del cff['notice'] + cff['copyright'] = configure.config.copyright + cff['fontName'] = postscript + cff['fullName'] = friendly[enUS] + cff['familyName'] = family[enUS] + cff['weight'] = subfamily - if 'CFF_' in font: - cff = font['CFF_'] - cff['version'] = configure.config.version - if 'notice' in cff: - del cff['notice'] - cff['copyright'] = configure.config.copyright - cff['fontName'] = friendly[1033].replace(" ", "-") - cff['fullName'] = friendly[1033] - cff['familyName'] = family[1033] - cff['weight'] = subfamily def GenerateAsianSymbolFont(font): - asianSymbol = [ - 0x00B7, # MIDDLE DOT - 0x2014, # EM DASH - 0x2015, # HORIZONTAL BAR - 0x2018, # LEFT SINGLE QUOTATION MARK - 0x2019, # RIGHT SINGLE QUOTATION MARK - 0x201C, # LEFT DOUBLE QUOTATION MARK - 0x201D, # RIGHT DOUBLE QUOTATION MARK - 0x2026, # HORIZONTAL ELLIPSIS - 0x2027, # HYPHENATION POINT - 0x2E3A, # TWO-EM DASH - 0x2E3B, # THREE-EM DASH - ] - font = copy.deepcopy(font) - if 'cmap_uvs' in font: - del font['cmap_uvs'] - rm = [] - for k in font['cmap']: - if int(k) not in asianSymbol: - rm.append(k) - for k in rm: - del font['cmap'][k] - NowarRemoveFeatures(font) - Gc(font) - return font + asianSymbol = [ + 0x00B7, # MIDDLE DOT + 0x2014, # EM DASH + 0x2015, # HORIZONTAL BAR + 0x2018, # LEFT SINGLE QUOTATION MARK + 0x2019, # RIGHT SINGLE QUOTATION MARK + 0x201C, # LEFT DOUBLE QUOTATION MARK + 0x201D, # RIGHT DOUBLE QUOTATION MARK + 0x2026, # HORIZONTAL ELLIPSIS + 0x2027, # HYPHENATION POINT + 0x2E3A, # TWO-EM DASH + 0x2E3B, # THREE-EM DASH + ] + symbolFont = {} + symbolFont["cmap"] = {k: v for k, + v in font["cmap"].items() if int(k) in asianSymbol} + glyphSet = {symbolFont["cmap"].values()} + symbolFont["glyf"] = {k: v for k, + v in font["glyf"].items() if k in glyphSet} + symbolFont["glyph_order"] = ["symb.notdef"] + return symbolFont + + +def Simplify(font): + from opencc_t2s import OpenCC_T2S + cmap = asianFont['cmap'] + for t, s in OpenCC_T2S.items(): + us = str(ord(s)) + if us in cmap: + ut = str(ord(t)) + cmap[ut] = cmap[us] + if __name__ == '__main__': - param = sys.argv[1] - param = Namespace(**json.loads(param)) + param = sys.argv[1] + param = json.loads(param) + + dep = configure.ResolveDependency(param) + + with open("build/roboto/{}.otd".format(configure.GenerateFilename(dep['Latin'])), 'rb') as baseFile: + baseFont = json.loads( + baseFile.read().decode('UTF-8', errors='replace')) + upm = baseFont["head"]["unitsPerEm"] + if (upm != 1000): + Rebase(baseFont, 1000 / upm, roundToInt=True) + NameFont(param, baseFont) - dep = configure.ResolveDependency(param) + hhea = baseFont["hhea"] + os_2 = baseFont["OS_2"] + if os_2["version"] < 4: + os_2["version"] = 4 + hhea['ascender'] = 880 + hhea['descender'] = -120 + hhea['lineGap'] = 200 + os_2['sTypoAscender'] = 880 + os_2['sTypoDescender'] = -120 + os_2['sTypoLineGap'] = 200 + os_2['fsSelection']['useTypoMetrics'] = True + os_2['usWinAscent'] = 1050 + os_2['usWinDescent'] = 300 - with open("build/roboto/{}.otd".format(configure.GenerateFilename(dep['Latin'])), 'rb') as baseFile: - baseFont = json.loads(baseFile.read().decode('UTF-8', errors='replace')) - Rebase(baseFont, 1000 / 2048, roundToInt = True) - NameFont(param, baseFont) + # oldstyle figure + if "OSF" in param["feature"]: + ApplyGsubSingle('pnum', baseFont) + ApplyGsubSingle('onum', baseFont) - baseFont['hhea']['ascender'] = 880 - baseFont['hhea']['descender'] = -120 - baseFont['hhea']['lineGap'] = 200 - baseFont['OS_2']['sTypoAscender'] = 880 - baseFont['OS_2']['sTypoDescender'] = -120 - baseFont['OS_2']['sTypoLineGap'] = 200 - baseFont['OS_2']['fsSelection']['useTypoMetrics'] = True - baseFont['OS_2']['usWinAscent'] = 1050 - baseFont['OS_2']['usWinDescent'] = 300 + # small caps + if "SC" in param["feature"]: + ApplyGsubSingle('smcp', baseFont) - # oldstyle figure - if "OSF" in param.feature: - ApplyGsubSingle('pnum', baseFont) - ApplyGsubSingle('onum', baseFont) + # Warcraft numeral hack + if param["width"] == 10: + with open("build/roboto/{}.otd".format(configure.GenerateFilename(dep['Numeral'])), 'rb') as numFile: + numFont = json.loads( + numFile.read().decode('UTF-8', errors='replace')) + if (upm != 1000): + Rebase(numFont, 1000 / upm, roundToInt=True) - # small caps - if "SC" in param.feature: - ApplyGsubSingle('smcp', baseFont) + gsubPnum = GetGsubFlat('pnum', numFont) + gsubTnum = GetGsubFlat('tnum', numFont) + gsubOnum = GetGsubFlat('onum', numFont) - # replace numerals - if param.family in [ "WarcraftSans", "WarcraftUI" ]: - with open("build/roboto/{}.otd".format(configure.GenerateFilename(dep['Numeral'])), 'rb') as numFile: - numFont = json.loads(numFile.read().decode('UTF-8', errors='replace')) - Rebase(numFont, 1000 / 2048, roundToInt = True) + num = [numFont['cmap'][str(ord('0') + i)] for i in range(10)] + pnum = [gsubPnum[n] for n in num] + onum = [gsubOnum[n] for n in pnum] + tonum = [gsubOnum[n] for n in num] - gsubPnum = GetGsubFlat('pnum', numFont) - gsubTnum = GetGsubFlat('tnum', numFont) - gsubOnum = GetGsubFlat('onum', numFont) + maxWidth = 490 + numWidth = numFont['glyf'][num[0]]['advanceWidth'] + changeWidth = maxWidth - numWidth if numWidth > maxWidth else 0 - num = [ numFont['cmap'][str(ord('0') + i)] for i in range(10) ] - pnum = [ gsubPnum[n] for n in num ] - onum = [ gsubOnum[n] for n in pnum ] - tonum = [ gsubOnum[n] for n in num ] + # dereference TT glyphs + if "CFF_" not in numFont: + for n in num + pnum + onum + tonum: + numFont['glyf'][n] = Dereference( + numFont['glyf'][n], numFont) - maxWidth = 490 - numWidth = numFont['glyf'][num[0]]['advanceWidth'] - changeWidth = maxWidth - numWidth if numWidth > maxWidth else 0 + for n in num + tonum: + tGlyph = numFont['glyf'][n] + tWidth = tGlyph['advanceWidth'] + pName = gsubPnum[n] + pGlyph = numFont['glyf'][pName] + pWidth = pGlyph['advanceWidth'] + if pWidth > tWidth: + numFont['glyf'][pName] = copy.deepcopy(tGlyph) + pGlyph = numFont['glyf'][pName] + pWidth = tWidth + if changeWidth != 0: + ChangeAdvanceWidth(pGlyph, changeWidth) + Transform(pGlyph, 1, 0, 0, 1, (changeWidth + 1) // 2, 0) - for n in num + tonum: - tGlyph = numFont['glyf'][n] - tWidth = tGlyph['advanceWidth'] - pName = gsubPnum[n] - pGlyph = numFont['glyf'][pName] - pWidth = pGlyph['advanceWidth'] - if pWidth > tWidth: - numFont['glyf'][pName] = copy.deepcopy(tGlyph) - pGlyph = numFont['glyf'][pName] - pWidth = tWidth - if changeWidth != 0: - ChangeAdvanceWidth(pGlyph, changeWidth) - Transform(pGlyph, 1, 0, 0, 1, (changeWidth + 1) // 2, 0) + for n in num + pnum + onum + tonum: + baseFont['glyf'][n] = numFont['glyf'][n] + ApplyGsubSingle('pnum', baseFont) - for n in num + pnum + onum + tonum: - baseFont['glyf'][n] = numFont['glyf'][n] - ApplyGsubSingle('pnum', baseFont) + with open("build/shs/{}.otd".format(configure.GenerateFilename(dep['CJK'])), 'rb') as asianFile: + asianFont = json.loads( + asianFile.read().decode('UTF-8', errors='replace')) - # merge CJK - if param.family in [ "Sans", "UI", "WarcraftSans", "WarcraftUI" ]: - with open("build/shs/{}.otd".format(configure.GenerateFilename(dep['CJK'])), 'rb') as asianFile: - asianFont = json.loads(asianFile.read().decode('UTF-8', errors = 'replace')) + # pre-apply `palt` in UI family + if "UI" in param["feature"]: + ApplyPalt(asianFont) + else: + NowarApplyPaltMultiplied(asianFont, 0.4) + asianSymbolFont = GenerateAsianSymbolFont(asianFont) + MergeAbove(baseFont, asianSymbolFont) - # pre-apply `palt` in UI family - if "UI" in param.family: - ApplyPalt(asianFont) - else: - NowarApplyPaltMultiplied(asianFont, 0.4) - asianSymbolFont = GenerateAsianSymbolFont(asianFont) - MergeAbove(baseFont, asianSymbolFont) + # pseudo-simplified font + if "Simp" in param["feature"]: + Simplify(asianFont) - NowarRemoveFeatures(asianFont) - Gc(asianFont) - MergeBelow(baseFont, asianFont) + NowarRemoveFeatures(asianFont) + MergeBelow(baseFont, asianFont) - # remap `丶` to `·` in RP variant - if "RP" in param.feature: - baseFont['cmap'][str(ord('丶'))] = baseFont['cmap'][str(ord('·'))] - Gc(baseFont) + # remap `丶` to `·` in RP variant + if "RP" in param["feature"]: + baseFont['cmap'][str(ord('丶'))] = baseFont['cmap'][str(ord('·'))] - outStr = json.dumps(baseFont, ensure_ascii=False, separators=(',',':')) - with codecs.open("build/nowar/{}.otd".format(configure.GenerateFilename(param)), 'w', 'UTF-8') as outFile: - outFile.write(outStr) + Gc(baseFont) + Consolidate(baseFont) + outStr = json.dumps(baseFont, ensure_ascii=False, separators=(',', ':')) + with codecs.open("build/nowar/{}.otd".format(configure.GenerateFilename(param)), 'w', 'UTF-8') as outFile: + outFile.write(outStr) diff --git a/opencc_t2s.py b/opencc_t2s.py new file mode 100644 index 0000000..0b2c906 --- /dev/null +++ b/opencc_t2s.py @@ -0,0 +1,4030 @@ +OpenCC_T2S = { + "㑮": "𫝈", + "㑯": "㑔", + "㑳": "㑇", + "㑶": "㐹", + "㒓": "𠉂", + "㓄": "𪠟", + "㓨": "刾", + "㔋": "𪟎", + "㖮": "𪠵", + "㗲": "𠵾", + "㗿": "𪡛", + "㘉": "𠰱", + "㘓": "𪢌", + "㘔": "㗷", + "㘚": "㘎", + "㛝": "𫝦", + "㜄": "㚯", + "㜏": "㛣", + "㜐": "𫝧", + "㜗": "𡞋", + "㜢": "𡞱", + "㜷": "𡝠", + "㞞": "𪨊", + "㟺": "𪩇", + "㠏": "㟆", + "㢗": "𪪑", + "㢝": "𢋈", + "㥮": "㤘", + "㦎": "𢛯", + "㦛": "𢗓", + "㦞": "𪫷", + "㨻": "𪮃", + "㩋": "𪮋", + "㩜": "㨫", + "㩳": "㧐", + "㩵": "擜", + "㪎": "𪯋", + "㯤": "𣘐", + "㰙": "𣗙", + "㵗": "𣳆", + "㵾": "𪷍", + "㶆": "𫞛", + "㷍": "𤆢", + "㷿": "𤈷", + "㸇": "𤎺", + "㹽": "𫞣", + "㺏": "𤠋", + "㺜": "𪺻", + "㻶": "𪼋", + "㿖": "𪽮", + "㿗": "𤻊", + "㿧": "𤽯", + "䀉": "𥁢", + "䀹": "𥅴", + "䁪": "𥇢", + "䁻": "䀥", + "䂎": "𥎝", + "䃮": "鿎", + "䅐": "𫀨", + "䅳": "𫀬", + "䆉": "𫁂", + "䉑": "𫁲", + "䉙": "𥬀", + "䉬": "𫂈", + "䉲": "𥮜", + "䉶": "𫁷", + "䊭": "𥺅", + "䊷": "䌶", + "䊺": "𫄚", + "䋃": "𫄜", + "䋔": "𫄞", + "䋙": "䌺", + "䋚": "䌻", + "䋦": "𫄩", + "䋹": "䌿", + "䋻": "䌾", + "䋼": "𫄮", + "䋿": "𦈓", + "䌈": "𦈖", + "䌋": "𦈘", + "䌖": "𦈜", + "䌝": "𦈟", + "䌟": "𦈞", + "䌥": "𦈠", + "䌰": "𦈙", + "䍤": "𫅅", + "䍦": "䍠", + "䍽": "𦍠", + "䎙": "𫅭", + "䎱": "䎬", + "䕤": "𫟕", + "䕳": "𦰴", + "䖅": "𫟑", + "䗅": "𫊪", + "䗿": "𧉞", + "䙔": "𫋲", + "䙡": "䙌", + "䙱": "𧜭", + "䚩": "𫌯", + "䛄": "𫍠", + "䛳": "𫍫", + "䜀": "䜧", + "䜖": "𫟢", + "䝭": "𫎧", + "䝻": "𧹕", + "䝼": "䞍", + "䞈": "𧹑", + "䞋": "𫎪", + "䞓": "𫎭", + "䟃": "𫎺", + "䟆": "𫎳", + "䟐": "𫎱", + "䠆": "𫏃", + "䠱": "𨅛", + "䡐": "𫟤", + "䡩": "𫟥", + "䡵": "𫟦", + "䢨": "𨑹", + "䤤": "𫟺", + "䥄": "𫠀", + "䥇": "䦂", + "䥑": "鿏", + "䥗": "𫔋", + "䥩": "𨱖", + "䥯": "𫔆", + "䥱": "䥾", + "䦘": "𨸄", + "䦛": "䦶", + "䦟": "䦷", + "䦯": "𫔵", + "䦳": "𨷿", + "䧢": "𨸟", + "䪊": "𫖅", + "䪏": "𩏼", + "䪗": "𩐀", + "䪘": "𩏿", + "䪴": "𫖫", + "䪾": "𫖬", + "䫀": "𫖱", + "䫂": "𫖰", + "䫟": "𫖲", + "䫴": "𩖗", + "䫶": "𫖺", + "䫻": "𫗇", + "䫾": "𫠈", + "䬓": "𫗊", + "䬘": "𩙮", + "䬝": "𩙯", + "䬞": "𩙧", + "䬧": "𫗟", + "䭀": "𩠇", + "䭃": "𩠈", + "䭑": "𫗱", + "䭔": "𫗰", + "䭿": "𩧭", + "䮄": "𫠊", + "䮝": "𩧰", + "䮞": "𩨁", + "䮠": "𩧿", + "䮫": "𩨇", + "䮰": "𫘮", + "䮳": "𩨏", + "䮾": "𩧪", + "䯀": "䯅", + "䯤": "𩩈", + "䰾": "鲃", + "䱀": "𫚐", + "䱁": "𫚏", + "䱙": "𩾈", + "䱧": "𫚠", + "䱬": "𩾊", + "䱰": "𩾋", + "䱷": "䲣", + "䱸": "𫠑", + "䱽": "䲝", + "䲁": "鳚", + "䲅": "𫚜", + "䲖": "𩾂", + "䲘": "鳤", + "䲰": "𪉂", + "䳜": "𫛬", + "䳢": "𫛰", + "䳤": "𫛮", + "䳧": "𫛺", + "䳫": "𫛼", + "䴉": "鹮", + "䴋": "𫜅", + "䴬": "𪎈", + "䴱": "𫜒", + "䴴": "𪎋", + "䴽": "𫜔", + "䵳": "𪑅", + "䵴": "𫜙", + "䶕": "𫜨", + "䶲": "𫜳", + "丟": "丢", + "並": "并", + "乾": "干", + "亂": "乱", + "亙": "亘", + "亞": "亚", + "佇": "伫", + "佈": "布", + "佔": "占", + "併": "并", + "來": "来", + "侖": "仑", + "侶": "侣", + "侷": "局", + "俁": "俣", + "係": "系", + "俓": "𠇹", + "俔": "伣", + "俠": "侠", + "俥": "伡", + "俬": "私", + "倀": "伥", + "倆": "俩", + "倈": "俫", + "倉": "仓", + "個": "个", + "們": "们", + "倖": "幸", + "倫": "伦", + "倲": "㑈", + "偉": "伟", + "偑": "㐽", + "側": "侧", + "偵": "侦", + "偽": "伪", + "傌": "㐷", + "傑": "杰", + "傖": "伧", + "傘": "伞", + "備": "备", + "傢": "家", + "傭": "佣", + "傯": "偬", + "傳": "传", + "傴": "伛", + "債": "债", + "傷": "伤", + "傾": "倾", + "僂": "偻", + "僅": "仅", + "僉": "佥", + "僑": "侨", + "僕": "仆", + "僞": "伪", + "僥": "侥", + "僨": "偾", + "僱": "雇", + "價": "价", + "儀": "仪", + "儁": "俊", + "儂": "侬", + "億": "亿", + "儈": "侩", + "儉": "俭", + "儎": "傤", + "儐": "傧", + "儔": "俦", + "儕": "侪", + "儘": "尽", + "償": "偿", + "儣": "𠆲", + "優": "优", + "儭": "𠋆", + "儲": "储", + "儷": "俪", + "儸": "㑩", + "儺": "傩", + "儻": "傥", + "儼": "俨", + "兇": "凶", + "兌": "兑", + "兒": "儿", + "兗": "兖", + "內": "内", + "兩": "两", + "冊": "册", + "冑": "胄", + "冪": "幂", + "凈": "净", + "凍": "冻", + "凙": "𪞝", + "凜": "凛", + "凱": "凯", + "別": "别", + "刪": "删", + "剄": "刭", + "則": "则", + "剋": "克", + "剎": "刹", + "剗": "刬", + "剛": "刚", + "剝": "剥", + "剮": "剐", + "剴": "剀", + "創": "创", + "剷": "铲", + "剾": "𠛅", + "劃": "划", + "劇": "剧", + "劉": "刘", + "劊": "刽", + "劌": "刿", + "劍": "剑", + "劏": "㓥", + "劑": "剂", + "劚": "㔉", + "勁": "劲", + "勑": "𠡠", + "動": "动", + "務": "务", + "勛": "勋", + "勝": "胜", + "勞": "劳", + "勢": "势", + "勣": "𪟝", + "勩": "勚", + "勱": "劢", + "勳": "勋", + "勵": "励", + "勸": "劝", + "勻": "匀", + "匭": "匦", + "匯": "汇", + "匱": "匮", + "區": "区", + "協": "协", + "卹": "恤", + "卻": "却", + "卽": "即", + "厙": "厍", + "厠": "厕", + "厤": "历", + "厭": "厌", + "厲": "厉", + "厴": "厣", + "參": "参", + "叄": "叁", + "叢": "丛", + "吒": "咤", + "吳": "吴", + "吶": "呐", + "呂": "吕", + "咼": "呙", + "員": "员", + "哯": "𠯟", + "唄": "呗", + "唓": "𪠳", + "唚": "吣", + "唸": "念", + "問": "问", + "啓": "启", + "啞": "哑", + "啟": "启", + "啢": "唡", + "喎": "㖞", + "喚": "唤", + "喪": "丧", + "喫": "吃", + "喬": "乔", + "單": "单", + "喲": "哟", + "嗆": "呛", + "嗇": "啬", + "嗊": "唝", + "嗎": "吗", + "嗚": "呜", + "嗩": "唢", + "嗰": "𠮶", + "嗶": "哔", + "嗹": "𪡏", + "嘆": "叹", + "嘍": "喽", + "嘓": "啯", + "嘔": "呕", + "嘖": "啧", + "嘗": "尝", + "嘜": "唛", + "嘩": "哗", + "嘪": "𪡃", + "嘮": "唠", + "嘯": "啸", + "嘰": "叽", + "嘳": "𪡞", + "嘵": "哓", + "嘸": "呒", + "嘺": "𪡀", + "嘽": "啴", + "噁": "恶", + "噅": "𠯠", + "噓": "嘘", + "噚": "㖊", + "噝": "咝", + "噞": "𪡋", + "噠": "哒", + "噥": "哝", + "噦": "哕", + "噯": "嗳", + "噲": "哙", + "噴": "喷", + "噸": "吨", + "噹": "当", + "嚀": "咛", + "嚇": "吓", + "嚌": "哜", + "嚐": "尝", + "嚕": "噜", + "嚙": "啮", + "嚛": "𪠸", + "嚥": "咽", + "嚦": "呖", + "嚧": "𠰷", + "嚨": "咙", + "嚮": "向", + "嚲": "亸", + "嚳": "喾", + "嚴": "严", + "嚶": "嘤", + "嚽": "𪢕", + "囀": "啭", + "囁": "嗫", + "囂": "嚣", + "囃": "𠱞", + "囅": "冁", + "囈": "呓", + "囉": "啰", + "囌": "苏", + "囑": "嘱", + "囒": "𪢠", + "囪": "囱", + "圇": "囵", + "國": "国", + "圍": "围", + "園": "园", + "圓": "圆", + "圖": "图", + "團": "团", + "圞": "𪢮", + "垵": "埯", + "埡": "垭", + "埬": "𪣆", + "埰": "采", + "執": "执", + "堅": "坚", + "堊": "垩", + "堖": "垴", + "堚": "𪣒", + "堝": "埚", + "堯": "尧", + "報": "报", + "場": "场", + "塊": "块", + "塋": "茔", + "塏": "垲", + "塒": "埘", + "塗": "涂", + "塚": "冢", + "塢": "坞", + "塤": "埙", + "塵": "尘", + "塹": "堑", + "塿": "𪣻", + "墊": "垫", + "墜": "坠", + "墮": "堕", + "墰": "坛", + "墲": "𪢸", + "墳": "坟", + "墶": "垯", + "墻": "墙", + "墾": "垦", + "壇": "坛", + "壈": "𡒄", + "壋": "垱", + "壎": "埙", + "壓": "压", + "壗": "𡋤", + "壘": "垒", + "壙": "圹", + "壚": "垆", + "壜": "坛", + "壞": "坏", + "壟": "垄", + "壠": "垅", + "壢": "坜", + "壣": "𪤚", + "壩": "坝", + "壪": "塆", + "壯": "壮", + "壺": "壶", + "壼": "壸", + "壽": "寿", + "夠": "够", + "夢": "梦", + "夥": "伙", + "夾": "夹", + "奐": "奂", + "奧": "奥", + "奩": "奁", + "奪": "夺", + "奬": "奖", + "奮": "奋", + "奼": "姹", + "妝": "妆", + "姍": "姗", + "姦": "奸", + "娛": "娱", + "婁": "娄", + "婡": "𫝫", + "婦": "妇", + "婭": "娅", + "媈": "𫝨", + "媧": "娲", + "媯": "妫", + "媰": "㛀", + "媼": "媪", + "媽": "妈", + "嫋": "袅", + "嫗": "妪", + "嫵": "妩", + "嫺": "娴", + "嫻": "娴", + "嫿": "婳", + "嬀": "妫", + "嬃": "媭", + "嬇": "𫝬", + "嬈": "娆", + "嬋": "婵", + "嬌": "娇", + "嬙": "嫱", + "嬡": "嫒", + "嬣": "𪥰", + "嬤": "嬷", + "嬦": "𫝩", + "嬪": "嫔", + "嬰": "婴", + "嬸": "婶", + "嬻": "𪥿", + "孃": "娘", + "孄": "𫝮", + "孆": "𫝭", + "孇": "𪥫", + "孋": "㛤", + "孌": "娈", + "孎": "𡠟", + "孫": "孙", + "學": "学", + "孻": "𡥧", + "孾": "𪧀", + "孿": "孪", + "宮": "宫", + "寀": "采", + "寠": "𪧘", + "寢": "寝", + "實": "实", + "寧": "宁", + "審": "审", + "寫": "写", + "寬": "宽", + "寵": "宠", + "寶": "宝", + "將": "将", + "專": "专", + "尋": "寻", + "對": "对", + "導": "导", + "尷": "尴", + "屆": "届", + "屍": "尸", + "屓": "屃", + "屜": "屉", + "屢": "屡", + "層": "层", + "屨": "屦", + "屩": "𪨗", + "屬": "属", + "岡": "冈", + "峯": "峰", + "峴": "岘", + "島": "岛", + "峽": "峡", + "崍": "崃", + "崑": "昆", + "崗": "岗", + "崙": "仑", + "崢": "峥", + "崬": "岽", + "嵐": "岚", + "嵗": "岁", + "嵼": "𡶴", + "嵾": "㟥", + "嶁": "嵝", + "嶄": "崭", + "嶇": "岖", + "嶈": "𡺃", + "嶔": "嵚", + "嶗": "崂", + "嶘": "𡺄", + "嶠": "峤", + "嶢": "峣", + "嶧": "峄", + "嶨": "峃", + "嶮": "崄", + "嶴": "岙", + "嶸": "嵘", + "嶹": "𫝵", + "嶺": "岭", + "嶼": "屿", + "嶽": "岳", + "巊": "𪩎", + "巋": "岿", + "巒": "峦", + "巔": "巅", + "巖": "岩", + "巗": "𪨷", + "巘": "𪩘", + "巰": "巯", + "巹": "卺", + "帥": "帅", + "師": "师", + "帳": "帐", + "帶": "带", + "幀": "帧", + "幃": "帏", + "幓": "㡎", + "幗": "帼", + "幘": "帻", + "幝": "𪩷", + "幟": "帜", + "幣": "币", + "幩": "𪩸", + "幫": "帮", + "幬": "帱", + "幹": "干", + "幾": "几", + "庫": "库", + "廁": "厕", + "廂": "厢", + "廄": "厩", + "廈": "厦", + "廎": "庼", + "廕": "荫", + "廚": "厨", + "廝": "厮", + "廟": "庙", + "廠": "厂", + "廡": "庑", + "廢": "废", + "廣": "广", + "廧": "𪪞", + "廩": "廪", + "廬": "庐", + "廳": "厅", + "弒": "弑", + "弔": "吊", + "弳": "弪", + "張": "张", + "強": "强", + "彃": "𪪼", + "彆": "别", + "彈": "弹", + "彌": "弥", + "彎": "弯", + "彔": "录", + "彙": "汇", + "彞": "彝", + "彠": "彟", + "彥": "彦", + "彫": "雕", + "彲": "彨", + "彷": "彷", + "彿": "佛", + "後": "后", + "徑": "径", + "從": "从", + "徠": "徕", + "復": "复", + "徵": "征", + "徹": "彻", + "徿": "𪫌", + "恆": "恒", + "恥": "耻", + "悅": "悦", + "悞": "悮", + "悵": "怅", + "悶": "闷", + "悽": "凄", + "惡": "恶", + "惱": "恼", + "惲": "恽", + "惻": "恻", + "愛": "爱", + "愜": "惬", + "愨": "悫", + "愴": "怆", + "愷": "恺", + "愻": "𢙏", + "愾": "忾", + "慄": "栗", + "態": "态", + "慍": "愠", + "慘": "惨", + "慚": "惭", + "慟": "恸", + "慣": "惯", + "慤": "悫", + "慪": "怄", + "慫": "怂", + "慮": "虑", + "慳": "悭", + "慶": "庆", + "慺": "㥪", + "慼": "戚", + "慾": "欲", + "憂": "忧", + "憊": "惫", + "憐": "怜", + "憑": "凭", + "憒": "愦", + "憖": "慭", + "憚": "惮", + "憢": "𢙒", + "憤": "愤", + "憫": "悯", + "憮": "怃", + "憲": "宪", + "憶": "忆", + "憸": "𪫺", + "憹": "𢙐", + "懀": "𢙓", + "懇": "恳", + "應": "应", + "懌": "怿", + "懍": "懔", + "懎": "𢠁", + "懞": "蒙", + "懟": "怼", + "懣": "懑", + "懤": "㤽", + "懨": "恹", + "懲": "惩", + "懶": "懒", + "懷": "怀", + "懸": "悬", + "懺": "忏", + "懼": "惧", + "懾": "慑", + "戀": "恋", + "戇": "戆", + "戔": "戋", + "戧": "戗", + "戩": "戬", + "戰": "战", + "戱": "戯", + "戲": "戏", + "戶": "户", + "拋": "抛", + "挩": "捝", + "挱": "挲", + "挾": "挟", + "捨": "舍", + "捫": "扪", + "捱": "挨", + "捲": "卷", + "掃": "扫", + "掄": "抡", + "掆": "㧏", + "掗": "挜", + "掙": "挣", + "掚": "𪭵", + "掛": "挂", + "採": "采", + "揀": "拣", + "揚": "扬", + "換": "换", + "揮": "挥", + "揯": "搄", + "損": "损", + "搖": "摇", + "搗": "捣", + "搵": "揾", + "搶": "抢", + "摋": "𢫬", + "摐": "𪭢", + "摑": "掴", + "摜": "掼", + "摟": "搂", + "摯": "挚", + "摳": "抠", + "摶": "抟", + "摺": "折", + "摻": "掺", + "撈": "捞", + "撊": "𪭾", + "撏": "挦", + "撐": "撑", + "撓": "挠", + "撝": "㧑", + "撟": "挢", + "撣": "掸", + "撥": "拨", + "撧": "𪮖", + "撫": "抚", + "撲": "扑", + "撳": "揿", + "撻": "挞", + "撾": "挝", + "撿": "捡", + "擁": "拥", + "擄": "掳", + "擇": "择", + "擊": "击", + "擋": "挡", + "擓": "㧟", + "擔": "担", + "據": "据", + "擟": "𪭧", + "擠": "挤", + "擡": "抬", + "擣": "捣", + "擫": "𢬍", + "擬": "拟", + "擯": "摈", + "擰": "拧", + "擱": "搁", + "擲": "掷", + "擴": "扩", + "擷": "撷", + "擺": "摆", + "擻": "擞", + "擼": "撸", + "擽": "㧰", + "擾": "扰", + "攄": "摅", + "攆": "撵", + "攋": "𪮶", + "攏": "拢", + "攔": "拦", + "攖": "撄", + "攙": "搀", + "攛": "撺", + "攜": "携", + "攝": "摄", + "攢": "攒", + "攣": "挛", + "攤": "摊", + "攪": "搅", + "攬": "揽", + "敎": "教", + "敓": "敚", + "敗": "败", + "敘": "叙", + "敵": "敌", + "數": "数", + "斂": "敛", + "斃": "毙", + "斅": "𢽾", + "斆": "敩", + "斕": "斓", + "斬": "斩", + "斷": "断", + "斸": "𣃁", + "於": "于", + "旂": "旗", + "旣": "既", + "昇": "升", + "時": "时", + "晉": "晋", + "晝": "昼", + "暈": "晕", + "暉": "晖", + "暘": "旸", + "暢": "畅", + "暫": "暂", + "曄": "晔", + "曆": "历", + "曇": "昙", + "曉": "晓", + "曊": "𪰶", + "曏": "向", + "曖": "暧", + "曠": "旷", + "曥": "𣆐", + "曨": "昽", + "曬": "晒", + "書": "书", + "會": "会", + "朥": "𦛨", + "朧": "胧", + "朮": "术", + "東": "东", + "杴": "锨", + "枴": "拐", + "柵": "栅", + "柺": "拐", + "査": "查", + "桱": "𣐕", + "桿": "杆", + "梔": "栀", + "梖": "𪱷", + "梘": "枧", + "條": "条", + "梟": "枭", + "梲": "棁", + "棄": "弃", + "棊": "棋", + "棖": "枨", + "棗": "枣", + "棟": "栋", + "棡": "㭎", + "棧": "栈", + "棲": "栖", + "棶": "梾", + "椏": "桠", + "椲": "㭏", + "楇": "𣒌", + "楊": "杨", + "楓": "枫", + "楨": "桢", + "業": "业", + "極": "极", + "榘": "矩", + "榦": "干", + "榪": "杩", + "榮": "荣", + "榲": "榅", + "榿": "桤", + "構": "构", + "槍": "枪", + "槓": "杠", + "槤": "梿", + "槧": "椠", + "槨": "椁", + "槫": "𣏢", + "槮": "椮", + "槳": "桨", + "槶": "椢", + "槼": "椝", + "樁": "桩", + "樂": "乐", + "樅": "枞", + "樑": "梁", + "樓": "楼", + "標": "标", + "樞": "枢", + "樠": "𣗊", + "樢": "㭤", + "樣": "样", + "樤": "𣔌", + "樧": "榝", + "樫": "㭴", + "樳": "桪", + "樸": "朴", + "樹": "树", + "樺": "桦", + "樿": "椫", + "橈": "桡", + "橋": "桥", + "機": "机", + "橢": "椭", + "橫": "横", + "橯": "𣓿", + "檁": "檩", + "檉": "柽", + "檔": "档", + "檜": "桧", + "檟": "槚", + "檢": "检", + "檣": "樯", + "檭": "𣘴", + "檮": "梼", + "檯": "台", + "檳": "槟", + "檵": "𪲛", + "檸": "柠", + "檻": "槛", + "檾": "𦼖", + "櫃": "柜", + "櫅": "𪲎", + "櫓": "橹", + "櫚": "榈", + "櫛": "栉", + "櫝": "椟", + "櫞": "橼", + "櫟": "栎", + "櫠": "𪲮", + "櫥": "橱", + "櫧": "槠", + "櫨": "栌", + "櫪": "枥", + "櫫": "橥", + "櫬": "榇", + "櫱": "蘖", + "櫳": "栊", + "櫸": "榉", + "櫺": "棂", + "櫻": "樱", + "欄": "栏", + "欅": "榉", + "欇": "𪳍", + "權": "权", + "欍": "𣐤", + "欏": "椤", + "欐": "𪲔", + "欑": "𪴙", + "欒": "栾", + "欓": "𣗋", + "欖": "榄", + "欘": "𣚚", + "欞": "棂", + "欽": "钦", + "歎": "叹", + "歐": "欧", + "歟": "欤", + "歡": "欢", + "歲": "岁", + "歷": "历", + "歸": "归", + "歿": "殁", + "殘": "残", + "殞": "殒", + "殢": "𣨼", + "殤": "殇", + "殨": "㱮", + "殫": "殚", + "殭": "僵", + "殮": "殓", + "殯": "殡", + "殰": "㱩", + "殲": "歼", + "殺": "杀", + "殻": "壳", + "殼": "壳", + "毀": "毁", + "毆": "殴", + "毊": "𪵑", + "毿": "毵", + "氂": "牦", + "氈": "毡", + "氌": "氇", + "氣": "气", + "氫": "氢", + "氬": "氩", + "氭": "𣱝", + "氳": "氲", + "氾": "泛", + "汎": "泛", + "汙": "污", + "決": "决", + "沈": "沈", + "沒": "没", + "沖": "冲", + "況": "况", + "泝": "溯", + "洩": "泄", + "洶": "汹", + "浹": "浃", + "涇": "泾", + "涗": "涚", + "涼": "凉", + "淒": "凄", + "淚": "泪", + "淥": "渌", + "淨": "净", + "淩": "凌", + "淪": "沦", + "淵": "渊", + "淶": "涞", + "淺": "浅", + "渙": "涣", + "減": "减", + "渢": "沨", + "渦": "涡", + "測": "测", + "渾": "浑", + "湊": "凑", + "湋": "𣲗", + "湞": "浈", + "湧": "涌", + "湯": "汤", + "溈": "沩", + "準": "准", + "溝": "沟", + "溡": "𪶄", + "溫": "温", + "溮": "浉", + "溳": "涢", + "溼": "湿", + "滄": "沧", + "滅": "灭", + "滌": "涤", + "滎": "荥", + "滙": "汇", + "滬": "沪", + "滯": "滞", + "滲": "渗", + "滷": "卤", + "滸": "浒", + "滻": "浐", + "滾": "滚", + "滿": "满", + "漁": "渔", + "漊": "溇", + "漚": "沤", + "漢": "汉", + "漣": "涟", + "漬": "渍", + "漲": "涨", + "漵": "溆", + "漸": "渐", + "漿": "浆", + "潁": "颍", + "潑": "泼", + "潔": "洁", + "潕": "𣲘", + "潙": "沩", + "潚": "㴋", + "潛": "潜", + "潣": "𫞗", + "潤": "润", + "潯": "浔", + "潰": "溃", + "潷": "滗", + "潿": "涠", + "澀": "涩", + "澅": "𣶩", + "澆": "浇", + "澇": "涝", + "澐": "沄", + "澗": "涧", + "澠": "渑", + "澤": "泽", + "澦": "滪", + "澩": "泶", + "澬": "𫞚", + "澮": "浍", + "澱": "淀", + "澾": "㳠", + "濁": "浊", + "濃": "浓", + "濄": "㳡", + "濆": "𣸣", + "濕": "湿", + "濘": "泞", + "濚": "溁", + "濛": "蒙", + "濜": "浕", + "濟": "济", + "濤": "涛", + "濧": "㳔", + "濫": "滥", + "濰": "潍", + "濱": "滨", + "濺": "溅", + "濼": "泺", + "濾": "滤", + "濿": "𪵱", + "瀂": "澛", + "瀃": "𣽷", + "瀅": "滢", + "瀆": "渎", + "瀇": "㲿", + "瀉": "泻", + "瀋": "沈", + "瀏": "浏", + "瀕": "濒", + "瀘": "泸", + "瀝": "沥", + "瀟": "潇", + "瀠": "潆", + "瀦": "潴", + "瀧": "泷", + "瀨": "濑", + "瀰": "弥", + "瀲": "潋", + "瀾": "澜", + "灃": "沣", + "灄": "滠", + "灍": "𫞝", + "灑": "洒", + "灒": "𪷽", + "灕": "漓", + "灘": "滩", + "灙": "𣺼", + "灝": "灏", + "灡": "㳕", + "灣": "湾", + "灤": "滦", + "灧": "滟", + "灩": "滟", + "災": "灾", + "為": "为", + "烏": "乌", + "烴": "烃", + "無": "无", + "煇": "𪸩", + "煉": "炼", + "煒": "炜", + "煙": "烟", + "煢": "茕", + "煥": "焕", + "煩": "烦", + "煬": "炀", + "煱": "㶽", + "熂": "𪸕", + "熅": "煴", + "熉": "𤈶", + "熌": "𤇄", + "熒": "荧", + "熓": "𤆡", + "熗": "炝", + "熚": "𤇹", + "熡": "𤋏", + "熱": "热", + "熲": "颎", + "熾": "炽", + "燁": "烨", + "燈": "灯", + "燉": "炖", + "燒": "烧", + "燙": "烫", + "燜": "焖", + "營": "营", + "燦": "灿", + "燬": "毁", + "燭": "烛", + "燴": "烩", + "燶": "㶶", + "燻": "熏", + "燼": "烬", + "燾": "焘", + "爃": "𫞡", + "爄": "𤇃", + "爇": "𦶟", + "爍": "烁", + "爐": "炉", + "爖": "𤇭", + "爛": "烂", + "爥": "𪹳", + "爧": "𫞠", + "爭": "争", + "爲": "为", + "爺": "爷", + "爾": "尔", + "牀": "床", + "牆": "墙", + "牘": "牍", + "牴": "牴", + "牽": "牵", + "犖": "荦", + "犛": "牦", + "犞": "𪺭", + "犢": "犊", + "犧": "牺", + "狀": "状", + "狹": "狭", + "狽": "狈", + "猌": "𪺽", + "猙": "狰", + "猶": "犹", + "猻": "狲", + "獁": "犸", + "獃": "呆", + "獄": "狱", + "獅": "狮", + "獊": "𪺷", + "獎": "奖", + "獨": "独", + "獩": "𤞃", + "獪": "狯", + "獫": "猃", + "獮": "狝", + "獰": "狞", + "獱": "㺍", + "獲": "获", + "獵": "猎", + "獷": "犷", + "獸": "兽", + "獺": "獭", + "獻": "献", + "獼": "猕", + "玀": "猡", + "玁": "𤞤", + "珼": "𫞥", + "現": "现", + "琱": "雕", + "琺": "珐", + "琿": "珲", + "瑋": "玮", + "瑒": "玚", + "瑣": "琐", + "瑤": "瑶", + "瑩": "莹", + "瑪": "玛", + "瑲": "玱", + "瑻": "𪻲", + "瑽": "𪻐", + "璉": "琏", + "璊": "𫞩", + "璝": "𪻺", + "璡": "琎", + "璣": "玑", + "璦": "瑷", + "璫": "珰", + "璯": "㻅", + "環": "环", + "璵": "玙", + "璸": "瑸", + "璼": "𫞨", + "璽": "玺", + "璾": "𫞦", + "瓄": "𪻨", + "瓊": "琼", + "瓏": "珑", + "瓔": "璎", + "瓕": "𤦀", + "瓚": "瓒", + "瓛": "𤩽", + "甌": "瓯", + "甕": "瓮", + "產": "产", + "産": "产", + "甦": "苏", + "甯": "宁", + "畝": "亩", + "畢": "毕", + "畫": "画", + "異": "异", + "畵": "画", + "當": "当", + "畼": "𪽈", + "疇": "畴", + "疊": "叠", + "痙": "痉", + "痠": "酸", + "痮": "𪽪", + "痾": "疴", + "瘂": "痖", + "瘋": "疯", + "瘍": "疡", + "瘓": "痪", + "瘞": "瘗", + "瘡": "疮", + "瘧": "疟", + "瘮": "瘆", + "瘱": "𪽷", + "瘲": "疭", + "瘺": "瘘", + "瘻": "瘘", + "療": "疗", + "癆": "痨", + "癇": "痫", + "癉": "瘅", + "癐": "𤶊", + "癒": "愈", + "癘": "疠", + "癟": "瘪", + "癡": "痴", + "癢": "痒", + "癤": "疖", + "癥": "症", + "癧": "疬", + "癩": "癞", + "癬": "癣", + "癭": "瘿", + "癮": "瘾", + "癰": "痈", + "癱": "瘫", + "癲": "癫", + "發": "发", + "皁": "皂", + "皚": "皑", + "皟": "𤾀", + "皰": "疱", + "皸": "皲", + "皺": "皱", + "盃": "杯", + "盜": "盗", + "盞": "盏", + "盡": "尽", + "監": "监", + "盤": "盘", + "盧": "卢", + "盨": "𪾔", + "盪": "荡", + "眝": "𪾣", + "眞": "真", + "眥": "眦", + "眾": "众", + "睍": "𪾢", + "睏": "困", + "睜": "睁", + "睞": "睐", + "睪": "睾", + "瞘": "眍", + "瞜": "䁖", + "瞞": "瞒", + "瞤": "𥆧", + "瞭": "瞭", + "瞶": "瞆", + "瞼": "睑", + "矇": "蒙", + "矉": "𪾸", + "矑": "𪾦", + "矓": "眬", + "矚": "瞩", + "矯": "矫", + "硃": "朱", + "硜": "硁", + "硤": "硖", + "硨": "砗", + "硯": "砚", + "碕": "埼", + "碙": "𥐻", + "碩": "硕", + "碭": "砀", + "碸": "砜", + "確": "确", + "碼": "码", + "碽": "䂵", + "磑": "硙", + "磚": "砖", + "磠": "硵", + "磣": "碜", + "磧": "碛", + "磯": "矶", + "磽": "硗", + "磾": "䃅", + "礄": "硚", + "礆": "硷", + "礎": "础", + "礒": "𥐟", + "礙": "碍", + "礦": "矿", + "礪": "砺", + "礫": "砾", + "礬": "矾", + "礮": "𪿫", + "礱": "砻", + "祇": "祇", + "祕": "秘", + "祿": "禄", + "禍": "祸", + "禎": "祯", + "禕": "祎", + "禡": "祃", + "禦": "御", + "禪": "禅", + "禮": "礼", + "禰": "祢", + "禱": "祷", + "禿": "秃", + "秈": "籼", + "稅": "税", + "稈": "秆", + "稏": "䅉", + "稜": "棱", + "稟": "禀", + "種": "种", + "稱": "称", + "穀": "谷", + "穇": "䅟", + "穌": "稣", + "積": "积", + "穎": "颖", + "穠": "秾", + "穡": "穑", + "穢": "秽", + "穩": "稳", + "穫": "获", + "穭": "穞", + "窩": "窝", + "窪": "洼", + "窮": "穷", + "窯": "窑", + "窵": "窎", + "窶": "窭", + "窺": "窥", + "竄": "窜", + "竅": "窍", + "竇": "窦", + "竈": "灶", + "竊": "窃", + "竚": "𥩟", + "竪": "竖", + "竱": "𫁟", + "競": "竞", + "筆": "笔", + "筍": "笋", + "筧": "笕", + "筴": "䇲", + "箇": "个", + "箋": "笺", + "箏": "筝", + "節": "节", + "範": "范", + "築": "筑", + "篋": "箧", + "篔": "筼", + "篘": "𥬠", + "篠": "筿", + "篤": "笃", + "篩": "筛", + "篳": "筚", + "篸": "𥮾", + "簀": "箦", + "簂": "𫂆", + "簍": "篓", + "簑": "蓑", + "簞": "箪", + "簡": "简", + "簢": "𫂃", + "簣": "篑", + "簫": "箫", + "簹": "筜", + "簽": "签", + "簾": "帘", + "籃": "篮", + "籅": "𥫣", + "籋": "𥬞", + "籌": "筹", + "籔": "䉤", + "籙": "箓", + "籛": "篯", + "籜": "箨", + "籟": "籁", + "籠": "笼", + "籤": "签", + "籩": "笾", + "籪": "簖", + "籬": "篱", + "籮": "箩", + "籲": "吁", + "粵": "粤", + "糉": "粽", + "糝": "糁", + "糞": "粪", + "糧": "粮", + "糰": "团", + "糲": "粝", + "糴": "籴", + "糶": "粜", + "糹": "纟", + "糺": "𫄙", + "糾": "纠", + "紀": "纪", + "紂": "纣", + "約": "约", + "紅": "红", + "紆": "纡", + "紇": "纥", + "紈": "纨", + "紉": "纫", + "紋": "纹", + "納": "纳", + "紐": "纽", + "紓": "纾", + "純": "纯", + "紕": "纰", + "紖": "纼", + "紗": "纱", + "紘": "纮", + "紙": "纸", + "級": "级", + "紛": "纷", + "紜": "纭", + "紝": "纴", + "紟": "𫄛", + "紡": "纺", + "紬": "䌷", + "紮": "扎", + "細": "细", + "紱": "绂", + "紲": "绁", + "紳": "绅", + "紵": "纻", + "紹": "绍", + "紺": "绀", + "紼": "绋", + "紿": "绐", + "絀": "绌", + "絁": "𫄟", + "終": "终", + "絃": "弦", + "組": "组", + "絅": "䌹", + "絆": "绊", + "絍": "𫟃", + "絎": "绗", + "結": "结", + "絕": "绝", + "絙": "𫄠", + "絛": "绦", + "絝": "绔", + "絞": "绞", + "絡": "络", + "絢": "绚", + "絥": "𫄢", + "給": "给", + "絧": "𫄡", + "絨": "绒", + "絰": "绖", + "統": "统", + "絲": "丝", + "絳": "绛", + "絶": "绝", + "絹": "绢", + "絺": "𫄨", + "綀": "𦈌", + "綁": "绑", + "綃": "绡", + "綆": "绠", + "綇": "𦈋", + "綈": "绨", + "綉": "绣", + "綋": "𫟄", + "綌": "绤", + "綏": "绥", + "綐": "䌼", + "綑": "捆", + "經": "经", + "綖": "𫄧", + "綜": "综", + "綞": "缍", + "綟": "𫄫", + "綠": "绿", + "綡": "𫟅", + "綢": "绸", + "綣": "绻", + "綫": "线", + "綬": "绶", + "維": "维", + "綯": "绹", + "綰": "绾", + "綱": "纲", + "網": "网", + "綳": "绷", + "綴": "缀", + "綵": "彩", + "綸": "纶", + "綹": "绺", + "綺": "绮", + "綻": "绽", + "綽": "绰", + "綾": "绫", + "綿": "绵", + "緄": "绲", + "緇": "缁", + "緊": "紧", + "緋": "绯", + "緍": "𦈏", + "緑": "绿", + "緒": "绪", + "緓": "绬", + "緔": "绱", + "緗": "缃", + "緘": "缄", + "緙": "缂", + "線": "线", + "緝": "缉", + "緞": "缎", + "緟": "𫟆", + "締": "缔", + "緡": "缗", + "緣": "缘", + "緤": "𫄬", + "緦": "缌", + "編": "编", + "緩": "缓", + "緬": "缅", + "緮": "𫄭", + "緯": "纬", + "緰": "𦈕", + "緱": "缑", + "緲": "缈", + "練": "练", + "緶": "缏", + "緷": "𦈉", + "緸": "𦈑", + "緹": "缇", + "緻": "致", + "緼": "缊", + "縈": "萦", + "縉": "缙", + "縊": "缢", + "縋": "缒", + "縍": "𫄰", + "縎": "𦈔", + "縐": "绉", + "縑": "缣", + "縕": "缊", + "縗": "缞", + "縛": "缚", + "縝": "缜", + "縞": "缟", + "縟": "缛", + "縣": "县", + "縧": "绦", + "縫": "缝", + "縬": "𦈚", + "縭": "缡", + "縮": "缩", + "縰": "𫄳", + "縱": "纵", + "縲": "缧", + "縳": "䌸", + "縴": "纤", + "縵": "缦", + "縶": "絷", + "縷": "缕", + "縸": "𫄲", + "縹": "缥", + "縺": "𦈐", + "總": "总", + "績": "绩", + "繂": "𫄴", + "繃": "绷", + "繅": "缫", + "繆": "缪", + "繈": "𫄶", + "繏": "𦈝", + "繐": "穗", + "繒": "缯", + "繓": "𦈛", + "織": "织", + "繕": "缮", + "繚": "缭", + "繞": "绕", + "繟": "𦈎", + "繡": "绣", + "繢": "缋", + "繨": "𫄤", + "繩": "绳", + "繪": "绘", + "繫": "系", + "繬": "𫄱", + "繭": "茧", + "繮": "缰", + "繯": "缳", + "繰": "缲", + "繳": "缴", + "繶": "𫄷", + "繷": "𫄣", + "繸": "䍁", + "繹": "绎", + "繻": "𦈡", + "繼": "继", + "繽": "缤", + "繾": "缱", + "繿": "䍀", + "纁": "𫄸", + "纇": "颣", + "纈": "缬", + "纊": "纩", + "續": "续", + "纍": "累", + "纏": "缠", + "纓": "缨", + "纔": "才", + "纖": "纤", + "纗": "𫄹", + "纘": "缵", + "纚": "𫄥", + "纜": "缆", + "缽": "钵", + "罃": "䓨", + "罈": "坛", + "罌": "罂", + "罎": "坛", + "罰": "罚", + "罵": "骂", + "罷": "罢", + "羅": "罗", + "羆": "罴", + "羈": "羁", + "羋": "芈", + "羣": "群", + "羥": "羟", + "羨": "羡", + "義": "义", + "羵": "𫅗", + "羶": "膻", + "習": "习", + "翬": "翚", + "翹": "翘", + "翽": "翙", + "耬": "耧", + "耮": "耢", + "聖": "圣", + "聞": "闻", + "聯": "联", + "聰": "聪", + "聲": "声", + "聳": "耸", + "聵": "聩", + "聶": "聂", + "職": "职", + "聹": "聍", + "聻": "𫆏", + "聽": "听", + "聾": "聋", + "肅": "肃", + "脅": "胁", + "脈": "脉", + "脛": "胫", + "脣": "唇", + "脥": "𣍰", + "脩": "修", + "脫": "脱", + "脹": "胀", + "腎": "肾", + "腖": "胨", + "腡": "脶", + "腦": "脑", + "腪": "𣍯", + "腫": "肿", + "腳": "脚", + "腸": "肠", + "膃": "腽", + "膕": "腘", + "膚": "肤", + "膞": "䏝", + "膠": "胶", + "膢": "𦝼", + "膩": "腻", + "膹": "𪱥", + "膽": "胆", + "膾": "脍", + "膿": "脓", + "臉": "脸", + "臍": "脐", + "臏": "膑", + "臗": "𣎑", + "臘": "腊", + "臚": "胪", + "臟": "脏", + "臠": "脔", + "臢": "臜", + "臥": "卧", + "臨": "临", + "臺": "台", + "與": "与", + "興": "兴", + "舉": "举", + "舊": "旧", + "舘": "馆", + "艙": "舱", + "艣": "𫇛", + "艤": "舣", + "艦": "舰", + "艫": "舻", + "艱": "艰", + "艷": "艳", + "芻": "刍", + "苧": "苎", + "茲": "兹", + "荊": "荆", + "莊": "庄", + "莖": "茎", + "莢": "荚", + "莧": "苋", + "菕": "芲", + "華": "华", + "菴": "庵", + "菸": "烟", + "萇": "苌", + "萊": "莱", + "萬": "万", + "萴": "荝", + "萵": "莴", + "葉": "叶", + "葒": "荭", + "葝": "𫈎", + "葤": "荮", + "葦": "苇", + "葯": "药", + "葷": "荤", + "蒍": "𫇭", + "蒐": "搜", + "蒓": "莼", + "蒔": "莳", + "蒕": "蒀", + "蒞": "莅", + "蒭": "𫇴", + "蒼": "苍", + "蓀": "荪", + "蓆": "席", + "蓋": "盖", + "蓧": "𦰏", + "蓮": "莲", + "蓯": "苁", + "蓴": "莼", + "蓽": "荜", + "蔔": "卜", + "蔘": "参", + "蔞": "蒌", + "蔣": "蒋", + "蔥": "葱", + "蔦": "茑", + "蔭": "荫", + "蔯": "𫈟", + "蔿": "𫇭", + "蕁": "荨", + "蕆": "蒇", + "蕎": "荞", + "蕒": "荬", + "蕓": "芸", + "蕕": "莸", + "蕘": "荛", + "蕝": "𫈵", + "蕢": "蒉", + "蕩": "荡", + "蕪": "芜", + "蕭": "萧", + "蕳": "𫈉", + "蕷": "蓣", + "蕽": "𫇽", + "薀": "蕰", + "薆": "𫉁", + "薈": "荟", + "薊": "蓟", + "薌": "芗", + "薑": "姜", + "薔": "蔷", + "薘": "荙", + "薟": "莶", + "薦": "荐", + "薩": "萨", + "薰": "薰", + "薳": "䓕", + "薴": "苧", + "薵": "䓓", + "薹": "苔", + "薺": "荠", + "藉": "藉", + "藍": "蓝", + "藎": "荩", + "藝": "艺", + "藥": "药", + "藪": "薮", + "藭": "䓖", + "藴": "蕴", + "藶": "苈", + "藷": "𫉄", + "藹": "蔼", + "藺": "蔺", + "蘀": "萚", + "蘄": "蕲", + "蘆": "芦", + "蘇": "苏", + "蘊": "蕴", + "蘋": "苹", + "蘚": "藓", + "蘞": "蔹", + "蘟": "𦻕", + "蘢": "茏", + "蘭": "兰", + "蘺": "蓠", + "蘿": "萝", + "虆": "蔂", + "處": "处", + "虛": "虚", + "虜": "虏", + "號": "号", + "虧": "亏", + "虯": "虬", + "蛺": "蛱", + "蛻": "蜕", + "蜆": "蚬", + "蝕": "蚀", + "蝟": "猬", + "蝦": "虾", + "蝨": "虱", + "蝸": "蜗", + "螄": "蛳", + "螞": "蚂", + "螢": "萤", + "螮": "䗖", + "螻": "蝼", + "螿": "螀", + "蟂": "𫋇", + "蟄": "蛰", + "蟈": "蝈", + "蟎": "螨", + "蟘": "𫋌", + "蟜": "𫊸", + "蟣": "虮", + "蟬": "蝉", + "蟯": "蛲", + "蟲": "虫", + "蟳": "𫊻", + "蟶": "蛏", + "蟻": "蚁", + "蠀": "𧏗", + "蠁": "蚃", + "蠅": "蝇", + "蠆": "虿", + "蠍": "蝎", + "蠐": "蛴", + "蠑": "蝾", + "蠔": "蚝", + "蠙": "𧏖", + "蠟": "蜡", + "蠣": "蛎", + "蠦": "𫊮", + "蠨": "蟏", + "蠱": "蛊", + "蠶": "蚕", + "蠻": "蛮", + "蠾": "𧑏", + "衆": "众", + "衊": "蔑", + "術": "术", + "衕": "同", + "衚": "胡", + "衛": "卫", + "衝": "冲", + "衹": "衹", + "袞": "衮", + "裊": "袅", + "裏": "里", + "補": "补", + "裝": "装", + "裡": "里", + "製": "制", + "複": "复", + "褌": "裈", + "褘": "袆", + "褲": "裤", + "褳": "裢", + "褸": "褛", + "褻": "亵", + "襀": "𫌀", + "襆": "幞", + "襇": "裥", + "襉": "裥", + "襏": "袯", + "襓": "𫋹", + "襖": "袄", + "襗": "𫋷", + "襘": "𫋻", + "襝": "裣", + "襠": "裆", + "襤": "褴", + "襪": "袜", + "襬": "摆", + "襯": "衬", + "襰": "𧝝", + "襲": "袭", + "襴": "襕", + "襵": "𫌇", + "覆": "覆", + "覈": "核", + "見": "见", + "覎": "觃", + "規": "规", + "覓": "觅", + "視": "视", + "覘": "觇", + "覛": "𫌪", + "覡": "觋", + "覥": "觍", + "覦": "觎", + "親": "亲", + "覬": "觊", + "覯": "觏", + "覲": "觐", + "覷": "觑", + "覹": "𫌭", + "覺": "觉", + "覼": "𫌨", + "覽": "览", + "覿": "觌", + "觀": "观", + "觴": "觞", + "觶": "觯", + "觸": "触", + "訁": "讠", + "訂": "订", + "訃": "讣", + "計": "计", + "訊": "讯", + "訌": "讧", + "討": "讨", + "訐": "讦", + "訑": "𫍙", + "訒": "讱", + "訓": "训", + "訕": "讪", + "訖": "讫", + "託": "托", + "記": "记", + "訛": "讹", + "訜": "𫍛", + "訝": "讶", + "訞": "𫍚", + "訟": "讼", + "訢": "䜣", + "訣": "诀", + "訥": "讷", + "訨": "𫟞", + "訩": "讻", + "訪": "访", + "設": "设", + "許": "许", + "訴": "诉", + "訶": "诃", + "診": "诊", + "註": "注", + "証": "证", + "詀": "𧮪", + "詁": "诂", + "詆": "诋", + "詊": "𫟟", + "詎": "讵", + "詐": "诈", + "詑": "𫍡", + "詒": "诒", + "詓": "𫍜", + "詔": "诏", + "評": "评", + "詖": "诐", + "詗": "诇", + "詘": "诎", + "詛": "诅", + "詞": "词", + "詠": "咏", + "詡": "诩", + "詢": "询", + "詣": "诣", + "試": "试", + "詩": "诗", + "詫": "诧", + "詬": "诟", + "詭": "诡", + "詮": "诠", + "詰": "诘", + "話": "话", + "該": "该", + "詳": "详", + "詵": "诜", + "詷": "𫍣", + "詼": "诙", + "詿": "诖", + "誂": "𫍥", + "誄": "诔", + "誅": "诛", + "誆": "诓", + "誇": "夸", + "誋": "𫍪", + "誌": "志", + "認": "认", + "誑": "诳", + "誒": "诶", + "誕": "诞", + "誘": "诱", + "誚": "诮", + "語": "语", + "誠": "诚", + "誡": "诫", + "誣": "诬", + "誤": "误", + "誥": "诰", + "誦": "诵", + "誨": "诲", + "說": "说", + "誫": "𫍨", + "説": "说", + "誰": "谁", + "課": "课", + "誳": "𫍮", + "誴": "𫟡", + "誶": "谇", + "誷": "𫍬", + "誹": "诽", + "誺": "𫍧", + "誼": "谊", + "誾": "訚", + "調": "调", + "諂": "谄", + "諄": "谆", + "談": "谈", + "諉": "诿", + "請": "请", + "諍": "诤", + "諏": "诹", + "諑": "诼", + "諒": "谅", + "論": "论", + "諗": "谂", + "諛": "谀", + "諜": "谍", + "諝": "谞", + "諞": "谝", + "諡": "谥", + "諢": "诨", + "諣": "𫍩", + "諤": "谔", + "諥": "𫍳", + "諦": "谛", + "諧": "谐", + "諫": "谏", + "諭": "谕", + "諮": "咨", + "諯": "𫍱", + "諰": "𫍰", + "諱": "讳", + "諳": "谙", + "諴": "𫍯", + "諶": "谌", + "諷": "讽", + "諸": "诸", + "諺": "谚", + "諼": "谖", + "諾": "诺", + "謀": "谋", + "謁": "谒", + "謂": "谓", + "謄": "誊", + "謅": "诌", + "謆": "𫍸", + "謉": "𫍷", + "謊": "谎", + "謎": "谜", + "謏": "𫍲", + "謐": "谧", + "謔": "谑", + "謖": "谡", + "謗": "谤", + "謙": "谦", + "謚": "谥", + "講": "讲", + "謝": "谢", + "謠": "谣", + "謡": "谣", + "謨": "谟", + "謫": "谪", + "謬": "谬", + "謭": "谫", + "謯": "𫍹", + "謱": "𫍴", + "謳": "讴", + "謸": "𫍵", + "謹": "谨", + "謾": "谩", + "譁": "哗", + "譂": "𫟠", + "譅": "䜧", + "譆": "𫍻", + "證": "证", + "譊": "𫍢", + "譎": "谲", + "譏": "讥", + "譑": "𫍤", + "譖": "谮", + "識": "识", + "譙": "谯", + "譚": "谭", + "譜": "谱", + "譞": "𫍽", + "譟": "噪", + "譨": "𫍦", + "譫": "谵", + "譭": "毁", + "譯": "译", + "議": "议", + "譴": "谴", + "護": "护", + "譸": "诪", + "譽": "誉", + "譾": "谫", + "讀": "读", + "讅": "谉", + "變": "变", + "讋": "詟", + "讌": "䜩", + "讎": "雠", + "讒": "谗", + "讓": "让", + "讕": "谰", + "讖": "谶", + "讚": "赞", + "讜": "谠", + "讞": "谳", + "豈": "岂", + "豎": "竖", + "豐": "丰", + "豔": "艳", + "豬": "猪", + "豵": "𫎆", + "豶": "豮", + "貓": "猫", + "貗": "𫎌", + "貙": "䝙", + "貝": "贝", + "貞": "贞", + "貟": "贠", + "負": "负", + "財": "财", + "貢": "贡", + "貧": "贫", + "貨": "货", + "販": "贩", + "貪": "贪", + "貫": "贯", + "責": "责", + "貯": "贮", + "貰": "贳", + "貲": "赀", + "貳": "贰", + "貴": "贵", + "貶": "贬", + "買": "买", + "貸": "贷", + "貺": "贶", + "費": "费", + "貼": "贴", + "貽": "贻", + "貿": "贸", + "賀": "贺", + "賁": "贲", + "賂": "赂", + "賃": "赁", + "賄": "贿", + "賅": "赅", + "資": "资", + "賈": "贾", + "賊": "贼", + "賑": "赈", + "賒": "赊", + "賓": "宾", + "賕": "赇", + "賙": "赒", + "賚": "赉", + "賜": "赐", + "賝": "𫎩", + "賞": "赏", + "賟": "𧹖", + "賠": "赔", + "賡": "赓", + "賢": "贤", + "賣": "卖", + "賤": "贱", + "賦": "赋", + "賧": "赕", + "質": "质", + "賫": "赍", + "賬": "账", + "賭": "赌", + "賰": "䞐", + "賴": "赖", + "賵": "赗", + "賺": "赚", + "賻": "赙", + "購": "购", + "賽": "赛", + "賾": "赜", + "贃": "𧹗", + "贄": "贽", + "贅": "赘", + "贇": "赟", + "贈": "赠", + "贉": "𫎫", + "贊": "赞", + "贋": "赝", + "贍": "赡", + "贏": "赢", + "贐": "赆", + "贑": "𫎬", + "贓": "赃", + "贔": "赑", + "贖": "赎", + "贗": "赝", + "贚": "𫎦", + "贛": "赣", + "贜": "赃", + "赬": "赪", + "趕": "赶", + "趙": "赵", + "趨": "趋", + "趲": "趱", + "跡": "迹", + "踐": "践", + "踰": "逾", + "踴": "踊", + "蹌": "跄", + "蹔": "𫏐", + "蹕": "跸", + "蹟": "迹", + "蹣": "蹒", + "蹤": "踪", + "蹳": "𫏆", + "蹺": "跷", + "蹻": "𫏋", + "躂": "跶", + "躉": "趸", + "躊": "踌", + "躋": "跻", + "躍": "跃", + "躎": "䟢", + "躑": "踯", + "躒": "跞", + "躓": "踬", + "躕": "蹰", + "躘": "𨀁", + "躚": "跹", + "躝": "𨅬", + "躡": "蹑", + "躥": "蹿", + "躦": "躜", + "躪": "躏", + "軀": "躯", + "軉": "𨉗", + "車": "车", + "軋": "轧", + "軌": "轨", + "軍": "军", + "軏": "𫐄", + "軑": "轪", + "軒": "轩", + "軔": "轫", + "軕": "𫐅", + "軗": "𨐅", + "軛": "轭", + "軜": "𫐇", + "軟": "软", + "軤": "轷", + "軨": "𫐉", + "軫": "轸", + "軬": "𫐊", + "軲": "轱", + "軷": "𫐈", + "軸": "轴", + "軹": "轵", + "軺": "轺", + "軻": "轲", + "軼": "轶", + "軾": "轼", + "軿": "𫐌", + "較": "较", + "輄": "𨐈", + "輅": "辂", + "輇": "辁", + "輈": "辀", + "載": "载", + "輊": "轾", + "輋": "𪨶", + "輒": "辄", + "輓": "挽", + "輔": "辅", + "輕": "轻", + "輖": "𫐏", + "輗": "𫐐", + "輛": "辆", + "輜": "辎", + "輝": "辉", + "輞": "辋", + "輟": "辍", + "輢": "𫐎", + "輥": "辊", + "輦": "辇", + "輨": "𫐑", + "輩": "辈", + "輪": "轮", + "輬": "辌", + "輮": "𫐓", + "輯": "辑", + "輳": "辏", + "輷": "𫐒", + "輸": "输", + "輻": "辐", + "輼": "辒", + "輾": "辗", + "輿": "舆", + "轀": "辒", + "轂": "毂", + "轄": "辖", + "轅": "辕", + "轆": "辘", + "轇": "𫐖", + "轉": "转", + "轊": "𫐕", + "轍": "辙", + "轎": "轿", + "轐": "𫐗", + "轔": "辚", + "轗": "𫐘", + "轟": "轰", + "轠": "𫐙", + "轡": "辔", + "轢": "轹", + "轣": "𫐆", + "轤": "轳", + "辦": "办", + "辭": "辞", + "辮": "辫", + "辯": "辩", + "農": "农", + "迴": "回", + "逕": "迳", + "這": "这", + "連": "连", + "週": "周", + "進": "进", + "遊": "游", + "運": "运", + "過": "过", + "達": "达", + "違": "违", + "遙": "遥", + "遜": "逊", + "遞": "递", + "遠": "远", + "遡": "溯", + "適": "适", + "遱": "𫐷", + "遲": "迟", + "遷": "迁", + "選": "选", + "遺": "遗", + "遼": "辽", + "邁": "迈", + "還": "还", + "邇": "迩", + "邊": "边", + "邏": "逻", + "邐": "逦", + "郟": "郏", + "郵": "邮", + "鄆": "郓", + "鄉": "乡", + "鄒": "邹", + "鄔": "邬", + "鄖": "郧", + "鄟": "𫑘", + "鄧": "邓", + "鄭": "郑", + "鄰": "邻", + "鄲": "郸", + "鄳": "𫑡", + "鄴": "邺", + "鄶": "郐", + "鄺": "邝", + "酇": "酂", + "酈": "郦", + "醃": "腌", + "醖": "酝", + "醜": "丑", + "醞": "酝", + "醟": "蒏", + "醣": "糖", + "醫": "医", + "醬": "酱", + "醱": "酦", + "醶": "𫑷", + "釀": "酿", + "釁": "衅", + "釃": "酾", + "釅": "酽", + "釋": "释", + "釐": "厘", + "釒": "钅", + "釓": "钆", + "釔": "钇", + "釕": "钌", + "釗": "钊", + "釘": "钉", + "釙": "钋", + "釚": "𫟲", + "針": "针", + "釟": "𫓥", + "釣": "钓", + "釤": "钐", + "釦": "扣", + "釧": "钏", + "釨": "𫓦", + "釩": "钒", + "釲": "𫟳", + "釳": "𨰿", + "釵": "钗", + "釷": "钍", + "釹": "钕", + "釺": "钎", + "釾": "䥺", + "鈀": "钯", + "鈁": "钫", + "鈃": "钘", + "鈄": "钭", + "鈅": "钥", + "鈆": "𫓪", + "鈇": "𫓧", + "鈈": "钚", + "鈉": "钠", + "鈋": "𨱂", + "鈍": "钝", + "鈎": "钩", + "鈐": "钤", + "鈑": "钣", + "鈒": "钑", + "鈔": "钞", + "鈕": "钮", + "鈖": "𫟴", + "鈗": "𫟵", + "鈛": "𫓨", + "鈞": "钧", + "鈠": "𨱁", + "鈡": "钟", + "鈣": "钙", + "鈥": "钬", + "鈦": "钛", + "鈧": "钪", + "鈮": "铌", + "鈯": "𨱄", + "鈰": "铈", + "鈲": "𨱃", + "鈳": "钶", + "鈴": "铃", + "鈷": "钴", + "鈸": "钹", + "鈹": "铍", + "鈺": "钰", + "鈽": "钸", + "鈾": "铀", + "鈿": "钿", + "鉀": "钾", + "鉁": "𨱅", + "鉅": "巨", + "鉆": "钻", + "鉈": "铊", + "鉉": "铉", + "鉋": "铇", + "鉍": "铋", + "鉑": "铂", + "鉔": "𫓬", + "鉕": "钷", + "鉗": "钳", + "鉚": "铆", + "鉛": "铅", + "鉝": "𫟷", + "鉞": "钺", + "鉠": "𫓭", + "鉢": "钵", + "鉤": "钩", + "鉦": "钲", + "鉬": "钼", + "鉭": "钽", + "鉳": "锫", + "鉶": "铏", + "鉷": "𫟹", + "鉸": "铰", + "鉺": "铒", + "鉻": "铬", + "鉽": "𫟸", + "鉾": "𫓴", + "鉿": "铪", + "銀": "银", + "銁": "𫓲", + "銂": "𫟻", + "銃": "铳", + "銅": "铜", + "銈": "𫓯", + "銊": "𫓰", + "銍": "铚", + "銏": "𫟶", + "銑": "铣", + "銓": "铨", + "銖": "铢", + "銘": "铭", + "銚": "铫", + "銛": "铦", + "銜": "衔", + "銠": "铑", + "銣": "铷", + "銥": "铱", + "銦": "铟", + "銨": "铵", + "銩": "铥", + "銪": "铕", + "銫": "铯", + "銬": "铐", + "銱": "铞", + "銳": "锐", + "銶": "𨱇", + "銷": "销", + "銹": "锈", + "銻": "锑", + "銼": "锉", + "鋁": "铝", + "鋂": "镅", + "鋃": "锒", + "鋅": "锌", + "鋇": "钡", + "鋉": "𨱈", + "鋌": "铤", + "鋏": "铗", + "鋒": "锋", + "鋗": "𫓶", + "鋙": "铻", + "鋝": "锊", + "鋟": "锓", + "鋠": "𫓵", + "鋣": "铘", + "鋤": "锄", + "鋥": "锃", + "鋦": "锔", + "鋨": "锇", + "鋩": "铓", + "鋪": "铺", + "鋭": "锐", + "鋮": "铖", + "鋯": "锆", + "鋰": "锂", + "鋱": "铽", + "鋶": "锍", + "鋸": "锯", + "鋼": "钢", + "錀": "𬬭", + "錁": "锞", + "錂": "𨱋", + "錄": "录", + "錆": "锖", + "錇": "锫", + "錈": "锩", + "錏": "铔", + "錐": "锥", + "錒": "锕", + "錕": "锟", + "錘": "锤", + "錙": "锱", + "錚": "铮", + "錛": "锛", + "錜": "𫓻", + "錝": "𫓽", + "錟": "锬", + "錠": "锭", + "錡": "锜", + "錢": "钱", + "錤": "𫓹", + "錥": "𫓾", + "錦": "锦", + "錨": "锚", + "錩": "锠", + "錫": "锡", + "錮": "锢", + "錯": "错", + "録": "录", + "錳": "锰", + "錶": "表", + "錸": "铼", + "錼": "镎", + "錽": "𫓸", + "鍀": "锝", + "鍁": "锨", + "鍃": "锪", + "鍄": "𨱉", + "鍅": "钫", + "鍆": "钔", + "鍇": "锴", + "鍈": "锳", + "鍉": "𫔂", + "鍊": "炼", + "鍋": "锅", + "鍍": "镀", + "鍒": "𫔄", + "鍔": "锷", + "鍘": "铡", + "鍚": "钖", + "鍛": "锻", + "鍠": "锽", + "鍤": "锸", + "鍥": "锲", + "鍩": "锘", + "鍬": "锹", + "鍮": "𨱎", + "鍰": "锾", + "鍵": "键", + "鍶": "锶", + "鍺": "锗", + "鍼": "针", + "鍾": "钟", + "鎂": "镁", + "鎄": "锿", + "鎇": "镅", + "鎈": "𫟿", + "鎊": "镑", + "鎌": "镰", + "鎍": "𫔅", + "鎔": "镕", + "鎖": "锁", + "鎘": "镉", + "鎙": "𫔈", + "鎚": "锤", + "鎛": "镈", + "鎝": "𨱏", + "鎞": "𫔇", + "鎡": "镃", + "鎢": "钨", + "鎣": "蓥", + "鎦": "镏", + "鎧": "铠", + "鎩": "铩", + "鎪": "锼", + "鎬": "镐", + "鎭": "镇", + "鎮": "镇", + "鎯": "𨱍", + "鎰": "镒", + "鎲": "镋", + "鎳": "镍", + "鎵": "镓", + "鎶": "鿔", + "鎷": "𨰾", + "鎸": "镌", + "鎿": "镎", + "鏃": "镞", + "鏆": "𨱌", + "鏇": "镟", + "鏈": "链", + "鏉": "𨱒", + "鏌": "镆", + "鏍": "镙", + "鏐": "镠", + "鏑": "镝", + "鏗": "铿", + "鏘": "锵", + "鏚": "戚", + "鏜": "镗", + "鏝": "镘", + "鏞": "镛", + "鏟": "铲", + "鏡": "镜", + "鏢": "镖", + "鏤": "镂", + "鏥": "𫔊", + "鏦": "𫓩", + "鏨": "錾", + "鏰": "镚", + "鏵": "铧", + "鏷": "镤", + "鏹": "镪", + "鏺": "䥽", + "鏽": "锈", + "鏾": "𫔌", + "鐃": "铙", + "鐄": "𨱑", + "鐇": "𫔍", + "鐈": "𫓱", + "鐋": "铴", + "鐍": "𫔎", + "鐎": "𨱓", + "鐏": "𨱔", + "鐐": "镣", + "鐒": "铹", + "鐓": "镦", + "鐔": "镡", + "鐗": "锏", + "鐘": "钟", + "鐙": "镫", + "鐝": "镢", + "鐠": "镨", + "鐥": "䦅", + "鐦": "锎", + "鐧": "锏", + "鐨": "镄", + "鐪": "𫓺", + "鐫": "镌", + "鐮": "镰", + "鐯": "䦃", + "鐲": "镯", + "鐳": "镭", + "鐵": "铁", + "鐶": "镮", + "鐸": "铎", + "鐺": "铛", + "鐼": "𫔁", + "鐽": "𫟼", + "鐿": "镱", + "鑀": "锿", + "鑄": "铸", + "鑉": "𫠁", + "鑊": "镬", + "鑌": "镔", + "鑑": "鉴", + "鑒": "鉴", + "鑔": "镲", + "鑕": "锧", + "鑞": "镴", + "鑠": "铄", + "鑣": "镳", + "鑥": "镥", + "鑪": "𬬻", + "鑭": "镧", + "鑰": "钥", + "鑱": "镵", + "鑲": "镶", + "鑴": "𫔔", + "鑷": "镊", + "鑹": "镩", + "鑼": "锣", + "鑽": "钻", + "鑾": "銮", + "鑿": "凿", + "钁": "镢", + "钂": "镋", + "镟": "旋", + "長": "长", + "門": "门", + "閂": "闩", + "閃": "闪", + "閆": "闫", + "閈": "闬", + "閉": "闭", + "開": "开", + "閌": "闶", + "閍": "𨸂", + "閎": "闳", + "閏": "闰", + "閐": "𨸃", + "閑": "闲", + "閒": "闲", + "間": "间", + "閔": "闵", + "閗": "𫔯", + "閘": "闸", + "閝": "𫠂", + "閞": "𫔰", + "閡": "阂", + "閣": "阁", + "閤": "合", + "閥": "阀", + "閨": "闺", + "閩": "闽", + "閫": "阃", + "閬": "阆", + "閭": "闾", + "閱": "阅", + "閲": "阅", + "閵": "𫔴", + "閶": "阊", + "閹": "阉", + "閻": "阎", + "閼": "阏", + "閽": "阍", + "閾": "阈", + "閿": "阌", + "闃": "阒", + "闆": "板", + "闇": "暗", + "闈": "闱", + "闊": "阔", + "闋": "阕", + "闌": "阑", + "闍": "阇", + "闐": "阗", + "闑": "𫔶", + "闒": "阘", + "闓": "闿", + "闔": "阖", + "闕": "阙", + "闖": "闯", + "關": "关", + "闞": "阚", + "闠": "阓", + "闡": "阐", + "闢": "辟", + "闤": "阛", + "闥": "闼", + "阪": "阪", + "陘": "陉", + "陝": "陕", + "陞": "升", + "陣": "阵", + "陰": "阴", + "陳": "陈", + "陸": "陆", + "陽": "阳", + "隉": "陧", + "隊": "队", + "階": "阶", + "隕": "陨", + "際": "际", + "隨": "随", + "險": "险", + "隯": "陦", + "隱": "隐", + "隴": "陇", + "隸": "隶", + "隻": "只", + "雋": "隽", + "雖": "虽", + "雙": "双", + "雛": "雏", + "雜": "杂", + "雞": "鸡", + "離": "离", + "難": "难", + "雲": "云", + "電": "电", + "霢": "霡", + "霣": "𫕥", + "霧": "雾", + "霼": "𪵣", + "霽": "霁", + "靂": "雳", + "靄": "霭", + "靆": "叇", + "靈": "灵", + "靉": "叆", + "靚": "靓", + "靜": "静", + "靝": "靔", + "靦": "腼", + "靧": "𫖃", + "靨": "靥", + "鞀": "鼗", + "鞏": "巩", + "鞝": "绱", + "鞦": "秋", + "鞽": "鞒", + "鞾": "𫖇", + "韁": "缰", + "韃": "鞑", + "韆": "千", + "韉": "鞯", + "韋": "韦", + "韌": "韧", + "韍": "韨", + "韓": "韩", + "韙": "韪", + "韚": "𫠅", + "韛": "𫖔", + "韜": "韬", + "韝": "鞲", + "韞": "韫", + "韠": "𫖒", + "韻": "韵", + "響": "响", + "頁": "页", + "頂": "顶", + "頃": "顷", + "項": "项", + "順": "顺", + "頇": "顸", + "須": "须", + "頊": "顼", + "頌": "颂", + "頍": "𫠆", + "頎": "颀", + "頏": "颃", + "預": "预", + "頑": "顽", + "頒": "颁", + "頓": "顿", + "頗": "颇", + "領": "领", + "頜": "颌", + "頡": "颉", + "頤": "颐", + "頦": "颏", + "頫": "𫖯", + "頭": "头", + "頮": "颒", + "頰": "颊", + "頲": "颋", + "頴": "颕", + "頵": "𫖳", + "頷": "颔", + "頸": "颈", + "頹": "颓", + "頻": "频", + "頽": "颓", + "顂": "𩓋", + "顃": "𩖖", + "顅": "𫖶", + "顆": "颗", + "題": "题", + "額": "额", + "顎": "颚", + "顏": "颜", + "顒": "颙", + "顓": "颛", + "顔": "颜", + "顗": "𫖮", + "願": "愿", + "顙": "颡", + "顛": "颠", + "類": "类", + "顢": "颟", + "顣": "𫖹", + "顥": "颢", + "顧": "顾", + "顫": "颤", + "顬": "颥", + "顯": "显", + "顰": "颦", + "顱": "颅", + "顳": "颞", + "顴": "颧", + "風": "风", + "颭": "飐", + "颮": "飑", + "颯": "飒", + "颰": "𩙥", + "颱": "台", + "颳": "刮", + "颶": "飓", + "颷": "𩙪", + "颸": "飔", + "颺": "飏", + "颻": "飖", + "颼": "飕", + "颾": "𩙫", + "飀": "飗", + "飄": "飘", + "飆": "飙", + "飈": "飚", + "飋": "𫗋", + "飛": "飞", + "飠": "饣", + "飢": "饥", + "飣": "饤", + "飥": "饦", + "飦": "𫗞", + "飩": "饨", + "飪": "饪", + "飫": "饫", + "飭": "饬", + "飯": "饭", + "飱": "飧", + "飲": "饮", + "飴": "饴", + "飵": "𫗢", + "飶": "𫗣", + "飼": "饲", + "飽": "饱", + "飾": "饰", + "飿": "饳", + "餃": "饺", + "餄": "饸", + "餅": "饼", + "餉": "饷", + "養": "养", + "餌": "饵", + "餎": "饹", + "餏": "饻", + "餑": "饽", + "餒": "馁", + "餓": "饿", + "餔": "𫗦", + "餕": "馂", + "餖": "饾", + "餗": "𫗧", + "餘": "余", + "餚": "肴", + "餛": "馄", + "餜": "馃", + "餞": "饯", + "餡": "馅", + "餦": "𫗠", + "餧": "𫗪", + "館": "馆", + "餪": "𫗬", + "餫": "𫗥", + "餬": "糊", + "餭": "𫗮", + "餱": "糇", + "餳": "饧", + "餵": "喂", + "餶": "馉", + "餷": "馇", + "餸": "𩠌", + "餺": "馎", + "餼": "饩", + "餾": "馏", + "餿": "馊", + "饁": "馌", + "饃": "馍", + "饅": "馒", + "饈": "馐", + "饉": "馑", + "饊": "馓", + "饋": "馈", + "饌": "馔", + "饑": "饥", + "饒": "饶", + "饗": "飨", + "饘": "𫗴", + "饜": "餍", + "饞": "馋", + "饟": "𫗵", + "饠": "𫗩", + "饢": "馕", + "馬": "马", + "馭": "驭", + "馮": "冯", + "馯": "𫘛", + "馱": "驮", + "馳": "驰", + "馴": "驯", + "馹": "驲", + "馼": "𫘜", + "駁": "驳", + "駃": "𫘝", + "駊": "𫘟", + "駎": "𩧨", + "駐": "驻", + "駑": "驽", + "駒": "驹", + "駔": "驵", + "駕": "驾", + "駘": "骀", + "駙": "驸", + "駚": "𩧫", + "駛": "驶", + "駝": "驼", + "駞": "𫘞", + "駟": "驷", + "駡": "骂", + "駢": "骈", + "駤": "𫘠", + "駧": "𩧲", + "駩": "𩧴", + "駫": "𫘡", + "駭": "骇", + "駰": "骃", + "駱": "骆", + "駶": "𩧺", + "駸": "骎", + "駻": "𫘣", + "駿": "骏", + "騁": "骋", + "騂": "骍", + "騃": "𫘤", + "騄": "𫘧", + "騅": "骓", + "騉": "𫘥", + "騊": "𫘦", + "騌": "骔", + "騍": "骒", + "騎": "骑", + "騏": "骐", + "騔": "𩨀", + "騖": "骛", + "騙": "骗", + "騚": "𩨊", + "騜": "𫘩", + "騝": "𩨃", + "騟": "𩨈", + "騠": "𫘨", + "騤": "骙", + "騧": "䯄", + "騪": "𩨄", + "騫": "骞", + "騭": "骘", + "騮": "骝", + "騰": "腾", + "騱": "𫘬", + "騴": "𫘫", + "騵": "𫘪", + "騶": "驺", + "騷": "骚", + "騸": "骟", + "騻": "𫘭", + "騼": "𫠋", + "騾": "骡", + "驀": "蓦", + "驁": "骜", + "驂": "骖", + "驃": "骠", + "驄": "骢", + "驅": "驱", + "驊": "骅", + "驋": "𩧯", + "驌": "骕", + "驍": "骁", + "驏": "骣", + "驓": "𫘯", + "驕": "骄", + "驗": "验", + "驙": "𫘰", + "驚": "惊", + "驛": "驿", + "驟": "骤", + "驢": "驴", + "驤": "骧", + "驥": "骥", + "驦": "骦", + "驨": "𫘱", + "驪": "骊", + "驫": "骉", + "骯": "肮", + "髏": "髅", + "髒": "脏", + "體": "体", + "髕": "髌", + "髖": "髋", + "髮": "发", + "鬆": "松", + "鬍": "胡", + "鬖": "𩭹", + "鬚": "须", + "鬠": "𫘽", + "鬢": "鬓", + "鬥": "斗", + "鬧": "闹", + "鬨": "哄", + "鬩": "阋", + "鬮": "阄", + "鬱": "郁", + "鬹": "鬶", + "魎": "魉", + "魘": "魇", + "魚": "鱼", + "魛": "鱽", + "魟": "𫚉", + "魢": "鱾", + "魥": "𩽹", + "魦": "𫚌", + "魨": "鲀", + "魯": "鲁", + "魴": "鲂", + "魵": "𫚍", + "魷": "鱿", + "魺": "鲄", + "魽": "𫠐", + "鮁": "鲅", + "鮃": "鲆", + "鮄": "𫚒", + "鮅": "𫚑", + "鮆": "𫚖", + "鮊": "鲌", + "鮋": "鲉", + "鮍": "鲏", + "鮎": "鲇", + "鮐": "鲐", + "鮑": "鲍", + "鮒": "鲋", + "鮓": "鲊", + "鮕": "𩾀", + "鮚": "鲒", + "鮜": "鲘", + "鮝": "鲞", + "鮞": "鲕", + "鮟": "𩽾", + "鮣": "䲟", + "鮤": "𫚓", + "鮦": "鲖", + "鮪": "鲔", + "鮫": "鲛", + "鮭": "鲑", + "鮮": "鲜", + "鮯": "𫚗", + "鮰": "𫚔", + "鮳": "鲓", + "鮵": "𫚛", + "鮶": "鲪", + "鮸": "𩾃", + "鮺": "鲝", + "鮿": "𫚚", + "鯀": "鲧", + "鯁": "鲠", + "鯄": "𩾁", + "鯆": "𫚙", + "鯇": "鲩", + "鯉": "鲤", + "鯊": "鲨", + "鯒": "鲬", + "鯔": "鲻", + "鯕": "鲯", + "鯖": "鲭", + "鯗": "鲞", + "鯛": "鲷", + "鯝": "鲴", + "鯞": "𫚡", + "鯡": "鲱", + "鯢": "鲵", + "鯤": "鲲", + "鯧": "鲳", + "鯨": "鲸", + "鯪": "鲮", + "鯫": "鲰", + "鯬": "𫚞", + "鯰": "鲶", + "鯱": "𩾇", + "鯴": "鲺", + "鯶": "𩽼", + "鯷": "鳀", + "鯽": "鲫", + "鯾": "𫚣", + "鯿": "鳊", + "鰁": "鳈", + "鰂": "鲗", + "鰃": "鳂", + "鰆": "䲠", + "鰈": "鲽", + "鰉": "鳇", + "鰋": "𫚢", + "鰌": "䲡", + "鰍": "鳅", + "鰏": "鲾", + "鰐": "鳄", + "鰑": "𫚊", + "鰒": "鳆", + "鰓": "鳃", + "鰕": "𫚥", + "鰛": "鳁", + "鰜": "鳒", + "鰟": "鳑", + "鰠": "鳋", + "鰣": "鲥", + "鰤": "𫚕", + "鰥": "鳏", + "鰦": "𫚤", + "鰧": "䲢", + "鰨": "鳎", + "鰩": "鳐", + "鰫": "𫚦", + "鰭": "鳍", + "鰮": "鳁", + "鰱": "鲢", + "鰲": "鳌", + "鰳": "鳓", + "鰵": "鳘", + "鰷": "鲦", + "鰹": "鲣", + "鰺": "鲹", + "鰻": "鳗", + "鰼": "鳛", + "鰽": "𫚧", + "鰾": "鳔", + "鱂": "鳉", + "鱄": "𫚋", + "鱅": "鳙", + "鱆": "𫠒", + "鱇": "𩾌", + "鱈": "鳕", + "鱉": "鳖", + "鱊": "𫚪", + "鱒": "鳟", + "鱔": "鳝", + "鱖": "鳜", + "鱗": "鳞", + "鱘": "鲟", + "鱝": "鲼", + "鱟": "鲎", + "鱠": "鲙", + "鱢": "𫚫", + "鱣": "鳣", + "鱤": "鳡", + "鱧": "鳢", + "鱨": "鲿", + "鱭": "鲚", + "鱮": "𫚈", + "鱯": "鳠", + "鱲": "𫚭", + "鱷": "鳄", + "鱸": "鲈", + "鱺": "鲡", + "鳥": "鸟", + "鳧": "凫", + "鳩": "鸠", + "鳬": "凫", + "鳲": "鸤", + "鳳": "凤", + "鳴": "鸣", + "鳶": "鸢", + "鳷": "𫛛", + "鳼": "𪉃", + "鳽": "𫛚", + "鳾": "䴓", + "鴀": "𫛜", + "鴃": "𫛞", + "鴅": "𫛝", + "鴆": "鸩", + "鴇": "鸨", + "鴉": "鸦", + "鴐": "𫛤", + "鴒": "鸰", + "鴔": "𫛡", + "鴕": "鸵", + "鴗": "𫁡", + "鴛": "鸳", + "鴜": "𪉈", + "鴝": "鸲", + "鴞": "鸮", + "鴟": "鸱", + "鴣": "鸪", + "鴥": "𫛣", + "鴦": "鸯", + "鴨": "鸭", + "鴮": "𫛦", + "鴯": "鸸", + "鴰": "鸹", + "鴲": "𪉆", + "鴳": "𫛩", + "鴴": "鸻", + "鴷": "䴕", + "鴻": "鸿", + "鴽": "𫛪", + "鴿": "鸽", + "鵁": "䴔", + "鵂": "鸺", + "鵃": "鸼", + "鵊": "𫛥", + "鵐": "鹀", + "鵑": "鹃", + "鵒": "鹆", + "鵓": "鹁", + "鵚": "𪉍", + "鵜": "鹈", + "鵝": "鹅", + "鵟": "𫛭", + "鵠": "鹄", + "鵡": "鹉", + "鵧": "𫛨", + "鵩": "𫛳", + "鵪": "鹌", + "鵫": "𫛱", + "鵬": "鹏", + "鵮": "鹐", + "鵯": "鹎", + "鵰": "雕", + "鵲": "鹊", + "鵷": "鹓", + "鵾": "鹍", + "鶄": "䴖", + "鶇": "鸫", + "鶉": "鹑", + "鶊": "鹒", + "鶌": "𫛵", + "鶒": "𫛶", + "鶓": "鹋", + "鶖": "鹙", + "鶗": "𫛸", + "鶘": "鹕", + "鶚": "鹗", + "鶡": "鹖", + "鶥": "鹛", + "鶦": "𫛷", + "鶩": "鹜", + "鶪": "䴗", + "鶬": "鸧", + "鶭": "𫛯", + "鶯": "莺", + "鶰": "𫛫", + "鶲": "鹟", + "鶴": "鹤", + "鶹": "鹠", + "鶺": "鹡", + "鶻": "鹘", + "鶼": "鹣", + "鶿": "鹚", + "鷀": "鹚", + "鷁": "鹢", + "鷂": "鹞", + "鷄": "鸡", + "鷅": "𫛽", + "鷈": "䴘", + "鷉": "䴘", + "鷊": "鹝", + "鷐": "𫜀", + "鷓": "鹧", + "鷔": "𪉑", + "鷖": "鹥", + "鷗": "鸥", + "鷙": "鸷", + "鷚": "鹨", + "鷣": "𫜃", + "鷤": "𫛴", + "鷥": "鸶", + "鷦": "鹪", + "鷨": "𪉊", + "鷩": "𫜁", + "鷫": "鹔", + "鷯": "鹩", + "鷲": "鹫", + "鷳": "鹇", + "鷴": "鹇", + "鷷": "𫜄", + "鷸": "鹬", + "鷹": "鹰", + "鷺": "鹭", + "鷽": "鸴", + "鷿": "䴙", + "鸂": "㶉", + "鸇": "鹯", + "鸊": "䴙", + "鸋": "𫛢", + "鸌": "鹱", + "鸏": "鹲", + "鸕": "鸬", + "鸗": "𫛟", + "鸘": "鹴", + "鸚": "鹦", + "鸛": "鹳", + "鸝": "鹂", + "鸞": "鸾", + "鹵": "卤", + "鹹": "咸", + "鹺": "鹾", + "鹼": "碱", + "鹽": "盐", + "麗": "丽", + "麥": "麦", + "麨": "𪎊", + "麩": "麸", + "麪": "面", + "麫": "面", + "麬": "𤿲", + "麯": "曲", + "麲": "𪎉", + "麳": "𪎌", + "麴": "曲", + "麵": "面", + "麷": "𫜑", + "麼": "么", + "麽": "么", + "黃": "黄", + "黌": "黉", + "點": "点", + "黨": "党", + "黲": "黪", + "黴": "霉", + "黶": "黡", + "黷": "黩", + "黽": "黾", + "黿": "鼋", + "鼂": "鼌", + "鼉": "鼍", + "鼕": "冬", + "鼴": "鼹", + "齇": "齄", + "齊": "齐", + "齋": "斋", + "齎": "赍", + "齏": "齑", + "齒": "齿", + "齔": "龀", + "齕": "龁", + "齗": "龂", + "齙": "龅", + "齜": "龇", + "齟": "龃", + "齠": "龆", + "齡": "龄", + "齣": "出", + "齦": "龈", + "齧": "啮", + "齩": "𫜪", + "齪": "龊", + "齬": "龉", + "齭": "𫜭", + "齯": "𫠜", + "齰": "𫜬", + "齲": "龋", + "齴": "𫜮", + "齶": "腭", + "齷": "龌", + "齾": "𫜰", + "龍": "龙", + "龎": "厐", + "龐": "庞", + "龑": "䶮", + "龓": "𫜲", + "龔": "龚", + "龕": "龛", + "龜": "龟", + "龭": "𩨎", + "龯": "𨱆", + "鿁": "䜤", + "鿓": "鿒", + "𠁞": "𠀾", + "𠌥": "𠆿", + "𠏢": "𠉗", + "𠐊": "𫝋", + "𠗣": "㓆", + "𠞆": "𠛆", + "𠠎": "𠚳", + "𠬙": "𪠡", + "𠽃": "𪠺", + "𠿕": "𪜎", + "𡂡": "𪢒", + "𡃄": "𪡺", + "𡃕": "𠴛", + "𡃤": "𪢐", + "𡄔": "𠴢", + "𡄣": "𠵸", + "𡅏": "𠲥", + "𡅯": "𪢖", + "𡑭": "𡋗", + "𡓁": "𪤄", + "𡓾": "𡋀", + "𡔖": "𡍣", + "𡞵": "㛟", + "𡟫": "𫝪", + "𡠹": "㛿", + "𡡎": "𡞱", + "𡢃": "㛠", + "𡮉": "𡭜", + "𡮣": "𡭬", + "𡳳": "𡳃", + "𡸗": "𪨩", + "𡹬": "𪨹", + "𡻕": "岁", + "𡽗": "𡸃", + "𡾱": "㟜", + "𡿖": "𪩛", + "𢍰": "𪪴", + "𢠼": "𢙑", + "𢣐": "𪬚", + "𢣚": "𢘝", + "𢣭": "𢘞", + "𢤩": "𪫡", + "𢤱": "𢘙", + "𢤿": "𪬯", + "𢯷": "𪭝", + "𢶒": "𪭯", + "𢶫": "𢫞", + "𢷬": "𢭏", + "𢷮": "𢫊", + "𢹿": "𢬦", + "𢺳": "𪮳", + "𣈶": "暅", + "𣋋": "𣈣", + "𣍐": "𠊉", + "𣙎": "㭣", + "𣜬": "𪳗", + "𣝕": "𣘷", + "𣞻": "𣘓", + "𣠩": "𣞎", + "𣠲": "𣑶", + "𣯩": "𣯣", + "𣯴": "𣭤", + "𣯶": "毶", + "𣽏": "𪶮", + "𣾷": "㳢", + "𣿉": "𣶫", + "𤁣": "𣺽", + "𤄷": "𪶒", + "𤅶": "𣷷", + "𤑳": "𤎻", + "𤑹": "𪹀", + "𤒎": "𤊀", + "𤒻": "𪹹", + "𤓌": "𪹠", + "𤓩": "𤊰", + "𤘀": "𪺣", + "𤛮": "𤙯", + "𤛱": "𫞢", + "𤜆": "𪺪", + "𤠮": "𪺸", + "𤢟": "𤝢", + "𤢻": "𢢐", + "𤩂": "𫞧", + "𤪺": "㻘", + "𤫩": "㻏", + "𤬅": "𪼴", + "𤳷": "𪽝", + "𤳸": "𤳄", + "𤷃": "𪽭", + "𤸫": "𤶧", + "𤺔": "𪽴", + "𥊝": "𥅿", + "𥌃": "𥅘", + "𥏝": "𪿊", + "𥕥": "𥐰", + "𥖅": "𥐯", + "𥖲": "𪿞", + "𥗇": "𪿵", + "𥜐": "𫀓", + "𥜰": "𫀌", + "𥞵": "𥞦", + "𥢢": "䅪", + "𥢶": "𫞷", + "𥢷": "𫀮", + "𥨐": "𥧂", + "𥪂": "𥩺", + "𥯤": "𫁳", + "𥴨": "𫂖", + "𥴼": "𫁺", + "𥵃": "𥱔", + "𥵊": "𥭉", + "𥶽": "𫁱", + "𥸠": "𥮋", + "𥻦": "𫂿", + "𥼽": "𥹥", + "𥽖": "𥺇", + "𥾯": "𫄝", + "𥿊": "𦈈", + "𦀖": "𫄦", + "𦂅": "𦈒", + "𦃄": "𦈗", + "𦃩": "𫄯", + "𦅇": "𫄪", + "𦅈": "𫄵", + "𦆲": "𫟇", + "𦒀": "𫅥", + "𦔖": "𫅼", + "𦘧": "𡳒", + "𦟼": "𫆝", + "𦠅": "𫞅", + "𦡝": "𫆫", + "𦢈": "𣍨", + "𦣎": "𦟗", + "𦧺": "𫇘", + "𦪙": "䑽", + "𦪽": "𦨩", + "𦱌": "𫇪", + "𦾟": "𦶻", + "𧎈": "𧌥", + "𧒯": "𫊹", + "𧔥": "𧒭", + "𧕟": "𧉐", + "𧜗": "䘞", + "𧜵": "䙊", + "𧝞": "䘛", + "𧞫": "𫌋", + "𧟀": "𧝧", + "𧡴": "𫌫", + "𧢄": "𫌬", + "𧦝": "𫍞", + "𧦧": "𫍟", + "𧩕": "𫍭", + "𧩙": "䜥", + "𧩼": "𫍶", + "𧫝": "𫍺", + "𧬤": "𫍼", + "𧭈": "𫍾", + "𧭹": "𫍐", + "𧳟": "𧳕", + "𧵳": "䞌", + "𧶔": "𧹓", + "𧶧": "䞎", + "𧷎": "𪠀", + "𧸘": "𫎨", + "𧹈": "𪥠", + "𧽯": "𫎸", + "𨂐": "𫏌", + "𨄣": "𨀱", + "𨅍": "𨁴", + "𨆪": "𫏕", + "𨇁": "𧿈", + "𨇞": "𨅫", + "𨇤": "𫏨", + "𨇰": "𫏞", + "𨇽": "𫏑", + "𨈊": "𨂺", + "𨈌": "𨄄", + "𨊰": "䢀", + "𨊸": "䢁", + "𨊻": "𨐆", + "𨋢": "䢂", + "𨌈": "𫐍", + "𨍰": "𫐔", + "𨎌": "𫐋", + "𨎮": "𨐉", + "𨏠": "𨐇", + "𨏥": "𨐊", + "𨞺": "𫟫", + "𨟊": "𫟬", + "𨢿": "𨡙", + "𨣈": "𨡺", + "𨣞": "𨟳", + "𨣧": "𨠨", + "𨤻": "𨤰", + "𨥛": "𨱀", + "𨥟": "𫓫", + "𨦫": "䦀", + "𨧀": "𬭊", + "𨧜": "䦁", + "𨧰": "𫟽", + "𨧱": "𨱊", + "𨨏": "𬭛", + "𨨛": "𫓼", + "𨨢": "𫓿", + "𨩰": "𫟾", + "𨪕": "𫓮", + "𨫒": "𨱐", + "𨬖": "𫔏", + "𨭆": "𬭶", + "𨭎": "𬭳", + "𨭖": "𫔑", + "𨭸": "𫔐", + "𨮂": "𨱕", + "𨮳": "𫔒", + "𨯅": "䥿", + "𨯟": "𫔓", + "𨰃": "𫔉", + "𨰋": "𫓳", + "𨰥": "𫔕", + "𨰲": "𫔃", + "𨲳": "𫔖", + "𨳑": "𨸁", + "𨳕": "𨸀", + "𨴗": "𨸅", + "𨴹": "𫔲", + "𨵩": "𨸆", + "𨵸": "𨸇", + "𨶀": "𨸉", + "𨶏": "𨸊", + "𨶮": "𨸌", + "𨶲": "𨸋", + "𨷲": "𨸎", + "𨼳": "𫔽", + "𨽏": "𨸘", + "𩀨": "𫕚", + "𩅙": "𫕨", + "𩎖": "𫖑", + "𩎢": "𩏾", + "𩏂": "𫖓", + "𩏠": "𫖖", + "𩏪": "𩏽", + "𩏷": "𫃗", + "𩑔": "𫖪", + "𩒎": "𫖭", + "𩓣": "𩖕", + "𩓥": "𫖵", + "𩔑": "𫖷", + "𩔳": "𫖴", + "𩖰": "𫠇", + "𩗀": "𩙦", + "𩗓": "𫗈", + "𩗴": "𫗉", + "𩘀": "𩙩", + "𩘝": "𩙭", + "𩘹": "𩙨", + "𩘺": "𩙬", + "𩙈": "𩙰", + "𩚛": "𩟿", + "𩚥": "𩠀", + "𩚩": "𫗡", + "𩚵": "𩠁", + "𩛆": "𩠂", + "𩛌": "𫗤", + "𩛡": "𫗨", + "𩛩": "𩠃", + "𩜇": "𩠉", + "𩜦": "𩠆", + "𩜵": "𩠊", + "𩝔": "𩠋", + "𩝽": "𫗳", + "𩞄": "𩠎", + "𩞦": "𩠏", + "𩞯": "䭪", + "𩟐": "𩠅", + "𩟗": "𫗚", + "𩠴": "𩠠", + "𩡣": "𩡖", + "𩡺": "𩧦", + "𩢡": "𩧬", + "𩢴": "𩧵", + "𩢸": "𩧳", + "𩢾": "𩧮", + "𩣏": "𩧶", + "𩣑": "䯃", + "𩣫": "𩧸", + "𩣵": "𩧻", + "𩣺": "𩧼", + "𩤊": "𩧩", + "𩤙": "𩨆", + "𩤲": "𩨉", + "𩤸": "𩨅", + "𩥄": "𩨋", + "𩥇": "𩨍", + "𩥉": "𩧱", + "𩥑": "𩨌", + "𩦠": "𫠌", + "𩧆": "𩨐", + "𩭙": "𩬣", + "𩯁": "𫙂", + "𩯳": "𩯒", + "𩰀": "𩬤", + "𩰹": "𩰰", + "𩳤": "𩲒", + "𩴵": "𩴌", + "𩵦": "𫠏", + "𩵩": "𩽺", + "𩵹": "𩽻", + "𩶁": "𫚎", + "𩶘": "䲞", + "𩶰": "𩽿", + "𩶱": "𩽽", + "𩷰": "𩾄", + "𩸃": "𩾅", + "𩸄": "𫚝", + "𩸡": "𫚟", + "𩸦": "𩾆", + "𩻗": "𫚨", + "𩻬": "𫚩", + "𩻮": "𫚘", + "𩼶": "𫚬", + "𩽇": "𩾎", + "𩿅": "𫠖", + "𩿤": "𫛠", + "𩿪": "𪉄", + "𪀖": "𫛧", + "𪀦": "𪉅", + "𪀾": "𪉋", + "𪁈": "𪉉", + "𪁖": "𪉌", + "𪂆": "𪉎", + "𪃍": "𪉐", + "𪃏": "𪉏", + "𪃒": "𫛻", + "𪃧": "𫛹", + "𪄆": "𪉔", + "𪄕": "𪉒", + "𪅂": "𫜂", + "𪆷": "𫛾", + "𪇳": "𪉕", + "𪈼": "𪉓", + "𪉸": "𫜊", + "𪋿": "𪎍", + "𪌭": "𫜓", + "𪍠": "𫜕", + "𪓰": "𫜟", + "𪔵": "𪔭", + "𪘀": "𪚏", + "𪘯": "𪚐", + "𪙏": "𫜯", + "𪟖": "𠛾", + "𪷓": "𣶭", + "𫒡": "𫓷", + "𫜦": "𫜫", +} diff --git a/set-encoding.py b/set-encoding.py index ce2b5f9..63ce3e9 100644 --- a/set-encoding.py +++ b/set-encoding.py @@ -1,21 +1,20 @@ import sys import json import codecs -from types import SimpleNamespace as Namespace import configure if __name__ == '__main__': - param = sys.argv[1] - param = Namespace(**json.loads(param)) + param = sys.argv[1] + param = json.loads(param) - dep = Namespace(**param.__dict__) - dep.encoding = "unspec" + dep = {**param, "encoding": "unspec"} - with open("build/nowar/{}.otd".format(configure.GenerateFilename(dep)), 'rb') as baseFile: - baseFont = json.loads(baseFile.read().decode('UTF-8', errors='replace')) + with open("build/nowar/{}.otd".format(configure.GenerateFilename(dep)), 'rb') as baseFile: + baseFont = json.loads( + baseFile.read().decode('UTF-8', errors='replace')) - baseFont['OS_2']['ulCodePageRange1'][param.encoding] = True + baseFont['OS_2']['ulCodePageRange1'][param["encoding"]] = True - outStr = json.dumps(baseFont, ensure_ascii=False, separators=(',',':')) - with codecs.open("build/nowar/{}.otd".format(configure.GenerateFilename(param)), 'w', 'UTF-8') as outFile: - outFile.write(outStr) + outStr = json.dumps(baseFont, ensure_ascii=False, separators=(',', ':')) + with codecs.open("build/nowar/{}.otd".format(configure.GenerateFilename(param)), 'w', 'UTF-8') as outFile: + outFile.write(outStr)