Exemple #1
0
 def test_options(self):
     # https://github.com/behdad/fonttools/issues/413
     opt1 = subset.Options()
     self.assertTrue('Xyz-' not in opt1.layout_features)
     opt2 = subset.Options()
     opt2.layout_features.append('Xyz-')
     self.assertTrue('Xyz-' in opt2.layout_features)
     self.assertTrue('Xyz-' not in opt1.layout_features)
    def _extract_subset(self, options=None):
        if options is None:
            options = subset.Options(layout_closure=False)
            options.drop_tables += ['GPOS', 'GDEF', 'GSUB']

        if self.use_raw_gids:
            # Have to retain GIDs in the Type2 (non-CFF) case, since we don't
            # have a predefined character set available (i.e. the ROS ordering
            # param is 'Identity')
            # This ensures that the PDF operators we output will keep working
            # with the subsetted font, at the cost of a slight space overhead in
            # the output.
            # This is fine, because fonts with a number of glyphs where this
            # would matter (i.e. large CJK fonts, basically), are subsetted as
            # CID-keyed CFF fonts anyway (and based on a predetermined charset),
            # so this subtlety doesn't apply and the space overhead is very
            # small.

            # NOTE: we apply the same procedure to string-keyed CFF fonts,
            # even though this is rather inefficient... XeTeX can subset these
            # much more compactly, presumably by rewriting the CFF charset data.
            # TODO look into how that works
            options.retain_gids = True

        subsetter: subset.Subsetter = subset.Subsetter(options=options)
        subsetter.populate(gids=list(self._glyphs.keys()))
        subsetter.subset(self.tt)
Exemple #3
0
def rename(font):
    names = set()
    for layers in font["COLR"].ColorLayers.values():
        names |= {l.name for l in layers if LAYER.match(l.name)}

    del font["COLR"]
    del font["CPAL"]

    glyphs = set(font.glyphOrder) - names
    options = subset.Options()
    options.set(layout_features='*',
                name_IDs='*',
                name_languages='*',
                notdef_outline=True,
                glyph_names=True)
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(glyphs=glyphs)
    subsetter.subset(font)

    for name in font["name"].names:
        if name.nameID in (1, 3, 4, 6):
            string = name.toUnicode()
            if name.nameID in (3, 6):
                string = string.replace("QuranColored", "Quran")
            else:
                string = string.replace("Quran Colored", "Quran")

            name.string = string.encode(name.getEncoding())
Exemple #4
0
def main():
    parser = argparse.ArgumentParser(description="Merge Aref Ruqaa fonts.")
    parser.add_argument("file1", metavar="FILE", help="input font to process")
    parser.add_argument("file2", metavar="FILE", help="input font to process")
    parser.add_argument("--out-file",
                        metavar="FILE",
                        help="output font to write",
                        required=True)

    args = parser.parse_args()

    configLogger(level=logging.ERROR)

    merger = merge.Merger()
    font = merger.merge([args.file1, args.file2])

    # Drop incomplete Greek support.
    unicodes = set(font.getBestCmap().keys()) - set(range(0x0370, 0x03FF))

    options = subset.Options()
    options.set(
        layout_features="*",
        layout_scripts=["arab", "latn", "DFLT"],
        name_IDs="*",
        name_languages="*",
        notdef_outline=True,
        glyph_names=False,
        recalc_average_width=True,
    )
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(unicodes=unicodes)
    subsetter.subset(font)

    font.save(args.out_file)
Exemple #5
0
 def woffCreate(self, text=None, No='2'):
     mergeTools = merge.Merger()
     woffFile = "static/font/" + No + ".woff"
     saveFilename = str(Path(self.cwd) / woffFile)
     filename = [self.fontFile, saveFilename]
     textLuck = []
     baseUrl = 'https://www.font.cn/preview/getFont?font_id=303&format=ttf&vers=v1.0&words='
     urlEnd = '&hex=1'
     if text is None:
         return
     collectText = {t for t in text}
     text = ''.join(collectText)
     for t in text:
         if t not in self.name:
             hexT = str(hex(ord(t)))
             textLuck.append(hexT[2:])
     # print(len(textLuck))
     if len(textLuck) != 0:
         mergeUrl = ','.join(textLuck)
         aimUrl = baseUrl + mergeUrl + urlEnd
         fontDown = self.downloadWoff(aimUrl, saveFilename)
         if fontDown != None:
             mergeFont = mergeTools.merge(filename)
             mergeFont.save(self.fontFile)
     # 拆分合并后的字体文件成2.woff
     options = subset.Options()
     fontMerge = subset.load_font(self.fontFile, options)
     subsetter = subset.Subsetter(options)
     subsetter.populate(text=text)
     subsetter.subset(fontMerge)
     options.flavor = 'woff'
     subset.save_font(fontMerge, saveFilename, options)
