├── pictures ├── hn001.jpg └── hn002.jpg ├── codes ├── vert.txt ├── fwid.txt ├── dlig.txt └── build.py ├── .github └── workflows │ └── build.yml ├── README.md └── README-TC.md /pictures/hn001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuiWonder/LanternMing/HEAD/pictures/hn001.jpg -------------------------------------------------------------------------------- /pictures/hn002.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuiWonder/LanternMing/HEAD/pictures/hn002.jpg -------------------------------------------------------------------------------- /codes/vert.txt: -------------------------------------------------------------------------------- 1 | ‥ ︰ 2 | 《 ︽ 3 | 》 ︾ 4 | 「 ﹁ 5 | 」 ﹂ 6 | 『 ﹃ 7 | 』 ﹄ 8 | 【 ︻ 9 | 】 ︼ 10 | 〔 ︹ 11 | 〕 ︺ 12 | 〖 ︗ 13 | 〗 ︘ 14 | ( ︵ 15 | ) ︶ 16 | [ ﹇ 17 | ] ﹈ 18 | _ ︳ 19 | { ︷ 20 | } ︸ 21 | — ︱ 22 | ‘ ﹁ 23 | ’ ﹂ 24 | “ ﹃ 25 | ” ﹄ 26 | … ︙ 27 | 、 ︑ 28 | 。 ︒ 29 | 〈 ︿ 30 | 〉 ﹀ 31 | ﹏ ︴ 32 | ! ︕ 33 | , ︐ 34 | : ︓ 35 | ; ︔ 36 | ? ︖ 37 | -------------------------------------------------------------------------------- /codes/fwid.txt: -------------------------------------------------------------------------------- 1 |   2 |     3 | ! ! 4 | # # 5 | $ $ 6 | % % 7 | & & 8 | ( ( 9 | ) ) 10 | * * 11 | + + 12 | - - 13 | / / 14 | 0 0 15 | 1 1 16 | 2 2 17 | 3 3 18 | 4 4 19 | 5 5 20 | 6 6 21 | 7 7 22 | 8 8 23 | 9 9 24 | : : 25 | ; ; 26 | < < 27 | = = 28 | > > 29 | ? ? 30 | @ @ 31 | A A 32 | B B 33 | C C 34 | D D 35 | E E 36 | F F 37 | G G 38 | H H 39 | I I 40 | J J 41 | K K 42 | L L 43 | M M 44 | N N 45 | O O 46 | P P 47 | Q Q 48 | R R 49 | S S 50 | T T 51 | U U 52 | V V 53 | W W 54 | X X 55 | Y Y 56 | Z Z 57 | [ [ 58 | \ \ 59 | ] ] 60 | ^ ^ 61 | _ _ 62 | ` ` 63 | a a 64 | b b 65 | c c 66 | d d 67 | e e 68 | f f 69 | g g 70 | h h 71 | i i 72 | j j 73 | k k 74 | l l 75 | m m 76 | n n 77 | o o 78 | p p 79 | q q 80 | r r 81 | s s 82 | t t 83 | u u 84 | v v 85 | w w 86 | x x 87 | y y 88 | z z 89 | { { 90 | | | 91 | } } 92 | ~ ~ 93 | ¥ ¥ 94 | ₩ ₩ 95 | " " 96 | ' ' 97 |     98 | │ | 99 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - name: Install fontforge 12 | run: sudo apt update && sudo apt install python3-fontforge 13 | - name: Get fonts 14 | run: | 15 | wget -P ./codes https://glyphwiki.org/font/gw1796612.ttf 16 | wget -P ./codes https://glyphwiki.org/font/gw1796547.ttf 17 | wget -P ./codes https://glyphwiki.org/font/gw3479103.ttf 18 | wget -P ./codes https://glyphwiki.org/font/gw3479104.ttf 19 | wget -P ./codes https://glyphwiki.org/font/gw3664726.ttf 20 | wget -P ./codes https://glyphwiki.org/font/gw4079303.ttf 21 | wget -P ./codes https://glyphwiki.org/font/gw6267281.ttf 22 | - name: Build A 23 | run: python3 ./codes/build.py ./LanternMingA.ttf A ./codes/gw1796612.ttf ./codes/gw3664726.ttf ./codes/gw3479103.ttf ./codes/gw4079303.ttf ./codes/gw6267281.ttf 24 | - name: Build B 25 | run: python3 ./codes/build.py ./LanternMingB.ttf B ./codes/gw1796547.ttf ./codes/gw3664726.ttf ./codes/gw3479104.ttf ./codes/gw4079303.ttf ./codes/gw6267281.ttf 26 | 27 | - uses: actions/upload-artifact@v4 28 | with: 29 | name: LanternMing 30 | path: "*.ttf" 31 | 32 | #- name: Upload to release 33 | # uses: ncipollo/release-action@v1 34 | # with: 35 | # token: "${{ secrets.GITHUB_TOKEN }}" 36 | # tag: "test-001" 37 | # artifacts: "*.ttf" 38 | # allowUpdates: true 39 | # prerelease: true 40 | # draft: true 41 | # name: "Build Test" 42 | # body: "LanternMing TTF" 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **简体中文** [繁體中文](README-TC.md#LanternMing-上元明朝) 2 | # LanternMing 上元明朝 3 | 上元明朝是一款自由开源的旧字形汉字字体,这款字体的特点是涵盖了目前 CJK (中日韩统一表意文字)字符集中所有的汉字。该字体基于醍醐书体与花园明朝制作,作为开源项目,任何人可自由下载使用。 4 | 5 | ## 说明 6 | - 完整支持 Unicode 17.0.0 标准中的全部汉字。 7 | - 汉字优先采用醍醐明朝的旧字形设计。 8 | - 继承花园明朝丰富的非汉字字符,兼容多种语言与符号。 9 | - 新增多项 OpenType 功能,包括竖排排版、全角字符替换及自由连字特性。 10 | - 与醍醐书体及花园明朝一致,本字体采用 2 个字体文件。 11 | ## 预览 12 | ![image](./pictures/hn001.jpg) 13 | ![image](./pictures/hn002.jpg) 14 | 15 | ## 汉字部分统计 16 | | 区块名称 | 上元明朝A | 上元明朝B | 上元明朝总数 | Unicode 收录总数 | 17 | | ---- | ---- | ---- | ---- | ---- | 18 | | 中日韩统一表意文字 (基本区) | 20992 | 1 | 20992 | 20992 | 19 | | 中日韩统一表意文字扩展区A | 6592 | 0 | 6592 | 6592 | 20 | | 中日韩统一表意文字扩展区B | 0 | 42720 | 42720 | 42720 | 21 | | 中日韩统一表意文字扩展区C | 4160 | 0 | 4160 | 4160 | 22 | | 中日韩统一表意文字扩展区D | 222 | 0 | 222 | 222 | 23 | | 中日韩统一表意文字扩展区E | 5774 | 0 | 5774 | 5774 | 24 | | 中日韩统一表意文字扩展区F | 7473 | 0 | 7473 | 7473 | 25 | | 中日韩统一表意文字扩展区G | 4939 | 0 | 4939 | 4939 | 26 | | 中日韩统一表意文字扩展区H | 4192 | 0 | 4192 | 4192 | 27 | | 中日韩统一表意文字扩展区I | 0 | 622 | 622 | 622 | 28 | | 中日韩统一表意文字扩展区J | 0 | 4298 | 4298 | 4298 | 29 | | 汉字〇 | 1 | 0 | 1 | 1 | 30 | | 中日韩兼容表意文字 | 472 | 0 | 472 | 472 | 31 | | 中日韩兼容表意文字补充区 | 542 | 0 | 542 | 542 | 32 | | 康熙部首 | 214 | 0 | 214 | 214 | 33 | | 中日韩汉字部首补充 | 115 | 0 | 115 | 115 | 34 | | 合计 | 55688 | 47641 | 103328 | 103328 | 35 | > 字体统计工具: https://github.com/GuiWonder/FontCountTool 36 | 37 | ## 下载字体 38 | 可从本站 [Releases](../../releases) 页面下载字体。 39 | 40 | ## 授权 41 | 遵循[GlyphWiki:著作权与许可协议](http://zhs.glyphwiki.org/wiki/GlyphWiki:著作权与许可协议)。 42 | 43 | ## 相关链接 44 | * [字形维基(GlyphWiki)](https://glyphwiki.org/) 45 | * [醍醐书体A](https://glyphwiki.org/wiki/Group:nobu_醍醐書體A) 46 | * [醍醐书体B](https://glyphwiki.org/wiki/Group:nobu_醍醐書體B) 47 | * [花园明朝A](https://glyphwiki.org/wiki/Group:kamichi_hma) 48 | * [花园明朝B](https://glyphwiki.org/wiki/Group:kamichi_hmb) 49 | * [AppendingToHanaMin](https://glyphwiki.org/wiki/Group:cutra_AppendingToHanaMin) 50 | * [spinda-kkmr_拡張I暫定](https://glyphwiki.org/wiki/Group:spinda-kkmr_拡張I暫定) 51 | * [spinda-kkmr_拡張J暫定](https://glyphwiki.org/wiki/Group:spinda-kkmr_拡張J暫定) 52 | * [FontForge](https://github.com/fontforge/fontforge) 53 | -------------------------------------------------------------------------------- /README-TC.md: -------------------------------------------------------------------------------- 1 | [简体中文](../../#LanternMing-上元明朝) **繁體中文** 2 | # LanternMing 上元明朝 3 | 上元明朝是一款自由開源的舊字形漢字字型,這款字型的特點是涵蓋了目前 CJK (中日韓統一表意文字)字符集中所有的漢字。該字型基於醍醐書體與花園明朝製作,作為開源專案,任何人可自由下載使用。 4 | 5 | ## 說明 6 | - 完整支援 Unicode 17.0.0 標準中的全部漢字。 7 | - 漢字優先採用醍醐明朝的舊字形設計。 8 | - 繼承花園明朝豐富的非漢字字元,相容多種語言與符號。 9 | - 新增多項 OpenType 功能,包括豎排排版、全形字元替換及自由連字特性。 10 | - 與醍醐書體及花園明朝一致,本字型採用 2 個字型檔案。 11 | 12 | ## 預覽 13 | ![image](./pictures/hn001.jpg) 14 | ![image](./pictures/hn002.jpg) 15 | 16 | ## 漢字部分統計 17 | | 區塊名稱 | 上元明朝A | 上元明朝B | 上元明朝總數 | Unicode 收錄總數 | 18 | | ---- | ---- | ---- | ---- | ---- | 19 | | 中日韓統一表意文字 (基本區) | 20992 | 1 | 20992 | 20992 | 20 | | 中日韓統一表意文字擴充區A | 6592 | 0 | 6592 | 6592 | 21 | | 中日韓統一表意文字擴充區B | 0 | 42720 | 42720 | 42720 | 22 | | 中日韓統一表意文字擴充區C | 4160 | 0 | 4160 | 4160 | 23 | | 中日韓統一表意文字擴充區D | 222 | 0 | 222 | 222 | 24 | | 中日韓統一表意文字擴充區E | 5774 | 0 | 5774 | 5774 | 25 | | 中日韓統一表意文字擴充區F | 7473 | 0 | 7473 | 7473 | 26 | | 中日韓統一表意文字擴充區G | 4939 | 0 | 4939 | 4939 | 27 | | 中日韓統一表意文字擴充區H | 4192 | 0 | 4192 | 4192 | 28 | | 中日韓統一表意文字擴充區I | 0 | 622 | 622 | 622 | 29 | | 中日韓統一表意文字擴充區J | 0 | 4298 | 4298 | 4298 | 30 | | 漢字〇 | 1 | 0 | 1 | 1 | 31 | | 中日韓相容表意文字 | 472 | 0 | 472 | 472 | 32 | | 中日韓相容表意文字補充區 | 542 | 0 | 542 | 542 | 33 | | 康熙部首 | 214 | 0 | 214 | 214 | 34 | | 中日韓漢字部首補充 | 115 | 0 | 115 | 115 | 35 | | 合計 | 55688 | 47641 | 103328 | 103328 | 36 | > 字型統計工具: https://github.com/GuiWonder/FontCountTool 37 | 38 | ## 下載字型 39 | 可從本站 [Releases](../../releases) 頁面下載字型。 40 | 41 | ## 授權 42 | 遵循[GlyphWiki:著作權與許可協議](http://zht.glyphwiki.org/wiki/GlyphWiki:著作權與許可協議)。 43 | 44 | ## 相關鏈接 45 | * [字形維基(GlyphWiki)](https://glyphwiki.org/) 46 | * [醍醐書體A](https://glyphwiki.org/wiki/Group:nobu_醍醐書體A) 47 | * [醍醐書體B](https://glyphwiki.org/wiki/Group:nobu_醍醐書體B) 48 | * [花園明朝A](https://glyphwiki.org/wiki/Group:kamichi_hma) 49 | * [花園明朝B](https://glyphwiki.org/wiki/Group:kamichi_hmb) 50 | * [AppendingToHanaMin](https://glyphwiki.org/wiki/Group:cutra_AppendingToHanaMin) 51 | * [spinda-kkmr_拡張I暫定](https://glyphwiki.org/wiki/Group:spinda-kkmr_拡張I暫定) 52 | * [spinda-kkmr_拡張J暫定](https://glyphwiki.org/wiki/Group:spinda-kkmr_拡張J暫定) 53 | * [FontForge](https://github.com/fontforge/fontforge) 54 | -------------------------------------------------------------------------------- /codes/dlig.txt: -------------------------------------------------------------------------------- 1 | ! ! ‼ 2 | ! ? ⁉ 3 | 0 点 ㍘ 4 | 1 0 日 ㏩ 5 | 1 0 月 ㋉ 6 | 1 0 点 ㍢ 7 | 1 1 日 ㏪ 8 | 1 1 月 ㋊ 9 | 1 1 点 ㍣ 10 | 1 2 日 ㏫ 11 | 1 2 月 ㋋ 12 | 1 2 点 ㍤ 13 | 1 3 日 ㏬ 14 | 1 3 点 ㍥ 15 | 1 4 日 ㏭ 16 | 1 4 点 ㍦ 17 | 1 5 日 ㏮ 18 | 1 5 点 ㍧ 19 | 1 6 日 ㏯ 20 | 1 6 点 ㍨ 21 | 1 7 日 ㏰ 22 | 1 7 点 ㍩ 23 | 1 8 日 ㏱ 24 | 1 8 点 ㍪ 25 | 1 9 日 ㏲ 26 | 1 9 点 ㍫ 27 | 1 日 ㏠ 28 | 1 月 ㋀ 29 | 1 点 ㍙ 30 | 2 0 日 ㏳ 31 | 2 0 点 ㍬ 32 | 2 1 日 ㏴ 33 | 2 1 点 ㍭ 34 | 2 2 日 ㏵ 35 | 2 2 点 ㍮ 36 | 2 3 日 ㏶ 37 | 2 3 点 ㍯ 38 | 2 4 日 ㏷ 39 | 2 4 点 ㍰ 40 | 2 5 日 ㏸ 41 | 2 6 日 ㏹ 42 | 2 7 日 ㏺ 43 | 2 8 日 ㏻ 44 | 2 9 日 ㏼ 45 | 2 日 ㏡ 46 | 2 月 ㋁ 47 | 2 点 ㍚ 48 | 3 0 日 ㏽ 49 | 3 1 日 ㏾ 50 | 3 日 ㏢ 51 | 3 月 ㋂ 52 | 3 点 ㍛ 53 | 4 日 ㏣ 54 | 4 月 ㋃ 55 | 4 点 ㍜ 56 | 5 日 ㏤ 57 | 5 月 ㋄ 58 | 5 点 ㍝ 59 | 6 日 ㏥ 60 | 6 月 ㋅ 61 | 6 点 ㍞ 62 | 7 日 ㏦ 63 | 7 月 ㋆ 64 | 7 点 ㍟ 65 | 8 日 ㏧ 66 | 8 月 ㋇ 67 | 8 点 ㍠ 68 | 9 日 ㏨ 69 | 9 月 ㋈ 70 | 9 点 ㍡ 71 | ? ! ⁈ 72 | ? ? ⁇ 73 | A / m ㏟ 74 | A U ㍳ 75 | B q ㏃ 76 | C / k g ㏆ 77 | C o . ㏇ 78 | F A X ℻ 79 | G H z ㎓ 80 | G P a ㎬ 81 | G B ㎇ 82 | G y ㏉ 83 | H P ㏋ 84 | H g ㋌ 85 | H z ㎐ 86 | I U ㍺ 87 | J I S 〄 88 | K B ㎅ 89 | K K ㏍ 90 | K M ㏎ 91 | K S ㉿ 92 | L T D ㋏ 93 | M H z ㎒ 94 | M P a ㎫ 95 | M B ㎆ 96 | M V ㎹ 97 | M W ㎿ 98 | M Ω ㏁ 99 | P P M ㏙ 100 | P T E ㉐ 101 | P H ㏗ 102 | P R ㏚ 103 | P a ㎩ 104 | S v ㏜ 105 | T H z ㎔ 106 | V / m ㏞ 107 | W b ㏝ 108 | a . m . ㏂ 109 | b a r ㍴ 110 | c a l ㎈ 111 | c m 2 ㎠ 112 | c m 3 ㎤ 113 | c m ² ㎠ 114 | c m ³ ㎤ 115 | c c ㏄ 116 | c d ㏅ 117 | c m ㎝ 118 | d m 2 ㍸ 119 | d m 3 ㍹ 120 | d m ² ㍸ 121 | d m ³ ㍹ 122 | d B ㏈ 123 | d a ㍲ 124 | d m ㍷ 125 | d ℓ ㎗ 126 | e r g ㋍ 127 | e V ㋎ 128 | f m ㎙ 129 | g a l ㏿ 130 | h P a ㍱ 131 | h a ㏊ 132 | i n ㏌ 133 | k c a l ㎉ 134 | k H z ㎑ 135 | k P a ㎪ 136 | k m 2 ㎢ 137 | k m 3 ㎦ 138 | k m ² ㎢ 139 | k m ³ ㎦ 140 | k A ㎄ 141 | k V ㎸ 142 | k W ㎾ 143 | k g ㎏ 144 | k m ㎞ 145 | k t ㏏ 146 | k Ω ㏀ 147 | k ℓ ㎘ 148 | l o g ㏒ 149 | l m ㏐ 150 | l n ㏑ 151 | l x ㏓ 152 | m / s 2 ㎨ 153 | m / s ² ㎨ 154 | m / s ㎧ 155 | m i l ㏕ 156 | m m 2 ㎟ 157 | m m 3 ㎣ 158 | m m ² ㎟ 159 | m m ³ ㎣ 160 | m o l ㏖ 161 | m 2 ㎡ 162 | m 3 ㎥ 163 | m A ㎃ 164 | m V ㎷ 165 | m W ㎽ 166 | m b ㏔ 167 | m g ㎎ 168 | m m ㎜ 169 | m s ㎳ 170 | m ² ㎡ 171 | m ³ ㎥ 172 | m ℓ ㎖ 173 | n A ㎁ 174 | n F ㎋ 175 | n V ㎵ 176 | n W ㎻ 177 | n m ㎚ 178 | n s ㎱ 179 | o V ㍵ 180 | p . m . ㏘ 181 | p A ㎀ 182 | p F ㎊ 183 | p V ㎴ 184 | p W ㎺ 185 | p c ㍶ 186 | p s ㎰ 187 | r a d / s 2 ㎯ 188 | r a d / s ² ㎯ 189 | r a d / s ㎮ 190 | r a d ㎭ 191 | s r ㏛ 192 | μ A ㎂ 193 | μ F ㎌ 194 | μ V ㎶ 195 | μ W ㎼ 196 | μ g ㎍ 197 | μ m ㎛ 198 | μ s ㎲ 199 | μ ℓ ㎕ 200 | ほ か 🈀 201 | よ り ゟ 202 | ア パ ー ト ㌀ 203 | ア ル フ ァ ㌁ 204 | ア ン ペ ア ㌂ 205 | ア ー ル ㌃ 206 | イ ニ ン グ ㌄ 207 | イ ン チ ㌅ 208 | ウ ォ ン ㌆ 209 | エ ス ク ー ド ㌇ 210 | エ ー カ ー ㌈ 211 | オ ン ス ㌉ 212 | オ ー ム ㌊ 213 | カ ラ ッ ト ㌌ 214 | カ ロ リ ー ㌍ 215 | カ イ リ ㌋ 216 | ガ ロ ン ㌎ 217 | ガ ン マ ㌏ 218 | キ ロ メ ー ト ル ㌖ 219 | キ ロ グ ラ ム ㌕ 220 | キ ロ ワ ッ ト ㌗ 221 | キ ュ リ ー ㌒ 222 | キ ロ ㌔ 223 | ギ ル ダ ー ㌓ 224 | ギ ニ ー ㌑ 225 | ギ ガ ㌐ 226 | ク ル ゼ イ ロ ㌚ 227 | ク ロ ー ネ ㌛ 228 | グ ラ ム ト ン ㌙ 229 | グ ラ ム ㌘ 230 | ケ ー ス ㌜ 231 | コ ル ナ ㌝ 232 | コ ー ポ ㌞ 233 | コ ト ヿ 234 | サ ン チ ー ム ㌠ 235 | サ イ ク ル ㌟ 236 | シ リ ン グ ㌡ 237 | セ ン チ ㌢ 238 | セ ン ト ㌣ 239 | ダ ー ス ㌤ 240 | デ シ ㌥ 241 | ト ン ㌧ 242 | ド ル ㌦ 243 | ナ ノ ㌨ 244 | ノ ッ ト ㌩ 245 | ハ イ ツ ㌪ 246 | バ ー レ ル ㌭ 247 | パ ー セ ン ト ㌫ 248 | ビ ル ㌱ 249 | ピ ア ス ト ル ㌮ 250 | ピ ク ル ㌯ 251 | ピ コ ㌰ 252 | フ ァ ラ ッ ド ㌲ 253 | フ ィ ー ト ㌳ 254 | フ ラ ン ㌵ 255 | ブ ッ シ ェ ル ㌴ 256 | ヘ ク タ ー ル ㌶ 257 | ヘ ル ツ ㌹ 258 | ベ ー タ ㌼ 259 | ペ ニ ヒ ㌸ 260 | ペ ン ス ㌺ 261 | ペ ー ジ ㌻ 262 | ペ ソ ㌷ 263 | ホ ー ル ㍁ 264 | ホ ー ン ㍂ 265 | ホ ン ㌿ 266 | ボ ル ト ㌾ 267 | ポ イ ン ト ㌽ 268 | ポ ン ド ㍀ 269 | マ ン シ ョ ン ㍇ 270 | マ イ ク ロ ㍃ 271 | マ イ ル ㍄ 272 | マ ッ ハ ㍅ 273 | マ ル ク ㍆ 274 | ミ リ バ ー ル ㍊ 275 | ミ ク ロ ン ㍈ 276 | ミ リ ㍉ 277 | メ ガ ト ン ㍌ 278 | メ ー ト ル ㍍ 279 | メ ガ ㍋ 280 | ヤ ー ド ㍎ 281 | ヤ ー ル ㍏ 282 | ユ ア ン ㍐ 283 | リ ッ ト ル ㍑ 284 | リ ラ ㍒ 285 | ル ー ブ ル ㍔ 286 | ル ピ ー ㍓ 287 | レ ン ト ゲ ン ㍖ 288 | レ ム ㍕ 289 | ワ ッ ト ㍗ 290 | 令 和 ㋿ 291 | 大 正 ㍽ 292 | 昭 和 ㍼ 293 | 株 式 会 社 ㍿ 294 | 平 成 ㍻ 295 | -------------------------------------------------------------------------------- /codes/build.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | import fontforge 3 | 4 | def mergeft(font, A, fin2, rplc=False): 5 | print('Merging', fin2) 6 | cmap=culcmap(font) 7 | print('Loading font2...') 8 | font2 = fontforge.open(fin2) 9 | font2.reencode("unicodefull") 10 | font2.em = font.em 11 | if A=='A': rmcd='B' 12 | else: rmcd='A' 13 | notgl=('.notdef', '.null', 'nonmarkingreturn', 'NULL', 'NUL') 14 | cmap2=culcmap(font2) 15 | cmap2={c:cmap2[c] for c in cmap2 if hancheck(c)!=rmcd or c==0x4E00} 16 | cmap2rev=dict() 17 | for c,v in cmap2.items(): 18 | if v not in cmap2rev: cmap2rev[v]=list() 19 | cmap2rev[v].append(c) 20 | code_codes2 = {} 21 | for g in cmap2rev.keys(): 22 | if g in notgl: continue 23 | cs = [c for c in cmap2rev[g] if rplc or c not in cmap] 24 | if len(cs) > 0: 25 | code_codes2[cs[0]] = cs[1:] 26 | font2.selection.select(*code_codes2.keys()) 27 | font2.copy() 28 | font.selection.select(*code_codes2.keys()) 29 | font.paste() 30 | print('Adding extra codings...') 31 | for cd1 in code_codes2.keys(): 32 | if len(code_codes2[cd1]) > 0: 33 | font[cd1].altuni = code_codes2[cd1] 34 | font2.close() 35 | 36 | def addlk(font, lkn, sl): 37 | cmap=culcmap(font) 38 | allc=set(cmap.keys()) 39 | lantgs=list() 40 | for lantg in ('DFLT', 'cyrl', 'grek', 'hang', 'hani', 'kana', 'latn'): 41 | lantgs.append((lantg, ("dflt",))) 42 | lknm, tbnm='lksg'+lkn, 'tbsg'+lkn 43 | if sl=='s': 44 | font.addLookup(lknm, 'gsub_single', None, ((lkn, tuple(lantgs)), )) 45 | elif sl=='l': 46 | font.addLookup(lknm, 'gsub_ligature', None, ((lkn, tuple(lantgs)), )) 47 | else: raise 48 | font.addLookupSubtable(lknm, tbnm) 49 | with open(os.path.join(os.path.abspath(os.path.dirname(__file__)), lkn+'.txt'), 'r', encoding = 'utf-8') as f: 50 | for line in f.readlines(): 51 | litm=line.strip('\r\n') 52 | if '\t' not in litm: continue 53 | s, t=litm.split('\t') 54 | if sl=='s': 55 | if s and t and s != t and ord(t) in cmap and ord(s) in cmap: 56 | gntc = cmap[ord(t)] 57 | gnsc = cmap[ord(s)] 58 | if gntc != gnsc: 59 | font[gnsc].addPosSub(tbnm, gntc) 60 | else: 61 | ss=s.split(' ') 62 | cc=[ord(ch) for ch in ss] 63 | if ord(t) in cmap and set(cc).issubset(allc): 64 | wdin=[cmap[c] for c in cc] 65 | font[cmap[ord(t)]].addPosSub(tbnm, tuple(wdin)) 66 | 67 | def cklkps(font): 68 | print('Checking lookups...') 69 | for lk in font.gsub_lookups: 70 | font.removeLookup(lk) 71 | addlk(font, 'vert', 's') 72 | addlk(font, 'fwid', 's') 73 | addlk(font, 'dlig', 'l') 74 | 75 | def setnm(font, A): 76 | print('Processing font name...') 77 | font.os2_vendor='GUIW' 78 | enname='LanternMing'+A 79 | tcname='上元明朝'+A 80 | scname='上元明朝'+A 81 | janame='上元明朝'+A 82 | versn='1.04' 83 | fontVURL='https://github.com/GuiWonder/LanternMing' 84 | copyright='Copyright(c) LanternMing, 2023-2025.' 85 | wt='Regular' 86 | subfamily='Regular' 87 | font.sfntRevision = float(versn) 88 | 89 | enfml=enname 90 | tcfml=tcname 91 | scfml=scname 92 | jafml=janame 93 | if wt in ('Regular', 'Bold'): 94 | enftname=enfml 95 | tcftname=tcfml 96 | scftname=scfml 97 | jaftname=jafml 98 | enfull=enfml+' '+wt 99 | tcfull=tcfml+' '+wt 100 | scfull=scfml+' '+wt 101 | jafull=jafml+' '+wt 102 | else: 103 | enftname=enfull=enfml+' '+wt 104 | tcftname=tcfull=tcfml+' '+wt 105 | scftname=scfull=scfml+' '+wt 106 | jaftname=jafull=jafml+' '+wt 107 | psname=enfml.replace(' ', '')+'-'+wt 108 | uniqid=versn+';'+psname 109 | newname=list() 110 | newname+=[ 111 | ('English (US)', 'Copyright', copyright), 112 | ('English (US)', 'Family', enftname), 113 | ('English (US)', 'SubFamily', subfamily), 114 | ('English (US)', 'UniqueID', uniqid), 115 | ('English (US)', 'Fullname', enfull), 116 | ('English (US)', 'Version', 'Version '+versn), 117 | ('English (US)', 'PostScriptName', psname), 118 | ('English (US)', 'Vendor URL', fontVURL) 119 | ] 120 | if wt not in ('Regular', 'Bold'): 121 | newname+=[ 122 | ('English (US)', 'Preferred Family', enfml), 123 | ('English (US)', 'Preferred Styles', wt), 124 | ] 125 | if tcname: 126 | for lang in ('Chinese (Taiwan)', 'Chinese (Hong Kong)', 'Chinese (Macau)'): 127 | newname+=[ 128 | (lang, 'Family', tcftname), 129 | (lang, 'SubFamily', subfamily), 130 | (lang, 'Fullname', tcfull), 131 | ] 132 | if wt not in ('Regular', 'Bold'): 133 | newname+=[ 134 | (lang, 'Preferred Family', tcfml), 135 | (lang, 'Preferred Styles', wt), 136 | ] 137 | if scname: 138 | for lang in ('Chinese (PRC)', 'Chinese (Singapore)'): 139 | newname+=[ 140 | (lang, 'Family', scftname), 141 | (lang, 'SubFamily', subfamily), 142 | (lang, 'Fullname', scfull), 143 | ] 144 | if wt not in ('Regular', 'Bold'): 145 | newname+=[ 146 | (lang, 'Preferred Family', scfml), 147 | (lang, 'Preferred Styles', wt), 148 | ] 149 | if janame: 150 | newname+=[ 151 | ('Japanese', 'Family', jaftname), 152 | ('Japanese', 'SubFamily', subfamily), 153 | ('Japanese', 'Fullname', jafull), 154 | ] 155 | if wt not in ('Regular', 'Bold'): 156 | newname+=[ 157 | ('Japanese', 'Preferred Family', jafml), 158 | ('Japanese', 'Preferred Styles', wt), 159 | ] 160 | font.sfnt_names=tuple(newname) 161 | 162 | def culcmap(font): 163 | cmap=dict() 164 | for g in font.glyphs(): 165 | if g.unicode>-1: 166 | cmap[g.unicode]=g.glyphname 167 | if g.altuni!=None: 168 | for uni in g.altuni: 169 | if uni[1]<=0: 170 | cmap[uni[0]]=g.glyphname 171 | return cmap 172 | 173 | def hancheck(c): 174 | if cjkcheck(c) in ('Ide', 'A', 'C', 'D', 'E', 'F', 'G', 'H', '0'): 175 | return 'A' 176 | if cjkcheck(c) in ('B', 'I', 'J'): 177 | return 'B' 178 | else: 179 | return 'Not' 180 | 181 | def cjkcheck(c): 182 | if c in range(0x4E00, 0x9FFF+1): return 'Ide' 183 | if c in range(0x3400, 0x4DBF+1): return 'A' 184 | if c in range(0x20000, 0x2A6DF+1): return 'B' 185 | if c in range(0x2A700, 0x2B73F+1): return 'C' 186 | if c in range(0x2B740, 0x2B81F+1): return 'D' 187 | if c in range(0x2B820, 0x2CEAF+1): return 'E' 188 | if c in range(0x2CEB0, 0x2EBEF+1): return 'F' 189 | if c in range(0x30000, 0x3134F+1): return 'G' 190 | if c in range(0x31350, 0x323AF+1): return 'H' 191 | if c in range(0x2EBF0, 0x2EE5F+1): return 'I' 192 | if c in range(0x323B0, 0x3347F+1): return 'J' 193 | if c==0x3007: return '0' 194 | return 'Not' 195 | 196 | def rmcode(font, A): 197 | print('Remove codes') 198 | if A=='A': rmcd='B' 199 | else: rmcd='A' 200 | notgl=('.notdef', '.null', 'nonmarkingreturn', 'NULL', 'NUL') 201 | cmap=culcmap(font) 202 | cmap={c:cmap[c] for c in cmap if hancheck(c)!=rmcd or c==0x4E00} 203 | for g in font.glyphs(): 204 | if g.glyphname in notgl: continue 205 | if g.glyphname not in cmap.values(): 206 | g.removePosSub('*') 207 | font.removeGlyph(g) 208 | elif g.altuni!=None: 209 | lu=list() 210 | for alt in g.altuni: 211 | c, u=alt[0], alt[1] 212 | if u<=0 and (hancheck(c)!=rmcd or c==0x4E00): 213 | lu.append(alt) 214 | if len(lu)>0: 215 | g.altuni=tuple(lu) 216 | else: 217 | g.altuni=None 218 | 219 | def build(outft, A, fonts): 220 | print('Target', outft) 221 | print('Processing...') 222 | font=fontforge.open(fonts[0]) 223 | font.reencode("unicodefull") 224 | mergeft(font, A, fonts[1], False) 225 | mergeft(font, A, fonts[2], True) 226 | for f in fonts[3:]: 227 | mergeft(font, A, f, False) 228 | rmcode(font, A) 229 | if A=='A': 230 | cklkps(font) 231 | setnm(font, A) 232 | print('Saving', outft) 233 | font.generate(outft) 234 | print('Finished') 235 | 236 | if __name__ == "__main__": 237 | build(sys.argv[1], sys.argv[2], sys.argv[3:]) 238 | --------------------------------------------------------------------------------