PDF Output: Ignore glyph size mismatches when merging fonts for TTF. Fixes #1866364 [PDF Conversion and Unicode Error](https://bugs.launchpad.net/calibre/+bug/1866364)

There appear to be a few mysterious windows systems where there are
fonts installed that cause this behavior in chromiums PDF system.
This commit is contained in:
Kovid Goyal 2020-03-07 08:14:31 +05:30
parent c2f2eed564
commit 166a242ee3
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 8 additions and 7 deletions

View File

@ -919,7 +919,7 @@ def fonts_are_identical(fonts):
return True return True
def merge_font(fonts): def merge_font(fonts, log):
# choose the largest font as the base font # choose the largest font as the base font
fonts.sort(key=lambda f: len(f['Data'] or b''), reverse=True) fonts.sort(key=lambda f: len(f['Data'] or b''), reverse=True)
base_font = fonts[0] base_font = fonts[0]
@ -932,7 +932,7 @@ def merge_font(fonts):
cmaps = list(filter(None, (f['ToUnicode'] for f in t0_fonts))) cmaps = list(filter(None, (f['ToUnicode'] for f in t0_fonts)))
if cmaps: if cmaps:
t0_font['ToUnicode'] = as_bytes(merge_cmaps(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(*(f['sfnt'] for f in descendant_fonts)) 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 = [] widths = []
arrays = tuple(filter(None, (f['W'] for f in descendant_fonts))) arrays = tuple(filter(None, (f['W'] for f in descendant_fonts)))
if arrays: if arrays:
@ -947,7 +947,7 @@ def merge_font(fonts):
return t0_font, base_font, references_to_drop return t0_font, base_font, references_to_drop
def merge_fonts(pdf_doc): def merge_fonts(pdf_doc, log):
all_fonts = pdf_doc.list_fonts(True) all_fonts = pdf_doc.list_fonts(True)
base_font_map = {} base_font_map = {}
@ -976,7 +976,7 @@ def merge_fonts(pdf_doc):
items = [] items = []
for name, fonts in iteritems(base_font_map): for name, fonts in iteritems(base_font_map):
if mergeable(fonts): if mergeable(fonts):
t0_font, base_font, references_to_drop = merge_font(fonts) t0_font, base_font, references_to_drop = merge_font(fonts, log)
for ref in references_to_drop: for ref in references_to_drop:
replacements[ref] = t0_font['Reference'] replacements[ref] = t0_font['Reference']
data = base_font['sfnt']()[0] data = base_font['sfnt']()[0]
@ -1246,7 +1246,7 @@ def convert(opf_path, opts, metadata=None, output_path=None, log=default_log, co
page_number_display_map, page_layout, page_margins_map, page_number_display_map, page_layout, page_margins_map,
pdf_metadata, report_progress, toc if has_toc else None) pdf_metadata, report_progress, toc if has_toc else None)
merge_fonts(pdf_doc) merge_fonts(pdf_doc, log)
num_removed = dedup_type3_fonts(pdf_doc) num_removed = dedup_type3_fonts(pdf_doc)
if num_removed: if num_removed:
log('Removed', num_removed, 'duplicated Type3 glyphs') log('Removed', num_removed, 'duplicated Type3 glyphs')

View File

@ -12,7 +12,7 @@ class GlyphSizeMismatch(ValueError):
pass pass
def merge_truetype_fonts_for_pdf(*fonts): def merge_truetype_fonts_for_pdf(fonts, log=None):
# only merges the glyf and loca tables, ignoring all other tables # only merges the glyf and loca tables, ignoring all other tables
all_glyphs = {} all_glyphs = {}
ans = fonts[0] ans = fonts[0]
@ -28,7 +28,8 @@ def merge_truetype_fonts_for_pdf(*fonts):
all_glyphs[glyph_id] = glyf.glyph_data(offset, sz, as_raw=True) all_glyphs[glyph_id] = glyf.glyph_data(offset, sz, as_raw=True)
else: else:
if abs(sz - len(prev_glyph_data)) > 8: if abs(sz - len(prev_glyph_data)) > 8:
raise GlyphSizeMismatch('Size mismatch for glyph id: {} prev_sz: {} sz: {}'.format(glyph_id, len(prev_glyph_data), sz)) if log is not None:
log('Size mismatch for glyph id: {} prev_sz: {} sz: {}'.format(glyph_id, len(prev_glyph_data), sz))
glyf = ans[b'glyf'] glyf = ans[b'glyf']
head = ans[b'head'] head = ans[b'head']