Exemple #6
0
    def generate(self, version, output):
        self._update_metadata(version)
        self._cleanup_glyphs()
        self._make_over_under_line()
        self._font.generate(output, flags=("opentype"))

        font = TTFont(output)

        # https://github.com/fontforge/fontforge/pull/3235
        # fontDirectionHint is deprecated and must be set to 2
        font["head"].fontDirectionHint = 2
        # unset bits 6..10
        font["head"].flags &= ~0x7e0

        options = subset.Options()
        options.set(layout_features='*', name_IDs='*', notdef_outline=True,
                    glyph_names=True, recalc_average_width=True,
                    drop_tables=["FFTM"])

        unicodes = font["cmap"].getBestCmap().keys()

        subsetter = subset.Subsetter(options=options)
        subsetter.populate(unicodes=unicodes)
        subsetter.subset(font)

        font.save(output)
Exemple #7
0
    def subset_otf_from_ufo(self, otf_path, ufo):
        """Subset a font using export flags set by glyphsLib."""

        keep_glyphs = set(ufo.lib.get(GLYPHS_PREFIX + 'Keep Glyphs', []))

        include = []
        for old_name, new_name in zip(
                ufo.lib[PUBLIC_PREFIX + 'glyphOrder'],
                TTFont(otf_path).getGlyphOrder()):
            glyph = ufo[old_name]
            if ((keep_glyphs and old_name not in keep_glyphs) or
                not glyph.lib.get(GLYPHS_PREFIX + 'Glyphs.Export', True)):
                continue
            include.append(new_name)

        # copied from nototools.subset
        opt = subset.Options()
        opt.name_IDs = ['*']
        opt.name_legacy = True
        opt.name_languages = ['*']
        opt.layout_features = ['*']
        opt.notdef_outline = True
        opt.recalc_bounds = True
        opt.recalc_timestamp = True
        opt.canonical_order = True

        opt.glyph_names = True

        font = subset.load_font(otf_path, opt, lazy=False)
        subsetter = subset.Subsetter(options=opt)
        subsetter.populate(glyphs=include)
        subsetter.subset(font)
        subset.save_font(font, otf_path, opt)
Exemple #8
0
    def test_timing_publishes_parts(self):
        _, fontpath = self.compile_font(self.getpath("TestTTF-Regular.ttx"),
                                        ".ttf")

        options = subset.Options()
        options.timing = True
        subsetter = subset.Subsetter(options)
        subsetter.populate(text='ABC')
        font = TTFont(fontpath)
        with CapturingLogHandler('fontTools.subset.timer',
                                 logging.DEBUG) as captor:
            captor.logger.propagate = False
            subsetter.subset(font)
            logs = captor.records
        captor.logger.propagate = True

        self.assertTrue(len(logs) > 5)
        self.assertEqual(
            len(logs),
            len([l for l in logs if 'msg' in l.args and 'time' in l.args]))
        # Look for a few things we know should happen
        self.assertTrue(filter(lambda l: l.args['msg'] == "load 'cmap'", logs))
        self.assertTrue(
            filter(lambda l: l.args['msg'] == "subset 'cmap'", logs))
        self.assertTrue(
            filter(lambda l: l.args['msg'] == "subset 'glyf'", logs))
Exemple #9
0
def makeWeb(args):
    """If we are building a web version then try to minimise file size"""

    font = TTFont(args.file, recalcTimestamp=False)

    # removed compatibility glyphs that of little use on the web
    ranges = (
        (0xfb50, 0xfbb1),
        (0xfbd3, 0xfd3d),
        (0xfd50, 0xfdf9),
        (0xfdfc, 0xfdfc),
        (0xfe70, 0xfefc),
    )

    cmap = font['cmap'].buildReversed()
    unicodes = set([min(cmap[c]) for c in cmap])
    for r in ranges:
        unicodes -= set(range(r[0], r[1] + 1))

    options = subset.Options()
    options.set(layout_features='*', name_IDs='*', drop_tables=['DSIG'])
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(unicodes=unicodes)
    subsetter.subset(font)

    base, ext = os.path.splitext(args.file)
    for flavor in ("woff", "woff2"):
        font.flavor = flavor
        font.save(args.dir + "/" + base + "." + flavor)
    font.close()
