mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2025-07-22 02:35:23 +03:00
228 lines
9.5 KiB
Diff
228 lines
9.5 KiB
Diff
Patch-Source: https://github.com/ryanoasis/nerd-fonts/pull/761 (modified)
|
|
--
|
|
From c53a6db686089cfcbf421867a0d3459eb466dd61 Mon Sep 17 00:00:00 2001
|
|
From: Fini Jastrow <ulf.fini.jastrow@desy.de>
|
|
Date: Tue, 11 Jan 2022 03:08:21 +0100
|
|
Subject: [PATCH 1/2] font-patcher: Fix wrong argument for postprocess
|
|
|
|
[why]
|
|
When the patched font does not have a fullname (which can never happen)
|
|
the postprocess is called with a wrong filename.
|
|
|
|
[note]
|
|
Also output the file name of the patched font, for easier access by the user.
|
|
|
|
Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
|
|
---
|
|
font-patcher | 14 ++++++++------
|
|
1 file changed, 8 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/font-patcher b/font-patcher
|
|
index 9440b2a52..756fccdf5 100755
|
|
--- a/font-patcher
|
|
+++ b/font-patcher
|
|
@@ -123,15 +123,17 @@ class font_patcher:
|
|
|
|
# the `PfEd-comments` flag is required for Fontforge to save '.comment' and '.fontlog'.
|
|
if self.sourceFont.fullname != None:
|
|
- self.sourceFont.generate(self.args.outputdir + "/" + self.sourceFont.fullname + self.extension, flags=(str('opentype'), str('PfEd-comments')))
|
|
- print("\nGenerated: {}".format(self.sourceFont.fontname))
|
|
+ outfile = self.args.outputdir + "/" + self.sourceFont.fullname + self.extension
|
|
+ self.sourceFont.generate(outfile, flags=(str('opentype'), str('PfEd-comments')))
|
|
+ print("\nGenerated: {} in {}".format(self.sourceFont.fontname, outfile))
|
|
else:
|
|
- self.sourceFont.generate(self.args.outputdir + "/" + self.sourceFont.cidfontname + self.extension, flags=(str('opentype'), str('PfEd-comments')))
|
|
- print("\nGenerated: {}".format(self.sourceFont.fullname))
|
|
+ outfile = self.sourceFont.generate(self.args.outputdir + "/" + self.sourceFont.cidfontname + self.extension
|
|
+ self.sourceFont.generate(outfile, flags=(str('opentype'), str('PfEd-comments')))
|
|
+ print("\nGenerated: {} in {}".format(self.sourceFont.fullname, outfile))
|
|
|
|
if self.args.postprocess:
|
|
- subprocess.call([self.args.postprocess, self.args.outputdir + "/" + self.sourceFont.fullname + self.extension])
|
|
- print("\nPost Processed: {}".format(self.sourceFont.fullname))
|
|
+ subprocess.call([self.args.postprocess, outfile])
|
|
+ print("\nPost Processed: {}".format(outfile))
|
|
|
|
|
|
def setup_arguments(self):
|
|
|
|
From 8b91c873a2ddded39cf98dc667a0ed7bd881c975 Mon Sep 17 00:00:00 2001
|
|
From: Fini Jastrow <ulf.fini.jastrow@desy.de>
|
|
Date: Tue, 11 Jan 2022 03:37:30 +0100
|
|
Subject: [PATCH 2/2] font-patcher: Handle lowestRecPPEM
|
|
|
|
[why]
|
|
Some fonts set specific lower resolutions and handle the small rendering
|
|
very nicely. But fontforge does not copy that information when it opens
|
|
a font; rather some default values are always written. That can destroy
|
|
the small font rendering.
|
|
|
|
The responsible settings are the 'ppem_to_int' flag and the
|
|
'lowestRecPPEM' setting, both in the HEAD table.
|
|
|
|
[how]
|
|
After successfully patching and generating the new font we copy that
|
|
settings over from the source font.
|
|
|
|
Instead of using fontTools (and thereby requiring all users to pull that
|
|
dependency) we handle the raw font file changes ourselves.
|
|
|
|
Fixes: 612
|
|
|
|
Reported-by: nojus297
|
|
Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
|
|
---
|
|
font-patcher | 129 +++++++++++++++++++++++++++++++++++++++++++++++++--
|
|
1 file changed, 126 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/font-patcher b/font-patcher
|
|
index 756fccdf5..9e2aa9f00 100755
|
|
--- a/font-patcher
|
|
+++ b/font-patcher
|
|
@@ -37,6 +37,113 @@ except ImportError:
|
|
)
|
|
|
|
|
|
+class TableHEADWriter:
|
|
+ """ Access to the HEAD table without external dependencies """
|
|
+ def getlong(self, pos = None):
|
|
+ """ Get four bytes from the font file as integer number """
|
|
+ if pos:
|
|
+ self.goto(pos)
|
|
+ return (ord(self.f.read(1)) << 24) + (ord(self.f.read(1)) << 16) + (ord(self.f.read(1)) << 8) + ord(self.f.read(1))
|
|
+
|
|
+ def getshort(self, pos = None):
|
|
+ """ Get two bytes from the font file as integer number """
|
|
+ if pos:
|
|
+ self.goto(pos)
|
|
+ return (ord(self.f.read(1)) << 8) + ord(self.f.read(1))
|
|
+
|
|
+ def putlong(self, num, pos = None):
|
|
+ """ Put number as four bytes into font file """
|
|
+ if pos:
|
|
+ self.goto(pos)
|
|
+ self.f.write(bytearray([(num >> 24) & 0xFF, (num >> 16) & 0xFF ,(num >> 8) & 0xFF, num & 0xFF]))
|
|
+ self.modified = True
|
|
+
|
|
+ def putshort(self, num, pos = None):
|
|
+ """ Put number as two bytes into font file """
|
|
+ if pos:
|
|
+ self.goto(pos)
|
|
+ self.f.write(bytearray([(num >> 8) & 0xFF, num & 0xFF]))
|
|
+ self.modified = True
|
|
+
|
|
+ def calc_checksum(self, start, end, checksum = 0):
|
|
+ """ Calculate a font table checksum, optionally ignoring another embedded checksum value (for table 'head') """
|
|
+ self.f.seek(start)
|
|
+ for i in range(start, end - 4, 4):
|
|
+ checksum += self.getlong()
|
|
+ checksum &= 0xFFFFFFFF
|
|
+ i += 4
|
|
+ extra = 0
|
|
+ for j in range(4):
|
|
+ if i + j <= end:
|
|
+ extra += ord(self.f.read(1))
|
|
+ extra = extra << 8
|
|
+ checksum = (checksum + extra) & 0xFFFFFFFF
|
|
+ return checksum
|
|
+
|
|
+ def find_head_table(self):
|
|
+ """ Search all tables for the HEAD table and store its metadata """
|
|
+ self.f.seek(4)
|
|
+ numtables = self.getshort()
|
|
+ self.f.seek(3*2, 1)
|
|
+
|
|
+ for i in range(numtables):
|
|
+ tab_name = self.f.read(4)
|
|
+ self.tab_check_offset = self.f.tell()
|
|
+ self.tab_check = self.getlong()
|
|
+ self.tab_offset = self.getlong()
|
|
+ self.tab_length = self.getlong()
|
|
+ if tab_name == b'head':
|
|
+ break
|
|
+
|
|
+ def goto(self, where):
|
|
+ """ Go to a named location in the file or to the specified index """
|
|
+ if type(where) is str:
|
|
+ positions = {'checksumAdjustment': 2+2+4,
|
|
+ 'flags': 2+2+4+4+4,
|
|
+ 'lowestRecPPEM': 2+2+4+4+4+2+2+8+8+2+2+2+2+2,
|
|
+ }
|
|
+ where = self.tab_offset + positions[where]
|
|
+ self.f.seek(where)
|
|
+
|
|
+
|
|
+ def calc_full_checksum(self, check = False):
|
|
+ """ Calculate the whole file's checksum """
|
|
+ self.f.seek(0, 2)
|
|
+ self.end = self.f.tell()
|
|
+ full_check = self.calc_checksum(0, self.end, (-self.checksum_adj) & 0xFFFFFFFF)
|
|
+ if check and (0xB1B0AFBA - full_check) & 0xFFFFFFFF != self.checksum_adj:
|
|
+ sys.exit("Checksum of whole font is bad")
|
|
+ return full_check
|
|
+
|
|
+ def calc_table_checksum(self, check = False):
|
|
+ tab_check_new = self.calc_checksum(self.tab_offset, self.tab_offset + self.tab_length - 1, (-self.checksum_adj) & 0xFFFFFFFF)
|
|
+ if check and tab_check_new != self.tab_check:
|
|
+ sys.exit("Checksum of 'head' in font is bad")
|
|
+ return tab_check_new
|
|
+
|
|
+ def reset_table_checksum(self):
|
|
+ new_check = self.calc_table_checksum()
|
|
+ self.putlong(new_check, self.tab_check_offset)
|
|
+
|
|
+ def reset_full_checksum(self):
|
|
+ new_adj = (0xB1B0AFBA - self.calc_full_checksum()) & 0xFFFFFFFF
|
|
+ self.putlong(new_adj, 'checksumAdjustment')
|
|
+
|
|
+ def close(self):
|
|
+ self.f.close()
|
|
+
|
|
+
|
|
+ def __init__(self, filename):
|
|
+ self.modified = False
|
|
+ self.f = open(filename, 'r+b')
|
|
+
|
|
+ self.find_head_table()
|
|
+
|
|
+ self.flags = self.getshort('flags')
|
|
+ self.lowppem = self.getshort('lowestRecPPEM')
|
|
+ self.checksum_adj = self.getlong('checksumAdjustment')
|
|
+
|
|
+
|
|
class font_patcher:
|
|
def __init__(self):
|
|
self.args = None # class 'argparse.Namespace'
|
|
@@ -125,11 +232,28 @@ class font_patcher:
|
|
if self.sourceFont.fullname != None:
|
|
outfile = self.args.outputdir + "/" + self.sourceFont.fullname + self.extension
|
|
self.sourceFont.generate(outfile, flags=(str('opentype'), str('PfEd-comments')))
|
|
- print("\nGenerated: {} in {}".format(self.sourceFont.fontname, outfile))
|
|
+ message = "\nGenerated: {} in '{}'".format(self.sourceFont.fontname, outfile)
|
|
else:
|
|
- outfile = self.sourceFont.generate(self.args.outputdir + "/" + self.sourceFont.cidfontname + self.extension
|
|
+ outfile = self.args.outputdir + "/" + self.sourceFont.cidfontname + self.extension
|
|
self.sourceFont.generate(outfile, flags=(str('opentype'), str('PfEd-comments')))
|
|
- print("\nGenerated: {} in {}".format(self.sourceFont.fullname, outfile))
|
|
+ message = "\nGenerated: {} in '{}'".format(self.sourceFont.fullname, outfile)
|
|
+
|
|
+ if not self.args.font.endswith('.sfd'):
|
|
+ # Adjust flags that can not be changed via fontforge
|
|
+ source_font = TableHEADWriter(self.args.font)
|
|
+ source_font.close()
|
|
+ dest_font = TableHEADWriter(outfile)
|
|
+ if source_font.flags & 0x08 == 0 and dest_font.flags & 0x08 != 0:
|
|
+ print("Changing flags from 0x{:X} to 0x{:X}".format(dest_font.flags, dest_font.flags & ~0x08))
|
|
+ dest_font.putshort(dest_font.flags & ~0x08, 'flags') # clear 'ppem_to_int'
|
|
+ if source_font.lowppem != dest_font.lowppem:
|
|
+ print("Changing lowestRecPPEM from {} to {}".format(dest_font.lowppem, source_font.lowppem))
|
|
+ dest_font.putshort(source_font.lowppem, 'lowestRecPPEM')
|
|
+ if dest_font.modified:
|
|
+ dest_font.reset_table_checksum()
|
|
+ dest_font.reset_full_checksum()
|
|
+ dest_font.close()
|
|
+ print(message)
|
|
|
|
if self.args.postprocess:
|
|
subprocess.call([self.args.postprocess, outfile])
|
|
|