Repository navigation
Conversation
Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
…/writer Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
…pData graph Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
…++ verifier Metadata is serialized last but its strings must be present in the string table, which is written first. Intern them up front, then freeze the table so a missed interning site throws instead of handing out an out of range index. Also store marker durations as a proportion of the animation and carry the composition width and height through to the metadata. Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
The managed counterpart of the native interpreter. It exists so that the wire format can be round tripped and compared with the original graph, which is a much stronger check than testing the serializer alone. Every index is bounds checked and the buffer is verified before it is read, because buffers are untrusted input. Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
…d graphs Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
…y kind Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
- Move #include <unknwn.h> before LottieRuntime.h (which pulls in C++/WinRT headers), satisfying the classic-COM interop requirement. - Use winrt::implements<> with the projected interface listed first for GeometrySource and Effect, so winrt::make<> returns a com_ptr convertible to CompositionPath / IGraphicsEffect directly. - Fix StrokeMiterLimit cast (was uint32_t, should be float). - Default-construct WinRT projection type caches with nullptr fill value; these types have no default constructor. - Link dxguid.lib for D2D1 effect CLSIDs (Composite, GaussianBlur).
A console tool that links LottieRuntime.vcxproj, loads a serialized Lottie composition (.lcomp) given as its command-line argument, and prints the composition object hierarchy of the resulting visual tree: visuals, their shapes (recursively through container shapes), fill and stroke brushes, and gradient stops. Each line shows the runtime class name and, where set, the Comment property, so the printed tree can be matched back to the source Lottie layers. Builds via project reference to LottieRuntime.vcxproj and copies LottieRuntime.dll next to the exe as a post-build step, since C++ project references do not do this automatically.
Defines ILottieCompositionLoader (IID 3874B71B-05E6-42A9-B838-1AE7F0BA4E1C), a classic COM interface accepting (UINT32 length, BYTE const* buffer, REFIID, void**) that wraps LoadComposition for callers without a C++/WinRT toolchain. Implements it as LottieCompositionLoader (CLSID 9F7B7089-F512-4BBC-81FE-4FF12B4DA159) via winrt::implements<>, plus DllGetClassObject/DllCanUnloadNow exports and a LottieRuntime.def to keep those names undecorated. The class is never registered with the system: LottieRuntime.manifest is a private-assembly manifest declaring the comClass, copied next to a consuming exe and named directly by an ACTCTX, so CoCreateInstance resolves the CLSID without any HKEY_CLASSES_ROOT entry. Adds LottieRuntimeComTest, a console harness that builds an activation context from that manifest, activates it, CoCreateInstances the loader, and calls LoadComposition on a file argument. Known issue: CoCreateInstance currently returns E_ACCESSDENIED (0x80070005) even though CreateActCtx/ActivateActCtx succeed and the DLL exports DllGetClassObject/DllCanUnloadNow correctly - the private-assembly activation path needs further debugging before this is fully working end-to-end. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Create the desktop DispatcherQueue lazily before activating the loader's Compositor. This keeps CoCreateInstance side-effect-free and gives Windows.UI.Composition the thread infrastructure it requires. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Use C++/WinRT's module lock for IClassFactory::LockServer and DllCanUnloadNow so COM cannot unload the DLL while its objects remain alive. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Build the COM test, record it under Time Travel Debugging, and collect optional SideBySide and COM event logs into one directory. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Remove the one-off investigation helper now that the activation failure is diagnosed. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Handle omitted property-set state, expose the required effect-source interface, cache and cycle-check canvas geometries and strings, preserve sprite shadows, and load URI and stream image surfaces. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Use the FlatBuffers headers and flatc from pinned upstream default-branch commit 5761d6e for C++. Keep C# generation on the 25.2.10 runtime available through Microsoft's configured NuGet feed. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Create custom controllers explicitly, pass them to StartAnimation, and initialize root property sets before descending into children so controller expressions can bind to root progress. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Remove exported C++ symbols, require callers to own the DispatcherQueue, support architecture-neutral registration-free activation, load embedded image streams synchronously, and make the native project portable from its packaged source layout. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Replace separate validation and dump executables with LottieRuntime.exe supporting validate, --dump, and --show modes. Document JSON conversion and package the complete native runtime source set, COM project, generated binding, and FlatBuffers headers in LottieGen.nupkg. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Disable incremental linking and enable /O1, function-level linking, string pooling, LTCG, reference elimination, and COMDAT folding for Release builds. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
Keep the runtime loadable on Windows 10 1809 while rejecting compositions whose declared UniversalApiContract version is unavailable before graph hydration. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 58fac82f-0489-4c57-a18d-2b7ba273faa6
|
@dotnet-policy-service agree company="Microsoft" |
Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
Co-authored-by: jonwis <18537118+jonwis@users.noreply.github.com>
Split runtime schema dependencies from tool-side serialization, avoid copying byte-array buffers, and process keyframes in one pass. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 408cb9b9-d2b1-4a7a-bc3e-f6ab25b8793f
…preter Add a managed FlatBuffer interpreter alongside the native one
|
@jonwis I left a few inline comments, but wanted to share some higher-level thoughts as well:
|
| return false; | ||
| } | ||
|
|
||
| // NOTE: this only writes the latest version of a multi-version translation. |
There was a problem hiding this comment.
Lower-UAP translations are silently dropped here.
There was a problem hiding this comment.
I'll see what it takes to do that. I was hoping we'd be able to drop support for older UAPs and focus on WASDK version levels instead.
| return E_ILLEGAL_METHOD_CALL; | ||
| } | ||
|
|
||
| m_compositor = Compositor(); |
There was a problem hiding this comment.
The loader creates its own Compositor, so the returned visual can't be attached to the host's tree. I think we should accept compositor parameter from the caller, e.g. LoadComposition(IUnknown* compositor, UINT32, BYTE const*, REFIID, void**)
There was a problem hiding this comment.
Sure. Will add the new parameter here and in the IDL, docs, etc.
| // | ||
| // Throws winrt::hresult_error with E_INVALIDARG if the buffer is not a well formed | ||
| // composition, and E_NOTIMPL if it requires a feature this build does not have. | ||
| winrt::Windows::UI::Composition::Visual LoadComposition( |
There was a problem hiding this comment.
Right now this only returns back a raw Visual, so it doesn't match what other generated code does. Should we wrap it in an IAnimatedVisualSource that exposes the same stuff the generated class does (Duration, Markers, FrameCount, FrameToProgress, SetColorProperty, etc.)? Then TryCreateAnimatedVisual(compositor) would return the visual with Size/Duration.
There was a problem hiding this comment.
Hm. That's a XAML type? Why not stay within the Composition scope so somebody can use it without XAML?
| @@ -0,0 +1,108 @@ | |||
| # LottieRuntime (managed) | |||
There was a problem hiding this comment.
I think the managed side should just live in Lottie-Windows. Then there's one C# library that handles both JSON and .lcomp, and .lcomp can reuse the existing pipeline (CompositionDeserializer → Instantiator → AnimatedVisualPlayer) instead of a separate C# interpreter. I'd keep LottieRuntime as the small native runtime for C++ only. Otherwise, I'm worried we end up with too many pieces doing the same thing but a little differently.
There was a problem hiding this comment.
OK. I'll extend the existing C# library with this support instead and remove this one.
| auto collection = container.Children(); | ||
| for (uint32_t i = 0; i != children->size(); ++i) | ||
| { | ||
| auto child = GetVisual(children->Get(i)); |
There was a problem hiding this comment.
We might want to cap recursion depth here (and in GetShape/BuildGeometry). A relatively small malformed or malicious .lcomp could blow the stack.
There was a problem hiding this comment.
Seems reasonable. What cap depth seems good? I'll start with 256 maybe?
OK, will narrow to just the producer and C++ consumer code, and update the C# instantiator. In Windows, we'll want to have a shared copy of the instantiator. What do you think about "a pretty OK sample" that shows using this in a common way? Or do we just assume the bots will figure out how to have one copy per process?
That'd be great! Is there anything needed to get this ready for a C++/WinRT consumer of WASDK XAML/Composition? Does Lottie-Windows have a C++/WinRT package?
See note on supported UAP versions. At some point we should include "supported WASDK versions" and migrate people to using the Microsoft.UI types. I'll make the changes you suggest.
I'll have to see what that looks like; IIRC I had to tinker a bit to get flatc.exe working correctly. Thanks for the comments! |
Summary
Adds a data-driven runtime path for Lottie animations:
LottieGen -Language flatbufferconverts Lottie JSON into a compact.lcompFlatBuffer.LottieRuntimevalidates the FlatBuffer and hydrates the correspondingWindows.UI.Compositionvisual tree.The serialized graph supports the Composition objects, animations, effects, geometries, loaded images, and custom animation controllers emitted by the existing native generators.
Motivation
Generated C++/CX and C++/WinRT implementations duplicate the code needed to construct every object, property, animation, and expression in each animation. Complex animations produce large generated translation units and linked binaries. That increases DLL size, loaded code pages, private working set, and duplicated WinRT ABI call-site code.
The FlatBuffer path keeps each animation as data. One shared interpreter hydrates any number of animations into the same Composition object graph the generated implementations produce. Applications pay the interpreter cost once, then add only the FlatBuffer payload for each additional animation. The COM form can also be shared across binaries.
Size comparison
Measured with
LottieSamples/Assets/LottieLogo1.json, targeting UAP 15 on both paths. Both native binaries used/O1,/Gy, string pooling,/GL+/LTCG,/OPT:REF,/OPT:ICF, and non-incremental linking.LottieLogo1.lcomp)The first interpreted animation is 15,400 bytes (7.8%) smaller than the generated DLL, including the complete interpreter. Each additional animation adds only its FlatBuffer: 28,120 bytes instead of another 198,656-byte generated implementation for this sample, an 85.8% reduction in marginal binary payload.
The generated comparison DLL exports one creation entry point to keep the complete generated graph construction path reachable. The measurement excludes application host code and dependencies common to both approaches.
Runtime and ABI
LottieRuntime:LCMPidentifier and FlatBuffer structure before reading data;ILottieCompositionLoader::LoadComposition(UINT32, BYTE const*, REFIID, void**)as its DLL ABI;LottieRuntime.manifest;LoadComposition(Compositor, span<byte>)API available to applications that compile the implementation directly.The DLL exports only
DllGetClassObjectandDllCanUnloadNow. C++ projection types and exceptions do not cross the DLL boundary. The DLL targets Windows 10 1809 / UniversalApiContract v7; individual buffers declare any newer contract they require.Tooling
LottieRuntime.exe <path-to-flatbuffer> [--dump|--show]provides one native test and inspection tool:--dump: print the hydrated Composition object hierarchy;--show: host and animate the resulting visual in a Win32 window.Distribution
LottieGen.nupkgincludes the complete native runtime source set underLottieRuntime/:C++/WinRT applications can compile
LottieRuntime.cppdirectly into their product. Managed applications addLottieRuntime.vcxprojto the solution and copyLottieRuntime.dllplusLottieRuntime.manifestinto application outputs.Validation
LottieLogo1.jsonconverted to.lcomp, activated through registration-free COM, and hydrated successfully.LottieRuntime.exevalidate, dump, and show modes exercised on Release x64.LottieGen.nupkgand built independently.(via Copilot)