Exemple #10
0
 def _prune(self, otf):
     options = subset.Options()
     options.set(layout_features='*', name_IDs='*', notdef_outline=True,
         recalc_average_width=True, recalc_bounds=True)
     subsetter = subset.Subsetter(options=options)
     subsetter.populate(unicodes=otf['cmap'].getBestCmap().keys())
     subsetter.subset(otf)
Exemple #11
0
        def handle_font(font_name):
            font = TTFont(font_name)
            orig_size = os.path.getsize(font_name)

            if decompress:
                from fontTools import subset
                options = subset.Options()
                options.desubroutinize = True
                subsetter = subset.Subsetter(options=options)
                subsetter.populate(glyphs=font.getGlyphOrder())
                subsetter.subset(font)

            if verbose:
                print("Compressing font through iterative_encode:")
            out_name = "%s.compressed%s" % os.path.splitext(font_name)

            compreffor = Compreffor(font, verbose=verbose, **comp_kwargs)
            compreffor.compress()

            # save compressed font
            font.save(out_name)

            if generate_cff:
                # save CFF version
                font["CFF "].cff.compile(
                    open("%s.cff" % os.path.splitext(out_name)[0], "w"), None)

            comp_size = os.path.getsize(out_name)
            print("Compressed to %s -- saved %s" %
                  (os.path.basename(out_name),
                   human_size(orig_size - comp_size)))

            if check:
                test_compression_integrity(filename, out_name)
                test_call_depth(out_name)
Exemple #12
0
def get_glyphs_subset(fontfile, characters):
    """
    Subset a TTF font

    Reads the named fontfile and restricts the font to the characters.
    Returns a serialization of the subset font as file-like object.

    Parameters
    ----------
    symbol : str
        Path to the font file
    characters : str
        Continuous set of characters to include in subset
    """

    options = subset.Options(glyph_names=True, recommended_glyphs=True)

    # prevent subsetting FontForge Timestamp and other tables
    options.drop_tables += ['FFTM', 'PfEd', 'BDF']

    # if fontfile is a ttc, specify font number
    if fontfile.endswith(".ttc"):
        options.font_number = 0

    with subset.load_font(fontfile, options) as font:
        subsetter = subset.Subsetter(options=options)
        subsetter.populate(text=characters)
        subsetter.subset(font)
        fh = BytesIO()
        font.save(fh, reorderTables=False)
        return fh
Exemple #13
0
def subset_ttf_font(filepath: str) -> dict:
    options = subset.Options()
    font = subset.load_font(f'{filepath}.ttf', options)
    options.flavor = 'woff'
    subset.save_font(font, f'{filepath}.woff', options)
    options.flavor = 'woff2'
    subset.save_font(font, f'{filepath}.woff2', options)
    return {'woff': f'{filepath}.woff', 'woff2': f'{filepath}.woff2'}
Exemple #14
0
def subSetFont(ff, tt):
    options = subset.Options()  # dir(options)
    font = subset.load_font(ff, options)
    subsetter = subset.Subsetter(options)
    subsetter.populate(text=tt)
    subsetter.subset(font)
    # options.flavor = 'woff'
    subset.save_font(font, 'font.ttf', options)
    modFont()
Exemple #15
0
def subset_font(source_file,
                target_file,
                include=None,
                exclude=None,
                options=None):
    """Subsets a font file.

    Subsets a font file based on a specified character set. If only include is
    specified, only characters from that set would be included in the output
    font.  If only exclude is specified, all characters except those in that
    set will be included.  If neither is specified, the character set will
    remain the same, but inaccessible glyphs will be removed.

    Args:
      source_file: Input file name.
      target_file: Output file name
      include: The list of characters to include from the source font.
      exclude: The list of characters to exclude from the source font.
      options: A dictionary listing which options should be different from the
          default.

    Raises:
      NotImplementedError: Both include and exclude were specified.
    """
    opt = subset.Options()

    opt.name_IDs = ["*"]
    opt.name_legacy = True
    opt.name_languages = ["*"]
    opt.layout_features = ["*"]
    opt.notdef_outline = True
    opt.recalc_bounds = True
    opt.recalc_timestamp = True
    opt.canonical_order = True
    opt.drop_tables = ["+TTFA"]

    if options is not None:
        for name, value in options.items():
            setattr(opt, name, value)

    if include is not None:
        if exclude is not None:
            raise NotImplementedError(
                "Subset cannot include and exclude a set at the same time.")
        target_charset = include
    else:
        if exclude is None:
            exclude = []
        source_charset = coverage.character_set(source_file)
        target_charset = source_charset - set(exclude)

    font = subset.load_font(source_file, opt)
    subsetter = subset.Subsetter(options=opt)
    subsetter.populate(unicodes=target_charset)
    subsetter.subset(font)
    subset.save_font(font, target_file, opt)
