Check-in [58300ed51a]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | implement repeatCount, some tests |
|---|---|
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
58300ed51a5725ba65262370548691a8 |
| User & Date: | mario 2022-10-23 20:02:22 |
Context
|
2022-10-31
| ||
| 09:37 | more pacing tests check-in: 64ef7120d0 user: mario tags: trunk | |
|
2022-10-23
| ||
| 20:02 | implement repeatCount, some tests check-in: 58300ed51a user: mario tags: trunk | |
|
2022-10-12
| ||
| 13:01 | recombine zip_args into imagick_gif(), distribute some flags onto frame.pngs check-in: 4621d9c6bd user: mario tags: trunk | |
Changes
Changes to inkscape/export_gif.py.
| ︙ | ︙ | |||
468 469 470 471 472 473 474 |
self.gif = parent
self.convert_png = parent.convert_png
self.svg = svg # ← already a deepcopy
self.layer = layer
self.frames = layer.animate
self.delay = float(layer.args.get("delay", self.gif.options.delay))
self.layer.args.update({
| | | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
self.gif = parent
self.convert_png = parent.convert_png
self.svg = svg # ← already a deepcopy
self.layer = layer
self.frames = layer.animate
self.delay = float(layer.args.get("delay", self.gif.options.delay))
self.layer.args.update({
"delay": self.delay / self.frames # frame time split between animation steps / TODO: might need reset
})
def export(self):
""" applies transforms in each subframe, yields filename+args list """
transforms = []
for anim in self.svg.xpath("//svg:animate"):
transforms.append([self.animate_style(anim, **anim.attrib), self.pace(anim)])
|
| ︙ | ︙ | |||
608 609 610 611 612 613 614 |
return animation.getparent()
# pylint: disable=function-redefined, no-else-return, bare-except
def pace(self, anim, smooth=False):
"""
Some relative time slice folding into linear 0.0 … 1.0 frame interval.
Might be able to recognize some of: begin, dur, keyTimes, calcMode, etc.
| | < < | 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 |
return animation.getparent()
# pylint: disable=function-redefined, no-else-return, bare-except
def pace(self, anim, smooth=False):
"""
Some relative time slice folding into linear 0.0 … 1.0 frame interval.
Might be able to recognize some of: begin, dur, keyTimes, calcMode, etc.
Simply chains bounding functions. Enabled on [pace] flag or global option.
"""
attr = anim.attrib.get
r_begin = self.seconds(attr("begin")) / self.delay
r_end = r_begin + self.seconds(attr("dur"), self.delay) / self.delay
def vary(r_time):
""" no transform / calcMode=linear """
|
| ︙ | ︙ | |||
632 633 634 635 636 637 638 |
if r_time < r_begin:
return 0.0
elif r_time > r_end:
return 1.0
else:
return (r_time - r_begin) / r_end
| > > > | > | | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
if r_time < r_begin:
return 0.0
elif r_time > r_end:
return 1.0
else:
return (r_time - r_begin) / r_end
if attr("repeatCount"):
# meh: ignorantly zigzags the repeat into our .delay time slice
def vary(r_time, count=int(attr("repeatCount")), vary=vary):
""" amplify by repeatCount, modulo into 0.0 … 1.0 interval """
return (count * vary(r_time)) % 1.0
if attr("calcMode") == "discrete":
def vary(r_time):
""" just snaps from one to the other extreme; nobody will ever use it """
return 0.0 if r_time < 0.5 else 1.0
if attr("calcMode") == "paced" or smooth and not attr("calcMode"):
def vary(r_time, vary=vary):
|
| ︙ | ︙ |
Added inkscape/pytest.ini.
> > > > > > > | 1 2 3 4 5 6 7 | [pytest] minversion = 1.0 addopts = -ra -q --ignore=test/util.py --ignore=test/_*.py --ignore=test/__*.py -p no:warnings testpaths = test/ python_files = *.py # Yes sure pytest, why not do the obvious thing anyway python_functions = !_* [a-z]* [A-Z]* !_* |
Added inkscape/test/conftest.py.
> > > > > > > > | 1 2 3 4 5 6 7 8 |
# id: __init__
import sys
sys.path.append(".")
sys.path.append("..")
sys.path.append("/usr/share/inkscape/extensions/")
import pylint
import export_gif
import animate_yo
|
Added inkscape/test/pace.py.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# t: t
# encoding:utf-8
# title: AnimationSteps().pace() interval mapping
#
# That's really the least worthwhile thing to test,
# but the only thing that can realistically be.
# (Generating SVGs and asserting binary GIF output is way beyond scope.)
#
import pytest
import export_gif as xg
from argparse import Namespace
# lazier @dataclass
class AnimTest():
def __init__(self, **kwargs):
self.attrib = kwargs
# stub out with parent attributes
class PaceTest(xg.AnimationSteps):
def __init__(self):
self.frames = 10
self.delay = 10
self.layer = Namespace(
tags = {"pace"},
args = {"delay": 10},
)
self.gif = Namespace(
options = Namespace(
all_pace = True,
delay = 10,
)
)
@pytest.fixture
def times():
return [i/10.0 for i in range(0, 11)]
# round result list
def _roundy(ls):
return [round(x, 2) for x in ls]
# simple interval 2s-4s within 10s frame
def pace_delay_dur(times):
anim = AnimTest(begin="2s", dur="4s")
vary = PaceTest().pace(anim)
assert _roundy(vary(r) for r in times) == [0.0, 0.0, 0.0, 0.17, 0.33, 0.5, 0.67, 1.0, 1.0, 1.0, 1.0]
# oscillate twice in 10s frame
def pace_repeat(times):
anim = AnimTest(begin="0s", dur="10s", repeatCount="2")
vary = PaceTest().pace(anim)
assert _roundy(vary(r+0.0000) for r in times) == [0.0, 0.2, 0.4, 0.6, 0.8, 0.0, 0.2, 0.4, 0.6, 0.8, 0.0]
assert _roundy(vary(r-0.0001) for r in times) == [0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 0.2, 0.4, 0.6, 0.8, 1.0]
|
Added inkscape/test/t.py.
> > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# t: t
# title: calcmodespline
def _map(r_time, steps=[0.0, 0.5]):
""" only linear [0, 0.33, 0.66, 1.0] here, values=[] would require interpretation in handlers """
dist = 1.0 / len(steps) # 0.25 for len=4
offs = int(r_time * len(steps)) # 0.30 → map [1]
steps = steps[:] + [1.0, 1.0]
val_diff = steps[offs+1] - steps[offs] # 0.33-0.25
off_diff = (r_time - dist * offs) / dist # offset [2]+0.1 to quantify value
return steps[offs] + val_diff * off_diff
def test_map_calcmode_spline():
for r in range(0, 21):
print(_map(r/20.0))
|