Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f43edba38f | |||
| a736526056 | |||
| d4cce21701 | |||
| b96bb96a88 | |||
| 2a27486aca |
38
.github/workflows/build.yml
vendored
38
.github/workflows/build.yml
vendored
@@ -17,22 +17,41 @@ jobs:
|
|||||||
- name: Build fonts
|
- name: Build fonts
|
||||||
run: python3 build.py
|
run: python3 build.py
|
||||||
|
|
||||||
|
- name: Download kobofix.py
|
||||||
|
run: curl -sL https://raw.githubusercontent.com/nicoverbruggen/kobo-font-fix/main/kobofix.py -o kobofix.py
|
||||||
|
|
||||||
|
- name: Generate Kobo (KF) fonts
|
||||||
|
run: |
|
||||||
|
python3 kobofix.py --preset kf out/ttf/*.ttf
|
||||||
|
mkdir -p out/kf
|
||||||
|
mv out/ttf/KF_*.ttf out/kf/
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Readerly
|
name: Readerly
|
||||||
path: out/ttf/*.ttf
|
path: out/ttf/*.ttf
|
||||||
|
|
||||||
|
- name: Upload Kobo artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: KF_Readerly
|
||||||
|
path: out/kf/*.ttf
|
||||||
|
|
||||||
- name: Zip TTFs for release
|
- name: Zip TTFs for release
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
run: cd out/ttf && zip -j ../../Readerly.zip *.ttf
|
run: |
|
||||||
|
cd out/ttf && zip -j ../../Readerly.zip *.ttf
|
||||||
|
cd ../../out/kf && zip -j ../../KF_Readerly.zip *.ttf
|
||||||
|
|
||||||
- name: Upload release zip
|
- name: Upload release zips
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Readerly-release
|
name: Readerly-release
|
||||||
path: Readerly.zip
|
path: |
|
||||||
|
Readerly.zip
|
||||||
|
KF_Readerly.zip
|
||||||
|
|
||||||
release:
|
release:
|
||||||
needs: build
|
needs: build
|
||||||
@@ -49,4 +68,15 @@ jobs:
|
|||||||
- name: Create release
|
- name: Create release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
files: Readerly.zip
|
draft: false
|
||||||
|
name: ${{ github.ref_name }}
|
||||||
|
body: |
|
||||||
|
> [!TIP]
|
||||||
|
> **If you are using a Kobo device and reading books purchased from the Kobo Store or reading `kepub` files converted via Calibre**, you should download KF_Readerly.zip, which has fonts slightly altered for optimal kerning for the `kepub` renderer.
|
||||||
|
|
||||||
|
### Learn more
|
||||||
|
|
||||||
|
Readerly is part of the `ebook-fonts` collection. For more information about those fonts, screenshots and how to install them, please consult the [README](https://github.com/nicoverbruggen/ebook-fonts/blob/main/README.md). The FAQ also includes an entry on how to enable ligatures on Kobo devices, which is highly recommended.
|
||||||
|
files: |
|
||||||
|
Readerly.zip
|
||||||
|
KF_Readerly.zip
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ The goal was to get a metrically/visually similar font, without actually copying
|
|||||||
|
|
||||||
To get to the final result, I decided to use the variable font and work on it. The original is located in `src` and is available under the same OFL as the end result, which is included in `LICENSE`.
|
To get to the final result, I decided to use the variable font and work on it. The original is located in `src` and is available under the same OFL as the end result, which is included in `LICENSE`.
|
||||||
|
|
||||||
|
## Downloads
|
||||||
|
|
||||||
|
Two versions are generated via the pipeline of the [latest release](../../releases/latest):
|
||||||
|
|
||||||
|
- **KF_Readerly.zip** — Kobo-optimized TrueType fonts with a legacy kern table and `KF` prefix. Use this if you have a Kobo e-reader, this version contains optimizations made with [Kobo Font Fix](https://github.com/nicoverbruggen/kobo-font-fix).
|
||||||
|
- **Readerly.zip** — The standard, unmodified fonts, as TrueType files. Useful for other e-readers and use on your desktop computer or smartphone.
|
||||||
|
|
||||||
## Project structure
|
## Project structure
|
||||||
|
|
||||||
- `src`: Newsreader variable font TTFs
|
- `src`: Newsreader variable font TTFs
|
||||||
|
|||||||
20
build.py
20
build.py
@@ -25,7 +25,7 @@ import textwrap
|
|||||||
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
#
|
#
|
||||||
# Most of these values are safe to tweak. The --customize flag only toggles
|
# Most of these values are safe to tweak. The --customize flag only toggles
|
||||||
# a small subset at runtime (family name, old-style kerning, outline fixes).
|
# a small subset at runtime (family name, outline fixes).
|
||||||
#
|
#
|
||||||
# Quick reference (what each knob does):
|
# Quick reference (what each knob does):
|
||||||
# - REGULAR_VF / ITALIC_VF: input variable fonts from ./src
|
# - REGULAR_VF / ITALIC_VF: input variable fonts from ./src
|
||||||
@@ -524,19 +524,15 @@ def ff_license_script():
|
|||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
def build_export_script(sfd_path, ttf_path, old_kern=True):
|
def build_export_script(sfd_path, ttf_path):
|
||||||
"""Build a FontForge script that opens an .sfd and exports to TTF."""
|
"""Build a FontForge script that opens an .sfd and exports to TTF."""
|
||||||
if old_kern:
|
|
||||||
flags_line = 'flags = ("opentype", "old-kern", "no-FFTM-table", "winkern")'
|
|
||||||
else:
|
|
||||||
flags_line = 'flags = ("opentype", "no-FFTM-table")'
|
|
||||||
return textwrap.dedent(f"""\
|
return textwrap.dedent(f"""\
|
||||||
import fontforge
|
import fontforge
|
||||||
|
|
||||||
f = fontforge.open({sfd_path!r})
|
f = fontforge.open({sfd_path!r})
|
||||||
print("Exporting: " + f.fontname)
|
print("Exporting: " + f.fontname)
|
||||||
|
|
||||||
{flags_line}
|
flags = ("opentype", "no-FFTM-table")
|
||||||
f.generate({ttf_path!r}, flags=flags)
|
f.generate({ttf_path!r}, flags=flags)
|
||||||
|
|
||||||
print(" -> " + {ttf_path!r})
|
print(" -> " + {ttf_path!r})
|
||||||
@@ -763,20 +759,16 @@ def main():
|
|||||||
print(f" ttfautohint: {shutil.which('ttfautohint')}")
|
print(f" ttfautohint: {shutil.which('ttfautohint')}")
|
||||||
|
|
||||||
family = DEFAULT_FAMILY
|
family = DEFAULT_FAMILY
|
||||||
old_kern = False
|
|
||||||
outline_fix = True
|
outline_fix = True
|
||||||
|
|
||||||
if "--customize" in sys.argv:
|
if "--customize" in sys.argv:
|
||||||
print()
|
print()
|
||||||
family = input(f" Font family name [{DEFAULT_FAMILY}]: ").strip() or DEFAULT_FAMILY
|
family = input(f" Font family name [{DEFAULT_FAMILY}]: ").strip() or DEFAULT_FAMILY
|
||||||
old_kern_input = input(" Export with old-style kerning? [y/N]: ").strip().lower()
|
|
||||||
old_kern = old_kern_input in ("y", "yes")
|
|
||||||
outline_input = input(" Apply outline fixes (remove overlaps + zero-area cleanup)? [Y/n]: ").strip().lower()
|
outline_input = input(" Apply outline fixes (remove overlaps + zero-area cleanup)? [Y/n]: ").strip().lower()
|
||||||
outline_fix = outline_input not in ("n", "no")
|
outline_fix = outline_input not in ("n", "no")
|
||||||
|
|
||||||
print()
|
print()
|
||||||
print(f" Family: {family}")
|
print(f" Family: {family}")
|
||||||
print(f" Old kern: {'yes' if old_kern else 'no'}")
|
|
||||||
print(f" Outline fix: {'yes' if outline_fix else 'no'}")
|
print(f" Outline fix: {'yes' if outline_fix else 'no'}")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
@@ -786,12 +778,12 @@ def main():
|
|||||||
os.makedirs(tmp_dir)
|
os.makedirs(tmp_dir)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_build(tmp_dir, family=family, old_kern=old_kern, outline_fix=outline_fix)
|
_build(tmp_dir, family=family, outline_fix=outline_fix)
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(tmp_dir, ignore_errors=True)
|
shutil.rmtree(tmp_dir, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
def _build(tmp_dir, family=DEFAULT_FAMILY, old_kern=True, outline_fix=True):
|
def _build(tmp_dir, family=DEFAULT_FAMILY, outline_fix=True):
|
||||||
variants = [(f"{family}-{style}", vf, wght, opsz)
|
variants = [(f"{family}-{style}", vf, wght, opsz)
|
||||||
for style, vf, wght, opsz in VARIANT_STYLES]
|
for style, vf, wght, opsz in VARIANT_STYLES]
|
||||||
variant_names = [name for name, _, _, _ in variants]
|
variant_names = [name for name, _, _, _ in variants]
|
||||||
@@ -883,7 +875,7 @@ def _build(tmp_dir, family=DEFAULT_FAMILY, old_kern=True, outline_fix=True):
|
|||||||
style_suffix = name.split("-")[-1] if "-" in name else "Regular"
|
style_suffix = name.split("-")[-1] if "-" in name else "Regular"
|
||||||
|
|
||||||
# Export TTF
|
# Export TTF
|
||||||
script = build_export_script(sfd_path, ttf_path, old_kern=old_kern)
|
script = build_export_script(sfd_path, ttf_path)
|
||||||
run_fontforge_script(script)
|
run_fontforge_script(script)
|
||||||
if outline_fix:
|
if outline_fix:
|
||||||
clean_ttf_degenerate_contours(ttf_path)
|
clean_ttf_degenerate_contours(ttf_path)
|
||||||
|
|||||||
Reference in New Issue
Block a user