Skip to content

Align Lottie graphic elements (grouping, geometry, and styles) with Lottie specifications - #2833

Open
MarkYav wants to merge 3 commits into
google:mainfrom
MarkYav:lottie-fix-AST-graphicelement
Open

Align Lottie graphic elements (grouping, geometry, and styles) with Lottie specifications#2833
MarkYav wants to merge 3 commits into
google:mainfrom
MarkYav:lottie-fix-AST-graphicelement

Conversation

@MarkYav

@MarkYav MarkYav commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

WHAT

Refactors and aligns all Lottie graphic elements (GraphicElement) in :remotecompose:lottie with the canonical Lottie 1.0.1 Specification and JSON Schema:

  • Sealed Category Hierarchies: Introduces category abstractions GeometryShape (contour path curves) and ShapeStyle (styling and shaders) under GraphicElement.
  • Grouping Elements: Brings Group and Transform into strict conformance with schema definitions #/$defs/shapes/group and #/$defs/shapes/transform.
  • Geometry Shapes: Unifies parametric and freeform path shapes (Ellipse, Path, PolyStar, Rectangle) under GeometryShape with canonical curve direction handling (ShapeDirection).
  • Shape Styles & Shaders: Implements AST models and polymorphic deserialization for solid strokes (Stroke), gradient fills (GradientFill), and gradient strokes (GradientStroke), alongside schema-compliant solid fills (Fill) and animatable gradient properties (Gradient.kt).
  • Metadata & Non-Spec Cleanup: Removes non-schema After Effects metadata attributes (ix, mn, cix, so, eo) and non-spec default object instantiations across all graphic elements.
  • Verification: Updates renderers and tests, enabling media screenshot diff tests (m3Next, volumeUp, volumeDown) to render accurately and pass without expected failure flags.

WHY

  1. Missing AST Support for Outlines and Gradients: Prior to this change, stroke elements ("ty": "st"), gradient fills ("ty": "gf"), and gradient strokes ("ty": "gs") were not supported in the AST or registered in GraphicElementSerializer. Animations containing stroked paths or gradients failed during parsing or omitted visible lines.
  2. Lack of Category Abstractions: Geometry and style elements previously implemented GraphicElement directly without intermediate contracts. This caused duplicated or missing definitions for common schema attributes (such as curve direction "d" on geometry shapes and required opacity "o" on shape styles).
  3. Spec Drift and Non-Schema Attributes: AST classes retained non-schema After Effects attributes (ix, mn, cix, so, eo) and default instances that did not conform to the Lottie 1.0.1 JSON Schema.

HOW

  1. Sealed Category Hierarchy:
    • Introduced GeometryShape exposing val direction: Int? ("d"), supported by ShapeDirection (Normal = 1, Reversed = 3) and fallback resolver shapeDirection.
    • Introduced ShapeStyle exposing val opacity: BaseScalarProperty ("o"), which is required across all style elements.
  2. Grouping Elements (Group, Transform):
    • Refactored Group to enforce schema properties: nm, hd, np, and ordered child elements it (shapes: List<GraphicElement>).
    • Refactored Transform to model required affine transformation properties (a, p, r, s, o) and optional skew distortion (sk, sa), removing obsolete extra opacity properties (so, eo).
  3. Geometry Shapes:
    • Aligned Ellipse (p, s, d), Path (ks, d), Rectangle (p, s, optional r, d), and PolyStar (sy, pt, p, r, or, os, optional ir, is, d) with exact schema requirements.
  4. Style Elements & Gradients:
    • Refactored Fill with schema fields nm, hd, o, c, and FillRule (NonZero = 1, EvenOdd = 2).
    • Implemented Stroke supporting line caps (LineCap), line joins (LineJoin), miter limits (ml, ml2), stroke width (w), and dash arrays (StrokeDash, StrokeDashType).
    • Implemented GradientFill and GradientStroke supporting linear and radial gradient types (GradientType), start/end points, and highlight properties.
    • Added BaseGradientProperty with polymorphic serialization for static (StaticGradientProperty) and keyframed animated gradients (AnimatedGradientProperty).
    • Registered all element discriminators in GraphicElementSerializer.
  5. Renderer & Tests:
    • Updated Shape.kt, Ellipse.kt, and Rectangle.kt to consume hidden?.constantValue, shapeDirection, and nullable cornerRadius.
    • Updated screenshot diff tests in MediaLottieDiffScreenshotTest.kt and regenerated verified golden screenshot fixtures.