Exemple #16
0
    def subset_otf_from_ufo(self, otf_path, ufo):
        """Subset a font using export flags set by glyphsLib.

        There are two more settings that can change export behavior:
        "Export Glyphs" and "Remove Glyphs", which are currently not supported
        for complexity reasons. See
        https://github.com/googlei18n/glyphsLib/issues/295.
        """
        from fontTools import subset

        # ufo2ft always inserts a ".notdef" glyph as the first glyph
        ufo_order = makeOfficialGlyphOrder(ufo)
        if ".notdef" not in ufo_order:
            ufo_order.insert(0, ".notdef")
        ot_order = TTFont(otf_path).getGlyphOrder()
        assert ot_order[0] == ".notdef"
        assert len(ufo_order) == len(ot_order)

        for key in (KEEP_GLYPHS_NEW_KEY, KEEP_GLYPHS_OLD_KEY):
            keep_glyphs_list = ufo.lib.get(key)
            if keep_glyphs_list is not None:
                keep_glyphs = set(keep_glyphs_list)
                break
        else:
            keep_glyphs = None

        include = []
        for source_name, binary_name in zip(ufo_order, ot_order):
            if keep_glyphs and source_name not in keep_glyphs:
                continue

            if source_name in ufo:
                exported = ufo[source_name].lib.get(GLYPH_EXPORT_KEY, True)
                if not exported:
                    continue

            include.append(binary_name)

        # copied from nototools.subset
        opt = subset.Options()
        opt.name_IDs = ['*']
        opt.name_legacy = True
        opt.name_languages = ['*']
        opt.layout_features = ['*']
        opt.notdef_outline = True
        opt.recalc_bounds = True
        opt.recalc_timestamp = True
        opt.canonical_order = True

        opt.glyph_names = True

        font = subset.load_font(otf_path, opt, lazy=False)
        subsetter = subset.Subsetter(options=opt)
        subsetter.populate(glyphs=include)
        subsetter.subset(font)
        subset.save_font(font, otf_path, opt)
Exemple #17
0
 def test_no_hinting_TTF(self):
     _, fontpath = self.compile_font(self.getpath("TestTTF-Regular.ttx"), ".ttf")
     subsetpath = self.temp_path(".ttf")
     subset.main([fontpath, "--no-hinting", "--notdef-outline",
                  "--output-file=%s" % subsetpath, "*"])
     subsetfont = TTFont(subsetpath)
     self.expect_ttx(subsetfont, self.getpath(
         "expect_no_hinting_TTF.ttx"), ["glyf", "maxp"])
     for tag in subset.Options().hinting_tables:
         self.assertTrue(tag not in subsetfont)
def _get_default_options():
    opt = subset.Options()
    opt.name_IDs = ['*']
    opt.name_legacy = True
    opt.name_languages = ['*']
    opt.layout_features = ['*']
    opt.notdef_outline = True
    opt.recalc_bounds = True
    opt.recalc_timestamp = True
    opt.canonical_order = True
    return opt
    def subset(self, font_bytes, codepoints):  # pylint: disable=no-self-use
        """Computes a subset of font_bytes to the given codepoints."""
        options = subset.Options()
        subsetter = subset.Subsetter(options=options)
        with io.BytesIO(font_bytes) as font_io, \
             subset.load_font(font_io, options) as font:
            subsetter.populate(unicodes=codepoints)
            subsetter.subset(font)

            with io.BytesIO() as output:
                subset.save_font(font, output, options)
                return output.getvalue()
Exemple #20
0
def prune_font(fontfile, out_dir):
    font = fonttools.load_font(fontfile, fonttools.Options())

    # Roundtripping a font trough FontForge adds a GDEF table. This table is not
    # present in the original version of Calluna, so remove it. It is present in
    # Inconsolata, but it does not appear to do any harm to remove it, apart
    # from reducing the file size.
    if 'GDEF' in font:
        del font['GDEF']

    font.save(os.path.join(out_dir, os.path.basename(fontfile)))
    font.close()
