Example #1
0
def svg2glif(svg_file,
             name,
             width=0,
             height=0,
             unicodes=None,
             transform=None,
             version=2):
    """ Convert an SVG outline to a UFO glyph with given 'name', advance
    'width' and 'height' (int), and 'unicodes' (list of int).
    Return the resulting string in GLIF format (default: version 2).
    If 'transform' is provided, apply a transformation matrix before the
    conversion (must be tuple of 6 floats, or a FontTools Transform object).
    """
    glyph = SimpleNamespace(width=width, height=height, unicodes=unicodes)
    outline = SVGPath(svg_file, transform)

    # writeGlyphToString takes a callable (usually a glyph's drawPoints
    # method) that accepts a PointPen, however SVGPath currently only has
    # a draw method that accepts a segment pen. We need to wrap the call
    # with a converter pen.
    def drawPoints(pointPen):
        pen = SegmentToPointPen(pointPen)
        outline.draw(pen)

    return writeGlyphToString(name,
                              glyphObject=glyph,
                              drawPointsFunc=drawPoints,
                              formatVersion=version)
Example #2
0
    def setContext(self, font, feaFile, compiler=None):
        """ Populate a temporary `self.context` namespace, which is reset
        after each new call to `_write` method.
        Subclasses can override this to provide contextual information
        which depends on other data, or set any temporary attributes.

        The default implementation sets:
        - the current font;
        - the current FeatureFile object;
        - the current compiler instance (only present when this writer was
          instantiated from a FeatureCompiler);
        - a set of features (tags) to be generated. If self.mode is "skip",
          these are all the features which are _not_ already present.

        Returns the context namespace instance.
        """
        todo = set(self.features)
        if self.mode == "skip":
            existing = ast.findFeatureTags(feaFile)
            todo.difference_update(existing)

        self.context = SimpleNamespace(font=font,
                                       feaFile=feaFile,
                                       compiler=compiler,
                                       todo=todo)

        return self.context
Example #3
0
 def getKerningData(cls, font, feaFile=None, glyphSet=None):
     side1Classes, side2Classes = cls.getKerningClasses(
         font, feaFile, glyphSet)
     pairs = cls.getKerningPairs(font, side1Classes, side2Classes, glyphSet)
     return SimpleNamespace(side1Classes=side1Classes,
                            side2Classes=side2Classes,
                            pairs=pairs)
Example #4
0
def test_decompile(table, numGlyphs, data, expected_indices,
                   expected_extra_indices):
    font = {'maxp': SimpleNamespace(numGlyphs=numGlyphs)}

    table.decompile(data, font)

    assert len(table.indices) == numGlyphs
    assert table.indices == expected_indices
    assert len(table.extra_indices) == 4
    assert table.extra_indices == expected_extra_indices
Example #5
0
def svg2glif(path, name, width=0, height=0, unicodes=None, version=2, transform=(1, 0, 0, 1, 0, 0)):
    glyph = SimpleNamespace(width=width, height=height, unicodes=unicodes)

    def drawPoints(pointPen):
        pen = TransformPen(SegmentToPointPen(pointPen), transform)
        parse_path(path, pen)

    return writeGlyphToString(name,
                              glyphObject=glyph,
                              drawPointsFunc=drawPoints,
                              formatVersion=version)
Example #6
0
    def set_context(self, font):
        """ Populate a `self.context` namespace, which is reset before each
        new call to `_write` method.

        Subclasses can override this to provide contextual information
        which depends on other data in the font that is not available in
        the glyphs objects currently being filtered, or set any other
        temporary attributes.

        The default implementation simply sets the current font, and
        returns the namepace instance.
        """
        self.context = SimpleNamespace(font=font)
        return self.context
Example #7
0
    def set_context(self, font, glyphSet):
        """ Populate a `self.context` namespace, which is reset before each
        new filter call.

        Subclasses can override this to provide contextual information
        which depends on other data in the font that is not available in
        the glyphs objects currently being filtered, or set any other
        temporary attributes.

        The default implementation simply sets the current font and glyphSet,
        and initializes an empty set that keeps track of the names of the
        glyphs that were modified.

        Returns the namespace instance.
        """
        self.context = SimpleNamespace(font=font, glyphSet=glyphSet)
        self.context.modified = set()
        return self.context
