diff --git a/src/calibre/ebooks/pdf/html_writer.py b/src/calibre/ebooks/pdf/html_writer.py
index 7c58c7a164..71e2a4d3ac 100644
--- a/src/calibre/ebooks/pdf/html_writer.py
+++ b/src/calibre/ebooks/pdf/html_writer.py
@@ -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
diff --git a/src/calibre/utils/fonts/sfnt/merge.py b/src/calibre/utils/fonts/sfnt/merge.py
index f8772fd8a0..01ed837938 100644
--- a/src/calibre/utils/fonts/sfnt/merge.py
+++ b/src/calibre/utils/fonts/sfnt/merge.py
@@ -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