Exemple #21
0
 def initOption(self, **kwargs):
     # 设置选项
     self.options = subset.Options()
     self.options.flavor = 'woff'
     for k, v in kwargs.items():
         if not hasattr(self.options, k):
             setattr(self.options, k, v)
     # 实例化字体
     self.font = subset.load_font(self.file_path, self.options)
     # 设置配置器
     self.subsetter = subset.Subsetter(self.options)
     self.subsetter.populate(text=self.text)
     self.subsetter.subset(self.font)
Exemple #22
0
def subsetFont(otf, unicodes):
    from fontTools import subset

    options = subset.Options()
    options.set(layout_features='*',
                name_IDs='*',
                name_languages='*',
                notdef_outline=True,
                glyph_names=True)
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(unicodes=unicodes)
    subsetter.subset(otf)
    return otf
Exemple #23
0
def subset_masters(designspace, subsetDict):
    from fontTools import subset
    subset_options = subset.Options(notdef_outline=True, layout_features='*')
    for ds_source in designspace.sources:
        key = tuple(ds_source.location.items())
        included = set(subsetDict[key])
        ttf_font = ds_source.font
        subsetter = subset.Subsetter(options=subset_options)
        subsetter.populate(glyphs=included)
        subsetter.subset(ttf_font)
        subset_path = f'{os.path.splitext(ds_source.path)[0]}.subset.otf'
        logger.progress(f'Saving subset font {subset_path}')
        ttf_font.save(subset_path)
        ds_source.font = TTFont(subset_path)
Exemple #24
0
def subsetFontFT(path, unicodes, quran=False):
    from fontTools import subset

    font = TTFont(path, recalcTimestamp=False)

    options = subset.Options()
    options.set(layout_features='*', name_IDs='*', name_languages='*',
        notdef_outline=True, glyph_names=True)
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(unicodes=unicodes)
    subsetter.subset(font)

    if quran:
        font["OS/2"].sTypoAscender = font["hhea"].ascent = font["head"].yMax

    font.save(path)
Exemple #25
0
def test_subset_feature_variations_keep_all(featureVarsTestFont):
    font = featureVarsTestFont

    options = subset.Options()
    subsetter = subset.Subsetter(options)
    subsetter.populate(unicodes=[ord("f"), ord("$")])
    subsetter.subset(font)

    featureTags = {
        r.FeatureTag for r in font["GSUB"].table.FeatureList.FeatureRecord
    }
    # 'dlig' is discretionary so it is dropped by default
    assert "dlig" not in featureTags
    assert "f_f" not in font.getGlyphOrder()
    # 'rvrn' is required so it is kept by default
    assert "rvrn" in featureTags
    assert "dollar.rvrn" in font.getGlyphOrder()
        def handle_font(font_name):
            font = TTFont(font_name)

            td = font['CFF '].cff.topDictIndex[0]
            no_subrs = lambda fd: hasattr(fd, 'Subrs') and len(fd.Subrs) > 0
            priv_subrs = (hasattr(td, 'FDArray')
                          and any(no_subrs(fd) for fd in td.FDArray))
            if len(td.GlobalSubrs) > 0 or priv_subrs:
                print("Warning: There are subrs in %s" % font_name)

            orig_size = os.path.getsize(font_name)

            if decompress:
                from fontTools import subset
                options = subset.Options()
                options.desubroutinize = True
                subsetter = subset.Subsetter(options=options)
                subsetter.populate(glyphs=font.getGlyphOrder())
                subsetter.subset(font)

            out_name = "%s.compressed%s" % os.path.splitext(font_name)

            compreff(font, verbose=verbose, **comp_kwargs)

            # save compressed font
            start_time = time.time()
            font.save(out_name)
            if verbose:
                print("Compiled and saved (took %gs)" %
                      (time.time() - start_time))

            if generate_cff:
                # save CFF version
                font['CFF '].cff.compile(
                    open("%s.cff" % os.path.splitext(out_name)[0], 'w'), None)

            comp_size = os.path.getsize(out_name)
            print("Compressed to %s -- saved %s" %
                  (os.path.basename(out_name),
                   human_size(orig_size - comp_size)))

            if check:
                test_compression_integrity(filename, out_name)
                test_call_depth(out_name)