Example #8
0
def totree(
    value,
    sort_keys=True,
    skipkeys=False,
    use_builtin_types=None,
    pretty_print=True,
    indent_level=1,
):
    if use_builtin_types is None:
        use_builtin_types = USE_BUILTIN_TYPES
    else:
        use_builtin_types = use_builtin_types
    context = SimpleNamespace(
        sort_keys=sort_keys,
        skipkeys=skipkeys,
        use_builtin_types=use_builtin_types,
        pretty_print=pretty_print,
        indent_level=indent_level,
    )
    return _make_element(value, context)
Example #9
0
    def __init__(self, features=None, mode=None, linesep="\n", **kwargs):
        if features is not None:
            default_features = set(self.__class__.features)
            self.features = []
            for feat in features:
                if feat not in default_features:
                    raise ValueError(feat)
                self.features.append(feat)

        if mode is not None:
            if mode not in _SUPPORTED_MODES:
                raise ValueError(mode)
            self.mode = mode

        self.linesep = linesep

        options = dict(self.__class__.options)
        for k in kwargs:
            if k not in options:
                raise TypeError("unsupported keyword argument: %r" % k)
            options[k] = kwargs[k]
        self.options = SimpleNamespace(**options)
Example #10
0
    def __init__(self, features=None, mode=None, **kwargs):
        if features is not None:
            features = frozenset(features)
            assert features, "features cannot be empty"
            unsupported = features.difference(self.__class__.features)
            if unsupported:
                raise ValueError("unsupported: %s" % ", ".join(unsupported))
            self.features = features

        if mode is not None:
            self.mode = mode
        if self.mode not in self._SUPPORTED_MODES:
            raise ValueError(self.mode)

        options = dict(self.__class__.options)
        for k in kwargs:
            if k not in options:
                raise TypeError("unsupported keyword argument: %r" % k)
            options[k] = kwargs[k]
        self.options = SimpleNamespace(**options)

        logger = ".".join([self.__class__.__module__, self.__class__.__name__])
        self.log = logging.getLogger(logger)
Example #11
0
    def __init__(self, *args, **kwargs):
        self.options = options = SimpleNamespace()

        # process positional arguments
        num_required = len(self._args)
        num_args = len(args)
        if num_args < num_required:
            missing = [repr(a) for a in self._args[num_args:]]
            num_missing = len(missing)
            raise TypeError(
                "missing {0} required positional argument{1}: {2}".format(
                    num_missing, "s" if num_missing > 1 else "",
                    ", ".join(missing)))
        elif num_args > num_required:
            extra = [repr(a) for a in args[num_required:]]
            num_extra = len(extra)
            raise TypeError(
                "got {0} unsupported positional argument{1}: {2}".format(
                    num_extra, "s" if num_extra > 1 else "", ", ".join(extra)))
        for key, value in zip(self._args, args):
            setattr(options, key, value)

        # process optional keyword arguments
        for key, default in self._kwargs.items():
            setattr(options, key, kwargs.pop(key, default))

        # process special include/exclude arguments
        include = kwargs.pop('include', None)
        exclude = kwargs.pop('exclude', None)
        if include is not None and exclude is not None:
            raise ValueError(
                "'include' and 'exclude' arguments are mutually exclusive")
        if callable(include):
            # 'include' can be a function (e.g. lambda) that takes a
            # glyph object and returns True/False based on some test
            self.include = include
            self._include_repr = lambda: repr(include)
        elif include is not None:
            # or it can be a list of glyph names to be included
            included = set(include)
            self.include = lambda g: g.name in included
            self._include_repr = lambda: repr(include)
        elif exclude is not None:
            # alternatively one can provide a list of names to not include
            excluded = set(exclude)
            self.include = lambda g: g.name not in excluded
            self._exclude_repr = lambda: repr(exclude)
        else:
            # by default, all glyphs are included
            self.include = lambda g: True

        # raise if any unsupported keyword arguments
        if kwargs:
            num_left = len(kwargs)
            raise TypeError(
                "got {0}unsupported keyword argument{1}: {2}".format(
                    "an " if num_left == 1 else "",
                    "s" if len(kwargs) > 1 else "",
                    ", ".join("'{}'".format(k) for k in kwargs)))

        # run the filter's custom initialization code
        self.start()
Example #12
0
 def fontInfo(self):
     if self._fontInfo is None:
         info = SimpleNamespace()
         self._reader.readInfo(info)
         self._fontInfo = vars(info)
     return self._fontInfo