Beispiel #1
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()
Beispiel #2
0
def subset_font_cmap(srcname,
                     dstname,
                     exclude=None,
                     include=None,
                     bump_version=True):

    opt = _DEFAULT_OPTIONS

    font = subset.load_font(srcname, opt)
    target_charset = set(font_data.get_cmap(font).keys())

    if include is not None:
        target_charset &= include
    if exclude is not None:
        target_charset -= exclude

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

    if bump_version:
        # assume version string has 'uh' if unhinted, else hinted.
        revision, version_string = swat_license.get_bumped_version(font)
        font['head'].fontRevision = revision
        font_data.set_name_record(font, _VERSION_ID, version_string)

    subset.save_font(font, dstname, opt)
Beispiel #3
0
    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)
Beispiel #4
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)
Beispiel #5
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)
Beispiel #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)
Beispiel #7
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())
Beispiel #8
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)
Beispiel #9
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)
Beispiel #10
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))
Beispiel #11
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)
Beispiel #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
Beispiel #13
0
def closeGlyphsOverGSUB(gsub, glyphs):
    """ Use the FontTools subsetter to perform a closure over the GSUB table
    given the initial `glyphs` (set of glyph names, str). Update the set
    in-place adding all the glyph names that can be reached via GSUB
    substitutions from this initial set.
    """
    subsetter = subset.Subsetter()
    subsetter.glyphs = glyphs
    gsub.closure_glyphs(subsetter)
Beispiel #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()
Beispiel #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)
Beispiel #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)
    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()
Beispiel #18
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)
Beispiel #19
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
Beispiel #20
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)
Beispiel #21
0
def _get_subset_font(source_file_path, text):
    """
    Given a source file and some text, returns a new, in-memory fontTools Font object
    that has only the glyphs specified in the set.

    Note that passing actual text instead of a glyph set to the subsetter allows it to
    generate appropriate ligatures and other features important for correct rendering.
    """
    if not os.path.exists(source_file_path):
        logging.error("'{}' not found".format(source_file_path))

    font = _load_font(source_file_path)
    subsetter = subset.Subsetter(options=FONT_TOOLS_OPTIONS)
    subsetter.populate(text=text)
    subsetter.subset(font)
    return font
Beispiel #22
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)
Beispiel #23
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()
Beispiel #24
0
        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)
Beispiel #25
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)
Beispiel #26
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
Beispiel #27
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()
Beispiel #28
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()
Beispiel #29
0
def _desubtoutinize(otf):
    # Desubroutinize with Subsetter (like compreffor does)
    from io import BytesIO

    stream = BytesIO()
    otf.save(stream, reorderTables=False)
    stream.flush()
    stream.seek(0)
    tmpfont = ttLib.TTFont(stream)

    options = subset.Options()
    options.desubroutinize = True
    options.notdef_outline = True
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(glyphs=tmpfont.getGlyphOrder())
    subsetter.subset(tmpfont)
    data = tmpfont['CFF '].compile(tmpfont)
    table = ttLib.newTable('CFF ')
    table.decompile(data, otf)
    otf['CFF '] = table
    tmpfont.close()
def main(args):
    if not args.filepath:
        raise AttributeError('Please specify font filepath')
    if not os.path.exists(args.filepath):
        raise AttributeError('File: %s not found' % args.filepath)

    textfile_dir = '_posts'
    unichars = set()

    def walk_callback(args, dirname, fnames):
        for fname in fnames:
            unichars.update(get_unicodes(os.path.join(dirname, fname)))

    os.path.walk(textfile_dir, walk_callback, None)
    unicodes = [ord(c) for c in unichars]

    cjk_fontfile = args.filepath
    out_fontdir = 'assets/fonts'
    out_fontfile = makeOutputFileName(os.path.basename(args.filepath),
                                      outputDir=out_fontdir,
                                      extension='.woff',
                                      overWrite=True)

    options = subset.Options()
    dontLoadGlyphNames = not options.glyph_names
    font = subset.load_font(cjk_fontfile,
                            options,
                            dontLoadGlyphNames=dontLoadGlyphNames)
    subsetter = subset.Subsetter()
    subsetter.populate(glyphs=[], gids=[], unicodes=unicodes, text='')
    subsetter.subset(font)
    sfnt.USE_ZOPFLI = True
    font.flavor = 'woff'
    font.save(out_fontfile, reorderTables=False)

    print('Input font: % 7d bytes: %s' %
          (os.path.getsize(cjk_fontfile), cjk_fontfile))
    print('Subset font: % 7d bytes: %s' %
          (os.path.getsize(out_fontfile), out_fontfile))