1
0
Fork 0
mirror of https://gitlab.alpinelinux.org/alpine/aports.git synced 2025-07-22 02:35:23 +03:00
aports/community/nerd-fonts/761-correct-small-rendering.patch
2022-07-25 01:57:04 +02:00

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])