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)) |