mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
PDF Output: yet another glyph width fix for change in Chromium output
Apparently, the HarfBuzz subsetter does not produce mergeable hhea tables, so we directly merge the W arrays instead, picking the widest width for each glyph id. Lord knows if the glyph ids are stable across fonts, if they aren't then we will need to do major surgery. Fixes #1907675 [MacOS 10.15.7 EPUB to PDF conversion](https://bugs.launchpad.net/calibre/+bug/1907675)
This commit is contained in:
parent
44f2d0e073
commit
24ac765178
@ -799,6 +799,43 @@ def merge_w_arrays(arrays):
|
||||
return ans
|
||||
|
||||
|
||||
def width_map_from_w_array(w):
|
||||
ans = {}
|
||||
i = 0
|
||||
while i + 1 < len(w):
|
||||
elem = w[i]
|
||||
next_elem = w[i+1]
|
||||
if isinstance(next_elem, list):
|
||||
for gid, width in zip(range(elem, elem + len(next_elem)), next_elem):
|
||||
ans[gid] = width
|
||||
i += 2
|
||||
else:
|
||||
try:
|
||||
width = w[i+2]
|
||||
except IndexError:
|
||||
width = 0
|
||||
for gid in range(elem, next_elem + 1):
|
||||
ans[gid] = width
|
||||
i += 3
|
||||
return ans
|
||||
|
||||
|
||||
def merge_w_arrays_directly(arrays):
|
||||
width_maps = tuple(map(width_map_from_w_array, arrays))
|
||||
|
||||
def getter(gid):
|
||||
return max(m.get(gid, 0) for m in width_maps)
|
||||
|
||||
all_gids = set()
|
||||
for m in width_maps:
|
||||
all_gids |= set(m)
|
||||
|
||||
widths = []
|
||||
for gid in sorted(all_gids):
|
||||
widths.extend((gid, gid, getter(gid)))
|
||||
return merge_w_arrays((widths,))
|
||||
|
||||
|
||||
class CMap(object):
|
||||
|
||||
def __init__(self):
|
||||
@ -933,18 +970,13 @@ def merge_font(fonts, log):
|
||||
cmaps = list(filter(None, (f['ToUnicode'] for f in t0_fonts)))
|
||||
if cmaps:
|
||||
t0_font['ToUnicode'] = as_bytes(merge_cmaps(cmaps))
|
||||
base_font['sfnt'], width_for_glyph_id, height_for_glyph_id = merge_truetype_fonts_for_pdf(tuple(f['sfnt'] for f in descendant_fonts), log)
|
||||
widths = []
|
||||
base_font['sfnt'] = merge_truetype_fonts_for_pdf(tuple(f['sfnt'] for f in descendant_fonts), log)
|
||||
arrays = tuple(filter(None, (f['W'] for f in descendant_fonts)))
|
||||
if arrays:
|
||||
for gid in all_glyph_ids_in_w_arrays(arrays):
|
||||
widths.append(gid), widths.append(gid), widths.append(1000*width_for_glyph_id(gid))
|
||||
base_font['W'] = merge_w_arrays((widths,))
|
||||
base_font['W'] = merge_w_arrays_directly(arrays)
|
||||
arrays = tuple(filter(None, (f['W2'] for f in descendant_fonts)))
|
||||
if arrays:
|
||||
for gid in all_glyph_ids_in_w_arrays(arrays):
|
||||
widths.append(gid), widths.append(gid), widths.append(1000*height_for_glyph_id(gid))
|
||||
base_font['W2'] = merge_w_arrays((widths,))
|
||||
base_font['W2'] = merge_w_arrays_directly(arrays)
|
||||
return t0_font, base_font, references_to_drop
|
||||
|
||||
|
||||
|
@ -15,6 +15,7 @@ def merge_truetype_fonts_for_pdf(fonts, log=None):
|
||||
# only merges the glyf and loca tables, ignoring all other tables
|
||||
all_glyphs = {}
|
||||
ans = fonts[0]
|
||||
|
||||
for font in fonts:
|
||||
loca = font[b'loca']
|
||||
glyf = font[b'glyf']
|
||||
@ -35,25 +36,6 @@ def merge_truetype_fonts_for_pdf(fonts, log=None):
|
||||
head = ans[b'head']
|
||||
loca = ans[b'loca']
|
||||
maxp = ans[b'maxp']
|
||||
advance_widths = advance_heights = (0,)
|
||||
hhea = ans.get(b'hhea')
|
||||
if hhea is not None:
|
||||
hhea.read_data(ans[b'hmtx'])
|
||||
advance_widths = tuple(x/head.units_per_em for x in hhea.advance_widths)
|
||||
vhea = ans.get(b'vhea')
|
||||
if vhea is not None:
|
||||
vhea.read_data(ans[b'vmtx'])
|
||||
advance_heights = tuple(x/head.units_per_em for x in vhea.advance_heights)
|
||||
|
||||
def width_for_glyph_id(gid):
|
||||
if gid >= len(advance_widths):
|
||||
gid = -1
|
||||
return advance_widths[gid]
|
||||
|
||||
def height_for_glyph_id(gid):
|
||||
if gid >= len(advance_heights):
|
||||
gid = -1
|
||||
return advance_heights[gid]
|
||||
|
||||
gmap = OrderedDict()
|
||||
for glyph_id in sorted(all_glyphs):
|
||||
@ -64,4 +46,4 @@ def merge_truetype_fonts_for_pdf(fonts, log=None):
|
||||
head.update()
|
||||
maxp.num_glyphs = len(loca.offset_map) - 1
|
||||
maxp.update()
|
||||
return ans, width_for_glyph_id, height_for_glyph_id
|
||||
return ans
|
||||
|
Loading…
x
Reference in New Issue
Block a user