Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for layer blend mode "bm" for NORMAL, SCREEN, OVERLAY, DARKEN, LIGHTEN, and ADD #2408

Merged
merged 19 commits into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8b5c429
feat: Add support for basic blend modes on Q and up
kudanai Oct 30, 2023
a8b7062
fix: default to NORMAL for invalid blend modes
kudanai Oct 30, 2023
e7b1257
feat: use PaintCompat and BlendModeCompat instead for better compatib…
kudanai Oct 30, 2023
0871413
Update lottie/src/main/java/com/airbnb/lottie/animation/content/FillC…
kudanai Oct 30, 2023
a804ac6
Update lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
kudanai Oct 30, 2023
eac4986
Update lottie/src/main/java/com/airbnb/lottie/model/content/LBlendMod…
kudanai Oct 30, 2023
0bdad7b
fix: refactor method `toNativeBlendMode`
kudanai Oct 30, 2023
e284d20
tests: add individual blend-mode test files
kudanai Oct 30, 2023
6ae0498
feat: separate blendModes that have backwards support
kudanai Nov 7, 2023
cabfeff
feat: separate blendModes that have backwards support
kudanai Nov 7, 2023
9abec0d
Merge remote-tracking branch 'origin/layer-blend' into layer-blend
kudanai Nov 7, 2023
8bc5e98
chore: lint
kudanai Nov 7, 2023
c3a570c
Update lottie/src/main/java/com/airbnb/lottie/animation/content/FillC…
kudanai Nov 15, 2023
e4b9a8f
Merge branch 'master' into layer-blend
kudanai Nov 16, 2023
cf97401
chore: code clean up and minor performance tweak
kudanai Nov 16, 2023
ffa60f3
chore: cleanup imports
kudanai Nov 16, 2023
17f9223
chore: cleanup imports
kudanai Nov 16, 2023
66e3cc5
Merge remote-tracking branch 'origin/layer-blend' into layer-blend
kudanai Nov 16, 2023
1cc5c1b
fix: re-add guard for potential invalid index on blend-mode
kudanai Nov 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.airbnb.lottie.animation.content;

import static com.airbnb.lottie.utils.MiscUtils.clamp;

import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;

import android.os.Build;
import androidx.annotation.Nullable;

import androidx.core.graphics.BlendModeCompat;
import androidx.core.graphics.PaintCompat;
import com.airbnb.lottie.L;
import com.airbnb.lottie.LottieDrawable;
import com.airbnb.lottie.LottieProperty;
Expand All @@ -29,6 +28,8 @@
import java.util.ArrayList;
import java.util.List;

import static com.airbnb.lottie.utils.MiscUtils.clamp;

public class FillContent
implements DrawingContent, BaseKeyframeAnimation.AnimationListener, KeyPathElementContent {
private final Path path = new Path();
Expand Down Expand Up @@ -120,6 +121,12 @@ public FillContent(final LottieDrawable lottieDrawable, BaseLayer layer, ShapeFi
dropShadowAnimation.applyTo(paint);
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
final BlendModeCompat blendMode = layer.getBlendMode().toNativeBlendMode();
if (blendMode != null)
PaintCompat.setBlendMode(paint, blendMode);
kudanai marked this conversation as resolved.
Show resolved Hide resolved
}

path.reset();
for (int i = 0; i < paths.size(); i++) {
path.addPath(paths.get(i).getPath(), parentMatrix);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.airbnb.lottie.model.content;

import android.os.Build;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.graphics.BlendModeCompat;

/**
* Lottie BlendMode,
* not to be confused with Paint.BlendMode in android graphics core,
* which we will rely on for rendering.
*/
public enum LBlendMode {
NORMAL,
MULTIPLY,
SCREEN,
OVERLAY,
DARKEN,
LIGHTEN,
COLOR_DODGE,
COLOR_BURN,
HARD_LIGHT,
SOFT_LIGHT,
DIFFERENCE,
EXCLUSION,
HUE,
SATURATION,
COLOR,
LUMINOSITY,
ADD,
HARD_MIX;

@Nullable
@RequiresApi(api = Build.VERSION_CODES.Q)
public BlendModeCompat toNativeBlendMode() {
switch (this){
case NORMAL:
return null; // BlendMode.CLEAR?
kudanai marked this conversation as resolved.
Show resolved Hide resolved
case MULTIPLY:
return BlendModeCompat.MULTIPLY;
case SCREEN:
return BlendModeCompat.SCREEN;
case OVERLAY:
return BlendModeCompat.OVERLAY;
case DARKEN:
return BlendModeCompat.DARKEN;
case LIGHTEN:
return BlendModeCompat.LIGHTEN;
case COLOR_DODGE:
return BlendModeCompat.COLOR_DODGE;
case COLOR_BURN:
return BlendModeCompat.COLOR_BURN;
case HARD_LIGHT:
return BlendModeCompat.HARD_LIGHT;
case SOFT_LIGHT:
return BlendModeCompat.SOFT_LIGHT;
case DIFFERENCE:
return BlendModeCompat.DIFFERENCE;
case EXCLUSION:
return BlendModeCompat.EXCLUSION;
case HUE:
return BlendModeCompat.HUE;
case SATURATION:
return BlendModeCompat.SATURATION;
case COLOR:
return BlendModeCompat.COLOR;
case LUMINOSITY:
return BlendModeCompat.LUMINOSITY;
case ADD:
return BlendModeCompat.PLUS;
case HARD_MIX:
return null; // todo: fix this
kudanai marked this conversation as resolved.
Show resolved Hide resolved
default:
return null;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.airbnb.lottie.model.KeyPath;
import com.airbnb.lottie.model.KeyPathElement;
import com.airbnb.lottie.model.content.BlurEffect;
import com.airbnb.lottie.model.content.LBlendMode;
import com.airbnb.lottie.model.content.Mask;
import com.airbnb.lottie.model.content.ShapeData;
import com.airbnb.lottie.parser.DropShadowEffect;
Expand Down Expand Up @@ -628,6 +629,10 @@ public BlurEffect getBlurEffect() {
return layerModel.getBlurEffect();
}

public LBlendMode getBlendMode() {
return layerModel.getBlendMode();
}

public BlurMaskFilter getBlurMaskFilter(float radius) {
if (blurMaskFilterRadius == radius) {
return blurMaskFilter;
Expand Down
12 changes: 10 additions & 2 deletions lottie/src/main/java/com/airbnb/lottie/model/layer/Layer.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.airbnb.lottie.model.layer;

import androidx.annotation.Nullable;

import com.airbnb.lottie.LottieComposition;
import com.airbnb.lottie.model.animatable.AnimatableFloatValue;
import com.airbnb.lottie.model.animatable.AnimatableTextFrame;
import com.airbnb.lottie.model.animatable.AnimatableTextProperties;
import com.airbnb.lottie.model.animatable.AnimatableTransform;
import com.airbnb.lottie.model.content.BlurEffect;
import com.airbnb.lottie.model.content.ContentModel;
import com.airbnb.lottie.model.content.LBlendMode;
import com.airbnb.lottie.model.content.Mask;
import com.airbnb.lottie.parser.DropShadowEffect;
import com.airbnb.lottie.value.Keyframe;
Expand Down Expand Up @@ -61,6 +61,8 @@ public enum MatteType {
private final boolean hidden;
@Nullable private final BlurEffect blurEffect;
@Nullable private final DropShadowEffect dropShadowEffect;
private final LBlendMode blendMode;


public Layer(List<ContentModel> shapes, LottieComposition composition, String layerName, long layerId,
LayerType layerType, long parentId, @Nullable String refId, List<Mask> masks,
Expand All @@ -69,7 +71,7 @@ public Layer(List<ContentModel> shapes, LottieComposition composition, String la
@Nullable AnimatableTextFrame text, @Nullable AnimatableTextProperties textProperties,
List<Keyframe<Float>> inOutKeyframes, MatteType matteType,
@Nullable AnimatableFloatValue timeRemapping, boolean hidden, @Nullable BlurEffect blurEffect,
@Nullable DropShadowEffect dropShadowEffect) {
@Nullable DropShadowEffect dropShadowEffect, LBlendMode blendMode) {
this.shapes = shapes;
this.composition = composition;
this.layerName = layerName;
Expand All @@ -94,6 +96,7 @@ public Layer(List<ContentModel> shapes, LottieComposition composition, String la
this.hidden = hidden;
this.blurEffect = blurEffect;
this.dropShadowEffect = dropShadowEffect;
this.blendMode = blendMode;
}

LottieComposition getComposition() {
Expand Down Expand Up @@ -188,6 +191,11 @@ public boolean isHidden() {
return hidden;
}

@Nullable
public LBlendMode getBlendMode() {
return blendMode;
}

@Nullable public BlurEffect getBlurEffect() {
return blurEffect;
}
Expand Down
19 changes: 16 additions & 3 deletions lottie/src/main/java/com/airbnb/lottie/parser/LayerParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.airbnb.lottie.model.animatable.AnimatableTextFrame;
import com.airbnb.lottie.model.animatable.AnimatableTextProperties;
import com.airbnb.lottie.model.animatable.AnimatableTransform;
import com.airbnb.lottie.model.content.LBlendMode;
import com.airbnb.lottie.model.content.BlurEffect;
import com.airbnb.lottie.model.content.ContentModel;
import com.airbnb.lottie.model.content.Mask;
Expand Down Expand Up @@ -49,7 +50,8 @@ private LayerParser() {
"op", // 19
"tm", // 20
"cl", // 21
"hd" // 22
"hd", // 22
"bm" // 23
);

public static Layer parse(LottieComposition composition) {
Expand All @@ -59,7 +61,8 @@ public static Layer parse(LottieComposition composition) {
Layer.LayerType.PRE_COMP, -1, null, Collections.<Mask>emptyList(),
new AnimatableTransform(), 0, 0, 0, 0, 0,
bounds.width(), bounds.height(), null, null, Collections.<Keyframe<Float>>emptyList(),
Layer.MatteType.NONE, null, false, null, null);
Layer.MatteType.NONE, null, false, null, null,
LBlendMode.NORMAL);
}

private static final JsonReader.Options TEXT_NAMES = JsonReader.Options.of(
Expand Down Expand Up @@ -95,6 +98,7 @@ public static Layer parse(JsonReader reader, LottieComposition composition) thro
DropShadowEffect dropShadowEffect = null;

Layer.MatteType matteType = Layer.MatteType.NONE;
LBlendMode blendMode = LBlendMode.NORMAL;
AnimatableTransform transform = null;
AnimatableTextFrame text = null;
AnimatableTextProperties textProperties = null;
Expand Down Expand Up @@ -256,6 +260,15 @@ public static Layer parse(JsonReader reader, LottieComposition composition) thro
case 22:
hidden = reader.nextBoolean();
break;
case 23:
int blendModeIndex = reader.nextInt();
if (blendModeIndex >= LBlendMode.values().length) {
composition.addWarning("Unsupported Blend Mode: " + blendModeIndex);
blendMode = LBlendMode.NORMAL;
break;
}
blendMode = LBlendMode.values()[blendModeIndex];
break;
default:
reader.skipName();
reader.skipValue();
Expand Down Expand Up @@ -287,6 +300,6 @@ public static Layer parse(JsonReader reader, LottieComposition composition) thro
return new Layer(shapes, composition, layerName, layerId, layerType, parentId, refId,
masks, transform, solidWidth, solidHeight, solidColor, timeStretch, startFrame,
preCompWidth, preCompHeight, text, textProperties, inOutKeyframes, matteType,
timeRemapping, hidden, blurEffect, dropShadowEffect);
timeRemapping, hidden, blurEffect, dropShadowEffect, blendMode);
}
}
1 change: 1 addition & 0 deletions snapshot-tests/src/main/assets/Tests/LayerBlend_0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":"5.7.1","ip":0,"op":180,"nm":"Animation","mn":"{429ff333-f31c-4124-91c5-5e861412a004}","fr":60,"w":512,"h":512,"assets":[],"layers":[{"ddd":0,"ty":4,"ind":1,"st":0,"ip":0,"op":180,"nm":"Layer","mn":"{625eab7e-4758-4d4b-b37c-d89115b1442b}","ks":{"a":{"a":0,"k":[256,256]},"p":{"a":0,"k":[256,256]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":77}},"shapes":[{"ty":"gr","nm":"Ellipse","mn":"{dd57d763-ff3b-420f-a94d-eb5503e7faa7}","it":[{"ty":"el","nm":"Ellipse","mn":"{fa5c495c-00d1-4253-b30c-cc8cb1b855b2}","p":{"a":0,"k":[400.1910447761194,240.71641791044777]},"s":{"a":0,"k":[195.15223880597017,180.53731343283584]}},{"ty":"st","hd":true,"nm":"Stroke","mn":"{89437b5f-dca9-42d4-aff9-c57ce08c8c1e}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"lc":2,"lj":2,"ml":0,"w":{"a":0,"k":30}},{"ty":"fl","nm":"Fill","mn":"{352559ca-ebe9-4b11-acdd-09e155612598}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.3411764705882353,0.01568627450980392]},"r":1},{"ty":"tr","a":{"a":0,"k":[400.1910447761194,240.71641791044777]},"p":{"a":0,"k":[400.1910447761194,240.71641791044777]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","nm":"PolyStar","mn":"{b6000853-a4d3-4b13-acdd-2e4f1a192760}","it":[{"ty":"sr","nm":"PolyStar","mn":"{d647a149-8105-4e08-b395-c8de40669fb0}","p":{"a":0,"k":[110.90149253731343,216.644776119403]},"or":{"a":0,"k":121.5619125366211},"ir":{"a":0,"k":60.78095626831055},"r":{"a":0,"k":143.04905700683594},"pt":{"a":0,"k":5},"sy":1,"os":{"a":0,"k":0},"is":{"a":0,"k":0}},{"ty":"st","hd":true,"nm":"Stroke","mn":"{67a87e2b-afff-4f55-9004-4cc274cefe07}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"lc":2,"lj":2,"ml":0,"w":{"a":0,"k":30}},{"ty":"fl","nm":"Fill","mn":"{39b8d13c-45cf-4ad7-972a-ef5169f1ffbf}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"r":1},{"ty":"tr","a":{"a":0,"k":[110.90149253731343,216.644776119403]},"p":{"a":0,"k":[159.9044776119403,247.59402985074627]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"bm":0},{"ddd":0,"ty":4,"ind":0,"st":0,"ip":0,"op":180,"nm":"Layer 1","mn":"{d74c9dcc-e7af-45c3-9eab-554c7b93f6b6}","ks":{"a":{"a":0,"k":[256,256]},"p":{"a":0,"k":[256,256]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","nm":"Rectangle 1","mn":"{b22ddad1-738b-471a-86eb-1f072fa45799}","it":[{"ty":"rc","nm":"Rectangle 1","mn":"{0c09bd21-59ab-4f1e-bd3d-547613eb3e2a}","p":{"a":0,"k":[241.57611940298506,357.6358208955224]},"s":{"a":0,"k":[383.4268656716418,211.4865671641791]},"r":{"a":0,"k":0}},{"ty":"st","hd":true,"nm":"Stroke","mn":"{8cd4fca9-3480-49fa-947f-04bc40ed74f5}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"lc":2,"lj":2,"ml":0,"w":{"a":0,"k":30}},{"ty":"fl","nm":"Fill","mn":"{050089d8-44c4-4312-8e23-3c89df7615aa}","o":{"a":0,"k":100},"c":{"a":0,"k":[0.7686274509803922,0.8509803921568627,0.9607843137254902]},"r":1},{"ty":"tr","a":{"a":0,"k":[241.57611940298506,357.6358208955224]},"p":{"a":0,"k":[226.1014925373134,131.53432835820894]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","nm":"Rectangle","mn":"{700bfca8-0e45-42e9-8559-15ac0ebe93b2}","it":[{"ty":"rc","nm":"Rectangle","mn":"{0e3ac2ac-22c8-4310-8208-f5d5ba9cd6d9}","p":{"a":0,"k":[277.68358208955226,148.2985074626866]},"s":{"a":0,"k":[335.2835820895522,162.48358208955224]},"r":{"a":0,"k":0}},{"ty":"st","hd":true,"nm":"Stroke","mn":"{af0c691f-7815-414e-a988-ac2eb6e32128}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"lc":2,"lj":2,"ml":0,"w":{"a":0,"k":30}},{"ty":"fl","nm":"Fill","mn":"{059d8c4e-de02-4fa7-99fe-c069b73218be}","o":{"a":0,"k":100},"c":{"a":0,"k":[0.19607843137254902,0.3137254901960784,0.6901960784313725]},"r":1},{"ty":"tr","a":{"a":0,"k":[277.68358208955226,148.2985074626866]},"p":{"a":0,"k":[277.68358208955226,366.6626865671642]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}]}],"meta":{"g":"Glaxnimate 0.4.6-32-gb62899be"}}
1 change: 1 addition & 0 deletions snapshot-tests/src/main/assets/Tests/LayerBlend_1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":"5.7.1","ip":0,"op":180,"nm":"Animation","mn":"{429ff333-f31c-4124-91c5-5e861412a004}","fr":60,"w":512,"h":512,"assets":[],"layers":[{"ddd":0,"ty":4,"ind":1,"st":0,"ip":0,"op":180,"nm":"Layer","mn":"{625eab7e-4758-4d4b-b37c-d89115b1442b}","ks":{"a":{"a":0,"k":[256,256]},"p":{"a":0,"k":[256,256]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":77}},"shapes":[{"ty":"gr","nm":"Ellipse","mn":"{dd57d763-ff3b-420f-a94d-eb5503e7faa7}","it":[{"ty":"el","nm":"Ellipse","mn":"{fa5c495c-00d1-4253-b30c-cc8cb1b855b2}","p":{"a":0,"k":[400.1910447761194,240.71641791044777]},"s":{"a":0,"k":[195.15223880597017,180.53731343283584]}},{"ty":"st","hd":true,"nm":"Stroke","mn":"{89437b5f-dca9-42d4-aff9-c57ce08c8c1e}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"lc":2,"lj":2,"ml":0,"w":{"a":0,"k":30}},{"ty":"fl","nm":"Fill","mn":"{352559ca-ebe9-4b11-acdd-09e155612598}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.3411764705882353,0.01568627450980392]},"r":1},{"ty":"tr","a":{"a":0,"k":[400.1910447761194,240.71641791044777]},"p":{"a":0,"k":[400.1910447761194,240.71641791044777]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","nm":"PolyStar","mn":"{b6000853-a4d3-4b13-acdd-2e4f1a192760}","it":[{"ty":"sr","nm":"PolyStar","mn":"{d647a149-8105-4e08-b395-c8de40669fb0}","p":{"a":0,"k":[110.90149253731343,216.644776119403]},"or":{"a":0,"k":121.5619125366211},"ir":{"a":0,"k":60.78095626831055},"r":{"a":0,"k":143.04905700683594},"pt":{"a":0,"k":5},"sy":1,"os":{"a":0,"k":0},"is":{"a":0,"k":0}},{"ty":"st","hd":true,"nm":"Stroke","mn":"{67a87e2b-afff-4f55-9004-4cc274cefe07}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"lc":2,"lj":2,"ml":0,"w":{"a":0,"k":30}},{"ty":"fl","nm":"Fill","mn":"{39b8d13c-45cf-4ad7-972a-ef5169f1ffbf}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"r":1},{"ty":"tr","a":{"a":0,"k":[110.90149253731343,216.644776119403]},"p":{"a":0,"k":[159.9044776119403,247.59402985074627]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"bm":1},{"ddd":0,"ty":4,"ind":0,"st":0,"ip":0,"op":180,"nm":"Layer 1","mn":"{d74c9dcc-e7af-45c3-9eab-554c7b93f6b6}","ks":{"a":{"a":0,"k":[256,256]},"p":{"a":0,"k":[256,256]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}},"shapes":[{"ty":"gr","nm":"Rectangle 1","mn":"{b22ddad1-738b-471a-86eb-1f072fa45799}","it":[{"ty":"rc","nm":"Rectangle 1","mn":"{0c09bd21-59ab-4f1e-bd3d-547613eb3e2a}","p":{"a":0,"k":[241.57611940298506,357.6358208955224]},"s":{"a":0,"k":[383.4268656716418,211.4865671641791]},"r":{"a":0,"k":0}},{"ty":"st","hd":true,"nm":"Stroke","mn":"{8cd4fca9-3480-49fa-947f-04bc40ed74f5}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"lc":2,"lj":2,"ml":0,"w":{"a":0,"k":30}},{"ty":"fl","nm":"Fill","mn":"{050089d8-44c4-4312-8e23-3c89df7615aa}","o":{"a":0,"k":100},"c":{"a":0,"k":[0.7686274509803922,0.8509803921568627,0.9607843137254902]},"r":1},{"ty":"tr","a":{"a":0,"k":[241.57611940298506,357.6358208955224]},"p":{"a":0,"k":[226.1014925373134,131.53432835820894]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","nm":"Rectangle","mn":"{700bfca8-0e45-42e9-8559-15ac0ebe93b2}","it":[{"ty":"rc","nm":"Rectangle","mn":"{0e3ac2ac-22c8-4310-8208-f5d5ba9cd6d9}","p":{"a":0,"k":[277.68358208955226,148.2985074626866]},"s":{"a":0,"k":[335.2835820895522,162.48358208955224]},"r":{"a":0,"k":0}},{"ty":"st","hd":true,"nm":"Stroke","mn":"{af0c691f-7815-414e-a988-ac2eb6e32128}","o":{"a":0,"k":100},"c":{"a":0,"k":[1,0.9803921568627451,0.2823529411764706]},"lc":2,"lj":2,"ml":0,"w":{"a":0,"k":30}},{"ty":"fl","nm":"Fill","mn":"{059d8c4e-de02-4fa7-99fe-c069b73218be}","o":{"a":0,"k":100},"c":{"a":0,"k":[0.19607843137254902,0.3137254901960784,0.6901960784313725]},"r":1},{"ty":"tr","a":{"a":0,"k":[277.68358208955226,148.2985074626866]},"p":{"a":0,"k":[277.68358208955226,366.6626865671642]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100}}]}]}],"meta":{"g":"Glaxnimate 0.4.6-32-gb62899be"}}