Skip to content

Curve_Gradient

sangfroid.layer.Curve_Gradient(tag=None) #

Bases: sangfroid.layer.layer.Layer

Attributes:

Name Type Description
amount sangfroid.value.simple.Real

blend_method sangfroid.value.blendmethod.BlendMethod

bline str

fast sangfroid.value.simple.Bool

gradient sangfroid.value.gradient.Gradient

loop sangfroid.value.simple.Bool

origin sangfroid.value.vector.X_Y

perpendicular sangfroid.value.simple.Bool

width sangfroid.value.simple.Real

z_depth sangfroid.value.simple.Real

zigzag sangfroid.value.simple.Bool

Source code in sangfroid/layer/layer.py
67
68
69
70
71
72
73
def __init__(self, tag=None):
    if tag is None:
        self._tag = self._construct_empty_tag()
    elif isinstance(tag, bs4.Tag):
        self._tag = tag
    else:
        raise TypeError(tag)

__call__ = find class-attribute instance-attribute #

Which Layer subclass handles which type of tag.

active = TagAttrField(bool, True) class-attribute instance-attribute #

True if this layer is enabled.

children property #

The sub-layers of this layer.

This is a generator. If this layer is not a Group, it yields no objects.

desc = DescField() class-attribute instance-attribute #

A description of this field. Can be None.

exclude_from_rendering = TagAttrField(bool, False, name='exclude_from_rendering') class-attribute instance-attribute #

True if this layer should not be rendered.

tag = TagField() class-attribute instance-attribute #

The BeautifulSoup tag behind this item.

type_ = TypeNameField() class-attribute instance-attribute #

The name Synfig uses internally for this type of layer.

In Python, you must spell this as type_, because type is a reserved word.

version = SynfigVersionField() class-attribute instance-attribute #

The earliest version of Synfig which will interpret the value of this field correctly.

append(layer) #

Adds a Layer to the end of a Group.

Synfig stores layers backwards, so this will result in the layer appearing in the file before all other layers of its group.

Parameters:

Name Type Description Default
layer typing.Self

the layer to add

required

Raises:

Type Description
NotImplementedError

if you're trying to add a layer to a layer which isn't a Group.

Source code in sangfroid/layer/layer.py
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
def append(self, layer: Self):
    """
    Adds a Layer to the end of a Group.

    Synfig stores layers backwards, so this will result in the layer
    appearing in the file before all other layers of its group.

    Args:
        layer: the layer to add

    Raises:
        NotImplementedError: if you're trying to add a layer
            to a layer which isn't a Group.
    """
    raise NotImplementedError(
            "Only Groups can contain other layers.")

find(*args, recursive=True, attrs=None, **kwargs) #

Like find_all(), except that it only returns the first item.

If no items are found, it returns None.

Arguments are as for find_all().

Source code in sangfroid/layer/layer.py
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
def find(self,
         *args:(bool|str|Self|Callable),
         recursive:bool = True,
         attrs:(dict|None) = None,
         **kwargs,
         ) -> (Self|None):
    """
    Like find_all(), except that it only returns the first item.

    If no items are found, it returns None.

    Arguments are as for find_all().
    """
    items = self.find_all(
            *args,
            recursive=recursive,
            attrs=attrs,
            **kwargs,
            )
    if items:
        return items[0]
    else:
        return None

find_all(*args, recursive=True, attrs=None, **kwargs) #

Finds sub-layers with particular properties.

This can only usefully be called on Groups. On other layers, it does nothing.

Parameters:

Name Type Description Default
args bool | str | typing.Self | collections.abc.Callable

you may specify at most one positional argument. If it's True, all children will match. If it's False, no children will match. If it's a string, it will match on the "type" field. If it's the Layer class or one of its subclasses, it will match layers of that type. If it's a callable, it will be called for each child; if it returns True, the child will be returned, and otherwise it won't.

()
recursive bool

if this is False, we only search the layer's immediate children; if it's True, which is the default, we search all the layer's descendants.

True
attrs dict | None

what to search for. We match against the field with the given name. The values should be strings, except that "type" can also be the class Layer or one of its subclasses.

None

You may supply extra kwargs, under the same terms as "attrs"; you may not specify the same key in both.