Checklist 📋

  • Add explicit visibility modifier and explicit return types for public declarations
  • Run spotless check
  • Run tests
  • Update metalava's signature text files

### Impact Summary
`Group` and `Transform` AST models now strictly align with the canonical Lottie 1.0.1 schema definitions (`#/$defs/shapes/group` and `#/$defs/shapes/transform`). Non-schema properties (`so`, `eo`, `ix`, `mn`, `cix`) and non-spec default property instantiations have been removed, enforcing pure data class declarations with empty bodies.
Establish a common sealed ancestor interface `GeometryShape : GraphicElement`
for all parametric and freeform path-generating shapes (`Ellipse`, `Path`,
`Rectangle`, `PolyStar`), and bring their AST property models into strict
compliance with the Lottie 1.0.1 specification and JSON Schema.
### Motivation & Context
Previously, geometry models implemented `GraphicElement` directly without a
category abstraction, resulting in duplicate or missing definitions of the
curve drawing direction attribute `"d"`.
Establish a common sealed ancestor interface `ShapeStyle : GraphicElement` for
all style graphic elements (`Fill`, `Stroke`, `GradientFill`, `GradientStroke`),
and align their AST models and serializers strictly with the canonical
Lottie 1.0.1 specification and JSON Schema.

### Impact Summary
- Introduces sealed `ShapeStyle` category interface exposing the mandatory
  `opacity: BaseScalarProperty` attribute shared by all fill and stroke styles.
- Refactors `Fill` (`"ty": "fl"`): removes non-schema After Effects metadata
  fields (`ix`, `mn`, `cix`), non-spec blend modes, and enforces strict schema
  fields: name (`nm`), hidden (`hd`), opacity (`o`), color (`c`), and fill
  rule (`r` / `FillRule`).
- Implements `Stroke` (`"ty": "st"`): supports solid strokes with line cap
  (`lc` / `LineCap`), line join (`lj` / `LineJoin`), miter limit (`ml`), miter
  limit alternative (`ml2`), stroke width (`w`), and dash patterns
  (`d` / `StrokeDash`, `StrokeDashType`).
- Implements `GradientFill` (`"ty": "gf"`): supports linear and radial gradients
  (`t` / `GradientType`), start point (`s`), end point (`e`), gradient colors
  (`g` / `BaseGradientProperty`), fill rule (`r`), and highlight angle/length
  (`a`, `h`).
- Implements `GradientStroke` (`"ty": "gs"`): combines stroke styling attributes
  with gradient color properties.
- Registers style elements (`"st"`, `"gf"`, `"gs"`) in `GraphicElementSerializer`.
- Updates `LottieDecoderResilienceTest` and `MediaLottieDiffScreenshotTest` to
  reflect stroke support and schema-mandated opacity.

### Motivation
Shape style models previously lacked a unifying sealed abstraction, and stroke
and gradient style elements (`Stroke`, `GradientFill`, `GradientStroke`) were
unsupported in the AST, preventing animations with line strokes and gradients
from loading. In addition, existing style models contained non-schema After
Effects metadata attributes and non-spec defaults.

