├── .github └── workflows │ └── build.yml ├── .gitignore ├── .vscode └── settings.json └── extract.py /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build msyh 2 | on: 3 | push: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-22.04 10 | steps: 11 | - name: Install dependencies 12 | run: sudo apt install git fontforge curl p7zip-full jq python3 python3-fontforge 13 | - uses: actions/checkout@v2 14 | - name: Grab latest version 15 | run: | 16 | curl -L https://api.github.com/repos/be5invis/Sarasa-Gothic/releases/latest -o api.json 17 | UPSTREAM_VERSION=$(cat api.json | jq -r .tag_name) 18 | DOWNLOAD_URL=$(cat api.json | jq -r '.assets[] | select(.name | test("Sarasa-TTC-(?!Unhinted)")) | select(.content_type|test("application/x-compressed")) | .browser_download_url') 19 | echo "UPSTREAM_VERSION=$UPSTREAM_VERSION" >> $GITHUB_ENV 20 | echo "DOWNLOAD_URL=$DOWNLOAD_URL" >> $GITHUB_ENV 21 | - name: Download font 22 | run: curl -Lvo /tmp/ttc.7z $DOWNLOAD_URL 23 | - name: Extract font 24 | run: 7z x -odata /tmp/ttc.7z 25 | - name: Run script 26 | run: | 27 | mkdir out 28 | python3 extract.py 29 | - name: Compress font 30 | run: | 31 | cd out 32 | 7z a ../out.7z * -mx=9 -md=512m -ms=on 33 | - name: Upload artifact 34 | uses: actions/upload-artifact@v4 35 | with: 36 | name: out 37 | path: out 38 | - name: Upload release 39 | uses: marvinpinto/action-automatic-releases@latest 40 | with: 41 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 42 | automatic_release_tag: "upstream-${{ env.UPSTREAM_VERSION }}" 43 | prerelease: true 44 | title: Nightly build 45 | files: out.7z 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | data 2 | out 3 | .venv 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.formatting.provider": "black" 3 | } -------------------------------------------------------------------------------- /extract.py: -------------------------------------------------------------------------------- 1 | import re 2 | import fontforge as ff 3 | from glob import glob 4 | 5 | class TTFTask: 6 | def __init__(self, font, variant, ui) -> None: 7 | self.font = font 8 | for locale, name, value in font.sfnt_names: 9 | if name == "Preferred Styles": 10 | self.variant = value 11 | break 12 | self.ui = ui 13 | 14 | def get_subfamily(self): 15 | return None 16 | 17 | def edit(self): 18 | enusr = "Microsoft YaHei" 19 | if self.ui: 20 | enusr = "Microsoft YaHei UI" 21 | enus = enusr + " " + self.variant 22 | zhcnr = "微软雅黑" 23 | if self.ui: 24 | zhcnr = enusr 25 | zhcn = zhcnr + " " + self.variant 26 | if self.variant == "Regular": 27 | enus = enusr 28 | zhcn = zhcnr 29 | if self.variant == "ExtraLight": 30 | enus = enusr + " " + "Light" 31 | zhcn = zhcnr + " " + "Light" 32 | # self.font.fullname = enus 33 | self.font.fontname = enus.replace(" ", "") 34 | self.font.fullname = enus 35 | self.font.familyname = enusr 36 | print(self.font.fontname) 37 | print(self.font.fullname) 38 | print(self.font.familyname) 39 | self.font.appendSFNTName("English (US)", "Family", enusr) 40 | self.font.appendSFNTName("English (US)", "UniqueID", enus) 41 | self.font.appendSFNTName("English (US)", "Fullname", enus) 42 | self.font.appendSFNTName("English (US)", "Preferred Family", enusr) 43 | self.font.appendSFNTName("Chinese (PRC)", "Family", zhcnr) 44 | self.font.appendSFNTName("Chinese (PRC)", "UniqueID", zhcn) 45 | self.font.appendSFNTName("Chinese (PRC)", "Fullname", zhcn) 46 | self.font.appendSFNTName("Chinese (PRC)", "Preferred Family", zhcnr) 47 | for (lang, key, field) in self.font.sfnt_names: 48 | print(lang, '%s=%s'%(key, field)) 49 | # print(self.font.sfnt_names) 50 | 51 | class TTCFile: 52 | def __init__(self, file, variant): 53 | self.file = file 54 | self.variant = variant 55 | self.output = transformVariant(variant) 56 | 57 | def openTTF(self, isui): 58 | target = "Sarasa Gothic SC" 59 | if isui: 60 | target = "Sarasa UI SC" 61 | font = ff.open('%s(%s%s)'%(self.file, target, self.variant)) 62 | return TTFTask(font, self.variant, isui) 63 | 64 | def build(self): 65 | ttf = self.openTTF(False) 66 | ttf.edit() 67 | ttfui = self.openTTF(True) 68 | ttfui.edit() 69 | ttf.font.generateTtc("out/%s"%self.output, ttfui.font, ttcflags = ("merge"), layer = 1) 70 | ttf.font.close() 71 | ttfui.font.close() 72 | 73 | def __str__(self) -> str: 74 | return 'TTCFile(%s, %s) -> %s'%(self.file, self.variant, self.output) 75 | 76 | def listTtc(pattern): 77 | for ttc in glob(pattern): 78 | for face in ff.fontsInFile(ttc): 79 | if m := re.match(r"Sarasa Gothic SC(.*)?", face): 80 | yield TTCFile(ttc, m.group(1)) 81 | 82 | def transformVariant(input): 83 | ret = "msyh" 84 | if "Bold" in input: 85 | ret += "bd" 86 | if "Semibold" in input: 87 | ret += "sb" 88 | if "Light" in input: 89 | ret += "l" 90 | if "Xlight" in input: 91 | ret += "xl" 92 | if "Italic" in input: 93 | ret += "i" 94 | return ret + ".ttc" 95 | 96 | for ttc in listTtc("data/*.ttc"): 97 | print(ttc) 98 | ttc.build() 99 | --------------------------------------------------------------------------------