@@ -1,36 +0,0 @@
|
||||
"""Extract notation glyph bounds from the shipped OTF, in staff-space units."""
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
from fontTools.pens.boundsPen import BoundsPen
|
||||
from fontTools.ttLib import TTFont
|
||||
|
||||
def generate(font_path, output):
|
||||
with TTFont(font_path) as font:
|
||||
glyphs, cmap = font.getGlyphSet(), font.getBestCmap()
|
||||
units = font['head'].unitsPerEm / 4
|
||||
ranges = [(0xE050, 0xE06F), (0xE080, 0xE09F), (0xE0A0, 0xE0A5),
|
||||
(0xE101, 0xE102), (0xE1E7, 0xE1E8), (0xE240, 0xE250),
|
||||
(0xE260, 0xE270), (0xE4E0, 0xE4EE)]
|
||||
records = []
|
||||
for start, end in ranges:
|
||||
for codepoint in range(start, end):
|
||||
if codepoint not in cmap:
|
||||
continue
|
||||
pen = BoundsPen(glyphs)
|
||||
glyphs[cmap[codepoint]].draw(pen)
|
||||
if pen.bounds:
|
||||
box = ', '.join(f'{v / units:.8f}F' for v in pen.bounds)
|
||||
records.append(f' {{{codepoint}, {{{box}}}}},')
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
output.write_text('#pragma once\n#include <array>\n#include <cstdint>\nnamespace vamp_zero::font_data {\n'
|
||||
'struct glyph { std::int32_t codepoint; std::array<float, 4> bounds; };\n'
|
||||
f'inline constexpr std::array<glyph, {len(records)}> glyphs = {{{{\n'
|
||||
+ '\n'.join(records) + '\n}};\n}\n', encoding='ascii')
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--font', type=Path, required=True)
|
||||
parser.add_argument('--output', type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
generate(args.font, args.output)
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import subprocess
|
||||
import tempfile
|
||||
import urllib.request
|
||||
|
||||
VERSION = '4.7.4.260706075'
|
||||
SHA256 = {
|
||||
'x86_64': '9233ed1b87d3e6b45722278f3c286dcd41e83da778bd0f80a1dd04949696ad93',
|
||||
'aarch64': '162ae55b317660f196b2e73d566bdb45c1e990ed4cc140709d25d97b9ef366b0',
|
||||
}
|
||||
|
||||
def install(destination: Path) -> Path:
|
||||
architecture = platform.machine()
|
||||
if architecture not in SHA256:
|
||||
raise RuntimeError('the pinned engraver requires an x86_64 or aarch64 Linux build host')
|
||||
destination = destination.resolve()
|
||||
executable = destination / 'squashfs-root' / 'AppRun'
|
||||
marker = destination / 'sha256'
|
||||
if executable.is_file() and marker.is_file() and marker.read_text().strip() == SHA256[architecture]:
|
||||
return executable
|
||||
if destination.exists() and any(destination.iterdir()):
|
||||
raise RuntimeError(f'{destination} contains a different or incomplete installation; choose an empty directory')
|
||||
destination.mkdir(parents=True, exist_ok=True)
|
||||
name = f'MuseScore-Studio-{VERSION}-{architecture}.AppImage'
|
||||
url = f'https://github.com/musescore/MuseScore/releases/download/v4.7.4/{name}'
|
||||
with tempfile.TemporaryDirectory(prefix='vamp-musescore-download-') as temporary:
|
||||
archive = Path(temporary) / name
|
||||
digest = hashlib.sha256()
|
||||
with urllib.request.urlopen(url, timeout=120) as response, archive.open('wb') as output:
|
||||
while chunk := response.read(1024 * 1024):
|
||||
digest.update(chunk)
|
||||
output.write(chunk)
|
||||
if digest.hexdigest() != SHA256[architecture]:
|
||||
raise RuntimeError('MuseScore AppImage checksum mismatch')
|
||||
archive.chmod(0o755)
|
||||
subprocess.run([str(archive), '--appimage-extract'], cwd=destination, check=True, stdout=subprocess.DEVNULL)
|
||||
if not executable.is_file():
|
||||
raise RuntimeError('MuseScore AppImage does not contain AppRun')
|
||||
marker.write_text(SHA256[architecture] + '\n')
|
||||
return executable
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description='Install the pinned build-only MuseScore engraver without FUSE.')
|
||||
parser.add_argument('destination', type=Path)
|
||||
print(install(parser.parse_args().destination))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,3 +1,2 @@
|
||||
Pillow==12.3.0
|
||||
defusedxml==0.7.1
|
||||
fonttools==4.63.0
|
||||
|
||||
Reference in New Issue
Block a user