Exemple #27
0
    def _extract_subset(self, options=None):
        options = options or subset.Options(layout_closure=False)
        if not self.is_cff_font:
            # Have to retain GIDs in the Type2 (non-CFF) case, since we don't
            # have a predefined character set available (i.e. the ROS ordering
            # param is 'Identity')
            # This ensures that the PDF operators we output will keep working
            # with the subsetted font, at the cost of a slight space overhead in
            # the output.
            # This is fine, because fonts with a number of glyphs where this
            # would matter (i.e. large CJK fonts, basically), are subsetted as
            # CFF fonts anyway (and based on a predetermined charset),
            # so this subtlety doesn't apply and the space overhead is very
            # small.
            options.retain_gids = True

        subsetter: subset.Subsetter = subset.Subsetter(options=options)
        subsetter.populate(gids=list(self._glyphs.keys()))
        subsetter.subset(self.tt)
Exemple #28
0
def test_subset_feature_variations_drop_all(featureVarsTestFont):
    font = featureVarsTestFont

    options = subset.Options()
    options.layout_features.remove("rvrn")  # drop 'rvrn'
    subsetter = subset.Subsetter(options)
    subsetter.populate(unicodes=[ord("f"), ord("$")])
    subsetter.subset(font)

    featureTags = {
        r.FeatureTag for r in font["GSUB"].table.FeatureList.FeatureRecord
    }
    glyphs = set(font.getGlyphOrder())

    assert "rvrn" not in featureTags
    assert glyphs == {".notdef", "f", "dollar"}
    # all FeatureVariationRecords were dropped
    assert font["GSUB"].table.FeatureVariations is None
    assert font["GSUB"].table.Version == 0x00010000
Exemple #29
0
def test_subset_feature_variations():
    fb = FontBuilder(unitsPerEm=100)
    fb.setupGlyphOrder([".notdef", "f", "f_f", "dollar", "dollar.rvrn"])
    fb.setupCharacterMap({ord("f"): "f", ord("$"): "dollar"})
    fb.setupNameTable({
        "familyName": "TestFeatureVars",
        "styleName": "Regular"
    })
    fb.setupPost()
    fb.setupFvar(axes=[("wght", 100, 400, 900, "Weight")], instances=[])
    fb.addOpenTypeFeatures("""\
        feature dlig {
            sub f f by f_f;
        } dlig;
    """)
    fb.addFeatureVariations([([{
        "wght": (0.20886, 1.0)
    }], {
        "dollar": "dollar.rvrn"
    })],
                            featureTag="rvrn")
    buf = io.BytesIO()
    fb.save(buf)
    buf.seek(0)

    font = TTFont(buf)

    options = subset.Options()
    subsetter = subset.Subsetter(options)
    subsetter.populate(unicodes=[ord("f"), ord("$")])
    subsetter.subset(font)

    featureTags = {
        r.FeatureTag
        for r in font["GSUB"].table.FeatureList.FeatureRecord
    }
    # 'dlig' is discretionary so it is dropped by default
    assert "dlig" not in featureTags
    assert "f_f" not in font.getGlyphOrder()
    # 'rvrn' is required so it is kept by default
    assert "rvrn" in featureTags
    assert "dollar.rvrn" in font.getGlyphOrder()
Exemple #30
0
def decompress(ttFont, **kwargs):
    """ Use the FontTools Subsetter to desubroutinize the font's CFF table.
    Any keyword arguments are passed on as options to the Subsetter.
    Skip if the font contains no subroutines.
    """
    if not has_subrs(ttFont):
        log.debug('No subroutines found; skip decompress')
        return

    from fontTools import subset

    # The FontTools subsetter modifies many tables by default; here
    # we only want to desubroutinize, so we run the subsetter on a
    # temporary copy and extract the resulting CFF table from it
    make_temp = kwargs.pop('make_temp', True)
    if make_temp:
        from io import BytesIO
        from fontTools.ttLib import TTFont, newTable

        stream = BytesIO()
        ttFont.save(stream, reorderTables=None)
        stream.flush()
        stream.seek(0)
        tmpfont = TTFont(stream)
    else:
        tmpfont = ttFont  # run subsetter on the original font

    options = subset.Options(**kwargs)
    options.desubroutinize = True
    options.notdef_outline = True
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(glyphs=tmpfont.getGlyphOrder())
    subsetter.subset(tmpfont)

    if make_temp:
        # copy modified CFF table to original font
        data = tmpfont['CFF '].compile(tmpfont)
        table = newTable('CFF ')
        table.decompile(data, ttFont)
        ttFont['CFF '] = table
        tmpfont.close()