Exemplo n.º 1
0
def merge_font(fonts):
    # choose the largest font as the base font
    fonts.sort(key=lambda f: len(f['Data'] or b''), reverse=True)
    base_font = fonts[0]
    t0_font = next(f for f in fonts if f['DescendantFont'] == base_font['Reference'])
    descendant_fonts = [f for f in fonts if f['Subtype'] != 'Type0']
    t0_fonts = [f for f in fonts if f['Subtype'] == 'Type0']
    references_to_drop = tuple(f['Reference'] for f in fonts if f is not base_font and f is not t0_font)
    if fonts_are_identical(descendant_fonts):
        return t0_font, base_font, references_to_drop
    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(*(f['sfnt'] for f in descendant_fonts))
    widths = []
    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,))
    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,))
    return t0_font, base_font, references_to_drop
Exemplo n.º 2
0
def merge_font_files(fonts, log):
    # As of Qt 5.15.1 Chromium has switched to harfbuzz and dropped sfntly. It
    # now produces font descriptors whose W arrays dont match the glyph width
    # information from the hhea table, in contravention of the PDF spec. So
    # we can no longer merge font descriptors, all we can do is merge the
    # actual sfnt data streams into a single stream and subset it to contain
    # only the glyphs from all W arrays.
    # choose the largest font as the base font

    fonts.sort(key=lambda f: len(f['Data'] or b''), reverse=True)
    descendant_fonts = [f for f in fonts if f['Subtype'] != 'Type0']
    total_size = sum(len(f['Data']) for f in descendant_fonts)
    merged_sfnt = merge_truetype_fonts_for_pdf(
        tuple(f['sfnt'] for f in descendant_fonts), log)
    w_arrays = tuple(filter(None, (f['W'] for f in descendant_fonts)))
    glyph_ids = all_glyph_ids_in_w_arrays(w_arrays, as_set=True)
    h_arrays = tuple(filter(None, (f['W2'] for f in descendant_fonts)))
    glyph_ids |= all_glyph_ids_in_w_arrays(h_arrays, as_set=True)
    try:
        pdf_subset(merged_sfnt, glyph_ids)
    except NoGlyphs:
        log.warn(
            f'Subsetting of {fonts[0]["BaseFont"]} failed with no glyphs found, ignoring'
        )
    font_data = merged_sfnt()[0]
    log(f'Merged {len(fonts)} instances of {fonts[0]["BaseFont"]} reducing size from {human_readable(total_size)} to {human_readable(len(font_data))}'
        )
    return font_data, tuple(f['Reference'] for f in descendant_fonts)