The format of the arguments is based on Beautiful Soup's Tag.find_all() method.

Source code in sangfroid/layer/layer.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
def find_all(self,
             *args:(bool|str|Self|Callable),
             recursive:bool = True,
             attrs:(dict|None) = None,
             **kwargs,
             ) -> [Self]:
    """
    Finds sub-layers with particular properties.

    This can only usefully be called on Groups. On other
    layers, it does nothing.

    Args:
        args: you may specify at most one positional argument.
            If it's True, all children will match.
            If it's False, no children will match.
            If it's a string, it will match on the "type" field.
            If it's the Layer class or one of its subclasses,
                it will match layers of that type.
            If it's a callable, it will be called for each
                child; if it returns True, the child will be
                returned, and otherwise it won't.

        recursive: if this is False, we only search
            the layer's immediate children; if it's True,
            which is the default, we search all the layer's
            descendants.

        attrs: what to search for. We match against the
            field with the given name. The values should be
            strings, except that "type" can also be the class
            Layer or one of its subclasses.

    You may supply extra kwargs, under the same terms as
    "attrs"; you may not specify the same key in both.

    The format of the arguments is based on Beautiful Soup's
    Tag.find_all() method.
    """

    matching_special = None

    if len(args)>1:
        raise ValueError(
                "You can only give one positional argument.")
    elif len(args)==1:

        if (
                isinstance(args[0], str) or
                (isinstance(args[0], type) and
                 issubclass(args[0], Layer))
                ):
            if 'type' in kwargs:
                raise ValueError(
                        "You can't give a type in both the positional "
                        "and keyword arguments.")

            kwargs['type'] = args[0]

        elif isinstance(args[0], bool):
            matching_special = args[0]

        elif hasattr(args[0], '__call__'):
            matching_special = args[0]

        else:
            raise TypeError(args[0])

    if 'attrs' in kwargs:
        for k,v in kwargs['attrs'].items():
            if k in kwargs:
                raise ValueError("{k} specified both as a kwarg and in attrs")
            kwargs[k] = v

        del kwargs['attrs']

    for k,v in kwargs.items():
        if k=='type':
            if not isinstance(v, str):
                v = v.__name__

            kwargs[k] = v.lower().replace('_', '')

    logger.debug("begin find_all")

    def matcher(found_tag):
        if found_tag.name!='layer':
            return False

        logger.debug("considering tag: %s %s",
                     found_tag.name, found_tag.attrs)

        found_layer = Layer.from_tag(found_tag)

        if matching_special is None:

            def munge(k,v):
                if k=='type':
                    k = 'type_'
                    v = v.lower()

                return (k,v)

            targets = [
                munge(k,v)
                for k,v in kwargs.items()
                ]

            logger.debug("want: %s", targets)

            for k, want_value in targets:
                try:
                    found_value = getattr(found_layer, k)
                    logger.debug("  -- %s field is %s; want %s", k,
                                 repr(found_value),
                                 repr(want_value),
                                 )
                except AttributeError:
                    logger.debug("  -- it does not have a %s", k)
                    continue

                logger.debug("  want: %s  found: %s",
                             want_value, found_value)

                if found_value==want_value:
                    logger.debug("    -- a match!")
                    return True

            logger.debug("  -- no matches.")
            return False

        elif isinstance(matching_special, bool):
            return matching_special

        else:
            result = matching_special(found_tag)
            logger.debug("  -- callback says: %s", result)
            return result

        raise ValueError(found_tag)

    result = [
            self.from_tag(x) for x in
            self._tag.find_all(matcher,
                              recursive=recursive,
                              )
            ]
    logger.debug("find_all found: %s",
                 result,
                 )

    return result

from_tag(tag) classmethod #

Constructs a layer from an XML tag.

Source code in sangfroid/layer/layer.py
336
337
338
339
340
341
342
343
344
345
@classmethod
def from_tag(cls, tag:bs4.Tag) -> Self:
    """
    Constructs a layer from an XML tag.
    """
    tag_type = tag.get('type', None)
    if tag_type is None:
        raise ValueError(
                f"tag has no 'type' field: {tag}")
    return cls.handles_type.from_name(name=tag_type)(tag)