### External References
- [Lottie Shape Style Specification](https://lottie.github.io/lottie-spec/latest/specs/shapes/#shape-style)
- [Lottie Fill Specification](https://lottie.github.io/lottie-spec/1.0.1/specs/shapes/#fill) (`#/$defs/shapes/fill`)
- [Lottie Stroke Specification](https://lottie.github.io/lottie-spec/1.0.1/specs/shapes/#stroke) (`#/$defs/shapes/stroke`)
- [Lottie Gradient Fill Specification](https://lottie.github.io/lottie-spec/1.0.1/specs/shapes/#gradient-fill) (`#/$defs/shapes/gradient-fill`)
- [Lottie Gradient Stroke Specification](https://lottie.github.io/lottie-spec/1.0.1/specs/shapes/#gradient-stroke) (`#/$defs/shapes/gradient-stroke`)
- [Lottie Line Cap Specification](https://lottie.github.io/lottie-spec/1.0.1/specs/constants/#line-cap) (`#/$defs/constants/line-cap`)
- [Lottie Line Join Specification](https://lottie.github.io/lottie-spec/1.0.1/specs/constants/#line-join) (`#/$defs/constants/line-join`)

TAG=agy
CONV=93d2d5dc-3a44-44b6-8aa1-9574ae6f2f12
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Preview Changes

Note

Compared against the baseline rendered from ac202ec0, which is 4 commit(s) behind this PR's base (bb12fd5b) — the newest baseline published when this ran. Any preview those commits changed is attributed to this PR below. Re-run this check once the baseline for bb12fd5b has published to see only this PR's own changes.

Warning

1 preview(s) failed to render in this PR's render run. The diff below covers only the previews that produced a PNG.

Render Failures (1 variant(s) across 1 function(s))

The render task completed but produced no PNG for these previews. Common causes: Robolectric sandbox crash, composePreviewRender NO-SOURCE, or a runtime exception inside the composable. Check the composePreviewRender-reports artifact attached to this run.

  • WearAppPreview (sample) — src/main/java/com/google/android/horologist/ambient/AmbientAwareActivity.kt
    • sample/com.google.android.horologist.ambient.AmbientAwareActivityKt.WearAppPreview_Devices - Large Round · Devices - Large Round
Unchanged (387 function(s), 576 variant(s))
  • AccountChipPreview
  • AccountChipPreviewNoAvatar
  • ActiveDurationTextCustomSeparatorPreview
  • ActiveDurationTextPreview
  • AlertDialogPreview
  • AlertDialogWithIconPreview
  • AlertDialogWithLongBodyPreview
  • AmbientMediaControlButtonsDisabledPreview
  • AmbientMediaControlButtonsPausedPreview
  • AmbientMediaControlButtonsPlayingPreview
  • AmbientMediaInfoDisplayLoadingPreview
  • AmbientMediaInfoDisplayNothingPlayingPreview
  • AmbientMediaInfoDisplayPreview
  • AmbientMessageDisplayPreview
  • AmbientPlayPauseButtonDisabledPreview
  • AmbientPlayPauseButtonPausedPreview
  • AmbientPlayPauseButtonPlayingPreview
  • AmbientPlayerScreenNothingPlayingPreview
  • AmbientPlayerScreenPausedPreview
  • AmbientPlayerScreenPreview
  • AmbientSeekToNextButtonPreview
  • AmbientSeekToPreviousButtonPreview
  • AnimatedMediaControlButtonsBufferingPreview
  • AnimatedMediaControlButtonsDisabledPreview
  • AnimatedMediaControlButtonsPausedPreview
  • AnimatedMediaControlButtonsPlayingPreview
  • AnimatedPlayPauseButtonPreview
  • AnimatedPlayPauseMorphPreview
  • AnimatedPlayPauseProgressButtonLoadingPreview
  • AnimatedPlayPauseProgressButtonMorphPreview
  • AnimatedPlayPauseProgressButtonPausedPreview
  • AnimatedPlayPauseProgressButtonPlayingPreview
  • AnimatedPlayPauseProgressButtonPreview
  • AnimatedSeekToNextButtonPreview
  • AnimatedSeekToNextButtonPreviewDisabled
  • AnimatedSeekToNextButtonPreviewEnabled
  • AnimatedSeekToPreviousButtonPreview
  • AnimatedSetVolumeButtonPreview
  • AnimatedVolumeButtonMotionPreview
  • ArtworkImageBackgroundPreview
  • AudioOutputButtonPreview
  • AuditMenuScreenPreview
  • AuthErrorScreenPreview
  • AuthMenuScreenPreview
  • BrowseScreenPreview
  • BrowseScreenPreviewEmpty
  • BrowseScreenPreviewFailed
  • BrowseScreenPreviewLoading
  • ButtonPreview
  • ButtonPreviewCustomSize
  • ButtonPreviewDisabled
  • ButtonPreviewLarge
  • ButtonPreviewSmall
  • ButtonPreviewWithIconButtonColors
  • ButtonPreviewWithSecondaryButtonColors
  • CardsAuditPreview
  • CheckYourPhoneScreenPreview
  • CheckYourPhoneScreenPreviewWithMessage
  • ChipIconWithProgressInProgressLargeIconPreview
  • ChipIconWithProgressInProgressMediumIconPreview
  • ChipIconWithProgressInProgressPreview
  • ChipIconWithProgressInProgressSmallIconPreview
  • ChipIconWithProgressPreview
  • ChipIconWithProgressWithIconPreview
  • ChipPreview
  • ChipPreviewDisabled
  • ChipPreviewWithGradientBackgroundChipColors
  • ChipPreviewWithIcon
  • ChipPreviewWithImageBackgroundChipColors
  • ChipPreviewWithLargeIcon
  • ChipPreviewWithSecondaryChipColors
  • ChipPreviewWithSecondaryLabel
  • ChipPreviewWithSecondaryLabelAndIcon
  • ChipPreviewWithSecondaryLabelAndLargeIcon
  • ColorBackgroundPreview
  • CompactChipPreview
  • CompactChipPreviewIconOnly
  • CompactChipPreviewWithIcon
  • ConfirmationLongTitlePreview
  • ConfirmationPreview
  • CreateAccountChipPreview
  • CreateAccountChipPreviewLargeIconSpace
  • CurvedTimeTextAuditPreview
  • DatePickerPreview
  • DatePickerPreviewLargeDeviceSmallFont
  • DatePickerPreviewSmallDeviceWithLargeFontBold
  • DefaultPreview
  • DeviceChipPreview
  • EntityButtonPreviewDisabled
  • EntityButtonPreviewEnabled
  • EntityScreenPreview
  • EntityScreenPreviewFailedState
  • EntityScreenPreviewLoaded
  • EntityScreenPreviewLoadedState
  • EntityScreenPreviewLoading
  • EntityScreenPreviewLoadingState
  • FailedResponseChipPreview
  • FillMaxRectanglePreview
  • GoogleSignInPromptSampleScreenPreview
  • GuestModeButtonPreview
  • GuestModeChipPreview
  • IconPreview
  • IconPreviewMirrored
  • InfoScreenPreview
  • InstallAppBottomSheetContentPreview
  • InstallAppBottomSheetContentPreviewNoIcon
  • InstallAppBottomSheetLandscapeContentPreview
  • InstallAppBottomSheetLandscapeContentPreviewNoIcon
  • InstallAppCustomPromptDemoScreenPreview
  • InstallAppCustomPromptDemoScreenPreviewWithPrompt
  • InstallAppPromptDemoScreenPreview
  • InstallTileBottomSheetContentPreview
  • InstallTileBottomSheetContentPreviewNoIcon
  • InstallTileBottomSheetLandscapeContentPreview
  • InstallTileBottomSheetLandscapeContentPreviewNoIcon
  • InstallTileCustomPromptDemoScreenPreview
  • InstallTileCustomPromptDemoScreenPreviewWithPrompt
  • InstallTilePromptDemoScreenPreview
  • LoadingMediaDisplayPreview
  • LottieGeometryAnimatedPreview
  • LottieGeometryPreview
  • LottieM3PlayPauseAnimatedPreview
  • LottieM3PlayPausePreview
  • LottieNextAnimatedPreview
  • LottieNextPreview
  • LottieParentChainPreview
  • LottiePlayPauseAnimatedPreview
  • LottiePlayPausePauseStatePreview
  • LottiePlayPausePreview
  • LottiePositionAnimatedLivePreview
  • LottiePositionAnimatedPreview
  • LottiePositionStaticPreview
  • LottieTintGeometryAnimatedPreview
  • LottieTintGeometryPreview
  • MainPreview
  • MainScreenPreview
  • MarqueeTextConstantScrollingPreview
  • MarqueeTextConstantWithIconScrollingPreview
  • MarqueeTextMediaDisplayPreview
  • MarqueeTextShortTextCenterPreview
  • MarqueeTextShortTextRightPreview
  • MarqueeTextShortTextRtlPreview
  • MarqueeTextStyledPreview
  • MarqueeTextTypicalPreview
  • MediaArtworkPreview
  • MediaButtonPreview
  • MediaChipPreview
  • MediaChipPreviewNoArtwork
  • MediaChipPreviewNoTitle
  • MediaChipPreviewVeryLongTitle
  • MediaCollectionWidgetRectangularPreview
  • MediaCollectionWidgetRoundPreview
  • MediaCollectionWidgetSquirclePreview
  • MediaControlButtonsDisabledPreview
  • MediaControlButtonsPausedPreview
  • MediaControlButtonsPlayingPreview
  • MediaControlButtonsPreview
  • MediaControlButtonsPreviewNoProgress
  • MediaDetailsButtonPreview
  • MediaTitleIconPreview
  • MenuScreenPreview
  • MessageMediaDisplayPreview
  • MetricDisplayPreview
  • MetricDisplayPreviewBottomRightText
  • MetricDisplayPreviewTextOnly
  • MetricDisplayPreviewTopRightText
  • MetricsScreenPreviewFourMetrics
  • MetricsScreenPreviewOneMetric
  • MetricsScreenPreviewThreeMetrics
  • MetricsScreenPreviewTwoMetrics
  • NodeCardPreview
  • NodeDetailsScreenPreview
  • NodesActionDialogPreview
  • NodesActionFailureDialogPreview
  • NodesActionSucceededDialogPreview
  • NodesActionsScreenPreviewApiNotAvailable
  • NodesActionsScreenPreviewEmptyNodes
  • NodesActionsScreenPreviewLoaded
  • NodesListenerScreenPreview
  • NodesListenerScreenPreviewApiNotAvailable
  • NodesListenerScreenPreviewEmptyNodes
  • NodesListenerScreenPreviewLoaded
  • NodesScreenPreview
  • NodesScreenPreviewApiNotAvailable
  • NodesScreenPreviewEmptyNodes
  • NothingPlayingDisplayPreview
  • OtherOptionsChipPreview
  • OutlinedChipPreview
  • OutlinedChipPreviewDisabled
  • OutlinedChipPreviewWithIcon
  • OutlinedChipPreviewWithLargeIcon
  • OutlinedChipPreviewWithSecondaryLabel
  • OutlinedChipPreviewWithSecondaryLabelAndIcon
  • OutlinedChipPreviewWithSecondaryLabelAndLargeIcon
  • OutlinedCompactChipPreview
  • OutlinedCompactChipPreviewIconOnly
  • OutlinedCompactChipPreviewWithIcon
  • PageIndicatorLeft5PlusAuditPreview
  • PageIndicatorRight5PlusAuditPreview
  • PagerScreenPreview
  • PagingItemCardPreviewWithDelayedContent
  • PagingItemCardPreviewWithInitialContent
  • PauseButtonPreview
  • PlaceholderChipPreview
  • PlaceholderChipPreviewWithSecondaryColors
  • PlayButtonPreview
  • PlayPauseButtonPreview
  • PlayPauseProgressButtonLoadingPreview
  • PlayPauseProgressButtonPausedPreview
  • PlayPauseProgressButtonPlayingPreview
  • PlayPauseProgressButtonPreview0
  • PlayPauseProgressButtonPreview100
  • PlayPauseProgressButtonPreview25
  • PlayPauseProgressButtonPreview75
  • PlayPauseProgressButtonPreviewOnWhite
  • PlayerLibraryPagerScreenPreview
  • PlayerScreenCustomBackgroundPreview
  • PlayerScreenLongTextPreview
  • PlayerScreenNothingPlayingPreview
  • PlayerScreenPausedPreview
  • PlayerScreenPreview
  • PlayerScreenPreviewCustomBackground
  • PlayerScreenPreviewCustomMediaDisplay
  • PlayerScreenPreviewDevices
  • PlayerScreenPreviewNotingPlayingDisplay
  • PlayerScreenPreviewUamp
  • PlayerScreenThemePreview
  • PlaylistDownloadBrowseScreenPreview
  • PlaylistDownloadBrowseScreenPreviewLoading
  • PlaylistDownloadBrowseScreenPreviewNoDownloads
  • PlaylistDownloadBrowseScreenPreviewUampTheme
  • PlaylistDownloadScreenPreview
  • PlaylistDownloadScreenPreviewFailed
  • PlaylistDownloadScreenPreviewLoadedFullyDownloaded
  • PlaylistDownloadScreenPreviewLoadedNoneDownloaded
  • PlaylistDownloadScreenPreviewLoadedNoneDownloadedDownloading
  • PlaylistDownloadScreenPreviewLoadedPartiallyDownloaded
  • PlaylistDownloadScreenPreviewLoadedPartiallyDownloadedDownloadingUnknownSize
  • PlaylistDownloadScreenPreviewLoadedPartiallyDownloadedDownloadingWaiting
  • PlaylistDownloadScreenPreviewLoading
  • PlaylistStreamingScreenPreview
  • PlaylistsScreenLongPreview
  • PlaylistsScreenPreview
  • PlaylistsScreenPreviewCustomLayout
  • PlaylistsScreenPreviewFailed
  • PlaylistsScreenPreviewLoaded
  • PlaylistsScreenPreviewLoading
  • PodcastControlButtonsPausedPreview
  • PodcastControlButtonsPlayingPreview
  • PodcastControlButtonsPreview
  • PodcastControlButtonsPreviewNoProgress
  • PodcastControlButtonsPreviewUnknown
  • PodcastControlDisabledLightBackground
  • Preview
  • PreviewHighCornerRadius
  • PreviewProgressAnimation
  • PreviewSquare
  • PreviewSquareWithBrushAndColorsCombined
  • PreviewSquareWithBrushColors
  • PromptScreenErrorPreview
  • PromptScreenMultiTurnPreview
  • PromptScreenStreamingPreview
  • PromptScreenSuccessPreview
  • RadialBackgroundPreview
  • ReEngageBottomSheetContentPreview
  • ReEngageBottomSheetContentPreviewNoIcon
  • ReEngageBottomSheetLandscapeContentPreview
  • ReEngageBottomSheetLandscapeContentPreviewNoIcon
  • ReEngageCustomPromptDemoScreenPreview
  • ReEngagePromptDemoScreenPreview
  • ResponseInProgressCardPreview
  • SamplePromptScreenPreviewEmpty
  • SamplePromptScreenPreviewMany
  • SamplePromptScreenPreviewMarkdown
  • SamplePromptScreenPreviewQuestion
  • SampleTilePreview
  • ScratchPreview
  • ScrollAwayScreenPreview
  • SecondaryTitlePreview
  • SecondaryTitlePreviewWithIcon
  • SecondaryTitlePreviewWithIconAndLongText
  • SecondaryTitlePreviewWithLongText
  • SectionedListExpandableScreenPreview
  • SectionedListPreviewEmptySection
  • SectionedListPreviewFailedSection
  • SectionedListPreviewLoadedSection
  • SectionedListPreviewLoadingSection
  • SectionedListStatefulScreenPreview
  • SectionedListStatelessScreenPreview
  • SeekButtonsGalleryPreview
  • SeekButtonsPreview
  • SeekToNextButtonPreview
  • SeekToPreviousButtonPreview
  • SegmentedProgressIndicatorBrushColorCombinedPreview
  • SegmentedProgressIndicatorBrushPreview
  • SegmentedProgressIndicatorRoundPreview
  • SegmentedProgressIndicatorSquarePreview
  • SelectAccountScreenManyAccountsPreview
  • SelectAccountScreenOneLineAccountsPreview
  • SelectAccountScreenPreview
  • SelectAccountScreenPreviewNoAvatar
  • SetAudioOutputButtonPreview
  • SetAudioOutputButtonPreviewMaxVolume
  • SetAudioOutputButtonPreviewMinVolume
  • SetAudioOutputButtonPreviewNoOutput
  • SetVolumeButtonPreview
  • SetVolumeButtonPreviewMaxVolume
  • SetVolumeButtonPreviewMinVolume
  • SettingsButtonsDisabledPreview
  • SettingsButtonsPreview
  • SettingsButtonsWithBrandIconPreview
  • SettingsScreenPreview
  • ShowPlaylistButtonPreview
  • ShowPlaylistChipPreview
  • ShowPlaylistChipPreviewNoArtwork
  • ShowPlaylistChipPreviewNoName
  • ShowPlaylistChipPreviewVeryLongName
  • ShuffleToggleButtonPreview
  • SignInBottomSheetContentPreview
  • SignInBottomSheetContentPreviewNoIcon
  • SignInBottomSheetLandscapeContentPreview
  • SignInBottomSheetLandscapeContentPreviewNoIcon
  • SignInButtonPreview
  • SignInChipPreview
  • SignInCustomPromptDemoScreenPreview
  • SignInCustomPromptDemoScreenPreviewWithPrompt
  • SignInPlaceholderScreenPreview
  • SignInPromptDemoScreenPreview
  • SignInPromptScreenPreviewCustomLoading
  • SignInPromptScreenPreviewLoading
  • SignInPromptScreenPreviewSignedOut
  • SignedInConfirmationDialogMinimalPreview
  • SignedInConfirmationDialogPreview
  • SignedInConfirmationDialogTruncationPreview
  • SplitToggleChipCheckboxPreview
  • SplitToggleChipPreviewDisabled
  • SplitToggleChipRadioPreview
  • SplitToggleChipSwitchPreview
  • SplitToggleChipUncheckedAndDisabledPreview
  • SplitToggleChipUncheckedPreview
  • SplitToggleChipWithSecondaryLabel
  • Standard
  • StepperFloatPreview
  • StepperPreview
  • TextMediaDisplayLongTextPreview
  • TextMediaDisplayPreview
  • TextMediaDisplayPreviewLongText
  • TextPromptDisplayPreview
  • TextResponseCardPreview
  • TimePicker12hPreview
  • TimePicker12hPreviewLargeDeviceSmallFont
  • TimePicker12hPreviewSmallDeviceWithLargeFontBold
  • TimePickerPreview
  • TimePickerPreviewLargeDeviceSmallFont
  • TimePickerPreviewSmallDeviceWithLargeFontBold
  • TitlePreview
  • TitlePreviewWithLongText
  • ToggleButtonPreview
  • ToggleButtonPreviewDisabled
  • ToggleButtonPreviewIconOnly
  • ToggleButtonPreviewIconOnlyNotChecked
  • ToggleButtonPreviewNotChecked
  • ToggleButtonPreviewNotCheckedDisabled
  • ToggleButtonPreviewSmall
  • ToggleButtonPreviewSmallNotChecked
  • ToggleButtonPreviewText
  • ToggleButtonPreviewTextNotChecked
  • ToggleChipCheckboxPreview
  • ToggleChipPreviewDisabled
  • ToggleChipPreviewWithIcon
  • ToggleChipPreviewWithSecondaryLabelAndIcon
  • ToggleChipRadioPreview
  • ToggleChipSwitchPreview
  • ToggleChipUncheckedAndDisabledPreview
  • ToggleChipUncheckedPreview
  • ToggleChipWithSecondaryLabel
  • TrackMediaDisplayPreview
  • TrackMediaDisplayPreviewLongText
  • TrackingScreenPreview
  • VerticalPagerIndicatorPreview
  • VolumeScreenLocalePreview
  • VolumeScreenLongLabelPreview
  • VolumeScreenPreview
  • VolumeScreenTheme
  • VolumeScreenWithLabel
  • WearAppPreview
  • WearableOssLicensesActivity

* Serializer for [GradientType] supporting integer and float primitives with fallback to
* [GradientType.Linear].
*/
internal object GradientTypeSerializer : KSerializer<GradientType> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether there is value in having a EnumTypeSerializer base class?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is an excellent idea! I will explore it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be deferred, not essential

ShapeType.Rectangle.value -> Rectangle.serializer()
ShapeType.Ellipse.value -> Ellipse.serializer()
ShapeType.PolyStar.value -> PolyStar.serializer()
else -> Group.serializer()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it this a safe default or does it have required fields? Should be Unknown Shape?

https://lottie.github.io/lottie-spec/latest/specs/schema/#/$defs/shapes/unknown-shape

* child shapes array.
*
* Schema Specification:
* - Required Fields:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like a gap in the schema: these attributes are not required, but no default values are present either. lottie-android player uses default values.

But here I would like to start a discussion: if we decide to go with using default values, should we add them here (in this class), or do the check during rendering. Where should we put this "default" logic?

From the rigorous perspective, I lean towards working with the null values during the renderer. On the other hand, having them here in AST simplifies the logic.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we agreed on defaults of 0


val cornerRadius = animateScalar(rect.cornerRadius, animationSettings).constantValueOrNull ?: 0f
val cornerRadius =
rect.cornerRadius?.let { animateScalar(it, animationSettings).constantValueOrNull } ?: 0f

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have TODOs for the constantValueOrNull calls throughout?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is in the renderer/ folder, and the next PRs will be refactoring that. I wanted to make the minimal changes to the classes in the renderer/ folder, and that is the reason for this approach.

@SerialName("hd") override val hidden: SerializableBoolean? = null,
@SerialName("ty") override val type: ShapeType = ShapeType.Group,
@SerialName("np") val numberOfProperties: Int? = null,
@SerialName("np") val numberOfProperties: SerializableRemoteFloat? = null,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this one of the index/length cases taht ew should discussed, does not need to be Remote?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Is it a good idea to have the post-hoc approach to keep as much values of Remote type as possible, and if later (during working on the renderer part) we see that we anyway have to work with the regular, non-Remote types -- we can change it back?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put a TODO then?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants