diff --git a/pages.json b/pages.json index e2bf077b47fdc009f69c0f3c14a0828b7948a850..02c97bf7693333d391aa1c36df40543265021fb8 100644 --- a/pages.json +++ b/pages.json @@ -477,17 +477,6 @@ "navigationBarTitleText": "涂鸦" } }, - // #ifndef WEB - { - "path": "pages/component/animation-view/animation-view", - "group": "0,5,2", - "style": { - "navigationBarTitleText": "animation-view | Lottie动画", - "enablePullDownRefresh": false - } - }, - // #endif - { "path": "pages/tabBar/API", "style": { @@ -2009,10 +1998,6 @@ { "id": "component.media.video", "name": "video" - }, - { - "id": "component.media.animation-view", - "name": "animation-view" } ] }, diff --git a/pages/component/animation-view/animation-view.uvue b/pages/component/animation-view/animation-view.uvue deleted file mode 100644 index 5750b727f261ab245760f68b56950ce764f3f93a..0000000000000000000000000000000000000000 --- a/pages/component/animation-view/animation-view.uvue +++ /dev/null @@ -1,91 +0,0 @@ - - - diff --git a/uni_modules/uni-animation-view/changelog.md b/uni_modules/uni-animation-view/changelog.md deleted file mode 100644 index c11e4d58cf33014bb777120c9b9409c0e92284bf..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/changelog.md +++ /dev/null @@ -1,12 +0,0 @@ -## 1.0.5(2024-06-14) -调整iOS平台组件内的默认样式 -## 1.0.4(2024-05-24) -+ 修复 Android uni-app x 正式包模式下,可能不展示动画的Bug -## 1.0.3(2024-04-11) -修复Android平台 修正组件名称为 `animation-view` -## 1.0.2(2024-03-22) -修复Android平台云打包编译失败的Bug -## 1.0.1(2023-04-07) -修复ios平台本地编译会报 swift 版本不兼容的bug -## 1.0.0(2023-01-16) -实现android/ios平台animation-view组件,仅支持nvue页面 diff --git a/uni_modules/uni-animation-view/package.json b/uni_modules/uni-animation-view/package.json deleted file mode 100644 index 86bd992b45e5825a59dd13ea7827c808372c7846..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/package.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "id": "uni-animation-view", - "displayName": "animation-view", - "version": "1.0.5", - "description": "使用uts组件开发,实现animation-view组件", - "keywords": [ - "animation-view", - "lottie" - ], - "repository": "", - "engines": { - "HBuilderX": "^3.7.0" - }, - "dcloudext": { - "type": "component-uts", - "sale": { - "regular": { - "price": "0.00" - }, - "sourcecode": { - "price": "0.00" - } - }, - "contact": { - "qq": "" - }, - "declaration": { - "ads": "无", - "data": "插件不采集任何数据", - "permissions": "无" - }, - "npmurl": "" - }, - "uni_modules": { - "dependencies": [], - "encrypt": [], - "platforms": { - "cloud": { - "tcb": "y", - "aliyun": "y", - "alipay": "n" - }, - "client": { - "Vue": { - "vue2": "y", - "vue3": "y" - }, - "App": { - "app-android": { - "minVersion": "21" - }, - "app-ios": { - "minVersion": "11" - } - }, - "H5-mobile": { - "Safari": "u", - "Android Browser": "u", - "微信浏览器(Android)": "u", - "QQ浏览器(Android)": "u" - }, - "H5-pc": { - "Chrome": "u", - "IE": "u", - "Edge": "u", - "Firefox": "u", - "Safari": "u" - }, - "小程序": { - "微信": "u", - "阿里": "u", - "百度": "u", - "字节跳动": "u", - "QQ": "u", - "钉钉": "u", - "快手": "u", - "飞书": "u", - "京东": "u" - }, - "快应用": { - "华为": "u", - "联盟": "u" - } - } - } - } -} diff --git a/uni_modules/uni-animation-view/readme.md b/uni_modules/uni-animation-view/readme.md deleted file mode 100644 index 118c91fad572d9a600adcaf799f1c6e4581acce0..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/readme.md +++ /dev/null @@ -1,79 +0,0 @@ -# animation-view - -> animation-view组件是[uts插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html),需 HBuilderX 3.7.0+ - -> 使用文档:[https://uniapp.dcloud.net.cn/component/animation-view.html](https://uniapp.dcloud.net.cn/component/animation-view.html) - - -### 属性说明 - -|属性名|类型|默认值|说明| -|:-|:-|:-|:-| -| path | String | | 动画资源地址,支持本地路径和网络路径 | -| loop | Boolean | false | 动画是否循环播放 | -| autoplay | Boolean | true | 动画是否自动播放 | -| action | String | play | 动画操作,可取值 play、pause、stop | -| hidden | Boolean | true | 是否隐藏动画 | -| @bindended | EventHandle | | 当播放到末尾时触发 ended 事件(自然播放结束会触发回调,循环播放结束及手动停止动画不会触发) | - - -**注意** -* animation-view 仅App端nvue页面支持 -* App端实现使用了Lottie三方SDK,参考开源项目:[Lottie for Android](https://github.com/airbnb/lottie-android),[Lottie for iOS](https://github.com/airbnb/lottie-ios) -* App-Android平台要求Android5(API Leavel 21)及以上系统 -* App-iOS平台要求iOS11及以上版本系统 - - -### 代码示例 - -```html - - - - - -``` - - - - - - diff --git a/uni_modules/uni-animation-view/static/lottie.json b/uni_modules/uni-animation-view/static/lottie.json deleted file mode 100644 index b85c38bcb3bb5bd243e06f5b56258e0181827485..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/static/lottie.json +++ /dev/null @@ -1 +0,0 @@ -{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.1.1","a":"","k":"","d":"","tc":""},"fr":24,"ip":0,"op":48,"w":408,"h":522,"nm":"dons_2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Layer 4 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[181.326,214.081,0],"ix":2},"a":{"a":0,"k":[28.299,22.945,0],"ix":1},"s":{"a":0,"k":[100,108.675,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-13.354,-5.413],[3.868,-9.545],[13.355,5.413],[-3.869,9.544]],"o":[[13.354,5.413],[-3.869,9.544],[-13.354,-5.413],[3.868,-9.545]],"v":[[7.005,-17.282],[24.181,9.801],[-7.005,17.282],[-24.18,-9.801]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.992156922583,0.976470648074,0.952941236309,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[28.299,22.945],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"bras","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[-0.462]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":9,"s":[-10.65]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[-10.65]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":24,"s":[34]},{"i":{"x":[0.09],"y":[1]},"o":{"x":[1],"y":[0]},"t":26,"s":[22]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":29,"s":[34]},{"t":36,"s":[-0.462]}],"ix":10},"p":{"a":0,"k":[133.32,104.53,0],"ix":2},"a":{"a":0,"k":[38.938,195.403,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[16.66,-7.812],[-2.153,-3.453],[-7.785,-1.342],[4.514,-6.255],[9.957,2.763],[-0.468,-1.814],[12.203,-10.355],[2.666,8.892],[0.015,0.156],[1.252,11.709],[0.352,5.64],[-3.072,8.607],[4.549,-8.18],[-0.773,-4.313],[-4.762,-1.151],[10.216,-4.196],[-0.224,-2.478],[-5.679,-0.129],[8.299,-9.998]],"o":[[-11.874,5.568],[4.814,10.311],[7.395,1.506],[-6.611,9.158],[-1.805,-0.5],[8.398,32.54],[-12.626,10.713],[-0.045,-0.151],[-2.701,-30.214],[-2.644,-11.492],[-1.238,-7.472],[4.472,-12.528],[-2.809,5.052],[5.651,-22.113],[4.148,1.003],[-5.706,2.342],[1.924,-0.448],[7.1,0.16],[-5.919,7.13]],"v":[[-2.544,-58.346],[-9.098,-35.436],[12.275,-26.365],[32.212,-16.298],[-0.357,-13.203],[-3.382,-10.278],[7.04,90.479],[-12.887,89.676],[-12.975,89.217],[-28.245,-15.87],[-35.488,-59.285],[-32.501,-88.664],[-20.309,-88.194],[-24.775,-64.518],[5.622,-98.227],[1.902,-84.239],[-8.913,-69.208],[5.158,-72.66],[19.322,-57.83]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[39.938,104.403],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 1","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-34,"ix":10},"p":{"a":0,"k":[-40.984,146.877,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.75,1],[4,-7.5],[0,0],[0,0],[0,0],[0,0],[-19.638,39.445],[-2.856,-2.914],[-3,2.75],[3.75,4.25],[-3.5,11.25],[-8.75,-1.5],[0,-0.5],[-5.25,1.5],[5.5,3.25],[0,0],[-8.5,-0.25],[0,1],[8.25,1.25],[6.75,-3],[0,0],[-2.75,0.75]],"o":[[-5.75,-1],[-4,7.5],[0,0],[0,0],[0,0],[0,0],[12.719,-25.548],[19.092,19.482],[3,-2.75],[-3.75,-4.25],[3.5,-11.25],[8.75,1.5],[0,0.5],[5.25,-1.5],[-5.5,-3.25],[0,0],[8.5,0.25],[0,-1],[-8.25,-1.25],[-6.75,3],[0,0],[2.75,-0.75]],"v":[[63.75,-226.5],[36.25,-205.5],[12.25,-151],[-16.75,-92.75],[-27,-69.75],[-7.408,-42.518],[15.73,-94.963],[37.5,-145],[67.75,-127.25],[62.25,-141],[43.5,-166.5],[61.75,-181.75],[74,-173.75],[80.5,-168.5],[79,-187],[62.75,-194],[77.75,-200.25],[91.25,-204],[84.25,-212.25],[60,-207.5],[47.5,-200.5],[61.75,-215.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125489994124,0.380391977348,0.301960993748,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.992156922583,0.976470648074,0.952941236309,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[59.408,142.518],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Layer 5 Outlines","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-13,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[39.158,21.872,0],"to":[-0.047,-3.333,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":15,"s":[38.874,1.874,0],"to":[0,0,0],"ti":[-0.047,-3.333,0]},{"t":19,"s":[39.158,21.872,0]}],"ix":2},"a":{"a":0,"k":[41.854,42.62,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.209,-0.69],[-0.511,0.048],[-0.236,0.203],[-0.229,0.246],[-0.179,0.228],[1.02,-0.13]],"o":[[0.151,0.433],[0.308,-0.048],[0.265,-0.206],[0.201,-0.209],[-0.947,-0.934],[0.136,0.707]],"v":[[-1.296,0.681],[-0.331,1.498],[0.502,1.114],[1.243,0.434],[1.814,-0.222],[-1.814,-1.416]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[33.451,44.92],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.195,-0.029],[0.008,-0.353],[0,0],[0,0],[-0.168,-0.016],[-0.02,0.005],[0.01,0.364],[0,0]],"o":[[-0.195,0.029],[0,0],[0,0],[0.002,0.308],[0.021,0.002],[0.195,-0.046],[0,0],[0.012,-0.344]],"v":[[0.011,-1.252],[-0.357,-0.558],[-0.357,-0.497],[-0.352,0.718],[-0.06,1.279],[0.004,1.274],[0.345,0.55],[0.346,-0.674]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.894,34.027],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.212,0.121],[-0.015,0.015],[0.157,0.252],[0.209,0.258],[0.204,-0.07],[0.028,-0.06],[-0.016,-0.065],[-0.206,-0.261],[-0.174,-0.221]],"o":[[0.019,-0.011],[0.273,-0.263],[-0.165,-0.289],[-0.116,-0.139],[-0.059,0.03],[-0.028,0.061],[0.077,0.323],[0.152,0.234],[0.119,0.151]],"v":[[0.56,1.061],[0.609,1.022],[0.366,0.017],[-0.196,-0.804],[-0.711,-1.112],[-0.847,-0.973],[-0.867,-0.779],[-0.436,0.107],[0.057,0.793]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[32.81,34.261],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":4,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.204,-0.083],[0.374,-0.834],[0.339,0.614],[0.458,0.355],[0.565,0.131],[0.273,-0.022],[0.313,-0.18],[0.199,-0.302],[-0.359,-0.794],[-0.93,-0.444],[0.462,-0.759],[-0.127,-0.528],[-0.702,-0.039],[-0.564,0.425],[-0.417,0.571],[0,0],[-0.168,-0.024],[-0.17,-0.028],[-0.342,-0.099],[-0.009,-0.006],[-0.122,-0.044],[-0.175,-0.074],[-0.268,-0.15],[-0.222,-0.136],[-0.029,0.05],[-0.056,0.107],[0,0],[-0.034,0.088],[0.009,0.096],[0.066,0.073],[0.125,0.072],[0.64,0.2],[0.693,0.038],[0,0],[0.034,0.509],[-0.183,-0.026],[-0.328,-0.065],[-0.906,-0.697],[0.006,0.022],[0.507,0.838],[0.354,0.195],[0.403,-0.014]],"o":[[-0.84,0.362],[-0.094,-0.695],[-0.268,-0.514],[-0.459,-0.355],[-0.269,-0.056],[-0.361,0.021],[-0.313,0.181],[-0.44,0.751],[0.424,0.938],[-0.782,0.423],[-0.28,0.462],[0.155,0.679],[0.705,-0.001],[0.583,-0.4],[0,0],[0.169,-0.019],[0.172,0.018],[0.353,0.053],[0.011,0.003],[0.118,0.034],[0.177,0.063],[0.283,0.122],[0.228,0.125],[0.011,0.005],[0.05,-0.107],[0,0],[0.047,-0.083],[0.03,-0.092],[-0.014,-0.097],[-0.095,-0.108],[-0.568,-0.356],[-0.661,-0.209],[0,0],[0.116,-0.496],[0.289,-0.006],[0.334,0.014],[1.12,0.228],[0,0],[0.198,-0.928],[-0.204,-0.349],[-0.354,-0.195],[-0.22,0.017]],"v":[[2.55,-2.869],[0.663,-1.007],[0.007,-2.989],[-1.095,-4.308],[-2.648,-5.046],[-3.464,-5.097],[-4.489,-4.791],[-5.267,-4.058],[-5.258,-1.537],[-3.162,0.604],[-5.062,2.408],[-5.427,3.95],[-3.861,5.119],[-1.906,4.463],[-0.394,2.997],[-0.372,2.994],[0.135,3.001],[0.648,3.07],[1.691,3.298],[1.721,3.312],[2.072,3.426],[2.599,3.632],[3.426,4.041],[4.101,4.437],[4.468,3.847],[4.64,3.532],[4.776,3.277],[4.898,3.019],[4.929,2.734],[4.807,2.473],[4.476,2.2],[2.657,1.363],[0.618,0.99],[0.579,0.99],[0.704,-0.525],[1.418,-0.512],[2.412,-0.394],[5.491,1.011],[5.498,0.994],[5.2,-1.911],[4.348,-2.742],[3.191,-3.019]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[32.167,38.948],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":4,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-8.59,-6.769]],"o":[[10.518,-6.189],[0,0]],"v":[[-20.375,-10.538],[10.841,-10.616]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[22.814,-24.65],[10.841,-10.616]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[-4.955,10.557]],"o":[[-4.477,-5.224],[0,0]],"v":[[-13.138,18.333],[-20.375,-10.538]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.295,7.422],[-10.518,6.189]],"o":[[0,0],[-2.063,-3.506],[0.395,-9.952],[0,0]],"v":[[-13.138,18.333],[-32.176,39.329],[-37.43,18.936],[-20.375,-10.538]],"c":false},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-13.138,18.333],[10.841,-10.616]],"c":false},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[-2.885,10.905],[-0.531,1.944],[-2.966,4.284]],"o":[[18.09,3.95],[1.393,-5.265],[0.596,-2.179],[0,0]],"v":[[-13.138,18.333],[13.367,3.421],[16.893,-13.831],[22.814,-24.65]],"c":false},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[0,0],[5.159,-7.45]],"o":[[-2.755,-4.825],[0,0]],"v":[[37.725,-34.504],[22.814,-24.65]],"c":false},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[40.936,42.7],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":9,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.715,5.099],[-11.354,4.592],[-12.719,-8.717],[-2.13,-2.167],[0,0],[0,0],[0,0],[0,0]],"o":[[-0.893,-6.374],[4.108,-1.661],[7.021,-0.745],[0,0],[0,0],[0,0],[0,0],[-1.321,-3.481]],"v":[[-25.941,11.835],[-7.163,-20.245],[19.813,-19.934],[26.535,-23.938],[24.234,-1.121],[13.635,8.865],[-0.799,9.311],[-21.085,28.651]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.992156922583,0.976470648074,0.952941236309,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30.208,51.717],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":4,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[4.464,3.366],[5.846,-12.984],[-4.804,11.218]],"o":[[-7.155,-5.396],[11.963,2.414],[5.226,-12.206]],"v":[[14.734,-20.133],[-19.197,23.115],[9.854,8.844]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[64.26,25.779],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":4,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"body","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[13]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":16,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":31,"s":[0]},{"t":41,"s":[13]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[142.297,202.632,0],"to":[0,-1.667,0],"ti":[0,1.667,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":16,"s":[142.297,192.632,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":31,"s":[142.297,192.632,0],"to":[0,1.667,0],"ti":[0,-1.667,0]},{"t":41,"s":[142.297,202.632,0]}],"ix":2},"a":{"a":0,"k":[92.494,93.24,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[20.164,29.219]],"o":[[-1.28,3.904],[0,0]],"v":[[13.561,-16.855],[-13.561,-12.363]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[87.756,97.125],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.574,-2.217],[3.993,-3.182]],"o":[[5.55,-0.989],[1.574,2.217],[0,0]],"v":[[-8.746,-0.146],[7.156,-0.495],[-2.855,11.822]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-2.917,0.914],[-2.107,-2.725]],"o":[[-1.081,-3.448],[3.604,-1.129],[0,0]],"v":[[-2.745,-3.079],[1.006,-10.693],[8.746,-6.678]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[93.075,68.164],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.917,0.913],[-2.107,-2.725]],"o":[[-1.081,-3.448],[3.604,-1.129],[0,0]],"v":[[-5.205,4.371],[-1.454,-3.242],[6.286,0.772]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[66.862,69.869],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.757,-4.123],[-4.205,-0.748],[0.95,4.302]],"o":[[-1.406,3.298],[1.318,0.446],[-1.187,-5.379]],"v":[[-6.583,-1.346],[4.273,5.022],[7.039,0.982]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[88.043,41.733],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":4,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.717,2.922],[1.917,-4.078],[-4.643,-0.214]],"o":[[-2.974,-2.338],[-0.816,1.22],[5.804,0.268]],"v":[[3.519,-5.584],[-5.949,3.727],[-2.593,7.654]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[60.12,50.424],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":4,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.05,-6.545],[6.544,-2.05],[2.05,6.545],[-6.544,2.05]],"o":[[2.05,6.544],[-6.545,2.05],[-2.05,-6.544],[6.545,-2.05]],"v":[[11.89,-7.175],[4.439,12.176],[-12.035,4.323],[-2.986,-11.524]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.58431372549,1,0.666666666667,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[47.828,90.915],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":4,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.05,-6.544],[-6.544,2.05],[2.051,6.544],[6.544,-2.05]],"o":[[2.05,6.545],[6.545,-2.051],[-2.05,-6.545],[-6.545,2.05]],"v":[[-13.127,0.329],[4.033,11.971],[13.082,-3.877],[-3.391,-11.729]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.58431372549,1,0.666666666667,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[119.233,66.376],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":4,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[39.85,-17.128],[-17.128,-39.85],[-39.851,17.128],[17.128,39.851]],"o":[[-39.85,17.128],[17.127,39.85],[39.85,-17.127],[-17.128,-39.85]],"v":[[-31.012,-72.156],[-72.156,31.012],[31.012,72.156],[72.156,-31.012]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[92.494,92.494],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 8","np":2,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[39.85,-17.128],[-17.128,-39.85],[-39.851,17.128],[17.128,39.851]],"o":[[-39.85,17.128],[17.127,39.85],[39.85,-17.127],[-17.128,-39.85]],"v":[[-31.012,-72.156],[-72.156,31.012],[31.012,72.156],[72.156,-31.012]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.992156922583,0.976470648074,0.952941236309,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[92.494,92.494],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 9","np":4,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.802,-3.269]],"o":[[2.335,-0.097],[0,0]],"v":[[-5.253,-1.849],[5.253,1.946]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[85.522,160.585],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 10","np":2,"cix":2,"bm":0,"ix":10,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Layer 8 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[9]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":9,"s":[19]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":20,"s":[24.913]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":24,"s":[1.609]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.993],"y":[0]},"t":26,"s":[11.207]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":29,"s":[0]},{"t":34,"s":[9]}],"ix":10},"p":{"a":0,"k":[206.516,209.876,0],"ix":2},"a":{"a":0,"k":[46.928,140.495,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[2.676,-6.958],[0,0]],"o":[[0,0],[8.991,1.606],[0,0],[0,0]],"v":[[-11.86,-10.501],[12.31,-24.085],[22.746,-0.802],[-25.422,24.085]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[68.772,130.12],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[30.048,-29.096],[16.859,-10.303],[-7.359,12.444],[-8.979,9.634],[2.554,0],[-1.161,4.26],[-2.944,0.134],[-4.816,10.598],[4.416,-1.606],[2.007,1.204],[-15.655,-0.802],[-2.007,-6.022],[0,0],[-5.78,0],[-0.536,-8.296],[-0.428,3.182],[-1.606,-9.634]],"o":[[-23.281,22.544],[-36.929,13.166],[19.667,-12.443],[2.478,-2.658],[-8.43,0],[1.205,-4.416],[8.162,-0.268],[6.022,-13.246],[-4.415,1.605],[-2.007,-1.204],[12.524,0.643],[0,0],[-0.803,-3.345],[5.78,0],[1.07,-5.218],[0.95,-7.073],[1.605,9.634]],"v":[[60.213,-0.128],[-53.788,70.118],[-44.956,38.005],[39.74,-14.177],[26.09,-17.388],[15.654,-25.015],[26.09,-27.825],[54.443,-41.539],[38.387,-59.2],[30.761,-57.996],[46.014,-71.243],[67.691,-52.376],[62.873,-68.834],[65.429,-82.329],[76.521,-53.982],[79.732,-73.65],[89.113,-73.65]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[93.928,86.495],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[30.048,-29.096],[16.859,-10.303],[-7.359,12.444],[-8.979,9.634],[2.554,0],[-1.161,4.26],[-2.944,0.134],[-4.816,10.598],[4.416,-1.606],[2.007,1.204],[-15.655,-0.802],[-2.007,-6.022],[0,0],[-5.78,0],[-0.536,-8.296],[-0.428,3.182],[-1.606,-9.634]],"o":[[-23.281,22.544],[-36.929,13.166],[19.667,-12.443],[2.478,-2.658],[-8.43,0],[1.205,-4.416],[8.162,-0.268],[6.022,-13.246],[-4.415,1.605],[-2.007,-1.204],[12.524,0.643],[0,0],[-0.803,-3.345],[5.78,0],[1.07,-5.218],[0.95,-7.073],[1.605,9.634]],"v":[[60.213,-0.128],[-53.788,70.118],[-44.956,38.005],[39.74,-14.177],[26.09,-17.388],[15.654,-25.015],[26.09,-27.825],[54.443,-41.539],[38.387,-59.2],[30.761,-57.996],[46.014,-71.243],[67.691,-52.376],[62.873,-68.834],[65.429,-82.329],[76.521,-53.982],[79.732,-73.65],[89.113,-73.65]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.992156922583,0.976470648074,0.952941236309,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[93.928,86.495],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":4,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[205,256.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-53.5,-2],[0,0],[0,0],[5.5,-1],[0,0],[1.5,-2.5]],"o":[[53.5,2],[0,0],[0,0],[-5.5,1],[0,0],[-1.5,2.5]],"v":[[-93,7.5],[-45,10],[-51,42],[-72,33.5],[-71,23],[-94,21]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125489994124,0.380391977348,0.301960993748,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Layer 7 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[120.672,368.357,0],"ix":2},"a":{"a":0,"k":[72.85,134.81,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.154],[0.759,-0.598],[1.592,-0.531],[5.019,0],[3.167,1.055],[0.741,0.584],[0,0.155],[-0.76,0.598],[-1.592,0.531],[-5.019,0],[-3.167,-1.055],[-0.742,-0.585]],"o":[[0,0.155],[-0.742,0.584],[-3.167,1.055],[-5.019,0],[-1.592,-0.531],[-0.76,-0.598],[0,-0.154],[0.741,-0.585],[3.167,-1.055],[5.019,0],[1.592,0.531],[0.759,0.598]],"v":[[17.021,-0.001],[16.169,1.156],[12.663,2.867],[0,4.604],[-12.663,2.867],[-16.169,1.156],[-17.021,-0.001],[-16.169,-1.156],[-12.663,-2.867],[0,-4.604],[12.663,-2.867],[16.169,-1.156]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[39.375,213.586],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.154],[0.759,-0.598],[1.592,-0.531],[5.019,0],[3.167,1.055],[0.741,0.584],[0,0.155],[-0.76,0.598],[-1.592,0.531],[-5.019,0],[-3.167,-1.055],[-0.742,-0.585]],"o":[[0,0.155],[-0.742,0.584],[-3.167,1.055],[-5.019,0],[-1.592,-0.531],[-0.76,-0.598],[0,-0.154],[0.741,-0.585],[3.167,-1.055],[5.019,0],[1.592,0.531],[0.759,0.598]],"v":[[17.021,-0.001],[16.169,1.156],[12.663,2.867],[0,4.604],[-12.663,2.867],[-16.169,1.156],[-17.021,-0.001],[-16.169,-1.156],[-12.663,-2.867],[0,-4.604],[12.663,-2.867],[16.169,-1.156]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.913725550034,0.847058883368,0.678431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[39.375,213.586],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-22.161,19.486]],"o":[[12.895,7.323],[0,0]],"v":[[-33.193,-7.355],[33.193,-9.743]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[39.129,223.329],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,7.642],[3.43,-0.801],[1.906,-5.256],[-2.36,-1.056]],"o":[[-0.955,-13.85],[-14.328,3.346],[-2.085,5.746],[13.846,6.195]],"v":[[16.716,-22.596],[3.821,-28.805],[-19.1,-31.668],[-19.1,-20.685]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-23.69,14.137]],"o":[[13.691,5.89],[0,0]],"v":[[-35.343,22.787],[35.343,22.787]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[38.896,217.077],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":4,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-14.328,3.346],[-0.955,-13.85],[13.847,6.195],[-2.085,5.746]],"o":[[3.43,-0.801],[0,7.642],[-2.36,-1.056],[1.906,-5.256]],"v":[[6.193,-3.098],[19.088,3.111],[-16.728,5.022],[-16.728,-5.961]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.913725550034,0.847058883368,0.678431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[36.524,191.37],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":4,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.764,14.902],[-5.253,3.184],[-3.025,1.751],[-9.075,-7.163],[0,-16.875],[14.646,7.483]],"o":[[0.764,-14.901],[10.699,4.202],[1.273,-1.433],[9.106,7.189],[-21.397,17.958],[-0.318,-2.706]],"v":[[-35.482,-6.632],[-18.766,-34.81],[4.693,-34.81],[27.14,-27.086],[35.737,18.286],[-35.482,20.114]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[39.457,230.165],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":2,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.764,14.902],[-5.253,3.184],[-3.025,1.751],[-9.075,-7.163],[0,-16.875],[14.646,7.483]],"o":[[0.764,-14.901],[10.699,4.202],[1.273,-1.433],[9.106,7.189],[-21.397,17.958],[-0.318,-2.706]],"v":[[-35.482,-6.632],[-18.766,-34.81],[4.693,-34.81],[27.14,-27.086],[35.737,18.286],[-35.482,20.114]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.913725550034,0.847058883368,0.678431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[39.457,230.165],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":4,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[30.411,2.444]],"o":[[-8.825,2.828],[0,0]],"v":[[32.244,-3.937],[-32.244,1.493]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[105.367,215.215],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 8","np":2,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-33.107,13.54]],"o":[[-0.61,3.391],[0,0]],"v":[[15.283,-23.224],[43.857,-11.751]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-3.002,-0.724],[-4.297,-5.254]],"o":[[2.702,0.295],[7.7,1.859],[0,0]],"v":[[15.283,-23.224],[23.846,-21.717],[43.857,-11.751]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[3.009,-8.69]],"o":[[2.737,1.089],[0,0]],"v":[[-40.91,-18.608],[-36.459,-4.479]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[-4.046,5.578]],"o":[[0.598,-10.858],[0,0]],"v":[[-48.939,5.796],[-40.91,-18.608]],"c":false},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0,0],[-7.329,-0.801]],"o":[[4.729,-1.106],[0,0]],"v":[[-2.949,-22.311],[15.283,-23.224]],"c":false},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[3.677,0.624],[-0.209,-2.911],[1.481,6.028],[4.256,-5.87]],"o":[[-0.176,-1.603],[-4.596,-0.78],[-3.232,-0.038],[0,0],[0,0]],"v":[[-2.949,-22.311],[-7.251,-32.294],[-16.876,-21.218],[-38.025,-28.456],[-40.91,-18.608]],"c":false},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[0,0],[-4.308,1.008]],"o":[[1.692,-1.143],[0,0]],"v":[[-12.059,-18.74],[-2.949,-22.311]],"c":false},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[12.331,0],[3.002,3.821],[0,3.387]],"o":[[0,0],[0,2.293],[-32.045,0],[-2.402,-3.057],[0,0]],"v":[[51.34,11.321],[51.34,30.457],[15.169,32.464],[-48.939,29.253],[-48.939,5.796]],"c":false},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ind":8,"ty":"sh","ix":9,"ks":{"a":0,"k":{"i":[[0,0],[6.019,5.172]],"o":[[-0.858,-3.461],[0,0]],"v":[[51.34,11.321],[43.857,-11.751]],"c":false},"ix":2},"nm":"Path 9","mn":"ADBE Vector Shape - Group","hd":false},{"ind":9,"ty":"sh","ix":10,"ks":{"a":0,"k":{"i":[[0,0],[-1.228,22.283]],"o":[[-34.164,3.481],[0,0]],"v":[[51.34,11.321],[-48.939,5.796]],"c":false},"ix":2},"nm":"Path 10","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[91.149,217.684],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 9","np":12,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.596,-0.78],[-0.176,-1.603],[-7.329,-0.801],[-3.002,-0.724],[-4.297,-5.254],[-0.858,-3.461],[0,0],[12.331,0],[3.002,3.821],[-0.208,4.43],[-0.011,0.202],[-4.046,5.578],[0.207,0.866],[0.016,0.066],[-0.031,-0.129],[-3.196,-0.037]],"o":[[3.677,0.624],[4.729,-1.106],[2.702,0.295],[7.7,1.859],[6.019,5.172],[0,0],[0,2.293],[-32.045,0],[-2.284,-2.906],[0,-0.196],[0.598,-10.858],[3.705,-5.11],[-0.02,-0.065],[0,0],[1.784,5.858],[-0.209,-2.911]],"v":[[-7.309,-32.294],[-3.008,-22.311],[15.223,-23.224],[23.788,-21.717],[43.799,-11.751],[51.281,11.321],[51.281,30.457],[15.111,32.464],[-48.997,29.253],[-49.014,6.392],[-48.997,5.796],[-40.969,-18.608],[-38.029,-28.26],[-38.083,-28.456],[-38.029,-28.26],[-16.934,-21.218]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.913725550034,0.847058883368,0.678431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[91.208,217.684],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 10","np":4,"cix":2,"bm":0,"ix":10,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.411,0.885],[-0.883,3.211],[-1.429,-4.013],[1.207,-2.809]],"o":[[-1.928,-0.709],[1.851,-6.7],[1.139,3.198],[-1.005,2.339]],"v":[[-16.462,3.989],[-14.454,-6.449],[17.251,-0.428],[14.445,10.81]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[47.315,147.729],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 11","np":2,"cix":2,"bm":0,"ix":11,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.411,0.885],[-0.883,3.211],[-1.429,-4.013],[1.207,-2.809]],"o":[[-1.928,-0.709],[1.851,-6.7],[1.139,3.198],[-1.005,2.339]],"v":[[-16.462,3.989],[-14.454,-6.449],[17.251,-0.428],[14.445,10.81]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[47.315,147.729],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 12","np":4,"cix":2,"bm":0,"ix":12,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.737,0.845],[-1.21,2.545],[-2.407,-2.007],[0.806,-3.613]],"o":[[-1.39,-0.675],[2.901,-4.373],[1.924,1.604],[-0.728,3.261]],"v":[[-12.733,2.512],[-10.682,-7.472],[12.2,-1.049],[10.193,8.584]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[73.651,155.977],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 13","np":2,"cix":2,"bm":0,"ix":13,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.737,0.845],[-1.21,2.545],[-2.407,-2.007],[0.806,-3.613]],"o":[[-1.39,-0.675],[2.901,-4.373],[1.924,1.604],[-0.728,3.261]],"v":[[-12.733,2.512],[-10.682,-7.472],[12.2,-1.049],[10.193,8.584]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[73.651,155.977],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 14","np":4,"cix":2,"bm":0,"ix":14,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[27.423,-66.525],[3.794,-76.512],[2.544,-73.555],[26.173,-63.567]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-7.522,62.497],[0,0],[6.577,-26.289]],"o":[[6.531,-26.104],[0,0],[-7.49,62.233],[0,0]],"v":[[-1.872,76.271],[28.392,-64.854],[25.204,-65.238],[-4.987,75.492]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-27.264,71.555],[-3.821,77.439],[-3.039,74.324],[-26.482,68.441]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[1.711,-11.608],[3.022,-14.521],[6.58,-18.695],[0,0],[-6.059,29.105],[-1.715,11.628],[0.413,5.16]],"o":[[0.38,4.744],[-1.703,11.548],[-6.05,29.061],[0,0],[6.652,-18.898],[3.032,-14.562],[1.705,-11.569],[0,0]],"v":[[1.568,-74.906],[-0.584,-49.537],[-7.867,-9.515],[-28.387,69.465],[-25.358,70.532],[-4.724,-8.86],[2.593,-49.069],[4.769,-75.162]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[26.798,-65.046],[28.392,-64.854],[28.537,-66.055],[27.423,-66.525]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.365,0.219],[-0.104,0.414]],"o":[[0,0],[0.414,0.104],[0.366,-0.219],[0,0]],"v":[[-3.43,75.882],[-3.821,77.439],[-2.605,77.258],[-1.872,76.271]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.214,-0.398],[-0.438,-0.11]],"o":[[0,0],[-0.15,0.426],[0.214,0.398],[0,0]],"v":[[-26.873,69.999],[-28.387,69.465],[-28.287,70.758],[-27.264,71.555]],"c":true},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[3.169,-75.034],[3.794,-76.512],[1.357,-77.542],[1.568,-74.906]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[63.414,77.792],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 15","np":12,"cix":2,"bm":0,"ix":15,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.584,19.807],[0,0],[6.555,-26.197]],"o":[[13.233,-37.594],[0,0],[-7.506,62.365],[0,0]],"v":[[-26.835,69.575],[3.206,-75.458],[26.835,-65.47],[-3.393,75.458]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.992156922583,0.976470648074,0.952941236309,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[63.377,78.216],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 16","np":4,"cix":2,"bm":0,"ix":16,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[27.424,-66.525],[3.794,-76.512],[2.544,-73.554],[26.173,-63.567]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-7.522,62.498],[0,0],[6.577,-26.288]],"o":[[6.532,-26.105],[0,0],[-7.49,62.233],[0,0]],"v":[[-1.872,76.271],[28.393,-64.854],[25.204,-65.237],[-4.987,75.492]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-27.263,71.557],[-3.82,77.439],[-3.039,74.325],[-26.482,68.441]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[1.711,-11.607],[3.023,-14.521],[6.581,-18.695],[0,0],[-6.059,29.106],[-1.714,11.628],[0.413,5.16]],"o":[[0.379,4.744],[-1.702,11.549],[-6.05,29.06],[0,0],[6.652,-18.897],[3.031,-14.562],[1.706,-11.569],[0,0]],"v":[[1.569,-74.905],[-0.584,-49.537],[-7.867,-9.514],[-28.387,69.465],[-25.358,70.532],[-4.723,-8.86],[2.593,-49.068],[4.77,-75.161]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[26.799,-65.046],[28.393,-64.854],[28.537,-66.054],[27.424,-66.525]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.366,0.219],[-0.103,0.413]],"o":[[0,0],[0.413,0.103],[0.365,-0.219],[0,0]],"v":[[-3.43,75.882],[-3.82,77.439],[-2.604,77.258],[-1.872,76.271]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.214,-0.397],[-0.438,-0.11]],"o":[[0,0],[-0.15,0.426],[0.214,0.398],[0,0]],"v":[[-26.872,69.999],[-28.387,69.465],[-28.287,70.758],[-27.263,71.557]],"c":true},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[3.169,-75.033],[3.794,-76.512],[1.358,-77.542],[1.569,-74.905]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[87.148,81.128],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 17","np":12,"cix":2,"bm":0,"ix":17,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.585,19.806],[0,0],[6.555,-26.197]],"o":[[13.232,-37.593],[0,0],[-7.507,62.366],[0,0]],"v":[[-26.836,69.574],[3.205,-75.458],[26.835,-65.471],[-3.394,75.458]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.992156922583,0.976470648074,0.952941236309,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[87.112,81.553],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 18","np":4,"cix":2,"bm":0,"ix":18,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.182,-7.001],[0,0],[0,0],[0,0]],"o":[[0.043,1.91],[0,0],[0,0],[0,0],[0,0]],"v":[[17.111,-18.601],[12.812,2.992],[8.165,23.813],[-17.154,18.162],[-6.411,-23.813]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[42.96,171.602],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 19","np":2,"cix":2,"bm":0,"ix":19,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.182,-7.001],[0,0],[0,0],[0,0]],"o":[[0.043,1.91],[0,0],[0,0],[0,0],[0,0]],"v":[[17.111,-18.601],[12.812,2.992],[8.165,23.813],[-17.154,18.162],[-6.411,-23.813]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[42.96,171.602],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 20","np":4,"cix":2,"bm":0,"ix":20,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.183,-7.001],[0,0],[0,0],[0,0]],"o":[[0.042,1.91],[0,0],[0,0],[0,0],[0,0]],"v":[[17.112,-18.6],[12.812,2.992],[8.166,23.813],[-17.154,18.163],[-6.412,-23.813]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.211,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[66.686,174.935],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 21","np":2,"cix":2,"bm":0,"ix":21,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.183,-7.001],[0,0],[0,0],[0,0]],"o":[[0.042,1.91],[0,0],[0,0],[0,0],[0,0]],"v":[[17.112,-18.6],[12.812,2.992],[8.166,23.813],[-17.154,18.163],[-6.412,-23.813]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[66.686,174.935],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 22","np":4,"cix":2,"bm":0,"ix":22,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.111,2.82],[7.027,1.405],[0,0]],"o":[[-2.111,-2.82],[0,0],[6.406,-0.201]],"v":[[10.804,1.805],[-12.915,-5.934],[-5.776,5.934]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.380392186782,0.301960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[70.311,185.683],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 23","np":4,"cix":2,"bm":0,"ix":23,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Layer 9 Outlines 7","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.079,104.613,0],"ix":2},"a":{"a":0,"k":[31.092,23.846,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":29,"s":[122.942,122.942,100]},{"t":37,"s":[2292.942,2292.942,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.171,-0.624],[-2.094,0.695],[-3.201,-0.672],[-1.344,-4.905],[3.328,-3.803],[5.833,-1.015],[4.185,0.011],[1.831,-0.129],[0.974,0.646],[0.616,1.279],[1.611,9.728],[-4.823,2.802],[-4.355,-7.673],[-0.035,-0.875],[-0.009,-0.197]],"o":[[0.009,0.654],[0.978,3.673],[3.118,-1.025],[4.75,1.011],[1.344,4.904],[-3.924,4.499],[-4.134,0.725],[-1.843,-0.01],[-1.088,0.074],[-1.232,-0.815],[-4.098,-8.552],[-0.908,-5.494],[7.593,-4.369],[0.43,0.764],[0.003,0.208],[0,0]],"v":[[1.009,-10.6],[1.192,-8.656],[8.421,-9.237],[18.092,-9.868],[29.498,-0.38],[25.608,14.26],[10.032,22.212],[-2.476,23.001],[-8.003,23.076],[-11.501,22.949],[-14.02,19.193],[-29.934,-5.15],[-22.827,-19.227],[0.361,-13.755],[0.981,-11.22],[0.997,-10.605]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.58431372549,1,0.666666666667,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.092,23.846],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":29,"op":77,"st":29,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Layer 9 Outlines 6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.079,104.613,0],"ix":2},"a":{"a":0,"k":[31.092,23.846,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":28,"s":[122.942,122.942,100]},{"t":36,"s":[2292.942,2292.942,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.171,-0.624],[-2.094,0.695],[-3.201,-0.672],[-1.344,-4.905],[3.328,-3.803],[5.833,-1.015],[4.185,0.011],[1.831,-0.129],[0.974,0.646],[0.616,1.279],[1.611,9.728],[-4.823,2.802],[-4.355,-7.673],[-0.035,-0.875],[-0.009,-0.197]],"o":[[0.009,0.654],[0.978,3.673],[3.118,-1.025],[4.75,1.011],[1.344,4.904],[-3.924,4.499],[-4.134,0.725],[-1.843,-0.01],[-1.088,0.074],[-1.232,-0.815],[-4.098,-8.552],[-0.908,-5.494],[7.593,-4.369],[0.43,0.764],[0.003,0.208],[0,0]],"v":[[1.009,-10.6],[1.192,-8.656],[8.421,-9.237],[18.092,-9.868],[29.498,-0.38],[25.608,14.26],[10.032,22.212],[-2.476,23.001],[-8.003,23.076],[-11.501,22.949],[-14.02,19.193],[-29.934,-5.15],[-22.827,-19.227],[0.361,-13.755],[0.981,-11.22],[0.997,-10.605]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.58431372549,1,0.666666666667,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.092,23.846],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":28,"op":76,"st":28,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Layer 9 Outlines 5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.079,104.613,0],"ix":2},"a":{"a":0,"k":[31.092,23.846,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":27,"s":[122.942,122.942,100]},{"t":35,"s":[2292.942,2292.942,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.171,-0.624],[-2.094,0.695],[-3.201,-0.672],[-1.344,-4.905],[3.328,-3.803],[5.833,-1.015],[4.185,0.011],[1.831,-0.129],[0.974,0.646],[0.616,1.279],[1.611,9.728],[-4.823,2.802],[-4.355,-7.673],[-0.035,-0.875],[-0.009,-0.197]],"o":[[0.009,0.654],[0.978,3.673],[3.118,-1.025],[4.75,1.011],[1.344,4.904],[-3.924,4.499],[-4.134,0.725],[-1.843,-0.01],[-1.088,0.074],[-1.232,-0.815],[-4.098,-8.552],[-0.908,-5.494],[7.593,-4.369],[0.43,0.764],[0.003,0.208],[0,0]],"v":[[1.009,-10.6],[1.192,-8.656],[8.421,-9.237],[18.092,-9.868],[29.498,-0.38],[25.608,14.26],[10.032,22.212],[-2.476,23.001],[-8.003,23.076],[-11.501,22.949],[-14.02,19.193],[-29.934,-5.15],[-22.827,-19.227],[0.361,-13.755],[0.981,-11.22],[0.997,-10.605]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682114545037,0.109412092321,0.626004806219,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.092,23.846],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":27,"op":75,"st":27,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Layer 9 Outlines 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.079,104.613,0],"ix":2},"a":{"a":0,"k":[31.092,23.846,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":26,"s":[122.942,122.942,100]},{"t":34,"s":[2292.942,2292.942,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.171,-0.624],[-2.094,0.695],[-3.201,-0.672],[-1.344,-4.905],[3.328,-3.803],[5.833,-1.015],[4.185,0.011],[1.831,-0.129],[0.974,0.646],[0.616,1.279],[1.611,9.728],[-4.823,2.802],[-4.355,-7.673],[-0.035,-0.875],[-0.009,-0.197]],"o":[[0.009,0.654],[0.978,3.673],[3.118,-1.025],[4.75,1.011],[1.344,4.904],[-3.924,4.499],[-4.134,0.725],[-1.843,-0.01],[-1.088,0.074],[-1.232,-0.815],[-4.098,-8.552],[-0.908,-5.494],[7.593,-4.369],[0.43,0.764],[0.003,0.208],[0,0]],"v":[[1.009,-10.6],[1.192,-8.656],[8.421,-9.237],[18.092,-9.868],[29.498,-0.38],[25.608,14.26],[10.032,22.212],[-2.476,23.001],[-8.003,23.076],[-11.501,22.949],[-14.02,19.193],[-29.934,-5.15],[-22.827,-19.227],[0.361,-13.755],[0.981,-11.22],[0.997,-10.605]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682114545037,0.109412092321,0.626004806219,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.092,23.846],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":26,"op":74,"st":26,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Layer 9 Outlines 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.079,104.613,0],"ix":2},"a":{"a":0,"k":[31.092,23.846,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":26,"s":[122.942,122.942,100]},{"t":34,"s":[2292.942,2292.942,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.171,-0.624],[-2.094,0.695],[-3.201,-0.672],[-1.344,-4.905],[3.328,-3.803],[5.833,-1.015],[4.185,0.011],[1.831,-0.129],[0.974,0.646],[0.616,1.279],[1.611,9.728],[-4.823,2.802],[-4.355,-7.673],[-0.035,-0.875],[-0.009,-0.197]],"o":[[0.009,0.654],[0.978,3.673],[3.118,-1.025],[4.75,1.011],[1.344,4.904],[-3.924,4.499],[-4.134,0.725],[-1.843,-0.01],[-1.088,0.074],[-1.232,-0.815],[-4.098,-8.552],[-0.908,-5.494],[7.593,-4.369],[0.43,0.764],[0.003,0.208],[0,0]],"v":[[1.009,-10.6],[1.192,-8.656],[8.421,-9.237],[18.092,-9.868],[29.498,-0.38],[25.608,14.26],[10.032,22.212],[-2.476,23.001],[-8.003,23.076],[-11.501,22.949],[-14.02,19.193],[-29.934,-5.15],[-22.827,-19.227],[0.361,-13.755],[0.981,-11.22],[0.997,-10.605]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682114545037,0.109412092321,0.626004806219,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.092,23.846],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":26,"op":74,"st":26,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Layer 9 Outlines 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.079,104.613,0],"ix":2},"a":{"a":0,"k":[31.092,23.846,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":25,"s":[122.942,122.942,100]},{"t":33,"s":[2292.942,2292.942,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.171,-0.624],[-2.094,0.695],[-3.201,-0.672],[-1.344,-4.905],[3.328,-3.803],[5.833,-1.015],[4.185,0.011],[1.831,-0.129],[0.974,0.646],[0.616,1.279],[1.611,9.728],[-4.823,2.802],[-4.355,-7.673],[-0.035,-0.875],[-0.009,-0.197]],"o":[[0.009,0.654],[0.978,3.673],[3.118,-1.025],[4.75,1.011],[1.344,4.904],[-3.924,4.499],[-4.134,0.725],[-1.843,-0.01],[-1.088,0.074],[-1.232,-0.815],[-4.098,-8.552],[-0.908,-5.494],[7.593,-4.369],[0.43,0.764],[0.003,0.208],[0,0]],"v":[[1.009,-10.6],[1.192,-8.656],[8.421,-9.237],[18.092,-9.868],[29.498,-0.38],[25.608,14.26],[10.032,22.212],[-2.476,23.001],[-8.003,23.076],[-11.501,22.949],[-14.02,19.193],[-29.934,-5.15],[-22.827,-19.227],[0.361,-13.755],[0.981,-11.22],[0.997,-10.605]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.895770981733,0.58431372549,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.092,23.846],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":25,"op":73,"st":25,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Layer 9 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.079,104.613,0],"ix":2},"a":{"a":0,"k":[31.092,23.846,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":24,"s":[122.942,122.942,100]},{"t":32,"s":[2292.942,2292.942,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.171,-0.624],[-2.094,0.695],[-3.201,-0.672],[-1.344,-4.905],[3.328,-3.803],[5.833,-1.015],[4.185,0.011],[1.831,-0.129],[0.974,0.646],[0.616,1.279],[1.611,9.728],[-4.823,2.802],[-4.355,-7.673],[-0.035,-0.875],[-0.009,-0.197]],"o":[[0.009,0.654],[0.978,3.673],[3.118,-1.025],[4.75,1.011],[1.344,4.904],[-3.924,4.499],[-4.134,0.725],[-1.843,-0.01],[-1.088,0.074],[-1.232,-0.815],[-4.098,-8.552],[-0.908,-5.494],[7.593,-4.369],[0.43,0.764],[0.003,0.208],[0,0]],"v":[[1.009,-10.6],[1.192,-8.656],[8.421,-9.237],[18.092,-9.868],[29.498,-0.38],[25.608,14.26],[10.032,22.212],[-2.476,23.001],[-8.003,23.076],[-11.501,22.949],[-14.02,19.193],[-29.934,-5.15],[-22.827,-19.227],[0.361,-13.755],[0.981,-11.22],[0.997,-10.605]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.58431372549,1,0.666666666667,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.092,23.846],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":24,"op":72,"st":24,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/uni_modules/uni-animation-view/utssdk/app-android/config.json b/uni_modules/uni-animation-view/utssdk/app-android/config.json deleted file mode 100644 index 12290c6b927b685588697ed648d82d6bb6273624..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-android/config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "minSdkVersion": "21", - "dependencies": [ - "com.airbnb.android:lottie:5.2.0", - "androidx.appcompat:appcompat:1.0.0" - ] -} diff --git a/uni_modules/uni-animation-view/utssdk/app-android/index.vue b/uni_modules/uni-animation-view/utssdk/app-android/index.vue deleted file mode 100644 index 91d55e8b37eeed28073a542ca347c7002f227296..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-android/index.vue +++ /dev/null @@ -1,214 +0,0 @@ - - - diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/Resources/PrivacyInfo.xcprivacy b/uni_modules/uni-animation-view/utssdk/app-ios/Resources/PrivacyInfo.xcprivacy deleted file mode 100644 index 187c151d1662c18ca7dfea1d4c7eadfb017dd80e..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/Resources/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,23 +0,0 @@ - - - - - NSPrivacyTracking - - NSPrivacyTrackingDomains - - NSPrivacyCollectedDataTypes - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp - NSPrivacyAccessedAPITypeReasons - - 3B52.1 - - - - - diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/config.json b/uni_modules/uni-animation-view/utssdk/app-ios/config.json deleted file mode 100644 index 30bde2f74b5485dcada042f8d411c8ce9409ff1c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "deploymentTarget": "12.0", - "validArchitectures": [ - "arm64", - "x86_64" - ] -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/index.vue b/uni_modules/uni-animation-view/utssdk/app-ios/index.vue deleted file mode 100644 index 95f5c940102d30a858d7e4c16966e8a8d3912271..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/index.vue +++ /dev/null @@ -1,233 +0,0 @@ - - diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/PrivacyInfo.xcprivacy b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/PrivacyInfo.xcprivacy deleted file mode 100644 index 187c151d1662c18ca7dfea1d4c7eadfb017dd80e..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,23 +0,0 @@ - - - - - NSPrivacyTracking - - NSPrivacyTrackingDomains - - NSPrivacyCollectedDataTypes - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp - NSPrivacyAccessedAPITypeReasons - - 3B52.1 - - - - - diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift deleted file mode 100644 index f62b7760db139a91f828bb4ac0adf5cd35af988e..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift +++ /dev/null @@ -1,81 +0,0 @@ -// Created by Cal Stephens on 1/6/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CAAnimation { - /// Creates a `CAAnimation` that wraps this animation, - /// applying timing-related configuration from the given `LayerAnimationContext`. - /// - This animation should start at the beginning of the animation and - /// last the entire duration of the animation. It will be trimmed and retimed - /// to match the current playback state / looping configuration of the animation view. - @nonobjc - func timed(with context: LayerAnimationContext, for layer: CALayer) -> CAAnimation { - // The base animation always has the duration of the full animation, - // since that's the time space where keyframing and interpolating happens. - // So we start with a simple animation timeline from 0% to 100%: - // - // ┌──────────────────────────────────┐ - // │ baseAnimation │ - // └──────────────────────────────────┘ - // 0% 100% - // - let baseAnimation = self - baseAnimation.duration = context.animationDuration - baseAnimation.speed = (context.endFrame < context.startFrame) ? -1 : 1 - - // To select the subrange of the `baseAnimation` that should be played, - // we create a parent animation with the duration of that subrange - // to clip the `baseAnimation`. This parent animation can then loop - // and/or autoreverse over the clipped subrange. - // - // ┌────────────────────┬───────► - // │ clippingParent │ ... - // └────────────────────┴───────► - // 25% 75% - // ┌──────────────────────────────────┐ - // │ baseAnimation │ - // └──────────────────────────────────┘ - // 0% 100% - // - let clippingParent = CAAnimationGroup() - clippingParent.animations = [baseAnimation] - - clippingParent.duration = Double(abs(context.endFrame - context.startFrame)) / context.animation.framerate - baseAnimation.timeOffset = context.animation.time(forFrame: context.startFrame) - - clippingParent.autoreverses = context.timingConfiguration.autoreverses - clippingParent.repeatCount = context.timingConfiguration.repeatCount - clippingParent.timeOffset = context.timingConfiguration.timeOffset - - // Once the animation ends, it should pause on the final frame - clippingParent.fillMode = .both - clippingParent.isRemovedOnCompletion = false - - // We can pause the animation on a specific frame by setting the root layer's - // `speed` to 0, and then setting the `timeOffset` for the given frame. - // - For that setup to work properly, we have to set the `beginTime` - // of this animation to a time slightly before the current time. - // - It's not really clear why this is necessary, but `timeOffset` - // is not applied correctly without this configuration. - // - We can't do this when playing the animation in real time, - // because it can cause keyframe timings to be incorrect. - if context.timingConfiguration.speed == 0 { - let currentTime = layer.convertTime(CACurrentMediaTime(), from: nil) - clippingParent.beginTime = currentTime - .leastNonzeroMagnitude - } - - return clippingParent - } -} - -extension CALayer { - /// Adds the given animation to this layer, timed with the given timing configuration - /// - The given animation should start at the beginning of the animation and - /// last the entire duration of the animation. It will be trimmed and retimed - /// to match the current playback state / looping configuration of the animation view. - @nonobjc - func add(_ animation: CAPropertyAnimation, timedWith context: LayerAnimationContext) { - add(animation.timed(with: context, for: self), forKey: animation.keyPath) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CALayer+addAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CALayer+addAnimation.swift deleted file mode 100644 index 35dd69dfb4373fe3f6326124b82ee24bc3a0d400..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +++ /dev/null @@ -1,469 +0,0 @@ -// Created by Cal Stephens on 12/14/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CALayer { - - // MARK: Internal - - /// Constructs a `CAKeyframeAnimation` that reflects the given keyframes, - /// and adds it to this `CALayer`. - @nonobjc - func addAnimation( - for property: LayerProperty, - keyframes: KeyframeGroup, - value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation, - context: LayerAnimationContext) - throws - { - if let customAnimation = try customizedAnimation(for: property, context: context) { - add(customAnimation, timedWith: context) - } - - else if - let defaultAnimation = try defaultAnimation( - for: property, - keyframes: keyframes, - value: keyframeValueMapping, - context: context) - { - let timedAnimation = defaultAnimation.timed(with: context, for: self) - add(timedAnimation, forKey: property.caLayerKeypath) - } - } - - // MARK: Private - - /// Constructs a `CAAnimation` that reflects the given keyframes - /// - If the value can be applied directly to the CALayer using KVC, - /// then no `CAAnimation` will be created and the value will be applied directly. - @nonobjc - private func defaultAnimation( - for property: LayerProperty, - keyframes keyframeGroup: KeyframeGroup, - value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation, - context: LayerAnimationContext) - throws -> CAAnimation? - { - let keyframes = keyframeGroup.keyframes - guard !keyframes.isEmpty else { return nil } - - // Check if this set of keyframes uses After Effects expressions, which aren't supported. - // - We only log this once per `CoreAnimationLayer` instance. - if keyframeGroup.unsupportedAfterEffectsExpression != nil, !context.loggingState.hasLoggedAfterEffectsExpressionsWarning { - context.loggingState.hasLoggedAfterEffectsExpressionsWarning = true - context.logger.info(""" - `\(property.caLayerKeypath)` animation for "\(context.currentKeypath.fullPath)" \ - includes an After Effects expression (https://helpx.adobe.com/after-effects/using/expression-language.html), \ - which is not supported by lottie-ios (expressions are only supported by lottie-web). \ - This animation may not play correctly. - """) - } - - // If there is exactly one keyframe value that doesn't animate, - // we can improve performance by applying that value directly to the layer - // instead of creating a relatively expensive `CAKeyframeAnimation`. - if keyframes.count == 1 { - return singleKeyframeAnimation( - for: property, - keyframeValue: try keyframeValueMapping(keyframes[0].value), - writeDirectlyToPropertyIfPossible: true) - } - - /// If we're required to use the `complexTimeRemapping` from some parent `PreCompLayer`, - /// we have to manually interpolate the keyframes with the time remapping applied. - if context.mustUseComplexTimeRemapping { - return try defaultAnimation( - for: property, - keyframes: Keyframes.manuallyInterpolatedWithTimeRemapping(keyframeGroup, context: context), - value: keyframeValueMapping, - context: context.withoutTimeRemapping()) - } - - // Split the keyframes into segments with the same `CAAnimationCalculationMode` value - // - Each of these segments will become their own `CAKeyframeAnimation` - let animationSegments = keyframes.segmentsSplitByCalculationMode() - - // If we only have a single segment, we can just create a single `CAKeyframeAnimation` - // instead of wrapping it in a `CAAnimationGroup` -- this reduces allocation overhead a bit. - if animationSegments.count == 1 { - return try keyframeAnimation( - for: property, - keyframes: animationSegments[0], - value: keyframeValueMapping, - context: context) - } else { - return try animationGroup( - for: property, - animationSegments: animationSegments, - value: keyframeValueMapping, - context: context) - } - } - - /// A `CAAnimation` that applies the custom value from the `AnyValueProvider` - /// registered for this specific property's `AnimationKeypath`, - /// if one has been registered using `LottieAnimationView.setValueProvider(_:keypath:)`. - @nonobjc - private func customizedAnimation( - for property: LayerProperty, - context: LayerAnimationContext) - throws -> CAPropertyAnimation? - { - guard - let customizableProperty = property.customizableProperty, - let customKeyframes = try context.valueProviderStore.customKeyframes( - of: customizableProperty, - for: AnimationKeypath(keys: context.currentKeypath.keys + customizableProperty.name.map { $0.rawValue }), - context: context) - else { return nil } - - // Since custom animations are overriding an existing animation, - // we always have to create a CAAnimation and can't write directly - // to the layer property - if - customKeyframes.keyframes.count == 1, - let singleKeyframeAnimation = singleKeyframeAnimation( - for: property, - keyframeValue: customKeyframes.keyframes[0].value, - writeDirectlyToPropertyIfPossible: false) - { - return singleKeyframeAnimation - } - - return try keyframeAnimation( - for: property, - keyframes: Array(customKeyframes.keyframes), - value: { $0 }, - context: context) - } - - /// Creates an animation that applies a single keyframe to this layer property - /// - In many cases this animation can be omitted entirely, and the underlying - /// property can be set directly. In that case, no animation will be created. - private func singleKeyframeAnimation( - for property: LayerProperty, - keyframeValue: ValueRepresentation, - writeDirectlyToPropertyIfPossible: Bool) - -> CABasicAnimation? - { - if writeDirectlyToPropertyIfPossible { - // If the keyframe value is the same as the layer's default value for this property, - // then we can just ignore this set of keyframes. - if property.isDefaultValue(keyframeValue) { - return nil - } - - // If the property on the CALayer being animated hasn't been modified from the default yet, - // then we can apply the keyframe value directly to the layer using KVC instead - // of creating a `CAAnimation`. - let currentValue = value(forKey: property.caLayerKeypath) as? ValueRepresentation - if property.isDefaultValue(currentValue) { - setValue(keyframeValue, forKeyPath: property.caLayerKeypath) - return nil - } - } - - // Otherwise, we still need to create a `CAAnimation`, but we can - // create a simple `CABasicAnimation` that is still less expensive - // than computing a `CAKeyframeAnimation`. - let animation = CABasicAnimation(keyPath: property.caLayerKeypath) - animation.fromValue = keyframeValue - animation.toValue = keyframeValue - return animation - } - - /// Creates a `CAAnimationGroup` that wraps a `CAKeyframeAnimation` for each - /// of the given `animationSegments` - private func animationGroup( - for property: LayerProperty, - animationSegments: [[Keyframe]], - value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation, - context: LayerAnimationContext) - throws -> CAAnimationGroup - { - // Build the `CAKeyframeAnimation` for each segment of keyframes - // with the same `CAAnimationCalculationMode`. - // - Here we have a non-zero number of animation segments, - // all of which have a non-zero number of keyframes. - let segmentAnimations: [CAKeyframeAnimation] = try animationSegments.indices.map { index in - let animationSegment = animationSegments[index] - var segmentStartTime = try context.time(forFrame: animationSegment.first!.time) - var segmentEndTime = try context.time(forFrame: animationSegment.last!.time) - - // Every portion of the animation timeline has to be covered by a `CAKeyframeAnimation`, - // so if this is the first or last segment then the start/end time should be exactly - // the start/end time of the animation itself. - let isFirstSegment = (index == animationSegments.indices.first!) - let isLastSegment = (index == animationSegments.indices.last!) - - if isFirstSegment { - segmentStartTime = min( - try context.time(forFrame: context.animation.startFrame), - segmentStartTime) - } - - if isLastSegment { - segmentEndTime = max( - try context.time(forFrame: context.animation.endFrame), - segmentEndTime) - } - - let segmentDuration = segmentEndTime - segmentStartTime - - // We're building `CAKeyframeAnimation`s, so the `keyTimes` are expressed - // relative to 0 (`segmentStartTime`) and 1 (`segmentEndTime`). This is different - // from the default behavior of the `keyframeAnimation` method, where times - // are expressed relative to the entire animation duration. - let customKeyTimes = try animationSegment.map { keyframeModel -> NSNumber in - let keyframeTime = try context.time(forFrame: keyframeModel.time) - let segmentProgressTime = ((keyframeTime - segmentStartTime) / segmentDuration) - return segmentProgressTime as NSNumber - } - - let animation = try keyframeAnimation( - for: property, - keyframes: animationSegment, - value: keyframeValueMapping, - customKeyTimes: customKeyTimes, - context: context) - - animation.duration = segmentDuration - animation.beginTime = segmentStartTime - return animation - } - - let fullAnimation = CAAnimationGroup() - fullAnimation.animations = segmentAnimations - return fullAnimation - } - - /// Creates and validates a `CAKeyframeAnimation` for the given keyframes - private func keyframeAnimation( - for property: LayerProperty, - keyframes: [Keyframe], - value keyframeValueMapping: (KeyframeValue) throws -> ValueRepresentation, - customKeyTimes: [NSNumber]? = nil, - context: LayerAnimationContext) - throws - -> CAKeyframeAnimation - { - // Convert the list of `Keyframe` into - // the representation used by `CAKeyframeAnimation` - var keyTimes = try customKeyTimes ?? keyframes.map { keyframeModel -> NSNumber in - NSNumber(value: Float(try context.progressTime(for: keyframeModel.time))) - } - - var timingFunctions = timingFunctions(for: keyframes) - let calculationMode = calculationMode(for: keyframes) - - let animation = CAKeyframeAnimation(keyPath: property.caLayerKeypath) - - // Position animations define a `CGPath` curve that should be followed, - // instead of animating directly between keyframe point values. - if property.caLayerKeypath == LayerProperty.position.caLayerKeypath { - animation.path = try path(keyframes: keyframes, value: { value in - guard let point = try keyframeValueMapping(value) as? CGPoint else { - context.logger.assertionFailure("Cannot create point from keyframe with value \(value)") - return .zero - } - - return point - }) - } - - // All other types of keyframes provide individual values that are interpolated by Core Animation - else { - var values = try keyframes.map { keyframeModel in - try keyframeValueMapping(keyframeModel.value) - } - - validate( - values: &values, - keyTimes: &keyTimes, - timingFunctions: &timingFunctions, - for: calculationMode, - context: context) - - animation.values = values - } - - animation.calculationMode = calculationMode - animation.keyTimes = keyTimes - animation.timingFunctions = timingFunctions - return animation - } - - /// The `CAAnimationCalculationMode` that should be used for a `CAKeyframeAnimation` - /// animating the given keyframes - private func calculationMode( - for keyframes: [Keyframe]) - -> CAAnimationCalculationMode - { - // At this point we expect all of the animations to have been split in - // to segments based on the `CAAnimationCalculationMode`, so we can just - // check the first keyframe. - if keyframes[0].isHold { - return .discrete - } else { - return .linear - } - } - - /// `timingFunctions` to apply to a `CAKeyframeAnimation` animating the given keyframes - private func timingFunctions( - for keyframes: [Keyframe]) - -> [CAMediaTimingFunction] - { - // Compute the timing function between each keyframe and the subsequent keyframe - var timingFunctions: [CAMediaTimingFunction] = [] - - for (index, keyframe) in keyframes.enumerated() - where index != keyframes.indices.last - { - let nextKeyframe = keyframes[index + 1] - - let controlPoint1 = keyframe.outTangent?.pointValue ?? .zero - let controlPoint2 = nextKeyframe.inTangent?.pointValue ?? CGPoint(x: 1, y: 1) - - timingFunctions.append(CAMediaTimingFunction( - controlPoints: - Float(controlPoint1.x), - Float(controlPoint1.y), - Float(controlPoint2.x), - Float(controlPoint2.y))) - } - - return timingFunctions - } - - /// Creates a `CGPath` for the given `position` keyframes, - /// which accounts for `spatialInTangent`s and `spatialOutTangents` - private func path( - keyframes positionKeyframes: [Keyframe], - value keyframeValueMapping: (KeyframeValue) throws -> CGPoint) rethrows - -> CGPath - { - let path = CGMutablePath() - - for (index, keyframe) in positionKeyframes.enumerated() { - if index == positionKeyframes.indices.first { - path.move(to: try keyframeValueMapping(keyframe.value)) - } - - if index != positionKeyframes.indices.last { - let nextKeyframe = positionKeyframes[index + 1] - - if - let controlPoint1 = keyframe.spatialOutTangent?.pointValue, - let controlPoint2 = nextKeyframe.spatialInTangent?.pointValue, - !(controlPoint1 == .zero && controlPoint2 == .zero) - { - path.addCurve( - to: try keyframeValueMapping(nextKeyframe.value), - control1: try keyframeValueMapping(keyframe.value) + controlPoint1, - control2: try keyframeValueMapping(nextKeyframe.value) + controlPoint2) - } - - else { - path.addLine(to: try keyframeValueMapping(nextKeyframe.value)) - } - } - } - - path.closeSubpath() - return path - } - - /// Validates that the requirements of the `CAKeyframeAnimation` API are met correctly - private func validate( - values: inout [ValueRepresentation], - keyTimes: inout [NSNumber], - timingFunctions: inout [CAMediaTimingFunction], - for calculationMode: CAAnimationCalculationMode, - context: LayerAnimationContext) - { - // Validate that we have correct start (0.0) and end (1.0) keyframes. - // From the documentation of `CAKeyframeAnimation.keyTimes`: - // - The first value in the `keyTimes` array must be 0.0 and the last value must be 1.0. - if keyTimes.first != 0.0 { - keyTimes.insert(0.0, at: 0) - values.insert(values[0], at: 0) - timingFunctions.insert(CAMediaTimingFunction(name: .linear), at: 0) - } - - if keyTimes.last != 1.0 { - keyTimes.append(1.0) - values.append(values.last!) - timingFunctions.append(CAMediaTimingFunction(name: .linear)) - } - - switch calculationMode { - case .linear, .cubic: - // From the documentation of `CAKeyframeAnimation.keyTimes`: - // - The number of elements in the keyTimes array - // should match the number of elements in the values property - context.logger.assert( - values.count == keyTimes.count, - "`values.count` must exactly equal `keyTimes.count`") - - context.logger.assert( - timingFunctions.count == (values.count - 1), - "`timingFunctions.count` must exactly equal `values.count - 1`") - - case .discrete: - // From the documentation of `CAKeyframeAnimation.keyTimes`: - // - If the calculationMode is set to discrete... the keyTimes array - // should have one more entry than appears in the values array. - values.removeLast() - - context.logger.assert( - keyTimes.count == values.count + 1, - "`keyTimes.count` must exactly equal `values.count + 1`") - - default: - context.logger.assertionFailure(""" - Unexpected keyframe calculation mode \(calculationMode) - """) - } - } - -} - -extension RandomAccessCollection { - /// Splits this array of `Keyframe`s into segments with the same `CAAnimationCalculationMode` - /// - Keyframes with `isHold=true` become `discrete`, and keyframes with `isHold=false` - /// become linear. Each `CAKeyframeAnimation` can only be one or the other, so each - /// `calculationModeSegment` becomes its own `CAKeyframeAnimation`. - func segmentsSplitByCalculationMode() -> [[Element]] - where Element == Keyframe, Index == Int - { - var segments: [[Element]] = [] - var currentSegment: [Element] = [] - - for keyframe in self { - guard let mostRecentKeyframe = currentSegment.last else { - currentSegment.append(keyframe) - continue - } - - // When `isHold` changes between any two given keyframes, we have to create a new segment - if keyframe.isHold != mostRecentKeyframe.isHold { - // Add this keyframe to both the existing segment that is ending, - // so we know how long that segment is, and the new segment, - // so we know when that segment starts. - currentSegment.append(keyframe) - segments.append(currentSegment) - currentSegment = [keyframe] - } - - else { - currentSegment.append(keyframe) - } - } - - segments.append(currentSegment) - return segments - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift deleted file mode 100644 index e5b888f45e8173801dc856ab8ef65662484ef1ad..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +++ /dev/null @@ -1,84 +0,0 @@ -// Created by Cal Stephens on 1/28/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CAShapeLayer { - /// Adds animations for the given `CombinedShapeItem` to this `CALayer` - @nonobjc - func addAnimations( - for combinedShapes: CombinedShapeItem, - context: LayerAnimationContext, - pathMultiplier: PathMultiplier) - throws - { - try addAnimation( - for: .path, - keyframes: combinedShapes.shapes, - value: { paths in - let combinedPath = CGMutablePath() - for path in paths { - combinedPath.addPath(path.cgPath().duplicated(times: pathMultiplier)) - } - return combinedPath - }, - context: context) - } -} - -// MARK: - CombinedShapeItem - -/// A custom `ShapeItem` subclass that combines multiple `Shape`s into a single `KeyframeGroup` -final class CombinedShapeItem: ShapeItem { - - // MARK: Lifecycle - - init(shapes: KeyframeGroup<[BezierPath]>, name: String) { - self.shapes = shapes - super.init(name: name, type: .shape, hidden: false) - } - - required init(from _: Decoder) throws { - fatalError("init(from:) has not been implemented") - } - - required init(dictionary _: [String: Any]) throws { - fatalError("init(dictionary:) has not been implemented") - } - - // MARK: Internal - - let shapes: KeyframeGroup<[BezierPath]> - -} - -extension CombinedShapeItem { - /// Manually combines the given shape keyframes by manually interpolating at each frame - static func manuallyInterpolating( - shapes: [KeyframeGroup], - name: String) - -> CombinedShapeItem - { - let interpolators = shapes.map { shape in - KeyframeInterpolator(keyframes: shape.keyframes) - } - - let times = shapes.flatMap { $0.keyframes.map { $0.time } } - - let minimumTime = times.min() ?? 0 - let maximumTime = times.max() ?? 0 - let animationLocalTimeRange = Int(minimumTime)...Int(maximumTime) - - let interpolatedKeyframes = animationLocalTimeRange.map { localTime in - Keyframe( - value: interpolators.compactMap { interpolator in - interpolator.value(frame: AnimationFrameTime(localTime)) as? BezierPath - }, - time: AnimationFrameTime(localTime)) - } - - return CombinedShapeItem( - shapes: KeyframeGroup(keyframes: ContiguousArray(interpolatedKeyframes)), - name: name) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CustomPathAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CustomPathAnimation.swift deleted file mode 100644 index 2171eda5172a4d6118c33cc6743507861d96bcd8..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/CustomPathAnimation.swift +++ /dev/null @@ -1,86 +0,0 @@ -// Created by Cal Stephens on 12/21/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CAShapeLayer { - /// Adds animations for the given `BezierPath` keyframes to this `CALayer` - @nonobjc - func addAnimations( - for customPath: KeyframeGroup, - context: LayerAnimationContext, - pathMultiplier: PathMultiplier = 1, - transformPath: (CGPath) -> CGPath = { $0 }, - roundedCorners: RoundedCorners? = nil) - throws - { - let combinedKeyframes = try BezierPathKeyframe.combining( - path: customPath, - cornerRadius: roundedCorners?.radius) - - try addAnimation( - for: .path, - keyframes: combinedKeyframes, - value: { pathKeyframe in - var path = pathKeyframe.path - if let cornerRadius = pathKeyframe.cornerRadius { - path = path.roundCorners(radius: cornerRadius.cgFloatValue) - } - - return transformPath(path.cgPath().duplicated(times: pathMultiplier)) - }, - context: context) - } -} - -extension CGPath { - /// Duplicates this `CGPath` so that it is repeated the given number of times - func duplicated(times: Int) -> CGPath { - if times <= 1 { - return self - } - - let cgPath = CGMutablePath() - - for _ in 0.., - cornerRadius: KeyframeGroup?) throws - -> KeyframeGroup - { - guard - let cornerRadius, - cornerRadius.keyframes.contains(where: { $0.value.cgFloatValue > 0 }) - else { - return path.map { path in - BezierPathKeyframe(path: path, cornerRadius: nil) - } - } - - return Keyframes.combined( - path, cornerRadius, - makeCombinedResult: BezierPathKeyframe.init) - } - - func interpolate(to: BezierPathKeyframe, amount: CGFloat) -> BezierPathKeyframe { - BezierPathKeyframe( - path: path.interpolate(to: to.path, amount: amount), - cornerRadius: cornerRadius.interpolate(to: to.cornerRadius, amount: amount)) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/DropShadowAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/DropShadowAnimation.swift deleted file mode 100644 index 92296390bbe07ddcb262e6e13de8ce70efca35df..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/DropShadowAnimation.swift +++ /dev/null @@ -1,160 +0,0 @@ -// Created by Cal Stephens on 8/15/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - DropShadowModel - -protocol DropShadowModel { - /// The opacity of the drop shadow, from 0 to 100. - var _opacity: KeyframeGroup? { get } - - /// The shadow radius of the blur - var _radius: KeyframeGroup? { get } - - /// The color of the drop shadow - var _color: KeyframeGroup? { get } - - /// The angle of the drop shadow, in degrees, - /// with "90" resulting in a shadow directly beneath the layer. - /// Combines with the `distance` to form the `shadowOffset`. - var _angle: KeyframeGroup? { get } - - /// The distance of the drop shadow offset. - /// Combines with the `angle` to form the `shadowOffset`. - var _distance: KeyframeGroup? { get } -} - -// MARK: - DropShadowStyle + DropShadowModel - -extension DropShadowStyle: DropShadowModel { - var _opacity: KeyframeGroup? { opacity } - var _color: KeyframeGroup? { color } - var _angle: KeyframeGroup? { angle } - var _distance: KeyframeGroup? { distance } - - var _radius: KeyframeGroup? { - size.map { sizeValue in - // After Effects shadow softness uses a different range of values than CALayer.shadowRadius, - // so shadows render too softly if we directly use the value from After Effects. We find that - // dividing this value from After Effects by 2 produces results that are visually similar. - LottieVector1D(sizeValue.cgFloatValue / 2) - } - } -} - -// MARK: - DropShadowEffect + DropShadowModel - -extension DropShadowEffect: DropShadowModel { - var _color: KeyframeGroup? { color?.value } - var _distance: KeyframeGroup? { distance?.value } - - var _radius: KeyframeGroup? { - softness?.value?.map { softnessValue in - // After Effects shadow softness uses a different range of values than CALayer.shadowRadius, - // so shadows render too softly if we directly use the value from After Effects. We find that - // dividing this value from After Effects by 5 produces results that are visually similar. - LottieVector1D(softnessValue.cgFloatValue / 5) - } - } - - var _opacity: KeyframeGroup? { - opacity?.value?.map { originalOpacityValue in - // `DropShadowEffect.opacity` is a value between 0 and 255, - // but `DropShadowModel._opacity` expects a value between 0 and 100. - LottieVector1D((originalOpacityValue.value / 255.0) * 100) - } - } - - var _angle: KeyframeGroup? { - direction?.value?.map { originalAngleValue in - // `DropShadowEffect.distance` is rotated 90º from the - // angle value representation expected by `DropShadowModel._angle` - LottieVector1D(originalAngleValue.value - 90) - } - } -} - -// MARK: - CALayer + DropShadowModel - -extension CALayer { - - // MARK: Internal - - /// Adds drop shadow animations from the given `DropShadowModel` to this layer - @nonobjc - func addDropShadowAnimations( - for dropShadowModel: DropShadowModel, - context: LayerAnimationContext) - throws - { - try addShadowOpacityAnimation(from: dropShadowModel, context: context) - try addShadowColorAnimation(from: dropShadowModel, context: context) - try addShadowRadiusAnimation(from: dropShadowModel, context: context) - try addShadowOffsetAnimation(from: dropShadowModel, context: context) - } - - // MARK: Private - - private func addShadowOpacityAnimation(from model: DropShadowModel, context: LayerAnimationContext) throws { - guard let opacityKeyframes = model._opacity else { return } - - try addAnimation( - for: .shadowOpacity, - keyframes: opacityKeyframes, - value: { - // Lottie animation files express opacity as a numerical percentage value - // (e.g. 0%, 50%, 100%) so we divide by 100 to get the decimal values - // expected by Core Animation (e.g. 0.0, 0.5, 1.0). - $0.cgFloatValue / 100 - }, - context: context) - } - - private func addShadowColorAnimation(from model: DropShadowModel, context: LayerAnimationContext) throws { - guard let shadowColorKeyframes = model._color else { return } - - try addAnimation( - for: .shadowColor, - keyframes: shadowColorKeyframes, - value: \.cgColorValue, - context: context) - } - - private func addShadowRadiusAnimation(from model: DropShadowModel, context: LayerAnimationContext) throws { - guard let shadowSizeKeyframes = model._radius else { return } - - try addAnimation( - for: .shadowRadius, - keyframes: shadowSizeKeyframes, - value: \.cgFloatValue, - context: context) - } - - private func addShadowOffsetAnimation(from model: DropShadowModel, context: LayerAnimationContext) throws { - guard - let angleKeyframes = model._angle, - let distanceKeyframes = model._distance - else { return } - - let offsetKeyframes = Keyframes.combined(angleKeyframes, distanceKeyframes) { angleDegrees, distance -> CGSize in - // Lottie animation files express rotation in degrees - // (e.g. 90º, 180º, 360º) so we convert to radians to get the - // values expected by Core Animation (e.g. π/2, π, 2π) - let angleRadians = (angleDegrees.cgFloatValue * .pi) / 180 - - // Lottie animation files express the `shadowOffset` as (angle, distance) pair, - // which we convert to the expected x / y offset values: - let offsetX = distance.cgFloatValue * cos(angleRadians) - let offsetY = distance.cgFloatValue * sin(angleRadians) - return CGSize(width: offsetX, height: offsetY) - } - - try addAnimation( - for: .shadowOffset, - keyframes: offsetKeyframes, - value: { $0 }, - context: context) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/EllipseAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/EllipseAnimation.swift deleted file mode 100644 index df3d148d485ce36e6449bc7b18379159794b5ac9..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/EllipseAnimation.swift +++ /dev/null @@ -1,49 +0,0 @@ -// Created by Cal Stephens on 12/21/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CAShapeLayer { - /// Adds animations for the given `Ellipse` to this `CALayer` - @nonobjc - func addAnimations( - for ellipse: Ellipse, - context: LayerAnimationContext, - pathMultiplier: PathMultiplier) - throws - { - try addAnimation( - for: .path, - keyframes: ellipse.combinedKeyframes(), - value: { keyframe in - BezierPath.ellipse( - size: keyframe.size.sizeValue, - center: keyframe.position.pointValue, - direction: ellipse.direction) - .cgPath() - .duplicated(times: pathMultiplier) - }, - context: context) - } -} - -extension Ellipse { - /// Data that represents how to render an ellipse at a specific point in time - struct Keyframe: Interpolatable { - let size: LottieVector3D - let position: LottieVector3D - - func interpolate(to: Ellipse.Keyframe, amount: CGFloat) -> Ellipse.Keyframe { - Keyframe( - size: size.interpolate(to: to.size, amount: amount), - position: position.interpolate(to: to.position, amount: amount)) - } - } - - /// Creates a single array of animatable keyframes from the separate arrays of keyframes in this Ellipse - func combinedKeyframes() throws -> KeyframeGroup { - Keyframes.combined( - size, position, - makeCombinedResult: Ellipse.Keyframe.init) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/GradientAnimations.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/GradientAnimations.swift deleted file mode 100644 index 17ebf274d00aefe31a0ff2b9d6cc9e1d97d014ff..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/GradientAnimations.swift +++ /dev/null @@ -1,244 +0,0 @@ -// Created by Cal Stephens on 1/7/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - GradientShapeItem - -/// A `ShapeItem` that represents a gradient -protocol GradientShapeItem: OpacityAnimationModel { - var startPoint: KeyframeGroup { get } - var endPoint: KeyframeGroup { get } - var gradientType: GradientType { get } - var numberOfColors: Int { get } - var colors: KeyframeGroup<[Double]> { get } -} - -// MARK: - GradientFill + GradientShapeItem - -extension GradientFill: GradientShapeItem { } - -// MARK: - GradientStroke + GradientShapeItem - -extension GradientStroke: GradientShapeItem { } - -// MARK: - GradientRenderLayer + GradientShapeItem - -extension GradientRenderLayer { - - // MARK: Internal - - /// Adds gradient-related animations to this layer, from the given `GradientFill` - /// - The RGB components and alpha components can have different color stops / locations, - /// so have to be rendered in separate `CAGradientLayer`s. - func addGradientAnimations( - for gradient: GradientShapeItem, - type: GradientContentType, - context: LayerAnimationContext) - throws - { - // We have to set `colors` and `locations` to non-nil values - // for the animations below to actually take effect - locations = [] - - // The initial value for `colors` must be an array with the exact same number of colors - // as the gradient that will be applied in the `CAAnimation` - switch type { - case .rgb: - colors = .init( - repeating: CGColor.rgb(0, 0, 0), - count: gradient.numberOfColors) - - case .alpha: - colors = .init( - repeating: CGColor.rgb(0, 0, 0), - count: gradient.colorConfiguration(from: gradient.colors.keyframes[0].value, type: .alpha).count) - } - - try addAnimation( - for: .colors, - keyframes: gradient.colors, - value: { colorComponents in - gradient.colorConfiguration(from: colorComponents, type: type).map { $0.color } - }, - context: context) - - try addAnimation( - for: .locations, - keyframes: gradient.colors, - value: { colorComponents in - gradient.colorConfiguration(from: colorComponents, type: type).map { $0.location } - }, - context: context) - - try addOpacityAnimation(for: gradient, context: context) - - switch gradient.gradientType { - case .linear: - try addLinearGradientAnimations(for: gradient, context: context) - case .radial: - try addRadialGradientAnimations(for: gradient, context: context) - case .none: - break - } - } - - // MARK: Private - - private func addLinearGradientAnimations( - for gradient: GradientShapeItem, - context: LayerAnimationContext) - throws - { - type = .axial - - try addAnimation( - for: .startPoint, - keyframes: gradient.startPoint, - value: { absoluteStartPoint in - percentBasedPointInBounds(from: absoluteStartPoint.pointValue) - }, - context: context) - - try addAnimation( - for: .endPoint, - keyframes: gradient.endPoint, - value: { absoluteEndPoint in - percentBasedPointInBounds(from: absoluteEndPoint.pointValue) - }, - context: context) - } - - private func addRadialGradientAnimations(for gradient: GradientShapeItem, context: LayerAnimationContext) throws { - type = .radial - - let combinedKeyframes = Keyframes.combined( - gradient.startPoint, gradient.endPoint, - makeCombinedResult: { absoluteStartPoint, absoluteEndPoint -> RadialGradientKeyframes in - // Convert the absolute start / end points to the relative structure used by Core Animation - let relativeStartPoint = percentBasedPointInBounds(from: absoluteStartPoint.pointValue) - let radius = absoluteStartPoint.pointValue.distanceTo(absoluteEndPoint.pointValue) - let relativeEndPoint = percentBasedPointInBounds( - from: CGPoint( - x: absoluteStartPoint.x + radius, - y: absoluteStartPoint.y + radius)) - - return RadialGradientKeyframes(startPoint: relativeStartPoint, endPoint: relativeEndPoint) - }) - - try addAnimation( - for: .startPoint, - keyframes: combinedKeyframes, - value: \.startPoint, - context: context) - - try addAnimation( - for: .endPoint, - keyframes: combinedKeyframes, - value: \.endPoint, - context: context) - } -} - -// MARK: - RadialGradientKeyframes - -private struct RadialGradientKeyframes: Interpolatable { - let startPoint: CGPoint - let endPoint: CGPoint - - func interpolate(to: RadialGradientKeyframes, amount: CGFloat) -> RadialGradientKeyframes { - RadialGradientKeyframes( - startPoint: startPoint.interpolate(to: to.startPoint, amount: amount), - endPoint: endPoint.interpolate(to: to.endPoint, amount: amount)) - } -} - -// MARK: - GradientContentType - -/// Each type of gradient that can be constructed from a `GradientShapeItem` -enum GradientContentType { - case rgb - case alpha -} - -/// `colors` and `locations` configuration for a `CAGradientLayer` -typealias GradientColorConfiguration = [(color: CGColor, location: CGFloat)] - -extension GradientShapeItem { - - // MARK: Internal - - /// Whether or not this `GradientShapeItem` includes an alpha component - /// that has to be rendered as a separate `CAGradientLayer` from the - /// layer that renders the rgb color components - var hasAlphaComponent: Bool { - for colorComponentsKeyframe in colors.keyframes { - let colorComponents = colorComponentsKeyframe.value - let alphaConfiguration = colorConfiguration(from: colorComponents, type: .alpha) - - let notFullyOpaque = alphaConfiguration.contains(where: { color, _ in - color.alpha < 0.999 - }) - - if notFullyOpaque { - return true - } - } - - return false - } - - // MARK: Fileprivate - - /// Converts the compact `[Double]` color components representation - /// into an array of `CGColor`s and the location of those colors within the gradient. - /// - The color components array is a repeating list of `[location, red, green, blue]` values - /// for each color in the gradient, followed by an optional repeating list of - /// `[location, alpha]` values that control the colors' alpha values. - /// - The RGB and alpha values can have different color stops / locations, - /// so each has to be rendered in a separate `CAGradientLayer`. - fileprivate func colorConfiguration( - from colorComponents: [Double], - type: GradientContentType) - -> GradientColorConfiguration - { - switch type { - case .rgb: - precondition( - colorComponents.count >= numberOfColors * 4, - "Each color must have RGB components and a location component") - - // Each group of four `Double` values represents a single `CGColor`, - // and its relative location within the gradient. - var colors = GradientColorConfiguration() - - for colorIndex in 0.. { - /// The `CALayer` KVC key path that this value should be assigned to - let caLayerKeypath: String - - /// Whether or not the given value is the default value for this property - /// - If the keyframe values are just equal to the default value, - /// then we can improve performance a bit by just not creating - /// a CAAnimation (since it would be redundant). - let isDefaultValue: (ValueRepresentation?) -> Bool - - /// A description of how this property can be customized dynamically - /// at runtime using `AnimationView.setValueProvider(_:keypath:)` - let customizableProperty: CustomizableProperty? -} - -extension LayerProperty where ValueRepresentation: Equatable { - /// Initializes a `LayerProperty` that corresponds to a property on `CALayer` - /// or some other `CALayer` subclass like `CAShapeLayer`. - /// - Parameters: - /// - caLayerKeypath: The Objective-C `#keyPath` to the `CALayer` property, - /// e.g. `#keyPath(CALayer.opacity)` or `#keyPath(CAShapeLayer.path)`. - /// - defaultValue: The default value of the property (e.g. the value of the - /// property immediately after calling `CALayer.init()`). Knowing this value - /// lets us perform some optimizations in `CALayer+addAnimation`. - /// - customizableProperty: A description of how this property can be customized - /// dynamically at runtime using `AnimationView.setValueProvider(_:keypath:)`. - init( - caLayerKeypath: String, - defaultValue: ValueRepresentation?, - customizableProperty: CustomizableProperty?) - { - self.init( - caLayerKeypath: caLayerKeypath, - isDefaultValue: { $0 == defaultValue }, - customizableProperty: customizableProperty) - } -} - -// MARK: - CustomizableProperty - -/// A description of how a `CALayer` property can be customized dynamically -/// at runtime using `LottieAnimationView.setValueProvider(_:keypath:)` -struct CustomizableProperty { - /// The name that `AnimationKeypath`s can use to refer to this property - /// - When building an animation for this property that will be applied - /// to a specific layer, this `name` is appended to the end of that - /// layer's `AnimationKeypath`. The combined keypath is used to query - /// the `ValueProviderStore`. - let name: [PropertyName] - - /// A closure that coverts the type-erased value of an `AnyValueProvider` - /// to the strongly-typed representation used by this property, if possible. - /// - `value` is the value for the current frame that should be converted, - /// as returned by `AnyValueProvider.typeErasedStorage`. - /// - `valueProvider` is the `AnyValueProvider` that returned the type-erased value. - let conversion: (_ value: Any, _ valueProvider: AnyValueProvider) -> ValueRepresentation? -} - -// MARK: - PropertyName - -/// The name of a customizable property that can be used in an `AnimationKeypath` -/// - These values should be shared between the two rendering engines, -/// since they form the public API of the `AnimationKeypath` system. -enum PropertyName: String, CaseIterable { - case color = "Color" - case opacity = "Opacity" - case scale = "Scale" - case position = "Position" - case rotation = "Rotation" - case strokeWidth = "Stroke Width" - case gradientColors = "Colors" -} - -// MARK: CALayer properties - -extension LayerProperty { - static var position: LayerProperty { - .init( - caLayerKeypath: "transform.translation", - defaultValue: CGPoint(x: 0, y: 0), - customizableProperty: .position) - } - - static var positionX: LayerProperty { - .init( - caLayerKeypath: "transform.translation.x", - defaultValue: 0, - customizableProperty: nil /* currently unsupported */ ) - } - - static var positionY: LayerProperty { - .init( - caLayerKeypath: "transform.translation.y", - defaultValue: 0, - customizableProperty: nil /* currently unsupported */ ) - } - - static var scale: LayerProperty { - .init( - caLayerKeypath: "transform.scale", - defaultValue: 1, - customizableProperty: nil /* currently unsupported */ ) - } - - static var scaleX: LayerProperty { - .init( - caLayerKeypath: "transform.scale.x", - defaultValue: 1, - customizableProperty: .scaleX) - } - - static var scaleY: LayerProperty { - .init( - caLayerKeypath: "transform.scale.y", - defaultValue: 1, - customizableProperty: .scaleY) - } - - static var rotationX: LayerProperty { - .init( - caLayerKeypath: "transform.rotation.x", - defaultValue: 0, - customizableProperty: nil /* currently unsupported */ ) - } - - static var rotationY: LayerProperty { - .init( - caLayerKeypath: "transform.rotation.y", - defaultValue: 0, - customizableProperty: nil /* currently unsupported */ ) - } - - static var rotationZ: LayerProperty { - .init( - caLayerKeypath: "transform.rotation.z", - defaultValue: 0, - customizableProperty: .rotation) - } - - static var anchorPoint: LayerProperty { - .init( - caLayerKeypath: #keyPath(CALayer.anchorPoint), - // This is intentionally not `GGPoint(x: 0.5, y: 0.5)` (the actual default) - // to opt `anchorPoint` out of the KVC `setValue` flow, which causes issues. - defaultValue: nil, - customizableProperty: nil /* currently unsupported */ ) - } - - static var opacity: LayerProperty { - .init( - caLayerKeypath: #keyPath(CALayer.opacity), - defaultValue: 1, - customizableProperty: .opacity) - } - - static var isHidden: LayerProperty { - .init( - caLayerKeypath: #keyPath(CALayer.isHidden), - defaultValue: false, - customizableProperty: nil /* unsupported */ ) - } - - static var transform: LayerProperty { - .init( - caLayerKeypath: #keyPath(CALayer.transform), - isDefaultValue: { transform in - guard let transform else { return false } - return CATransform3DIsIdentity(transform) - }, - customizableProperty: nil /* currently unsupported */ ) - } - - static var shadowOpacity: LayerProperty { - .init( - caLayerKeypath: #keyPath(CALayer.shadowOpacity), - defaultValue: 0, - customizableProperty: nil /* currently unsupported */ ) - } - - static var shadowColor: LayerProperty { - .init( - caLayerKeypath: #keyPath(CALayer.shadowColor), - defaultValue: .rgb(0, 0, 0), - customizableProperty: nil /* currently unsupported */ ) - } - - static var shadowRadius: LayerProperty { - .init( - caLayerKeypath: #keyPath(CALayer.shadowRadius), - defaultValue: 3.0, - customizableProperty: nil /* currently unsupported */ ) - } - - static var shadowOffset: LayerProperty { - .init( - caLayerKeypath: #keyPath(CALayer.shadowOffset), - defaultValue: CGSize(width: 0, height: -3.0), - customizableProperty: nil /* currently unsupported */ ) - } -} - -// MARK: CAShapeLayer properties - -extension LayerProperty { - static var path: LayerProperty { - .init( - caLayerKeypath: #keyPath(CAShapeLayer.path), - defaultValue: nil, - customizableProperty: nil /* currently unsupported */ ) - } - - static var fillColor: LayerProperty { - .init( - caLayerKeypath: #keyPath(CAShapeLayer.fillColor), - defaultValue: nil, - customizableProperty: .color) - } - - static var lineWidth: LayerProperty { - .init( - caLayerKeypath: #keyPath(CAShapeLayer.lineWidth), - defaultValue: 1, - customizableProperty: .floatValue(.strokeWidth)) - } - - static var lineDashPhase: LayerProperty { - .init( - caLayerKeypath: #keyPath(CAShapeLayer.lineDashPhase), - defaultValue: 0, - customizableProperty: nil /* currently unsupported */ ) - } - - static var strokeColor: LayerProperty { - .init( - caLayerKeypath: #keyPath(CAShapeLayer.strokeColor), - defaultValue: nil, - customizableProperty: .color) - } - - static var strokeStart: LayerProperty { - .init( - caLayerKeypath: #keyPath(CAShapeLayer.strokeStart), - defaultValue: 0, - customizableProperty: nil /* currently unsupported */ ) - } - - static var strokeEnd: LayerProperty { - .init( - caLayerKeypath: #keyPath(CAShapeLayer.strokeEnd), - defaultValue: 1, - customizableProperty: nil /* currently unsupported */ ) - } -} - -// MARK: CAGradientLayer properties - -extension LayerProperty { - static var colors: LayerProperty<[CGColor]> { - .init( - caLayerKeypath: #keyPath(CAGradientLayer.colors), - defaultValue: nil, - customizableProperty: .gradientColors) - } - - static var locations: LayerProperty<[CGFloat]> { - .init( - caLayerKeypath: #keyPath(CAGradientLayer.locations), - defaultValue: nil, - customizableProperty: .gradientLocations) - } - - static var startPoint: LayerProperty { - .init( - caLayerKeypath: #keyPath(CAGradientLayer.startPoint), - defaultValue: nil, - customizableProperty: nil /* currently unsupported */ ) - } - - static var endPoint: LayerProperty { - .init( - caLayerKeypath: #keyPath(CAGradientLayer.endPoint), - defaultValue: nil, - customizableProperty: nil /* currently unsupported */ ) - } -} - -// MARK: - CustomizableProperty types - -extension CustomizableProperty { - static var color: CustomizableProperty { - .init( - name: [.color], - conversion: { typeErasedValue, _ in - guard let color = typeErasedValue as? LottieColor else { - return nil - } - - return .rgba(CGFloat(color.r), CGFloat(color.g), CGFloat(color.b), CGFloat(color.a)) - }) - } - - static var opacity: CustomizableProperty { - .init( - name: [.opacity], - conversion: { typeErasedValue, _ in - guard let vector = typeErasedValue as? LottieVector1D else { return nil } - - // Lottie animation files express opacity as a numerical percentage value - // (e.g. 50%, 100%, 200%) so we divide by 100 to get the decimal values - // expected by Core Animation (e.g. 0.5, 1.0, 2.0). - return vector.cgFloatValue / 100 - }) - } - - static var scaleX: CustomizableProperty { - .init( - name: [.scale], - conversion: { typeErasedValue, _ in - guard let vector = typeErasedValue as? LottieVector3D else { return nil } - - // Lottie animation files express scale as a numerical percentage value - // (e.g. 50%, 100%, 200%) so we divide by 100 to get the decimal values - // expected by Core Animation (e.g. 0.5, 1.0, 2.0). - return vector.pointValue.x / 100 - }) - } - - static var scaleY: CustomizableProperty { - .init( - name: [.scale], - conversion: { typeErasedValue, _ in - guard let vector = typeErasedValue as? LottieVector3D else { return nil } - - // Lottie animation files express scale as a numerical percentage value - // (e.g. 50%, 100%, 200%) so we divide by 100 to get the decimal values - // expected by Core Animation (e.g. 0.5, 1.0, 2.0). - return vector.pointValue.y / 100 - }) - } - - static var rotation: CustomizableProperty { - .init( - name: [.rotation], - conversion: { typeErasedValue, _ in - guard let vector = typeErasedValue as? LottieVector1D else { return nil } - - // Lottie animation files express rotation in degrees - // (e.g. 90º, 180º, 360º) so we covert to radians to get the - // values expected by Core Animation (e.g. π/2, π, 2π) - return vector.cgFloatValue * .pi / 180 - }) - } - - static var position: CustomizableProperty { - .init( - name: [.position], - conversion: { typeErasedValue, _ in - guard let vector = typeErasedValue as? LottieVector3D else { return nil } - return vector.pointValue - }) - } - - static var gradientColors: CustomizableProperty<[CGColor]> { - .init( - name: [.gradientColors], - conversion: { _, typeErasedValueProvider in - guard let gradientValueProvider = typeErasedValueProvider as? GradientValueProvider else { return nil } - return gradientValueProvider.colors.map { $0.cgColorValue } - }) - } - - static var gradientLocations: CustomizableProperty<[CGFloat]> { - .init( - name: [.gradientColors], - conversion: { _, typeErasedValueProvider in - guard let gradientValueProvider = typeErasedValueProvider as? GradientValueProvider else { return nil } - return gradientValueProvider.locations.map { CGFloat($0) } - }) - } - - static func floatValue(_ name: PropertyName...) -> CustomizableProperty { - .init( - name: name, - conversion: { typeErasedValue, _ in - guard let vector = typeErasedValue as? LottieVector1D else { return nil } - return vector.cgFloatValue - }) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/OpacityAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/OpacityAnimation.swift deleted file mode 100644 index b7bf2200eb3acd540cb8139550067b35d3fe18f3..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/OpacityAnimation.swift +++ /dev/null @@ -1,52 +0,0 @@ -// Created by Cal Stephens on 5/17/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - OpacityAnimationModel - -protocol OpacityAnimationModel { - /// The opacity animation to apply to a `CALayer` - var opacity: KeyframeGroup { get } -} - -// MARK: - Transform + OpacityAnimationModel - -extension Transform: OpacityAnimationModel { } - -// MARK: - ShapeTransform + OpacityAnimationModel - -extension ShapeTransform: OpacityAnimationModel { } - -// MARK: - Fill + OpacityAnimationModel - -extension Fill: OpacityAnimationModel { } - -// MARK: - GradientFill + OpacityAnimationModel - -extension GradientFill: OpacityAnimationModel { } - -// MARK: - Stroke + OpacityAnimationModel - -extension Stroke: OpacityAnimationModel { } - -// MARK: - GradientStroke + OpacityAnimationModel - -extension GradientStroke: OpacityAnimationModel { } - -extension CALayer { - /// Adds the opacity animation from the given `OpacityAnimationModel` to this layer - @nonobjc - func addOpacityAnimation(for opacity: OpacityAnimationModel, context: LayerAnimationContext) throws { - try addAnimation( - for: .opacity, - keyframes: opacity.opacity, - value: { - // Lottie animation files express opacity as a numerical percentage value - // (e.g. 0%, 50%, 100%) so we divide by 100 to get the decimal values - // expected by Core Animation (e.g. 0.0, 0.5, 1.0). - $0.cgFloatValue / 100 - }, - context: context) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/RectangleAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/RectangleAnimation.swift deleted file mode 100644 index 8c617a67eb40c34f14374966178070c8d9054eab..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/RectangleAnimation.swift +++ /dev/null @@ -1,54 +0,0 @@ -// Created by Cal Stephens on 12/21/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CAShapeLayer { - /// Adds animations for the given `Rectangle` to this `CALayer` - @nonobjc - func addAnimations( - for rectangle: Rectangle, - context: LayerAnimationContext, - pathMultiplier: PathMultiplier, - roundedCorners: RoundedCorners?) - throws - { - try addAnimation( - for: .path, - keyframes: try rectangle.combinedKeyframes(roundedCorners: roundedCorners), - value: { keyframe in - BezierPath.rectangle( - position: keyframe.position.pointValue, - size: keyframe.size.sizeValue, - cornerRadius: keyframe.cornerRadius.cgFloatValue, - direction: rectangle.direction) - .cgPath() - .duplicated(times: pathMultiplier) - }, - context: context) - } -} - -extension Rectangle { - /// Data that represents how to render a rectangle at a specific point in time - struct Keyframe: Interpolatable { - let size: LottieVector3D - let position: LottieVector3D - let cornerRadius: LottieVector1D - - func interpolate(to: Rectangle.Keyframe, amount: CGFloat) -> Rectangle.Keyframe { - Rectangle.Keyframe( - size: size.interpolate(to: to.size, amount: amount), - position: position.interpolate(to: to.position, amount: amount), - cornerRadius: cornerRadius.interpolate(to: to.cornerRadius, amount: amount)) - } - } - - /// Creates a single array of animatable keyframes from the separate arrays of keyframes in this Rectangle - func combinedKeyframes(roundedCorners: RoundedCorners?) throws -> KeyframeGroup { - let cornerRadius = roundedCorners?.radius ?? cornerRadius - return Keyframes.combined( - size, position, cornerRadius, - makeCombinedResult: Rectangle.Keyframe.init) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/ShapeAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/ShapeAnimation.swift deleted file mode 100644 index 0559f29a2f8f1c7af41896d1452f01ec7d49636d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/ShapeAnimation.swift +++ /dev/null @@ -1,236 +0,0 @@ -// Created by Cal Stephens on 1/7/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CAShapeLayer { - /// Adds a `path` animation for the given `ShapeItem` - @nonobjc - func addAnimations( - for shape: ShapeItem, - context: LayerAnimationContext, - pathMultiplier: PathMultiplier, - roundedCorners: RoundedCorners?) - throws - { - switch shape { - case let customShape as Shape: - try addAnimations( - for: customShape.path, - context: context, - pathMultiplier: pathMultiplier, - roundedCorners: roundedCorners) - - case let combinedShape as CombinedShapeItem: - try addAnimations(for: combinedShape, context: context, pathMultiplier: pathMultiplier) - try context.compatibilityAssert(roundedCorners == nil, """ - Rounded corners support is not currently implemented for combined shape items - """) - - case let ellipse as Ellipse: - try addAnimations(for: ellipse, context: context, pathMultiplier: pathMultiplier) - - case let rectangle as Rectangle: - try addAnimations( - for: rectangle, - context: context, - pathMultiplier: pathMultiplier, - roundedCorners: roundedCorners) - - case let star as Star: - try addAnimations(for: star, context: context, pathMultiplier: pathMultiplier) - try context.compatibilityAssert(roundedCorners == nil, """ - Rounded corners support is currently not implemented for polygon items - """) - - default: - // None of the other `ShapeItem` subclasses draw a `path` - try context.logCompatibilityIssue("Unexpected shape type \(type(of: shape))") - return - } - } - - /// Adds a `fillColor` animation for the given `Fill` object - @nonobjc - func addAnimations(for fill: Fill, context: LayerAnimationContext) throws { - fillRule = fill.fillRule.caFillRule - - try addAnimation( - for: .fillColor, - keyframes: fill.color, - value: \.cgColorValue, - context: context) - - try addOpacityAnimation(for: fill, context: context) - } - - /// Adds animations for `strokeStart` and `strokeEnd` from the given `Trim` object - @nonobjc - func addAnimations(for trim: Trim, context: LayerAnimationContext) throws -> PathMultiplier { - let (strokeStartKeyframes, strokeEndKeyframes, pathMultiplier) = try trim.caShapeLayerKeyframes() - - try addAnimation( - for: .strokeStart, - keyframes: strokeStartKeyframes, - value: { strokeStart in - // Lottie animation files express stoke trims as a numerical percentage value - // (e.g. 25%, 50%, 100%) so we divide by 100 to get the decimal values - // expected by Core Animation (e.g. 0.25, 0.5, 1.0). - CGFloat(strokeStart.cgFloatValue) / CGFloat(pathMultiplier) / 100 - }, context: context) - - try addAnimation( - for: .strokeEnd, - keyframes: strokeEndKeyframes, - value: { strokeEnd in - // Lottie animation files express stoke trims as a numerical percentage value - // (e.g. 25%, 50%, 100%) so we divide by 100 to get the decimal values - // expected by Core Animation (e.g. 0.25, 0.5, 1.0). - CGFloat(strokeEnd.cgFloatValue) / CGFloat(pathMultiplier) / 100 - }, context: context) - - return pathMultiplier - } -} - -/// The number of times that a `CGPath` needs to be duplicated in order to support the animation's `Trim` keyframes -typealias PathMultiplier = Int - -extension Trim { - - // MARK: Fileprivate - - /// The `strokeStart` and `strokeEnd` keyframes to apply to a `CAShapeLayer`, - /// plus a `pathMultiplier` that should be applied to the layer's `path` so that - /// trim values larger than 100% can be displayed properly. - fileprivate func caShapeLayerKeyframes() - throws - -> (strokeStart: KeyframeGroup, strokeEnd: KeyframeGroup, pathMultiplier: PathMultiplier) - { - let strokeStart: KeyframeGroup - let strokeEnd: KeyframeGroup - - // CAShapeLayer requires strokeStart to be less than strokeEnd. This - // isn't required by the Lottie schema, so some animations may have - // strokeStart and strokeEnd flipped. - if startValueIsAlwaysLessOrEqualToThanEndValue() { - // If the start value is always _less than_ or equal to the end value - // then we can use the given values without any modifications - strokeStart = start - strokeEnd = end - } else if startValueIsAlwaysGreaterThanOrEqualToEndValue() { - // If the start value is always _greater than_ or equal to the end value, - // then we can just swap the start / end keyframes. This lets us avoid - // manually interpolating the keyframes values at each frame, which - // would be more expensive. - strokeStart = end - strokeEnd = start - } else { - // Otherwise if the start / end values ever swap places we have to - // fix the order on a per-keyframe basis, which may require manually - // interpolating the keyframe values at each frame. - (strokeStart, strokeEnd) = interpolatedAtEachFrame() - } - - // If there are no offsets, then the stroke values can be used as-is - guard - !offset.keyframes.isEmpty, - offset.keyframes.contains(where: { $0.value.cgFloatValue != 0 }) - else { - return (strokeStart, strokeEnd, 1) - } - - // Apply the offset to the start / end values at each frame - let offsetStrokeKeyframes = Keyframes.combined( - strokeStart, - strokeEnd, - offset, - makeCombinedResult: { start, end, offset -> (start: LottieVector1D, end: LottieVector1D) in - // Compute the adjusted value by converting the offset value to a stroke value - let offsetStart = start.cgFloatValue + (offset.cgFloatValue / 360 * 100) - let offsetEnd = end.cgFloatValue + (offset.cgFloatValue / 360 * 100) - return (start: LottieVector1D(offsetStart), end: LottieVector1D(offsetEnd)) - }) - - var adjustedStrokeStart = offsetStrokeKeyframes.map { $0.start } - var adjustedStrokeEnd = offsetStrokeKeyframes.map { $0.end } - - // If maximum stroke value is larger than 100%, then we have to create copies of the path - // so the total path length includes the maximum stroke - let startStrokes = adjustedStrokeStart.keyframes.map { $0.value.cgFloatValue } - let endStrokes = adjustedStrokeEnd.keyframes.map { $0.value.cgFloatValue } - let minimumStrokeMultiplier = Double(floor((startStrokes.min() ?? 0) / 100.0)) - let maximumStrokeMultiplier = Double(ceil((endStrokes.max() ?? 100) / 100.0)) - - if minimumStrokeMultiplier < 0 { - // Core Animation doesn't support negative stroke offsets, so we have to - // shift all of the offset values up by the minimum - adjustedStrokeStart = adjustedStrokeStart.map { LottieVector1D($0.value + (abs(minimumStrokeMultiplier) * 100.0)) } - adjustedStrokeEnd = adjustedStrokeEnd.map { LottieVector1D($0.value + (abs(minimumStrokeMultiplier) * 100.0)) } - } - - return ( - strokeStart: adjustedStrokeStart, - strokeEnd: adjustedStrokeEnd, - pathMultiplier: Int(abs(maximumStrokeMultiplier) + abs(minimumStrokeMultiplier))) - } - - // MARK: Private - - /// Checks whether or not the value for `trim.start` is less than - /// or equal to the value for every `trim.end` at every frame. - private func startValueIsAlwaysLessOrEqualToThanEndValue() -> Bool { - startAndEndValuesAllSatisfy { startValue, endValue in - startValue <= endValue - } - } - - /// Checks whether or not the value for `trim.start` is greater than - /// or equal to the value for every `trim.end` at every frame. - private func startValueIsAlwaysGreaterThanOrEqualToEndValue() -> Bool { - startAndEndValuesAllSatisfy { startValue, endValue in - startValue >= endValue - } - } - - private func startAndEndValuesAllSatisfy(_ condition: (_ start: CGFloat, _ end: CGFloat) -> Bool) -> Bool { - let keyframeTimes = Set(start.keyframes.map { $0.time } + end.keyframes.map { $0.time }) - - let startInterpolator = KeyframeInterpolator(keyframes: start.keyframes) - let endInterpolator = KeyframeInterpolator(keyframes: end.keyframes) - - for keyframeTime in keyframeTimes { - guard - let startAtTime = startInterpolator.value(frame: keyframeTime) as? LottieVector1D, - let endAtTime = endInterpolator.value(frame: keyframeTime) as? LottieVector1D - else { continue } - - if !condition(startAtTime.cgFloatValue, endAtTime.cgFloatValue) { - return false - } - } - - return true - } - - /// Interpolates the start and end keyframes, at each frame if necessary, - /// so that the value of `strokeStart` is always less than `strokeEnd`. - private func interpolatedAtEachFrame() - -> (strokeStart: KeyframeGroup, strokeEnd: KeyframeGroup) - { - let combinedKeyframes = Keyframes.combined( - start, - end, - makeCombinedResult: { startValue, endValue -> (start: LottieVector1D, end: LottieVector1D) in - if startValue.cgFloatValue < endValue.cgFloatValue { - return (start: startValue, end: endValue) - } else { - return (start: endValue, end: startValue) - } - }) - - return ( - strokeStart: combinedKeyframes.map { $0.start }, - strokeEnd: combinedKeyframes.map { $0.end }) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/StarAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/StarAnimation.swift deleted file mode 100644 index 62a762111be7c4f55e9a19da76cb26e716129ddf..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/StarAnimation.swift +++ /dev/null @@ -1,116 +0,0 @@ -// Created by Cal Stephens on 1/10/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CAShapeLayer { - - // MARK: Internal - - /// Adds animations for the given `Rectangle` to this `CALayer` - @nonobjc - func addAnimations( - for star: Star, - context: LayerAnimationContext, - pathMultiplier: PathMultiplier) - throws - { - switch star.starType { - case .star: - try addStarAnimation(for: star, context: context, pathMultiplier: pathMultiplier) - case .polygon: - try addPolygonAnimation(for: star, context: context, pathMultiplier: pathMultiplier) - case .none: - break - } - } - - // MARK: Private - - @nonobjc - private func addStarAnimation( - for star: Star, - context: LayerAnimationContext, - pathMultiplier: PathMultiplier) - throws - { - try addAnimation( - for: .path, - keyframes: try star.combinedKeyframes(), - value: { keyframe in - BezierPath.star( - position: keyframe.position.pointValue, - outerRadius: keyframe.outerRadius.cgFloatValue, - innerRadius: keyframe.innerRadius.cgFloatValue, - outerRoundedness: keyframe.outerRoundness.cgFloatValue, - innerRoundedness: keyframe.innerRoundness.cgFloatValue, - numberOfPoints: keyframe.points.cgFloatValue, - rotation: keyframe.rotation.cgFloatValue, - direction: star.direction) - .cgPath() - .duplicated(times: pathMultiplier) - }, - context: context) - } - - @nonobjc - private func addPolygonAnimation( - for star: Star, - context: LayerAnimationContext, - pathMultiplier: PathMultiplier) - throws - { - try addAnimation( - for: .path, - keyframes: try star.combinedKeyframes(), - value: { keyframe in - BezierPath.polygon( - position: keyframe.position.pointValue, - numberOfPoints: keyframe.points.cgFloatValue, - outerRadius: keyframe.outerRadius.cgFloatValue, - outerRoundedness: keyframe.outerRoundness.cgFloatValue, - rotation: keyframe.rotation.cgFloatValue, - direction: star.direction) - .cgPath() - .duplicated(times: pathMultiplier) - }, - context: context) - } -} - -extension Star { - /// Data that represents how to render a star at a specific point in time - struct Keyframe: Interpolatable { - let position: LottieVector3D - let outerRadius: LottieVector1D - let innerRadius: LottieVector1D - let outerRoundness: LottieVector1D - let innerRoundness: LottieVector1D - let points: LottieVector1D - let rotation: LottieVector1D - - func interpolate(to: Star.Keyframe, amount: CGFloat) -> Star.Keyframe { - Star.Keyframe( - position: position.interpolate(to: to.position, amount: amount), - outerRadius: outerRadius.interpolate(to: to.outerRadius, amount: amount), - innerRadius: innerRadius.interpolate(to: to.innerRadius, amount: amount), - outerRoundness: outerRoundness.interpolate(to: to.outerRoundness, amount: amount), - innerRoundness: innerRoundness.interpolate(to: to.innerRoundness, amount: amount), - points: points.interpolate(to: to.points, amount: amount), - rotation: rotation.interpolate(to: to.rotation, amount: amount)) - } - } - - /// Creates a single array of animatable keyframes from the separate arrays of keyframes in this star/polygon - func combinedKeyframes() throws -> KeyframeGroup { - Keyframes.combined( - position, - outerRadius, - innerRadius ?? KeyframeGroup(LottieVector1D(0)), - outerRoundness, - innerRoundness ?? KeyframeGroup(LottieVector1D(0)), - points, - rotation, - makeCombinedResult: Star.Keyframe.init) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/StrokeAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/StrokeAnimation.swift deleted file mode 100644 index 92b5e4a18b776bce70e85cbd8e0813f27dfc72bb..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/StrokeAnimation.swift +++ /dev/null @@ -1,86 +0,0 @@ -// Created by Cal Stephens on 2/10/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - StrokeShapeItem - -/// A `ShapeItem` that represents a stroke -protocol StrokeShapeItem: ShapeItem, OpacityAnimationModel { - var strokeColor: KeyframeGroup? { get } - var width: KeyframeGroup { get } - var lineCap: LineCap { get } - var lineJoin: LineJoin { get } - var miterLimit: Double { get } - var dashPattern: [DashElement]? { get } - func copy(width: KeyframeGroup) -> StrokeShapeItem -} - -// MARK: - Stroke + StrokeShapeItem - -extension Stroke: StrokeShapeItem { - var strokeColor: KeyframeGroup? { color } - - func copy(width: KeyframeGroup) -> StrokeShapeItem { - // Type-erase the copy from `Stroke` to `StrokeShapeItem` - let copy: Stroke = copy(width: width) - return copy - } -} - -// MARK: - GradientStroke + StrokeShapeItem - -extension GradientStroke: StrokeShapeItem { - var strokeColor: KeyframeGroup? { nil } - - func copy(width: KeyframeGroup) -> StrokeShapeItem { - // Type-erase the copy from `GradientStroke` to `StrokeShapeItem` - let copy: GradientStroke = copy(width: width) - return copy - } -} - -// MARK: - CAShapeLayer + StrokeShapeItem - -extension CAShapeLayer { - /// Adds animations for properties related to the given `Stroke` object (`strokeColor`, `lineWidth`, etc) - @nonobjc - func addStrokeAnimations(for stroke: StrokeShapeItem, context: LayerAnimationContext) throws { - lineJoin = stroke.lineJoin.caLineJoin - lineCap = stroke.lineCap.caLineCap - miterLimit = CGFloat(stroke.miterLimit) - - if let strokeColor = stroke.strokeColor { - try addAnimation( - for: .strokeColor, - keyframes: strokeColor, - value: \.cgColorValue, - context: context) - } - - try addAnimation( - for: .lineWidth, - keyframes: stroke.width, - value: \.cgFloatValue, - context: context) - - try addOpacityAnimation(for: stroke, context: context) - - if let (dashPattern, dashPhase) = stroke.dashPattern?.shapeLayerConfiguration { - let lineDashPattern = try dashPattern.map { - try KeyframeGroup(keyframes: $0) - .exactlyOneKeyframe(context: context, description: "stroke dashPattern").cgFloatValue - } - - if lineDashPattern.isSupportedLayerDashPattern { - self.lineDashPattern = lineDashPattern as [NSNumber] - } - - try addAnimation( - for: .lineDashPhase, - keyframes: KeyframeGroup(keyframes: dashPhase), - value: \.cgFloatValue, - context: context) - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/TransformAnimations.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/TransformAnimations.swift deleted file mode 100644 index b9f69d605c12e1d39e72df5fd973638579e2f641..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/TransformAnimations.swift +++ /dev/null @@ -1,343 +0,0 @@ -// Created by Cal Stephens on 12/17/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - TransformModel - -/// This protocol mirrors the interface of `Transform`, -/// but is also implemented by `ShapeTransform` to allow -/// both transform types to share the same animation implementation. -protocol TransformModel { - /// The anchor point of the transform. - var anchorPoint: KeyframeGroup { get } - - /// The position of the transform. This is nil if the position data was split. - var _position: KeyframeGroup? { get } - - /// The positionX of the transform. This is nil if the position property is set. - var _positionX: KeyframeGroup? { get } - - /// The positionY of the transform. This is nil if the position property is set. - var _positionY: KeyframeGroup? { get } - - /// The scale of the transform - var scale: KeyframeGroup { get } - - /// The rotation of the transform on X axis. - var rotationX: KeyframeGroup { get } - - /// The rotation of the transform on Y axis. - var rotationY: KeyframeGroup { get } - - /// The rotation of the transform on Z axis. - var rotationZ: KeyframeGroup { get } - - /// The skew of the transform (only present on `ShapeTransform`s) - var _skew: KeyframeGroup? { get } - - /// The skew axis of the transform (only present on `ShapeTransform`s) - var _skewAxis: KeyframeGroup? { get } -} - -// MARK: - Transform + TransformModel - -extension Transform: TransformModel { - var _position: KeyframeGroup? { position } - var _positionX: KeyframeGroup? { positionX } - var _positionY: KeyframeGroup? { positionY } - var _skew: KeyframeGroup? { nil } - var _skewAxis: KeyframeGroup? { nil } -} - -// MARK: - ShapeTransform + TransformModel - -extension ShapeTransform: TransformModel { - var anchorPoint: KeyframeGroup { anchor } - var _position: KeyframeGroup? { position } - var _positionX: KeyframeGroup? { nil } - var _positionY: KeyframeGroup? { nil } - var _skew: KeyframeGroup? { skew } - var _skewAxis: KeyframeGroup? { skewAxis } -} - -// MARK: - CALayer + TransformModel - -extension CALayer { - - // MARK: Internal - - /// Adds transform-related animations from the given `TransformModel` to this layer - /// - This _doesn't_ apply `transform.opacity`, which has to be handled separately - /// since child layers don't inherit the `opacity` of their parent. - @nonobjc - func addTransformAnimations( - for transformModel: TransformModel, - context: LayerAnimationContext) - throws - { - if - // CALayers don't support animating skew with its own set of keyframes. - // If the transform includes a skew, we have to combine all of the transform - // components into a single set of keyframes. - transformModel.hasSkew - // Negative `scale.x` values aren't applied correctly by Core Animation when animating - // `transform.scale.x` and `transform.scale.y` using separate `CAKeyframeAnimation`s - // (https://openradar.appspot.com/FB9862872). If the transform includes negative `scale.x` - // values, we have to combine all of the transform components into a single set of keyframes. - || transformModel.hasNegativeXScaleValues - { - try addCombinedTransformAnimation(for: transformModel, context: context) - } - - else { - try addPositionAnimations(from: transformModel, context: context) - try addAnchorPointAnimation(from: transformModel, context: context) - try addScaleAnimations(from: transformModel, context: context) - try addRotationAnimations(from: transformModel, context: context) - } - } - - // MARK: Private - - @nonobjc - private func addPositionAnimations( - from transformModel: TransformModel, - context: LayerAnimationContext) - throws - { - if let positionKeyframes = transformModel._position { - try addAnimation( - for: .position, - keyframes: positionKeyframes, - value: \.pointValue, - context: context) - } else if - let xKeyframes = transformModel._positionX, - let yKeyframes = transformModel._positionY - { - try addAnimation( - for: .positionX, - keyframes: xKeyframes, - value: \.cgFloatValue, - context: context) - - try addAnimation( - for: .positionY, - keyframes: yKeyframes, - value: \.cgFloatValue, - context: context) - } else { - try context.logCompatibilityIssue(""" - `Transform` values must provide either `position` or `positionX` / `positionY` keyframes - """) - } - } - - @nonobjc - private func addAnchorPointAnimation( - from transformModel: TransformModel, - context: LayerAnimationContext) - throws - { - try addAnimation( - for: .anchorPoint, - keyframes: transformModel.anchorPoint, - value: { absoluteAnchorPoint in - guard bounds.width > 0, bounds.height > 0 else { - context.logger.assertionFailure("Size must be non-zero before an animation can be played") - return .zero - } - - // Lottie animation files express anchorPoint as an absolute point value, - // so we have to divide by the width/height of this layer to get the - // relative decimal values expected by Core Animation. - return CGPoint( - x: CGFloat(absoluteAnchorPoint.x) / bounds.width, - y: CGFloat(absoluteAnchorPoint.y) / bounds.height) - }, - context: context) - } - - @nonobjc - private func addScaleAnimations( - from transformModel: TransformModel, - context: LayerAnimationContext) - throws - { - try addAnimation( - for: .scaleX, - keyframes: transformModel.scale, - value: { scale in - // Lottie animation files express scale as a numerical percentage value - // (e.g. 50%, 100%, 200%) so we divide by 100 to get the decimal values - // expected by Core Animation (e.g. 0.5, 1.0, 2.0). - CGFloat(scale.x) / 100 - }, - context: context) - - try addAnimation( - for: .scaleY, - keyframes: transformModel.scale, - value: { scale in - // Lottie animation files express scale as a numerical percentage value - // (e.g. 50%, 100%, 200%) so we divide by 100 to get the decimal values - // expected by Core Animation (e.g. 0.5, 1.0, 2.0). - CGFloat(scale.y) / 100 - }, - context: context) - } - - private func addRotationAnimations( - from transformModel: TransformModel, - context: LayerAnimationContext) - throws - { - let containsXRotationValues = transformModel.rotationX.keyframes.contains(where: { $0.value.cgFloatValue != 0 }) - let containsYRotationValues = transformModel.rotationY.keyframes.contains(where: { $0.value.cgFloatValue != 0 }) - - // When `rotation.x` or `rotation.y` is used, it doesn't render property in test snapshots - // but do renders correctly on the simulator / device - if TestHelpers.snapshotTestsAreRunning { - if containsXRotationValues { - context.logger.warn(""" - `rotation.x` values are not displayed correctly in snapshot tests - """) - } - - if containsYRotationValues { - context.logger.warn(""" - `rotation.y` values are not displayed correctly in snapshot tests - """) - } - } - - // Lottie animation files express rotation in degrees - // (e.g. 90º, 180º, 360º) so we convert to radians to get the - // values expected by Core Animation (e.g. π/2, π, 2π) - - try addAnimation( - for: .rotationX, - keyframes: transformModel.rotationX, - value: { rotationDegrees in - rotationDegrees.cgFloatValue * .pi / 180 - }, - context: context) - - try addAnimation( - for: .rotationY, - keyframes: transformModel.rotationY, - value: { rotationDegrees in - rotationDegrees.cgFloatValue * .pi / 180 - }, - context: context) - - try addAnimation( - for: .rotationZ, - keyframes: transformModel.rotationZ, - value: { rotationDegrees in - // Lottie animation files express rotation in degrees - // (e.g. 90º, 180º, 360º) so we convert to radians to get the - // values expected by Core Animation (e.g. π/2, π, 2π) - rotationDegrees.cgFloatValue * .pi / 180 - }, - context: context) - } - - /// Adds an animation for the entire `transform` key by combining all of the - /// position / size / rotation / skew animations into a single set of keyframes. - /// This is more expensive that animating each component separately, since - /// it may require manually interpolating the keyframes at each frame. - private func addCombinedTransformAnimation( - for transformModel: TransformModel, - context: LayerAnimationContext) - throws - { - let requiresManualInterpolation = - // Core Animation doesn't animate skew changes properly. If the skew value - // changes over the course of the animation then we have to manually - // compute the `CATransform3D` for each frame individually. - transformModel.hasSkewAnimation - // `addAnimation` requires that we use an `Interpolatable` value, but we can't interpolate a `CATransform3D`. - // Since this is only necessary when using `complexTimeRemapping`, we can avoid this by manually interpolating - // when `context.mustUseComplexTimeRemapping` is true and just returning a `Hold` container. - // Since our keyframes are already manually interpolated, they won't need to be interpolated again. - || context.mustUseComplexTimeRemapping - - let combinedTransformKeyframes = Keyframes.combined( - transformModel.anchorPoint, - transformModel._position ?? KeyframeGroup(LottieVector3D(x: 0.0, y: 0.0, z: 0.0)), - transformModel._positionX ?? KeyframeGroup(LottieVector1D(0)), - transformModel._positionY ?? KeyframeGroup(LottieVector1D(0)), - transformModel.scale, - transformModel.rotationX, - transformModel.rotationY, - transformModel.rotationZ, - transformModel._skew ?? KeyframeGroup(LottieVector1D(0)), - transformModel._skewAxis ?? KeyframeGroup(LottieVector1D(0)), - requiresManualInterpolation: requiresManualInterpolation, - makeCombinedResult: { - anchor, position, positionX, positionY, scale, rotationX, rotationY, rotationZ, skew, skewAxis - -> Hold in - - let transformPosition: CGPoint - if transformModel._positionX != nil, transformModel._positionY != nil { - transformPosition = CGPoint(x: positionX.cgFloatValue, y: positionY.cgFloatValue) - } else { - transformPosition = position.pointValue - } - - let transform = CATransform3D.makeTransform( - anchor: anchor.pointValue, - position: transformPosition, - scale: scale.sizeValue, - rotationX: rotationX.cgFloatValue, - rotationY: rotationY.cgFloatValue, - rotationZ: rotationZ.cgFloatValue, - skew: skew.cgFloatValue, - skewAxis: skewAxis.cgFloatValue) - - return Hold(value: transform) - }) - - try addAnimation( - for: .transform, - keyframes: combinedTransformKeyframes, - value: { $0.value }, - context: context) - } - -} - -extension TransformModel { - /// Whether or not this transform has a non-zero skew value - var hasSkew: Bool { - guard - let _skew, - let _skewAxis, - !_skew.keyframes.isEmpty, - !_skewAxis.keyframes.isEmpty - else { - return false - } - - return _skew.keyframes.contains(where: { $0.value.cgFloatValue != 0 }) - } - - /// Whether or not this transform has a non-zero skew value which animates - var hasSkewAnimation: Bool { - guard - hasSkew, - let _skew, - let _skewAxis - else { return false } - - return _skew.keyframes.count > 1 - || _skewAxis.keyframes.count > 1 - } - - /// Whether or not this `TransformModel` has any negative X scale values - var hasNegativeXScaleValues: Bool { - scale.keyframes.contains(where: { $0.value.x < 0 }) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/VisibilityAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/VisibilityAnimation.swift deleted file mode 100644 index 7d6c4b71ea1ac5b7c396c7dac7a69f7094124c73..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Animations/VisibilityAnimation.swift +++ /dev/null @@ -1,63 +0,0 @@ -// Created by Cal Stephens on 12/21/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CALayer { - /// Adds an animation for the given `inTime` and `outTime` to this `CALayer` - @nonobjc - func addVisibilityAnimation( - inFrame: AnimationFrameTime, - outFrame: AnimationFrameTime, - context: LayerAnimationContext) - throws - { - /// If this layer uses `complexTimeRemapping`, use the `addAnimation` codepath - /// which uses `Keyframes.manuallyInterpolatedWithTimeRemapping`. - if context.mustUseComplexTimeRemapping { - let isHiddenKeyframes = KeyframeGroup(keyframes: [ - Keyframe(value: true, time: 0, isHold: true), // hidden, before `inFrame` - Keyframe(value: false, time: inFrame, isHold: true), // visible - Keyframe(value: true, time: outFrame, isHold: true), // hidden, after `outFrame` - ]) - - try addAnimation( - for: .isHidden, - keyframes: isHiddenKeyframes.map { Hold(value: $0) }, - value: { $0.value }, - context: context) - } - - /// Otherwise continue using the legacy codepath that doesn't support complex time remapping. - /// - TODO: We could remove this codepath in favor of always using the simpler codepath above, - /// but would have to solve https://github.com/airbnb/lottie-ios/pull/2254 for that codepath. - else { - let animation = CAKeyframeAnimation(keyPath: #keyPath(isHidden)) - animation.calculationMode = .discrete - - animation.values = [ - true, // hidden, before `inFrame` - false, // visible - true, // hidden, after `outFrame` - ] - - // From the documentation of `keyTimes`: - // - If the calculationMode is set to discrete, the first value in the array - // must be 0.0 and the last value must be 1.0. The array should have one more - // entry than appears in the values array. For example, if there are two values, - // there should be three key times. - animation.keyTimes = [ - NSNumber(value: 0.0), - NSNumber(value: max(Double(try context.progressTime(for: inFrame)), 0)), - // Anything visible during the last frame should stay visible until the absolute end of the animation. - // - This matches the behavior of the main thread rendering engine. - context.simpleTimeRemapping(outFrame) == context.animation.endFrame - ? NSNumber(value: Double(1.0)) - : NSNumber(value: min(Double(try context.progressTime(for: outFrame)), 1)), - NSNumber(value: 1.0), - ] - - add(animation, timedWith: context) - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/CompatibilityTracker.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/CompatibilityTracker.swift deleted file mode 100644 index ce7e09793ee8e8314e1565808edc7d8ec14be40d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/CompatibilityTracker.swift +++ /dev/null @@ -1,130 +0,0 @@ -// Created by Cal Stephens on 5/4/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -// MARK: - CompatibilityIssue - -/// A compatibility issue that was encountered while setting up an animation with the Core Animation engine -struct CompatibilityIssue: CustomStringConvertible { - let message: String - let context: String - - var description: String { - "[\(context)] \(message)" - } -} - -// MARK: - CompatibilityTracker - -/// A type that tracks whether or not an animation is compatible with the Core Animation engine -final class CompatibilityTracker { - - // MARK: Lifecycle - - init(mode: Mode, logger: LottieLogger) { - self.mode = mode - self.logger = logger - } - - // MARK: Internal - - /// How compatibility issues should be handled - enum Mode { - /// When a compatibility issue is encountered, an error will be thrown immediately, - /// aborting the animation setup process as soon as possible. - case abort - - /// When a compatibility issue is encountered, it is stored in `CompatibilityTracker.issues` - case track - } - - enum Error: Swift.Error { - case encounteredCompatibilityIssue(CompatibilityIssue) - } - - /// Records a compatibility issue that will be reported according to `CompatibilityTracker.Mode` - func logIssue(message: String, context: String) throws { - logger.assert(!context.isEmpty, "Compatibility issue context is unexpectedly empty") - - let issue = CompatibilityIssue( - // Compatibility messages are usually written in source files using multi-line strings, - // but converting them to be a single line makes it easier to read the ultimate log output. - message: message.replacingOccurrences(of: "\n", with: " "), - context: context) - - switch mode { - case .abort: - throw CompatibilityTracker.Error.encounteredCompatibilityIssue(issue) - case .track: - issues.append(issue) - } - } - - /// Asserts that a condition is true, otherwise logs a compatibility issue that will be reported - /// according to `CompatibilityTracker.Mode` - func assert( - _ condition: Bool, - _ message: @autoclosure () -> String, - context: @autoclosure () -> String) - throws - { - if !condition { - try logIssue(message: message(), context: context()) - } - } - - /// Reports the compatibility issues that were recorded when setting up the animation, - /// and clears the set of tracked issues. - func reportCompatibilityIssues(_ handler: ([CompatibilityIssue]) -> Void) { - handler(issues) - issues = [] - } - - // MARK: Private - - private let mode: Mode - private let logger: LottieLogger - - /// Compatibility issues encountered while setting up the animation - private var issues = [CompatibilityIssue]() - -} - -// MARK: - CompatibilityTrackerProviding - -protocol CompatibilityTrackerProviding { - var compatibilityTracker: CompatibilityTracker { get } - var compatibilityIssueContext: String { get } -} - -extension CompatibilityTrackerProviding { - /// Records a compatibility issue that will be reported according to `CompatibilityTracker.Mode` - func logCompatibilityIssue(_ message: String) throws { - try compatibilityTracker.logIssue(message: message, context: compatibilityIssueContext) - } - - /// Asserts that a condition is true, otherwise logs a compatibility issue that will be reported - /// according to `CompatibilityTracker.Mode` - func compatibilityAssert( - _ condition: Bool, - _ message: @autoclosure () -> String) - throws - { - try compatibilityTracker.assert(condition, message(), context: compatibilityIssueContext) - } -} - -// MARK: - LayerContext + CompatibilityTrackerProviding - -extension LayerContext: CompatibilityTrackerProviding { - var compatibilityIssueContext: String { - layerName - } -} - -// MARK: - LayerAnimationContext + CompatibilityTrackerProviding - -extension LayerAnimationContext: CompatibilityTrackerProviding { - var compatibilityIssueContext: String { - currentKeypath.fullPath - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/CoreAnimationLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/CoreAnimationLayer.swift deleted file mode 100644 index 8389dd5600b92cc6f41e16cb6ee54e9e598f601a..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/CoreAnimationLayer.swift +++ /dev/null @@ -1,584 +0,0 @@ -// Created by Cal Stephens on 12/13/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - CoreAnimationLayer - -/// The root `CALayer` of the Core Animation rendering engine -final class CoreAnimationLayer: BaseAnimationLayer { - - // MARK: Lifecycle - - /// Initializes a `CALayer` that renders the given animation using `CAAnimation`s. - /// - This initializer is throwing, but will only throw when using - /// `CompatibilityTracker.Mode.abort`. - init( - animation: LottieAnimation, - imageProvider: AnimationImageProvider, - textProvider: AnimationKeypathTextProvider, - fontProvider: AnimationFontProvider, - maskAnimationToBounds: Bool, - compatibilityTrackerMode: CompatibilityTracker.Mode, - logger: LottieLogger) - throws - { - self.animation = animation - self.imageProvider = imageProvider - self.textProvider = textProvider - self.fontProvider = fontProvider - self.logger = logger - compatibilityTracker = CompatibilityTracker(mode: compatibilityTrackerMode, logger: logger) - valueProviderStore = ValueProviderStore(logger: logger) - super.init() - masksToBounds = maskAnimationToBounds - setup() - try setupChildLayers() - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("init(layer:) incorrectly called with \(type(of: layer))") - } - - animation = typedLayer.animation - currentAnimationConfiguration = typedLayer.currentAnimationConfiguration - imageProvider = typedLayer.imageProvider - textProvider = typedLayer.textProvider - fontProvider = typedLayer.fontProvider - didSetUpAnimation = typedLayer.didSetUpAnimation - compatibilityTracker = typedLayer.compatibilityTracker - logger = typedLayer.logger - valueProviderStore = typedLayer.valueProviderStore - super.init(layer: typedLayer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - /// Timing-related configuration to apply to this layer's child `CAAnimation`s - /// - This is effectively a configurable subset of `CAMediaTiming` - struct CAMediaTimingConfiguration: Equatable { - var autoreverses = false - var repeatCount: Float = 0 - var speed: Float = 1 - var timeOffset: TimeInterval = 0 - } - - enum PlaybackState: Equatable { - /// The animation is has started playing, and may still be playing. - /// - When animating with a finite duration (e.g. `playOnce`), playback - /// state will still be `playing` when the animation completes. - /// To check if the animation is currently playing, prefer `isAnimationPlaying`. - case playing - /// The animation is statically displaying a specific frame - case paused(frame: AnimationFrameTime) - } - - /// Configuration used by the `playAnimation` method - struct AnimationConfiguration: Equatable { - var animationContext: AnimationContext - var timingConfiguration: CAMediaTimingConfiguration - var recordHierarchyKeypath: ((String) -> Void)? - - static func ==(_ lhs: AnimationConfiguration, _ rhs: AnimationConfiguration) -> Bool { - lhs.animationContext == rhs.animationContext - && lhs.timingConfiguration == rhs.timingConfiguration - && ((lhs.recordHierarchyKeypath == nil) == (rhs.recordHierarchyKeypath == nil)) - } - } - - /// The parent `LottieAnimationLayer` that manages this layer - weak var lottieAnimationLayer: LottieAnimationLayer? - - /// A closure that is called after this layer sets up its animation. - /// If the animation setup was unsuccessful and encountered compatibility issues, - /// those issues are included in this call. - var didSetUpAnimation: (([CompatibilityIssue]) -> Void)? - - /// The `AnimationImageProvider` that `ImageLayer`s use to retrieve images, - /// referenced by name in the animation json. - var imageProvider: AnimationImageProvider { - didSet { reloadImages() } - } - - /// The `AnimationKeypathTextProvider` that `TextLayer`'s use to retrieve texts, - /// that they should use to render their text context - var textProvider: AnimationKeypathTextProvider { - didSet { - // We need to rebuild the current animation after updating the text provider, - // since this is used in `TextLayer.setupAnimations(context:)` - rebuildCurrentAnimation() - } - } - - /// The `FontProvider` that `TextLayer`s use to retrieve the `CTFont` - /// that they should use to render their text content - var fontProvider: AnimationFontProvider { - didSet { reloadFonts() } - } - - /// Queues the animation with the given timing configuration - /// to begin playing at the next `display()` call. - /// - This batches together animations so that even if `playAnimation` - /// is called multiple times in the same run loop cycle, the animation - /// will only be set up a single time. - func playAnimation( - configuration: AnimationConfiguration, - playbackState: PlaybackState = .playing) - { - pendingAnimationConfiguration = ( - animationConfiguration: configuration, - playbackState: playbackState) - - setNeedsDisplay() - } - - override func layoutSublayers() { - super.layoutSublayers() - - // If no animation has been set up yet, display the first frame - // now that the layer hierarchy has been setup and laid out - if - pendingAnimationConfiguration == nil, - currentAnimationConfiguration == nil, - bounds.size != .zero - { - currentFrame = animation.frameTime(forProgress: animationProgress) - } - } - - override func display() { - // We intentionally don't call `super.display()`, since this layer - // doesn't directly render any content. - // - This fixes an issue where certain animations would unexpectedly - // allocate a very large amount of memory (400mb+). - // - Alternatively this layer could subclass `CATransformLayer`, - // but this causes Core Animation to emit unnecessary logs. - if var pendingAnimationConfiguration { - pendingAnimationConfigurationModification?(&pendingAnimationConfiguration.animationConfiguration) - pendingAnimationConfigurationModification = nil - self.pendingAnimationConfiguration = nil - - do { - try setupAnimation(for: pendingAnimationConfiguration.animationConfiguration) - } catch { - if case CompatibilityTracker.Error.encounteredCompatibilityIssue(let compatibilityIssue) = error { - // Even though the animation setup failed, we still update the layer's playback state - // so it can be read by the parent `LottieAnimationView` when handling this error - currentPlaybackState = pendingAnimationConfiguration.playbackState - - didSetUpAnimation?([compatibilityIssue]) - return - } - } - - currentPlaybackState = pendingAnimationConfiguration.playbackState - - compatibilityTracker.reportCompatibilityIssues { compatibilityIssues in - didSetUpAnimation?(compatibilityIssues) - } - } - } - - // MARK: Private - - /// The configuration for the most recent animation which has been - /// queued by calling `playAnimation` but not yet actually set up - private var pendingAnimationConfiguration: ( - animationConfiguration: AnimationConfiguration, - playbackState: PlaybackState)? - - /// A modification that should be applied to the next animation configuration - private var pendingAnimationConfigurationModification: ((inout AnimationConfiguration) -> Void)? - - /// Configuration for the animation that is currently setup in this layer - private var currentAnimationConfiguration: AnimationConfiguration? - - /// The current progress of the placeholder `CAAnimation`, - /// which is also the realtime animation progress of this layer's animation - @objc private var animationProgress: CGFloat = 0 - - private let animation: LottieAnimation - private let valueProviderStore: ValueProviderStore - private let compatibilityTracker: CompatibilityTracker - private let logger: LottieLogger - private let loggingState = LoggingState() - - /// The current playback state of the animation that is displayed in this layer - private var currentPlaybackState: PlaybackState? { - didSet { - guard playbackState != oldValue else { return } - - switch playbackState { - case .playing, nil: - timeOffset = 0 - case .paused(let frame): - timeOffset = animation.time(forFrame: frame) - } - } - } - - /// The current or pending playback state of the animation displayed in this layer - private var playbackState: PlaybackState? { - pendingAnimationConfiguration?.playbackState ?? currentPlaybackState - } - - /// Context used when setting up and configuring sublayers - private var layerContext: LayerContext { - LayerContext( - animation: animation, - imageProvider: imageProvider, - textProvider: textProvider, - fontProvider: fontProvider, - compatibilityTracker: compatibilityTracker, - layerName: "root layer") - } - - private func setup() { - bounds = animation.bounds - } - - private func setupChildLayers() throws { - try setupLayerHierarchy( - for: animation.layers, - context: layerContext) - - try validateReasonableNumberOfTimeRemappingLayers() - } - - /// Immediately builds and begins playing `CAAnimation`s for each sublayer - private func setupAnimation(for configuration: AnimationConfiguration) throws { - // Remove any existing animations from the layer hierarchy - removeAnimations() - - currentAnimationConfiguration = configuration - - let layerContext = LayerAnimationContext( - animation: animation, - timingConfiguration: configuration.timingConfiguration, - startFrame: configuration.animationContext.playFrom, - endFrame: configuration.animationContext.playTo, - valueProviderStore: valueProviderStore, - compatibilityTracker: compatibilityTracker, - logger: logger, - loggingState: loggingState, - currentKeypath: AnimationKeypath(keys: []), - textProvider: textProvider, - recordHierarchyKeypath: configuration.recordHierarchyKeypath) - - // Perform a layout pass if necessary so all of the sublayers - // have the most up-to-date sizing information - layoutIfNeeded() - - // Set the speed of this layer, which will be inherited - // by all sublayers and their animations. - // - This is required to support scrubbing with a speed of 0 - speed = configuration.timingConfiguration.speed - - // Setup a placeholder animation to let us track the realtime animation progress - setupPlaceholderAnimation(context: layerContext) - - // Set up the new animations with the current `TimingConfiguration` - for animationLayer in sublayers ?? [] { - try (animationLayer as? AnimationLayer)?.setupAnimations(context: layerContext) - } - } - - /// Sets up a placeholder `CABasicAnimation` that tracks the current - /// progress of this animation (between 0 and 1). This lets us provide - /// realtime animation progress via `self.currentFrame`. - private func setupPlaceholderAnimation(context: LayerAnimationContext) { - let animationProgressTracker = CABasicAnimation(keyPath: #keyPath(animationProgress)) - animationProgressTracker.fromValue = 0 - animationProgressTracker.toValue = 1 - - let timedProgressAnimation = animationProgressTracker.timed(with: context, for: self) - timedProgressAnimation.delegate = currentAnimationConfiguration?.animationContext.closure - - // Remove the progress animation once complete so we know when the animation - // has finished playing (if it doesn't loop infinitely) - timedProgressAnimation.isRemovedOnCompletion = true - - add(timedProgressAnimation, forKey: #keyPath(animationProgress)) - } - - // Removes the current `CAAnimation`s, and rebuilds new animations - // using the same configuration as the previous animations. - private func rebuildCurrentAnimation() { - guard - // Don't replace any pending animations that are queued to begin - // on the next run loop cycle, since an existing pending animation - // will cause the animation to be rebuilt anyway. - pendingAnimationConfiguration == nil - else { return } - - if isAnimationPlaying == true { - lottieAnimationLayer?.updateInFlightAnimation() - } else { - let currentFrame = currentFrame - removeAnimations() - self.currentFrame = currentFrame - } - } - -} - -// MARK: RootAnimationLayer - -extension CoreAnimationLayer: RootAnimationLayer { - - var primaryAnimationKey: AnimationKey { - .specific(#keyPath(animationProgress)) - } - - /// Whether or not the animation is currently playing. - /// - Handles case where CAAnimations with a finite duration animation (e.g. `playOnce`) - /// have finished playing but still present on this layer. - var isAnimationPlaying: Bool? { - switch pendingAnimationConfiguration?.playbackState { - case .playing: - return true - case .paused: - return false - case nil: - switch playbackState { - case .playing: - return animation(forKey: #keyPath(animationProgress)) != nil - case nil, .paused: - return false - } - } - } - - /// The current frame of the animation being displayed, - /// accounting for the realtime progress of any active CAAnimations. - var currentFrame: AnimationFrameTime { - get { - switch playbackState { - case .paused(let frame): - return frame - - case .playing, nil: - // When in the `playing` state, the animation is either actively playing - // or is completed on the final frame of a non-repeating animation. - // When a non-repeating animation is complete, `animation(forKey: #keyPath(animationProgress))` - // is no longer present and the Core-Animation-managed `animationProgress` value is just 0. - // In that case, since the animation is complete, we just return the final frame that was played to. - let animationCurrentlyPlaying = animation(forKey: #keyPath(animationProgress)) != nil - - if !animationCurrentlyPlaying, let configuration = currentAnimationConfiguration { - return configuration.animationContext.playTo - } else { - return animation.frameTime(forProgress: (presentation() ?? self).animationProgress) - } - } - } - set { - // We can display a specific frame of the animation by setting - // `timeOffset` of this layer. This requires setting up the layer hierarchy - // with a specific configuration (speed=0, etc) at least once. But if - // the layer hierarchy is already set up correctly, we can update the - // `timeOffset` very cheaply. - let requiredAnimationConfiguration = AnimationConfiguration( - animationContext: AnimationContext( - playFrom: animation.startFrame, - // Normal animation playback (like when looping) skips the last frame. - // However when the animation is paused, we need to be able to render the final frame. - // To allow this we have to extend the length of the animation by one frame. - playTo: animation.endFrame + 1, - closure: nil), - timingConfiguration: CAMediaTimingConfiguration(speed: 0)) - - if - pendingAnimationConfiguration == nil, - currentAnimationConfiguration == requiredAnimationConfiguration - { - currentPlaybackState = .paused(frame: newValue) - } - - else { - playAnimation( - configuration: requiredAnimationConfiguration, - playbackState: .paused(frame: newValue)) - } - } - } - - var renderScale: CGFloat { - get { contentsScale } - set { - contentsScale = newValue - - for sublayer in allSublayers { - sublayer.contentsScale = newValue - } - } - } - - var respectAnimationFrameRate: Bool { - get { false } - set { - logger.assertionFailure(""" - The Core Animation rendering engine currently doesn't support `respectAnimationFrameRate`) - """) - } - } - - var _animationLayers: [CALayer] { - (sublayers ?? []).filter { $0 is AnimationLayer } - } - - func reloadImages() { - // When the image provider changes, we have to update all `ImageLayer`s - // so they can query the most up-to-date image from the new image provider. - for sublayer in allSublayers { - if let imageLayer = sublayer as? ImageLayer { - imageLayer.setupImage(context: layerContext) - } - } - } - - func reloadFonts() { - // When the text provider changes, we have to update all `TextLayer`s - // so they can query the most up-to-date font from the new font provider. - for sublayer in allSublayers { - if let textLayer = sublayer as? TextLayer { - try? textLayer.configureRenderLayer(with: layerContext) - } - } - } - - func forceDisplayUpdate() { - // Unimplemented - // - We can't call `display()` here, because it would cause unexpected frame animations: - // https://github.com/airbnb/lottie-ios/issues/2193 - } - - func logHierarchyKeypaths() { - for keypath in allHierarchyKeypaths() { - logger.info(keypath) - } - } - - func allHierarchyKeypaths() -> [String] { - guard pendingAnimationConfiguration?.animationConfiguration ?? currentAnimationConfiguration != nil else { - logger.info("Cannot log hierarchy keypaths until animation has been set up at least once") - return [] - } - - logger.info("Lottie: Rebuilding animation with hierarchy keypath logging enabled") - - var allAnimationKeypaths = [String]() - pendingAnimationConfigurationModification = { configuration in - configuration.recordHierarchyKeypath = { keypath in - allAnimationKeypaths.append(keypath) - } - } - - rebuildCurrentAnimation() - displayIfNeeded() - - return allAnimationKeypaths - } - - func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) { - valueProviderStore.setValueProvider(valueProvider, keypath: keypath) - - // We need to rebuild the current animation after registering a value provider, - // since any existing `CAAnimation`s could now be out of date. - rebuildCurrentAnimation() - } - - func getValue(for _: AnimationKeypath, atFrame _: AnimationFrameTime?) -> Any? { - logger.assertionFailure(""" - The Core Animation rendering engine doesn't support querying values for individual frames - """) - return nil - } - - func getOriginalValue(for _: AnimationKeypath, atFrame _: AnimationFrameTime?) -> Any? { - logger.assertionFailure(""" - The Core Animation rendering engine doesn't support querying values for individual frames - """) - return nil - } - - func layer(for _: AnimationKeypath) -> CALayer? { - logger.assertionFailure(""" - The Core Animation rendering engine doesn't support retrieving `CALayer`s by keypath - """) - return nil - } - - func animatorNodes(for _: AnimationKeypath) -> [AnimatorNode]? { - logger.assertionFailure(""" - The Core Animation rendering engine does not use `AnimatorNode`s - """) - return nil - } - - func removeAnimations() { - currentAnimationConfiguration = nil - currentPlaybackState = nil - removeAllAnimations() - - for sublayer in allSublayers { - sublayer.removeAllAnimations() - } - } - - /// Time remapping in the Core Animation rendering engine requires manually interpolating - /// every frame of every animation. For very large animations with a huge number of layers, - /// this can be prohibitively expensive. - func validateReasonableNumberOfTimeRemappingLayers() throws { - try layerContext.compatibilityAssert( - numberOfLayersWithTimeRemapping < 500, - """ - This animation has a very large number of layers with time remapping (\(numberOfLayersWithTimeRemapping)), - so will perform poorly with the Core Animation rendering engine. - """) - } - -} - -// MARK: - CALayer + allSublayers - -extension CALayer { - /// All of the layers in the layer tree that are descendants from this later - @nonobjc - var allSublayers: [CALayer] { - var allSublayers: [CALayer] = [] - - for sublayer in sublayers ?? [] { - allSublayers.append(sublayer) - allSublayers.append(contentsOf: sublayer.allSublayers) - } - - return allSublayers - } - - /// The number of layers in this layer hierarchy that have a time remapping applied - @nonobjc - var numberOfLayersWithTimeRemapping: Int { - var numberOfSublayersWithTimeRemapping = 0 - - for sublayer in sublayers ?? [] { - if - let preCompLayer = sublayer as? PreCompLayer, - preCompLayer.preCompLayer.timeRemapping != nil - { - numberOfSublayersWithTimeRemapping += preCompLayer.allSublayers.count - } else { - numberOfSublayersWithTimeRemapping += sublayer.numberOfLayersWithTimeRemapping - } - } - - return numberOfSublayersWithTimeRemapping - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/CALayer+fillBounds.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/CALayer+fillBounds.swift deleted file mode 100644 index fe9e9e02683032eb456b3dcb4221f73dd393aa4d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/CALayer+fillBounds.swift +++ /dev/null @@ -1,35 +0,0 @@ -// Created by Cal Stephens on 12/15/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - CALayer + fillBoundsOfSuperlayer - -extension CALayer { - /// Updates the `bounds` of this layer to fill the bounds of its `superlayer` - /// without setting `frame` (which is not permitted if the layer can rotate) - @nonobjc - func fillBoundsOfSuperlayer() { - guard let superlayer else { return } - - if let customLayerLayer = self as? CustomLayoutLayer { - customLayerLayer.layout(superlayerBounds: superlayer.bounds) - } - - else { - // By default the `anchorPoint` of a layer is `CGPoint(x: 0.5, y: 0.5)`. - // Setting it to `.zero` makes the layer have the same coordinate space - // as its superlayer, which lets use use `superlayer.bounds` directly. - anchorPoint = .zero - - bounds = superlayer.bounds - } - } -} - -// MARK: - CustomLayoutLayer - -/// A `CALayer` that sets a custom `bounds` and `anchorPoint` relative to its superlayer -protocol CustomLayoutLayer: CALayer { - func layout(superlayerBounds: CGRect) -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift deleted file mode 100644 index 627d7429367aac0c43bfde0816c00193b793d05d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/KeyframeGroup+exactlyOneKeyframe.swift +++ /dev/null @@ -1,29 +0,0 @@ -// Created by Cal Stephens on 1/11/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -// MARK: - KeyframeGroup + exactlyOneKeyframe - -extension KeyframeGroup { - /// Retrieves the first `Keyframe` from this group, - /// and asserts that there are not any extra keyframes that would be ignored - /// - This should only be used in cases where it's fundamentally not possible to - /// support animating a given property (e.g. if Core Animation itself doesn't - /// support the property). - func exactlyOneKeyframe( - context: CompatibilityTrackerProviding, - description: String, - fileID _: StaticString = #fileID, - line _: UInt = #line) - throws - -> T - { - try context.compatibilityAssert( - keyframes.count == 1, - """ - The Core Animation rendering engine does not support animating multiple keyframes - for \(description) values, due to limitations of Core Animation. - """) - - return keyframes[0].value - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/Keyframes+combined.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/Keyframes+combined.swift deleted file mode 100644 index ceaefd74663e890f77f394ffb5beea9d9466fbf1..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/Keyframes+combined.swift +++ /dev/null @@ -1,328 +0,0 @@ -// Created by Cal Stephens on 1/28/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -// MARK: - Keyframes - -enum Keyframes { - - // MARK: Internal - - /// Combines the given keyframe groups of `Keyframe`s into a single keyframe group of of `Keyframe<[T]>`s - /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged - /// - Otherwise, the keyframes are manually interpolated at each frame in the animation - static func combined( - _ allGroups: [KeyframeGroup], - requiresManualInterpolation: Bool = false) - -> KeyframeGroup<[T]> - where T: AnyInterpolatable - { - Keyframes.combined( - allGroups, - requiresManualInterpolation: requiresManualInterpolation, - makeCombinedResult: { untypedValues in - untypedValues.compactMap { $0 as? T } - }) - } - - /// Combines the given keyframe groups of `Keyframe`s into a single keyframe group of of `Keyframe<[T]>`s - /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged - /// - Otherwise, the keyframes are manually interpolated at each frame in the animation - static func combined( - _ k1: KeyframeGroup, - _ k2: KeyframeGroup, - requiresManualInterpolation: Bool = false, - makeCombinedResult: (T1, T2) throws -> CombinedResult) - rethrows - -> KeyframeGroup - where T1: AnyInterpolatable, T2: AnyInterpolatable - { - try Keyframes.combined( - [k1, k2], - requiresManualInterpolation: requiresManualInterpolation, - makeCombinedResult: { untypedValues in - guard - let t1 = untypedValues[0] as? T1, - let t2 = untypedValues[1] as? T2 - else { return nil } - - return try makeCombinedResult(t1, t2) - }) - } - - /// Combines the given keyframe groups of `Keyframe`s into a single keyframe group of of `Keyframe<[T]>`s - /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged - /// - Otherwise, the keyframes are manually interpolated at each frame in the animation - static func combined( - _ k1: KeyframeGroup, - _ k2: KeyframeGroup, - _ k3: KeyframeGroup, - requiresManualInterpolation: Bool = false, - makeCombinedResult: (T1, T2, T3) -> CombinedResult) - -> KeyframeGroup - where T1: AnyInterpolatable, T2: AnyInterpolatable, T3: AnyInterpolatable - { - Keyframes.combined( - [k1, k2, k3], - requiresManualInterpolation: requiresManualInterpolation, - makeCombinedResult: { untypedValues in - guard - let t1 = untypedValues[0] as? T1, - let t2 = untypedValues[1] as? T2, - let t3 = untypedValues[2] as? T3 - else { return nil } - - return makeCombinedResult(t1, t2, t3) - }) - } - - /// Combines the given keyframe groups of `Keyframe`s into a single keyframe group of of `Keyframe<[T]>`s - /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged - /// - Otherwise, the keyframes are manually interpolated at each frame in the animation - static func combined( - _ k1: KeyframeGroup, - _ k2: KeyframeGroup, - _ k3: KeyframeGroup, - _ k4: KeyframeGroup, - _ k5: KeyframeGroup, - _ k6: KeyframeGroup, - _ k7: KeyframeGroup, - requiresManualInterpolation: Bool = false, - makeCombinedResult: (T1, T2, T3, T4, T5, T6, T7) -> CombinedResult) - -> KeyframeGroup - where T1: AnyInterpolatable, T2: AnyInterpolatable, T3: AnyInterpolatable, T4: AnyInterpolatable, - T5: AnyInterpolatable, T6: AnyInterpolatable, T7: AnyInterpolatable - { - Keyframes.combined( - [k1, k2, k3, k4, k5, k6, k7], - requiresManualInterpolation: requiresManualInterpolation, - makeCombinedResult: { untypedValues in - guard - let t1 = untypedValues[0] as? T1, - let t2 = untypedValues[1] as? T2, - let t3 = untypedValues[2] as? T3, - let t4 = untypedValues[3] as? T4, - let t5 = untypedValues[4] as? T5, - let t6 = untypedValues[5] as? T6, - let t7 = untypedValues[6] as? T7 - else { return nil } - - return makeCombinedResult(t1, t2, t3, t4, t5, t6, t7) - }) - } - - /// Combines the given keyframe groups of `Keyframe`s into a single keyframe group of of `Keyframe<[T]>`s - /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged - /// - Otherwise, the keyframes are manually interpolated at each frame in the animation - static func combined( - _ k1: KeyframeGroup, - _ k2: KeyframeGroup, - _ k3: KeyframeGroup, - _ k4: KeyframeGroup, - _ k5: KeyframeGroup, - _ k6: KeyframeGroup, - _ k7: KeyframeGroup, - _ k8: KeyframeGroup, - requiresManualInterpolation: Bool = false, - makeCombinedResult: (T1, T2, T3, T4, T5, T6, T7, T8) -> CombinedResult) - -> KeyframeGroup - where T1: AnyInterpolatable, T2: AnyInterpolatable, T3: AnyInterpolatable, T4: AnyInterpolatable, - T5: AnyInterpolatable, T6: AnyInterpolatable, T7: AnyInterpolatable, T8: AnyInterpolatable - { - Keyframes.combined( - [k1, k2, k3, k4, k5, k6, k7, k8], - requiresManualInterpolation: requiresManualInterpolation, - makeCombinedResult: { untypedValues in - guard - let t1 = untypedValues[0] as? T1, - let t2 = untypedValues[1] as? T2, - let t3 = untypedValues[2] as? T3, - let t4 = untypedValues[3] as? T4, - let t5 = untypedValues[4] as? T5, - let t6 = untypedValues[5] as? T6, - let t7 = untypedValues[6] as? T7, - let t8 = untypedValues[7] as? T8 - else { return nil } - - return makeCombinedResult(t1, t2, t3, t4, t5, t6, t7, t8) - }) - } - - /// Combines the given keyframe groups of `Keyframe`s into a single keyframe group of of `Keyframe<[T]>`s - /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged - /// - Otherwise, the keyframes are manually interpolated at each frame in the animation - static func combined( - _ k1: KeyframeGroup, - _ k2: KeyframeGroup, - _ k3: KeyframeGroup, - _ k4: KeyframeGroup, - _ k5: KeyframeGroup, - _ k6: KeyframeGroup, - _ k7: KeyframeGroup, - _ k8: KeyframeGroup, - _ k9: KeyframeGroup, - _ k10: KeyframeGroup, - requiresManualInterpolation: Bool = false, - makeCombinedResult: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> CombinedResult) - -> KeyframeGroup - where T1: AnyInterpolatable, T2: AnyInterpolatable, T3: AnyInterpolatable, T4: AnyInterpolatable, - T5: AnyInterpolatable, T6: AnyInterpolatable, T7: AnyInterpolatable, T8: AnyInterpolatable, - T9: AnyInterpolatable, T10: AnyInterpolatable - { - Keyframes.combined( - [k1, k2, k3, k4, k5, k6, k7, k8, k9, k10], - requiresManualInterpolation: requiresManualInterpolation, - makeCombinedResult: { untypedValues in - guard - let t1 = untypedValues[0] as? T1, - let t2 = untypedValues[1] as? T2, - let t3 = untypedValues[2] as? T3, - let t4 = untypedValues[3] as? T4, - let t5 = untypedValues[4] as? T5, - let t6 = untypedValues[5] as? T6, - let t7 = untypedValues[6] as? T7, - let t8 = untypedValues[7] as? T8, - let t9 = untypedValues[8] as? T9, - let t10 = untypedValues[9] as? T10 - else { return nil } - - return makeCombinedResult(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) - }) - } - - // MARK: Private - - /// Combines the given `[KeyframeGroup]` of `Keyframe`s into a single `KeyframeGroup` of `Keyframe`s - /// - If all of the `KeyframeGroup`s have the exact same animation timing, the keyframes are merged - /// - Otherwise, the keyframes are manually interpolated at each frame in the animation - /// - /// `makeCombinedResult` is a closure that takes an array of keyframe values (with the exact same length as `AnyKeyframeGroup`), - /// casts them to the expected type, and combined them into the final resulting keyframe. - /// - /// `requiresManualInterpolation` determines whether the keyframes must be computed using `Keyframes.manuallyInterpolated`, - /// which interpolates the value at each frame, or if the keyframes can simply be combined. - private static func combined( - _ allGroups: [AnyKeyframeGroup], - requiresManualInterpolation: Bool, - makeCombinedResult: ([Any]) throws -> CombinedResult?) - rethrows - -> KeyframeGroup - { - let untypedGroups = allGroups.map { $0.untyped } - - // Animations with no timing information (e.g. with just a single keyframe) - // can be trivially combined with any other set of keyframes, so we don't need - // to check those. - let animatingKeyframes = untypedGroups.filter { $0.keyframes.count > 1 } - - guard - !requiresManualInterpolation, - !allGroups.isEmpty, - animatingKeyframes.allSatisfy({ $0.hasSameTimingParameters(as: animatingKeyframes[0]) }) - else { - // If the keyframes don't all share the same timing information, - // we have to interpolate the value at each individual frame - return try Keyframes.manuallyInterpolated(allGroups, makeCombinedResult: makeCombinedResult) - } - - var combinedKeyframes = ContiguousArray>() - let baseKeyframes = (animatingKeyframes.first ?? untypedGroups[0]).keyframes - - for index in baseKeyframes.indices { - let baseKeyframe = baseKeyframes[index] - let untypedValues = untypedGroups.map { $0.valueForCombinedKeyframes(at: index) } - - if let combinedValue = try makeCombinedResult(untypedValues) { - combinedKeyframes.append(baseKeyframe.withValue(combinedValue)) - } else { - LottieLogger.shared.assertionFailure(""" - Failed to cast untyped keyframe values to expected type. This is an internal error. - """) - } - } - - return KeyframeGroup(keyframes: combinedKeyframes) - } - - private static func manuallyInterpolated( - _ allGroups: [AnyKeyframeGroup], - makeCombinedResult: ([Any]) throws -> CombinedResult?) - rethrows - -> KeyframeGroup - { - let untypedGroups = allGroups.map { $0.untyped } - let untypedInterpolators = allGroups.map { $0.interpolator } - - let times = untypedGroups.flatMap { $0.keyframes.map { $0.time } } - - let minimumTime = times.min() ?? 0 - let maximumTime = times.max() ?? 0 - - // We disable Core Animation interpolation when using manually interpolated keyframes, - // so we don't animate between these values. To prevent the animation from being choppy - // even at low playback speed, we have to interpolate at a very high fidelity. - let animationLocalTimeRange = stride(from: minimumTime, to: maximumTime, by: 0.1) - - let interpolatedKeyframes = try animationLocalTimeRange.compactMap { localTime -> Keyframe? in - let interpolatedValues = untypedInterpolators.map { interpolator in - interpolator.value(frame: AnimationFrameTime(localTime)) - } - - guard let combinedResult = try makeCombinedResult(interpolatedValues) else { - LottieLogger.shared.assertionFailure(""" - Failed to cast untyped keyframe values to expected type. This is an internal error. - """) - return nil - } - - return Keyframe( - value: combinedResult, - time: AnimationFrameTime(localTime), - // Since we already manually interpolated the keyframes, have Core Animation display - // each value as a static keyframe rather than trying to interpolate between them. - isHold: true) - } - - return KeyframeGroup(keyframes: ContiguousArray(interpolatedKeyframes)) - } - -} - -extension KeyframeGroup { - /// Whether or not all of the keyframes in this `KeyframeGroup` have the same - /// timing parameters as the corresponding keyframe in the other given `KeyframeGroup` - func hasSameTimingParameters(as other: KeyframeGroup) -> Bool { - guard keyframes.count == other.keyframes.count else { - return false - } - - return zip(keyframes, other.keyframes).allSatisfy { - $0.hasSameTimingParameters(as: $1) - } - } -} - -extension Keyframe { - /// Whether or not this keyframe has the same timing parameters as the given keyframe, - /// excluding `spatialInTangent` and `spatialOutTangent`. - fileprivate func hasSameTimingParameters(as other: Keyframe) -> Bool { - time == other.time - && isHold == other.isHold - && inTangent == other.inTangent - && outTangent == other.outTangent - // We intentionally don't compare spatial in/out tangents, - // since those values are only used in very specific cases - // (animating the x/y position of a layer), which aren't ever - // combined in this way. - } -} - -extension KeyframeGroup { - /// The value to use for a combined set of keyframes, for the given index - fileprivate func valueForCombinedKeyframes(at index: Int) -> T { - if keyframes.count == 1 { - return keyframes[0].value - } else { - return keyframes[index].value - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/Keyframes+timeRemapping.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/Keyframes+timeRemapping.swift deleted file mode 100644 index 217e38ddae20b698f5cac997b75b0ac611518666..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Extensions/Keyframes+timeRemapping.swift +++ /dev/null @@ -1,46 +0,0 @@ -// Created by Cal Stephens on 1/8/24. -// Copyright © 2024 Airbnb Inc. All rights reserved. - -extension Keyframes { - /// Manually interpolates the given keyframes, and applies `context.complexTimeRemapping`. - /// - Since `complexTimeRemapping` is a mapping from "global time" to "local time", - /// we have to manually interpolate the keyframes at every frame in the animation. - static func manuallyInterpolatedWithTimeRemapping( - _ keyframes: KeyframeGroup, - context: LayerAnimationContext) - -> KeyframeGroup - { - let minimumTime = context.animation.startFrame - let maximumTime = context.animation.endFrame - let animationLocalTimeRange = stride(from: minimumTime, to: maximumTime, by: 1.0) - - let interpolator = keyframes.interpolator - - // Since potentially many global times can refer to the same local time, - // we can cache and reused these local-time values. - var localTimeCache = [AnimationFrameTime: T]() - - let interpolatedRemappedKeyframes = animationLocalTimeRange.compactMap { globalTime -> Keyframe? in - let remappedLocalTime = context.complexTimeRemapping(globalTime) - - let valueAtRemappedTime: T - if let cachedValue = localTimeCache[remappedLocalTime] { - valueAtRemappedTime = cachedValue - } else if let interpolatedValue = interpolator.value(frame: remappedLocalTime) as? T { - valueAtRemappedTime = interpolatedValue - localTimeCache[remappedLocalTime] = interpolatedValue - } else { - LottieLogger.shared.assertionFailure(""" - Failed to cast untyped keyframe values to expected type. This is an internal error. - """) - return nil - } - - return Keyframe( - value: valueAtRemappedTime, - time: AnimationFrameTime(globalTime)) - } - - return KeyframeGroup(keyframes: ContiguousArray(interpolatedRemappedKeyframes)) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/AnimationLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/AnimationLayer.swift deleted file mode 100644 index e15ae531a214394574e79ebb18c15d00038a75a0..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/AnimationLayer.swift +++ /dev/null @@ -1,169 +0,0 @@ -// Created by Cal Stephens on 12/14/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - AnimationLayer - -/// A type of `CALayer` that can be used in a Lottie animation -/// - Layers backed by a `LayerModel` subclass should subclass `BaseCompositionLayer` -protocol AnimationLayer: CALayer { - /// Instructs this layer to setup its `CAAnimation`s - /// using the given `LayerAnimationContext` - func setupAnimations(context: LayerAnimationContext) throws -} - -// MARK: - LayerAnimationContext - -// Context describing the timing parameters of the current animation -struct LayerAnimationContext { - /// The animation being played - let animation: LottieAnimation - - /// The timing configuration that should be applied to `CAAnimation`s - let timingConfiguration: CoreAnimationLayer.CAMediaTimingConfiguration - - /// The absolute frame number that this animation begins at - let startFrame: AnimationFrameTime - - /// The absolute frame number that this animation ends at - let endFrame: AnimationFrameTime - - /// The set of custom Value Providers applied to this animation - let valueProviderStore: ValueProviderStore - - /// Information about whether or not an animation is compatible with the Core Animation engine - let compatibilityTracker: CompatibilityTracker - - /// The logger that should be used for assertions and warnings - let logger: LottieLogger - - /// Mutable state related to log events, stored on the `CoreAnimationLayer`. - let loggingState: LoggingState - - /// The AnimationKeypath represented by the current layer - var currentKeypath: AnimationKeypath - - /// The `AnimationKeypathTextProvider` - var textProvider: AnimationKeypathTextProvider - - /// Records the given animation keypath so it can be logged or collected into a list - /// - Used for `CoreAnimationLayer.logHierarchyKeypaths()` and `allHierarchyKeypaths()` - var recordHierarchyKeypath: ((String) -> Void)? - - /// A closure that remaps the given frame in the child layer's local time to a frame - /// in the animation's overall global time. - /// - This time remapping is simple and only used `preCompLayer.timeStretch` and `preCompLayer.startTime`, - /// so is a trivial function and is invertible. This allows us to invert the time remapping from - /// "global time to local time" to instead be "local time to global time". - private(set) var simpleTimeRemapping: ((_ localTime: AnimationFrameTime) -> AnimationFrameTime) = { $0 } - - /// A complex time remapping closure that remaps the given frame in the animation's overall global time - /// into the child layer's local time. - /// - This time remapping is arbitrarily complex because it includes the full `preCompLayer.timeRemapping`. - /// - Since it isn't possible to invert the time remapping function, this can only be applied by converting - /// from global time to local time. This requires using `Keyframes.manuallyInterpolatedWithTimeRemapping`. - private(set) var complexTimeRemapping: ((_ globalTime: AnimationFrameTime) -> AnimationFrameTime) = { $0 } - - /// Whether or not this layer is required to use the `complexTimeRemapping` via - /// the more expensive `Keyframes.manuallyInterpolatedWithTimeRemapping` codepath. - var mustUseComplexTimeRemapping = false - - /// The duration of the animation - var animationDuration: AnimationFrameTime { - // Normal animation playback (like when looping) skips the last frame. - // However when the animation is paused, we need to be able to render the final frame. - // To allow this we have to extend the length of the animation by one frame. - let animationEndFrame: AnimationFrameTime - if timingConfiguration.speed == 0 { - animationEndFrame = animation.endFrame + 1 - } else { - animationEndFrame = animation.endFrame - } - - return Double(animationEndFrame - animation.startFrame) / animation.framerate - } - - /// Adds the given component string to the `AnimationKeypath` stored - /// that describes the current path being configured by this context value - func addingKeypathComponent(_ component: String) -> LayerAnimationContext { - var context = self - context.currentKeypath.keys.append(component) - return context - } - - /// The `AnimationProgressTime` for the given `AnimationFrameTime` within this layer, - /// accounting for the `simpleTimeRemapping` applied to this layer. - func progressTime(for frame: AnimationFrameTime) throws -> AnimationProgressTime { - try compatibilityAssert( - !mustUseComplexTimeRemapping, - "LayerAnimationContext.time(forFrame:) does not support complex time remapping") - - let animationFrameCount = animationDuration * animation.framerate - return (simpleTimeRemapping(frame) - animation.startFrame) / animationFrameCount - } - - /// The real-time `TimeInterval` for the given `AnimationFrameTime` within this layer, - /// accounting for the `simpleTimeRemapping` applied to this layer. - func time(forFrame frame: AnimationFrameTime) throws -> TimeInterval { - try compatibilityAssert( - !mustUseComplexTimeRemapping, - "LayerAnimationContext.time(forFrame:) does not support complex time remapping") - - return animation.time(forFrame: simpleTimeRemapping(frame)) - } - - /// Chains an additional time remapping closure onto the `simpleTimeRemapping` closure - func withSimpleTimeRemapping( - _ additionalSimpleTimeRemapping: @escaping (_ localTime: AnimationFrameTime) -> AnimationFrameTime) - -> LayerAnimationContext - { - var copy = self - copy.simpleTimeRemapping = { [existingSimpleTimeRemapping = simpleTimeRemapping] time in - existingSimpleTimeRemapping(additionalSimpleTimeRemapping(time)) - } - return copy - } - - /// Chains an additional time remapping closure onto the `complexTimeRemapping` closure. - /// - If `required` is `true`, all subsequent child layers will be required to use the expensive - /// `complexTimeRemapping` / `Keyframes.manuallyInterpolatedWithTimeRemapping` codepath. - /// - `required: true` is necessary when this time remapping is not available via `simpleTimeRemapping`. - func withComplexTimeRemapping( - required: Bool, - _ additionalComplexTimeRemapping: @escaping (_ globalTime: AnimationFrameTime) -> AnimationFrameTime) - -> LayerAnimationContext - { - var copy = self - copy.mustUseComplexTimeRemapping = copy.mustUseComplexTimeRemapping || required - copy.complexTimeRemapping = { [existingComplexTimeRemapping = complexTimeRemapping] time in - additionalComplexTimeRemapping(existingComplexTimeRemapping(time)) - } - return copy - } - - /// Returns a copy of this context with time remapping removed - func withoutTimeRemapping() -> LayerAnimationContext { - var copy = self - copy.simpleTimeRemapping = { $0 } - copy.complexTimeRemapping = { $0 } - copy.mustUseComplexTimeRemapping = false - return copy - } -} - -// MARK: - LoggingState - -/// Mutable state related to log events, stored on the `CoreAnimationLayer`. -final class LoggingState { - - // MARK: Lifecycle - - init() { } - - // MARK: Internal - - /// Whether or not the warning about unsupported After Effects expressions - /// has been logged yet for this layer. - var hasLoggedAfterEffectsExpressionsWarning = false -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/BaseAnimationLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/BaseAnimationLayer.swift deleted file mode 100644 index 06248b20f87dd81d04a733e0773c6f166f847322..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/BaseAnimationLayer.swift +++ /dev/null @@ -1,33 +0,0 @@ -// Created by Cal Stephens on 1/27/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -/// A base `CALayer` that manages the frame and animations -/// of its `sublayers` and `mask` -class BaseAnimationLayer: CALayer, AnimationLayer { - - // MARK: Internal - - override func layoutSublayers() { - super.layoutSublayers() - - for sublayer in managedSublayers { - sublayer.fillBoundsOfSuperlayer() - } - } - - func setupAnimations(context: LayerAnimationContext) throws { - for childAnimationLayer in managedSublayers { - try (childAnimationLayer as? AnimationLayer)?.setupAnimations(context: context) - } - } - - // MARK: Private - - /// All of the sublayers managed by this container - private var managedSublayers: [CALayer] { - (sublayers ?? []) + [mask].compactMap { $0 } - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/BaseCompositionLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/BaseCompositionLayer.swift deleted file mode 100644 index 976580338e0eee51eb02ee3b274a318dbb2ca3a3..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +++ /dev/null @@ -1,110 +0,0 @@ -// Created by Cal Stephens on 12/20/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - BaseCompositionLayer - -/// The base type of `AnimationLayer` that can contain other `AnimationLayer`s -class BaseCompositionLayer: BaseAnimationLayer { - - // MARK: Lifecycle - - init(layerModel: LayerModel) { - baseLayerModel = layerModel - super.init() - - setupSublayers() - compositingFilter = layerModel.blendMode.filterName - name = layerModel.name - contentsLayer.name = "\(layerModel.name) (Content)" - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - baseLayerModel = typedLayer.baseLayerModel - super.init(layer: typedLayer) - } - - // MARK: Internal - - /// The layer that content / sublayers should be rendered in. - /// This is the layer that transform animations are applied to. - let contentsLayer = BaseAnimationLayer() - - /// Whether or not this layer render should render any visible content - var renderLayerContents: Bool { true } - - /// Sets up the base `LayerModel` animations for this layer, - /// and all child `AnimationLayer`s. - /// - Can be overridden by subclasses, which much call `super`. - override func setupAnimations(context: LayerAnimationContext) throws { - let layerContext = context.addingKeypathComponent(baseLayerModel.name) - let childContext = renderLayerContents ? layerContext : context - - try setupLayerAnimations(context: layerContext) - try setupChildAnimations(context: childContext) - } - - func setupLayerAnimations(context: LayerAnimationContext) throws { - let transformContext = context.addingKeypathComponent("Transform") - - try contentsLayer.addTransformAnimations(for: baseLayerModel.transform, context: transformContext) - - if renderLayerContents { - try contentsLayer.addOpacityAnimation(for: baseLayerModel.transform, context: transformContext) - - try contentsLayer.addVisibilityAnimation( - inFrame: CGFloat(baseLayerModel.inFrame), - outFrame: CGFloat(baseLayerModel.outFrame), - context: context) - - // There are two different drop shadow schemas, either using `DropShadowEffect` or `DropShadowStyle`. - // If both happen to be present, prefer the `DropShadowEffect` (which is the drop shadow schema - // supported on other platforms). - let dropShadowEffect = baseLayerModel.effects.first(where: { $0 is DropShadowEffect }) as? DropShadowModel - let dropShadowStyle = baseLayerModel.styles.first(where: { $0 is DropShadowStyle }) as? DropShadowModel - if let dropShadowModel = dropShadowEffect ?? dropShadowStyle { - try contentsLayer.addDropShadowAnimations(for: dropShadowModel, context: context) - } - } - } - - func setupChildAnimations(context: LayerAnimationContext) throws { - try super.setupAnimations(context: context) - } - - override func addSublayer(_ layer: CALayer) { - if layer === contentsLayer { - super.addSublayer(contentsLayer) - } else { - contentsLayer.addSublayer(layer) - } - } - - // MARK: Private - - private let baseLayerModel: LayerModel - - private func setupSublayers() { - addSublayer(contentsLayer) - - if - renderLayerContents, - let masks = baseLayerModel.masks?.filter({ $0.mode != .none }), - !masks.isEmpty - { - contentsLayer.mask = MaskCompositionLayer(masks: masks) - } - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift deleted file mode 100644 index dfbf28cff55fb08537e7325dcdac92b363d49e68..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +++ /dev/null @@ -1,169 +0,0 @@ -// Created by Cal Stephens on 1/11/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CALayer { - - // MARK: Internal - - /// Sets up an `AnimationLayer` / `CALayer` hierarchy in this layer, - /// using the given list of layers. - @nonobjc - func setupLayerHierarchy( - for layers: [LayerModel], - context: LayerContext) - throws - { - // A `LottieAnimation`'s `LayerModel`s are listed from front to back, - // but `CALayer.sublayers` are listed from back to front. - // We reverse the layer ordering to match what Core Animation expects. - // The final view hierarchy must display the layers in this exact order. - let layersInZAxisOrder = layers.reversed() - - let layersByIndex = Dictionary(grouping: layersInZAxisOrder, by: \.index) - .compactMapValues(\.first) - - /// Layers specify a `parent` layer. Child layers inherit the `transform` of their parent. - /// - We can't add the child as a sublayer of the parent `CALayer`, since that would - /// break the ordering specified in `layersInZAxisOrder`. - /// - Instead, we create an invisible `TransformLayer` to handle the parent - /// transform animations, and add the child layer to that `TransformLayer`. - func makeParentTransformLayer( - childLayerModel: LayerModel, - childLayer: CALayer, - name: (LayerModel) -> String) - -> CALayer - { - guard - let parentIndex = childLayerModel.parent, - let parentLayerModel = layersByIndex[parentIndex] - else { return childLayer } - - let parentLayer = TransformLayer(layerModel: parentLayerModel) - parentLayer.name = name(parentLayerModel) - parentLayer.addSublayer(childLayer) - - return makeParentTransformLayer( - childLayerModel: parentLayerModel, - childLayer: parentLayer, - name: name) - } - - // Create an `AnimationLayer` for each `LayerModel` - for (layerModel, mask) in try layersInZAxisOrder.pairedLayersAndMasks() { - guard let layer = try layerModel.makeAnimationLayer(context: context) else { - continue - } - - // If this layer has a `parent`, we create an invisible `TransformLayer` - // to handle displaying / animating the parent transform. - let parentTransformLayer = makeParentTransformLayer( - childLayerModel: layerModel, - childLayer: layer, - name: { parentLayerModel in - "\(layerModel.name) (parent, \(parentLayerModel.name))" - }) - - // Create the `mask` layer for this layer, if it has a `MatteType` - if - let mask, - let maskLayer = try maskLayer(for: mask.model, type: mask.matteType, context: context) - { - let maskParentTransformLayer = makeParentTransformLayer( - childLayerModel: mask.model, - childLayer: maskLayer, - name: { parentLayerModel in - "\(mask.model.name) (mask of \(layerModel.name)) (parent, \(parentLayerModel.name))" - }) - - // Set up a parent container to host both the layer - // and its mask in the same coordinate space - let maskContainer = BaseAnimationLayer() - maskContainer.name = "\(layerModel.name) (parent, masked)" - maskContainer.addSublayer(parentTransformLayer) - - // Core Animation will silently fail to apply a mask if a `mask` layer - // itself _also_ has a `mask`. As a workaround, we can wrap this layer's - // mask in an additional container layer which never has its own `mask`. - let additionalMaskParent = BaseAnimationLayer() - additionalMaskParent.addSublayer(maskParentTransformLayer) - maskContainer.mask = additionalMaskParent - - addSublayer(maskContainer) - } - - else { - addSublayer(parentTransformLayer) - } - } - } - - // MARK: Fileprivate - - /// Creates a mask `CALayer` from the given matte layer model, using the `MatteType` - /// from the layer that is being masked. - fileprivate func maskLayer( - for matteLayerModel: LayerModel, - type: MatteType, - context: LayerContext) - throws -> CALayer? - { - switch type { - case .add: - return try matteLayerModel.makeAnimationLayer(context: context) - - case .invert: - guard let maskLayer = try matteLayerModel.makeAnimationLayer(context: context) else { - return nil - } - - // We can invert the mask layer by having a large solid black layer with the - // given mask layer subtracted out using the `xor` blend mode. When applied to the - // layer being masked, this creates an inverted mask where only areas _outside_ - // of the mask layer are visible. - // https://developer.apple.com/documentation/coregraphics/cgblendmode/xor - // - The inverted mask is supposed to expand infinitely around the shape, - // so we use `InfiniteOpaqueAnimationLayer` - let base = InfiniteOpaqueAnimationLayer() - base.backgroundColor = .rgb(0, 0, 0) - base.addSublayer(maskLayer) - maskLayer.compositingFilter = "xor" - return base - - case .none, .unknown: - return nil - } - } - -} - -extension Collection { - /// Pairs each `LayerModel` within this array with - /// a `LayerModel` to use as its mask, if applicable - /// based on the layer's `MatteType` configuration. - /// - Assumes the layers are sorted in z-axis order. - fileprivate func pairedLayersAndMasks() throws - -> [(layer: LayerModel, mask: (model: LayerModel, matteType: MatteType)?)] - { - var layersAndMasks = [(layer: LayerModel, mask: (model: LayerModel, matteType: MatteType)?)]() - var unprocessedLayers = reversed() - - while let layer = unprocessedLayers.popLast() { - /// If a layer has a `MatteType`, then the next layer will be used as its `mask` - if - let matteType = layer.matte, - matteType != .none, - let maskLayer = unprocessedLayers.popLast() - { - layersAndMasks.append((layer: layer, mask: (model: maskLayer, matteType: matteType))) - } - - else { - layersAndMasks.append((layer: layer, mask: nil)) - } - } - - return layersAndMasks - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/GradientRenderLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/GradientRenderLayer.swift deleted file mode 100644 index cb2fe4888e7a0891a26e306e71db6cdb02870d5c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/GradientRenderLayer.swift +++ /dev/null @@ -1,97 +0,0 @@ -// Created by Cal Stephens on 1/10/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - GradientRenderLayer - -/// A `CAGradientLayer` subclass used to render a gradient _outside_ the normal layer bounds -/// -/// - `GradientFill.startPoint` and `GradientFill.endPoint` are expressed -/// with respect to the `bounds` of the `ShapeItemLayer`. -/// -/// - The gradient itself is supposed to be rendered infinitely in all directions -/// (e.g. including outside of `bounds`). This is because `ShapeItemLayer` paths -/// don't necessarily sit within the layer's `bounds`. -/// -/// - To support this, `GradientRenderLayer` tracks a `gradientReferenceBounds` -/// that `startPoint` / `endPoint` are calculated relative to. -/// The _actual_ `bounds` of this layer is padded by a large amount so that -/// the gradient can be drawn outside of the `gradientReferenceBounds`. -/// -final class GradientRenderLayer: CAGradientLayer { - - // MARK: Internal - - /// The reference bounds within this layer that the gradient's - /// `startPoint` and `endPoint` should be calculated relative to - var gradientReferenceBounds: CGRect = .zero { - didSet { - if oldValue != gradientReferenceBounds { - updateLayout() - } - } - } - - /// Converts the given `CGPoint` within `gradientReferenceBounds` - /// to a percentage value relative to the full `bounds` of this layer - /// - This converts absolute `startPoint` and `endPoint` values into - /// the percent-based values expected by Core Animation, - /// with respect to the custom bounds geometry used by this layer type. - func percentBasedPointInBounds(from referencePoint: CGPoint) -> CGPoint { - guard bounds.width > 0, bounds.height > 0 else { - LottieLogger.shared.assertionFailure("Size must be non-zero before an animation can be played") - return .zero - } - - let pointInBounds = CGPoint( - x: referencePoint.x + CALayer.veryLargeLayerPadding, - y: referencePoint.y + CALayer.veryLargeLayerPadding) - - return CGPoint( - x: CGFloat(pointInBounds.x) / bounds.width, - y: CGFloat(pointInBounds.y) / bounds.height) - } - - // MARK: Private - - private func updateLayout() { - anchorPoint = .zero - - bounds = CGRect( - x: gradientReferenceBounds.origin.x, - y: gradientReferenceBounds.origin.y, - width: CALayer.veryLargeLayerPadding + gradientReferenceBounds.width + CALayer.veryLargeLayerPadding, - height: CALayer.veryLargeLayerPadding + gradientReferenceBounds.height + CALayer.veryLargeLayerPadding) - - // Align the center of this layer to be at the center point of its parent layer - let superlayerSize = superlayer?.frame.size ?? gradientReferenceBounds.size - - transform = CATransform3DMakeTranslation( - (superlayerSize.width - bounds.width) / 2, - (superlayerSize.height - bounds.height) / 2, - 0) - } - -} - -// MARK: CustomLayoutLayer - -extension GradientRenderLayer: CustomLayoutLayer { - func layout(superlayerBounds: CGRect) { - gradientReferenceBounds = superlayerBounds - - if let gradientMask = mask as? GradientRenderLayer { - gradientMask.layout(superlayerBounds: superlayerBounds) - } - } -} - -extension CALayer { - /// Extra padding to add around layers that should be very large or "infinite" in size. - /// Examples include `GradientRenderLayer` and `InfiniteOpaqueAnimationLayer`. - /// - This specific value is arbitrary and can be increased if necessary. - /// - Theoretically this should be "infinite", to match the behavior of - /// `CGContext.drawLinearGradient` with `[.drawsAfterEndLocation, .drawsBeforeStartLocation]` etc. - static let veryLargeLayerPadding: CGFloat = 10_000 -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/ImageLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/ImageLayer.swift deleted file mode 100644 index 433c06f3b75b44c6ccf96136cf124c669333cf6f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/ImageLayer.swift +++ /dev/null @@ -1,80 +0,0 @@ -// Created by Cal Stephens on 1/10/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - ImageLayer - -/// The `CALayer` type responsible for rendering `ImageLayerModel`s -final class ImageLayer: BaseCompositionLayer { - - // MARK: Lifecycle - - init( - imageLayer: ImageLayerModel, - context: LayerContext) - { - self.imageLayer = imageLayer - super.init(layerModel: imageLayer) - setupImage(context: context) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - imageLayer = typedLayer.imageLayer - super.init(layer: typedLayer) - } - - // MARK: Internal - - func setupImage(context: LayerContext) { - guard - let imageAsset = context.animation.assetLibrary?.imageAssets[imageLayer.referenceID], - let image = context.imageProvider.imageForAsset(asset: imageAsset) - else { - self.imageAsset = nil - contentsLayer.contents = nil - return - } - - self.imageAsset = imageAsset - contentsLayer.contents = image - contentsLayer.contentsGravity = context.imageProvider.contentsGravity(for: imageAsset) - setNeedsLayout() - } - - // MARK: Private - - private let imageLayer: ImageLayerModel - private var imageAsset: ImageAsset? - -} - -// MARK: CustomLayoutLayer - -extension ImageLayer: CustomLayoutLayer { - func layout(superlayerBounds: CGRect) { - anchorPoint = .zero - - guard let imageAsset else { - bounds = superlayerBounds - return - } - - // Image layers specifically need to use the size of the image itself - bounds = CGRect( - x: superlayerBounds.origin.x, - y: superlayerBounds.origin.y, - width: CGFloat(imageAsset.width), - height: CGFloat(imageAsset.height)) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/InfiniteOpaqueAnimationLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/InfiniteOpaqueAnimationLayer.swift deleted file mode 100644 index 4549fea691b0a57971498713631ceba7441dee39..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/InfiniteOpaqueAnimationLayer.swift +++ /dev/null @@ -1,56 +0,0 @@ -// Created by Cal Stephens on 10/10/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - ExpandedAnimationLayer - -/// A `BaseAnimationLayer` subclass that renders its background color -/// as if the layer is infinitely large, without affecting its bounds -/// or the bounds of its sublayers -final class InfiniteOpaqueAnimationLayer: BaseAnimationLayer { - - // MARK: Lifecycle - - override init() { - super.init() - addSublayer(additionalPaddingLayer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - super.init(layer: layer) - } - - // MARK: Internal - - override func layoutSublayers() { - super.layoutSublayers() - - masksToBounds = false - additionalPaddingLayer.backgroundColor = backgroundColor - - // Scale `additionalPaddingLayer` to be larger than this layer - // by `additionalPadding` at each size, and centered at the center - // of this layer. Since `additionalPadding` is very large, this has - // the affect of making `additionalPaddingLayer` appear infinite. - let scaleRatioX = (bounds.width + (CALayer.veryLargeLayerPadding * 2)) / bounds.width - let scaleRatioY = (bounds.height + (CALayer.veryLargeLayerPadding * 2)) / bounds.height - - additionalPaddingLayer.transform = CATransform3DScale( - CATransform3DMakeTranslation(-CALayer.veryLargeLayerPadding, -CALayer.veryLargeLayerPadding, 0), - scaleRatioX, - scaleRatioY, - 1) - } - - // MARK: Private - - private let additionalPaddingLayer = CALayer() - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift deleted file mode 100644 index 0ca9339049b61975d17449fad34b09f6fa12cb49..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +++ /dev/null @@ -1,59 +0,0 @@ -// Created by Cal Stephens on 12/20/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -// MARK: - LayerContext - -/// Context available when constructing an `AnimationLayer` -struct LayerContext { - let animation: LottieAnimation - let imageProvider: AnimationImageProvider - let textProvider: AnimationKeypathTextProvider - let fontProvider: AnimationFontProvider - let compatibilityTracker: CompatibilityTracker - var layerName: String - - func forLayer(_ layer: LayerModel) -> LayerContext { - var context = self - context.layerName = layer.name - return context - } -} - -// MARK: - LayerModel + makeAnimationLayer - -extension LayerModel { - /// Constructs an `AnimationLayer` / `CALayer` that represents this `LayerModel` - func makeAnimationLayer(context: LayerContext) throws -> BaseCompositionLayer? { - let context = context.forLayer(self) - - if hidden { - return TransformLayer(layerModel: self) - } - - switch (type, self) { - case (.precomp, let preCompLayerModel as PreCompLayerModel): - let preCompLayer = PreCompLayer(preCompLayer: preCompLayerModel) - try preCompLayer.setup(context: context) - return preCompLayer - - case (.solid, let solidLayerModel as SolidLayerModel): - return SolidLayer(solidLayerModel) - - case (.shape, let shapeLayerModel as ShapeLayerModel): - return try ShapeLayer(shapeLayer: shapeLayerModel, context: context) - - case (.image, let imageLayerModel as ImageLayerModel): - return ImageLayer(imageLayer: imageLayerModel, context: context) - - case (.text, let textLayerModel as TextLayerModel): - return try TextLayer(textLayerModel: textLayerModel, context: context) - - case (.null, _): - return TransformLayer(layerModel: self) - - case (.unknown, _), (.precomp, _), (.solid, _), (.image, _), (.shape, _), (.text, _): - return nil - } - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/MaskCompositionLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/MaskCompositionLayer.swift deleted file mode 100644 index d032ab5dabb60c1f1a0270ec617eb764d9f4fa68..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/MaskCompositionLayer.swift +++ /dev/null @@ -1,138 +0,0 @@ -// Created by Cal Stephens on 1/6/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - MaskCompositionLayer - -/// The CALayer type responsible for rendering the `Mask` of a `BaseCompositionLayer` -final class MaskCompositionLayer: CALayer { - - // MARK: Lifecycle - - init(masks: [Mask]) { - maskLayers = masks.map(MaskLayer.init(mask:)) - super.init() - - var containerLayer = BaseAnimationLayer() - var firstObject = true - for maskLayer in maskLayers { - if maskLayer.maskModel.mode.usableMode == .none { - continue - } else if maskLayer.maskModel.mode.usableMode == .add || firstObject { - firstObject = false - containerLayer.addSublayer(maskLayer) - } else { - containerLayer.mask = maskLayer - let newContainer = BaseAnimationLayer() - newContainer.addSublayer(containerLayer) - containerLayer = newContainer - } - } - - addSublayer(containerLayer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - maskLayers = typedLayer.maskLayers - super.init(layer: typedLayer) - } - - // MARK: Internal - - override func layoutSublayers() { - super.layoutSublayers() - - for sublayer in sublayers ?? [] { - sublayer.fillBoundsOfSuperlayer() - } - } - - // MARK: Private - - private let maskLayers: [MaskLayer] - -} - -// MARK: AnimationLayer - -extension MaskCompositionLayer: AnimationLayer { - func setupAnimations(context: LayerAnimationContext) throws { - for maskLayer in maskLayers { - try maskLayer.setupAnimations(context: context) - } - } -} - -// MARK: MaskCompositionLayer.MaskLayer - -extension MaskCompositionLayer { - final class MaskLayer: CAShapeLayer { - - // MARK: Lifecycle - - init(mask: Mask) { - maskModel = mask - super.init() - - fillRule = .evenOdd - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - maskModel = typedLayer.maskModel - super.init(layer: typedLayer) - } - - // MARK: Internal - - let maskModel: Mask - - } -} - -// MARK: - MaskCompositionLayer.MaskLayer + AnimationLayer - -extension MaskCompositionLayer.MaskLayer: AnimationLayer { - func setupAnimations(context: LayerAnimationContext) throws { - let shouldInvertMask = (maskModel.mode.usableMode == .subtract && !maskModel.inverted) - || (maskModel.mode.usableMode == .add && maskModel.inverted) - - try addAnimations( - for: maskModel.shape, - context: context, - transformPath: { maskPath in - // If the mask is using `MaskMode.subtract` or has `inverted: true`, - // we have to invert the area filled by the path. We can do that by - // drawing a rectangle, and then adding a path (which is subtracted - // from the rectangle based on the .evenOdd fill mode). - if shouldInvertMask { - let path = CGMutablePath() - path.addRect(.veryLargeRect) - path.addPath(maskPath) - return path - } else { - return maskPath - } - }) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/PreCompLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/PreCompLayer.swift deleted file mode 100644 index 700619273822cdabfaeacfd497818256e270d9e4..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/PreCompLayer.swift +++ /dev/null @@ -1,105 +0,0 @@ -// Created by Cal Stephens on 12/14/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - PreCompLayer - -/// The `CALayer` type responsible for rendering `PreCompLayerModel`s -final class PreCompLayer: BaseCompositionLayer { - - // MARK: Lifecycle - - init(preCompLayer: PreCompLayerModel) { - self.preCompLayer = preCompLayer - super.init(layerModel: preCompLayer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - preCompLayer = typedLayer.preCompLayer - super.init(layer: typedLayer) - } - - // MARK: Internal - - let preCompLayer: PreCompLayerModel - - /// Post-init setup for `PreCompLayer`s. - /// Should always be called after `PreCompLayer.init(preCompLayer:)`. - /// - /// This is a workaround for a hard-to-reproduce crash that was - /// triggered when `PreCompLayer.init` was called reentantly. We didn't - /// have any consistent repro steps for this crash (it happened 100% of - /// the time for some testers, and 0% of the time for other testers), - /// but moving this code out of `PreCompLayer.init` does seem to fix it. - /// - /// The stack trace looked like: - /// - `_os_unfair_lock_recursive_abort` - /// - `-[CALayerAccessibility__UIKit__QuartzCore dealloc]` - /// - `PreCompLayer.__allocating_init(preCompLayer:context:)` <- reentrant init call - /// - ... - /// - `CALayer.setupLayerHierarchy(for:context:)` - /// - `PreCompLayer.init(preCompLayer:context:)` - /// - func setup(context: LayerContext) throws { - try setupLayerHierarchy( - for: context.animation.assetLibrary?.precompAssets[preCompLayer.referenceID]?.layers ?? [], - context: context) - } - - override func setupAnimations(context: LayerAnimationContext) throws { - var context = context - context = context.addingKeypathComponent(preCompLayer.name) - try setupLayerAnimations(context: context) - - let timeRemappingInterpolator = preCompLayer.timeRemapping.flatMap { KeyframeInterpolator(keyframes: $0.keyframes) } - - let contextForChildren = context - // `timeStretch` and `startTime` are a simple linear function so can be inverted from a - // "global time to local time" function into the simpler "local time to global time". - .withSimpleTimeRemapping { [preCompLayer] layerLocalFrame in - (layerLocalFrame * AnimationFrameTime(preCompLayer.timeStretch)) + AnimationFrameTime(preCompLayer.startTime) - } - // `timeRemappingInterpolator` is arbitrarily complex and cannot be inverted, - // so can only be applied via `complexTimeRemapping` from global time to local time. - .withComplexTimeRemapping(required: preCompLayer.timeRemapping != nil) { [preCompLayer] globalTime in - if let timeRemappingInterpolator { - let remappedLocalTime = timeRemappingInterpolator.value(frame: globalTime) as! LottieVector1D - return remappedLocalTime.cgFloatValue * context.animation.framerate - } else { - return (globalTime - preCompLayer.startTime) / preCompLayer.timeStretch - } - } - - try setupChildAnimations(context: contextForChildren) - } - -} - -// MARK: CustomLayoutLayer - -extension PreCompLayer: CustomLayoutLayer { - func layout(superlayerBounds: CGRect) { - anchorPoint = .zero - - // Pre-comp layers use a size specified in the layer model, - // and clip the composition to that bounds - bounds = CGRect( - x: superlayerBounds.origin.x, - y: superlayerBounds.origin.y, - width: CGFloat(preCompLayer.width), - height: CGFloat(preCompLayer.height)) - - contentsLayer.masksToBounds = true - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/RepeaterLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/RepeaterLayer.swift deleted file mode 100644 index e27e7e876b5d1b248329cf53cc37bd8fb2bfaa3a..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/RepeaterLayer.swift +++ /dev/null @@ -1,98 +0,0 @@ -// Created by Cal Stephens on 8/1/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - RepeaterLayer - -/// A layer that renders a child layer at some offset using a `Repeater` -final class RepeaterLayer: BaseAnimationLayer { - - // MARK: Lifecycle - - init(repeater: Repeater, childLayer: CALayer, index: Int) { - repeaterTransform = RepeaterTransform(repeater: repeater, index: index) - super.init() - addSublayer(childLayer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - repeaterTransform = typedLayer.repeaterTransform - super.init(layer: typedLayer) - } - - // MARK: Internal - - override func setupAnimations(context: LayerAnimationContext) throws { - try super.setupAnimations(context: context) - try addTransformAnimations(for: repeaterTransform, context: context) - } - - // MARK: Private - - private let repeaterTransform: RepeaterTransform - -} - -// MARK: - RepeaterTransform - -/// A transform model created from a `Repeater` -private struct RepeaterTransform { - - // MARK: Lifecycle - - init(repeater: Repeater, index: Int) { - anchorPoint = repeater.anchorPoint - scale = repeater.scale - - rotationX = repeater.rotationX.map { rotation in - LottieVector1D(rotation.value * Double(index)) - } - - rotationY = repeater.rotationY.map { rotation in - LottieVector1D(rotation.value * Double(index)) - } - - rotationZ = repeater.rotationZ.map { rotation in - LottieVector1D(rotation.value * Double(index)) - } - - position = repeater.position.map { position in - LottieVector3D( - x: position.x * Double(index), - y: position.y * Double(index), - z: position.z * Double(index)) - } - } - - // MARK: Internal - - let anchorPoint: KeyframeGroup - let position: KeyframeGroup - let rotationX: KeyframeGroup - let rotationY: KeyframeGroup - let rotationZ: KeyframeGroup - - let scale: KeyframeGroup - -} - -// MARK: TransformModel - -extension RepeaterTransform: TransformModel { - var _position: KeyframeGroup? { position } - var _positionX: KeyframeGroup? { nil } - var _positionY: KeyframeGroup? { nil } - var _skew: KeyframeGroup? { nil } - var _skewAxis: KeyframeGroup? { nil } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/ShapeItemLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/ShapeItemLayer.swift deleted file mode 100644 index 23524d107bef23274bcb83b12e6cc97d4e1bf4e7..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/ShapeItemLayer.swift +++ /dev/null @@ -1,344 +0,0 @@ -// Created by Cal Stephens on 12/13/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - ShapeItemLayer - -/// A CALayer type that renders an array of `[ShapeItem]`s, -/// from a `Group` in a `ShapeLayerModel`. -final class ShapeItemLayer: BaseAnimationLayer { - - // MARK: Lifecycle - - /// Initializes a `ShapeItemLayer` that renders a `Group` from a `ShapeLayerModel` - /// - Parameters: - /// - shape: The `ShapeItem` in this group that renders a `GGPath` - /// - otherItems: Other items in this group that affect the appearance of the shape - init(shape: Item, otherItems: [Item], context: LayerContext) throws { - self.shape = shape - self.otherItems = otherItems - - try context.compatibilityAssert( - shape.item.drawsCGPath, - "`ShapeItemLayer` must contain exactly one `ShapeItem` that draws a `GPPath`") - - try context.compatibilityAssert( - !otherItems.contains(where: { $0.item.drawsCGPath }), - "`ShapeItemLayer` must contain exactly one `ShapeItem` that draws a `GPPath`") - - super.init() - - setupLayerHierarchy() - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - shape = typedLayer.shape - otherItems = typedLayer.otherItems - super.init(layer: typedLayer) - } - - // MARK: Internal - - /// An item that can be displayed by this layer - struct Item { - /// A `ShapeItem` that should be rendered by this layer - let item: ShapeItem - - /// The set of groups that this item descends from - /// - Due to the way `GroupLayer`s are setup, the original `ShapeItem` - /// hierarchy from the `ShapeLayer` data model may no longer exactly - /// match the hierarchy of `GroupLayer` / `ShapeItemLayer`s constructed - /// at runtime. Since animation keypaths need to match the original - /// structure of the `ShapeLayer` data model, we track that info here. - let groupPath: [String] - } - - override func setupAnimations(context: LayerAnimationContext) throws { - try super.setupAnimations(context: context) - - guard let sublayerConfiguration else { return } - - switch sublayerConfiguration.fill { - case .solidFill(let shapeLayer): - try setupSolidFillAnimations(shapeLayer: shapeLayer, context: context) - - case .gradientFill(let gradientLayers): - try setupGradientFillAnimations(layers: gradientLayers, context: context) - } - - if let gradientStrokeConfiguration = sublayerConfiguration.gradientStroke { - try setupGradientStrokeAnimations(layers: gradientStrokeConfiguration, context: context) - } - } - - // MARK: Private - - private struct GradientLayers { - /// The `CALayer` that renders the RGB components of the gradient - let gradientColorLayer: GradientRenderLayer - /// The `CALayer` that renders the alpha components of the gradient, - /// masking the `gradientColorLayer` - let gradientAlphaLayer: GradientRenderLayer? - /// The `CAShapeLayer` that clips the gradient layers to the expected shape - let shapeMaskLayer: CAShapeLayer - /// The top-most `CAShapeLayer` used to render `Stroke`s over the gradient if necessary - let overlayLayer: CAShapeLayer? - } - - /// The configuration of this layer's `fill` sublayers - private enum FillLayerConfiguration { - /// This layer displays a single `CAShapeLayer` - case solidFill(CAShapeLayer) - - /// This layer displays a `GradientRenderLayer` masked by a `CAShapeLayer`. - case gradientFill(GradientLayers) - } - - /// The `ShapeItem` in this group that renders a `GGPath` - private let shape: Item - - /// Other items in this group that affect the appearance of the shape - private let otherItems: [Item] - - /// The current configuration of this layer's sublayer(s) - private var sublayerConfiguration: (fill: FillLayerConfiguration, gradientStroke: GradientLayers?)? - - private func setupLayerHierarchy() { - // We have to build a different layer hierarchy depending on if - // we're rendering a gradient (a `CAGradientLayer` masked by a `CAShapeLayer`) - // or a solid shape (a simple `CAShapeLayer`). - let fillLayerConfiguration: FillLayerConfiguration - if let gradientFill = otherItems.first(GradientFill.self) { - fillLayerConfiguration = setupGradientFillLayerHierarchy(for: gradientFill) - } else { - fillLayerConfiguration = setupSolidFillLayerHierarchy() - } - - let gradientStrokeConfiguration: GradientLayers? - if let gradientStroke = otherItems.first(GradientStroke.self) { - gradientStrokeConfiguration = setupGradientStrokeLayerHierarchy(for: gradientStroke) - } else { - gradientStrokeConfiguration = nil - } - - sublayerConfiguration = (fillLayerConfiguration, gradientStrokeConfiguration) - } - - private func setupSolidFillLayerHierarchy() -> FillLayerConfiguration { - let shapeLayer = CAShapeLayer() - addSublayer(shapeLayer) - - // `CAShapeLayer.fillColor` defaults to black, so we have to - // nil out the background color if there isn't an expected fill color - if !otherItems.contains(where: { $0.item is Fill }) { - shapeLayer.fillColor = nil - } - - return .solidFill(shapeLayer) - } - - private func setupGradientFillLayerHierarchy( - for gradientFill: GradientFill) - -> FillLayerConfiguration - { - let container = BaseAnimationLayer() - let pathContainer = BaseAnimationLayer() - - let pathMask = CAShapeLayer() - pathMask.fillColor = .rgb(0, 0, 0) - pathContainer.mask = pathMask - - let rgbGradientLayer = GradientRenderLayer() - pathContainer.addSublayer(rgbGradientLayer) - container.addSublayer(pathContainer) - - let overlayLayer = CAShapeLayer() - overlayLayer.fillColor = nil - container.addSublayer(overlayLayer) - - addSublayer(container) - - let alphaGradientLayer: GradientRenderLayer? - if gradientFill.hasAlphaComponent { - alphaGradientLayer = GradientRenderLayer() - rgbGradientLayer.mask = alphaGradientLayer - } else { - alphaGradientLayer = nil - } - - return .gradientFill(GradientLayers( - gradientColorLayer: rgbGradientLayer, - gradientAlphaLayer: alphaGradientLayer, - shapeMaskLayer: pathMask, - overlayLayer: overlayLayer)) - } - - private func setupGradientStrokeLayerHierarchy( - for gradientStroke: GradientStroke) - -> GradientLayers - { - let container = BaseAnimationLayer() - - let pathMask = CAShapeLayer() - pathMask.fillColor = nil - pathMask.strokeColor = .rgb(0, 0, 0) - container.mask = pathMask - - let rgbGradientLayer = GradientRenderLayer() - container.addSublayer(rgbGradientLayer) - addSublayer(container) - - let alphaGradientLayer: GradientRenderLayer? - if gradientStroke.hasAlphaComponent { - alphaGradientLayer = GradientRenderLayer() - rgbGradientLayer.mask = alphaGradientLayer - } else { - alphaGradientLayer = nil - } - - return GradientLayers( - gradientColorLayer: rgbGradientLayer, - gradientAlphaLayer: alphaGradientLayer, - shapeMaskLayer: pathMask, - overlayLayer: nil) - } - - private func setupSolidFillAnimations( - shapeLayer: CAShapeLayer, - context: LayerAnimationContext) - throws - { - var trimPathMultiplier: PathMultiplier? = nil - if let (trim, context) = otherItems.first(Trim.self, where: { !$0.isEmpty }, context: context) { - trimPathMultiplier = try shapeLayer.addAnimations(for: trim, context: context) - - try context.compatibilityAssert( - otherItems.first(Fill.self) == nil, - """ - The Core Animation rendering engine doesn't currently support applying - trims to filled shapes (only stroked shapes). - """) - } - - try shapeLayer.addAnimations( - for: shape.item, - context: context.for(shape), - pathMultiplier: trimPathMultiplier ?? 1, - roundedCorners: otherItems.first(RoundedCorners.self)) - - if let (fill, context) = otherItems.first(Fill.self, context: context) { - try shapeLayer.addAnimations(for: fill, context: context) - } - - if let (stroke, context) = otherItems.first(Stroke.self, context: context) { - try shapeLayer.addStrokeAnimations(for: stroke, context: context) - } - } - - private func setupGradientFillAnimations( - layers: GradientLayers, - context: LayerAnimationContext) - throws - { - let pathLayers = [layers.shapeMaskLayer, layers.overlayLayer] - for pathLayer in pathLayers { - try pathLayer?.addAnimations( - for: shape.item, - context: context.for(shape), - pathMultiplier: 1, - roundedCorners: otherItems.first(RoundedCorners.self)) - } - - if let (gradientFill, context) = otherItems.first(GradientFill.self, context: context) { - layers.shapeMaskLayer.fillRule = gradientFill.fillRule.caFillRule - try layers.gradientColorLayer.addGradientAnimations(for: gradientFill, type: .rgb, context: context) - try layers.gradientAlphaLayer?.addGradientAnimations(for: gradientFill, type: .alpha, context: context) - } - - if let (stroke, context) = otherItems.first(Stroke.self, context: context) { - try layers.overlayLayer?.addStrokeAnimations(for: stroke, context: context) - } - } - - private func setupGradientStrokeAnimations( - layers: GradientLayers, - context: LayerAnimationContext) - throws - { - var trimPathMultiplier: PathMultiplier? = nil - if let (trim, context) = otherItems.first(Trim.self, context: context) { - trimPathMultiplier = try layers.shapeMaskLayer.addAnimations(for: trim, context: context) - } - - try layers.shapeMaskLayer.addAnimations( - for: shape.item, - context: context.for(shape), - pathMultiplier: trimPathMultiplier ?? 1, - roundedCorners: otherItems.first(RoundedCorners.self)) - - if let (gradientStroke, context) = otherItems.first(GradientStroke.self, context: context) { - try layers.gradientColorLayer.addGradientAnimations(for: gradientStroke, type: .rgb, context: context) - try layers.gradientAlphaLayer?.addGradientAnimations(for: gradientStroke, type: .alpha, context: context) - - try layers.shapeMaskLayer.addStrokeAnimations(for: gradientStroke, context: context) - } - } - -} - -// MARK: - [ShapeItem] helpers - -extension [ShapeItemLayer.Item] { - /// The first `ShapeItem` in this array of the given type - func first( - _: ItemType.Type, - where condition: (ItemType) -> Bool = { _ in true }, - context: LayerAnimationContext) - -> (item: ItemType, context: LayerAnimationContext)? - { - for item in self { - if let match = item.item as? ItemType, condition(match) { - return (match, context.for(item)) - } - } - - return nil - } - - /// The first `ShapeItem` in this array of the given type - func first(_: ItemType.Type) -> ItemType? { - for item in self { - if let match = item.item as? ItemType { - return match - } - } - - return nil - } -} - -extension LayerAnimationContext { - /// An updated `LayerAnimationContext` with the`AnimationKeypath` - /// that refers to this specific `ShapeItem`. - func `for`(_ item: ShapeItemLayer.Item) -> LayerAnimationContext { - var context = self - - for parentGroupName in item.groupPath { - context.currentKeypath.keys.append(parentGroupName) - } - - context.currentKeypath.keys.append(item.item.name) - return context - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/ShapeLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/ShapeLayer.swift deleted file mode 100644 index 7249d39777c09c3d3e02c510b0f6d07272f57d70..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/ShapeLayer.swift +++ /dev/null @@ -1,561 +0,0 @@ -// Created by Cal Stephens on 12/14/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - ShapeLayer - -/// The CALayer type responsible for rendering `ShapeLayerModel`s -final class ShapeLayer: BaseCompositionLayer { - - // MARK: Lifecycle - - init(shapeLayer: ShapeLayerModel, context: LayerContext) throws { - self.shapeLayer = shapeLayer - super.init(layerModel: shapeLayer) - try setUpGroups(context: context) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - shapeLayer = typedLayer.shapeLayer - super.init(layer: typedLayer) - } - - // MARK: Private - - private let shapeLayer: ShapeLayerModel - - private func setUpGroups(context: LayerContext) throws { - let shapeItems = shapeLayer.items.map { ShapeItemLayer.Item(item: $0, groupPath: []) } - try setupGroups(from: shapeItems, parentGroup: nil, parentGroupPath: [], context: context) - } - -} - -// MARK: - GroupLayer - -/// The CALayer type responsible for rendering `Group`s -final class GroupLayer: BaseAnimationLayer { - - // MARK: Lifecycle - - init(group: Group, items: [ShapeItemLayer.Item], groupPath: [String], context: LayerContext) throws { - self.group = group - self.items = items - self.groupPath = groupPath - super.init() - try setupLayerHierarchy(context: context) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - group = typedLayer.group - items = typedLayer.items - groupPath = typedLayer.groupPath - super.init(layer: typedLayer) - } - - // MARK: Internal - - override func setupAnimations(context: LayerAnimationContext) throws { - try super.setupAnimations(context: context) - - if let (shapeTransform, context) = nonGroupItems.first(ShapeTransform.self, context: context) { - try addTransformAnimations(for: shapeTransform, context: context) - try addOpacityAnimation(for: shapeTransform, context: context) - } - } - - // MARK: Private - - private let group: Group - - /// `ShapeItemLayer.Item`s rendered by this `Group` - /// - In the original `ShapeLayer` data model, these items could have originated from a different group - private let items: [ShapeItemLayer.Item] - - /// The keypath that represents this group, with respect to the parent `ShapeLayer` - /// - Due to the way `GroupLayer`s are setup, the original `ShapeItem` - /// hierarchy from the `ShapeLayer` data model may no longer exactly - /// match the hierarchy of `GroupLayer` / `ShapeItemLayer`s constructed - /// at runtime. Since animation keypaths need to match the original - /// structure of the `ShapeLayer` data model, we track that info here. - private let groupPath: [String] - - /// Child group items contained in this group. Correspond to a child `GroupLayer` - private lazy var childGroups = items.filter { $0.item is Group } - - /// `ShapeItem`s (other than nested `Group`s) that are rendered by this layer - private lazy var nonGroupItems = items.filter { !($0.item is Group) } - - private func setupLayerHierarchy(context: LayerContext) throws { - // Groups can contain other groups, so we may have to continue - // recursively creating more `GroupLayer`s - try setupGroups(from: items, parentGroup: group, parentGroupPath: groupPath, context: context) - - // Create `ShapeItemLayer`s for each subgroup of shapes that should be rendered as a single unit - // - These groups are listed from front-to-back, so we have to add the sublayers in reverse order - let renderGroups = items.shapeRenderGroups(groupHasChildGroupsToInheritUnusedItems: !childGroups.isEmpty) - for shapeRenderGroup in renderGroups.validGroups.reversed() { - // When there are multiple path-drawing items, they're supposed to be rendered - // in a single `CAShapeLayer` (instead of rendering them in separate layers) so - // `CAShapeLayerFillRule.evenOdd` can be applied correctly if the paths overlap. - // Since a `CAShapeLayer` only supports animating a single `CGPath` from a single `KeyframeGroup`, - // this requires combining all of the path-drawing items into a single set of keyframes. - if - shapeRenderGroup.pathItems.count > 1, - // We currently only support this codepath for `Shape` items that directly contain bezier path keyframes. - // We could also support this for other path types like rectangles, ellipses, and polygons with more work. - shapeRenderGroup.pathItems.allSatisfy({ $0.item is Shape }), - // `Trim`s are currently only applied correctly using individual `ShapeItemLayer`s, - // because each path has to be trimmed separately. - !shapeRenderGroup.otherItems.contains(where: { $0.item is Trim }) - { - let allPathKeyframes = shapeRenderGroup.pathItems.compactMap { ($0.item as? Shape)?.path } - let combinedShape = CombinedShapeItem( - shapes: Keyframes.combined(allPathKeyframes), - name: group.name) - - let sublayer = try ShapeItemLayer( - shape: ShapeItemLayer.Item(item: combinedShape, groupPath: shapeRenderGroup.pathItems[0].groupPath), - otherItems: shapeRenderGroup.otherItems, - context: context) - - addSublayer(sublayer) - } - - // Otherwise, if each `ShapeItem` that draws a `GGPath` animates independently, - // we have to create a separate `ShapeItemLayer` for each one. This may render - // incorrectly if there are multiple paths that overlap with each other. - else { - for pathDrawingItem in shapeRenderGroup.pathItems { - let sublayer = try ShapeItemLayer( - shape: pathDrawingItem, - otherItems: shapeRenderGroup.otherItems, - context: context) - - addSublayer(sublayer) - } - } - } - } - -} - -extension CALayer { - - // MARK: Fileprivate - - /// Sets up `GroupLayer`s for each `Group` in the given list of `ShapeItem`s - /// - Each `Group` item becomes its own `GroupLayer` sublayer. - /// - Other `ShapeItem` are applied to all sublayers - fileprivate func setupGroups( - from items: [ShapeItemLayer.Item], - parentGroup: Group?, - parentGroupPath: [String], - context: LayerContext) - throws - { - // If the layer has any `Repeater`s, set up each repeater - // and then handle any remaining groups like normal. - if items.contains(where: { $0.item is Repeater }) { - let repeaterGroupings = items.split(whereSeparator: { $0.item is Repeater }) - - // Iterate through the groupings backwards to preserve the expected rendering order - for repeaterGrouping in repeaterGroupings.reversed() { - // Each repeater applies to the previous items in the list - if let repeater = repeaterGrouping.trailingSeparator?.item as? Repeater { - try setUpRepeater( - repeater, - items: repeaterGrouping.grouping, - parentGroupPath: parentGroupPath, - context: context) - } - - // Any remaining items after the last repeater are handled like normal - else { - try setupGroups( - from: repeaterGrouping.grouping, - parentGroup: parentGroup, - parentGroupPath: parentGroupPath, - context: context) - } - } - } - - else { - let groupLayers = try makeGroupLayers( - from: items, - parentGroup: parentGroup, - parentGroupPath: parentGroupPath, - context: context) - - for groupLayer in groupLayers { - addSublayer(groupLayer) - } - } - } - - // MARK: Private - - /// Sets up this layer using the given `Repeater` - private func setUpRepeater( - _ repeater: Repeater, - items allItems: [ShapeItemLayer.Item], - parentGroupPath: [String], - context: LayerContext) - throws - { - let items = allItems.filter { !($0.item is Repeater) } - let copyCount = Int(try repeater.copies.exactlyOneKeyframe(context: context, description: "repeater copies").value) - - for index in 0.. [GroupLayer] - { - var groupItems = items.compactMap { $0.item as? Group }.filter { !$0.hidden } - var otherItems = items.filter { !($0.item is Group) && !$0.item.hidden } - - // Handle the top-level `shapeLayer.items` array. This is typically just a single `Group`, - // but in practice can be any combination of items. The implementation expects all path-drawing - // shape items to be managed by a `GroupLayer`, so if there's a top-level path item we - // have to create a placeholder group. - if parentGroup == nil, otherItems.contains(where: { $0.item.drawsCGPath }) { - groupItems = [Group(items: items.map { $0.item }, name: "")] - otherItems = [] - } - - // Any child items that wouldn't be included in a valid shape render group - // need to be applied to child groups (otherwise they'd be silently ignored). - let inheritedItemsForChildGroups = otherItems - .shapeRenderGroups(groupHasChildGroupsToInheritUnusedItems: !groupItems.isEmpty) - .unusedItems - - // Groups are listed from front to back, - // but `CALayer.sublayers` are listed from back to front. - let groupsInZAxisOrder = groupItems.reversed() - - return try groupsInZAxisOrder.compactMap { group in - var pathForChildren = parentGroupPath - if !group.name.isEmpty { - pathForChildren.append(group.name) - } - - let childItems = group.items - .filter { !$0.hidden } - .map { ShapeItemLayer.Item(item: $0, groupPath: pathForChildren) } - - // Some shape item properties are affected by scaling (e.g. stroke width). - // The child group may have a `ShapeTransform` that affects the scale of its items, - // but shouldn't affect the scale of any inherited items. To prevent this scale - // from affecting inherited items, we have to apply an inverse scale to them. - let inheritedItems = try inheritedItemsForChildGroups.map { item in - ShapeItemLayer.Item( - item: try item.item.scaledCopyForChildGroup(group, context: context), - groupPath: item.groupPath) - } - - return try GroupLayer( - group: group, - items: childItems + inheritedItems, - groupPath: pathForChildren, - context: context) - } - } -} - -extension ShapeItem { - /// Whether or not this `ShapeItem` is responsible for rendering a `CGPath` - var drawsCGPath: Bool { - switch type { - case .ellipse, .rectangle, .shape, .star: - return true - - case .fill, .gradientFill, .group, .gradientStroke, .merge, - .repeater, .round, .stroke, .trim, .transform, .unknown: - return false - } - } - - /// Whether or not this `ShapeItem` provides a fill for a set of shapes - var isFill: Bool { - switch type { - case .fill, .gradientFill: - return true - - case .ellipse, .rectangle, .shape, .star, .group, .gradientStroke, - .merge, .repeater, .round, .stroke, .trim, .transform, .unknown: - return false - } - } - - /// Whether or not this `ShapeItem` provides a stroke for a set of shapes - var isStroke: Bool { - switch type { - case .stroke, .gradientStroke: - return true - - case .ellipse, .rectangle, .shape, .star, .group, .gradientFill, - .merge, .repeater, .round, .fill, .trim, .transform, .unknown: - return false - } - } - - // For any inherited shape items that are affected by scaling (e.g. strokes but not fills), - // any `ShapeTransform` in the given child group isn't supposed to be applied to the item. - // To cancel out the effect of the transform, we can apply an inverse transform to the - // shape item. - func scaledCopyForChildGroup(_ childGroup: Group, context: LayerContext) throws -> ShapeItem { - guard - // Path-drawing items aren't inherited by child groups in this way - !drawsCGPath, - // Stroke widths are affected by scaling, but fill colors aren't. - // We can expand this to other types of items in the future if necessary. - let stroke = self as? StrokeShapeItem, - // We only need to handle scaling if there's a `ShapeTransform` present - let transform = childGroup.items.first(where: { $0 is ShapeTransform }) as? ShapeTransform - else { return self } - - let newWidth = try Keyframes.combined(stroke.width, transform.scale) { strokeWidth, scale -> LottieVector1D in - // Since we're applying this scale to a scalar value rather than to a layer, - // we can only handle cases where the scale is also a scalar (e.g. the same for both x and y) - try context.compatibilityAssert(scale.x == scale.y, """ - The Core Animation rendering engine doesn't support applying separate x/y scale values \ - (x: \(scale.x), y: \(scale.y)) to this stroke item (\(self.name)). - """) - - return LottieVector1D(strokeWidth.value * (100 / scale.x)) - } - - return stroke.copy(width: newWidth) - } -} - -extension Collection { - /// Splits this collection into two groups, based on the given predicate - func grouped(by predicate: (Element) -> Bool) -> (trueElements: [Element], falseElements: [Element]) { - var trueElements = [Element]() - var falseElements = [Element]() - - for element in self { - if predicate(element) { - trueElements.append(element) - } else { - falseElements.append(element) - } - } - - return (trueElements, falseElements) - } - - /// Splits this collection into an array of grouping separated by the given separator. - /// For example, `[A, B, C]` split by `B` returns an array with two elements: - /// 1. `(grouping: [A], trailingSeparator: B)` - /// 2. `(grouping: [C], trailingSeparator: nil)` - func split(whereSeparator separatorPredicate: (Element) -> Bool) - -> [(grouping: [Element], trailingSeparator: Element?)] - { - guard !isEmpty else { return [] } - - var groupings: [(grouping: [Element], trailingSeparator: Element?)] = [] - - for element in self { - if groupings.isEmpty || groupings.last?.trailingSeparator != nil { - groupings.append((grouping: [], trailingSeparator: nil)) - } - - if separatorPredicate(element) { - groupings[groupings.indices.last!].trailingSeparator = element - } else { - groupings[groupings.indices.last!].grouping.append(element) - } - } - - return groupings - } -} - -// MARK: - ShapeRenderGroup - -/// A group of `ShapeItem`s that should be rendered together as a single unit -struct ShapeRenderGroup { - /// The items in this group that render `CGPath`s. - /// Valid shape render groups must have at least one path-drawing item. - var pathItems: [ShapeItemLayer.Item] = [] - /// Shape items that modify the appearance of the shapes rendered by this group - var otherItems: [ShapeItemLayer.Item] = [] -} - -extension [ShapeItemLayer.Item] { - /// Splits this list of `ShapeItem`s into groups that should be rendered together as individual units, - /// plus the remaining items that were not included in any group. - /// - groupHasChildGroupsToInheritUnusedItems: whether or not this group has child groups - /// that will inherit any items that aren't used as part of a valid render group - func shapeRenderGroups(groupHasChildGroupsToInheritUnusedItems: Bool) - -> (validGroups: [ShapeRenderGroup], unusedItems: [ShapeItemLayer.Item]) - { - var renderGroups = [ShapeRenderGroup()] - - for item in self { - // `renderGroups` is non-empty, so is guaranteed to have a valid end index - var lastIndex: Int { - renderGroups.indices.last! - } - - if item.item.drawsCGPath { - // Trims should only affect paths that precede them in the group, - // so if the existing group already has a trim we create a new group for this path item. - if renderGroups[lastIndex].otherItems.contains(where: { $0.item is Trim }) { - renderGroups.append(ShapeRenderGroup()) - } - - renderGroups[lastIndex].pathItems.append(item) - } - - // `Fill` items are unique, because they specifically only apply to _previous_ shapes in a `Group` - // - For example, with [Rectangle, Fill(Red), Circle, Fill(Blue)], the Rectangle should be Red - // but the Circle should be Blue. - // - To handle this, we create a new `ShapeRenderGroup` when we encounter a `Fill` item - else if item.item.isFill { - renderGroups[lastIndex].otherItems.append(item) - - // There are cases where the current render group doesn't have a path-drawing - // shape item yet, and could just contain this fill. Some examples: - // - `[Circle, Fill(Red), Fill(Green)]`: In this case, the second fill would - // be unused and silently ignored. To avoid this we render the fill using - // the shape items from the previous group. - // - `[Circle, Fill(Red), Group, Fill(Green)]`: In this case, the second fill - // is inherited and rendered by the child group. - if - renderGroups[lastIndex].pathItems.isEmpty, - !groupHasChildGroupsToInheritUnusedItems, - lastIndex != renderGroups.indices.first - { - renderGroups[lastIndex].pathItems = renderGroups[lastIndex - 1].pathItems - } - - // Finalize the group so the fill item doesn't affect following shape items - renderGroups.append(ShapeRenderGroup()) - } - - // Other items in the list are applied to all subgroups - else { - for index in renderGroups.indices { - renderGroups[index].otherItems.append(item) - } - } - } - - /// The main thread rendering engine draws each Stroke and Fill as a separate `CAShapeLayer`. - /// As an optimization, we can combine them into a single shape layer when a few conditions are met: - /// 1. There is at most one stroke and one fill (a `CAShapeLayer` can only render one of each) - /// 2. The stroke is drawn on top of the fill (the behavior of a `CAShapeLayer`) - /// 3. The fill and stroke have the same `opacity` animations (since a `CAShapeLayer` can only render - /// a single set of `opacity` animations). - /// Otherwise, each stroke / fill needs to be split into a separate layer. - renderGroups = renderGroups.flatMap { group -> [ShapeRenderGroup] in - let (strokesAndFills, otherItems) = group.otherItems.grouped(by: { $0.item.isFill || $0.item.isStroke }) - let (strokes, fills) = strokesAndFills.grouped(by: { $0.item.isStroke }) - - // A `CAShapeLayer` can only draw a single fill and a single stroke - let hasAtMostOneFill = fills.count <= 1 - let hasAtMostOneStroke = strokes.count <= 1 - - // A `CAShapeLayer` can only draw a stroke on top of a fill -- if the fill is supposed to be - // drawn on top of the stroke, then they have to be rendered as separate layers. - let strokeDrawnOnTopOfFill: Bool - if - let strokeIndex = strokesAndFills.firstIndex(where: { $0.item.isStroke }), - let fillIndex = strokesAndFills.firstIndex(where: { $0.item.isFill }) - { - strokeDrawnOnTopOfFill = strokeIndex < fillIndex - } else { - strokeDrawnOnTopOfFill = false - } - - // `Fill` and `Stroke` items have an `alpha` property that can be animated separately, - // but each layer only has a single `opacity` property. We can only use a single `CAShapeLayer` - // when the items have the same `alpha` animations. - let allAlphaAnimationsAreIdentical = { - strokesAndFills.allSatisfy { item in - (item.item as? OpacityAnimationModel)?.opacity - == (strokesAndFills.first?.item as? OpacityAnimationModel)?.opacity - } - } - - // If all the required conditions are met, this group can be rendered using a single `ShapeItemLayer` - if - hasAtMostOneFill, - hasAtMostOneStroke, - strokeDrawnOnTopOfFill, - allAlphaAnimationsAreIdentical() - { - return [group] - } - - // Otherwise each stroke / fill needs to be rendered as a separate `ShapeItemLayer` - return strokesAndFills.map { strokeOrFill in - ShapeRenderGroup( - pathItems: group.pathItems, - otherItems: [strokeOrFill] + otherItems) - } - } - - // All valid render groups must have a path, otherwise the items wouldn't be rendered - renderGroups = renderGroups.filter { renderGroup in - !renderGroup.pathItems.isEmpty - } - - let itemsInValidRenderGroups = NSSet( - array: renderGroups.lazy - .flatMap { $0.pathItems + $0.otherItems } - .map { $0.item }) - - // `unusedItems` should only include each original item a single time, - // and should preserve the existing order - let itemsNotInValidRenderGroups = filter { item in - !itemsInValidRenderGroups.contains(item.item) - } - - return (validGroups: renderGroups, unusedItems: itemsNotInValidRenderGroups) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/SolidLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/SolidLayer.swift deleted file mode 100644 index 2e1d5e33e154fd8ba1f8a4ce96d91f73ed40f703..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/SolidLayer.swift +++ /dev/null @@ -1,65 +0,0 @@ -// Created by Cal Stephens on 12/13/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - SolidLayer - -final class SolidLayer: BaseCompositionLayer { - - // MARK: Lifecycle - - init(_ solidLayer: SolidLayerModel) { - self.solidLayer = solidLayer - super.init(layerModel: solidLayer) - setupContentLayer() - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - solidLayer = typedLayer.solidLayer - super.init(layer: typedLayer) - } - - // MARK: Internal - - override func setupAnimations(context: LayerAnimationContext) throws { - try super.setupAnimations(context: context) - - var context = context - context = context.addingKeypathComponent(solidLayer.name) - - // Even though the Lottie json schema provides a fixed `solidLayer.colorHex` value, - // we still need to create a set of keyframes and go through the standard `CAAnimation` - // codepath so that this value can be customized using the custom `ValueProvider`s API. - try shapeLayer.addAnimation( - for: .fillColor, - keyframes: KeyframeGroup(solidLayer.colorHex.lottieColor), - value: { $0.cgColorValue }, - context: context) - } - - // MARK: Private - - private let solidLayer: SolidLayerModel - - /// Render the fill color in a child `CAShapeLayer` - /// - Using a `CAShapeLayer` specifically, instead of a `CALayer` with a `backgroundColor`, - /// allows the size of the fill shape to be different from `contentsLayer.size`. - private let shapeLayer = CAShapeLayer() - - private func setupContentLayer() { - shapeLayer.path = CGPath(rect: .init(x: 0, y: 0, width: solidLayer.width, height: solidLayer.height), transform: nil) - addSublayer(shapeLayer) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/TextLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/TextLayer.swift deleted file mode 100644 index 48b77096208c46e3794e0420aee8c6fdc91370c9..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/TextLayer.swift +++ /dev/null @@ -1,115 +0,0 @@ -// Created by Cal Stephens on 2/9/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -/// The `CALayer` type responsible for rendering `TextLayer`s -final class TextLayer: BaseCompositionLayer { - - // MARK: Lifecycle - - init( - textLayerModel: TextLayerModel, - context: LayerContext) - throws - { - self.textLayerModel = textLayerModel - super.init(layerModel: textLayerModel) - setupSublayers() - try configureRenderLayer(with: context) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - textLayerModel = typedLayer.textLayerModel - super.init(layer: typedLayer) - } - - // MARK: Internal - - override func setupAnimations(context: LayerAnimationContext) throws { - try super.setupAnimations(context: context) - let textAnimationContext = context.addingKeypathComponent(textLayerModel.name) - - let sourceText = try textLayerModel.text.exactlyOneKeyframe( - context: textAnimationContext, - description: "text layer text") - - // Prior to Lottie 4.3.0 the Core Animation rendering engine always just used `LegacyAnimationTextProvider` - // but incorrectly called it with the full keypath string, unlike the Main Thread rendering engine - // which only used the last component of the keypath. Starting in Lottie 4.3.0 we use `AnimationKeypathTextProvider` - // instead if implemented. - if let keypathTextValue = context.textProvider.text(for: textAnimationContext.currentKeypath, sourceText: sourceText.text) { - renderLayer.text = keypathTextValue - } else if let legacyTextProvider = context.textProvider as? LegacyAnimationTextProvider { - renderLayer.text = legacyTextProvider.textFor( - keypathName: textAnimationContext.currentKeypath.fullPath, - sourceText: sourceText.text) - } else { - renderLayer.text = sourceText.text - } - - renderLayer.sizeToFit() - } - - func configureRenderLayer(with context: LayerContext) throws { - // We can't use `CATextLayer`, because it doesn't support enough features we use. - // Instead, we use the same `CoreTextRenderLayer` (with a custom `draw` implementation) - // used by the Main Thread rendering engine. This means the Core Animation engine can't - // _animate_ text properties, but it can display static text without any issues. - let text = try textLayerModel.text.exactlyOneKeyframe(context: context, description: "text layer text") - - // The Core Animation engine doesn't currently support `TextAnimator`s. - // - We could add support for animating the transform-related properties without much trouble. - // - We may be able to support animating `fillColor` by getting clever with layer blend modes - // or masks (e.g. use `CoreTextRenderLayer` to draw black glyphs, and then fill them in - // using a `CAShapeLayer`). - if !textLayerModel.animators.isEmpty { - try context.logCompatibilityIssue(""" - The Core Animation rendering engine currently doesn't support text animators. - """) - } - - renderLayer.font = context.fontProvider.fontFor(family: text.fontFamily, size: CGFloat(text.fontSize)) - - renderLayer.alignment = text.justification.textAlignment - renderLayer.lineHeight = CGFloat(text.lineHeight) - renderLayer.tracking = (CGFloat(text.fontSize) * CGFloat(text.tracking)) / 1000 - - renderLayer.fillColor = text.fillColorData?.cgColorValue - renderLayer.strokeColor = text.strokeColorData?.cgColorValue - renderLayer.strokeWidth = CGFloat(text.strokeWidth ?? 0) - renderLayer.strokeOnTop = text.strokeOverFill ?? false - - renderLayer.preferredSize = text.textFrameSize?.sizeValue - renderLayer.sizeToFit() - - renderLayer.transform = CATransform3DIdentity - renderLayer.position = text.textFramePosition?.pointValue ?? .zero - } - - // MARK: Private - - private let textLayerModel: TextLayerModel - private let renderLayer = CoreTextRenderLayer() - - private func setupSublayers() { - // Place the text render layer in an additional container - // - Direct sublayers of a `BaseCompositionLayer` always fill the bounds - // of their superlayer -- so this container will be the bounds of self, - // and the text render layer can be positioned anywhere. - let textContainerLayer = CALayer() - textContainerLayer.addSublayer(renderLayer) - addSublayer(textContainerLayer) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/TransformLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/TransformLayer.swift deleted file mode 100644 index 027739a4473334a52f0987d82ef69d69a2372608..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/Layers/TransformLayer.swift +++ /dev/null @@ -1,11 +0,0 @@ -// Created by Cal Stephens on 12/21/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -/// The CALayer type responsible for only rendering the `transform` of a `LayerModel` -final class TransformLayer: BaseCompositionLayer { - - /// `TransformLayer`s don't render any visible content, - /// they just `transform` their sublayers - override var renderLayerContents: Bool { false } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/ValueProviderStore.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/ValueProviderStore.swift deleted file mode 100644 index 68a1432ca4a7808e6f8d42f63d2ca3b37ef96e52..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/CoreAnimation/ValueProviderStore.swift +++ /dev/null @@ -1,151 +0,0 @@ -// Created by Cal Stephens on 1/13/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - ValueProviderStore - -/// Registration and storage for `AnyValueProvider`s that can dynamically -/// provide custom values for `AnimationKeypath`s within a `LottieAnimation`. -final class ValueProviderStore { - - // MARK: Lifecycle - - init(logger: LottieLogger) { - self.logger = logger - } - - // MARK: Internal - - /// Registers an `AnyValueProvider` for the given `AnimationKeypath` - func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) { - logger.assert( - valueProvider.typeErasedStorage.isSupportedByCoreAnimationRenderingEngine, - """ - The Core Animation rendering engine doesn't support Value Providers that vend a closure, - because that would require calling the closure on the main thread once per frame. - """) - - let supportedProperties = PropertyName.allCases.map { $0.rawValue } - let propertyBeingCustomized = keypath.keys.last ?? "" - - logger.assert( - supportedProperties.contains(propertyBeingCustomized), - """ - The Core Animation rendering engine currently doesn't support customizing "\(propertyBeingCustomized)" \ - properties. Supported properties are: \(supportedProperties.joined(separator: ", ")). - """) - - valueProviders.removeAll(where: { $0.keypath == keypath }) - valueProviders.append((keypath: keypath, valueProvider: valueProvider)) - } - - // Retrieves the custom value keyframes for the given property, - // if an `AnyValueProvider` was registered for the given keypath. - func customKeyframes( - of customizableProperty: CustomizableProperty, - for keypath: AnimationKeypath, - context: LayerAnimationContext) - throws -> KeyframeGroup? - { - context.recordHierarchyKeypath?(keypath.fullPath) - - guard let anyValueProvider = valueProvider(for: keypath) else { - return nil - } - - // Retrieve the type-erased keyframes from the custom `ValueProvider` - let typeErasedKeyframes: [Keyframe] - switch anyValueProvider.typeErasedStorage { - case .singleValue(let typeErasedValue): - typeErasedKeyframes = [Keyframe(typeErasedValue)] - - case .keyframes(let keyframes, _): - typeErasedKeyframes = keyframes - - case .closure: - try context.logCompatibilityIssue(""" - The Core Animation rendering engine doesn't support Value Providers that vend a closure, - because that would require calling the closure on the main thread once per frame. - """) - return nil - } - - // Convert the type-erased keyframe values using this `CustomizableProperty`'s conversion closure - let typedKeyframes = typeErasedKeyframes.compactMap { typeErasedKeyframe -> Keyframe? in - guard let convertedValue = customizableProperty.conversion(typeErasedKeyframe.value, anyValueProvider) else { - logger.assertionFailure(""" - Could not convert value of type \(type(of: typeErasedKeyframe.value)) from \(anyValueProvider) to expected type \( - Value - .self) - """) - return nil - } - - return typeErasedKeyframe.withValue(convertedValue) - } - - // Verify that all of the keyframes were successfully converted to the expected type - guard typedKeyframes.count == typeErasedKeyframes.count else { - return nil - } - - return KeyframeGroup(keyframes: ContiguousArray(typedKeyframes)) - } - - // MARK: Private - - private let logger: LottieLogger - private var valueProviders = [(keypath: AnimationKeypath, valueProvider: AnyValueProvider)]() - - /// Retrieves the most-recently-registered Value Provider that matches the given keypath. - private func valueProvider(for keypath: AnimationKeypath) -> AnyValueProvider? { - // Find the last keypath matching the given keypath, - // so we return the value provider that was registered most-recently - valueProviders.last(where: { registeredKeypath, _ in - keypath.matches(registeredKeypath) - })?.valueProvider - } - -} - -extension AnyValueProviderStorage { - /// Whether or not this type of value provider is supported - /// by the new Core Animation rendering engine - var isSupportedByCoreAnimationRenderingEngine: Bool { - switch self { - case .singleValue, .keyframes: - return true - case .closure: - return false - } - } -} - -extension AnimationKeypath { - /// Whether or not this keypath from the animation hierarchy - /// matches the given keypath (which may contain wildcards) - func matches(_ keypath: AnimationKeypath) -> Bool { - var regex = "^" // match the start of the string - + keypath.keys.joined(separator: "\\.") // match this keypath, escaping "." characters - + "$" // match the end of the string - - // Replace the ** and * wildcards with markers that are guaranteed to be unique - // and won't conflict with regex syntax (e.g. `.*`). - let doubleWildcardMarker = UUID().uuidString - let singleWildcardMarker = UUID().uuidString - regex = regex.replacingOccurrences(of: "**", with: doubleWildcardMarker) - regex = regex.replacingOccurrences(of: "*", with: singleWildcardMarker) - - // "**" wildcards match zero or more path segments separated by "\\." - // - "**.Color" matches any of "Color", "Layer 1.Color", and "Layer 1.Layer 2.Color" - regex = regex.replacingOccurrences(of: "\(doubleWildcardMarker)\\.", with: ".*") - regex = regex.replacingOccurrences(of: doubleWildcardMarker, with: ".*") - - // "*" wildcards match exactly one path component - // - "*.Color" matches "Layer 1.Color" but not "Layer 1.Layer 2.Color" - regex = regex.replacingOccurrences(of: singleWildcardMarker, with: "[^.]+") - - return fullPath.range(of: regex, options: .regularExpression) != nil - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/Collection+Diff.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/Collection+Diff.swift deleted file mode 100644 index 572e2a2812eba9f6046061ccc47a50b1e86fb526..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/Collection+Diff.swift +++ /dev/null @@ -1,263 +0,0 @@ -// Created by Laura Skelton on 11/25/16. -// Copyright © 2016 Airbnb. All rights reserved. - -// MARK: - Collection - -extension Collection where Element: Diffable, Index == Int { - - /// Diffs two collections (e.g. `Array`s) of `Diffable` items, returning an `IndexChangeset` - /// representing the minimal set of changes to get from the other collection to this collection. - /// - /// - Parameters: - /// - from other: The collection of old data. - func makeChangeset(from other: Self) -> IndexChangeset { - // Arranging the elements contiguously prior to diffing improves performance by ~40%. - let new = ContiguousArray(self) - let old = ContiguousArray(other) - - /// The entries in both this and the other collection, keyed by their `dataID`s. - var entries = [AnyHashable: EpoxyEntry](minimumCapacity: new.count) - var duplicates = [EpoxyEntry]() - - var newResults = ContiguousArray() - newResults.reserveCapacity(new.count) - - for index in new.indices { - let id = new[index].diffIdentifier - let entry = entries[id, default: EpoxyEntry()] - if entry.trackNewIndex(index) { - duplicates.append(entry) - } - entries[id] = entry - newResults.append(NewRecord(entry: entry)) - } - - var oldResults = ContiguousArray() - oldResults.reserveCapacity(old.count) - - for index in old.indices { - let id = old[index].diffIdentifier - let entry = entries[id] - entry?.pushOldIndex(index) - oldResults.append(OldRecord(entry: entry)) - } - - for newIndex in new.indices { - let entry = newResults[newIndex].entry - if let oldIndex = entry.popOldIndex() { - let newItem = new[newIndex] - let oldItem = other[oldIndex] - - if !oldItem.isDiffableItemEqual(to: newItem) { - entry.isUpdated = true - } - - newResults[newIndex].correspondingOldIndex = oldIndex - oldResults[oldIndex].correspondingNewIndex = newIndex - } - } - - var deletes = [Int]() - var deleteOffsets = [Int]() - deleteOffsets.reserveCapacity(old.count) - var runningDeleteOffset = 0 - - for index in old.indices { - deleteOffsets.append(runningDeleteOffset) - - let record = oldResults[index] - - if record.correspondingNewIndex == nil { - deletes.append(index) - runningDeleteOffset += 1 - } - } - - var inserts = [Int]() - var updates = [(Int, Int)]() - var moves = [(Int, Int)]() - var insertOffsets = [Int]() - insertOffsets.reserveCapacity(new.count) - var runningInsertOffset = 0 - - for index in new.indices { - insertOffsets.append(runningInsertOffset) - - let record = newResults[index] - - if let oldArrayIndex = record.correspondingOldIndex { - if record.entry.isUpdated { - updates.append((oldArrayIndex, index)) - } - - let insertOffset = insertOffsets[index] - let deleteOffset = deleteOffsets[oldArrayIndex] - if (oldArrayIndex - deleteOffset + insertOffset) != index { - moves.append((oldArrayIndex, index)) - } - - } else { - inserts.append(index) - runningInsertOffset += 1 - } - } - - EpoxyLogger.shared.assert( - old.count + inserts.count - deletes.count == new.count, - "Failed sanity check for old count with changes matching new count.") - - return IndexChangeset( - inserts: inserts, - deletes: deletes, - updates: updates, - moves: moves, - newIndices: oldResults.map { $0.correspondingNewIndex }, - duplicates: duplicates.map { $0.newIndices }) - } - - /// Diffs between two collections (eg. `Array`s) of `Diffable` items, and returns an `IndexPathChangeset` - /// representing the minimal set of changes to get from the other collection to this collection. - /// - /// - Parameters: - /// - from other: The collection of old data. - /// - fromSection: The section the other collection's data exists within. Defaults to `0`. - /// - toSection: The section this collection's data exists within. Defaults to `0`. - func makeIndexPathChangeset( - from other: Self, - fromSection: Int = 0, - toSection: Int = 0) - -> IndexPathChangeset - { - let indexChangeset = makeChangeset(from: other) - - return IndexPathChangeset( - inserts: indexChangeset.inserts.map { index in - [toSection, index] - }, - deletes: indexChangeset.deletes.map { index in - [fromSection, index] - }, - updates: indexChangeset.updates.map { fromIndex, toIndex in - ([fromSection, fromIndex], [toSection, toIndex]) - }, - moves: indexChangeset.moves.map { fromIndex, toIndex in - ([fromSection, fromIndex], [toSection, toIndex]) - }, - duplicates: indexChangeset.duplicates.map { duplicate in - duplicate.map { index in - [toSection, index] - } - }) - } - - /// Diffs between two collections (e.g. `Array`s) of `Diffable` items, returning an - /// `IndexSetChangeset` representing the minimal set of changes to get from the other collection - /// to this collection. - /// - /// - Parameters: - /// - from other: The collection of old data. - func makeIndexSetChangeset(from other: Self) -> IndexSetChangeset { - let indexChangeset = makeChangeset(from: other) - - return IndexSetChangeset( - inserts: .init(indexChangeset.inserts), - deletes: .init(indexChangeset.deletes), - updates: indexChangeset.updates, - moves: indexChangeset.moves, - newIndices: indexChangeset.newIndices, - duplicates: indexChangeset.duplicates.map { .init($0) }) - } - -} - -extension Collection where Element: DiffableSection, Index == Int { - /// Diffs between two collections (e.g. `Array`s) of `DiffableSection` items, returning an - /// `SectionedChangeset` representing the minimal set of changes to get from the other collection - /// to this collection. - /// - /// - Parameters: - /// - from other: The collection of old data. - func makeSectionedChangeset(from other: Self) -> SectionedChangeset { - let sectionChangeset = makeIndexSetChangeset(from: other) - var itemChangeset = IndexPathChangeset() - - for fromSectionIndex in other.indices { - guard let toSectionIndex = sectionChangeset.newIndices[fromSectionIndex] else { - continue - } - - let fromItems = other[fromSectionIndex].diffableItems - let toItems = self[toSectionIndex].diffableItems - - let itemIndexChangeset = toItems.makeIndexPathChangeset( - from: fromItems, - fromSection: fromSectionIndex, - toSection: toSectionIndex) - - itemChangeset += itemIndexChangeset - } - - return SectionedChangeset(sectionChangeset: sectionChangeset, itemChangeset: itemChangeset) - } -} - -// MARK: - EpoxyEntry - -/// A bookkeeping refrence type for the diffing algorithm. -private final class EpoxyEntry { - - // MARK: Internal - - private(set) var oldIndices = [Int]() - private(set) var newIndices = [Int]() - var isUpdated = false - - /// Tracks an index from the new indices, returning `true` if this entry has previously tracked - /// a new index as a means to identify duplicates and `false` otherwise. - func trackNewIndex(_ index: Int) -> Bool { - let previouslyEmpty = newIndices.isEmpty - - newIndices.append(index) - - // We've encountered a duplicate, return true so we can track it. - if !previouslyEmpty, newIndices.count == 2 { - return true - } - - return false - } - - func pushOldIndex(_ index: Int) { - oldIndices.append(index) - } - - func popOldIndex() -> Int? { - guard currentOldIndex < oldIndices.endIndex else { - return nil - } - defer { - currentOldIndex += 1 - } - return oldIndices[currentOldIndex] - } - - // MARK: Private - - private var currentOldIndex = 0 -} - -// MARK: - OldRecord - -/// A bookkeeping type for pairing up an old element with its new index. -private struct OldRecord { - var entry: EpoxyEntry? - var correspondingNewIndex: Int? = nil -} - -// MARK: - NewRecord - -/// A bookkeeping type for pairing up a new element with its old index. -private struct NewRecord { - var entry: EpoxyEntry - var correspondingOldIndex: Int? = nil -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/Diffable.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/Diffable.swift deleted file mode 100644 index 4cb0b2d2cdf8e018c73b8d9353b1b820ef0cdc38..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/Diffable.swift +++ /dev/null @@ -1,18 +0,0 @@ -// Created by Laura Skelton on 5/11/17. -// Copyright © 2017 Airbnb. All rights reserved. - -// MARK: - Diffable - -/// A protocol that allows us to check identity and equality between items for the purposes of -/// diffing. -protocol Diffable { - - /// Checks for equality between items when diffing. - /// - /// - Parameters: - /// - otherDiffableItem: The other item to check equality against while diffing. - func isDiffableItemEqual(to otherDiffableItem: Diffable) -> Bool - - /// The identifier to use when checking identity while diffing. - var diffIdentifier: AnyHashable { get } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/DiffableSection.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/DiffableSection.swift deleted file mode 100644 index acbf93a639a51c34e9f34bdfbdef10786008a2a6..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/DiffableSection.swift +++ /dev/null @@ -1,16 +0,0 @@ -// Created by eric_horacek on 12/9/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - DiffableSection - -/// A protocol that allows us to check identity and equality between sections of `Diffable` items -/// for the purposes of diffing. -protocol DiffableSection: Diffable { - /// The diffable items in this section. - associatedtype DiffableItems: Collection where - DiffableItems.Index == Int, - DiffableItems.Element: Diffable - - /// The diffable items in this section. - var diffableItems: DiffableItems { get } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/IndexChangeset.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/IndexChangeset.swift deleted file mode 100644 index 2cb8653db8826477b900ab9eee671a02b1cf8740..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/IndexChangeset.swift +++ /dev/null @@ -1,187 +0,0 @@ -// Created by Laura Skelton on 11/25/16. -// Copyright © 2016 Airbnb. All rights reserved. - -import Foundation - -// MARK: - IndexChangeset - -/// A set of inserts, deletes, updates, and moves that define the changes between two collections. -struct IndexChangeset { - - // MARK: Lifecycle - - init( - inserts: [Int] = [], - deletes: [Int] = [], - updates: [(old: Int, new: Int)] = [], - moves: [(old: Int, new: Int)] = [], - newIndices: [Int?] = [], - duplicates: [[Int]] = []) - { - self.inserts = inserts - self.deletes = deletes - self.updates = updates - self.moves = moves - self.newIndices = newIndices - self.duplicates = duplicates - } - - // MARK: Internal - - /// The inserted indices needed to get from the old collection to the new collection. - var inserts: [Int] - - /// The deleted indices needed to get from the old collection to the new collection. - var deletes: [Int] - - /// The updated indices needed to get from the old collection to the new collection. - var updates: [(old: Int, new: Int)] - - /// The moved indices needed to get from the old collection to the new collection. - var moves: [(old: Int, new: Int)] - - /// A record for each old collection item to its index (if any) is in the new collection. - /// - /// The indexes of this `Array` represent the indexes old collection, with elements of the - /// corresponding index of the same item in the new collection it exists, else `nil`. - var newIndices: [Int?] - - /// A record of each element in the new collection that has an identical `diffIdentifier` with - /// another element in the same collection. - /// - /// Each element in the outer `Array` corresponds to a duplicated identifier, with each inner - /// `[Int]` containing the indexes that share a duplicate identifier in the new collection. - /// - /// While the diffing algorithm makes a best effort to handle duplicates, they can lead to - /// unexpected behavior since identity of elements cannot be established and should be avoided if - /// possible. - var duplicates: [[Int]] - - /// Whether there are any inserts, deletes, moves, or updates in this changeset. - var isEmpty: Bool { - inserts.isEmpty && deletes.isEmpty && updates.isEmpty && moves.isEmpty - } -} - -// MARK: - IndexPathChangeset - -/// A set of inserts, deletes, updates, and moves that define the changes between two collections -/// with indexes stored as `IndexPath`s. -struct IndexPathChangeset { - - // MARK: Lifecycle - - init( - inserts: [IndexPath] = [], - deletes: [IndexPath] = [], - updates: [(old: IndexPath, new: IndexPath)] = [], - moves: [(old: IndexPath, new: IndexPath)] = [], - duplicates: [[IndexPath]] = []) - { - self.inserts = inserts - self.deletes = deletes - self.updates = updates - self.moves = moves - self.duplicates = duplicates - } - - // MARK: Internal - - /// The inserted `IndexPath`s needed to get from the old collection to the new collection. - var inserts: [IndexPath] - - /// The deleted `IndexPath`s needed to get from the old collection to the new collection. - var deletes: [IndexPath] - - /// The updated `IndexPath`s needed to get from the old collection to the new collection. - var updates: [(old: IndexPath, new: IndexPath)] - - /// The moved `IndexPath`s needed to get from the old collection to the new collection. - var moves: [(old: IndexPath, new: IndexPath)] - - /// A record for each element in the new collection that has an identical `diffIdentifier` with - /// another element in the same collection. - /// - /// Each element in the outer `Array` corresponds to a duplicated identifier, with each inner - /// `[IndexPath]` corresponding to the indexes that share a duplicate identifier in the new - /// collection. - /// - /// While the diffing algorithm makes a best effort to handle duplicates, they can lead to - /// unexpected behavior since identity of elements cannot be established and should be avoided if - /// possible. - var duplicates: [[IndexPath]] - - /// Whether there are any inserts, deletes, moves, or updates in this changeset. - var isEmpty: Bool { - inserts.isEmpty && deletes.isEmpty && updates.isEmpty && moves.isEmpty - } - - static func += (left: inout IndexPathChangeset, right: IndexPathChangeset) { - left.inserts += right.inserts - left.deletes += right.deletes - left.updates += right.updates - left.moves += right.moves - left.duplicates += right.duplicates - } -} - -// MARK: - IndexSetChangeset - -/// A set of inserts, deletes, updates, and moves that define the changes between two collections -/// with indexes stored as `IndexSet`. -struct IndexSetChangeset { - - // MARK: Lifecycle - - init( - inserts: IndexSet = [], - deletes: IndexSet = [], - updates: [(old: Int, new: Int)] = [], - moves: [(old: Int, new: Int)] = [], - newIndices: [Int?] = [], - duplicates: [IndexSet] = []) - { - self.inserts = inserts - self.deletes = deletes - self.updates = updates - self.moves = moves - self.newIndices = newIndices - self.duplicates = duplicates - } - - // MARK: Internal - - /// An `IndexSet` of inserts needed to get from the old collection to the new collection. - var inserts: IndexSet - - /// An `IndexSet` of deletes needed to get from the old collection to the new collection. - var deletes: IndexSet - - /// The updated indices needed to get from the old collection to the new collection. - var updates: [(old: Int, new: Int)] - - /// The moved indices needed to get from the old collection to the new collection. - var moves: [(old: Int, new: Int)] - - /// A record for each old collection item of what its index (if any) is in the new collection. - /// - /// The indexes of this `Array` represent the indexes old collection, with elements of the - /// corresponding index of the same item in the new collection it exists, else `nil`. - var newIndices: [Int?] - - /// A record for each element in the new collection that has an identical `diffIdentifier` with - /// another element in the same collection. - /// - /// Each element in the `Array` corresponds to a duplicated identifier, with each `IndexSet` - /// containing the indexes that share a duplicate identifier in the new collection. - /// - /// While the diffing algorithm makes a best effort to handle duplicates, they can lead to - /// unexpected behavior since identity of elements cannot be established and should be avoided if - /// possible. - var duplicates: [IndexSet] - - /// Whether there are any inserts, deletes, moves, or updates in this changeset. - var isEmpty: Bool { - inserts.isEmpty && deletes.isEmpty && updates.isEmpty && moves.isEmpty - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/SectionedChangeset.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/SectionedChangeset.swift deleted file mode 100644 index f18fae5737fbdfd3762ec63a9d81c7d5e3d436ef..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Diffing/SectionedChangeset.swift +++ /dev/null @@ -1,32 +0,0 @@ -// Created by Laura Skelton on 5/11/17. -// Copyright © 2017 Airbnb. All rights reserved. - -/// A set of the minimum changes to get from one array of `DiffableSection`s to another, used for -/// diffing. -struct SectionedChangeset { - - // MARK: Lifecycle - - init( - sectionChangeset: IndexSetChangeset, - itemChangeset: IndexPathChangeset) - { - self.sectionChangeset = sectionChangeset - self.itemChangeset = itemChangeset - } - - // MARK: Internal - - /// A set of the minimum changes to get from one set of sections to another. - var sectionChangeset: IndexSetChangeset - - /// A set of the minimum changes to get from one set of items to another, aggregated across all - /// sections. - var itemChangeset: IndexPathChangeset - - /// Whether there are any inserts, deletes, moves, or updates in this changeset. - var isEmpty: Bool { - sectionChangeset.isEmpty && itemChangeset.isEmpty - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Logging/EpoxyLogger.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Logging/EpoxyLogger.swift deleted file mode 100644 index 405c4d7f68baaf961a6367149b23c9eb885cbe16..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Logging/EpoxyLogger.swift +++ /dev/null @@ -1,99 +0,0 @@ -// Created by eric_horacek on 12/9/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -/// A shared logger that allows consumers to intercept Epoxy assertions and warning messages to pipe -/// into their own logging systems. -final class EpoxyLogger { - - // MARK: Lifecycle - - init( - assert: @escaping Assert = { condition, message, file, line in - // If we default to `Swift.assert` directly with `assert: Assert = Swift.assert`, - // the call will unexpectedly not respect the -O flag and will crash in release - // https://github.com/apple/swift/issues/60249 - Swift.assert(condition(), message(), file: file, line: line) - }, - assertionFailure: @escaping AssertionFailure = { message, file, line in - // If we default to `Swift.assertionFailure` directly with - // `assertionFailure: AssertionFailure = Swift.assertionFailure`, - // the call will unexpectedly not respect the -O flag and will crash in release - // https://github.com/apple/swift/issues/60249 - Swift.assertionFailure(message(), file: file, line: line) - }, - warn: @escaping Warn = { message, _, _ in - #if DEBUG - // swiftlint:disable:next no_direct_standard_out_logs - print(message()) - #endif - }) - { - _assert = assert - _assertionFailure = assertionFailure - _warn = warn - } - - // MARK: Internal - - /// Logs that an assertion occurred. - typealias Assert = ( - _ condition: @autoclosure () -> Bool, - _ message: @autoclosure () -> String, - _ fileID: StaticString, - _ line: UInt) - -> Void - - /// Logs that an assertion failure occurred. - typealias AssertionFailure = ( - _ message: @autoclosure () -> String, - _ fileID: StaticString, - _ line: UInt) - -> Void - - /// Logs a warning message. - typealias Warn = ( - _ message: @autoclosure () -> String, - _ fileID: StaticString, - _ line: UInt) - -> Void - - /// The shared instance used to log Epoxy assertions and warnings. - /// - /// Set this to a new logger instance to intercept assertions and warnings logged by Epoxy. - static var shared = EpoxyLogger() - - /// Logs that an assertion occurred. - func assert( - _ condition: @autoclosure () -> Bool, - _ message: @autoclosure () -> String = String(), - fileID: StaticString = #fileID, - line: UInt = #line) - { - _assert(condition(), message(), fileID, line) - } - - /// Logs that an assertion failure occurred. - func assertionFailure( - _ message: @autoclosure () -> String = String(), - fileID: StaticString = #fileID, - line: UInt = #line) - { - _assertionFailure(message(), fileID, line) - } - - /// Logs a warning message. - func warn( - _ message: @autoclosure () -> String = String(), - fileID: StaticString = #fileID, - line: UInt = #line) - { - _warn(message(), fileID, line) - } - - // MARK: Private - - private let _assert: Assert - private let _assertionFailure: AssertionFailure - private let _warn: Warn - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/CallbackContextEpoxyModeled.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/CallbackContextEpoxyModeled.swift deleted file mode 100644 index 7a6ecbc07043bcd698b692450b65d128c2519a4c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/CallbackContextEpoxyModeled.swift +++ /dev/null @@ -1,8 +0,0 @@ -// Created by eric_horacek on 12/15/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -/// An Epoxy model with an associated context type that's passed into callback closures. -protocol CallbackContextEpoxyModeled: EpoxyModeled { - /// A context type that's passed into callback closures. - associatedtype CallbackContext -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelArrayBuilder.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelArrayBuilder.swift deleted file mode 100644 index a846ba27eb1e41adc4fadb2cd91d120b9682be84..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelArrayBuilder.swift +++ /dev/null @@ -1,48 +0,0 @@ -// Created by eric_horacek on 3/15/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -/// A generic result builder that enables a DSL for building arrays of Epoxy models. -@resultBuilder -enum EpoxyModelArrayBuilder { - typealias Expression = Model - typealias Component = [Model] - - static func buildExpression(_ expression: Expression) -> Component { - [expression] - } - - static func buildExpression(_ expression: Component) -> Component { - expression - } - - static func buildExpression(_ expression: Expression?) -> Component { - if let expression { - return [expression] - } - return [] - } - - static func buildBlock(_ children: Component...) -> Component { - children.flatMap { $0 } - } - - static func buildBlock(_ component: Component) -> Component { - component - } - - static func buildOptional(_ children: Component?) -> Component { - children ?? [] - } - - static func buildEither(first child: Component) -> Component { - child - } - - static func buildEither(second child: Component) -> Component { - child - } - - static func buildArray(_ components: [Component]) -> Component { - components.flatMap { $0 } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelProperty.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelProperty.swift deleted file mode 100644 index a7905cb58858c446ee94d697867b5c59810632e1..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelProperty.swift +++ /dev/null @@ -1,158 +0,0 @@ -// Created by eric_horacek on 11/18/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - EpoxyModelProperty - -/// A property that can be stored in any concrete `EpoxyModeled` type. -/// -/// Custom model properties can be declared in any module. It's recommended that properties are -/// declared as `var`s in extensions to `EpoxyModeled` with a `*Property` suffix. -/// -/// For example, to declare a `EpoxyModelProperty` that fulfills the `TitleProviding` protocol: -/// -/// ```` -/// internal protocol TitleProviding { -/// var title: String? { get } -/// } -/// -/// extension EpoxyModeled where Self: TitleProviding { -/// internal var title: String? { -/// get { self[titleProperty] } -/// set { self[titleProperty] = newValue } -/// } -/// -/// internal func title(_ value: String?) -> Self { -/// copy(updating: titleProperty, to: value) -/// } -/// -/// private var titleProperty: EpoxyModelProperty { -/// .init(keyPath: \TitleProviding.title, defaultValue: nil, updateStrategy: .replace) -/// } -/// } -/// ```` -struct EpoxyModelProperty { - - // MARK: Lifecycle - - /// Creates a property identified by a `KeyPath` to its provided `value` and with its default - /// value if not customized in content by consumers. - /// - /// The `updateStrategy` is used to update the value when updating from an old value to a new - /// value. - init( - keyPath: KeyPath, - defaultValue: @escaping @autoclosure () -> Value, - updateStrategy: UpdateStrategy) - { - self.keyPath = keyPath - self.defaultValue = defaultValue - self.updateStrategy = updateStrategy - } - - // MARK: Internal - - /// The `KeyPath` that uniquely identifies this property. - let keyPath: AnyKeyPath - - /// A closure that produces the default property value when called. - let defaultValue: () -> Value - - /// A closure used to update an `EpoxyModelProperty` from an old value to a new value. - let updateStrategy: UpdateStrategy - -} - -// MARK: EpoxyModelProperty.UpdateStrategy - -extension EpoxyModelProperty { - /// A closure used to update an `EpoxyModelProperty` from an old value to a new value. - struct UpdateStrategy { - - // MARK: Lifecycle - - init(update: @escaping (Value, Value) -> Value) { - self.update = update - } - - // MARK: Public - - /// A closure used to update an `EpoxyModelProperty` from an old value to a new value. - var update: (_ old: Value, _ new: Value) -> Value - } -} - -// MARK: Defaults - -extension EpoxyModelProperty.UpdateStrategy { - /// Replaces the old value with the new value when an update occurs. - static var replace: Self { - .init { _, new in new } - } - - /// Chains the new closure value onto the old closure value, returning a new closure that first - /// calls the old closure and then subsequently calls the new closure. - static func chain() -> EpoxyModelProperty<(() -> Void)?>.UpdateStrategy { - .init { old, new in - guard let new else { return old } - guard let old else { return new } - return { - old() - new() - } - } - } - - /// Chains the new closure value onto the old closure value, returning a new closure that first - /// calls the old closure and then subsequently calls the new closure. - static func chain() -> EpoxyModelProperty<((A) -> Void)?>.UpdateStrategy { - .init { old, new in - guard let new else { return old } - guard let old else { return new } - return { a in - old(a) - new(a) - } - } - } - - /// Chains the new closure value onto the old closure value, returning a new closure that first - /// calls the old closure and then subsequently calls the new closure. - static func chain() -> EpoxyModelProperty<((A, B) -> Void)?>.UpdateStrategy { - .init { old, new in - guard let new else { return old } - guard let old else { return new } - return { a, b in - old(a, b) - new(a, b) - } - } - } - - /// Chains the new closure value onto the old closure value, returning a new closure that first - /// calls the old closure and then subsequently calls the new closure. - static func chain() -> EpoxyModelProperty<((A, B, C) -> Void)?>.UpdateStrategy { - .init { old, new in - guard let new else { return old } - guard let old else { return new } - return { a, b, c in - old(a, b, c) - new(a, b, c) - } - } - } - - /// Chains the new closure value onto the old closure value, returning a new closure that first - /// calls the old closure and then subsequently calls the new closure. - static func chain() -> EpoxyModelProperty<((A, B, C, D) -> Void)?>.UpdateStrategy { - .init { old, new in - guard let new else { return old } - guard let old else { return new } - return { a, b, c, d in - old(a, b, c, d) - new(a, b, c, d) - } - } - } - - // Add more arities as needed -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelStorage.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelStorage.swift deleted file mode 100644 index e6377cba7dfb71c912e498846da2896024ed091f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelStorage.swift +++ /dev/null @@ -1,88 +0,0 @@ -// Created by eric_horacek on 11/18/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - EpoxyModelStorage - -/// The underlying storage for an `EpoxyModeled` model that is capable of storing any -/// `EpoxyModelProperty`. -/// -/// Supports being extended with additional storage capabilities in other modules and conditionally -/// based on the provider capabilities that the content containing this storage conforms to. -struct EpoxyModelStorage { - - // MARK: Lifecycle - - init() { } - - // MARK: Internal - - /// Stores or retrieves the value of the specified property. - subscript(property: EpoxyModelProperty) -> Property { - get { - guard let propertyStorage = storage[property.keyPath] else { - return property.defaultValue() - } - - // This cast will never fail as the storage is only settable via this subscript and the - // `KeyPath` key is unique for any provider and value type pair. - // swiftlint:disable:next force_cast - return propertyStorage.value as! Property - } - set { - // We first update the value without using the `updateStrategy` since the likely scenario - // is that there won't be a collision that requires the `updateStrategy`, and we'll be able to - // return without incurring the cost of another write. - let propertyStorage = PropertyStorage(value: newValue, property: property) - - guard var replaced = storage.updateValue(propertyStorage, forKey: property.keyPath) else { - return - } - - // This cast will never fail as the storage is only settable via this subscript and the - // `KeyPath` key is unique for any provider and value type pair. - // swiftlint:disable:next force_cast - replaced.value = property.updateStrategy.update(replaced.value as! Property, newValue) - - storage[property.keyPath] = replaced - } - } - - /// Merges the given storage into this storage. - /// - /// In the case of a collision, the `UpdateStrategy` of the property is used to determine the - /// resulting value in this storage. - mutating func merge(_ other: Self) { - for (key, otherValue) in other.storage { - // We first update the value without using the `updateStrategy` since the likely scenario - // is that there won't be a collision that requires the `updateStrategy`, and we'll be able to - // return without incurring the cost of another write. - guard var replaced = storage.updateValue(otherValue, forKey: key) else { - continue - } - - replaced.value = replaced.property.update(old: replaced.value, new: otherValue.value) - - storage[key] = replaced - } - } - - // MARK: Private - - /// The underlying storage for the properties, with a key of the `EpoxyModelProperty.keyPath` and - /// a value of the property's `PropertyStorage`. - /// - /// Does not include default values. - private var storage = [AnyKeyPath: PropertyStorage]() - -} - -// MARK: - PropertyStorage - -/// A value stored within an `EpoxyModelStorage`. -private struct PropertyStorage { - /// The type-erased value of the `EpoxyModelProperty`. - var value: Any - - /// The property's corresponding `EpoxyModelProperty`, erased to an `AnyEpoxyModelProperty`. - var property: AnyEpoxyModelProperty -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModeled.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModeled.swift deleted file mode 100644 index 98e6787d5d71edb3cc3756f6f0f5d198508731a4..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModeled.swift +++ /dev/null @@ -1,54 +0,0 @@ -// Created by eric_horacek on 11/18/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - EpoxyModeled - -/// A protocol that all concrete Epoxy declarative UI model types conform to. -/// -/// This protocol should be conditionally extended to fulfill provider protocols and with chainable -/// setters for those providers that concrete model types can receive by declaring conformance to -/// provider protocols. -protocol EpoxyModeled { - /// The underlying storage of this model that stores the current property values. - var storage: EpoxyModelStorage { get set } -} - -// MARK: Extensions - -extension EpoxyModeled { - /// Stores or retrieves a value of the specified property in `storage`. - /// - /// If the value was set previously for the given `property`, the conflict is resolved using the - /// `EpoxyModelProperty.UpdateStrategy` of the `property`. - subscript(property: EpoxyModelProperty) -> Property { - get { storage[property] } - set { storage[property] = newValue } - } - - /// Returns a copy of this model with the given property updated to the provided value. - /// - /// Typically called from within the context of a chainable setter to allow fluent setting of a - /// property, e.g.: - /// - /// ```` - /// internal func title(_ value: String?) -> Self { - /// copy(updating: titleProperty, to: value) - /// } - /// ```` - /// - /// If a `value` was set previously for the given `property`, the conflict is resolved using the - /// `EpoxyModelProperty.UpdateStrategy` of the `property`. - func copy(updating property: EpoxyModelProperty, to value: Value) -> Self { - var copy = self - copy.storage[property] = value - return copy - } - - /// Returns a copy of this model produced by merging the given `other` model's storage into this - /// model's storage. - func merging(_ other: EpoxyModeled) -> Self { - var copy = self - copy.storage.merge(other.storage) - return copy - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/AnyEpoxyModelProperty.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/AnyEpoxyModelProperty.swift deleted file mode 100644 index f5fb10abd673737378328ccb419faf9a8a7e576f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/AnyEpoxyModelProperty.swift +++ /dev/null @@ -1,29 +0,0 @@ -// Created by eric_horacek on 12/1/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - AnyEpoxyModelProperty - -/// An erased `EpoxyModelProperty`, with the ability to call the `UpdateStrategy` even when the type -/// has been erased. -protocol AnyEpoxyModelProperty { - /// Returns the updated property from updating from given old to new property. - func update(old: Any, new: Any) -> Any -} - -// MARK: - EpoxyModelProperty + AnyEpoxyModelProperty - -extension EpoxyModelProperty: AnyEpoxyModelProperty { - func update(old: Any, new: Any) -> Any { - guard let typedOld = old as? Value else { - EpoxyLogger.shared.assertionFailure( - "Expected old to be of type \(Value.self), instead found \(old). This is programmer error.") - return defaultValue() - } - guard let typedNew = new as? Value else { - EpoxyLogger.shared.assertionFailure( - "Expected new to be of type \(Value.self), instead found \(old). This is programmer error.") - return defaultValue() - } - return updateStrategy.update(typedOld, typedNew) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/ClassReference.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/ClassReference.swift deleted file mode 100644 index e3edc246c3f9ace5288d3d3277527cae1364bf44..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Internal/ClassReference.swift +++ /dev/null @@ -1,39 +0,0 @@ -// Created by Cal Stephens on 10/15/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -// MARK: - ClassReference - -/// A `Hashable` value wrapper around an `AnyClass` value -/// - Unlike `ObjectIdentifier(class)`, `ClassReference(class)` -/// preserves the `AnyClass` value and is more human-readable. -struct ClassReference { - init(_ class: AnyClass) { - self.class = `class` - } - - let `class`: AnyClass -} - -// MARK: Equatable - -extension ClassReference: Equatable { - static func ==(_ lhs: Self, _ rhs: Self) -> Bool { - ObjectIdentifier(lhs.class) == ObjectIdentifier(rhs.class) - } -} - -// MARK: Hashable - -extension ClassReference: Hashable { - func hash(into hasher: inout Hasher) { - hasher.combine(ObjectIdentifier(`class`)) - } -} - -// MARK: CustomStringConvertible - -extension ClassReference: CustomStringConvertible { - var description: String { - String(describing: `class`) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/AnimatedProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/AnimatedProviding.swift deleted file mode 100644 index 1862b2515b1a6eee3358777b871c5e41d5020db1..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/AnimatedProviding.swift +++ /dev/null @@ -1,10 +0,0 @@ -// Created by eric_horacek on 12/16/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -/// The capability of providing a flag indicating whether an operation should be animated. -/// -/// Typically conformed to by the `CallbackContext` of a `CallbackContextEpoxyModeled`. -protocol AnimatedProviding { - /// Whether this operation should be animated. - var animated: Bool { get } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DataIDProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DataIDProviding.swift deleted file mode 100644 index bf82156db7cf210d683587bd0fc27e1625e18bfd..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DataIDProviding.swift +++ /dev/null @@ -1,57 +0,0 @@ -// Created by eric_horacek on 12/1/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - DataIDProviding - -/// The capability of providing a stable data identifier with an erased type. -/// -/// While it has similar semantics, this type cannot inherit from `Identifiable` as this would give -/// it an associated type, which would cause the `keyPath` used in its `EpoxyModelProperty` to not -/// be stable across types if written as `\Self.dataID` since the `KeyPath` `Root` would be -/// different for each type. -/// -/// - SeeAlso: `Identifiable`. -protocol DataIDProviding { - /// A stable identifier that uniquely identifies this instance, with its typed erased. - /// - /// Defaults to `DefaultDataID.noneProvided` if no data ID is provided. - var dataID: AnyHashable { get } -} - -// MARK: - EpoxyModeled - -extension EpoxyModeled where Self: DataIDProviding { - - // MARK: Internal - - /// A stable identifier that uniquely identifies this model, with its typed erased. - var dataID: AnyHashable { - get { self[dataIDProperty] } - set { self[dataIDProperty] = newValue } - } - - /// Returns a copy of this model with the ID replaced with the provided ID. - func dataID(_ value: AnyHashable) -> Self { - copy(updating: dataIDProperty, to: value) - } - - // MARK: Private - - private var dataIDProperty: EpoxyModelProperty { - EpoxyModelProperty( - keyPath: \DataIDProviding.dataID, - defaultValue: DefaultDataID.noneProvided, - updateStrategy: .replace) - } -} - -// MARK: - DefaultDataID - -/// The default data ID when none is provided. -enum DefaultDataID: Hashable, CustomDebugStringConvertible { - case noneProvided - - var debugDescription: String { - "DefaultDataID.noneProvided" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidDisplayProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidDisplayProviding.swift deleted file mode 100644 index 5a2f2cbb57e85548dba49815df9930f0165a9f22..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidDisplayProviding.swift +++ /dev/null @@ -1,41 +0,0 @@ -// Created by eric_horacek on 1/6/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -// MARK: - DidDisplayProviding - -/// A sentinel protocol for enabling an `CallbackContextEpoxyModeled` to provide a `didDisplay` -/// closure property. -/// -/// - SeeAlso: `WillDisplayProviding` -/// - SeeAlso: `DidEndDisplayingProviding` -protocol DidDisplayProviding { } - -// MARK: - CallbackContextEpoxyModeled - -extension CallbackContextEpoxyModeled where Self: DidDisplayProviding { - - // MARK: Internal - - /// A closure that's called after a view has been added to the view hierarchy following any - /// appearance animations. - typealias DidDisplay = (_ context: CallbackContext) -> Void - - /// A closure that's called after the view has been added to the view hierarchy following any - /// appearance animations. - var didDisplay: DidDisplay? { - get { self[didDisplayProperty] } - set { self[didDisplayProperty] = newValue } - } - - /// Returns a copy of this model with the given did display closure called after the current did - /// display closure of this model, if there is one. - func didDisplay(_ value: DidDisplay?) -> Self { - copy(updating: didDisplayProperty, to: value) - } - - // MARK: Private - - private var didDisplayProperty: EpoxyModelProperty { - .init(keyPath: \Self.didDisplay, defaultValue: nil, updateStrategy: .chain()) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidEndDisplayingProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidEndDisplayingProviding.swift deleted file mode 100644 index db71be6dc2964f65b76f17a58681ba4f540fc868..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidEndDisplayingProviding.swift +++ /dev/null @@ -1,41 +0,0 @@ -// Created by eric_horacek on 12/15/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - DidEndDisplayingProviding - -/// A sentinel protocol for enabling an `CallbackContextEpoxyModeled` to provide a -/// `didEndDisplaying` closure property. -protocol DidEndDisplayingProviding { } - -// MARK: - CallbackContextEpoxyModeled - -extension CallbackContextEpoxyModeled where Self: DidEndDisplayingProviding { - - // MARK: Internal - - /// A closure that's called when a view is no longer displayed following any disappearance - /// animations and when it has been removed from the view hierarchy. - typealias DidEndDisplaying = (_ context: CallbackContext) -> Void - - /// A closure that's called when the view is no longer displayed following any disappearance - /// animations and when it has been removed from the view hierarchy. - var didEndDisplaying: DidEndDisplaying? { - get { self[didEndDisplayingProperty] } - set { self[didEndDisplayingProperty] = newValue } - } - - /// Returns a copy of this model with the given did end displaying closure called after the - /// current did end displaying closure of this model, if there is one. - func didEndDisplaying(_ value: DidEndDisplaying?) -> Self { - copy(updating: didEndDisplayingProperty, to: value) - } - - // MARK: Private - - private var didEndDisplayingProperty: EpoxyModelProperty { - .init( - keyPath: \Self.didEndDisplaying, - defaultValue: nil, - updateStrategy: .chain()) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidSelectProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidSelectProviding.swift deleted file mode 100644 index 007e0244e338bccc960d160132ac35ca18972b11..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/DidSelectProviding.swift +++ /dev/null @@ -1,36 +0,0 @@ -// Created by eric_horacek on 12/2/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - DidSelectProviding - -/// A sentinel protocol for enabling an `CallbackContextEpoxyModeled` to provide a `didSelect` -/// closure property. -protocol DidSelectProviding { } - -// MARK: - CallbackContextEpoxyModeled - -extension CallbackContextEpoxyModeled where Self: DidSelectProviding { - - // MARK: Internal - - /// A closure that's called to handle this model's view being selected. - typealias DidSelect = (CallbackContext) -> Void - - /// A closure that's called to handle this model's view being selected. - var didSelect: DidSelect? { - get { self[didSelectProperty] } - set { self[didSelectProperty] = newValue } - } - - /// Returns a copy of this model with the given did select closure called after the current did - /// select closure of this model, if there is one. - func didSelect(_ value: DidSelect?) -> Self { - copy(updating: didSelectProperty, to: value) - } - - // MARK: Private - - private var didSelectProperty: EpoxyModelProperty { - .init(keyPath: \Self.didSelect, defaultValue: nil, updateStrategy: .chain()) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ErasedContentProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ErasedContentProviding.swift deleted file mode 100644 index 556c3b8cbf00238681b26a65dd6ee79463a62454..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ErasedContentProviding.swift +++ /dev/null @@ -1,49 +0,0 @@ -// Created by eric_horacek on 12/2/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - ErasedContentProviding - -/// The capability of providing an type-erased `Equatable` content instance. -protocol ErasedContentProviding { - /// The type-erased content instance of this model, else `nil` if there is no content. - /// - /// If there was an `AnyEquatable` type, we could store this property using it. Instead we need - /// need to store `isErasedContentEqual` to determine equality. - var erasedContent: Any? { get } - - /// A closure that can be called to determine whether the given `model`'s `erasedContent` is equal - /// to this model's `erasedContent`, else `nil` if there is no content or the content is always - /// equal. - var isErasedContentEqual: ((Self) -> Bool)? { get } -} - -// MARK: - EpoxyModeled - -extension EpoxyModeled where Self: ErasedContentProviding { - - // MARK: Internal - - /// The type-erased content instance of this model, else `nil` if there is no content. - var erasedContent: Any? { - get { self[contentProperty] } - set { self[contentProperty] = newValue } - } - - /// A closure that can be called to determine whether the given `model`'s `erasedContent` is equal - /// to this model's `erasedContent`, else `nil` if there is no content or the content is always - /// equal. - var isErasedContentEqual: ((Self) -> Bool)? { - get { self[isContentEqualProperty] } - set { self[isContentEqualProperty] = newValue } - } - - // MARK: Private - - private var contentProperty: EpoxyModelProperty { - .init(keyPath: \Self.erasedContent, defaultValue: nil, updateStrategy: .replace) - } - - private var isContentEqualProperty: EpoxyModelProperty<((Self) -> Bool)?> { - .init(keyPath: \Self.isErasedContentEqual, defaultValue: nil, updateStrategy: .replace) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/MakeViewProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/MakeViewProviding.swift deleted file mode 100644 index 0b4301f4e09ef2a74cf1c353b5a1dfc891ac4f4c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/MakeViewProviding.swift +++ /dev/null @@ -1,60 +0,0 @@ -// Created by eric_horacek on 12/1/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - MakeViewProviding - -/// The capability of constructing a `UIView`. -protocol MakeViewProviding { - /// The view constructed when the `MakeView` closure is called. - associatedtype View: ViewType - - /// A closure that's called to construct an instance of `View`. - typealias MakeView = () -> View - - /// A closure that's called to construct an instance of `View`. - var makeView: MakeView { get } -} - -// MARK: - ViewEpoxyModeled - -extension ViewEpoxyModeled where Self: MakeViewProviding { - - // MARK: Internal - - /// A closure that's called to construct an instance of `View` represented by this model. - var makeView: MakeView { - get { self[makeViewProperty] } - set { self[makeViewProperty] = newValue } - } - - /// Replaces the default closure to construct the view with the given closure. - func makeView(_ value: @escaping MakeView) -> Self { - copy(updating: makeViewProperty, to: value) - } - - // MARK: Private - - private var makeViewProperty: EpoxyModelProperty { - // If you're getting a `EXC_BAD_INSTRUCTION` crash with this property in your stack trace, you - // probably either: - // - Conformed a view to `EpoxyableView` / `StyledView` with a custom initializer that - // takes parameters, or: - // - Used the `EpoxyModeled.init(dataID:)` initializer on a view has required initializer - // parameters. - // If you have parameters to view initialization, they should either be passed to `init(style:)` - // or you should provide a `makeView` closure when constructing your view's corresponding model, - // e.g: - // ``` - // MyView.itemModel(…) - // .makeView { MyView(customParameter: …) } - // .styleID(…) - // ``` - // Note that with the above approach that you must supply an `styleID` with the same identity as - // your view parameters to ensure that views with different parameters are not reused in place - // of one another. - .init( - keyPath: \Self.makeView, - defaultValue: View.init, - updateStrategy: .replace) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetBehaviorsProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetBehaviorsProviding.swift deleted file mode 100644 index a73de043de623d72a035ca2a04f7383d027485f1..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetBehaviorsProviding.swift +++ /dev/null @@ -1,38 +0,0 @@ -// Created by eric_horacek on 12/2/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - SetBehaviorsProviding - -/// A sentinel protocol for enabling an `CallbackContextEpoxyModeled` to provide a `setBehaviors` -/// closure property. -protocol SetBehaviorsProviding { } - -// MARK: - CallbackContextEpoxyModeled - -extension CallbackContextEpoxyModeled where Self: SetBehaviorsProviding { - - // MARK: Internal - - /// A closure that's called to set the content on this model's view with behaviors (e.g. tap handler - /// closures) whenever this model is updated. - typealias SetBehaviors = (CallbackContext) -> Void - - /// A closure that's called to set the content on this model's view with behaviors (e.g. tap handler - /// closures) whenever this model is updated. - var setBehaviors: SetBehaviors? { - get { self[setBehaviorsProperty] } - set { self[setBehaviorsProperty] = newValue } - } - - /// Returns a copy of this model with the set behaviors closure called after the current set - /// behaviors closure of this model, if there is one. - func setBehaviors(_ value: SetBehaviors?) -> Self { - copy(updating: setBehaviorsProperty, to: value) - } - - // MARK: Private - - private var setBehaviorsProperty: EpoxyModelProperty { - .init(keyPath: \Self.setBehaviors, defaultValue: nil, updateStrategy: .chain()) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetContentProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetContentProviding.swift deleted file mode 100644 index e1456dceb480f6836408940025cd23fb22efa5b8..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/SetContentProviding.swift +++ /dev/null @@ -1,38 +0,0 @@ -// Created by eric_horacek on 12/1/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - SetContentProviding - -/// A sentinel protocol for enabling an `CallbackContextEpoxyModeled` to provide a `setContent` -/// closure property. -protocol SetContentProviding { } - -// MARK: - CallbackContextEpoxyModeled - -extension CallbackContextEpoxyModeled where Self: SetContentProviding { - - // MARK: Internal - - /// A closure that's called to set the content on this model's view when it is first created and - /// subsequently when the content changes. - typealias SetContent = (CallbackContext) -> Void - - /// A closure that's called to set the content on this model's view when it is first created and - /// subsequently when the content changes. - var setContent: SetContent? { - get { self[setContentProperty] } - set { self[setContentProperty] = newValue } - } - - /// Returns a copy of this model with the given setContent view closure called after the current - /// setContent view closure of this model, if there is one. - func setContent(_ value: SetContent?) -> Self { - copy(updating: setContentProperty, to: value) - } - - // MARK: Private - - private var setContentProperty: EpoxyModelProperty { - .init(keyPath: \Self.setContent, defaultValue: nil, updateStrategy: .chain()) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/StyleIDProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/StyleIDProviding.swift deleted file mode 100644 index 8242de12d48bdb2bab7a77c91f1d6583d9b2bd67..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/StyleIDProviding.swift +++ /dev/null @@ -1,37 +0,0 @@ -// Created by eric_horacek on 12/1/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - StyleIDProviding - -protocol StyleIDProviding { - /// An optional ID for a style type to use for reuse of a view. - /// - /// Use this to differentiate between different styling configurations. - var styleID: AnyHashable? { get } -} - -// MARK: - EpoxyModeled - -extension EpoxyModeled where Self: StyleIDProviding { - - // MARK: Internal - - var styleID: AnyHashable? { - get { self[styleIDProperty] } - set { self[styleIDProperty] = newValue } - } - - /// Returns a copy of this model with the `styleID` replaced with the provided `value`. - func styleID(_ value: AnyHashable?) -> Self { - copy(updating: styleIDProperty, to: value) - } - - // MARK: Private - - private var styleIDProperty: EpoxyModelProperty { - .init( - keyPath: \StyleIDProviding.styleID, - defaultValue: nil, - updateStrategy: .replace) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/TraitCollectionProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/TraitCollectionProviding.swift deleted file mode 100644 index e41ac7906ddd47507393ce2274de05daef9b747f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/TraitCollectionProviding.swift +++ /dev/null @@ -1,14 +0,0 @@ -// Created by eric_horacek on 12/16/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -#if !os(macOS) -import UIKit - -/// The capability of providing a `UITraitCollection` instance. -/// -/// Typically conformed to by the `CallbackContext` of a `CallbackContextEpoxyModeled`. -protocol TraitCollectionProviding { - /// The `UITraitCollection` instance provided by this type. - var traitCollection: UITraitCollection { get } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewDifferentiatorProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewDifferentiatorProviding.swift deleted file mode 100644 index 45c0130e8755da013db7ee1d0a039c25c8c5bc40..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewDifferentiatorProviding.swift +++ /dev/null @@ -1,34 +0,0 @@ -// Created by Bryan Keller on 12/17/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - ViewDifferentiatorProviding - -/// The capability of providing a view differentiator that facilitates generating collection view -/// cell reuse identifiers. -protocol ViewDifferentiatorProviding { - /// The view differentiator for the item model. - var viewDifferentiator: ViewDifferentiator { get } -} - -// MARK: - ViewDifferentiator - -/// Facilitates differentiating between two models' views, based on their view type, optional style -/// identifier, and optional element kind for supplementary view models. If two models have the same -/// view differentiator, then they're compatible with one another for element reuse. If two models -/// have different view differentiators, then they're incompatible with one another for element -/// reuse. -struct ViewDifferentiator: Hashable { - - // MARK: Lifecycle - - init(viewType: AnyClass, styleID: AnyHashable?) { - viewTypeDescription = "\(type(of: viewType.self))" - self.styleID = styleID - } - - // MARK: Public - - var viewTypeDescription: String - var styleID: AnyHashable? - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewProviding.swift deleted file mode 100644 index b36eed8cbe7ac2d5d9ccb8bcf00eb51d2d15e267..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/ViewProviding.swift +++ /dev/null @@ -1,13 +0,0 @@ -// Created by eric_horacek on 12/16/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -/// The capability of providing an `View` instance -/// -/// Typically conformed to by the `CallbackContext` of a `CallbackContextEpoxyModeled`. -protocol ViewProviding { - /// The `UIView` view of this type. - associatedtype View: ViewType - - /// The `UIView` view instance provided by this type. - var view: View { get } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/WillDisplayProviding.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/WillDisplayProviding.swift deleted file mode 100644 index 9bf2163024c7e7c77da364b71422b6540eaed642..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/Providers/WillDisplayProviding.swift +++ /dev/null @@ -1,41 +0,0 @@ -// Created by eric_horacek on 12/15/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - WillDisplayProviding - -/// A sentinel protocol for enabling an `CallbackContextEpoxyModeled` to provide a `willDisplay` -/// closure property. -/// -/// - SeeAlso: `DidDisplayProviding` -/// - SeeAlso: `DidEndDisplayingProviding` -protocol WillDisplayProviding { } - -// MARK: - CallbackContextEpoxyModeled - -extension CallbackContextEpoxyModeled where Self: WillDisplayProviding { - - // MARK: Internal - - /// A closure that's called when a view is about to be displayed, before it has been added to the - /// view hierarcy. - typealias WillDisplay = (_ context: CallbackContext) -> Void - - /// A closure that's called when the view is about to be displayed, before it has been added to - /// the view hierarcy. - var willDisplay: WillDisplay? { - get { self[willDisplayProperty] } - set { self[willDisplayProperty] = newValue } - } - - /// Returns a copy of this model with the given will display closure called after the current will - /// display closure of this model, if there is one. - func willDisplay(_ value: WillDisplay?) -> Self { - copy(updating: willDisplayProperty, to: value) - } - - // MARK: Private - - private var willDisplayProperty: EpoxyModelProperty { - .init(keyPath: \Self.willDisplay, defaultValue: nil, updateStrategy: .chain()) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/ViewEpoxyModeled.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/ViewEpoxyModeled.swift deleted file mode 100644 index 27901b28fb70a437dfb56aae76f6113ca8d88181..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Model/ViewEpoxyModeled.swift +++ /dev/null @@ -1,10 +0,0 @@ -// Created by eric_horacek on 12/4/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -/// An Epoxy model with an associated `UIView` type. -protocol ViewEpoxyModeled: EpoxyModeled { - /// The view type associated with this model. - /// - /// An instance of this view is typically configured by this model. - associatedtype View: ViewType -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/README.md b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/README.md deleted file mode 100644 index f79da6e6760e1d2f3511d1779c57a83891527ee3..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/README.md +++ /dev/null @@ -1,31 +0,0 @@ -## EpoxyCore - -This directory includes the source code of the EpoxyCore library, from the following release: -https://github.com/airbnb/epoxy-ios/releases/tag/0.10.0 - -Lottie is distributed via multiple package managers (SPM, Cocoapods, Carthage, and NPM), -each with different packaging and compilation requirements. - -Due to limitations of these package managers, we can't depend on / import -a separate EpoxyCore module / library. Instead, we include the source -directly within the Lottie library and compile everything as a single unit. - -### Update instructions - -From time to time we may need to update to a more recent version of EpoxyCore. -When doing this, follow these steps: - - 1. Download the latest release from https://github.com/epoxy-ios/EpoxyCore - and replace the source code in this directory with the updated code. - - 2. Update the URL at the top of this file to indicate what release is being used. - - 3. Change all of the `public` symbols defined in this module to instead be `internal` - to prevent Lottie from exposing any EpoxyCore APIs. - - 4. Add `@available` annotations as necessary so the library compiles - (Lottie has a lower minimum iOS version than EpoxyCore). - - 5. Namespace any types that conflict with other existing types. - For example, the EpoxyCore `Entry` type conflicts with the ZipFoundation `Entry` type, - so the EpoxyCore type has been renamed to `EpoxyEntry`. diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIHostingController.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIHostingController.swift deleted file mode 100644 index 10e99a956a879cb9cd6e98a085a9e1ad134bef25..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIHostingController.swift +++ /dev/null @@ -1,46 +0,0 @@ -// Created by eric_horacek on 10/8/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) && !os(macOS) -import SwiftUI - -// MARK: - EpoxySwiftUIUIHostingController - -/// A `UIHostingController` that hosts SwiftUI views within an Epoxy container, e.g. an Epoxy -/// `CollectionView`. -/// -/// Exposed internally to allow consumers to reason about these view controllers, e.g. to opt -/// collection view cells out of automated view controller impression tracking. -/// -/// - SeeAlso: `EpoxySwiftUIHostingView` -@available(iOS 13.0, tvOS 13.0, *) -open class EpoxySwiftUIHostingController: UIHostingController { - - // MARK: Lifecycle - - /// Creates a `UIHostingController` that optionally ignores the `safeAreaInsets` when laying out - /// its contained `RootView`. - convenience init(rootView: Content, ignoreSafeArea: Bool) { - self.init(rootView: rootView) - - // We unfortunately need to call a private API to disable the safe area. We can also accomplish - // this by dynamically subclassing this view controller's view at runtime and overriding its - // `safeAreaInsets` property and returning `.zero`. An implementation of that logic is - // available in this file in the `2d28b3181cca50b89618b54836f7a9b6e36ea78e` commit if this API - // no longer functions in future SwiftUI versions. - _disableSafeArea = ignoreSafeArea - } - - // MARK: Open - - open override func viewDidLoad() { - super.viewDidLoad() - - // A `UIHostingController` has a system background color by default as it's typically used in - // full-screen use cases. Since we're using this view controller to place SwiftUI views within - // other view controllers we default the background color to clear so we can see the views - // below, e.g. to draw highlight states in a `CollectionView`. - view.backgroundColor = .clear - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift deleted file mode 100644 index c1b8c52790136fcdfd68c86be7036d678f1c2a6d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIHostingView.swift +++ /dev/null @@ -1,389 +0,0 @@ -// Created by eric_horacek on 9/16/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -#if canImport(Combine) && canImport(SwiftUI) && !os(macOS) -import Combine -import SwiftUI - -// MARK: - SwiftUIHostingViewReuseBehavior - -/// The reuse behavior of an `EpoxySwiftUIHostingView`. -enum SwiftUIHostingViewReuseBehavior: Hashable { - /// Instances of a `EpoxySwiftUIHostingView` with `RootView`s of same type can be reused within - /// the Epoxy container. - /// - /// This is the default reuse behavior. - case reusable - /// Instances of a `EpoxySwiftUIHostingView` with `RootView`s of same type can only reused within - /// the Epoxy container when they have identical `reuseID`s. - case unique(reuseID: AnyHashable) -} - -// MARK: - CallbackContextEpoxyModeled - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension CallbackContextEpoxyModeled - where - Self: WillDisplayProviding & DidEndDisplayingProviding, - CallbackContext: ViewProviding & AnimatedProviding -{ - /// Updates the appearance state of a `EpoxySwiftUIHostingView` in coordination with the - /// `willDisplay` and `didEndDisplaying` callbacks of this `EpoxyableModel`. - /// - /// - Note: You should only need to call then from the implementation of a concrete - /// `EpoxyableModel` convenience vendor method, e.g. `SwiftUI.View.itemModel(…)`. - func linkDisplayLifecycle() -> Self - where - CallbackContext.View == EpoxySwiftUIHostingView - { - willDisplay { context in - context.view.handleWillDisplay(animated: context.animated) - } - .didEndDisplaying { context in - context.view.handleDidEndDisplaying(animated: context.animated) - } - } -} - -// MARK: - EpoxySwiftUIHostingView - -/// A `UIView` that hosts a SwiftUI view within an Epoxy container, e.g. an Epoxy `CollectionView`. -/// -/// Wraps an `EpoxySwiftUIHostingController` and adds it as a child view controller to the next -/// ancestor view controller in the hierarchy. -/// -/// There's a private API that accomplishes this same behavior without needing a `UIViewController`: -/// `_UIHostingView`, but we can't safely use it as 1) the behavior may change out from under us, 2) -/// the API is private and 3) the `_UIHostingView` doesn't not accept setting a new `View` instance. -/// -/// - SeeAlso: `EpoxySwiftUIHostingController` -@available(iOS 13.0, tvOS 13.0, *) -final class EpoxySwiftUIHostingView: UIView, EpoxyableView { - - // MARK: Lifecycle - - init(style: Style) { - // Ignore the safe area to ensure the view isn't laid out incorrectly when being sized while - // overlapping the safe area. - epoxyContent = EpoxyHostingContent(rootView: style.initialContent.rootView) - viewController = EpoxySwiftUIHostingController( - rootView: .init(content: epoxyContent, environment: epoxyEnvironment), - ignoreSafeArea: true) - - dataID = style.initialContent.dataID ?? DefaultDataID.noneProvided as AnyHashable - - super.init(frame: .zero) - - epoxyEnvironment.intrinsicContentSizeInvalidator = .init(invalidate: { [weak self] in - self?.viewController.view.invalidateIntrinsicContentSize() - - // Inform the enclosing collection view that the size has changed, if we're contained in one, - // allowing the cell to resize. - // - // On iOS 16+, we could call `invalidateIntrinsicContentSize()` on the enclosing collection - // view cell instead, but that currently causes visual artifacts with `MagazineLayout`. The - // better long term fix is likely to switch to `UIHostingConfiguration` on iOS 16+ anyways. - if let enclosingCollectionView = self?.superview?.superview?.superview as? UICollectionView { - enclosingCollectionView.collectionViewLayout.invalidateLayout() - } - }) - layoutMargins = .zero - } - - @available(*, unavailable) - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - struct Style: Hashable { - init(reuseBehavior: SwiftUIHostingViewReuseBehavior, initialContent: Content) { - self.reuseBehavior = reuseBehavior - self.initialContent = initialContent - } - - var reuseBehavior: SwiftUIHostingViewReuseBehavior - var initialContent: Content - - static func == (lhs: Style, rhs: Style) -> Bool { - lhs.reuseBehavior == rhs.reuseBehavior - } - - func hash(into hasher: inout Hasher) { - hasher.combine(reuseBehavior) - } - } - - struct Content: Equatable { - init(rootView: RootView, dataID: AnyHashable?) { - self.rootView = rootView - self.dataID = dataID - } - - var rootView: RootView - var dataID: AnyHashable? - - static func == (_: Content, _: Content) -> Bool { - // The content should never be equal since we need the `rootView` to be updated on every - // content change. - false - } - } - - override func didMoveToWindow() { - super.didMoveToWindow() - - // We'll only be able to discover a valid parent `viewController` once we're added to a window, - // so we do so here in addition to the `handleWillDisplay(…)` method. - if window != nil { - addViewControllerIfNeeded() - } - } - - func setContent(_ content: Content, animated _: Bool) { - // This triggers a change in the observed `EpoxyHostingContent` object and allows the - // propagation of the SwiftUI transaction, instead of just replacing the `rootView`. - epoxyContent.rootView = content.rootView - dataID = content.dataID ?? DefaultDataID.noneProvided as AnyHashable - - // The view controller must be added to the view controller hierarchy to measure its content. - if window != nil { - addViewControllerIfNeeded() - } - - // As of iOS 15.2, `UIHostingController` now renders updated content asynchronously, and as such - // this view will get sized incorrectly with the previous content when reused unless we invoke - // this semi-private API. We couldn't find any other method to get the view to resize - // synchronously after updating `rootView`, but hopefully this will become a internal API soon so - // we can remove this call. - viewController._render(seconds: 0) - - // This is required to ensure that views with new content are properly resized. - viewController.view.invalidateIntrinsicContentSize() - } - - override func layoutMarginsDidChange() { - super.layoutMarginsDidChange() - - let margins = layoutMargins - switch effectiveUserInterfaceLayoutDirection { - case .rightToLeft: - epoxyEnvironment.layoutMargins = .init( - top: margins.top, - leading: margins.right, - bottom: margins.bottom, - trailing: margins.left) - case .leftToRight: - fallthrough - @unknown default: - epoxyEnvironment.layoutMargins = .init( - top: margins.top, - leading: margins.left, - bottom: margins.bottom, - trailing: margins.right) - } - - // Allow the layout margins update to fully propagate through to the SwiftUI View before - // invalidating the layout. - DispatchQueue.main.async { - self.viewController.view.invalidateIntrinsicContentSize() - } - } - - func handleWillDisplay(animated: Bool) { - guard state != .appeared, window != nil else { return } - transition(to: .appearing(animated: animated)) - transition(to: .appeared) - } - - func handleDidEndDisplaying(animated: Bool) { - guard state != .disappeared else { return } - transition(to: .disappearing(animated: animated)) - transition(to: .disappeared) - } - - // MARK: Private - - private let viewController: EpoxySwiftUIHostingController> - private let epoxyContent: EpoxyHostingContent - private let epoxyEnvironment = EpoxyHostingEnvironment() - private var dataID: AnyHashable - private var state: AppearanceState = .disappeared - - /// Updates the appearance state of the `viewController`. - private func transition(to state: AppearanceState) { - guard state != self.state else { return } - - // See "Handling View-Related Notifications" section for the state machine diagram. - // https://developer.apple.com/documentation/uikit/uiviewcontroller - switch (to: state, from: self.state) { - case (to: .appearing(let animated), from: .disappeared): - viewController.beginAppearanceTransition(true, animated: animated) - addViewControllerIfNeeded() - case (to: .disappearing(let animated), from: .appeared): - viewController.beginAppearanceTransition(false, animated: animated) - case (to: .disappeared, from: .disappearing): - removeViewControllerIfNeeded() - case (to: .appeared, from: .appearing): - viewController.endAppearanceTransition() - case (to: .disappeared, from: .appeared): - viewController.beginAppearanceTransition(false, animated: true) - removeViewControllerIfNeeded() - case (to: .appeared, from: .disappearing(let animated)): - viewController.beginAppearanceTransition(true, animated: animated) - viewController.endAppearanceTransition() - case (to: .disappeared, from: .appearing(let animated)): - viewController.beginAppearanceTransition(false, animated: animated) - removeViewControllerIfNeeded() - case (to: .appeared, from: .disappeared): - viewController.beginAppearanceTransition(true, animated: false) - addViewControllerIfNeeded() - viewController.endAppearanceTransition() - case (to: .appearing(let animated), from: .appeared): - viewController.beginAppearanceTransition(false, animated: animated) - viewController.beginAppearanceTransition(true, animated: animated) - case (to: .appearing(let animated), from: .disappearing): - viewController.beginAppearanceTransition(true, animated: animated) - case (to: .disappearing(let animated), from: .disappeared): - viewController.beginAppearanceTransition(true, animated: animated) - addViewControllerIfNeeded() - viewController.beginAppearanceTransition(false, animated: animated) - case (to: .disappearing(let animated), from: .appearing): - viewController.beginAppearanceTransition(false, animated: animated) - case (to: .appearing, from: .appearing), - (to: .appeared, from: .appeared), - (to: .disappearing, from: .disappearing), - (to: .disappeared, from: .disappeared): - // This should never happen since we guard on identical states. - EpoxyLogger.shared.assertionFailure("Impossible state change from \(self.state) to \(state)") - } - - self.state = state - } - - private func addViewControllerIfNeeded() { - // This isn't great, and means that we're going to add this view controller as a child view - // controller of a view controller somewhere else in the hierarchy, which the author of that - // view controller may not be expecting. However there's not really a better pathway forward - // here without requiring a view controller instance to be passed all the way through, which is - // both burdensome and error-prone. - guard let nextViewController = superview?.next(UIViewController.self) else { - EpoxyLogger.shared.assertionFailure( - """ - Unable to add a UIHostingController view, could not locate a UIViewController in the \ - responder chain for view with ID \(dataID) of type \(RootView.self). - """) - return - } - - guard viewController.parent !== nextViewController else { return } - - // If in a different parent, we need to first remove from it before we add. - if viewController.parent != nil { - removeViewControllerIfNeeded() - } - - addViewController(to: nextViewController) - - state = .appeared - } - - private func addViewController(to parent: UIViewController) { - viewController.willMove(toParent: parent) - - parent.addChild(viewController) - - addSubview(viewController.view) - - // Get the view controller's view to be sized correctly so that we don't have to wait for - // autolayout to perform a pass to do so. - viewController.view.frame = bounds - - viewController.view.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - viewController.view.leadingAnchor.constraint(equalTo: leadingAnchor), - viewController.view.topAnchor.constraint(equalTo: topAnchor), - viewController.view.trailingAnchor.constraint(equalTo: trailingAnchor), - viewController.view.bottomAnchor.constraint(equalTo: bottomAnchor), - ]) - - viewController.didMove(toParent: parent) - } - - private func removeViewControllerIfNeeded() { - guard viewController.parent != nil else { return } - - viewController.willMove(toParent: nil) - viewController.view.removeFromSuperview() - viewController.removeFromParent() - viewController.didMove(toParent: nil) - } -} - -// MARK: - AppearanceState - -/// The appearance state of a `EpoxySwiftUIHostingController` contained within a -/// `EpoxySwiftUIHostingView`. -private enum AppearanceState: Equatable { - case appearing(animated: Bool) - case appeared - case disappearing(animated: Bool) - case disappeared -} - -// MARK: - UIResponder - -extension UIResponder { - /// Recursively traverses the responder chain upwards from this responder to its next responder - /// until the a responder of the given type is located, else returns `nil`. - @nonobjc - fileprivate func next(_ type: ResponderType.Type) -> ResponderType? { - self as? ResponderType ?? next?.next(type) - } -} - -// MARK: - EpoxyHostingContent - -/// The object that is used to communicate changes in the root view to the -/// `EpoxySwiftUIHostingController`. -@available(iOS 13.0, tvOS 13.0, *) -final class EpoxyHostingContent: ObservableObject { - - // MARK: Lifecycle - - init(rootView: RootView) { - _rootView = .init(wrappedValue: rootView) - } - - // MARK: Internal - - @Published var rootView: RootView -} - -// MARK: - EpoxyHostingEnvironment - -/// The object that is used to communicate values to SwiftUI views within an -/// `EpoxySwiftUIHostingController`, e.g. layout margins. -@available(iOS 13.0, tvOS 13.0, *) -final class EpoxyHostingEnvironment: ObservableObject { - @Published var layoutMargins = EdgeInsets() - @Published var intrinsicContentSizeInvalidator = EpoxyIntrinsicContentSizeInvalidator(invalidate: { }) -} - -// MARK: - EpoxyHostingWrapper - -/// The wrapper view that is used to communicate values to SwiftUI views within an -/// `EpoxySwiftUIHostingController`, e.g. layout margins. -@available(iOS 13.0, tvOS 13.0, *) -struct EpoxyHostingWrapper: View { - @ObservedObject var content: EpoxyHostingContent - @ObservedObject var environment: EpoxyHostingEnvironment - - var body: some View { - content.rootView - .environment(\.epoxyLayoutMargins, environment.layoutMargins) - .environment(\.epoxyIntrinsicContentSizeInvalidator, environment.intrinsicContentSizeInvalidator) - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIIntrinsicContentSizeInvalidator.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIIntrinsicContentSizeInvalidator.swift deleted file mode 100644 index 47ebde44b4b53a3503ad97ac63e490756469bb9b..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUIIntrinsicContentSizeInvalidator.swift +++ /dev/null @@ -1,46 +0,0 @@ -// Created by matthew_cheok on 11/19/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -// MARK: - EpoxyIntrinsicContentSizeInvalidator - -/// Allows the SwiftUI view contained in an Epoxy model to request the invalidation of -/// the container's intrinsic content size. -/// -/// ``` -/// @Environment(\.epoxyIntrinsicContentSizeInvalidator) var invalidateIntrinsicContentSize -/// -/// var body: some View { -/// ... -/// .onChange(of: size) { -/// invalidateIntrinsicContentSize() -/// } -/// } -/// ``` -struct EpoxyIntrinsicContentSizeInvalidator { - let invalidate: () -> Void - - func callAsFunction() { - invalidate() - } -} - -// MARK: - EnvironmentValues - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension EnvironmentValues { - /// A means of invalidating the intrinsic content size of the parent `EpoxySwiftUIHostingView`. - var epoxyIntrinsicContentSizeInvalidator: EpoxyIntrinsicContentSizeInvalidator { - get { self[EpoxyIntrinsicContentSizeInvalidatorKey.self] } - set { self[EpoxyIntrinsicContentSizeInvalidatorKey.self] = newValue } - } -} - -// MARK: - EpoxyIntrinsicContentSizeInvalidatorKey - -private struct EpoxyIntrinsicContentSizeInvalidatorKey: EnvironmentKey { - static let defaultValue = EpoxyIntrinsicContentSizeInvalidator(invalidate: { }) -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUILayoutMargins.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUILayoutMargins.swift deleted file mode 100644 index 44fc83fbacffeddadc4be994b62f83febb7203ca..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxySwiftUILayoutMargins.swift +++ /dev/null @@ -1,53 +0,0 @@ -// Created by eric_horacek on 10/8/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -// MARK: - View - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension View { - /// Applies the layout margins from the parent `EpoxySwiftUIHostingView` to this `View`, if there - /// are any. - /// - /// Can be used to have a background in SwiftUI underlap the safe area within a bar installer, for - /// example. - /// - /// These margins are propagated via the `EnvironmentValues.epoxyLayoutMargins`. - func epoxyLayoutMargins() -> some View { - modifier(EpoxyLayoutMarginsPadding()) - } -} - -// MARK: - EnvironmentValues - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension EnvironmentValues { - /// The layout margins of the parent `EpoxySwiftUIHostingView`, else zero if there is none. - var epoxyLayoutMargins: EdgeInsets { - get { self[EpoxyLayoutMarginsKey.self] } - set { self[EpoxyLayoutMarginsKey.self] = newValue } - } -} - -// MARK: - EpoxyLayoutMarginsKey - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -private struct EpoxyLayoutMarginsKey: EnvironmentKey { - static let defaultValue = EdgeInsets() -} - -// MARK: - EpoxyLayoutMarginsPadding - -/// A view modifier that applies the layout margins from an enclosing `EpoxySwiftUIHostingView` to -/// the modified `View`. -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -private struct EpoxyLayoutMarginsPadding: ViewModifier { - @Environment(\.epoxyLayoutMargins) var epoxyLayoutMargins - - func body(content: Content) -> some View { - content.padding(epoxyLayoutMargins) - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxyableView+SwiftUIView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxyableView+SwiftUIView.swift deleted file mode 100644 index 06febc2cc4d97c0a4bf4e8b6e464d912d2a47047..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/EpoxyableView+SwiftUIView.swift +++ /dev/null @@ -1,174 +0,0 @@ -// Created by eric_horacek on 9/13/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -// MARK: - StyledView - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension StyledView where Self: ContentConfigurableView & BehaviorsConfigurableView { - /// Returns a SwiftUI `View` representing this `EpoxyableView`. - /// - /// To perform additional configuration of the `EpoxyableView` instance, call `configure` on the - /// returned SwiftUI `View`: - /// ``` - /// MyView.swiftUIView(…) - /// .configure { context in - /// context.view.doSomething() - /// } - /// ``` - /// - /// To configure the sizing behavior of the `EpoxyableView` instance, call `sizing` on the - /// returned SwiftUI `View`: - /// ``` - /// MyView.swiftUIView(…).sizing(.intrinsicSize) - /// ``` - static func swiftUIView( - content: Content, - style: Style, - behaviors: Behaviors? = nil) - -> SwiftUIView - { - SwiftUIView(storage: (content: content, style: style)) { - let view = Self(style: style) - view.setContent(content, animated: false) - return view - } - .configure { context in - // We need to create a new view instance when the style changes. - if context.oldStorage.style != style { - context.view = Self(style: style) - context.view.setContent(content, animated: context.animated) - } - // Otherwise, if the just the content changes, we need to update it. - else if context.oldStorage.content != content { - context.view.setContent(content, animated: context.animated) - context.container.invalidateIntrinsicContentSize() - } - - context.view.setBehaviors(behaviors) - } - } -} - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension StyledView - where - Self: ContentConfigurableView & BehaviorsConfigurableView, - Style == Never -{ - /// Returns a SwiftUI `View` representing this `EpoxyableView`. - /// - /// To perform additional configuration of the `EpoxyableView` instance, call `configure` on the - /// returned SwiftUI `View`: - /// ``` - /// MyView.swiftUIView(…) - /// .configure { context in - /// context.view.doSomething() - /// } - /// ``` - /// - /// To configure the sizing behavior of the `EpoxyableView` instance, call `sizing` on the - /// returned SwiftUI `View`: - /// ``` - /// MyView.swiftUIView(…).sizing(.intrinsicSize) - /// ``` - static func swiftUIView( - content: Content, - behaviors: Behaviors? = nil) - -> SwiftUIView - { - SwiftUIView(storage: content) { - let view = Self() - view.setContent(content, animated: false) - return view - } - .configure { context in - // We need to update the content of the existing view when the content is updated. - if context.oldStorage != content { - context.view.setContent(content, animated: context.animated) - context.container.invalidateIntrinsicContentSize() - } - - context.view.setBehaviors(behaviors) - } - } -} - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension StyledView - where - Self: ContentConfigurableView & BehaviorsConfigurableView, - Content == Never -{ - /// Returns a SwiftUI `View` representing this `EpoxyableView`. - /// - /// To perform additional configuration of the `EpoxyableView` instance, call `configure` on the - /// returned SwiftUI `View`: - /// ``` - /// MyView.swiftUIView(…) - /// .configure { context in - /// context.view.doSomething() - /// } - /// ``` - /// - /// To configure the sizing behavior of the `EpoxyableView` instance, call `sizing` on the - /// returned SwiftUI `View`: - /// ``` - /// MyView.swiftUIView(…).sizing(.intrinsicSize) - /// ``` - /// The sizing defaults to `.automatic`. - static func swiftUIView( - style: Style, - behaviors: Behaviors? = nil) - -> SwiftUIView - { - SwiftUIView(storage: style) { - Self(style: style) - } - .configure { context in - // We need to create a new view instance when the style changes. - if context.oldStorage != style { - context.view = Self(style: style) - } - - context.view.setBehaviors(behaviors) - } - } -} - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension StyledView - where - Self: ContentConfigurableView & BehaviorsConfigurableView, - Content == Never, - Style == Never -{ - /// Returns a SwiftUI `View` representing this `EpoxyableView`. - /// - /// To perform additional configuration of the `EpoxyableView` instance, call `configure` on the - /// returned SwiftUI `View`: - /// ``` - /// MyView.swiftUIView(…) - /// .configure { context in - /// context.view.doSomething() - /// } - /// ``` - /// - /// To configure the sizing behavior of the `EpoxyableView` instance, call `sizing` on the - /// returned SwiftUI `View`: - /// ``` - /// MyView.swiftUIView(…).sizing(.intrinsicSize) - /// ``` - /// The sizing defaults to `.automatic`. - static func swiftUIView(behaviors: Behaviors? = nil) -> SwiftUIView { - SwiftUIView { - Self() - } - .configure { context in - context.view.setBehaviors(behaviors) - } - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift deleted file mode 100644 index 065aaa71042b0ecdda7ebf1b706066e5f2dcdd46..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/MeasuringViewRepresentable.swift +++ /dev/null @@ -1,130 +0,0 @@ -// Created by eric_horacek on 6/22/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -// MARK: - MeasuringViewRepresentable - -/// A `UIViewRepresentable` that uses a `SwiftUIMeasurementContainer` wrapping its represented -/// `UIView` to report its size that fits a proposed size to SwiftUI. -/// -/// Supports iOS 13-15 using the private `_overrideSizeThatFits(…)` method and iOS 16+ using the -/// `sizeThatFits(…)` method. -/// -/// - SeeAlso: ``SwiftUIMeasurementContainer`` -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -protocol MeasuringViewRepresentable: ViewRepresentableType - where - RepresentableViewType == SwiftUIMeasurementContainer -{ - /// The `UIView` content that's being measured by the enclosing `SwiftUIMeasurementContainer`. - associatedtype Content: ViewType - - /// The sizing strategy of the represented view. - /// - /// To configure the sizing behavior of the `View` instance, call `sizing` on this `View`, e.g.: - /// ``` - /// myView.sizing(.intrinsicSize) - /// ``` - var sizing: SwiftUIMeasurementContainerStrategy { get set } -} - -// MARK: Extensions - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension MeasuringViewRepresentable { - /// Returns a copy of this view with its sizing strategy updated to the given `sizing` value. - func sizing(_ strategy: SwiftUIMeasurementContainerStrategy) -> Self { - var copy = self - copy.sizing = strategy - return copy - } -} - -// MARK: Defaults - -#if os(iOS) || os(tvOS) -@available(iOS 13.0, tvOS 13.0, *) -extension MeasuringViewRepresentable { - func _overrideSizeThatFits( - _ size: inout CGSize, - in proposedSize: _ProposedSize, - uiView: UIViewType) - { - uiView.strategy = sizing - - // Note: this method is not double-called on iOS 16, so we don't need to do anything to prevent - // extra work here. - let children = Mirror(reflecting: proposedSize).children - - // Creates a `CGSize` by replacing `nil`s with `UIView.noIntrinsicMetric` - uiView.proposedSize = .init( - width: children.first { $0.label == "width" }?.value as? CGFloat ?? ViewType.noIntrinsicMetric, - height: children.first { $0.label == "height" }?.value as? CGFloat ?? ViewType.noIntrinsicMetric) - - size = uiView.measuredFittingSize - } - - #if swift(>=5.7) // Proxy check for being built with the iOS 15 SDK - @available(iOS 16.0, tvOS 16.0, macOS 13.0, *) - func sizeThatFits( - _ proposal: ProposedViewSize, - uiView: UIViewType, - context _: Context) - -> CGSize? - { - uiView.strategy = sizing - - // Creates a size by replacing `nil`s with `UIView.noIntrinsicMetric` - uiView.proposedSize = .init( - width: proposal.width ?? ViewType.noIntrinsicMetric, - height: proposal.height ?? ViewType.noIntrinsicMetric) - - return uiView.measuredFittingSize - } - #endif -} - -#elseif os(macOS) -@available(macOS 10.15, *) -extension MeasuringViewRepresentable { - func _overrideSizeThatFits( - _ size: inout CGSize, - in proposedSize: _ProposedSize, - nsView: NSViewType) - { - nsView.strategy = sizing - - let children = Mirror(reflecting: proposedSize).children - - // Creates a `CGSize` by replacing `nil`s with `UIView.noIntrinsicMetric` - nsView.proposedSize = .init( - width: children.first { $0.label == "width" }?.value as? CGFloat ?? ViewType.noIntrinsicMetric, - height: children.first { $0.label == "height" }?.value as? CGFloat ?? ViewType.noIntrinsicMetric) - - size = nsView.measuredFittingSize - } - - // Proxy check for being built with the macOS 13 SDK. - #if swift(>=5.7.1) - @available(macOS 13.0, *) - func sizeThatFits( - _ proposal: ProposedViewSize, - nsView: NSViewType, - context _: Context) - -> CGSize? - { - nsView.strategy = sizing - - // Creates a size by replacing `nil`s with `UIView.noIntrinsicMetric` - nsView.proposedSize = .init( - width: proposal.width ?? ViewType.noIntrinsicMetric, - height: proposal.height ?? ViewType.noIntrinsicMetric) - - return nsView.measuredFittingSize - } - #endif -} -#endif -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift deleted file mode 100644 index 5dcf7b2217f3986181d92cd37623c82c9fd9821d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift +++ /dev/null @@ -1,454 +0,0 @@ -// Created by Bryn Bodayle on 1/24/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -// MARK: - SwiftUIMeasurementContainer - -/// A view that has an `intrinsicContentSize` of the `uiView`'s `systemLayoutSizeFitting(…)` and -/// supports double layout pass sizing and content size category changes. -/// -/// This container view uses an injected proposed width to measure the view and return its ideal -/// height through the `SwiftUISizingContext` binding. -/// -/// - SeeAlso: ``MeasuringViewRepresentable`` -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -final class SwiftUIMeasurementContainer: ViewType { - - // MARK: Lifecycle - - init(content: Content, strategy: SwiftUIMeasurementContainerStrategy) { - self.content = content - self.strategy = strategy - - // On iOS 15 and below, passing zero can result in a constraint failure the first time a view - // is displayed, but the system gracefully recovers afterwards. On iOS 16, it's fine to pass - // zero. - let initialSize: CGSize - if #available(iOS 16, tvOS 16, macOS 13, *) { - initialSize = .zero - } else { - initialSize = .init(width: 375, height: 150) - } - super.init(frame: .init(origin: .zero, size: initialSize)) - - addSubview(content) - setUpConstraints() - } - - @available(*, unavailable) - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - /// The most recently measured fitting size of the `uiView` that fits within the current - /// `proposedSize`. - /// - /// Contains `proposedSize`/`bounds.size` fallbacks for dimensions with no intrinsic size, as - /// compared to `intrinsicContentSize` which has `UIView.noIntrinsicMetric` fields in the case of - /// no intrinsic size. - var measuredFittingSize: CGSize { - _measuredFittingSize ?? measureView() - } - - /// The `UIView` content that's being measured by this container. - var content: Content { - didSet { - guard content !== oldValue else { return } - oldValue.removeFromSuperview() - addSubview(content) - // Invalidate the strategy since it's derived from this view. - _resolvedStrategy = nil - // Re-configure the constraints since they depend on the resolved strategy. - setUpConstraints() - // Finally, we need to re-measure the view. - _measuredFittingSize = nil - } - } - - /// The proposed size at the time of the latest measurement. - /// - /// Has a side-effect of updating the `measuredIntrinsicContentSize` if it's changed. - var proposedSize = CGSize.noIntrinsicMetric { - didSet { - guard oldValue != proposedSize else { return } - // The proposed size is only used by the measurement, so just re-measure. - _measuredFittingSize = nil - } - } - - /// The measurement strategy of this container. - /// - /// Has a side-effect of updating the `measuredIntrinsicContentSize` if it's changed. - var strategy: SwiftUIMeasurementContainerStrategy { - didSet { - guard oldValue != strategy else { return } - // Invalidate the resolved strategy since it's derived from this strategy. - _resolvedStrategy = nil - // Then, re-measure the view. - _measuredFittingSize = nil - } - } - - override var intrinsicContentSize: CGSize { - _intrinsicContentSize - } - - #if os(macOS) - override func layout() { - super.layout() - - // We need to re-measure the view whenever the size of the bounds changes, as the previous size - // may now be incorrect. - if latestMeasurementBoundsSize != nil, bounds.size != latestMeasurementBoundsSize { - // This will trigger SwiftUI to re-measure the view. - super.invalidateIntrinsicContentSize() - } - } - #else - override func layoutSubviews() { - super.layoutSubviews() - - // We need to re-measure the view whenever the size of the bounds changes, as the previous size - // may now be incorrect. - if latestMeasurementBoundsSize != nil, bounds.size != latestMeasurementBoundsSize { - // This will trigger SwiftUI to re-measure the view. - super.invalidateIntrinsicContentSize() - } - } - #endif - - override func invalidateIntrinsicContentSize() { - super.invalidateIntrinsicContentSize() - - // Invalidate the resolved strategy in case it changes with the re-measurement as it relies on - // the intrinsic size. - _resolvedStrategy = nil - _measuredFittingSize = nil - } - - // MARK: Private - - /// The most recently measured intrinsic content size of the `uiView`, else `noIntrinsicMetric` if - /// it has not yet been measured. - /// - /// Contains `UIView.noIntrinsicMetric` fallbacks for dimensions with no intrinsic size, - /// as compared to `measuredFittingSize` which has `proposedSize`/`bounds.size` fallbacks. - private var _intrinsicContentSize = CGSize.noIntrinsicMetric - - /// The bounds size at the time of the latest measurement. - private var latestMeasurementBoundsSize: CGSize? - - /// The most recently updated set of constraints constraining `uiView` to `self`. - private var uiViewConstraints = [NSLayoutConstraint.Attribute: NSLayoutConstraint]() - - /// The cached `resolvedStrategy` to prevent unnecessary re-measurements. - private var _resolvedStrategy: ResolvedSwiftUIMeasurementContainerStrategy? - - /// The cached `measuredFittingSize` to prevent unnecessary re-measurements. - private var _measuredFittingSize: CGSize? - - /// The resolved measurement strategy. - private var resolvedStrategy: ResolvedSwiftUIMeasurementContainerStrategy { - if let resolvedStrategy = _resolvedStrategy { - return resolvedStrategy - } - - let resolved: ResolvedSwiftUIMeasurementContainerStrategy - switch strategy { - case .automatic: - // Perform an intrinsic size measurement pass, which gives us valid values for - // `UILabel.preferredMaxLayoutWidth`. - let intrinsicSize = content.systemLayoutFittingIntrinsicSize() - - // If the view has a intrinsic width and contains a double layout pass subview, give it the - // proposed width to allow the label content to gracefully wrap to multiple lines. - if intrinsicSize.width > 0, content.containsDoubleLayoutPassSubviews() { - resolved = .intrinsicHeightProposedWidth - } else { - let zero = CGFloat(0) - switch (width: intrinsicSize.width, height: intrinsicSize.height) { - case (width: ...zero, height: ...zero): - resolved = .proposed - case (width: ...zero, height: zero.nextUp...): - resolved = .intrinsicHeightProposedWidth - case (width: zero.nextUp..., height: ...zero): - resolved = .intrinsicWidthProposedHeight - default: - resolved = .intrinsic(intrinsicSize) - } - } - case .proposed: - resolved = .proposed - case .intrinsicHeightProposedWidth: - resolved = .intrinsicHeightProposedWidth - case .intrinsicWidthProposedHeight: - resolved = .intrinsicWidthProposedHeight - case .intrinsic: - resolved = .intrinsic(content.systemLayoutFittingIntrinsicSize()) - } - _resolvedStrategy = resolved - return resolved - } - - private func setUpConstraints() { - content.translatesAutoresizingMaskIntoConstraints = false - - let leading = content.leadingAnchor.constraint(equalTo: leadingAnchor) - let top = content.topAnchor.constraint(equalTo: topAnchor) - let trailing = content.trailingAnchor.constraint(equalTo: trailingAnchor) - let bottom = content.bottomAnchor.constraint(equalTo: bottomAnchor) - let newConstraints: [NSLayoutConstraint.Attribute: NSLayoutConstraint] = [ - .leading: leading, .top: top, .trailing: trailing, .bottom: bottom, - ] - // Start with the lowest priority constraints so we aren't measuring the view too early, the - // priorities will be updated later on. - prioritizeConstraints(newConstraints, strategy: .intrinsic(.zero)) - - NSLayoutConstraint.deactivate(Array(uiViewConstraints.values)) - uiViewConstraints = newConstraints - NSLayoutConstraint.activate(Array(uiViewConstraints.values)) - } - - /// Prioritizes the given constraints based on the provided resolved strategy. - private func prioritizeConstraints( - _ constraints: [NSLayoutConstraint.Attribute: NSLayoutConstraint], - strategy: ResolvedSwiftUIMeasurementContainerStrategy) - { - // Give a required constraint in the dimensions that are fixed to the bounds, otherwise almost - // required. - switch strategy { - case .proposed: - constraints[.trailing]?.priority = .required - constraints[.bottom]?.priority = .required - case .intrinsicHeightProposedWidth: - constraints[.trailing]?.priority = .required - constraints[.bottom]?.priority = .almostRequired - case .intrinsicWidthProposedHeight: - constraints[.trailing]?.priority = .almostRequired - constraints[.bottom]?.priority = .required - case .intrinsic: - constraints[.trailing]?.priority = .almostRequired - constraints[.bottom]?.priority = .almostRequired - } - - #if os(macOS) - // On macOS, views default to having required constraints setting their height / width - // equal to their intrinsic content size. These have to be disabled in favor of the constraints - // we create here. - content.isVerticalContentSizeConstraintActive = false - content.isHorizontalContentSizeConstraintActive = false - #endif - } - - /// Measures the `uiView`, storing the resulting size in `measuredIntrinsicContentSize`. - private func measureView() -> CGSize { - latestMeasurementBoundsSize = bounds.size - prioritizeConstraints(uiViewConstraints, strategy: resolvedStrategy) - - var measuredSize: CGSize - let proposedSizeElseBounds = proposedSize.replacingNoIntrinsicMetric(with: bounds.size) - - switch resolvedStrategy { - case .proposed: - measuredSize = .noIntrinsicMetric - - case .intrinsicHeightProposedWidth: - measuredSize = content.systemLayoutFittingIntrinsicHeightFixedWidth(proposedSizeElseBounds.width) - measuredSize.width = ViewType.noIntrinsicMetric - - case .intrinsicWidthProposedHeight: - measuredSize = content.systemLayoutFittingIntrinsicWidthFixedHeight(proposedSizeElseBounds.height) - measuredSize.height = ViewType.noIntrinsicMetric - - case .intrinsic(let size): - measuredSize = size - - // If the measured size exceeds an available width or height, set the measured size to - // `noIntrinsicMetric` to ensure that the component can be compressed, otherwise it will - // overflow beyond the proposed size. - // - If the previous intrinsic content size is the same as the new proposed size, we don't - // do this as SwiftUI sometimes "proposes" the same intrinsic size back to the component and - // we don't want that scenario to prevent size changes when there is actually more space - // available. - if - proposedSize.width != ViewType.noIntrinsicMetric, - measuredSize.width > proposedSizeElseBounds.width, - _intrinsicContentSize.width != proposedSize.width - { - measuredSize.width = ViewType.noIntrinsicMetric - } - if - proposedSize.height != ViewType.noIntrinsicMetric, - measuredSize.height > proposedSizeElseBounds.height, - _intrinsicContentSize.height != proposedSize.height - { - measuredSize.height = ViewType.noIntrinsicMetric - } - } - - _intrinsicContentSize = measuredSize - - let measuredFittingSize = measuredSize.replacingNoIntrinsicMetric(with: proposedSizeElseBounds) - _measuredFittingSize = measuredFittingSize - return measuredFittingSize - } -} - -// MARK: - SwiftUIMeasurementContainerStrategy - -/// The measurement strategy of a `SwiftUIMeasurementContainer`. -enum SwiftUIMeasurementContainerStrategy { - /// The container makes a best effort to correctly choose the measurement strategy of the view. - /// - /// The best effort is based on a number of heuristics: - /// - The `uiView` will be given its intrinsic width and/or height when measurement in that - /// dimension produces a positive value, while zero/negative values will result in that - /// dimension receiving the available space proposed by the parent. - /// - If the view contains `UILabel` subviews that require a double layout pass as determined by - /// a `preferredMaxLayoutWidth` that's greater than zero after a layout, then the view will - /// default to `intrinsicHeightProposedWidth` to allow the labels to wrap. - /// - /// If you would like to opt out of automatic sizing for performance or to override the default - /// behavior, choose another strategy. - case automatic - - /// The `uiView` is sized to fill the area proposed by its parent. - /// - /// Typically used for views that should expand greedily in both axes, e.g. a background view. - case proposed - - /// The `uiView` is sized with its intrinsic height and expands horizontally to fill the width - /// proposed by its parent. - /// - /// Typically used for views that have a height that's a function of their width, e.g. a row with - /// text that can wrap to multiple lines. - case intrinsicHeightProposedWidth - - /// The `uiView` is sized with its intrinsic width and expands vertically to fill the height - /// proposed by its parent. - /// - /// Typically used for views that are free to grow vertically but have a fixed width, e.g. a view - /// in a horizontal carousel. - case intrinsicWidthProposedHeight - - /// The `uiView` is sized to its intrinsic width and height. - /// - /// Typically used for components with a specific intrinsic size in both axes, e.g. controls or - /// inputs. - case intrinsic -} - -// MARK: - ResolvedSwiftUIMeasurementContainerStrategy - -/// The resolved measurement strategy of a `SwiftUIMeasurementContainer`, matching the cases of the -/// `SwiftUIMeasurementContainerStrategy` without the automatic case. -private enum ResolvedSwiftUIMeasurementContainerStrategy { - case proposed, intrinsicHeightProposedWidth, intrinsicWidthProposedHeight, intrinsic(CGSize) -} - -// MARK: - UILayoutPriority - -extension LayoutPriorityType { - /// An "almost required" constraint, useful for creating near-required constraints that don't - /// error when unable to be satisfied. - @nonobjc - fileprivate static var almostRequired: LayoutPriorityType { .init(rawValue: required.rawValue - 1) } -} - -// MARK: - UIView - -extension ViewType { - /// The `systemLayoutSizeFitting(…)` of this view with a compressed size and fitting priorities. - @nonobjc - fileprivate func systemLayoutFittingIntrinsicSize() -> CGSize { - #if os(macOS) - intrinsicContentSize - #else - systemLayoutSizeFitting( - UIView.layoutFittingCompressedSize, - withHorizontalFittingPriority: .fittingSizeLevel, - verticalFittingPriority: .fittingSizeLevel) - #endif - } - - /// The `systemLayoutSizeFitting(…)` of this view with a compressed height with a fitting size - /// priority and with the given fixed width and fitting priority. - @nonobjc - fileprivate func systemLayoutFittingIntrinsicHeightFixedWidth( - _ width: CGFloat, - priority: LayoutPriorityType = .almostRequired) - -> CGSize - { - #if os(macOS) - return CGSize(width: width, height: intrinsicContentSize.height) - #else - let targetSize = CGSize(width: width, height: UIView.layoutFittingCompressedSize.height) - - return systemLayoutSizeFitting( - targetSize, - withHorizontalFittingPriority: priority, - verticalFittingPriority: .fittingSizeLevel) - #endif - } - - /// The `systemLayoutSizeFitting(…)` of this view with a compressed width with a fitting size - /// priority and with the given fixed height and fitting priority. - @nonobjc - fileprivate func systemLayoutFittingIntrinsicWidthFixedHeight( - _ height: CGFloat, - priority: LayoutPriorityType = .almostRequired) - -> CGSize - { - #if os(macOS) - return CGSize(width: intrinsicContentSize.width, height: height) - #else - let targetSize = CGSize(width: UIView.layoutFittingCompressedSize.width, height: height) - - return systemLayoutSizeFitting( - targetSize, - withHorizontalFittingPriority: .fittingSizeLevel, - verticalFittingPriority: priority) - #endif - } - - /// Whether this view or any of its subviews has a subview that has a double layout pass `UILabel` - /// as determined by a non-zero `preferredMaxLayoutWidth`, which implies that it should get a - /// `intrinsicHeightProposedWidth` sizing strategy to allow the label to wrap and grow. - @nonobjc - fileprivate func containsDoubleLayoutPassSubviews() -> Bool { - #if os(macOS) - return false - #else - var contains = false - if let label = self as? UILabel, label.preferredMaxLayoutWidth > 0 { - contains = true - } - for subview in subviews { - contains = contains || subview.containsDoubleLayoutPassSubviews() - } - return contains - #endif - } -} - -// MARK: - CGSize - -extension CGSize { - /// A `CGSize` with `noIntrinsicMetric` for both its width and height. - fileprivate static var noIntrinsicMetric: CGSize { - .init(width: ViewType.noIntrinsicMetric, height: ViewType.noIntrinsicMetric) - } - - /// Returns a `CGSize` with its width and/or height replaced with the corresponding field of the - /// provided `fallback` size if they are `UIView.noIntrinsicMetric`. - fileprivate func replacingNoIntrinsicMetric(with fallback: CGSize) -> CGSize { - .init( - width: width == ViewType.noIntrinsicMetric ? fallback.width : width, - height: height == ViewType.noIntrinsicMetric ? fallback.height : height) - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/SwiftUIView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/SwiftUIView.swift deleted file mode 100644 index 8be06f2893c0a27c415f5673429c0fc9d7b1b9c8..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/SwiftUIView.swift +++ /dev/null @@ -1,150 +0,0 @@ -// Created by eric_horacek on 9/8/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -// MARK: - SwiftUIView - -/// A `UIViewRepresentable` SwiftUI `View` that wraps its `Content` `UIView` within a -/// `SwiftUIMeasurementContainer`, used to size a UIKit view correctly within a SwiftUI view -/// hierarchy. -/// -/// Includes an optional generic `Storage` value, which can be used to compare old and new values -/// across state changes to prevent redundant view updates. -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -struct SwiftUIView: MeasuringViewRepresentable, - UIViewConfiguringSwiftUIView -{ - - // MARK: Lifecycle - - /// Creates a SwiftUI representation of the content view with the given storage and the provided - /// `makeContent` closure to construct the content whenever `makeUIView(…)` is invoked. - init(storage: Storage, makeContent: @escaping () -> Content) { - self.storage = storage - self.makeContent = makeContent - } - - /// Creates a SwiftUI representation of the content view with the provided `makeContent` closure - /// to construct it whenever `makeUIView(…)` is invoked. - init(makeContent: @escaping () -> Content) where Storage == Void { - storage = () - self.makeContent = makeContent - } - - // MARK: Internal - - var configurations: [Configuration] = [] - - var sizing: SwiftUIMeasurementContainerStrategy = .automatic - - // MARK: Private - - /// The current stored value, with the previous value provided to the configuration closure as - /// the `oldStorage`. - private var storage: Storage - - /// A closure that's invoked to construct the represented content view. - private var makeContent: () -> Content -} - -// MARK: UIViewRepresentable - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension SwiftUIView { - func makeCoordinator() -> Coordinator { - Coordinator(storage: storage) - } - - #if os(macOS) - func makeNSView(context _: Context) -> SwiftUIMeasurementContainer { - SwiftUIMeasurementContainer(content: makeContent(), strategy: sizing) - } - - func updateNSView(_ uiView: SwiftUIMeasurementContainer, context: Context) { - let oldStorage = context.coordinator.storage - context.coordinator.storage = storage - - let configurationContext = ConfigurationContext( - oldStorage: oldStorage, - viewRepresentableContext: context, - container: uiView) - - for configuration in configurations { - configuration(configurationContext) - } - } - #else - func makeUIView(context _: Context) -> SwiftUIMeasurementContainer { - SwiftUIMeasurementContainer(content: makeContent(), strategy: sizing) - } - - func updateUIView(_ uiView: SwiftUIMeasurementContainer, context: Context) { - let oldStorage = context.coordinator.storage - context.coordinator.storage = storage - - let configurationContext = ConfigurationContext( - oldStorage: oldStorage, - viewRepresentableContext: context, - container: uiView) - - for configuration in configurations { - configuration(configurationContext) - } - } - #endif -} - -// MARK: SwiftUIView.ConfigurationContext - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension SwiftUIView { - /// The configuration context that's available to configure the `Content` view whenever the - /// `updateUIView()` method is invoked via a configuration closure. - struct ConfigurationContext: ViewProviding { - /// The previous value for the `Storage` of this `SwiftUIView`, which can be used to store - /// values across state changes to prevent redundant view updates. - var oldStorage: Storage - - /// The `UIViewRepresentable.Context`, with information about the transaction and environment. - var viewRepresentableContext: Context - - /// The backing measurement container that contains the `Content`. - var container: SwiftUIMeasurementContainer - - /// The `UIView` content that's being configured. - /// - /// Setting this to a new value updates the backing measurement container's `content`. - var view: Content { - get { container.content } - nonmutating set { container.content = newValue } - } - - /// A convenience accessor indicating whether this content update should be animated. - var animated: Bool { - viewRepresentableContext.transaction.animation != nil - } - } -} - -// MARK: SwiftUIView.Coordinator - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension SwiftUIView { - /// A coordinator that stores the `storage` associated with this view, enabling the old storage - /// value to be accessed during the `updateUIView(…)`. - final class Coordinator { - - // MARK: Lifecycle - - fileprivate init(storage: Storage) { - self.storage = storage - } - - // MARK: Internal - - fileprivate(set) var storage: Storage - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIView+SwiftUIView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIView+SwiftUIView.swift deleted file mode 100644 index 4984ea0d0845b9de381898fedebae9531c0a2db9..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIView+SwiftUIView.swift +++ /dev/null @@ -1,42 +0,0 @@ -// Created by eric_horacek on 3/3/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -// MARK: - ViewTypeProtocol + swiftUIView - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension ViewTypeProtocol { - /// Returns a SwiftUI `View` representing this `UIView`, constructed with the given `makeView` - /// closure and sized with the given sizing configuration. - /// - /// To perform additional configuration of the `UIView` instance, call `configure` on the - /// returned SwiftUI `View`: - /// ``` - /// MyUIView.swiftUIView(…) - /// .configure { context in - /// context.view.doSomething() - /// } - /// ``` - /// - /// To configure the sizing behavior of the `UIView` instance, call `sizing` on the returned - /// SwiftUI `View`: - /// ``` - /// MyView.swiftUIView(…).sizing(.intrinsicSize) - /// ``` - /// The sizing defaults to `.automatic`. - static func swiftUIView(makeView: @escaping () -> Self) -> SwiftUIView { - SwiftUIView(makeContent: makeView) - } -} - -// MARK: - ViewTypeProtocol - -/// A protocol that all `UIView`s conform to, enabling extensions that have a `Self` reference. -protocol ViewTypeProtocol: ViewType { } - -// MARK: - ViewType + ViewTypeProtocol - -extension ViewType: ViewTypeProtocol { } -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIViewConfiguringSwiftUIView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIViewConfiguringSwiftUIView.swift deleted file mode 100644 index 7a2405823c4cff4c98215ee4e4350c2f073432dd..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/UIViewConfiguringSwiftUIView.swift +++ /dev/null @@ -1,45 +0,0 @@ -// Created by eric_horacek on 3/4/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -// MARK: - UIViewConfiguringSwiftUIView - -/// A protocol describing a SwiftUI `View` that can configure its `UIView` content via an array of -/// `configuration` closures. -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -protocol UIViewConfiguringSwiftUIView: View { - /// The context available to this configuration, which provides the `UIView` instance at a minimum - /// but can include additional context as needed. - associatedtype ConfigurationContext: ViewProviding - - /// A closure that is invoked to configure the represented content view. - typealias Configuration = (ConfigurationContext) -> Void - - /// A mutable array of configuration closures that should each be invoked with the - /// `ConfigurationContext` whenever `updateUIView` is called in a `UIViewRepresentable`. - var configurations: [Configuration] { get set } -} - -// MARK: Extensions - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension UIViewConfiguringSwiftUIView { - /// Returns a copy of this view updated to have the given closure applied to its represented view - /// whenever it is updated via the `updateUIView(…)` method. - func configure(_ configure: @escaping Configuration) -> Self { - var copy = self - copy.configurations.append(configure) - return copy - } - - /// Returns a copy of this view updated to have the given closures applied to its represented view - /// whenever it is updated via the `updateUIView(…)` method. - func configurations(_ configurations: [Configuration]) -> Self { - var copy = self - copy.configurations.append(contentsOf: configurations) - return copy - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/BehaviorsConfigurableView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/BehaviorsConfigurableView.swift deleted file mode 100644 index 33c63f5684ad9de9eb5a93c80de2051d1d250cad..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/BehaviorsConfigurableView.swift +++ /dev/null @@ -1,45 +0,0 @@ -// Created by Tyler Hedrick on 5/26/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - BehaviorsConfigurableView - -/// A view that can be configured with a `Behaviors` instance that contains the view's non- -/// `Equatable` properties that can be updated on view instances after initialization, e.g. callback -/// closures or delegates. -/// -/// Since it is not possible to establish the equality of two `Behaviors` instances, `Behaviors` -/// will be set more often than `ContentConfigurableView.Content`, needing to be updated every time -/// the view's corresponding `EpoxyModeled` instance is updated. As such, setting behaviors should -/// be as lightweight as possible. -/// -/// Properties of `Behaviors` should be mutually exclusive with the properties in the -/// `StyledView.Style` and `ContentConfigurableView.Content`. -/// -/// - SeeAlso: `ContentConfigurableView` -/// - SeeAlso: `StyledView` -/// - SeeAlso: `EpoxyableView` -protocol BehaviorsConfigurableView: ViewType { - /// The non-`Equatable` properties that can be changed over of the lifecycle this View's - /// instances, e.g. callback closures or delegates. - /// - /// Defaults to `Never` for views that do not have `Behaviors`. - associatedtype Behaviors = Never - - /// Updates the behaviors of this view to those in the given `behaviors`, else resets the - /// behaviors if `nil`. - /// - /// Behaviors are optional as they must be "resettable" in order for Epoxy to reset the behaviors - /// on your view when no behaviors are provided. - func setBehaviors(_ behaviors: Self.Behaviors?) -} - -// MARK: Defaults - -extension BehaviorsConfigurableView where Behaviors == Never { - func setBehaviors(_ behaviors: Never?) { - switch behaviors { - case nil: - break - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/ContentConfigurableView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/ContentConfigurableView.swift deleted file mode 100644 index 6ebce5ac17fbac5228c59b04602df8ed1c3392bb..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/ContentConfigurableView.swift +++ /dev/null @@ -1,36 +0,0 @@ -// Created by Laura Skelton on 5/30/17. -// Copyright © 2017 Airbnb. All rights reserved. - -// MARK: - ContentConfigurableView - -/// A view that can be configured with a `Content` instance that contains the view's `Equatable` -/// properties that can be updated on existing view instances, e.g. text `String`s or image `URL`s. -/// -/// For performance, it is generally expected that `Content` is only set when it is not equal to the -/// previous `Content` instance that has been set on a view instance. As a further optimization, -/// this view can guard updates on the equality of each property of the `Content` against the -/// current property value when set. -/// -/// Properties of `Content` should be mutually exclusive with the properties of the -/// `StyledView.Style` and `BehaviorsConfigurableView.Behaviors`. -/// -/// - SeeAlso: `BehaviorsConfigurableView` -/// - SeeAlso: `StyledView` -/// - SeeAlso: `EpoxyableView` -protocol ContentConfigurableView: ViewType { - /// The `Equatable` properties that can be updated on instances of this view, e.g. text `String`s - /// or image `URL`s. - /// - /// Defaults to `Never` for views that do not have `Content`. - associatedtype Content: Equatable = Never - - /// Updates the content of this view to the properties of the given `content`, optionally - /// animating the updates. - func setContent(_ content: Self.Content, animated: Bool) -} - -// MARK: Defaults - -extension ContentConfigurableView where Content == Never { - func setContent(_: Never, animated _: Bool) { } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/EpoxyableView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/EpoxyableView.swift deleted file mode 100644 index 5f13195a312f77b94cd2b553ad0397e05e2b2826..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/EpoxyableView.swift +++ /dev/null @@ -1,5 +0,0 @@ -// Created by eric_horacek on 1/13/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -/// A `UIView` that can be declaratively configured via a concrete `EpoxyableModel` instance. -typealias EpoxyableView = BehaviorsConfigurableView & ContentConfigurableView & StyledView diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/StyledView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/StyledView.swift deleted file mode 100644 index 13f871199b4aa7f97d33fbd5497bfdd085a59a86..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/StyledView.swift +++ /dev/null @@ -1,42 +0,0 @@ -// Created by Laura Skelton on 4/14/16. -// Copyright © 2016 Airbnb. All rights reserved. - -// MARK: - StyledView - -/// A view that can be initialized with a `Style` instance that contains the view's invariant -/// configuration parameters, e.g. the `UIButton.ButtonType` of a `UIButton`. -/// -/// A `Style` is expected to be invariant over the lifecycle of the view; it should not possible to -/// change the `Style` of a view after it is created. All variant properties of the view should -/// either be included in the `ContentConfigurableView.Content` if they are `Equatable` (e.g. a -/// title `String`) or the `BehaviorsConfigurableView.Behaviors` if they are not (e.g. a callback -/// closure). -/// -/// A `Style` is `Hashable` to allow views of the same type with equal `Style`s to be reused by -/// establishing whether their invariant `Style` instances are equal. -/// -/// Properties of `Style` should be mutually exclusive with the properties of the -/// `ContentConfigurableView.Content` and `BehaviorsConfigurableView.Behaviors`. -/// -/// - SeeAlso: `ContentConfigurableView` -/// - SeeAlso: `BehaviorsConfigurableView` -/// - SeeAlso: `EpoxyableView` -protocol StyledView: ViewType { - /// The style type of this view, passed into its initializer to configure the resulting instance. - /// - /// Defaults to `Never` for views that do not have a `Style`. - associatedtype Style: Hashable = Never - - /// Creates an instance of this view configured with the given `Style` instance. - init(style: Style) -} - -// MARK: Defaults - -extension StyledView where Style == Never { - init(style: Never) { - // An empty switch is required to silence the "'self.init' isn't called on all paths before - // returning from initializer" error. - switch style { } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/ViewType.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/ViewType.swift deleted file mode 100644 index c673d28746d689108c332f89b8143f6aa1d51d43..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/EpoxyCore/Views/ViewType.swift +++ /dev/null @@ -1,52 +0,0 @@ -// Created by Cal Stephens on 6/26/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI -#if canImport(UIKit) -import UIKit - -/// The platform's main view type. -/// Either `UIView` on iOS/tvOS or `NSView` on macOS. -typealias ViewType = UIView - -/// The platform's SwiftUI view representable type. -/// Either `UIViewRepresentable` on iOS/tvOS or `NSViewRepresentable` on macOS. -@available(iOS 13.0, tvOS 13.0, *) -typealias ViewRepresentableType = UIViewRepresentable - -/// The platform's layout constraint priority type. -/// Either `UILayoutPriority` on iOS/tvOS or `NSLayoutConstraint.Priority` on macOS. -typealias LayoutPriorityType = UILayoutPriority - -@available(iOS 13.0, tvOS 13.0, *) -extension ViewRepresentableType { - /// The platform's view type for `ViewRepresentableType`. - /// Either `UIViewType` on iOS/tvOS or `NSViewType` on macOS. - typealias RepresentableViewType = UIViewType -} - -#elseif canImport(AppKit) -import AppKit - -/// The platform's main view type. -/// Either `UIView` on iOS/tvOS, or `NSView` on macOS. -typealias ViewType = NSView - -/// The platform's SwiftUI view representable type. -/// Either `UIViewRepresentable` on iOS/tvOS, or `NSViewRepresentable` on macOS. -@available(macOS 10.15, *) -typealias ViewRepresentableType = NSViewRepresentable - -/// The platform's layout constraint priority type. -/// Either `UILayoutPriority` on iOS/tvOS, or `NSLayoutConstraint.Priority` on macOS. -typealias LayoutPriorityType = NSLayoutConstraint.Priority - -@available(macOS 10.15, *) -extension ViewRepresentableType { - /// The platform's view type for `ViewRepresentableType`. - /// Either `UIViewType` on iOS/tvOS or `NSViewType` on macOS. - typealias RepresentableViewType = NSViewType -} -#endif -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/LRUCache/LRUCache.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/LRUCache/LRUCache.swift deleted file mode 100644 index 9a0e033391f278c5afb9f73ecf9076140fb649fb..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/LRUCache/LRUCache.swift +++ /dev/null @@ -1,256 +0,0 @@ -// -// LRUCache.swift -// LRUCache -// -// Version 1.0.2 -// -// Created by Nick Lockwood on 05/08/2021. -// Copyright © 2021 Nick Lockwood. All rights reserved. -// -// Distributed under the permissive MIT license -// Get the latest version from here: -// -// https://github.com/nicklockwood/LRUCache -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// - -import Foundation - -#if canImport(UIKit) -import UIKit - -/// Notification that cache should be cleared -let LRUCacheMemoryWarningNotification: NSNotification.Name = - UIApplication.didReceiveMemoryWarningNotification - -#else - -/// Notification that cache should be cleared -let LRUCacheMemoryWarningNotification: NSNotification.Name = - .init("LRUCacheMemoryWarningNotification") - -#endif - -// MARK: - LRUCache - -final class LRUCache { - - // MARK: Lifecycle - - /// Initialize the cache with the specified `totalCostLimit` and `countLimit` - init( - totalCostLimit: Int = .max, - countLimit: Int = .max, - notificationCenter: NotificationCenter = .default) - { - self.totalCostLimit = totalCostLimit - self.countLimit = countLimit - self.notificationCenter = notificationCenter - - token = notificationCenter.addObserver( - forName: LRUCacheMemoryWarningNotification, - object: nil, - queue: nil) - { [weak self] _ in - self?.removeAllValues() - } - } - - deinit { - if let token { - notificationCenter.removeObserver(token) - } - } - - // MARK: Internal - - /// The current total cost of values in the cache - private(set) var totalCost = 0 - - /// The maximum total cost permitted - var totalCostLimit: Int { - didSet { clean() } - } - - /// The maximum number of values permitted - var countLimit: Int { - didSet { clean() } - } - - // MARK: Private - - private var values: [Key: Container] = [:] - private unowned(unsafe) var head: Container? - private unowned(unsafe) var tail: Container? - private let lock: NSLock = .init() - private var token: AnyObject? - private let notificationCenter: NotificationCenter - -} - -extension LRUCache { - /// The number of values currently stored in the cache - var count: Int { - values.count - } - - /// Is the cache empty? - var isEmpty: Bool { - values.isEmpty - } - - /// Returns all values in the cache from oldest to newest - var allValues: [Value] { - lock.lock() - defer { lock.unlock() } - var values = [Value]() - var next = head - while let container = next { - values.append(container.value) - next = container.next - } - return values - } - - /// Insert a value into the cache with optional `cost` - func setValue(_ value: Value?, forKey key: Key, cost: Int = 0) { - guard let value else { - removeValue(forKey: key) - return - } - lock.lock() - if let container = values[key] { - container.value = value - totalCost -= container.cost - container.cost = cost - remove(container) - append(container) - } else { - let container = Container( - value: value, - cost: cost, - key: key) - values[key] = container - append(container) - } - totalCost += cost - lock.unlock() - clean() - } - - /// Remove a value from the cache and return it - @discardableResult - func removeValue(forKey key: Key) -> Value? { - lock.lock() - defer { lock.unlock() } - guard let container = values.removeValue(forKey: key) else { - return nil - } - remove(container) - totalCost -= container.cost - return container.value - } - - /// Fetch a value from the cache - func value(forKey key: Key) -> Value? { - lock.lock() - defer { lock.unlock() } - if let container = values[key] { - remove(container) - append(container) - return container.value - } - return nil - } - - /// Remove all values from the cache - func removeAllValues() { - lock.lock() - values.removeAll() - head = nil - tail = nil - lock.unlock() - } -} - -extension LRUCache { - - // MARK: Fileprivate - - fileprivate final class Container { - - // MARK: Lifecycle - - init(value: Value, cost: Int, key: Key) { - self.value = value - self.cost = cost - self.key = key - } - - // MARK: Internal - - var value: Value - var cost: Int - let key: Key - unowned(unsafe) var prev: Container? - unowned(unsafe) var next: Container? - - } - - // MARK: Private - - // Remove container from list (must be called inside lock) - private func remove(_ container: Container) { - if head === container { - head = container.next - } - if tail === container { - tail = container.prev - } - container.next?.prev = container.prev - container.prev?.next = container.next - container.next = nil - } - - // Append container to list (must be called inside lock) - private func append(_ container: Container) { - assert(container.next == nil) - if head == nil { - head = container - } - container.prev = tail - tail?.next = container - tail = container - } - - // Remove expired values (must be called outside lock) - private func clean() { - lock.lock() - defer { lock.unlock() } - while - totalCost > totalCostLimit || count > countLimit, - let container = head - { - remove(container) - values.removeValue(forKey: container.key) - totalCost -= container.cost - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/LRUCache/README.md b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/LRUCache/README.md deleted file mode 100644 index cd1100fcf36e98f0acaeff98081a6f1f9dc3b211..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/LRUCache/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## LRUCache - -This directory includes the source code of the LRUCache library, from the following release: -https://github.com/nicklockwood/LRUCache/releases/tag/1.0.4 - -Lottie is distributed via multiple package managers (SPM, Cocoapods, Carthage, and NPM), -each with different packaging and compilation requirements. - -Due to limitations of these package managers, we can't depend on / import -a separate LRUCache module / library. Instead, we include the source -directly within the Lottie library and compile everything as a single unit. - -### Update instructions - -From time to time we may need to update to a more recent version of LRUCache. -When doing this, follow these steps: - - 1. Download the latest release from https://github.com/nicklockwood/LRUCache - and replace the source code in this directory with the updated code. - - 2. Update the URL at the top of this file to indicate what release is being used. - - 3. Change all of the `public` symbols defined in this module to instead be `internal` - to prevent Lottie from exposing any EpoxyCore APIs. diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/README.md b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/README.md deleted file mode 100644 index f925b8895f79a682ef8617c0bc8dc1ed60dd6094..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/README.md +++ /dev/null @@ -1,43 +0,0 @@ -## ZipFoundation - -This directory includes the source code of libraries that are embedded within lottie-ios. - -This includes: - - ZipFoundation (https://github.com/weichsel/ZIPFoundation) - - EpoxyCore (https://github.com/airbnb/epoxy-ios) - - LRUCache (https://github.com/nicklockwood/LRUCache) - -Lottie is distributed via multiple package managers (SPM, Cocoapods, Carthage, and NPM), -each with different packaging and compilation requirements. - -Due to limitations of these package managers, we can't depend on / import -a separates modules / libraries. Instead, we include the source -directly within the Lottie library and compile everything as a single unit. - -### Update instructions - -From time to time we may need to update to a more recent version of one of these libraries. -When doing this, follow these steps: - - 1. Download the latest release of the library and replace the source code in - the corresponding directory with the updated code. - - 2. Update the URL in the directory's README.md to indicate what release is being used. - - 3. Change all of the `public` symbols defined in the module to instead be `internal` - to prevent Lottie from exposing any APIs from other libraries. - -### Adding a new dependencies - - 1. Create a subdirectory in `EmbeddedLibraries` for the new dependency. - - 2. Add the dependency to the list at the top of this file. - - 3. Add a `README.md` to the directory for the new library, using the same formatting as the `README.md` file used by other dependencies. - - 4. Exclude the new `README.md` file from the lottie-ios package by adding it to the `exclude:` list in `Package.swift`. - - 5. Change all of the `public` symbols defined in the module to instead be `internal` - to prevent Lottie from exposing any APIs from other libraries. - - 6. If the dependency provides a privacy manifest, incorporate content from that dependency's privacy manifest into Lottie's privacy manifest. diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+BackingConfiguration.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+BackingConfiguration.swift deleted file mode 100644 index 101b0363f3b6f46cc21cd2d63d74b50dc5925762..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+BackingConfiguration.swift +++ /dev/null @@ -1,147 +0,0 @@ -// -// Archive+BackingConfiguration.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Archive { - - struct BackingConfiguration { - let file: FILEPointer - let endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord - let zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory? - - #if swift(>=5.0) - let memoryFile: MemoryFile? - - init( - file: FILEPointer, - endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord, - zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory? = nil, - memoryFile: MemoryFile? = nil) - { - self.file = file - self.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord - self.zip64EndOfCentralDirectory = zip64EndOfCentralDirectory - self.memoryFile = memoryFile - } - #else - - init( - file: FILEPointer, - endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord, - zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory?) - { - self.file = file - self.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord - self.zip64EndOfCentralDirectory = zip64EndOfCentralDirectory - } - #endif - } - - static func makeBackingConfiguration(for url: URL, mode: AccessMode) - -> BackingConfiguration? - { - let fileManager = FileManager() - switch mode { - case .read: - let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path) - guard - let archiveFile = fopen(fileSystemRepresentation, "rb"), - let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) - else { - return nil - } - return BackingConfiguration( - file: archiveFile, - endOfCentralDirectoryRecord: eocdRecord, - zip64EndOfCentralDirectory: zip64EOCD) - case .create: - let endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord( - numberOfDisk: 0, - numberOfDiskStart: 0, - totalNumberOfEntriesOnDisk: 0, - totalNumberOfEntriesInCentralDirectory: 0, - sizeOfCentralDirectory: 0, - offsetToStartOfCentralDirectory: 0, - zipFileCommentLength: 0, - zipFileCommentData: Data()) - do { - try endOfCentralDirectoryRecord.data.write(to: url, options: .withoutOverwriting) - } catch { return nil } - fallthrough - case .update: - let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path) - guard - let archiveFile = fopen(fileSystemRepresentation, "rb+"), - let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) - else { - return nil - } - fseeko(archiveFile, 0, SEEK_SET) - return BackingConfiguration( - file: archiveFile, - endOfCentralDirectoryRecord: eocdRecord, - zip64EndOfCentralDirectory: zip64EOCD) - } - } - - #if swift(>=5.0) - static func makeBackingConfiguration(for data: Data, mode: AccessMode) - -> BackingConfiguration? - { - let posixMode: String - switch mode { - case .read: posixMode = "rb" - case .create: posixMode = "wb+" - case .update: posixMode = "rb+" - } - let memoryFile = MemoryFile(data: data) - guard let archiveFile = memoryFile.open(mode: posixMode) else { return nil } - - switch mode { - case .read: - guard let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else { - return nil - } - - return BackingConfiguration( - file: archiveFile, - endOfCentralDirectoryRecord: eocdRecord, - zip64EndOfCentralDirectory: zip64EOCD, - memoryFile: memoryFile) - case .create: - let endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord( - numberOfDisk: 0, - numberOfDiskStart: 0, - totalNumberOfEntriesOnDisk: 0, - totalNumberOfEntriesInCentralDirectory: 0, - sizeOfCentralDirectory: 0, - offsetToStartOfCentralDirectory: 0, - zipFileCommentLength: 0, - zipFileCommentData: Data()) - _ = endOfCentralDirectoryRecord.data.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in - fwrite(buffer.baseAddress, buffer.count, 1, archiveFile) // Errors handled during read - } - fallthrough - case .update: - guard let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else { - return nil - } - - fseeko(archiveFile, 0, SEEK_SET) - return BackingConfiguration( - file: archiveFile, - endOfCentralDirectoryRecord: eocdRecord, - zip64EndOfCentralDirectory: zip64EOCD, - memoryFile: memoryFile) - } - } - #endif -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Helpers.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Helpers.swift deleted file mode 100644 index 28690de5feeb3280d1d9bf6a1035cd4a615933bc..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Helpers.swift +++ /dev/null @@ -1,351 +0,0 @@ -// -// Archive+Helpers.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Archive { - - // MARK: - Reading - - func readUncompressed( - entry: Entry, - bufferSize: Int, - skipCRC32: Bool, - progress: Progress? = nil, - with consumer: Consumer) - throws -> CRC32 - { - let size = entry.centralDirectoryStructure.effectiveUncompressedSize - guard size <= .max else { throw ArchiveError.invalidEntrySize } - return try Data.consumePart( - of: Int64(size), - chunkSize: bufferSize, - skipCRC32: skipCRC32, - provider: { _, chunkSize -> Data in - try Data.readChunk(of: chunkSize, from: self.archiveFile) - }, - consumer: { data in - if progress?.isCancelled == true { throw ArchiveError.cancelledOperation } - try consumer(data) - progress?.completedUnitCount += Int64(data.count) - }) - } - - func readCompressed( - entry: Entry, - bufferSize: Int, - skipCRC32: Bool, - progress: Progress? = nil, - with consumer: Consumer) - throws -> CRC32 - { - let size = entry.centralDirectoryStructure.effectiveCompressedSize - guard size <= .max else { throw ArchiveError.invalidEntrySize } - return try Data.decompress( - size: Int64(size), - bufferSize: bufferSize, - skipCRC32: skipCRC32, - provider: { _, chunkSize -> Data in - try Data.readChunk(of: chunkSize, from: self.archiveFile) - }, - consumer: { data in - if progress?.isCancelled == true { throw ArchiveError.cancelledOperation } - try consumer(data) - progress?.completedUnitCount += Int64(data.count) - }) - } - - // MARK: - Writing - - func writeEntry( - uncompressedSize: Int64, - type: Entry.EntryType, - compressionMethod: CompressionMethod, - bufferSize: Int, - progress: Progress? = nil, - provider: Provider) throws -> (sizeWritten: Int64, crc32: CRC32) - { - var checksum = CRC32(0) - var sizeWritten = Int64(0) - switch type { - case .file: - switch compressionMethod { - case .none: - (sizeWritten, checksum) = try writeUncompressed( - size: uncompressedSize, - bufferSize: bufferSize, - progress: progress, - provider: provider) - case .deflate: - (sizeWritten, checksum) = try writeCompressed( - size: uncompressedSize, - bufferSize: bufferSize, - progress: progress, - provider: provider) - } - case .directory: - _ = try provider(0, 0) - if let progress { progress.completedUnitCount = progress.totalUnitCount } - case .symlink: - let (linkSizeWritten, linkChecksum) = try writeSymbolicLink( - size: Int(uncompressedSize), - provider: provider) - (sizeWritten, checksum) = (Int64(linkSizeWritten), linkChecksum) - if let progress { progress.completedUnitCount = progress.totalUnitCount } - } - return (sizeWritten, checksum) - } - - func writeLocalFileHeader( - path: String, - compressionMethod: CompressionMethod, - size: (uncompressed: UInt64, compressed: UInt64), - checksum: CRC32, - modificationDateTime: (UInt16, UInt16)) - throws -> LocalFileHeader - { - // We always set Bit 11 in generalPurposeBitFlag, which indicates an UTF-8 encoded path. - guard let fileNameData = path.data(using: .utf8) else { throw ArchiveError.invalidEntryPath } - - var uncompressedSizeOfLFH = UInt32(0) - var compressedSizeOfLFH = UInt32(0) - var extraFieldLength = UInt16(0) - var zip64ExtendedInformation: Entry.ZIP64ExtendedInformation? - var versionNeededToExtract = Version.v20.rawValue - // ZIP64 Extended Information in the Local header MUST include BOTH original and compressed file size fields. - if size.uncompressed >= maxUncompressedSize || size.compressed >= maxCompressedSize { - uncompressedSizeOfLFH = .max - compressedSizeOfLFH = .max - extraFieldLength = UInt16(20) // 2 + 2 + 8 + 8 - versionNeededToExtract = Version.v45.rawValue - zip64ExtendedInformation = Entry.ZIP64ExtendedInformation( - dataSize: extraFieldLength - 4, - uncompressedSize: size.uncompressed, - compressedSize: size.compressed, - relativeOffsetOfLocalHeader: 0, - diskNumberStart: 0) - } else { - uncompressedSizeOfLFH = UInt32(size.uncompressed) - compressedSizeOfLFH = UInt32(size.compressed) - } - - let localFileHeader = LocalFileHeader( - versionNeededToExtract: versionNeededToExtract, - generalPurposeBitFlag: UInt16(2048), - compressionMethod: compressionMethod.rawValue, - lastModFileTime: modificationDateTime.1, - lastModFileDate: modificationDateTime.0, - crc32: checksum, - compressedSize: compressedSizeOfLFH, - uncompressedSize: uncompressedSizeOfLFH, - fileNameLength: UInt16(fileNameData.count), - extraFieldLength: extraFieldLength, - fileNameData: fileNameData, - extraFieldData: zip64ExtendedInformation?.data ?? Data()) - _ = try Data.write(chunk: localFileHeader.data, to: archiveFile) - return localFileHeader - } - - func writeCentralDirectoryStructure( - localFileHeader: LocalFileHeader, - relativeOffset: UInt64, - externalFileAttributes: UInt32) - throws -> CentralDirectoryStructure - { - var extraUncompressedSize: UInt64? - var extraCompressedSize: UInt64? - var extraOffset: UInt64? - var relativeOffsetOfCD = UInt32(0) - var extraFieldLength = UInt16(0) - var zip64ExtendedInformation: Entry.ZIP64ExtendedInformation? - if localFileHeader.uncompressedSize == .max || localFileHeader.compressedSize == .max { - let zip64Field = Entry.ZIP64ExtendedInformation - .scanForZIP64Field(in: localFileHeader.extraFieldData, fields: [.uncompressedSize, .compressedSize]) - extraUncompressedSize = zip64Field?.uncompressedSize - extraCompressedSize = zip64Field?.compressedSize - } - if relativeOffset >= maxOffsetOfLocalFileHeader { - extraOffset = relativeOffset - relativeOffsetOfCD = .max - } else { - relativeOffsetOfCD = UInt32(relativeOffset) - } - extraFieldLength = [extraUncompressedSize, extraCompressedSize, extraOffset] - .compactMap { $0 } - .reduce(UInt16(0)) { $0 + UInt16(MemoryLayout.size(ofValue: $1)) } - if extraFieldLength > 0 { - // Size of extra fields, shouldn't include the leading 4 bytes - zip64ExtendedInformation = Entry.ZIP64ExtendedInformation( - dataSize: extraFieldLength, - uncompressedSize: extraUncompressedSize ?? 0, - compressedSize: extraCompressedSize ?? 0, - relativeOffsetOfLocalHeader: extraOffset ?? 0, - diskNumberStart: 0) - extraFieldLength += Entry.ZIP64ExtendedInformation.headerSize - } - let centralDirectory = CentralDirectoryStructure( - localFileHeader: localFileHeader, - fileAttributes: externalFileAttributes, - relativeOffset: relativeOffsetOfCD, - extraField: ( - extraFieldLength, - zip64ExtendedInformation?.data ?? Data())) - _ = try Data.write(chunk: centralDirectory.data, to: archiveFile) - return centralDirectory - } - - func writeEndOfCentralDirectory( - centralDirectoryStructure: CentralDirectoryStructure, - startOfCentralDirectory: UInt64, - startOfEndOfCentralDirectory: UInt64, - operation: ModifyOperation) - throws -> EndOfCentralDirectoryStructure - { - var record = endOfCentralDirectoryRecord - let sizeOfCD = sizeOfCentralDirectory - let numberOfTotalEntries = totalNumberOfEntriesInCentralDirectory - let countChange = operation.rawValue - var dataLength = centralDirectoryStructure.extraFieldLength - dataLength += centralDirectoryStructure.fileNameLength - dataLength += centralDirectoryStructure.fileCommentLength - let cdDataLengthChange = countChange * (Int(dataLength) + CentralDirectoryStructure.size) - let (updatedSizeOfCD, updatedNumberOfEntries): (UInt64, UInt64) = try { - switch operation { - case .add: - guard .max - sizeOfCD >= cdDataLengthChange else { - throw ArchiveError.invalidCentralDirectorySize - } - guard .max - numberOfTotalEntries >= countChange else { - throw ArchiveError.invalidCentralDirectoryEntryCount - } - return (sizeOfCD + UInt64(cdDataLengthChange), numberOfTotalEntries + UInt64(countChange)) - case .remove: - return (sizeOfCD - UInt64(-cdDataLengthChange), numberOfTotalEntries - UInt64(-countChange)) - } - }() - let sizeOfCDForEOCD = updatedSizeOfCD >= maxSizeOfCentralDirectory - ? UInt32.max - : UInt32(updatedSizeOfCD) - let numberOfTotalEntriesForEOCD = updatedNumberOfEntries >= maxTotalNumberOfEntries - ? UInt16.max - : UInt16(updatedNumberOfEntries) - let offsetOfCDForEOCD = startOfCentralDirectory >= maxOffsetOfCentralDirectory - ? UInt32.max - : UInt32(startOfCentralDirectory) - // ZIP64 End of Central Directory - var zip64EOCD: ZIP64EndOfCentralDirectory? - if numberOfTotalEntriesForEOCD == .max || offsetOfCDForEOCD == .max || sizeOfCDForEOCD == .max { - zip64EOCD = try writeZIP64EOCD( - totalNumberOfEntries: updatedNumberOfEntries, - sizeOfCentralDirectory: updatedSizeOfCD, - offsetOfCentralDirectory: startOfCentralDirectory, - offsetOfEndOfCentralDirectory: startOfEndOfCentralDirectory) - } - record = EndOfCentralDirectoryRecord( - record: record, - numberOfEntriesOnDisk: numberOfTotalEntriesForEOCD, - numberOfEntriesInCentralDirectory: numberOfTotalEntriesForEOCD, - updatedSizeOfCentralDirectory: sizeOfCDForEOCD, - startOfCentralDirectory: offsetOfCDForEOCD) - _ = try Data.write(chunk: record.data, to: archiveFile) - return (record, zip64EOCD) - } - - func writeUncompressed( - size: Int64, - bufferSize: Int, - progress: Progress? = nil, - provider: Provider) throws -> (sizeWritten: Int64, checksum: CRC32) - { - var position: Int64 = 0 - var sizeWritten: Int64 = 0 - var checksum = CRC32(0) - while position < size { - if progress?.isCancelled == true { throw ArchiveError.cancelledOperation } - let readSize = (size - position) >= bufferSize ? bufferSize : Int(size - position) - let entryChunk = try provider(position, readSize) - checksum = entryChunk.crc32(checksum: checksum) - sizeWritten += Int64(try Data.write(chunk: entryChunk, to: archiveFile)) - position += Int64(bufferSize) - progress?.completedUnitCount = sizeWritten - } - return (sizeWritten, checksum) - } - - func writeCompressed( - size: Int64, - bufferSize: Int, - progress: Progress? = nil, - provider: Provider) throws -> (sizeWritten: Int64, checksum: CRC32) - { - var sizeWritten: Int64 = 0 - let consumer: Consumer = { data in sizeWritten += Int64(try Data.write(chunk: data, to: self.archiveFile)) } - let checksum = try Data.compress( - size: size, - bufferSize: bufferSize, - provider: { position, size -> Data in - if progress?.isCancelled == true { throw ArchiveError.cancelledOperation } - let data = try provider(position, size) - progress?.completedUnitCount += Int64(data.count) - return data - }, - consumer: consumer) - return (sizeWritten, checksum) - } - - func writeSymbolicLink(size: Int, provider: Provider) throws -> (sizeWritten: Int, checksum: CRC32) { - // The reported size of a symlink is the number of characters in the path it points to. - let linkData = try provider(0, size) - let checksum = linkData.crc32(checksum: 0) - let sizeWritten = try Data.write(chunk: linkData, to: archiveFile) - return (sizeWritten, checksum) - } - - func writeZIP64EOCD( - totalNumberOfEntries: UInt64, - sizeOfCentralDirectory: UInt64, - offsetOfCentralDirectory: UInt64, - offsetOfEndOfCentralDirectory: UInt64) - throws -> ZIP64EndOfCentralDirectory - { - var zip64EOCD: ZIP64EndOfCentralDirectory = zip64EndOfCentralDirectory ?? { - // Shouldn't include the leading 12 bytes: (size - 12 = 44) - let record = ZIP64EndOfCentralDirectoryRecord( - sizeOfZIP64EndOfCentralDirectoryRecord: UInt64(44), - versionMadeBy: UInt16(789), - versionNeededToExtract: Version.v45.rawValue, - numberOfDisk: 0, - numberOfDiskStart: 0, - totalNumberOfEntriesOnDisk: 0, - totalNumberOfEntriesInCentralDirectory: 0, - sizeOfCentralDirectory: 0, - offsetToStartOfCentralDirectory: 0, - zip64ExtensibleDataSector: Data()) - let locator = ZIP64EndOfCentralDirectoryLocator( - numberOfDiskWithZIP64EOCDRecordStart: 0, - relativeOffsetOfZIP64EOCDRecord: 0, - totalNumberOfDisk: 1) - return ZIP64EndOfCentralDirectory(record: record, locator: locator) - }() - - let updatedRecord = ZIP64EndOfCentralDirectoryRecord( - record: zip64EOCD.record, - numberOfEntriesOnDisk: totalNumberOfEntries, - numberOfEntriesInCD: totalNumberOfEntries, - sizeOfCentralDirectory: sizeOfCentralDirectory, - offsetToStartOfCD: offsetOfCentralDirectory) - let updatedLocator = ZIP64EndOfCentralDirectoryLocator( - locator: zip64EOCD.locator, - offsetOfZIP64EOCDRecord: offsetOfEndOfCentralDirectory) - zip64EOCD = ZIP64EndOfCentralDirectory(record: updatedRecord, locator: updatedLocator) - _ = try Data.write(chunk: zip64EOCD.data, to: archiveFile) - return zip64EOCD - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+MemoryFile.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+MemoryFile.swift deleted file mode 100644 index cda58976bd8374f5e57520553457a3c2893e6903..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+MemoryFile.swift +++ /dev/null @@ -1,183 +0,0 @@ -// -// Archive+MemoryFile.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Archive { - var isMemoryArchive: Bool { url.scheme == memoryURLScheme } -} - -#if swift(>=5.0) - -extension Archive { - /// Returns a `Data` object containing a representation of the receiver. - var data: Data? { memoryFile?.data } -} - -class MemoryFile { - - // MARK: Lifecycle - - init(data: Data = Data()) { - self.data = data - } - - // MARK: Internal - - private(set) var data: Data - - func open(mode: String) -> FILEPointer? { - let cookie = Unmanaged.passRetained(self) - let writable = mode.count > 0 && (mode.first! != "r" || mode.last! == "+") - let append = mode.count > 0 && mode.first! == "a" - #if os(macOS) || canImport(UIKit) || os(Android) - let result = writable - ? funopen(cookie.toOpaque(), readStub, writeStub, seekStub, closeStub) - : funopen(cookie.toOpaque(), readStub, nil, seekStub, closeStub) - #else - let stubs = cookie_io_functions_t(read: readStub, write: writeStub, seek: seekStub, close: closeStub) - let result = fopencookie(cookie.toOpaque(), mode, stubs) - #endif - if append { - fseeko(result, 0, SEEK_END) - } - return result - } - - // MARK: Private - - private var offset = 0 - -} - -extension MemoryFile { - fileprivate func readData(buffer: UnsafeMutableRawBufferPointer) -> Int { - let size = min(buffer.count, data.count - offset) - let start = data.startIndex - data.copyBytes(to: buffer.bindMemory(to: UInt8.self), from: start + offset.. Int { - let start = data.startIndex - if offset < data.count, offset + buffer.count > data.count { - data.removeSubrange(start + offset.. data.count { - data.append(Data(count: offset - data.count)) - } - if offset == data.count { - data.append(buffer.bindMemory(to: UInt8.self)) - } else { - let start = data.startIndex // May have changed in earlier mutation - data.replaceSubrange(start + offset.. Int { - var result = -1 - if whence == SEEK_SET { - result = offset - } else if whence == SEEK_CUR { - result = self.offset + offset - } else if whence == SEEK_END { - result = data.count + offset - } - self.offset = result - return self.offset - } -} - -private func fileFromCookie(cookie: UnsafeRawPointer) -> MemoryFile { - Unmanaged.fromOpaque(cookie).takeUnretainedValue() -} - -private func closeStub(_ cookie: UnsafeMutableRawPointer?) -> Int32 { - if let cookie { - Unmanaged.fromOpaque(cookie).release() - } - return 0 -} - -#if os(macOS) || canImport(UIKit) || os(Android) -private func readStub( - _ cookie: UnsafeMutableRawPointer?, - _ bytePtr: UnsafeMutablePointer?, - _ count: Int32) - -> Int32 -{ - guard let cookie, let bytePtr else { return 0 } - return Int32(fileFromCookie(cookie: cookie).readData( - buffer: UnsafeMutableRawBufferPointer(start: bytePtr, count: Int(count)))) -} - -private func writeStub( - _ cookie: UnsafeMutableRawPointer?, - _ bytePtr: UnsafePointer?, - _ count: Int32) - -> Int32 -{ - guard let cookie, let bytePtr else { return 0 } - return Int32(fileFromCookie(cookie: cookie).writeData( - buffer: UnsafeRawBufferPointer(start: bytePtr, count: Int(count)))) -} - -private func seekStub( - _ cookie: UnsafeMutableRawPointer?, - _ offset: fpos_t, - _ whence: Int32) - -> fpos_t -{ - guard let cookie else { return 0 } - return fpos_t(fileFromCookie(cookie: cookie).seek(offset: Int(offset), whence: whence)) -} - -#else -private func readStub( - _ cookie: UnsafeMutableRawPointer?, - _ bytePtr: UnsafeMutablePointer?, - _ count: Int) - -> Int -{ - guard let cookie, let bytePtr else { return 0 } - return fileFromCookie(cookie: cookie).readData( - buffer: UnsafeMutableRawBufferPointer(start: bytePtr, count: count)) -} - -private func writeStub( - _ cookie: UnsafeMutableRawPointer?, - _ bytePtr: UnsafePointer?, - _ count: Int) - -> Int -{ - guard let cookie, let bytePtr else { return 0 } - return fileFromCookie(cookie: cookie).writeData( - buffer: UnsafeRawBufferPointer(start: bytePtr, count: count)) -} - -private func seekStub( - _ cookie: UnsafeMutableRawPointer?, - _ offset: UnsafeMutablePointer?, - _ whence: Int32) - -> Int32 -{ - guard let cookie, let offset else { return 0 } - let result = fileFromCookie(cookie: cookie).seek(offset: Int(offset.pointee), whence: whence) - if result >= 0 { - offset.pointee = result - return 0 - } else { - return -1 - } -} -#endif -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Progress.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Progress.swift deleted file mode 100644 index f8c3bd69cb1f5bb83b5f8fd95b2b7b61d3b3cea0..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Progress.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// Archive+Progress.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Archive { - /// The number of the work units that have to be performed when - /// removing `entry` from the receiver. - /// - /// - Parameter entry: The entry that will be removed. - /// - Returns: The number of the work units. - func totalUnitCountForRemoving(_ entry: Entry) -> Int64 { - Int64(offsetToStartOfCentralDirectory - entry.localSize) - } - - func makeProgressForRemoving(_ entry: Entry) -> Progress { - Progress(totalUnitCount: totalUnitCountForRemoving(entry)) - } - - /// The number of the work units that have to be performed when - /// reading `entry` from the receiver. - /// - /// - Parameter entry: The entry that will be read. - /// - Returns: The number of the work units. - func totalUnitCountForReading(_ entry: Entry) -> Int64 { - switch entry.type { - case .file, .symlink: - return Int64(entry.uncompressedSize) - case .directory: - return defaultDirectoryUnitCount - } - } - - func makeProgressForReading(_ entry: Entry) -> Progress { - Progress(totalUnitCount: totalUnitCountForReading(entry)) - } - - /// The number of the work units that have to be performed when - /// adding the file at `url` to the receiver. - /// - Parameter entry: The entry that will be removed. - /// - Returns: The number of the work units. - func totalUnitCountForAddingItem(at url: URL) -> Int64 { - var count = Int64(0) - do { - let type = try FileManager.typeForItem(at: url) - switch type { - case .file, .symlink: - count = Int64(try FileManager.fileSizeForItem(at: url)) - case .directory: - count = defaultDirectoryUnitCount - } - } catch { count = -1 } - return count - } - - func makeProgressForAddingItem(at url: URL) -> Progress { - Progress(totalUnitCount: totalUnitCountForAddingItem(at: url)) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Reading.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Reading.swift deleted file mode 100644 index cf5510dc7e36fa9058f3dfae17f4990cabe717bf..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Reading.swift +++ /dev/null @@ -1,144 +0,0 @@ -// -// Archive+Reading.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Archive { - /// Read a ZIP `Entry` from the receiver and write it to `url`. - /// - /// - Parameters: - /// - entry: The ZIP `Entry` to read. - /// - url: The destination file URL. - /// - bufferSize: The maximum size of the read buffer and the decompression buffer (if needed). - /// - skipCRC32: Optional flag to skip calculation of the CRC32 checksum to improve performance. - /// - progress: A progress object that can be used to track or cancel the extract operation. - /// - Returns: The checksum of the processed content or 0 if the `skipCRC32` flag was set to `true`. - /// - Throws: An error if the destination file cannot be written or the entry contains malformed content. - func extract( - _ entry: Entry, - to url: URL, - bufferSize: Int = defaultReadChunkSize, - skipCRC32: Bool = false, - progress: Progress? = nil) - throws -> CRC32 - { - guard bufferSize > 0 else { - throw ArchiveError.invalidBufferSize - } - let fileManager = FileManager() - var checksum = CRC32(0) - switch entry.type { - case .file: - guard !fileManager.itemExists(at: url) else { - throw CocoaError(.fileWriteFileExists, userInfo: [NSFilePathErrorKey: url.path]) - } - try fileManager.createParentDirectoryStructure(for: url) - let destinationRepresentation = fileManager.fileSystemRepresentation(withPath: url.path) - guard let destinationFile: FILEPointer = fopen(destinationRepresentation, "wb+") else { - throw CocoaError(.fileNoSuchFile) - } - defer { fclose(destinationFile) } - let consumer = { _ = try Data.write(chunk: $0, to: destinationFile) } - checksum = try extract( - entry, - bufferSize: bufferSize, - skipCRC32: skipCRC32, - progress: progress, - consumer: consumer) - case .directory: - let consumer = { (_: Data) in - try fileManager.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) - } - checksum = try extract( - entry, - bufferSize: bufferSize, - skipCRC32: skipCRC32, - progress: progress, - consumer: consumer) - case .symlink: - guard !fileManager.itemExists(at: url) else { - throw CocoaError(.fileWriteFileExists, userInfo: [NSFilePathErrorKey: url.path]) - } - let consumer = { (data: Data) in - guard let linkPath = String(data: data, encoding: .utf8) else { throw ArchiveError.invalidEntryPath } - try fileManager.createParentDirectoryStructure(for: url) - try fileManager.createSymbolicLink(atPath: url.path, withDestinationPath: linkPath) - } - checksum = try extract( - entry, - bufferSize: bufferSize, - skipCRC32: skipCRC32, - progress: progress, - consumer: consumer) - } - let attributes = FileManager.attributes(from: entry) - try fileManager.setAttributes(attributes, ofItemAtPath: url.path) - return checksum - } - - /// Read a ZIP `Entry` from the receiver and forward its contents to a `Consumer` closure. - /// - /// - Parameters: - /// - entry: The ZIP `Entry` to read. - /// - bufferSize: The maximum size of the read buffer and the decompression buffer (if needed). - /// - skipCRC32: Optional flag to skip calculation of the CRC32 checksum to improve performance. - /// - progress: A progress object that can be used to track or cancel the extract operation. - /// - consumer: A closure that consumes contents of `Entry` as `Data` chunks. - /// - Returns: The checksum of the processed content or 0 if the `skipCRC32` flag was set to `true`.. - /// - Throws: An error if the destination file cannot be written or the entry contains malformed content. - func extract( - _ entry: Entry, - bufferSize: Int = defaultReadChunkSize, - skipCRC32: Bool = false, - progress: Progress? = nil, - consumer: Consumer) - throws -> CRC32 - { - guard bufferSize > 0 else { - throw ArchiveError.invalidBufferSize - } - var checksum = CRC32(0) - let localFileHeader = entry.localFileHeader - guard entry.dataOffset <= .max else { throw ArchiveError.invalidLocalHeaderDataOffset } - fseeko(archiveFile, off_t(entry.dataOffset), SEEK_SET) - progress?.totalUnitCount = totalUnitCountForReading(entry) - switch entry.type { - case .file: - guard let compressionMethod = CompressionMethod(rawValue: localFileHeader.compressionMethod) else { - throw ArchiveError.invalidCompressionMethod - } - switch compressionMethod { - case .none: checksum = try readUncompressed( - entry: entry, - bufferSize: bufferSize, - skipCRC32: skipCRC32, - progress: progress, - with: consumer) - case .deflate: checksum = try readCompressed( - entry: entry, - bufferSize: bufferSize, - skipCRC32: skipCRC32, - progress: progress, - with: consumer) - } - case .directory: - try consumer(Data()) - progress?.completedUnitCount = totalUnitCountForReading(entry) - case .symlink: - let localFileHeader = entry.localFileHeader - let size = Int(localFileHeader.compressedSize) - let data = try Data.readChunk(of: size, from: archiveFile) - checksum = data.crc32(checksum: 0) - try consumer(data) - progress?.completedUnitCount = totalUnitCountForReading(entry) - } - return checksum - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+ReadingDeprecated.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+ReadingDeprecated.swift deleted file mode 100644 index 1e30365456b51b5f63edd18af9349641b10a6141..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+ReadingDeprecated.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// Archive+ReadingDeprecated.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Archive { - - @available( - *, - deprecated, - message: "Please use `Int` for `bufferSize`.") - func extract( - _ entry: Entry, - to url: URL, - bufferSize: UInt32, - skipCRC32: Bool = false, - progress: Progress? = nil) - throws -> CRC32 - { - try extract(entry, to: url, bufferSize: Int(bufferSize), skipCRC32: skipCRC32, progress: progress) - } - - @available( - *, - deprecated, - message: "Please use `Int` for `bufferSize`.") - func extract( - _ entry: Entry, - bufferSize: UInt32, - skipCRC32: Bool = false, - progress: Progress? = nil, - consumer: Consumer) - throws -> CRC32 - { - try extract( - entry, - bufferSize: Int(bufferSize), - skipCRC32: skipCRC32, - progress: progress, - consumer: consumer) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Writing.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Writing.swift deleted file mode 100644 index 800643947068bf637fc53abcf47e8357c5c9af43..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+Writing.swift +++ /dev/null @@ -1,385 +0,0 @@ -// -// Archive+Writing.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Archive { - enum ModifyOperation: Int { - case remove = -1 - case add = 1 - } - - typealias EndOfCentralDirectoryStructure = (EndOfCentralDirectoryRecord, ZIP64EndOfCentralDirectory?) - - /// Write files, directories or symlinks to the receiver. - /// - /// - Parameters: - /// - path: The path that is used to identify an `Entry` within the `Archive` file. - /// - baseURL: The base URL of the resource to add. - /// The `baseURL` combined with `path` must form a fully qualified file URL. - /// - compressionMethod: Indicates the `CompressionMethod` that should be applied to `Entry`. - /// By default, no compression will be applied. - /// - bufferSize: The maximum size of the write buffer and the compression buffer (if needed). - /// - progress: A progress object that can be used to track or cancel the add operation. - /// - Throws: An error if the source file cannot be read or the receiver is not writable. - func addEntry( - with path: String, - relativeTo baseURL: URL, - compressionMethod: CompressionMethod = .none, - bufferSize: Int = defaultWriteChunkSize, - progress: Progress? = nil) - throws - { - let fileURL = baseURL.appendingPathComponent(path) - - try addEntry( - with: path, - fileURL: fileURL, - compressionMethod: compressionMethod, - bufferSize: bufferSize, - progress: progress) - } - - /// Write files, directories or symlinks to the receiver. - /// - /// - Parameters: - /// - path: The path that is used to identify an `Entry` within the `Archive` file. - /// - fileURL: An absolute file URL referring to the resource to add. - /// - compressionMethod: Indicates the `CompressionMethod` that should be applied to `Entry`. - /// By default, no compression will be applied. - /// - bufferSize: The maximum size of the write buffer and the compression buffer (if needed). - /// - progress: A progress object that can be used to track or cancel the add operation. - /// - Throws: An error if the source file cannot be read or the receiver is not writable. - func addEntry( - with path: String, - fileURL: URL, - compressionMethod: CompressionMethod = .none, - bufferSize: Int = defaultWriteChunkSize, - progress: Progress? = nil) - throws - { - let fileManager = FileManager() - guard fileManager.itemExists(at: fileURL) else { - throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: fileURL.path]) - } - let type = try FileManager.typeForItem(at: fileURL) - // symlinks do not need to be readable - guard type == .symlink || fileManager.isReadableFile(atPath: fileURL.path) else { - throw CocoaError(.fileReadNoPermission, userInfo: [NSFilePathErrorKey: url.path]) - } - let modDate = try FileManager.fileModificationDateTimeForItem(at: fileURL) - let uncompressedSize = type == .directory ? 0 : try FileManager.fileSizeForItem(at: fileURL) - let permissions = try FileManager.permissionsForItem(at: fileURL) - var provider: Provider - switch type { - case .file: - let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: fileURL.path) - guard let entryFile: FILEPointer = fopen(entryFileSystemRepresentation, "rb") else { - throw CocoaError(.fileNoSuchFile) - } - defer { fclose(entryFile) } - provider = { _, _ in try Data.readChunk(of: bufferSize, from: entryFile) } - try addEntry( - with: path, - type: type, - uncompressedSize: uncompressedSize, - modificationDate: modDate, - permissions: permissions, - compressionMethod: compressionMethod, - bufferSize: bufferSize, - progress: progress, - provider: provider) - case .directory: - provider = { _, _ in Data() } - try addEntry( - with: path.hasSuffix("/") ? path : path + "/", - type: type, - uncompressedSize: uncompressedSize, - modificationDate: modDate, - permissions: permissions, - compressionMethod: compressionMethod, - bufferSize: bufferSize, - progress: progress, - provider: provider) - case .symlink: - provider = { _, _ -> Data in - let linkDestination = try fileManager.destinationOfSymbolicLink(atPath: fileURL.path) - let linkFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: linkDestination) - let linkLength = Int(strlen(linkFileSystemRepresentation)) - let linkBuffer = UnsafeBufferPointer(start: linkFileSystemRepresentation, count: linkLength) - return Data(buffer: linkBuffer) - } - try addEntry( - with: path, - type: type, - uncompressedSize: uncompressedSize, - modificationDate: modDate, - permissions: permissions, - compressionMethod: compressionMethod, - bufferSize: bufferSize, - progress: progress, - provider: provider) - } - } - - /// Write files, directories or symlinks to the receiver. - /// - /// - Parameters: - /// - path: The path that is used to identify an `Entry` within the `Archive` file. - /// - type: Indicates the `Entry.EntryType` of the added content. - /// - uncompressedSize: The uncompressed size of the data that is going to be added with `provider`. - /// - modificationDate: A `Date` describing the file modification date of the `Entry`. - /// Default is the current `Date`. - /// - permissions: POSIX file permissions for the `Entry`. - /// Default is `0`o`644` for files and symlinks and `0`o`755` for directories. - /// - compressionMethod: Indicates the `CompressionMethod` that should be applied to `Entry`. - /// By default, no compression will be applied. - /// - bufferSize: The maximum size of the write buffer and the compression buffer (if needed). - /// - progress: A progress object that can be used to track or cancel the add operation. - /// - provider: A closure that accepts a position and a chunk size. Returns a `Data` chunk. - /// - Throws: An error if the source data is invalid or the receiver is not writable. - func addEntry( - with path: String, - type: Entry.EntryType, - uncompressedSize: Int64, - modificationDate: Date = Date(), - permissions: UInt16? = nil, - compressionMethod: CompressionMethod = .none, - bufferSize: Int = defaultWriteChunkSize, - progress: Progress? = nil, - provider: Provider) - throws - { - guard accessMode != .read else { throw ArchiveError.unwritableArchive } - // Directories and symlinks cannot be compressed - let compressionMethod = type == .file ? compressionMethod : .none - progress?.totalUnitCount = type == .directory ? defaultDirectoryUnitCount : uncompressedSize - let (eocdRecord, zip64EOCD) = (endOfCentralDirectoryRecord, zip64EndOfCentralDirectory) - guard offsetToStartOfCentralDirectory <= .max else { throw ArchiveError.invalidCentralDirectoryOffset } - var startOfCD = Int64(offsetToStartOfCentralDirectory) - fseeko(archiveFile, off_t(startOfCD), SEEK_SET) - let existingSize = sizeOfCentralDirectory - let existingData = try Data.readChunk(of: Int(existingSize), from: archiveFile) - fseeko(archiveFile, off_t(startOfCD), SEEK_SET) - let fileHeaderStart = Int64(ftello(archiveFile)) - let modDateTime = modificationDate.fileModificationDateTime - defer { fflush(self.archiveFile) } - do { - // Local File Header - var localFileHeader = try writeLocalFileHeader( - path: path, - compressionMethod: compressionMethod, - size: (UInt64(uncompressedSize), 0), - checksum: 0, - modificationDateTime: modDateTime) - // File Data - let (written, checksum) = try writeEntry( - uncompressedSize: uncompressedSize, - type: type, - compressionMethod: compressionMethod, - bufferSize: bufferSize, - progress: progress, - provider: provider) - startOfCD = Int64(ftello(archiveFile)) - // Write the local file header a second time. Now with compressedSize (if applicable) and a valid checksum. - fseeko(archiveFile, off_t(fileHeaderStart), SEEK_SET) - localFileHeader = try writeLocalFileHeader( - path: path, - compressionMethod: compressionMethod, - size: (UInt64(uncompressedSize), UInt64(written)), - checksum: checksum, - modificationDateTime: modDateTime) - // Central Directory - fseeko(archiveFile, off_t(startOfCD), SEEK_SET) - _ = try Data.writeLargeChunk(existingData, size: existingSize, bufferSize: bufferSize, to: archiveFile) - let permissions = permissions ?? (type == .directory ? defaultDirectoryPermissions : defaultFilePermissions) - let externalAttributes = FileManager.externalFileAttributesForEntry(of: type, permissions: permissions) - let centralDir = try writeCentralDirectoryStructure( - localFileHeader: localFileHeader, - relativeOffset: UInt64(fileHeaderStart), - externalFileAttributes: externalAttributes) - // End of Central Directory Record (including ZIP64 End of Central Directory Record/Locator) - let startOfEOCD = UInt64(ftello(archiveFile)) - let eocd = try writeEndOfCentralDirectory( - centralDirectoryStructure: centralDir, - startOfCentralDirectory: UInt64(startOfCD), - startOfEndOfCentralDirectory: startOfEOCD, - operation: .add) - (endOfCentralDirectoryRecord, zip64EndOfCentralDirectory) = eocd - } catch ArchiveError.cancelledOperation { - try rollback(UInt64(fileHeaderStart), (existingData, existingSize), bufferSize, eocdRecord, zip64EOCD) - throw ArchiveError.cancelledOperation - } - } - - /// Remove a ZIP `Entry` from the receiver. - /// - /// - Parameters: - /// - entry: The `Entry` to remove. - /// - bufferSize: The maximum size for the read and write buffers used during removal. - /// - progress: A progress object that can be used to track or cancel the remove operation. - /// - Throws: An error if the `Entry` is malformed or the receiver is not writable. - func remove(_ entry: Entry, bufferSize: Int = defaultReadChunkSize, progress: Progress? = nil) throws { - guard accessMode != .read else { throw ArchiveError.unwritableArchive } - let (tempArchive, tempDir) = try makeTempArchive() - defer { tempDir.map { try? FileManager().removeItem(at: $0) } } - progress?.totalUnitCount = totalUnitCountForRemoving(entry) - var centralDirectoryData = Data() - var offset: UInt64 = 0 - for currentEntry in self { - let cds = currentEntry.centralDirectoryStructure - if currentEntry != entry { - let entryStart = cds.effectiveRelativeOffsetOfLocalHeader - fseeko(archiveFile, off_t(entryStart), SEEK_SET) - let provider: Provider = { _, chunkSize -> Data in - try Data.readChunk(of: chunkSize, from: self.archiveFile) - } - let consumer: Consumer = { - if progress?.isCancelled == true { throw ArchiveError.cancelledOperation } - _ = try Data.write(chunk: $0, to: tempArchive.archiveFile) - progress?.completedUnitCount += Int64($0.count) - } - guard currentEntry.localSize <= .max else { throw ArchiveError.invalidLocalHeaderSize } - _ = try Data.consumePart( - of: Int64(currentEntry.localSize), - chunkSize: bufferSize, - provider: provider, - consumer: consumer) - let updatedCentralDirectory = updateOffsetInCentralDirectory( - centralDirectoryStructure: cds, - updatedOffset: entryStart - offset) - centralDirectoryData.append(updatedCentralDirectory.data) - } else { offset = currentEntry.localSize } - } - let startOfCentralDirectory = UInt64(ftello(tempArchive.archiveFile)) - _ = try Data.write(chunk: centralDirectoryData, to: tempArchive.archiveFile) - let startOfEndOfCentralDirectory = UInt64(ftello(tempArchive.archiveFile)) - tempArchive.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord - tempArchive.zip64EndOfCentralDirectory = zip64EndOfCentralDirectory - let ecodStructure = try - tempArchive.writeEndOfCentralDirectory( - centralDirectoryStructure: entry.centralDirectoryStructure, - startOfCentralDirectory: startOfCentralDirectory, - startOfEndOfCentralDirectory: startOfEndOfCentralDirectory, - operation: .remove) - (tempArchive.endOfCentralDirectoryRecord, tempArchive.zip64EndOfCentralDirectory) = ecodStructure - (endOfCentralDirectoryRecord, zip64EndOfCentralDirectory) = ecodStructure - fflush(tempArchive.archiveFile) - try replaceCurrentArchive(with: tempArchive) - } - - func replaceCurrentArchive(with archive: Archive) throws { - fclose(archiveFile) - if isMemoryArchive { - #if swift(>=5.0) - guard - let data = archive.data, - let config = Archive.makeBackingConfiguration(for: data, mode: .update) - else { - throw ArchiveError.unwritableArchive - } - archiveFile = config.file - memoryFile = config.memoryFile - endOfCentralDirectoryRecord = config.endOfCentralDirectoryRecord - zip64EndOfCentralDirectory = config.zip64EndOfCentralDirectory - #endif - } else { - let fileManager = FileManager() - #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) - do { - _ = try fileManager.replaceItemAt(url, withItemAt: archive.url) - } catch { - _ = try fileManager.removeItem(at: url) - _ = try fileManager.moveItem(at: archive.url, to: url) - } - #else - _ = try fileManager.removeItem(at: url) - _ = try fileManager.moveItem(at: archive.url, to: url) - #endif - let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path) - guard let file = fopen(fileSystemRepresentation, "rb+") else { throw ArchiveError.unreadableArchive } - archiveFile = file - } - } -} - -// MARK: - Private - -extension Archive { - - private func updateOffsetInCentralDirectory( - centralDirectoryStructure: CentralDirectoryStructure, - updatedOffset: UInt64) - -> CentralDirectoryStructure - { - let zip64ExtendedInformation = Entry.ZIP64ExtendedInformation( - zip64ExtendedInformation: centralDirectoryStructure.zip64ExtendedInformation, offset: updatedOffset) - let offsetInCD = updatedOffset < maxOffsetOfLocalFileHeader ? UInt32(updatedOffset) : UInt32.max - return CentralDirectoryStructure( - centralDirectoryStructure: centralDirectoryStructure, - zip64ExtendedInformation: zip64ExtendedInformation, - relativeOffset: offsetInCD) - } - - private func rollback( - _ localFileHeaderStart: UInt64, - _ existingCentralDirectory: (data: Data, size: UInt64), - _ bufferSize: Int, - _ endOfCentralDirRecord: EndOfCentralDirectoryRecord, - _ zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory?) - throws - { - fflush(archiveFile) - ftruncate(fileno(archiveFile), off_t(localFileHeaderStart)) - fseeko(archiveFile, off_t(localFileHeaderStart), SEEK_SET) - _ = try Data.writeLargeChunk( - existingCentralDirectory.data, - size: existingCentralDirectory.size, - bufferSize: bufferSize, - to: archiveFile) - _ = try Data.write(chunk: existingCentralDirectory.data, to: archiveFile) - if let zip64EOCD = zip64EndOfCentralDirectory { - _ = try Data.write(chunk: zip64EOCD.data, to: archiveFile) - } - _ = try Data.write(chunk: endOfCentralDirRecord.data, to: archiveFile) - } - - private func makeTempArchive() throws -> (Archive, URL?) { - var archive: Archive - var url: URL? - if isMemoryArchive { - #if swift(>=5.0) - guard - let tempArchive = Archive( - data: Data(), - accessMode: .create, - preferredEncoding: preferredEncoding) - else { - throw ArchiveError.unwritableArchive - } - archive = tempArchive - #else - fatalError("Memory archives are unsupported.") - #endif - } else { - let manager = FileManager() - let tempDir = URL.temporaryReplacementDirectoryURL(for: self) - let uniqueString = ProcessInfo.processInfo.globallyUniqueString - let tempArchiveURL = tempDir.appendingPathComponent(uniqueString) - try manager.createParentDirectoryStructure(for: tempArchiveURL) - guard let tempArchive = Archive(url: tempArchiveURL, accessMode: .create) else { - throw ArchiveError.unwritableArchive - } - archive = tempArchive - url = tempDir - } - return (archive, url) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+WritingDeprecated.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+WritingDeprecated.swift deleted file mode 100644 index 311c6a81b505a04d771c12c931cce40d114bd647..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+WritingDeprecated.swift +++ /dev/null @@ -1,91 +0,0 @@ -// -// Archive+WritingDeprecated.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Archive { - - @available( - *, - deprecated, - message: "Please use `Int` for `bufferSize`.") - func addEntry( - with path: String, - relativeTo baseURL: URL, - compressionMethod: CompressionMethod = .none, - bufferSize: UInt32, - progress: Progress? = nil) - throws - { - try addEntry( - with: path, - relativeTo: baseURL, - compressionMethod: compressionMethod, - bufferSize: Int(bufferSize), - progress: progress) - } - - @available( - *, - deprecated, - message: "Please use `Int` for `bufferSize`.") - func addEntry( - with path: String, - fileURL: URL, - compressionMethod: CompressionMethod = .none, - bufferSize: UInt32, - progress: Progress? = nil) - throws - { - try addEntry( - with: path, - fileURL: fileURL, - compressionMethod: compressionMethod, - bufferSize: Int(bufferSize), - progress: progress) - } - - @available( - *, - deprecated, - message: "Please use `Int64` for `uncompressedSize` and provider `position`. `Int` for `bufferSize`.") - func addEntry( - with path: String, - type: Entry.EntryType, - uncompressedSize: UInt32, - modificationDate: Date = Date(), - permissions: UInt16? = nil, - compressionMethod: CompressionMethod = .none, - bufferSize: Int = defaultWriteChunkSize, - progress: Progress? = nil, - provider: (_ position: Int, _ size: Int) throws -> Data) - throws - { - let newProvider: Provider = { try provider(Int($0), $1) } - try addEntry( - with: path, - type: type, - uncompressedSize: Int64(uncompressedSize), - modificationDate: modificationDate, - permissions: permissions, - compressionMethod: compressionMethod, - bufferSize: bufferSize, - progress: progress, - provider: newProvider) - } - - @available( - *, - deprecated, - message: "Please use `Int` for `bufferSize`.") - func remove(_ entry: Entry, bufferSize: UInt32, progress: Progress? = nil) throws { - try remove(entry, bufferSize: Int(bufferSize), progress: progress) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+ZIP64.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+ZIP64.swift deleted file mode 100644 index 2b301f7d131c742d0332a959a6514b4ce852bbc7..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive+ZIP64.swift +++ /dev/null @@ -1,170 +0,0 @@ -// -// Archive+ZIP64.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -let zip64EOCDRecordStructSignature = 0x06064b50 -let zip64EOCDLocatorStructSignature = 0x07064b50 - -// MARK: - ExtraFieldHeaderID - -enum ExtraFieldHeaderID: UInt16 { - case zip64ExtendedInformation = 0x0001 -} - -extension Archive { - struct ZIP64EndOfCentralDirectory { - let record: ZIP64EndOfCentralDirectoryRecord - let locator: ZIP64EndOfCentralDirectoryLocator - } - - struct ZIP64EndOfCentralDirectoryRecord: DataSerializable { - let zip64EOCDRecordSignature = UInt32(zip64EOCDRecordStructSignature) - let sizeOfZIP64EndOfCentralDirectoryRecord: UInt64 - let versionMadeBy: UInt16 - let versionNeededToExtract: UInt16 - let numberOfDisk: UInt32 - let numberOfDiskStart: UInt32 - let totalNumberOfEntriesOnDisk: UInt64 - let totalNumberOfEntriesInCentralDirectory: UInt64 - let sizeOfCentralDirectory: UInt64 - let offsetToStartOfCentralDirectory: UInt64 - let zip64ExtensibleDataSector: Data - static let size = 56 - } - - struct ZIP64EndOfCentralDirectoryLocator: DataSerializable { - let zip64EOCDLocatorSignature = UInt32(zip64EOCDLocatorStructSignature) - let numberOfDiskWithZIP64EOCDRecordStart: UInt32 - let relativeOffsetOfZIP64EOCDRecord: UInt64 - let totalNumberOfDisk: UInt32 - static let size = 20 - } -} - -extension Archive.ZIP64EndOfCentralDirectoryRecord { - - // MARK: Lifecycle - - init?(data: Data, additionalDataProvider _: (Int) throws -> Data) { - guard data.count == Archive.ZIP64EndOfCentralDirectoryRecord.size else { return nil } - guard data.scanValue(start: 0) == zip64EOCDRecordSignature else { return nil } - sizeOfZIP64EndOfCentralDirectoryRecord = data.scanValue(start: 4) - versionMadeBy = data.scanValue(start: 12) - versionNeededToExtract = data.scanValue(start: 14) - // Version Needed to Extract: 4.5 - File uses ZIP64 format extensions - guard versionNeededToExtract >= Archive.Version.v45.rawValue else { return nil } - numberOfDisk = data.scanValue(start: 16) - numberOfDiskStart = data.scanValue(start: 20) - totalNumberOfEntriesOnDisk = data.scanValue(start: 24) - totalNumberOfEntriesInCentralDirectory = data.scanValue(start: 32) - sizeOfCentralDirectory = data.scanValue(start: 40) - offsetToStartOfCentralDirectory = data.scanValue(start: 48) - zip64ExtensibleDataSector = Data() - } - - init( - record: Archive.ZIP64EndOfCentralDirectoryRecord, - numberOfEntriesOnDisk: UInt64, - numberOfEntriesInCD: UInt64, - sizeOfCentralDirectory: UInt64, - offsetToStartOfCD: UInt64) - { - sizeOfZIP64EndOfCentralDirectoryRecord = record.sizeOfZIP64EndOfCentralDirectoryRecord - versionMadeBy = record.versionMadeBy - versionNeededToExtract = record.versionNeededToExtract - numberOfDisk = record.numberOfDisk - numberOfDiskStart = record.numberOfDiskStart - totalNumberOfEntriesOnDisk = numberOfEntriesOnDisk - totalNumberOfEntriesInCentralDirectory = numberOfEntriesInCD - self.sizeOfCentralDirectory = sizeOfCentralDirectory - offsetToStartOfCentralDirectory = offsetToStartOfCD - zip64ExtensibleDataSector = record.zip64ExtensibleDataSector - } - - // MARK: Internal - - var data: Data { - var zip64EOCDRecordSignature = zip64EOCDRecordSignature - var sizeOfZIP64EOCDRecord = sizeOfZIP64EndOfCentralDirectoryRecord - var versionMadeBy = versionMadeBy - var versionNeededToExtract = versionNeededToExtract - var numberOfDisk = numberOfDisk - var numberOfDiskStart = numberOfDiskStart - var totalNumberOfEntriesOnDisk = totalNumberOfEntriesOnDisk - var totalNumberOfEntriesInCD = totalNumberOfEntriesInCentralDirectory - var sizeOfCD = sizeOfCentralDirectory - var offsetToStartOfCD = offsetToStartOfCentralDirectory - var data = Data() - withUnsafePointer(to: &zip64EOCDRecordSignature) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &sizeOfZIP64EOCDRecord) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &versionMadeBy) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &versionNeededToExtract) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &numberOfDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &numberOfDiskStart) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &totalNumberOfEntriesOnDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &totalNumberOfEntriesInCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &sizeOfCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &offsetToStartOfCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - data.append(zip64ExtensibleDataSector) - return data - } - -} - -extension Archive.ZIP64EndOfCentralDirectoryLocator { - - // MARK: Lifecycle - - init?(data: Data, additionalDataProvider _: (Int) throws -> Data) { - guard data.count == Archive.ZIP64EndOfCentralDirectoryLocator.size else { return nil } - guard data.scanValue(start: 0) == zip64EOCDLocatorSignature else { return nil } - numberOfDiskWithZIP64EOCDRecordStart = data.scanValue(start: 4) - relativeOffsetOfZIP64EOCDRecord = data.scanValue(start: 8) - totalNumberOfDisk = data.scanValue(start: 16) - } - - init(locator: Archive.ZIP64EndOfCentralDirectoryLocator, offsetOfZIP64EOCDRecord: UInt64) { - numberOfDiskWithZIP64EOCDRecordStart = locator.numberOfDiskWithZIP64EOCDRecordStart - relativeOffsetOfZIP64EOCDRecord = offsetOfZIP64EOCDRecord - totalNumberOfDisk = locator.totalNumberOfDisk - } - - // MARK: Internal - - var data: Data { - var zip64EOCDLocatorSignature = zip64EOCDLocatorSignature - var numberOfDiskWithZIP64EOCD = numberOfDiskWithZIP64EOCDRecordStart - var offsetOfZIP64EOCDRecord = relativeOffsetOfZIP64EOCDRecord - var totalNumberOfDisk = totalNumberOfDisk - var data = Data() - withUnsafePointer(to: &zip64EOCDLocatorSignature) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &numberOfDiskWithZIP64EOCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &offsetOfZIP64EOCDRecord) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &totalNumberOfDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - return data - } - -} - -extension Archive.ZIP64EndOfCentralDirectory { - var data: Data { record.data + locator.data } -} - -/// Properties that represent the maximum value of each field -var maxUInt32 = UInt32.max -var maxUInt16 = UInt16.max - -var maxCompressedSize: UInt32 { maxUInt32 } -var maxUncompressedSize: UInt32 { maxUInt32 } -var maxOffsetOfLocalFileHeader: UInt32 { maxUInt32 } -var maxOffsetOfCentralDirectory: UInt32 { maxUInt32 } -var maxSizeOfCentralDirectory: UInt32 { maxUInt32 } -var maxTotalNumberOfEntries: UInt16 { maxUInt16 } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive.swift deleted file mode 100644 index bb46a7c9b3bbbc871bae09520d7ef27f6e5bcaf6..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Archive.swift +++ /dev/null @@ -1,398 +0,0 @@ -// -// Archive.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -/// The default chunk size when reading entry data from an archive. -let defaultReadChunkSize = Int(16 * 1024) -/// The default chunk size when writing entry data to an archive. -let defaultWriteChunkSize = defaultReadChunkSize -/// The default permissions for newly added entries. -let defaultFilePermissions = UInt16(0o644) -/// The default permissions for newly added directories. -let defaultDirectoryPermissions = UInt16(0o755) -let defaultPOSIXBufferSize = defaultReadChunkSize -let defaultDirectoryUnitCount = Int64(1) -let minEndOfCentralDirectoryOffset = Int64(22) -let endOfCentralDirectoryStructSignature = 0x06054b50 -let localFileHeaderStructSignature = 0x04034b50 -let dataDescriptorStructSignature = 0x08074b50 -let centralDirectoryStructSignature = 0x02014b50 -let memoryURLScheme = "memory" - -// MARK: - Archive - -/// A sequence of uncompressed or compressed ZIP entries. -/// -/// You use an `Archive` to create, read or update ZIP files. -/// To read an existing ZIP file, you have to pass in an existing file `URL` and `AccessMode.read`: -/// -/// var archiveURL = URL(fileURLWithPath: "/path/file.zip") -/// var archive = Archive(url: archiveURL, accessMode: .read) -/// -/// An `Archive` is a sequence of entries. You can -/// iterate over an archive using a `for`-`in` loop to get access to individual `Entry` objects: -/// -/// for entry in archive { -/// print(entry.path) -/// } -/// -/// Each `Entry` in an `Archive` is represented by its `path`. You can -/// use `path` to retrieve the corresponding `Entry` from an `Archive` via subscripting: -/// -/// let entry = archive['/path/file.txt'] -/// -/// To create a new `Archive`, pass in a non-existing file URL and `AccessMode.create`. To modify an -/// existing `Archive` use `AccessMode.update`: -/// -/// var archiveURL = URL(fileURLWithPath: "/path/file.zip") -/// var archive = Archive(url: archiveURL, accessMode: .update) -/// try archive?.addEntry("test.txt", relativeTo: baseURL, compressionMethod: .deflate) -final class Archive: Sequence { - - // MARK: Lifecycle - - /// Initializes a new ZIP `Archive`. - /// - /// You can use this initalizer to create new archive files or to read and update existing ones. - /// The `mode` parameter indicates the intended usage of the archive: `.read`, `.create` or `.update`. - /// - Parameters: - /// - url: File URL to the receivers backing file. - /// - mode: Access mode of the receiver. - /// - preferredEncoding: Encoding for entry paths. Overrides the encoding specified in the archive. - /// This encoding is only used when _decoding_ paths from the receiver. - /// Paths of entries added with `addEntry` are always UTF-8 encoded. - /// - Returns: An archive initialized with a backing file at the passed in file URL and the given access mode - /// or `nil` if the following criteria are not met: - /// - Note: - /// - The file URL _must_ point to an existing file for `AccessMode.read`. - /// - The file URL _must_ point to a non-existing file for `AccessMode.create`. - /// - The file URL _must_ point to an existing file for `AccessMode.update`. - init?(url: URL, accessMode mode: AccessMode, preferredEncoding: String.Encoding? = nil) { - self.url = url - accessMode = mode - self.preferredEncoding = preferredEncoding - guard let config = Archive.makeBackingConfiguration(for: url, mode: mode) else { - return nil - } - archiveFile = config.file - endOfCentralDirectoryRecord = config.endOfCentralDirectoryRecord - zip64EndOfCentralDirectory = config.zip64EndOfCentralDirectory - setvbuf(archiveFile, nil, _IOFBF, Int(defaultPOSIXBufferSize)) - } - - deinit { - fclose(self.archiveFile) - } - - // MARK: Internal - - typealias LocalFileHeader = Entry.LocalFileHeader - typealias DataDescriptor = Entry.DefaultDataDescriptor - typealias ZIP64DataDescriptor = Entry.ZIP64DataDescriptor - typealias CentralDirectoryStructure = Entry.CentralDirectoryStructure - - /// An error that occurs during reading, creating or updating a ZIP file. - enum ArchiveError: Error { - /// Thrown when an archive file is either damaged or inaccessible. - case unreadableArchive - /// Thrown when an archive is either opened with AccessMode.read or the destination file is unwritable. - case unwritableArchive - /// Thrown when the path of an `Entry` cannot be stored in an archive. - case invalidEntryPath - /// Thrown when an `Entry` can't be stored in the archive with the proposed compression method. - case invalidCompressionMethod - /// Thrown when the stored checksum of an `Entry` doesn't match the checksum during reading. - case invalidCRC32 - /// Thrown when an extract, add or remove operation was canceled. - case cancelledOperation - /// Thrown when an extract operation was called with zero or negative `bufferSize` parameter. - case invalidBufferSize - /// Thrown when uncompressedSize/compressedSize exceeds `Int64.max` (Imposed by file API). - case invalidEntrySize - /// Thrown when the offset of local header data exceeds `Int64.max` (Imposed by file API). - case invalidLocalHeaderDataOffset - /// Thrown when the size of local header exceeds `Int64.max` (Imposed by file API). - case invalidLocalHeaderSize - /// Thrown when the offset of central directory exceeds `Int64.max` (Imposed by file API). - case invalidCentralDirectoryOffset - /// Thrown when the size of central directory exceeds `UInt64.max` (Imposed by ZIP specification). - case invalidCentralDirectorySize - /// Thrown when number of entries in central directory exceeds `UInt64.max` (Imposed by ZIP specification). - case invalidCentralDirectoryEntryCount - /// Thrown when an archive does not contain the required End of Central Directory Record. - case missingEndOfCentralDirectoryRecord - } - - /// The access mode for an `Archive`. - enum AccessMode: UInt { - /// Indicates that a newly instantiated `Archive` should create its backing file. - case create - /// Indicates that a newly instantiated `Archive` should read from an existing backing file. - case read - /// Indicates that a newly instantiated `Archive` should update an existing backing file. - case update - } - - /// The version of an `Archive` - enum Version: UInt16 { - /// The minimum version for deflate compressed archives - case v20 = 20 - /// The minimum version for archives making use of ZIP64 extensions - case v45 = 45 - } - - struct EndOfCentralDirectoryRecord: DataSerializable { - let endOfCentralDirectorySignature = UInt32(endOfCentralDirectoryStructSignature) - let numberOfDisk: UInt16 - let numberOfDiskStart: UInt16 - let totalNumberOfEntriesOnDisk: UInt16 - let totalNumberOfEntriesInCentralDirectory: UInt16 - let sizeOfCentralDirectory: UInt32 - let offsetToStartOfCentralDirectory: UInt32 - let zipFileCommentLength: UInt16 - let zipFileCommentData: Data - static let size = 22 - } - - /// URL of an Archive's backing file. - let url: URL - /// Access mode for an archive file. - let accessMode: AccessMode - var archiveFile: FILEPointer - var endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord - var zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory? - var preferredEncoding: String.Encoding? - - var totalNumberOfEntriesInCentralDirectory: UInt64 { - zip64EndOfCentralDirectory?.record.totalNumberOfEntriesInCentralDirectory - ?? UInt64(endOfCentralDirectoryRecord.totalNumberOfEntriesInCentralDirectory) - } - - var sizeOfCentralDirectory: UInt64 { - zip64EndOfCentralDirectory?.record.sizeOfCentralDirectory - ?? UInt64(endOfCentralDirectoryRecord.sizeOfCentralDirectory) - } - - var offsetToStartOfCentralDirectory: UInt64 { - zip64EndOfCentralDirectory?.record.offsetToStartOfCentralDirectory - ?? UInt64(endOfCentralDirectoryRecord.offsetToStartOfCentralDirectory) - } - - #if swift(>=5.0) - var memoryFile: MemoryFile? - - /// Initializes a new in-memory ZIP `Archive`. - /// - /// You can use this initalizer to create new in-memory archive files or to read and update existing ones. - /// - /// - Parameters: - /// - data: `Data` object used as backing for in-memory archives. - /// - mode: Access mode of the receiver. - /// - preferredEncoding: Encoding for entry paths. Overrides the encoding specified in the archive. - /// This encoding is only used when _decoding_ paths from the receiver. - /// Paths of entries added with `addEntry` are always UTF-8 encoded. - /// - Returns: An in-memory archive initialized with passed in backing data. - /// - Note: - /// - The backing `data` _must_ contain a valid ZIP archive for `AccessMode.read` and `AccessMode.update`. - /// - The backing `data` _must_ be empty (or omitted) for `AccessMode.create`. - init?(data: Data = Data(), accessMode mode: AccessMode, preferredEncoding: String.Encoding? = nil) { - guard - let url = URL(string: "\(memoryURLScheme)://"), - let config = Archive.makeBackingConfiguration(for: data, mode: mode) - else { - return nil - } - - self.url = url - accessMode = mode - self.preferredEncoding = preferredEncoding - archiveFile = config.file - memoryFile = config.memoryFile - endOfCentralDirectoryRecord = config.endOfCentralDirectoryRecord - zip64EndOfCentralDirectory = config.zip64EndOfCentralDirectory - } - #endif - - // MARK: - Helpers - - static func scanForEndOfCentralDirectoryRecord(in file: FILEPointer) - -> EndOfCentralDirectoryStructure? - { - var eocdOffset: UInt64 = 0 - var index = minEndOfCentralDirectoryOffset - fseeko(file, 0, SEEK_END) - let archiveLength = Int64(ftello(file)) - while eocdOffset == 0, index <= archiveLength { - fseeko(file, off_t(archiveLength - index), SEEK_SET) - var potentialDirectoryEndTag = UInt32() - fread(&potentialDirectoryEndTag, 1, MemoryLayout.size, file) - if potentialDirectoryEndTag == UInt32(endOfCentralDirectoryStructSignature) { - eocdOffset = UInt64(archiveLength - index) - guard let eocd: EndOfCentralDirectoryRecord = Data.readStruct(from: file, at: eocdOffset) else { - return nil - } - let zip64EOCD = scanForZIP64EndOfCentralDirectory(in: file, eocdOffset: eocdOffset) - return (eocd, zip64EOCD) - } - index += 1 - } - return nil - } - - func makeIterator() -> AnyIterator { - let totalNumberOfEntriesInCD = totalNumberOfEntriesInCentralDirectory - var directoryIndex = offsetToStartOfCentralDirectory - var index = 0 - return AnyIterator { - guard index < totalNumberOfEntriesInCD else { return nil } - guard - let centralDirStruct: CentralDirectoryStructure = Data.readStruct( - from: self.archiveFile, - at: directoryIndex) - else { - return nil - } - let offset = UInt64(centralDirStruct.effectiveRelativeOffsetOfLocalHeader) - guard - let localFileHeader: LocalFileHeader = Data.readStruct( - from: self.archiveFile, - at: offset) - else { return nil } - var dataDescriptor: DataDescriptor? - var zip64DataDescriptor: ZIP64DataDescriptor? - if centralDirStruct.usesDataDescriptor { - let additionalSize = UInt64(localFileHeader.fileNameLength) + UInt64(localFileHeader.extraFieldLength) - let isCompressed = centralDirStruct.compressionMethod != CompressionMethod.none.rawValue - let dataSize = isCompressed - ? centralDirStruct.effectiveCompressedSize - : centralDirStruct.effectiveUncompressedSize - let descriptorPosition = offset + UInt64(LocalFileHeader.size) + additionalSize + dataSize - if centralDirStruct.isZIP64 { - zip64DataDescriptor = Data.readStruct(from: self.archiveFile, at: descriptorPosition) - } else { - dataDescriptor = Data.readStruct(from: self.archiveFile, at: descriptorPosition) - } - } - defer { - directoryIndex += UInt64(CentralDirectoryStructure.size) - directoryIndex += UInt64(centralDirStruct.fileNameLength) - directoryIndex += UInt64(centralDirStruct.extraFieldLength) - directoryIndex += UInt64(centralDirStruct.fileCommentLength) - index += 1 - } - return Entry( - centralDirectoryStructure: centralDirStruct, - localFileHeader: localFileHeader, - dataDescriptor: dataDescriptor, - zip64DataDescriptor: zip64DataDescriptor) - } - } - - /// Retrieve the ZIP `Entry` with the given `path` from the receiver. - /// - /// - Note: The ZIP file format specification does not enforce unique paths for entries. - /// Therefore an archive can contain multiple entries with the same path. This method - /// always returns the first `Entry` with the given `path`. - /// - /// - Parameter path: A relative file path identifying the corresponding `Entry`. - /// - Returns: An `Entry` with the given `path`. Otherwise, `nil`. - subscript(path: String) -> Entry? { - if let encoding = preferredEncoding { - return first { $0.path(using: encoding) == path } - } - return first { $0.path == path } - } - - // MARK: Private - - private static func scanForZIP64EndOfCentralDirectory(in file: FILEPointer, eocdOffset: UInt64) - -> ZIP64EndOfCentralDirectory? - { - guard UInt64(ZIP64EndOfCentralDirectoryLocator.size) < eocdOffset else { - return nil - } - let locatorOffset = eocdOffset - UInt64(ZIP64EndOfCentralDirectoryLocator.size) - - guard UInt64(ZIP64EndOfCentralDirectoryRecord.size) < locatorOffset else { - return nil - } - let recordOffset = locatorOffset - UInt64(ZIP64EndOfCentralDirectoryRecord.size) - guard - let locator: ZIP64EndOfCentralDirectoryLocator = Data.readStruct(from: file, at: locatorOffset), - let record: ZIP64EndOfCentralDirectoryRecord = Data.readStruct(from: file, at: recordOffset) - else { - return nil - } - return ZIP64EndOfCentralDirectory(record: record, locator: locator) - } -} - -extension Archive.EndOfCentralDirectoryRecord { - - // MARK: Lifecycle - - init?(data: Data, additionalDataProvider provider: (Int) throws -> Data) { - guard data.count == Archive.EndOfCentralDirectoryRecord.size else { return nil } - guard data.scanValue(start: 0) == endOfCentralDirectorySignature else { return nil } - numberOfDisk = data.scanValue(start: 4) - numberOfDiskStart = data.scanValue(start: 6) - totalNumberOfEntriesOnDisk = data.scanValue(start: 8) - totalNumberOfEntriesInCentralDirectory = data.scanValue(start: 10) - sizeOfCentralDirectory = data.scanValue(start: 12) - offsetToStartOfCentralDirectory = data.scanValue(start: 16) - zipFileCommentLength = data.scanValue(start: 20) - guard let commentData = try? provider(Int(zipFileCommentLength)) else { return nil } - guard commentData.count == Int(zipFileCommentLength) else { return nil } - zipFileCommentData = commentData - } - - init( - record: Archive.EndOfCentralDirectoryRecord, - numberOfEntriesOnDisk: UInt16, - numberOfEntriesInCentralDirectory: UInt16, - updatedSizeOfCentralDirectory: UInt32, - startOfCentralDirectory: UInt32) - { - numberOfDisk = record.numberOfDisk - numberOfDiskStart = record.numberOfDiskStart - totalNumberOfEntriesOnDisk = numberOfEntriesOnDisk - totalNumberOfEntriesInCentralDirectory = numberOfEntriesInCentralDirectory - sizeOfCentralDirectory = updatedSizeOfCentralDirectory - offsetToStartOfCentralDirectory = startOfCentralDirectory - zipFileCommentLength = record.zipFileCommentLength - zipFileCommentData = record.zipFileCommentData - } - - // MARK: Internal - - var data: Data { - var endOfCDSignature = endOfCentralDirectorySignature - var numberOfDisk = numberOfDisk - var numberOfDiskStart = numberOfDiskStart - var totalNumberOfEntriesOnDisk = totalNumberOfEntriesOnDisk - var totalNumberOfEntriesInCD = totalNumberOfEntriesInCentralDirectory - var sizeOfCentralDirectory = sizeOfCentralDirectory - var offsetToStartOfCD = offsetToStartOfCentralDirectory - var zipFileCommentLength = zipFileCommentLength - var data = Data() - withUnsafePointer(to: &endOfCDSignature) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &numberOfDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &numberOfDiskStart) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &totalNumberOfEntriesOnDisk) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &totalNumberOfEntriesInCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &sizeOfCentralDirectory) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &offsetToStartOfCD) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &zipFileCommentLength) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - data.append(zipFileCommentData) - return data - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Data+Compression.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Data+Compression.swift deleted file mode 100644 index 065661696adeb1a5ab6ef1b6af982401b5c2cb8c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Data+Compression.swift +++ /dev/null @@ -1,403 +0,0 @@ -// -// Data+Compression.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -#if canImport(zlib) -import zlib -#endif - -// MARK: - CompressionMethod - -/// The compression method of an `Entry` in a ZIP `Archive`. -enum CompressionMethod: UInt16 { - /// Indicates that an `Entry` has no compression applied to its contents. - case none = 0 - /// Indicates that contents of an `Entry` have been compressed with a zlib compatible Deflate algorithm. - case deflate = 8 -} - -/// An unsigned 32-Bit Integer representing a checksum. -typealias CRC32 = UInt32 -/// A custom handler that consumes a `Data` object containing partial entry data. -/// - Parameters: -/// - data: A chunk of `Data` to consume. -/// - Throws: Can throw to indicate errors during data consumption. -typealias Consumer = (_ data: Data) throws -> Void -/// A custom handler that receives a position and a size that can be used to provide data from an arbitrary source. -/// - Parameters: -/// - position: The current read position. -/// - size: The size of the chunk to provide. -/// - Returns: A chunk of `Data`. -/// - Throws: Can throw to indicate errors in the data source. -typealias Provider = (_ position: Int64, _ size: Int) throws -> Data - -extension Data { - enum CompressionError: Error { - case invalidStream - case corruptedData - } - - /// Compress the output of `provider` and pass it to `consumer`. - /// - Parameters: - /// - size: The uncompressed size of the data to be compressed. - /// - bufferSize: The maximum size of the compression buffer. - /// - provider: A closure that accepts a position and a chunk size. Returns a `Data` chunk. - /// - consumer: A closure that processes the result of the compress operation. - /// - Returns: The checksum of the processed content. - static func compress(size: Int64, bufferSize: Int, provider: Provider, consumer: Consumer) throws -> CRC32 { - #if os(macOS) || canImport(UIKit) - return try process( - operation: COMPRESSION_STREAM_ENCODE, - size: size, - bufferSize: bufferSize, - provider: provider, - consumer: consumer) - #else - return try encode(size: size, bufferSize: bufferSize, provider: provider, consumer: consumer) - #endif - } - - /// Decompress the output of `provider` and pass it to `consumer`. - /// - Parameters: - /// - size: The compressed size of the data to be decompressed. - /// - bufferSize: The maximum size of the decompression buffer. - /// - skipCRC32: Optional flag to skip calculation of the CRC32 checksum to improve performance. - /// - provider: A closure that accepts a position and a chunk size. Returns a `Data` chunk. - /// - consumer: A closure that processes the result of the decompress operation. - /// - Returns: The checksum of the processed content. - static func decompress( - size: Int64, - bufferSize: Int, - skipCRC32: Bool, - provider: Provider, - consumer: Consumer) - throws -> CRC32 - { - #if os(macOS) || canImport(UIKit) - return try process( - operation: COMPRESSION_STREAM_DECODE, - size: size, - bufferSize: bufferSize, - skipCRC32: skipCRC32, - provider: provider, - consumer: consumer) - #else - return try decode(bufferSize: bufferSize, skipCRC32: skipCRC32, provider: provider, consumer: consumer) - #endif - } - - /// Calculate the `CRC32` checksum of the receiver. - /// - /// - Parameter checksum: The starting seed. - /// - Returns: The checksum calculated from the bytes of the receiver and the starting seed. - func crc32(checksum: CRC32) -> CRC32 { - #if canImport(zlib) - return withUnsafeBytes { bufferPointer in - let length = UInt32(count) - return CRC32(zlib.crc32(UInt(checksum), bufferPointer.bindMemory(to: UInt8.self).baseAddress, length)) - } - #else - return builtInCRC32(checksum: checksum) - #endif - } - -} - -// MARK: - Apple Platforms - -#if os(macOS) || canImport(UIKit) -import Compression - -extension Data { - - static func process( - operation: compression_stream_operation, - size: Int64, - bufferSize: Int, - skipCRC32: Bool = false, - provider: Provider, - consumer: Consumer) - throws -> CRC32 - { - var crc32 = CRC32(0) - let destPointer = UnsafeMutablePointer.allocate(capacity: bufferSize) - defer { destPointer.deallocate() } - let streamPointer = UnsafeMutablePointer.allocate(capacity: 1) - defer { streamPointer.deallocate() } - var stream = streamPointer.pointee - var status = compression_stream_init(&stream, operation, COMPRESSION_ZLIB) - guard status != COMPRESSION_STATUS_ERROR else { throw CompressionError.invalidStream } - defer { compression_stream_destroy(&stream) } - stream.src_size = 0 - stream.dst_ptr = destPointer - stream.dst_size = bufferSize - var position: Int64 = 0 - var sourceData: Data? - repeat { - let isExhausted = stream.src_size == 0 - if isExhausted { - do { - sourceData = try provider(position, Int(Swift.min(size - position, Int64(bufferSize)))) - position += Int64(stream.prepare(for: sourceData)) - } catch { throw error } - } - if let sourceData { - sourceData.withUnsafeBytes { rawBufferPointer in - if let baseAddress = rawBufferPointer.baseAddress { - let pointer = baseAddress.assumingMemoryBound(to: UInt8.self) - stream.src_ptr = pointer.advanced(by: sourceData.count - stream.src_size) - let flags = sourceData.count < bufferSize ? Int32(COMPRESSION_STREAM_FINALIZE.rawValue) : 0 - status = compression_stream_process(&stream, flags) - } - } - if - operation == COMPRESSION_STREAM_ENCODE, - isExhausted, skipCRC32 == false { crc32 = sourceData.crc32(checksum: crc32) } - } - switch status { - case COMPRESSION_STATUS_OK, COMPRESSION_STATUS_END: - let outputData = Data(bytesNoCopy: destPointer, count: bufferSize - stream.dst_size, deallocator: .none) - try consumer(outputData) - if operation == COMPRESSION_STREAM_DECODE, !skipCRC32 { crc32 = outputData.crc32(checksum: crc32) } - stream.dst_ptr = destPointer - stream.dst_size = bufferSize - default: throw CompressionError.corruptedData - } - } while status == COMPRESSION_STATUS_OK - return crc32 - } -} - -extension compression_stream { - - fileprivate mutating func prepare(for sourceData: Data?) -> Int { - guard let sourceData else { return 0 } - - src_size = sourceData.count - return sourceData.count - } -} - -// MARK: - Linux - -#else -import CZlib - -extension Data { - static func encode(size: Int64, bufferSize: Int, provider: Provider, consumer: Consumer) throws -> CRC32 { - var stream = z_stream() - let streamSize = Int32(MemoryLayout.size) - var result = deflateInit2_( - &stream, - Z_DEFAULT_COMPRESSION, - Z_DEFLATED, - -MAX_WBITS, - 9, - Z_DEFAULT_STRATEGY, - ZLIB_VERSION, - streamSize) - defer { deflateEnd(&stream) } - guard result == Z_OK else { throw CompressionError.invalidStream } - var flush = Z_NO_FLUSH - var position: Int64 = 0 - var zipCRC32 = CRC32(0) - repeat { - let readSize = Int(Swift.min(size - position, Int64(bufferSize))) - var inputChunk = try provider(position, readSize) - zipCRC32 = inputChunk.crc32(checksum: zipCRC32) - stream.avail_in = UInt32(inputChunk.count) - try inputChunk.withUnsafeMutableBytes { rawBufferPointer in - if let baseAddress = rawBufferPointer.baseAddress { - let pointer = baseAddress.assumingMemoryBound(to: UInt8.self) - stream.next_in = pointer - flush = position + Int64(bufferSize) >= size ? Z_FINISH : Z_NO_FLUSH - } else if rawBufferPointer.count > 0 { - throw CompressionError.corruptedData - } else { - stream.next_in = nil - flush = Z_FINISH - } - var outputChunk = Data(count: bufferSize) - repeat { - stream.avail_out = UInt32(bufferSize) - try outputChunk.withUnsafeMutableBytes { rawBufferPointer in - guard let baseAddress = rawBufferPointer.baseAddress, rawBufferPointer.count > 0 else { - throw CompressionError.corruptedData - } - let pointer = baseAddress.assumingMemoryBound(to: UInt8.self) - stream.next_out = pointer - result = deflate(&stream, flush) - } - guard result >= Z_OK else { throw CompressionError.corruptedData } - - outputChunk.count = bufferSize - Int(stream.avail_out) - try consumer(outputChunk) - } while stream.avail_out == 0 - } - position += Int64(readSize) - } while flush != Z_FINISH - return zipCRC32 - } - - static func decode(bufferSize: Int, skipCRC32: Bool, provider: Provider, consumer: Consumer) throws -> CRC32 { - var stream = z_stream() - let streamSize = Int32(MemoryLayout.size) - var result = inflateInit2_(&stream, -MAX_WBITS, ZLIB_VERSION, streamSize) - defer { inflateEnd(&stream) } - guard result == Z_OK else { throw CompressionError.invalidStream } - var unzipCRC32 = CRC32(0) - var position: Int64 = 0 - repeat { - stream.avail_in = UInt32(bufferSize) - var chunk = try provider(position, bufferSize) - position += Int64(chunk.count) - try chunk.withUnsafeMutableBytes { rawBufferPointer in - if let baseAddress = rawBufferPointer.baseAddress, rawBufferPointer.count > 0 { - let pointer = baseAddress.assumingMemoryBound(to: UInt8.self) - stream.next_in = pointer - repeat { - var outputData = Data(count: bufferSize) - stream.avail_out = UInt32(bufferSize) - try outputData.withUnsafeMutableBytes { rawBufferPointer in - if let baseAddress = rawBufferPointer.baseAddress, rawBufferPointer.count > 0 { - let pointer = baseAddress.assumingMemoryBound(to: UInt8.self) - stream.next_out = pointer - } else { - throw CompressionError.corruptedData - } - result = inflate(&stream, Z_NO_FLUSH) - guard - result != Z_NEED_DICT, - result != Z_DATA_ERROR, - result != Z_MEM_ERROR - else { - throw CompressionError.corruptedData - } - } - let remainingLength = UInt32(bufferSize) - stream.avail_out - outputData.count = Int(remainingLength) - try consumer(outputData) - if !skipCRC32 { unzipCRC32 = outputData.crc32(checksum: unzipCRC32) } - } while stream.avail_out == 0 - } - } - } while result != Z_STREAM_END - return unzipCRC32 - } -} - -#endif - -/// The lookup table used to calculate `CRC32` checksums when using the built-in -/// CRC32 implementation. -private let crcTable: [CRC32] = [ - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, - 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, - 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, - 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, - 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, - 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, - 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, - 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, - 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, - 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, - 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, - 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, -] - -extension Data { - - /// Lookup table-based CRC32 implenetation that is used - /// if `zlib` isn't available. - /// - Parameter checksum: Running checksum or `0` for the initial run. - /// - Returns: The calculated checksum of the receiver. - func builtInCRC32(checksum: CRC32) -> CRC32 { - // The typecast is necessary on 32-bit platforms because of - // https://bugs.swift.org/browse/SR-1774 - let mask = 0xffffffff as CRC32 - var result = checksum ^ mask - #if swift(>=5.0) - crcTable.withUnsafeBufferPointer { crcTablePointer in - self.withUnsafeBytes { bufferPointer in - var bufferIndex = 0 - while bufferIndex < self.count { - let byte = bufferPointer[bufferIndex] - let index = Int((result ^ CRC32(byte)) & 0xff) - result = (result >> 8) ^ crcTablePointer[index] - bufferIndex += 1 - } - } - } - #else - withUnsafeBytes { bytes in - let bins = stride(from: 0, to: self.count, by: 256) - for bin in bins { - for binIndex in 0..<256 { - let byteIndex = bin + binIndex - guard byteIndex < self.count else { break } - - let byte = bytes[byteIndex] - let index = Int((result ^ CRC32(byte)) & 0xff) - result = (result >> 8) ^ crcTable[index] - } - } - } - #endif - return result ^ mask - } -} - -#if !swift(>=5.0) - -// Since Swift 5.0, `Data.withUnsafeBytes()` passes an `UnsafeRawBufferPointer` instead of an `UnsafePointer` -// into `body`. -// We provide a compatible method for targets that use Swift 4.x so that we can use the new version -// across all language versions. - -extension Data { - func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T { - let count = count - return try withUnsafeBytes { (pointer: UnsafePointer) throws -> T in - try body(UnsafeRawBufferPointer(start: pointer, count: count)) - } - } - - #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) - #else - mutating func withUnsafeMutableBytes(_ body: (UnsafeMutableRawBufferPointer) throws -> T) rethrows -> T { - let count = count - guard count > 0 else { - return try body(UnsafeMutableRawBufferPointer(start: nil, count: count)) - } - return try withUnsafeMutableBytes { (pointer: UnsafeMutablePointer) throws -> T in - try body(UnsafeMutableRawBufferPointer(start: pointer, count: count)) - } - } - #endif -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Data+CompressionDeprecated.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Data+CompressionDeprecated.swift deleted file mode 100644 index 43844b32a2518ff8b5035c38bda5580dbe450653..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Data+CompressionDeprecated.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// Data+CompressionDeprecated.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Data { - - @available(*, deprecated, message: "Please use `Int64` for `size` and provider `position`.") - static func compress( - size: Int, - bufferSize: Int, - provider: (_ position: Int, _ size: Int) throws -> Data, - consumer: Consumer) - throws -> CRC32 - { - let newProvider: Provider = { try provider(Int($0), $1) } - return try compress(size: Int64(size), bufferSize: bufferSize, provider: newProvider, consumer: consumer) - } - - @available(*, deprecated, message: "Please use `Int64` for `size` and provider `position`.") - static func decompress( - size: Int, - bufferSize: Int, - skipCRC32: Bool, - provider: (_ position: Int, _ size: Int) throws -> Data, - consumer: Consumer) - throws -> CRC32 - { - let newProvider: Provider = { try provider(Int($0), $1) } - return try decompress( - size: Int64(size), - bufferSize: bufferSize, - skipCRC32: skipCRC32, - provider: newProvider, - consumer: consumer) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Data+Serialization.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Data+Serialization.swift deleted file mode 100644 index 94479228f4f7e9bf01a6c3c33fe641e00c929886..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Data+Serialization.swift +++ /dev/null @@ -1,149 +0,0 @@ -// -// Data+Serialization.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -#if os(Android) -typealias FILEPointer = OpaquePointer -#else -typealias FILEPointer = UnsafeMutablePointer -#endif - -// MARK: - DataSerializable - -protocol DataSerializable { - static var size: Int { get } - init?(data: Data, additionalDataProvider: (Int) throws -> Data) - var data: Data { get } -} - -extension Data { - enum DataError: Error { - case unreadableFile - case unwritableFile - } - - static func readStruct(from file: FILEPointer, at offset: UInt64) - -> T? where T: DataSerializable - { - guard offset <= .max else { return nil } - fseeko(file, off_t(offset), SEEK_SET) - guard let data = try? readChunk(of: T.size, from: file) else { - return nil - } - let structure = T(data: data, additionalDataProvider: { additionalDataSize -> Data in - try self.readChunk(of: additionalDataSize, from: file) - }) - return structure - } - - static func consumePart( - of size: Int64, - chunkSize: Int, - skipCRC32: Bool = false, - provider: Provider, - consumer: Consumer) - throws -> CRC32 - { - var checksum = CRC32(0) - guard size > 0 else { - try consumer(Data()) - return checksum - } - - let readInOneChunk = (size < chunkSize) - var chunkSize = readInOneChunk ? Int(size) : chunkSize - var bytesRead: Int64 = 0 - while bytesRead < size { - let remainingSize = size - bytesRead - chunkSize = remainingSize < chunkSize ? Int(remainingSize) : chunkSize - let data = try provider(bytesRead, chunkSize) - try consumer(data) - if !skipCRC32 { - checksum = data.crc32(checksum: checksum) - } - bytesRead += Int64(chunkSize) - } - return checksum - } - - static func readChunk(of size: Int, from file: FILEPointer) throws -> Data { - let alignment = MemoryLayout.alignment - #if swift(>=4.1) - let bytes = UnsafeMutableRawPointer.allocate(byteCount: size, alignment: alignment) - #else - let bytes = UnsafeMutableRawPointer.allocate(bytes: size, alignedTo: alignment) - #endif - let bytesRead = fread(bytes, 1, size, file) - let error = ferror(file) - if error > 0 { - throw DataError.unreadableFile - } - #if swift(>=4.1) - return Data(bytesNoCopy: bytes, count: bytesRead, deallocator: .custom { buf, _ in buf.deallocate() }) - #else - let deallocator = Deallocator.custom { buf, _ in buf.deallocate(bytes: size, alignedTo: 1) } - return Data(bytesNoCopy: bytes, count: bytesRead, deallocator: deallocator) - #endif - } - - static func write(chunk: Data, to file: FILEPointer) throws -> Int { - var sizeWritten = 0 - chunk.withUnsafeBytes { rawBufferPointer in - if let baseAddress = rawBufferPointer.baseAddress, rawBufferPointer.count > 0 { - let pointer = baseAddress.assumingMemoryBound(to: UInt8.self) - sizeWritten = fwrite(pointer, 1, chunk.count, file) - } - } - let error = ferror(file) - if error > 0 { - throw DataError.unwritableFile - } - return sizeWritten - } - - static func writeLargeChunk( - _ chunk: Data, - size: UInt64, - bufferSize: Int, - to file: FILEPointer) - throws -> UInt64 - { - var sizeWritten: UInt64 = 0 - chunk.withUnsafeBytes { rawBufferPointer in - if let baseAddress = rawBufferPointer.baseAddress, rawBufferPointer.count > 0 { - let pointer = baseAddress.assumingMemoryBound(to: UInt8.self) - - while sizeWritten < size { - let remainingSize = size - sizeWritten - let chunkSize = Swift.min(Int(remainingSize), bufferSize) - let curPointer = pointer.advanced(by: Int(sizeWritten)) - fwrite(curPointer, 1, chunkSize, file) - sizeWritten += UInt64(chunkSize) - } - } - } - let error = ferror(file) - if error > 0 { - throw DataError.unwritableFile - } - return sizeWritten - } - - func scanValue(start: Int) -> T { - let subdata = subdata(in: start...size) - #if swift(>=5.0) - return subdata.withUnsafeBytes { $0.load(as: T.self) } - #else - return subdata.withUnsafeBytes { $0.pointee } - #endif - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Entry+Serialization.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Entry+Serialization.swift deleted file mode 100644 index 8c22c1324783d746e3722be0f55bf0cf88d6abbd..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Entry+Serialization.swift +++ /dev/null @@ -1,189 +0,0 @@ -// -// Entry+Serialization.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension Entry.LocalFileHeader { - - // MARK: Lifecycle - - init?(data: Data, additionalDataProvider provider: (Int) throws -> Data) { - guard data.count == Entry.LocalFileHeader.size else { return nil } - guard data.scanValue(start: 0) == localFileHeaderSignature else { return nil } - versionNeededToExtract = data.scanValue(start: 4) - generalPurposeBitFlag = data.scanValue(start: 6) - compressionMethod = data.scanValue(start: 8) - lastModFileTime = data.scanValue(start: 10) - lastModFileDate = data.scanValue(start: 12) - crc32 = data.scanValue(start: 14) - compressedSize = data.scanValue(start: 18) - uncompressedSize = data.scanValue(start: 22) - fileNameLength = data.scanValue(start: 26) - extraFieldLength = data.scanValue(start: 28) - let additionalDataLength = Int(fileNameLength) + Int(extraFieldLength) - guard let additionalData = try? provider(additionalDataLength) else { return nil } - guard additionalData.count == additionalDataLength else { return nil } - var subRangeStart = 0 - var subRangeEnd = Int(fileNameLength) - fileNameData = additionalData.subdata(in: subRangeStart.. Data) { - guard data.count == Entry.CentralDirectoryStructure.size else { return nil } - guard data.scanValue(start: 0) == centralDirectorySignature else { return nil } - versionMadeBy = data.scanValue(start: 4) - versionNeededToExtract = data.scanValue(start: 6) - generalPurposeBitFlag = data.scanValue(start: 8) - compressionMethod = data.scanValue(start: 10) - lastModFileTime = data.scanValue(start: 12) - lastModFileDate = data.scanValue(start: 14) - crc32 = data.scanValue(start: 16) - compressedSize = data.scanValue(start: 20) - uncompressedSize = data.scanValue(start: 24) - fileNameLength = data.scanValue(start: 28) - extraFieldLength = data.scanValue(start: 30) - fileCommentLength = data.scanValue(start: 32) - diskNumberStart = data.scanValue(start: 34) - internalFileAttributes = data.scanValue(start: 36) - externalFileAttributes = data.scanValue(start: 38) - relativeOffsetOfLocalHeader = data.scanValue(start: 42) - let additionalDataLength = Int(fileNameLength) + Int(extraFieldLength) + Int(fileCommentLength) - guard let additionalData = try? provider(additionalDataLength) else { return nil } - guard additionalData.count == additionalDataLength else { return nil } - var subRangeStart = 0 - var subRangeEnd = Int(fileNameLength) - fileNameData = additionalData.subdata(in: subRangeStart.. Data) { - guard data.count == Self.size else { return nil } - let signature: UInt32 = data.scanValue(start: 0) - // The DataDescriptor signature is not mandatory so we have to re-arrange the input data if it is missing. - var readOffset = 0 - if signature == dataDescriptorSignature { readOffset = 4 } - crc32 = data.scanValue(start: readOffset) - readOffset += MemoryLayout.size - compressedSize = data.scanValue(start: readOffset) - readOffset += Self.memoryLengthOfSize - uncompressedSize = data.scanValue(start: readOffset) - // Our add(_ entry:) methods always maintain compressed & uncompressed - // sizes and so we don't need a data descriptor for newly added entries. - // Data descriptors of already existing entries are manually preserved - // when copying those entries to the tempArchive during remove(_ entry:). - self.data = Data() - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Entry+ZIP64.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Entry+ZIP64.swift deleted file mode 100644 index f763a218919cda7da6ebd5388a498b7269ecfd0c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/Entry+ZIP64.swift +++ /dev/null @@ -1,173 +0,0 @@ -// -// Entry+ZIP64.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -// MARK: - ExtensibleDataField - -protocol ExtensibleDataField { - var headerID: UInt16 { get } - var dataSize: UInt16 { get } -} - -extension Entry { - enum EntryError: Error { - case invalidDataError - } - - struct ZIP64ExtendedInformation: ExtensibleDataField { - let headerID: UInt16 = ExtraFieldHeaderID.zip64ExtendedInformation.rawValue - let dataSize: UInt16 - static let headerSize: UInt16 = 4 - let uncompressedSize: UInt64 - let compressedSize: UInt64 - let relativeOffsetOfLocalHeader: UInt64 - let diskNumberStart: UInt32 - } - - var zip64ExtendedInformation: ZIP64ExtendedInformation? { - centralDirectoryStructure.zip64ExtendedInformation - } -} - -typealias Field = Entry.ZIP64ExtendedInformation.Field - -extension Entry.LocalFileHeader { - var validFields: [Field] { - var fields: [Field] = [] - if uncompressedSize == .max { fields.append(.uncompressedSize) } - if compressedSize == .max { fields.append(.compressedSize) } - return fields - } -} - -extension Entry.CentralDirectoryStructure { - var validFields: [Field] { - var fields: [Field] = [] - if uncompressedSize == .max { fields.append(.uncompressedSize) } - if compressedSize == .max { fields.append(.compressedSize) } - if relativeOffsetOfLocalHeader == .max { fields.append(.relativeOffsetOfLocalHeader) } - if diskNumberStart == .max { fields.append(.diskNumberStart) } - return fields - } - - var zip64ExtendedInformation: Entry.ZIP64ExtendedInformation? { - extraFields?.compactMap { $0 as? Entry.ZIP64ExtendedInformation }.first - } -} - -extension Entry.ZIP64ExtendedInformation { - - // MARK: Lifecycle - - init?(data: Data, fields: [Field]) { - let headerLength = 4 - guard fields.reduce(0, { $0 + $1.size }) + headerLength == data.count else { return nil } - var readOffset = headerLength - func value(of field: Field) throws -> T where T: BinaryInteger { - if fields.contains(field) { - defer { - readOffset += MemoryLayout.size - } - guard readOffset + field.size <= data.count else { - throw Entry.EntryError.invalidDataError - } - return data.scanValue(start: readOffset) - } else { - return 0 - } - } - do { - dataSize = data.scanValue(start: 2) - uncompressedSize = try value(of: .uncompressedSize) - compressedSize = try value(of: .compressedSize) - relativeOffsetOfLocalHeader = try value(of: .relativeOffsetOfLocalHeader) - diskNumberStart = try value(of: .diskNumberStart) - } catch { - return nil - } - } - - init?(zip64ExtendedInformation: Entry.ZIP64ExtendedInformation?, offset: UInt64) { - // Only used when removing entry, if no ZIP64 extended information exists, - // then this information will not be newly added either - guard let existingInfo = zip64ExtendedInformation else { return nil } - relativeOffsetOfLocalHeader = offset >= maxOffsetOfLocalFileHeader ? offset : 0 - uncompressedSize = existingInfo.uncompressedSize - compressedSize = existingInfo.compressedSize - diskNumberStart = existingInfo.diskNumberStart - let tempDataSize = [relativeOffsetOfLocalHeader, uncompressedSize, compressedSize] - .filter { $0 != 0 } - .reduce(UInt16(0)) { $0 + UInt16(MemoryLayout.size(ofValue: $1)) } - dataSize = tempDataSize + (diskNumberStart > 0 ? UInt16(MemoryLayout.size(ofValue: diskNumberStart)) : 0) - if dataSize == 0 { return nil } - } - - // MARK: Internal - - enum Field { - case uncompressedSize - case compressedSize - case relativeOffsetOfLocalHeader - case diskNumberStart - - var size: Int { - switch self { - case .uncompressedSize, .compressedSize, .relativeOffsetOfLocalHeader: - return 8 - case .diskNumberStart: - return 4 - } - } - } - - var data: Data { - var headerID = headerID - var dataSize = dataSize - var uncompressedSize = uncompressedSize - var compressedSize = compressedSize - var relativeOffsetOfLFH = relativeOffsetOfLocalHeader - var diskNumberStart = diskNumberStart - var data = Data() - withUnsafePointer(to: &headerID) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &dataSize) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - if uncompressedSize != 0 || compressedSize != 0 { - withUnsafePointer(to: &uncompressedSize) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - withUnsafePointer(to: &compressedSize) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - } - if relativeOffsetOfLocalHeader != 0 { - withUnsafePointer(to: &relativeOffsetOfLFH) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - } - if diskNumberStart != 0 { - withUnsafePointer(to: &diskNumberStart) { data.append(UnsafeBufferPointer(start: $0, count: 1)) } - } - return data - } - - static func scanForZIP64Field(in data: Data, fields: [Field]) -> Entry.ZIP64ExtendedInformation? { - guard data.isEmpty == false else { return nil } - var offset = 0 - var headerID: UInt16 - var dataSize: UInt16 - let extraFieldLength = data.count - let headerSize = Int(Entry.ZIP64ExtendedInformation.headerSize) - while offset < extraFieldLength - headerSize { - headerID = data.scanValue(start: offset) - dataSize = data.scanValue(start: offset + 2) - let nextOffset = offset + headerSize + Int(dataSize) - guard nextOffset <= extraFieldLength else { return nil } - if headerID == ExtraFieldHeaderID.zip64ExtendedInformation.rawValue { - return Entry.ZIP64ExtendedInformation(data: data.subdata(in: offset..: DataSerializable { - let data: Data - let dataDescriptorSignature = UInt32(dataDescriptorStructSignature) - let crc32: UInt32 - // For normal archives, the compressed and uncompressed sizes are 4 bytes each. - // For ZIP64 format archives, the compressed and uncompressed sizes are 8 bytes each. - let compressedSize: T - let uncompressedSize: T - static var memoryLengthOfSize: Int { MemoryLayout.size } - static var size: Int { memoryLengthOfSize * 2 + 8 } - } - - typealias DefaultDataDescriptor = DataDescriptor - typealias ZIP64DataDescriptor = DataDescriptor - - struct CentralDirectoryStructure: DataSerializable { - static let size = 46 - - let centralDirectorySignature = UInt32(centralDirectoryStructSignature) - let versionMadeBy: UInt16 - let versionNeededToExtract: UInt16 - let generalPurposeBitFlag: UInt16 - let compressionMethod: UInt16 - let lastModFileTime: UInt16 - let lastModFileDate: UInt16 - let crc32: UInt32 - let compressedSize: UInt32 - let uncompressedSize: UInt32 - let fileNameLength: UInt16 - let extraFieldLength: UInt16 - let fileCommentLength: UInt16 - let diskNumberStart: UInt16 - let internalFileAttributes: UInt16 - let externalFileAttributes: UInt32 - let relativeOffsetOfLocalHeader: UInt32 - let fileNameData: Data - let extraFieldData: Data - let fileCommentData: Data - - var extraFields: [ExtensibleDataField]? - - var usesDataDescriptor: Bool { (generalPurposeBitFlag & (1 << 3)) != 0 } - var usesUTF8PathEncoding: Bool { (generalPurposeBitFlag & (1 << 11)) != 0 } - var isEncrypted: Bool { (generalPurposeBitFlag & (1 << 0)) != 0 } - var isZIP64: Bool { - // If ZIP64 extended information is existing, try to treat cd as ZIP64 format - // even if the version needed to extract is lower than 4.5 - UInt8(truncatingIfNeeded: versionNeededToExtract) >= 45 || zip64ExtendedInformation != nil - } - } - - let centralDirectoryStructure: CentralDirectoryStructure - let localFileHeader: LocalFileHeader - let dataDescriptor: DefaultDataDescriptor? - let zip64DataDescriptor: ZIP64DataDescriptor? - - /// The `path` of the receiver within a ZIP `Archive`. - var path: String { - let dosLatinUS = 0x400 - let dosLatinUSEncoding = CFStringEncoding(dosLatinUS) - let dosLatinUSStringEncoding = CFStringConvertEncodingToNSStringEncoding(dosLatinUSEncoding) - let codepage437 = String.Encoding(rawValue: dosLatinUSStringEncoding) - let encoding = centralDirectoryStructure.usesUTF8PathEncoding ? .utf8 : codepage437 - return self.path(using: encoding) - } - - /// The file attributes of the receiver as key/value pairs. - /// - /// Contains the modification date and file permissions. - var fileAttributes: [FileAttributeKey: Any] { - FileManager.attributes(from: self) - } - - /// The `CRC32` checksum of the receiver. - /// - /// - Note: Always returns `0` for entries of type `EntryType.directory`. - var checksum: CRC32 { - if centralDirectoryStructure.usesDataDescriptor { - return zip64DataDescriptor?.crc32 ?? dataDescriptor?.crc32 ?? 0 - } - return centralDirectoryStructure.crc32 - } - - /// The `EntryType` of the receiver. - var type: EntryType { - // OS Type is stored in the upper byte of versionMadeBy - let osTypeRaw = centralDirectoryStructure.versionMadeBy >> 8 - let osType = OSType(rawValue: UInt(osTypeRaw)) ?? .unused - var isDirectory = path.hasSuffix("/") - switch osType { - case .unix, .osx: - let mode = mode_t(centralDirectoryStructure.externalFileAttributes >> 16) & S_IFMT - switch mode { - case S_IFREG: - return .file - case S_IFDIR: - return .directory - case S_IFLNK: - return .symlink - default: - return isDirectory ? .directory : .file - } - case .msdos: - isDirectory = isDirectory || ((centralDirectoryStructure.externalFileAttributes >> 4) == 0x01) - fallthrough // For all other OSes we can only guess based on the directory suffix char - default: return isDirectory ? .directory : .file - } - } - - /// Indicates whether or not the receiver is compressed. - var isCompressed: Bool { - localFileHeader.compressionMethod != CompressionMethod.none.rawValue - } - - /// The size of the receiver's compressed data. - var compressedSize: UInt64 { - if centralDirectoryStructure.isZIP64 { - return zip64DataDescriptor?.compressedSize ?? centralDirectoryStructure.effectiveCompressedSize - } - return UInt64(dataDescriptor?.compressedSize ?? centralDirectoryStructure.compressedSize) - } - - /// The size of the receiver's uncompressed data. - var uncompressedSize: UInt64 { - if centralDirectoryStructure.isZIP64 { - return zip64DataDescriptor?.uncompressedSize ?? centralDirectoryStructure.effectiveUncompressedSize - } - return UInt64(dataDescriptor?.uncompressedSize ?? centralDirectoryStructure.uncompressedSize) - } - - /// The combined size of the local header, the data and the optional data descriptor. - var localSize: UInt64 { - let localFileHeader = localFileHeader - var extraDataLength = Int(localFileHeader.fileNameLength) - extraDataLength += Int(localFileHeader.extraFieldLength) - var size = UInt64(LocalFileHeader.size + extraDataLength) - size += isCompressed ? compressedSize : uncompressedSize - if centralDirectoryStructure.isZIP64 { - size += zip64DataDescriptor != nil ? UInt64(ZIP64DataDescriptor.size) : 0 - } else { - size += dataDescriptor != nil ? UInt64(DefaultDataDescriptor.size) : 0 - } - return size - } - - var dataOffset: UInt64 { - var dataOffset = centralDirectoryStructure.effectiveRelativeOffsetOfLocalHeader - dataOffset += UInt64(LocalFileHeader.size) - dataOffset += UInt64(localFileHeader.fileNameLength) - dataOffset += UInt64(localFileHeader.extraFieldLength) - return dataOffset - } - - static func == (lhs: Entry, rhs: Entry) -> Bool { - lhs.path == rhs.path - && lhs.localFileHeader.crc32 == rhs.localFileHeader.crc32 - && lhs.centralDirectoryStructure.effectiveRelativeOffsetOfLocalHeader - == rhs.centralDirectoryStructure.effectiveRelativeOffsetOfLocalHeader - } - - /// Returns the `path` of the receiver within a ZIP `Archive` using a given encoding. - /// - /// - Parameters: - /// - encoding: `String.Encoding` - func path(using encoding: String.Encoding) -> String { - String(data: centralDirectoryStructure.fileNameData, encoding: encoding) ?? "" - } - -} - -extension Entry.CentralDirectoryStructure { - - init( - localFileHeader: Entry.LocalFileHeader, - fileAttributes: UInt32, - relativeOffset: UInt32, - extraField: (length: UInt16, data: Data)) - { - versionMadeBy = UInt16(789) - versionNeededToExtract = localFileHeader.versionNeededToExtract - generalPurposeBitFlag = localFileHeader.generalPurposeBitFlag - compressionMethod = localFileHeader.compressionMethod - lastModFileTime = localFileHeader.lastModFileTime - lastModFileDate = localFileHeader.lastModFileDate - crc32 = localFileHeader.crc32 - compressedSize = localFileHeader.compressedSize - uncompressedSize = localFileHeader.uncompressedSize - fileNameLength = localFileHeader.fileNameLength - extraFieldLength = extraField.length - fileCommentLength = UInt16(0) - diskNumberStart = UInt16(0) - internalFileAttributes = UInt16(0) - externalFileAttributes = fileAttributes - relativeOffsetOfLocalHeader = relativeOffset - fileNameData = localFileHeader.fileNameData - extraFieldData = extraField.data - fileCommentData = Data() - if - let zip64ExtendedInformation = Entry.ZIP64ExtendedInformation.scanForZIP64Field( - in: extraFieldData, - fields: validFields) - { - extraFields = [zip64ExtendedInformation] - } - } - - init( - centralDirectoryStructure: Entry.CentralDirectoryStructure, - zip64ExtendedInformation: Entry.ZIP64ExtendedInformation?, - relativeOffset: UInt32) - { - if let existingInfo = zip64ExtendedInformation { - extraFieldData = existingInfo.data - versionNeededToExtract = max( - centralDirectoryStructure.versionNeededToExtract, - Archive.Version.v45.rawValue) - } else { - extraFieldData = centralDirectoryStructure.extraFieldData - let existingVersion = centralDirectoryStructure.versionNeededToExtract - versionNeededToExtract = existingVersion < Archive.Version.v45.rawValue - ? centralDirectoryStructure.versionNeededToExtract - : Archive.Version.v20.rawValue - } - extraFieldLength = UInt16(extraFieldData.count) - relativeOffsetOfLocalHeader = relativeOffset - versionMadeBy = centralDirectoryStructure.versionMadeBy - generalPurposeBitFlag = centralDirectoryStructure.generalPurposeBitFlag - compressionMethod = centralDirectoryStructure.compressionMethod - lastModFileTime = centralDirectoryStructure.lastModFileTime - lastModFileDate = centralDirectoryStructure.lastModFileDate - crc32 = centralDirectoryStructure.crc32 - compressedSize = centralDirectoryStructure.compressedSize - uncompressedSize = centralDirectoryStructure.uncompressedSize - fileNameLength = centralDirectoryStructure.fileNameLength - fileCommentLength = centralDirectoryStructure.fileCommentLength - diskNumberStart = centralDirectoryStructure.diskNumberStart - internalFileAttributes = centralDirectoryStructure.internalFileAttributes - externalFileAttributes = centralDirectoryStructure.externalFileAttributes - fileNameData = centralDirectoryStructure.fileNameData - fileCommentData = centralDirectoryStructure.fileCommentData - if - let zip64ExtendedInformation = Entry.ZIP64ExtendedInformation.scanForZIP64Field( - in: extraFieldData, - fields: validFields) - { - extraFields = [zip64ExtendedInformation] - } - } -} - -extension Entry.CentralDirectoryStructure { - - var effectiveCompressedSize: UInt64 { - if isZIP64, let compressedSize = zip64ExtendedInformation?.compressedSize, compressedSize > 0 { - return compressedSize - } - return UInt64(compressedSize) - } - - var effectiveUncompressedSize: UInt64 { - if isZIP64, let uncompressedSize = zip64ExtendedInformation?.uncompressedSize, uncompressedSize > 0 { - return uncompressedSize - } - return UInt64(uncompressedSize) - } - - var effectiveRelativeOffsetOfLocalHeader: UInt64 { - if isZIP64, let offset = zip64ExtendedInformation?.relativeOffsetOfLocalHeader, offset > 0 { - return offset - } - return UInt64(relativeOffsetOfLocalHeader) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIP.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIP.swift deleted file mode 100644 index 69ea55e16358312112be9ca91b262b6abb56c5b4..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIP.swift +++ /dev/null @@ -1,368 +0,0 @@ -// -// FileManager+ZIP.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension FileManager { - typealias CentralDirectoryStructure = Entry.CentralDirectoryStructure - - class func attributes(from entry: Entry) -> [FileAttributeKey: Any] { - let centralDirectoryStructure = entry.centralDirectoryStructure - let entryType = entry.type - let fileTime = centralDirectoryStructure.lastModFileTime - let fileDate = centralDirectoryStructure.lastModFileDate - let defaultPermissions = entryType == .directory ? defaultDirectoryPermissions : defaultFilePermissions - var attributes = [.posixPermissions: defaultPermissions] as [FileAttributeKey: Any] - // Certain keys are not yet supported in swift-corelibs - #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) - attributes[.modificationDate] = Date(dateTime: (fileDate, fileTime)) - #endif - let versionMadeBy = centralDirectoryStructure.versionMadeBy - guard let osType = Entry.OSType(rawValue: UInt(versionMadeBy >> 8)) else { return attributes } - - let externalFileAttributes = centralDirectoryStructure.externalFileAttributes - let permissions = permissions(for: externalFileAttributes, osType: osType, entryType: entryType) - attributes[.posixPermissions] = NSNumber(value: permissions) - return attributes - } - - class func permissions( - for externalFileAttributes: UInt32, - osType: Entry.OSType, - entryType: Entry.EntryType) - -> UInt16 - { - switch osType { - case .unix, .osx: - let permissions = mode_t(externalFileAttributes >> 16) & ~S_IFMT - let defaultPermissions = entryType == .directory ? defaultDirectoryPermissions : defaultFilePermissions - return permissions == 0 ? defaultPermissions : UInt16(permissions) - default: - return entryType == .directory ? defaultDirectoryPermissions : defaultFilePermissions - } - } - - class func externalFileAttributesForEntry(of type: Entry.EntryType, permissions: UInt16) -> UInt32 { - var typeInt: UInt16 - switch type { - case .file: - typeInt = UInt16(S_IFREG) - case .directory: - typeInt = UInt16(S_IFDIR) - case .symlink: - typeInt = UInt16(S_IFLNK) - } - var externalFileAttributes = UInt32(typeInt | UInt16(permissions)) - externalFileAttributes = (externalFileAttributes << 16) - return externalFileAttributes - } - - class func permissionsForItem(at URL: URL) throws -> UInt16 { - let fileManager = FileManager() - let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: URL.path) - var fileStat = stat() - lstat(entryFileSystemRepresentation, &fileStat) - let permissions = fileStat.st_mode - return UInt16(permissions) - } - - class func fileModificationDateTimeForItem(at url: URL) throws -> Date { - let fileManager = FileManager() - guard fileManager.itemExists(at: url) else { - throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: url.path]) - } - let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path) - var fileStat = stat() - lstat(entryFileSystemRepresentation, &fileStat) - #if os(macOS) || canImport(UIKit) - let modTimeSpec = fileStat.st_mtimespec - #else - let modTimeSpec = fileStat.st_mtim - #endif - - let timeStamp = TimeInterval(modTimeSpec.tv_sec) + TimeInterval(modTimeSpec.tv_nsec) / 1000000000.0 - let modDate = Date(timeIntervalSince1970: timeStamp) - return modDate - } - - class func fileSizeForItem(at url: URL) throws -> Int64 { - let fileManager = FileManager() - guard fileManager.itemExists(at: url) else { - throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: url.path]) - } - let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path) - var fileStat = stat() - lstat(entryFileSystemRepresentation, &fileStat) - guard fileStat.st_size >= 0 else { - throw CocoaError(.fileReadTooLarge, userInfo: [NSFilePathErrorKey: url.path]) - } - // `st_size` is a signed int value - return Int64(fileStat.st_size) - } - - class func typeForItem(at url: URL) throws -> Entry.EntryType { - let fileManager = FileManager() - guard url.isFileURL, fileManager.itemExists(at: url) else { - throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: url.path]) - } - let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path) - var fileStat = stat() - lstat(entryFileSystemRepresentation, &fileStat) - return Entry.EntryType(mode: mode_t(fileStat.st_mode)) - } - - /// Zips the file or directory contents at the specified source URL to the destination URL. - /// - /// If the item at the source URL is a directory, the directory itself will be - /// represented within the ZIP `Archive`. Calling this method with a directory URL - /// `file:///path/directory/` will create an archive with a `directory/` entry at the root level. - /// You can override this behavior by passing `false` for `shouldKeepParent`. In that case, the contents - /// of the source directory will be placed at the root of the archive. - /// - Parameters: - /// - sourceURL: The file URL pointing to an existing file or directory. - /// - destinationURL: The file URL that identifies the destination of the zip operation. - /// - shouldKeepParent: Indicates that the directory name of a source item should be used as root element - /// within the archive. Default is `true`. - /// - compressionMethod: Indicates the `CompressionMethod` that should be applied. - /// By default, `zipItem` will create uncompressed archives. - /// - progress: A progress object that can be used to track or cancel the zip operation. - /// - Throws: Throws an error if the source item does not exist or the destination URL is not writable. - func zipItem( - at sourceURL: URL, - to destinationURL: URL, - shouldKeepParent: Bool = true, - compressionMethod: CompressionMethod = .none, - progress: Progress? = nil) - throws - { - let fileManager = FileManager() - guard fileManager.itemExists(at: sourceURL) else { - throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: sourceURL.path]) - } - guard !fileManager.itemExists(at: destinationURL) else { - throw CocoaError(.fileWriteFileExists, userInfo: [NSFilePathErrorKey: destinationURL.path]) - } - guard let archive = Archive(url: destinationURL, accessMode: .create) else { - throw Archive.ArchiveError.unwritableArchive - } - let isDirectory = try FileManager.typeForItem(at: sourceURL) == .directory - if isDirectory { - let subPaths = try subpathsOfDirectory(atPath: sourceURL.path) - var totalUnitCount = Int64(0) - if let progress { - totalUnitCount = subPaths.reduce(Int64(0)) { - let itemURL = sourceURL.appendingPathComponent($1) - let itemSize = archive.totalUnitCountForAddingItem(at: itemURL) - return $0 + itemSize - } - progress.totalUnitCount = totalUnitCount - } - - // If the caller wants to keep the parent directory, we use the lastPathComponent of the source URL - // as common base for all entries (similar to macOS' Archive Utility.app) - let directoryPrefix = sourceURL.lastPathComponent - for entryPath in subPaths { - let finalEntryPath = shouldKeepParent ? directoryPrefix + "/" + entryPath : entryPath - let finalBaseURL = shouldKeepParent ? sourceURL.deletingLastPathComponent() : sourceURL - if let progress { - let itemURL = sourceURL.appendingPathComponent(entryPath) - let entryProgress = archive.makeProgressForAddingItem(at: itemURL) - progress.addChild(entryProgress, withPendingUnitCount: entryProgress.totalUnitCount) - try archive.addEntry( - with: finalEntryPath, - relativeTo: finalBaseURL, - compressionMethod: compressionMethod, - progress: entryProgress) - } else { - try archive.addEntry( - with: finalEntryPath, - relativeTo: finalBaseURL, - compressionMethod: compressionMethod) - } - } - } else { - progress?.totalUnitCount = archive.totalUnitCountForAddingItem(at: sourceURL) - let baseURL = sourceURL.deletingLastPathComponent() - try archive.addEntry( - with: sourceURL.lastPathComponent, - relativeTo: baseURL, - compressionMethod: compressionMethod, - progress: progress) - } - } - - /// Unzips the contents at the specified source URL to the destination URL. - /// - /// - Parameters: - /// - sourceURL: The file URL pointing to an existing ZIP file. - /// - destinationURL: The file URL that identifies the destination directory of the unzip operation. - /// - skipCRC32: Optional flag to skip calculation of the CRC32 checksum to improve performance. - /// - progress: A progress object that can be used to track or cancel the unzip operation. - /// - preferredEncoding: Encoding for entry paths. Overrides the encoding specified in the archive. - /// - Throws: Throws an error if the source item does not exist or the destination URL is not writable. - func unzipItem( - at sourceURL: URL, - to destinationURL: URL, - skipCRC32: Bool = false, - progress: Progress? = nil, - preferredEncoding: String.Encoding? = nil) - throws - { - let fileManager = FileManager() - guard fileManager.itemExists(at: sourceURL) else { - throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: sourceURL.path]) - } - guard let archive = Archive(url: sourceURL, accessMode: .read, preferredEncoding: preferredEncoding) else { - throw Archive.ArchiveError.unreadableArchive - } - // Defer extraction of symlinks until all files & directories have been created. - // This is necessary because we can't create links to files that haven't been created yet. - let sortedEntries = archive.sorted { left, right -> Bool in - switch (left.type, right.type) { - case (.directory, .file): return true - case (.directory, .symlink): return true - case (.file, .symlink): return true - default: return false - } - } - var totalUnitCount = Int64(0) - if let progress { - totalUnitCount = sortedEntries.reduce(0) { $0 + archive.totalUnitCountForReading($1) } - progress.totalUnitCount = totalUnitCount - } - - for entry in sortedEntries { - let path = preferredEncoding == nil ? entry.path : entry.path(using: preferredEncoding!) - let entryURL = destinationURL.appendingPathComponent(path) - guard entryURL.isContained(in: destinationURL) else { - throw CocoaError( - .fileReadInvalidFileName, - userInfo: [NSFilePathErrorKey: entryURL.path]) - } - let crc32: CRC32 - if let progress { - let entryProgress = archive.makeProgressForReading(entry) - progress.addChild(entryProgress, withPendingUnitCount: entryProgress.totalUnitCount) - crc32 = try archive.extract(entry, to: entryURL, skipCRC32: skipCRC32, progress: entryProgress) - } else { - crc32 = try archive.extract(entry, to: entryURL, skipCRC32: skipCRC32) - } - - func verifyChecksumIfNecessary() throws { - if skipCRC32 == false, crc32 != entry.checksum { - throw Archive.ArchiveError.invalidCRC32 - } - } - try verifyChecksumIfNecessary() - } - } - - // MARK: - Helpers - - func itemExists(at url: URL) -> Bool { - // Use `URL.checkResourceIsReachable()` instead of `FileManager.fileExists()` here - // because we don't want implicit symlink resolution. - // As per documentation, `FileManager.fileExists()` traverses symlinks and therefore a broken symlink - // would throw a `.fileReadNoSuchFile` false positive error. - // For ZIP files it may be intended to archive "broken" symlinks because they might be - // resolvable again when extracting the archive to a different destination. - (try? url.checkResourceIsReachable()) == true - } - - func createParentDirectoryStructure(for url: URL) throws { - let parentDirectoryURL = url.deletingLastPathComponent() - try createDirectory(at: parentDirectoryURL, withIntermediateDirectories: true, attributes: nil) - } - -} - -extension Date { - - // MARK: Lifecycle - - init(dateTime: (UInt16, UInt16)) { - var msdosDateTime = Int(dateTime.0) - msdosDateTime <<= 16 - msdosDateTime |= Int(dateTime.1) - var unixTime = tm() - unixTime.tm_sec = Int32((msdosDateTime & 31) * 2) - unixTime.tm_min = Int32((msdosDateTime >> 5) & 63) - unixTime.tm_hour = Int32((Int(dateTime.1) >> 11) & 31) - unixTime.tm_mday = Int32((msdosDateTime >> 16) & 31) - unixTime.tm_mon = Int32((msdosDateTime >> 21) & 15) - unixTime.tm_mon -= 1 // UNIX time struct month entries are zero based. - unixTime.tm_year = Int32(1980 + (msdosDateTime >> 25)) - unixTime.tm_year -= 1900 // UNIX time structs count in "years since 1900". - let time = timegm(&unixTime) - self = Date(timeIntervalSince1970: TimeInterval(time)) - } - - // MARK: Internal - - var fileModificationDateTime: (UInt16, UInt16) { - (self.fileModificationDate, self.fileModificationTime) - } - - var fileModificationDate: UInt16 { - var time = time_t(timeIntervalSince1970) - guard let unixTime = gmtime(&time) else { - return 0 - } - var year = unixTime.pointee.tm_year + 1900 // UNIX time structs count in "years since 1900". - // ZIP uses the MSDOS date format which has a valid range of 1980 - 2099. - year = year >= 1980 ? year : 1980 - year = year <= 2099 ? year : 2099 - let month = unixTime.pointee.tm_mon + 1 // UNIX time struct month entries are zero based. - let day = unixTime.pointee.tm_mday - return UInt16(day + (month * 32) + ((year - 1980) * 512)) - } - - var fileModificationTime: UInt16 { - var time = time_t(timeIntervalSince1970) - guard let unixTime = gmtime(&time) else { - return 0 - } - let hour = unixTime.pointee.tm_hour - let minute = unixTime.pointee.tm_min - let second = unixTime.pointee.tm_sec - return UInt16((second / 2) + (minute * 32) + (hour * 2048)) - } -} - -#if swift(>=4.2) -#else - -#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) -#else - -// The swift-corelibs-foundation version of NSError.swift was missing a convenience method to create -// error objects from error codes. (https://github.com/apple/swift-corelibs-foundation/pull/1420) -// We have to provide an implementation for non-Darwin platforms using Swift versions < 4.2. - -extension CocoaError { - static func error(_ code: CocoaError.Code, userInfo: [AnyHashable: Any]? = nil, url: URL? = nil) -> Error { - var info: [String: Any] = userInfo as? [String: Any] ?? [:] - if let url { - info[NSURLErrorKey] = url - } - return NSError(domain: NSCocoaErrorDomain, code: code.rawValue, userInfo: info) - } -} - -#endif -#endif - -extension URL { - func isContained(in parentDirectoryURL: URL) -> Bool { - // Ensure this URL is contained in the passed in URL - let parentDirectoryURL = URL(fileURLWithPath: parentDirectoryURL.path, isDirectory: true).standardized - return standardized.absoluteString.hasPrefix(parentDirectoryURL.absoluteString) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/README.md b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/README.md deleted file mode 100644 index 24d5c63877b7ae864adfac5f6e2134522668031c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## ZipFoundation - -This directory includes the source code of the ZIPFoundation library, from the following release: -https://github.com/weichsel/ZIPFoundation/releases/tag/0.9.16 - -Lottie is distributed via multiple package managers (SPM, Cocoapods, Carthage, and NPM), -each with different packaging and compilation requirements. - -Due to limitations of these package managers, we can't depend on / import -a separate ZIPFoundation module / library. Instead, we include the source -directly within the Lottie library and compile everything as a single unit. - -### Update instructions - -From time to time we may need to update to a more recent version of ZIPFoundation. -When doing this, follow these steps: - - 1. Download the latest release from https://github.com/weichsel/ZIPFoundation - and replace the source code in this directory with the updated code. - - 2. Update the URL at the top of this file to indicate what release is being used. - - 3. Change all of the `public` symbols defined in this module to instead be `internal` - to prevent Lottie from exposing any ZIPFoundation APIs. diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/URL+ZIP.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/URL+ZIP.swift deleted file mode 100644 index add5aa649c3340bd06d6025e1f58d97fe645e35d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/EmbeddedLibraries/ZipFoundation/URL+ZIP.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// URL+ZIP.swift -// ZIPFoundation -// -// Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors. -// Released under the MIT License. -// -// See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information. -// - -import Foundation - -extension URL { - - static func temporaryReplacementDirectoryURL(for archive: Archive) -> URL { - #if swift(>=5.0) || os(macOS) || os(iOS) || os(watchOS) || os(tvOS) - if - archive.url.isFileURL, - let tempDir = try? FileManager().url( - for: .itemReplacementDirectory, - in: .userDomainMask, - appropriateFor: archive.url, - create: true) - { - return tempDir - } - #endif - - return URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent( - ProcessInfo.processInfo.globallyUniqueString) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift deleted file mode 100644 index ba673900ddc3eb413b3301d390f67ed229556f33..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift +++ /dev/null @@ -1,160 +0,0 @@ -// -// LayerContainer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/22/19. -// - -import QuartzCore - -// MARK: - CompositionLayer - -/// The base class for a child layer of CompositionContainer -class CompositionLayer: CALayer, KeypathSearchable { - - // MARK: Lifecycle - - init(layer: LayerModel, size: CGSize) { - transformNode = LayerTransformNode(transform: layer.transform) - if let masks = layer.masks?.filter({ $0.mode != .none }), !masks.isEmpty { - maskLayer = MaskContainerLayer(masks: masks) - } else { - maskLayer = nil - } - matteType = layer.matte - inFrame = layer.inFrame.cgFloat - outFrame = layer.outFrame.cgFloat - timeStretch = layer.timeStretch.cgFloat - startFrame = layer.startTime.cgFloat - keypathName = layer.name - childKeypaths = [transformNode.transformProperties] - super.init() - anchorPoint = .zero - actions = [ - "opacity" : NSNull(), - "transform" : NSNull(), - "bounds" : NSNull(), - "anchorPoint" : NSNull(), - "sublayerTransform" : NSNull(), - ] - - contentsLayer.anchorPoint = .zero - contentsLayer.bounds = CGRect(origin: .zero, size: size) - contentsLayer.actions = [ - "opacity" : NSNull(), - "transform" : NSNull(), - "bounds" : NSNull(), - "anchorPoint" : NSNull(), - "sublayerTransform" : NSNull(), - "hidden" : NSNull(), - ] - compositingFilter = layer.blendMode.filterName - addSublayer(contentsLayer) - - if let maskLayer { - contentsLayer.mask = maskLayer - } - - name = layer.name - } - - override init(layer: Any) { - /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - guard let layer = layer as? CompositionLayer else { - fatalError("Wrong Layer Class") - } - transformNode = layer.transformNode - matteType = layer.matteType - inFrame = layer.inFrame - outFrame = layer.outFrame - timeStretch = layer.timeStretch - startFrame = layer.startFrame - keypathName = layer.keypathName - childKeypaths = [transformNode.transformProperties] - maskLayer = nil - super.init(layer: layer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - weak var layerDelegate: CompositionLayerDelegate? - - let transformNode: LayerTransformNode - - let contentsLayer = CALayer() - - let maskLayer: MaskContainerLayer? - - let matteType: MatteType? - - let inFrame: CGFloat - let outFrame: CGFloat - let startFrame: CGFloat - let timeStretch: CGFloat - - // MARK: Keypath Searchable - - let keypathName: String - - final var childKeypaths: [KeypathSearchable] - - var renderScale: CGFloat = 1 { - didSet { - updateRenderScale() - } - } - - var matteLayer: CompositionLayer? { - didSet { - if let matte = matteLayer { - if let type = matteType, type == .invert { - mask = InvertedMatteLayer(inputMatte: matte) - } else { - mask = matte - } - } else { - mask = nil - } - } - } - - var keypathProperties: [String: AnyNodeProperty] { - [:] - } - - var keypathLayer: CALayer? { - contentsLayer - } - - final func displayWithFrame(frame: CGFloat, forceUpdates: Bool) { - transformNode.updateTree(frame, forceUpdates: forceUpdates) - let layerVisible = frame.isInRangeOrEqual(inFrame, outFrame) - /// Only update contents if current time is within the layers time bounds. - if layerVisible { - displayContentsWithFrame(frame: frame, forceUpdates: forceUpdates) - maskLayer?.updateWithFrame(frame: frame, forceUpdates: forceUpdates) - } - contentsLayer.transform = transformNode.globalTransform - contentsLayer.opacity = transformNode.opacity - contentsLayer.isHidden = !layerVisible - layerDelegate?.frameUpdated(frame: frame) - } - - func displayContentsWithFrame(frame _: CGFloat, forceUpdates _: Bool) { - /// To be overridden by subclass - } - - func updateRenderScale() { - contentsScale = renderScale - } -} - -// MARK: - CompositionLayerDelegate - -protocol CompositionLayerDelegate: AnyObject { - func frameUpdated(frame: CGFloat) -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/ImageCompositionLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/ImageCompositionLayer.swift deleted file mode 100644 index 708b8a14bef6053f0e7c8d8715208c5ddab17a0a..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/ImageCompositionLayer.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// ImageCompositionLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -import QuartzCore - -final class ImageCompositionLayer: CompositionLayer { - - // MARK: Lifecycle - - init(imageLayer: ImageLayerModel, size: CGSize) { - imageReferenceID = imageLayer.referenceID - super.init(layer: imageLayer, size: size) - contentsLayer.masksToBounds = true - contentsLayer.contentsGravity = CALayerContentsGravity.resize - } - - override init(layer: Any) { - /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - guard let layer = layer as? ImageCompositionLayer else { - fatalError("init(layer:) Wrong Layer Class") - } - imageReferenceID = layer.imageReferenceID - image = nil - super.init(layer: layer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - let imageReferenceID: String - - var image: CGImage? = nil { - didSet { - if let image { - contentsLayer.contents = image - } else { - contentsLayer.contents = nil - } - } - } - - var imageContentsGravity: CALayerContentsGravity = .resize { - didSet { - contentsLayer.contentsGravity = imageContentsGravity - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift deleted file mode 100644 index d1182dbaff3c955a3b0554a96f3fbb0661a42059..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +++ /dev/null @@ -1,190 +0,0 @@ -// -// MaskContainerLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -import QuartzCore - -extension MaskMode { - var usableMode: MaskMode { - switch self { - case .add: - return .add - case .subtract: - return .subtract - case .intersect: - return .intersect - case .lighten: - return .add - case .darken: - return .darken - case .difference: - return .intersect - case .none: - return .none - } - } -} - -// MARK: - MaskContainerLayer - -final class MaskContainerLayer: CALayer { - - // MARK: Lifecycle - - init(masks: [Mask]) { - super.init() - anchorPoint = .zero - var containerLayer = CALayer() - var firstObject = true - for mask in masks { - let maskLayer = MaskLayer(mask: mask) - maskLayers.append(maskLayer) - if mask.mode.usableMode == .none { - continue - } else if mask.mode.usableMode == .add || firstObject { - firstObject = false - containerLayer.addSublayer(maskLayer) - } else { - containerLayer.mask = maskLayer - let newContainer = CALayer() - newContainer.addSublayer(containerLayer) - containerLayer = newContainer - } - } - addSublayer(containerLayer) - } - - override init(layer: Any) { - /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - guard let layer = layer as? MaskContainerLayer else { - fatalError("init(layer:) Wrong Layer Class") - } - super.init(layer: layer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - func updateWithFrame(frame: CGFloat, forceUpdates: Bool) { - for maskLayer in maskLayers { - maskLayer.updateWithFrame(frame: frame, forceUpdates: forceUpdates) - } - } - - // MARK: Fileprivate - - fileprivate var maskLayers: [MaskLayer] = [] -} - -extension CGRect { - static var veryLargeRect: CGRect { - CGRect( - x: -10_000_000, - y: -10_000_000, - width: 20_000_000, - height: 20_000_000) - } -} - -// MARK: - MaskLayer - -private class MaskLayer: CALayer { - - // MARK: Lifecycle - - init(mask: Mask) { - properties = MaskNodeProperties(mask: mask) - super.init() - addSublayer(maskLayer) - anchorPoint = .zero - maskLayer.fillColor = mask.mode == .add - ? .rgb(1, 0, 0) - : .rgb(0, 1, 0) - maskLayer.fillRule = CAShapeLayerFillRule.evenOdd - actions = [ - "opacity" : NSNull(), - ] - } - - override init(layer: Any) { - properties = nil - super.init(layer: layer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - let properties: MaskNodeProperties? - - let maskLayer = CAShapeLayer() - - func updateWithFrame(frame: CGFloat, forceUpdates: Bool) { - guard let properties else { return } - if properties.opacity.needsUpdate(frame: frame) || forceUpdates { - properties.opacity.update(frame: frame) - opacity = Float(properties.opacity.value.cgFloatValue) - } - - if properties.shape.needsUpdate(frame: frame) || forceUpdates { - properties.shape.update(frame: frame) - properties.expansion.update(frame: frame) - - let shapePath = properties.shape.value.cgPath() - var path = shapePath - if - properties.mode.usableMode == .subtract && !properties.inverted || - (properties.mode.usableMode == .add && properties.inverted) - { - /// Add a bounds rect to invert the mask - let newPath = CGMutablePath() - newPath.addRect(CGRect.veryLargeRect) - newPath.addPath(shapePath) - path = newPath - } - maskLayer.path = path - } - } -} - -// MARK: - MaskNodeProperties - -private class MaskNodeProperties: NodePropertyMap { - - // MARK: Lifecycle - - init(mask: Mask) { - mode = mask.mode - inverted = mask.inverted - opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: mask.opacity.keyframes)) - shape = NodeProperty(provider: KeyframeInterpolator(keyframes: mask.shape.keyframes)) - expansion = NodeProperty(provider: KeyframeInterpolator(keyframes: mask.expansion.keyframes)) - propertyMap = [ - PropertyName.opacity.rawValue : opacity, - "Shape" : shape, - "Expansion" : expansion, - ] - properties = Array(propertyMap.values) - } - - // MARK: Internal - - var propertyMap: [String: AnyNodeProperty] - - var properties: [AnyNodeProperty] - - let mode: MaskMode - let inverted: Bool - - let opacity: NodeProperty - let shape: NodeProperty - let expansion: NodeProperty -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/NullCompositionLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/NullCompositionLayer.swift deleted file mode 100644 index 3fdf163760618522289ad8dda69853364ce50932..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/NullCompositionLayer.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// NullCompositionLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -import Foundation - -final class NullCompositionLayer: CompositionLayer { - - init(layer: LayerModel) { - super.init(layer: layer, size: .zero) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override init(layer: Any) { - /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - guard let layer = layer as? NullCompositionLayer else { - fatalError("init(layer:) Wrong Layer Class") - } - super.init(layer: layer) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift deleted file mode 100644 index f17025e3e77b0ee8983023aacc44ca08a7940ad4..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +++ /dev/null @@ -1,133 +0,0 @@ -// -// PreCompositionLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -import QuartzCore - -final class PreCompositionLayer: CompositionLayer { - - // MARK: Lifecycle - - init( - precomp: PreCompLayerModel, - asset: PrecompAsset, - layerImageProvider: LayerImageProvider, - layerTextProvider: LayerTextProvider, - textProvider: AnimationKeypathTextProvider, - fontProvider: AnimationFontProvider, - assetLibrary: AssetLibrary?, - frameRate: CGFloat, - rootAnimationLayer: MainThreadAnimationLayer?) - { - animationLayers = [] - if let keyframes = precomp.timeRemapping?.keyframes { - remappingNode = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframes)) - } else { - remappingNode = nil - } - self.frameRate = frameRate - super.init(layer: precomp, size: CGSize(width: precomp.width, height: precomp.height)) - bounds = CGRect(origin: .zero, size: CGSize(width: precomp.width, height: precomp.height)) - contentsLayer.masksToBounds = true - contentsLayer.bounds = bounds - - let layers = asset.layers.initializeCompositionLayers( - assetLibrary: assetLibrary, - layerImageProvider: layerImageProvider, - layerTextProvider: layerTextProvider, - textProvider: textProvider, - fontProvider: fontProvider, - frameRate: frameRate, - rootAnimationLayer: rootAnimationLayer) - - var imageLayers = [ImageCompositionLayer]() - var textLayers = [TextCompositionLayer]() - - var mattedLayer: CompositionLayer? = nil - - for layer in layers.reversed() { - layer.bounds = bounds - animationLayers.append(layer) - if let imageLayer = layer as? ImageCompositionLayer { - imageLayers.append(imageLayer) - } - if let textLayer = layer as? TextCompositionLayer { - textLayers.append(textLayer) - } - if let matte = mattedLayer { - /// The previous layer requires this layer to be its matte - matte.matteLayer = layer - mattedLayer = nil - continue - } - if - let matte = layer.matteType, - matte == .add || matte == .invert - { - /// We have a layer that requires a matte. - mattedLayer = layer - } - contentsLayer.addSublayer(layer) - } - - childKeypaths.append(contentsOf: layers) - - layerImageProvider.addImageLayers(imageLayers) - layerTextProvider.addTextLayers(textLayers) - } - - override init(layer: Any) { - /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - guard let layer = layer as? PreCompositionLayer else { - fatalError("init(layer:) Wrong Layer Class") - } - frameRate = layer.frameRate - remappingNode = nil - animationLayers = [] - - super.init(layer: layer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - let frameRate: CGFloat - let remappingNode: NodeProperty? - - override var keypathProperties: [String: AnyNodeProperty] { - guard let remappingNode else { - return super.keypathProperties - } - return ["Time Remap" : remappingNode] - } - - override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) { - let localFrame: CGFloat - if let remappingNode { - remappingNode.update(frame: frame) - localFrame = remappingNode.value.cgFloatValue * frameRate - } else { - localFrame = (frame - startFrame) / timeStretch - } - for animationLayer in animationLayers { - animationLayer.displayWithFrame(frame: localFrame, forceUpdates: forceUpdates) - } - } - - override func updateRenderScale() { - super.updateRenderScale() - for animationLayer in animationLayers { - animationLayer.renderScale = renderScale - } - } - - // MARK: Fileprivate - - fileprivate var animationLayers: [CompositionLayer] -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/ShapeCompositionLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/ShapeCompositionLayer.swift deleted file mode 100644 index a10189f22979ae3725e7a7fc2d4b74802ee38843..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/ShapeCompositionLayer.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// ShapeLayerContainer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/22/19. -// - -import CoreGraphics -import Foundation - -/// A CompositionLayer responsible for initializing and rendering shapes -final class ShapeCompositionLayer: CompositionLayer { - - // MARK: Lifecycle - - init(shapeLayer: ShapeLayerModel) { - let results = shapeLayer.items.initializeNodeTree() - let renderContainer = ShapeContainerLayer() - self.renderContainer = renderContainer - rootNode = results.rootNode - super.init(layer: shapeLayer, size: .zero) - contentsLayer.addSublayer(renderContainer) - for container in results.renderContainers { - renderContainer.insertRenderLayer(container) - } - rootNode?.updateTree(0, forceUpdates: true) - childKeypaths.append(contentsOf: results.childrenNodes) - } - - override init(layer: Any) { - guard let layer = layer as? ShapeCompositionLayer else { - fatalError("init(layer:) wrong class.") - } - rootNode = nil - renderContainer = nil - super.init(layer: layer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - let rootNode: AnimatorNode? - let renderContainer: ShapeContainerLayer? - - override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) { - rootNode?.updateTree(frame, forceUpdates: forceUpdates) - renderContainer?.markRenderUpdates(forFrame: frame) - } - - override func updateRenderScale() { - super.updateRenderScale() - renderContainer?.renderScale = renderScale - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/SolidCompositionLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/SolidCompositionLayer.swift deleted file mode 100644 index 7902770b560e3eb2f0ff67883f5ef918d115f2a6..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/SolidCompositionLayer.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// SolidCompositionLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -import QuartzCore - -final class SolidCompositionLayer: CompositionLayer { - - // MARK: Lifecycle - - init(solid: SolidLayerModel) { - let components = solid.colorHex.hexColorComponents() - colorProperty = - NodeProperty(provider: SingleValueProvider(LottieColor( - r: Double(components.red), - g: Double(components.green), - b: Double(components.blue), - a: 1))) - - super.init(layer: solid, size: .zero) - solidShape.path = CGPath(rect: CGRect(x: 0, y: 0, width: solid.width, height: solid.height), transform: nil) - contentsLayer.addSublayer(solidShape) - } - - override init(layer: Any) { - /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - guard let layer = layer as? SolidCompositionLayer else { - fatalError("init(layer:) Wrong Layer Class") - } - colorProperty = layer.colorProperty - super.init(layer: layer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - let colorProperty: NodeProperty? - let solidShape = CAShapeLayer() - - override var keypathProperties: [String: AnyNodeProperty] { - guard let colorProperty else { return super.keypathProperties } - return [PropertyName.color.rawValue : colorProperty] - } - - override func displayContentsWithFrame(frame: CGFloat, forceUpdates _: Bool) { - guard let colorProperty else { return } - colorProperty.update(frame: frame) - solidShape.fillColor = colorProperty.value.cgColorValue - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift deleted file mode 100644 index f26a51cfce83754257dbb16ef44780640798b1cc..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift +++ /dev/null @@ -1,170 +0,0 @@ -// -// TextCompositionLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -/// Needed for NSMutableParagraphStyle... -#if os(OSX) -import AppKit -#else -import UIKit -#endif - -extension TextJustification { - var textAlignment: NSTextAlignment { - switch self { - case .left: - return .left - case .right: - return .right - case .center: - return .center - } - } - - var caTextAlignement: CATextLayerAlignmentMode { - switch self { - case .left: - return .left - case .right: - return .right - case .center: - return .center - } - } -} - -// MARK: - TextCompositionLayer - -final class TextCompositionLayer: CompositionLayer { - - // MARK: Lifecycle - - init( - textLayer: TextLayerModel, - textProvider: AnimationKeypathTextProvider, - fontProvider: AnimationFontProvider, - rootAnimationLayer: MainThreadAnimationLayer?) - { - var rootNode: TextAnimatorNode? - for animator in textLayer.animators { - rootNode = TextAnimatorNode(parentNode: rootNode, textAnimator: animator) - } - self.rootNode = rootNode - textDocument = KeyframeInterpolator(keyframes: textLayer.text.keyframes) - - self.textProvider = textProvider - self.fontProvider = fontProvider - self.rootAnimationLayer = rootAnimationLayer - - super.init(layer: textLayer, size: .zero) - contentsLayer.addSublayer(self.textLayer) - self.textLayer.masksToBounds = false - self.textLayer.isGeometryFlipped = true - - if let rootNode { - childKeypaths.append(rootNode) - } - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override init(layer: Any) { - /// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - guard let layer = layer as? TextCompositionLayer else { - fatalError("init(layer:) Wrong Layer Class") - } - rootNode = nil - textDocument = nil - - textProvider = DefaultTextProvider() - fontProvider = DefaultFontProvider() - - super.init(layer: layer) - } - - // MARK: Internal - - let rootNode: TextAnimatorNode? - let textDocument: KeyframeInterpolator? - - let textLayer = CoreTextRenderLayer() - var textProvider: AnimationKeypathTextProvider - var fontProvider: AnimationFontProvider - weak var rootAnimationLayer: MainThreadAnimationLayer? - - lazy var fullAnimationKeypath: AnimationKeypath = // Individual layers don't know their full keypaths, so we have to delegate - // to the `MainThreadAnimationLayer` to search the layer hierarchy and find - // the full keypath (which includes this layer's parent layers) - rootAnimationLayer?.keypath(for: self) - // If that failed for some reason, just use the last path component (which we do have here) - ?? AnimationKeypath(keypath: keypathName) - - override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) { - guard let textDocument else { return } - - textLayer.contentsScale = renderScale - - let documentUpdate = textDocument.hasUpdate(frame: frame) - let animatorUpdate = rootNode?.updateContents(frame, forceLocalUpdate: forceUpdates) ?? false - guard documentUpdate == true || animatorUpdate == true else { return } - - rootNode?.rebuildOutputs(frame: frame) - - // Get Text Attributes - let text = textDocument.value(frame: frame) as! TextDocument - - // Prior to Lottie 4.3.0 the Main Thread rendering engine always just used `LegacyAnimationTextProvider` - // and called it with the `keypathName` (only the last path component of the full keypath). - // Starting in Lottie 4.3.0 we use `AnimationKeypathTextProvider` instead if implemented. - let textString: String - if let keypathTextValue = textProvider.text(for: fullAnimationKeypath, sourceText: text.text) { - textString = keypathTextValue - } else if let legacyTextProvider = textProvider as? LegacyAnimationTextProvider { - textString = legacyTextProvider.textFor(keypathName: keypathName, sourceText: text.text) - } else { - textString = text.text - } - - let strokeColor = rootNode?.textOutputNode.strokeColor ?? text.strokeColorData?.cgColorValue - let strokeWidth = rootNode?.textOutputNode.strokeWidth ?? CGFloat(text.strokeWidth ?? 0) - let tracking = (CGFloat(text.fontSize) * (rootNode?.textOutputNode.tracking ?? CGFloat(text.tracking))) / 1000.0 - let matrix = rootNode?.textOutputNode.xform ?? CATransform3DIdentity - let ctFont = fontProvider.fontFor(family: text.fontFamily, size: CGFloat(text.fontSize)) - - // Set all of the text layer options - textLayer.text = textString - textLayer.font = ctFont - textLayer.alignment = text.justification.textAlignment - textLayer.lineHeight = CGFloat(text.lineHeight) - textLayer.tracking = tracking - - if let fillColor = rootNode?.textOutputNode.fillColor { - textLayer.fillColor = fillColor - } else if let fillColor = text.fillColorData?.cgColorValue { - textLayer.fillColor = fillColor - } else { - textLayer.fillColor = nil - } - - textLayer.preferredSize = text.textFrameSize?.sizeValue - textLayer.strokeOnTop = text.strokeOverFill ?? false - textLayer.strokeWidth = strokeWidth - textLayer.strokeColor = strokeColor - textLayer.sizeToFit() - - textLayer.opacity = Float(rootNode?.textOutputNode.opacity ?? 1) - textLayer.transform = CATransform3DIdentity - textLayer.position = text.textFramePosition?.pointValue ?? CGPoint.zero - textLayer.transform = matrix - } - - override func updateRenderScale() { - super.updateRenderScale() - textLayer.contentsScale = renderScale - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift deleted file mode 100644 index c62b53c4b967f6cc766111c54a9b0ed0f185cf3b..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +++ /dev/null @@ -1,312 +0,0 @@ -// -// MainThreadAnimationLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/24/19. -// - -import QuartzCore - -// MARK: - MainThreadAnimationLayer - -/// The base `CALayer` for the Main Thread rendering engine -/// -/// This layer holds a single composition container and allows for animation of -/// the currentFrame property. -final class MainThreadAnimationLayer: CALayer, RootAnimationLayer { - - // MARK: Lifecycle - - init( - animation: LottieAnimation, - imageProvider: AnimationImageProvider, - textProvider: AnimationKeypathTextProvider, - fontProvider: AnimationFontProvider, - maskAnimationToBounds: Bool, - logger: LottieLogger) - { - layerImageProvider = LayerImageProvider(imageProvider: imageProvider, assets: animation.assetLibrary?.imageAssets) - layerTextProvider = LayerTextProvider(textProvider: textProvider) - layerFontProvider = LayerFontProvider(fontProvider: fontProvider) - animationLayers = [] - self.logger = logger - super.init() - masksToBounds = maskAnimationToBounds - bounds = animation.bounds - let layers = animation.layers.initializeCompositionLayers( - assetLibrary: animation.assetLibrary, - layerImageProvider: layerImageProvider, - layerTextProvider: layerTextProvider, - textProvider: textProvider, - fontProvider: fontProvider, - frameRate: CGFloat(animation.framerate), - rootAnimationLayer: self) - - var imageLayers = [ImageCompositionLayer]() - var textLayers = [TextCompositionLayer]() - - var mattedLayer: CompositionLayer? = nil - - for layer in layers.reversed() { - layer.bounds = bounds - animationLayers.append(layer) - if let imageLayer = layer as? ImageCompositionLayer { - imageLayers.append(imageLayer) - } - if let textLayer = layer as? TextCompositionLayer { - textLayers.append(textLayer) - } - if let matte = mattedLayer { - /// The previous layer requires this layer to be its matte - matte.matteLayer = layer - mattedLayer = nil - continue - } - if - let matte = layer.matteType, - matte == .add || matte == .invert - { - /// We have a layer that requires a matte. - mattedLayer = layer - } - addSublayer(layer) - } - - layerImageProvider.addImageLayers(imageLayers) - layerImageProvider.reloadImages() - layerTextProvider.addTextLayers(textLayers) - layerTextProvider.reloadTexts() - layerFontProvider.addTextLayers(textLayers) - layerFontProvider.reloadTexts() - setNeedsDisplay() - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - animationLayers = [] - layerImageProvider = LayerImageProvider(imageProvider: BlankImageProvider(), assets: nil) - layerTextProvider = LayerTextProvider(textProvider: DefaultTextProvider()) - layerFontProvider = LayerFontProvider(fontProvider: DefaultFontProvider()) - logger = typedLayer.logger - super.init(layer: layer) - - currentFrame = typedLayer.currentFrame - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Public - - public var respectAnimationFrameRate = false - - // MARK: CALayer Animations - - override public class func needsDisplay(forKey key: String) -> Bool { - if key == "currentFrame" { - return true - } - return super.needsDisplay(forKey: key) - } - - override public func action(forKey event: String) -> CAAction? { - if event == "currentFrame" { - let animation = CABasicAnimation(keyPath: event) - animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) - animation.fromValue = presentation()?.currentFrame - return animation - } - return super.action(forKey: event) - } - - public override func display() { - guard Thread.isMainThread else { return } - var newFrame: CGFloat - if - let animationKeys = animationKeys(), - !animationKeys.isEmpty - { - newFrame = presentation()?.currentFrame ?? currentFrame - } else { - // We ignore the presentation's frame if there's no animation in the layer. - newFrame = currentFrame - } - if respectAnimationFrameRate { - newFrame = floor(newFrame) - } - for animationLayer in animationLayers { - animationLayer.displayWithFrame(frame: newFrame, forceUpdates: forceDisplayUpdateOnEachFrame) - } - } - - // MARK: Internal - - /// The animatable Current Frame Property - @NSManaged var currentFrame: CGFloat - - /// The parent `LottieAnimationLayer` that manages this layer - weak var lottieAnimationLayer: LottieAnimationLayer? - - /// Whether or not to use `forceDisplayUpdate()` when rendering each individual frame. - /// - The main thread rendering engine implements optimizations to decrease the amount - /// of properties that have to be re-rendered on each frame. There are some cases - /// where this can result in bugs / incorrect behavior, so we allow it to be disabled. - /// - Forcing a full render on every frame will decrease performance, and is not recommended - /// except as a workaround to a bug in the main thread rendering engine. - var forceDisplayUpdateOnEachFrame = false - - var animationLayers: ContiguousArray - - var primaryAnimationKey: AnimationKey { - .managed - } - - var isAnimationPlaying: Bool? { - nil // this state is managed by `LottieAnimationView` - } - - var _animationLayers: [CALayer] { - Array(animationLayers) - } - - var imageProvider: AnimationImageProvider { - get { - layerImageProvider.imageProvider - } - set { - layerImageProvider.imageProvider = newValue - } - } - - var renderScale: CGFloat = 1 { - didSet { - for animationLayer in animationLayers { - animationLayer.renderScale = renderScale - } - } - } - - var textProvider: AnimationKeypathTextProvider { - get { layerTextProvider.textProvider } - set { layerTextProvider.textProvider = newValue } - } - - var fontProvider: AnimationFontProvider { - get { layerFontProvider.fontProvider } - set { layerFontProvider.fontProvider = newValue } - } - - func reloadImages() { - layerImageProvider.reloadImages() - } - - func removeAnimations() { - // no-op, since the primary animation is managed by the `LottieAnimationView`. - } - - /// Forces the view to update its drawing. - func forceDisplayUpdate() { - for animationLayer in animationLayers { - animationLayer.displayWithFrame(frame: currentFrame, forceUpdates: true) - } - } - - func logHierarchyKeypaths() { - logger.info("Lottie: Logging Animation Keypaths") - - for keypath in allHierarchyKeypaths() { - logger.info(keypath) - } - } - - func allHierarchyKeypaths() -> [String] { - animationLayers.flatMap { $0.allKeypaths() } - } - - func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) { - for layer in animationLayers { - if let foundProperties = layer.nodeProperties(for: keypath) { - for property in foundProperties { - property.setProvider(provider: valueProvider) - } - layer.displayWithFrame(frame: presentation()?.currentFrame ?? currentFrame, forceUpdates: true) - } - } - } - - func getValue(for keypath: AnimationKeypath, atFrame: CGFloat?) -> Any? { - for layer in animationLayers { - if - let foundProperties = layer.nodeProperties(for: keypath), - let first = foundProperties.first - { - return first.valueProvider.value(frame: atFrame ?? currentFrame) - } - } - return nil - } - - func getOriginalValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? { - for layer in animationLayers { - if - let foundProperties = layer.nodeProperties(for: keypath), - let first = foundProperties.first - { - return first.originalValueProvider.value(frame: atFrame ?? currentFrame) - } - } - return nil - } - - func layer(for keypath: AnimationKeypath) -> CALayer? { - for layer in animationLayers { - if let foundLayer = layer.layer(for: keypath) { - return foundLayer - } - } - return nil - } - - func keypath(for layerToFind: CALayer) -> AnimationKeypath? { - for layer in animationLayers { - if let foundKeypath = layer.keypath(for: layerToFind) { - return foundKeypath - } - } - return nil - } - - func animatorNodes(for keypath: AnimationKeypath) -> [AnimatorNode]? { - var results = [AnimatorNode]() - for layer in animationLayers { - if let nodes = layer.animatorNodes(for: keypath) { - results.append(contentsOf: nodes) - } - } - if results.count == 0 { - return nil - } - return results - } - - // MARK: Fileprivate - - fileprivate let layerImageProvider: LayerImageProvider - fileprivate let layerTextProvider: LayerTextProvider - fileprivate let layerFontProvider: LayerFontProvider - fileprivate let logger: LottieLogger -} - -// MARK: - BlankImageProvider - -private class BlankImageProvider: AnimationImageProvider { - func imageForAsset(asset _: ImageAsset) -> CGImage? { - nil - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/CachedImageProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/CachedImageProvider.swift deleted file mode 100644 index 068f3aa7951f29d64fef2d6abf4bc71c0c069b5e..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/CachedImageProvider.swift +++ /dev/null @@ -1,58 +0,0 @@ -// Created by Jianjun Wu on 2022/5/12. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - CachedImageProvider - -private final class CachedImageProvider: AnimationImageProvider { - - // MARK: Lifecycle - - /// Initializes an image provider with an image provider - /// - /// - Parameter imageProvider: The provider to load image from asset - /// - public init(imageProvider: AnimationImageProvider) { - self.imageProvider = imageProvider - } - - // MARK: Public - - public func imageForAsset(asset: ImageAsset) -> CGImage? { - if let image = imageCache.value(forKey: asset.id) { - return image - } - if let image = imageProvider.imageForAsset(asset: asset) { - imageCache.setValue(image, forKey: asset.id) - return image - } - return nil - } - - // MARK: Internal - - func contentsGravity(for asset: ImageAsset) -> CALayerContentsGravity { - imageProvider.contentsGravity(for: asset) - } - - // MARK: Private - - /// The underlying storage of this cache. - /// - We use the `LRUCache` library instead of `NSCache`, because `NSCache` - /// clears all cached values when the app is backgrounded instead of - /// only when the app receives a memory warning notification. - private var imageCache = LRUCache() - private let imageProvider: AnimationImageProvider - -} - -extension AnimationImageProvider { - /// Create a cache enabled image provider which will reuse the asset image with the same asset id - /// It wraps the current provider as image loader, and uses `NSCache` to cache the images for resue. - /// The cache will be reset when the `animation` is reset. - var cachedImageProvider: AnimationImageProvider { - guard cacheEligible else { return self } - return CachedImageProvider(imageProvider: self) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/CompositionLayersInitializer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/CompositionLayersInitializer.swift deleted file mode 100644 index f95efbe31eca60f6c252e55d948ba6e18eea5f7c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/CompositionLayersInitializer.swift +++ /dev/null @@ -1,99 +0,0 @@ -// -// CompositionLayersInitializer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -import CoreGraphics -import Foundation - -extension [LayerModel] { - - func initializeCompositionLayers( - assetLibrary: AssetLibrary?, - layerImageProvider: LayerImageProvider, - layerTextProvider: LayerTextProvider, - textProvider: AnimationKeypathTextProvider, - fontProvider: AnimationFontProvider, - frameRate: CGFloat, - rootAnimationLayer: MainThreadAnimationLayer?) - -> [CompositionLayer] - { - var compositionLayers = [CompositionLayer]() - var layerMap = [Int : CompositionLayer]() - - /// Organize the assets into a dictionary of [ID : ImageAsset] - var childLayers = [LayerModel]() - - for layer in self { - if layer.hidden == true { - let genericLayer = NullCompositionLayer(layer: layer) - compositionLayers.append(genericLayer) - layerMap[layer.index] = genericLayer - } else if let shapeLayer = layer as? ShapeLayerModel { - let shapeContainer = ShapeCompositionLayer(shapeLayer: shapeLayer) - compositionLayers.append(shapeContainer) - layerMap[layer.index] = shapeContainer - } else if let solidLayer = layer as? SolidLayerModel { - let solidContainer = SolidCompositionLayer(solid: solidLayer) - compositionLayers.append(solidContainer) - layerMap[layer.index] = solidContainer - } else if - let precompLayer = layer as? PreCompLayerModel, - let assetLibrary, - let precompAsset = assetLibrary.precompAssets[precompLayer.referenceID] - { - let precompContainer = PreCompositionLayer( - precomp: precompLayer, - asset: precompAsset, - layerImageProvider: layerImageProvider, - layerTextProvider: layerTextProvider, - textProvider: textProvider, - fontProvider: fontProvider, - assetLibrary: assetLibrary, - frameRate: frameRate, - rootAnimationLayer: rootAnimationLayer) - compositionLayers.append(precompContainer) - layerMap[layer.index] = precompContainer - } else if - let imageLayer = layer as? ImageLayerModel, - let assetLibrary, - let imageAsset = assetLibrary.imageAssets[imageLayer.referenceID] - { - let imageContainer = ImageCompositionLayer( - imageLayer: imageLayer, - size: CGSize(width: imageAsset.width, height: imageAsset.height)) - compositionLayers.append(imageContainer) - layerMap[layer.index] = imageContainer - } else if let textLayer = layer as? TextLayerModel { - let textContainer = TextCompositionLayer( - textLayer: textLayer, - textProvider: textProvider, - fontProvider: fontProvider, - rootAnimationLayer: rootAnimationLayer) - compositionLayers.append(textContainer) - layerMap[layer.index] = textContainer - } else { - let genericLayer = NullCompositionLayer(layer: layer) - compositionLayers.append(genericLayer) - layerMap[layer.index] = genericLayer - } - if layer.parent != nil { - childLayers.append(layer) - } - } - - /// Now link children with their parents - for layerModel in childLayers { - if let parentID = layerModel.parent { - let childLayer = layerMap[layerModel.index] - let parentLayer = layerMap[parentID] - childLayer?.transformNode.parentNode = parentLayer?.transformNode - } - } - - return compositionLayers - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift deleted file mode 100644 index db621fff6eaef6c3063288b30172af27cab6cf16..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift +++ /dev/null @@ -1,349 +0,0 @@ -// -// TextLayer.swift -// Pods -// -// Created by Brandon Withrow on 8/3/20. -// - -import CoreGraphics -import CoreText -import Foundation -import QuartzCore -/// Needed for NSMutableParagraphStyle... -#if os(OSX) -import AppKit -#else -import UIKit -#endif - -// MARK: - CoreTextRenderLayer - -/// A CALayer subclass that renders text content using CoreText -final class CoreTextRenderLayer: CALayer { - - // MARK: Public - - public var text: String? { - didSet { - needsContentUpdate = true - setNeedsLayout() - setNeedsDisplay() - } - } - - public var font: CTFont? { - didSet { - needsContentUpdate = true - setNeedsLayout() - setNeedsDisplay() - } - } - - public var alignment: NSTextAlignment = .left { - didSet { - needsContentUpdate = true - setNeedsLayout() - setNeedsDisplay() - } - } - - public var lineHeight: CGFloat = 0 { - didSet { - needsContentUpdate = true - setNeedsLayout() - setNeedsDisplay() - } - } - - public var tracking: CGFloat = 0 { - didSet { - needsContentUpdate = true - setNeedsLayout() - setNeedsDisplay() - } - } - - public var fillColor: CGColor? { - didSet { - needsContentUpdate = true - setNeedsLayout() - setNeedsDisplay() - } - } - - public var strokeColor: CGColor? { - didSet { - needsContentUpdate = true - setNeedsLayout() - setNeedsDisplay() - } - } - - public var strokeWidth: CGFloat = 0 { - didSet { - needsContentUpdate = true - setNeedsLayout() - setNeedsDisplay() - } - } - - public var strokeOnTop = false { - didSet { - setNeedsLayout() - setNeedsDisplay() - } - } - - public var preferredSize: CGSize? { - didSet { - needsContentUpdate = true - setNeedsLayout() - setNeedsDisplay() - } - } - - public func sizeToFit() { - updateTextContent() - bounds = drawingRect - anchorPoint = drawingAnchor - setNeedsLayout() - setNeedsDisplay() - } - - // MARK: Internal - - override func action(forKey _: String) -> CAAction? { - nil - } - - override func draw(in ctx: CGContext) { - guard let attributedString else { return } - updateTextContent() - guard fillFrameSetter != nil || strokeFrameSetter != nil else { return } - - ctx.textMatrix = .identity - ctx.setAllowsAntialiasing(true) - ctx.setAllowsFontSubpixelPositioning(true) - ctx.setAllowsFontSubpixelQuantization(true) - - ctx.setShouldAntialias(true) - ctx.setShouldSubpixelPositionFonts(true) - ctx.setShouldSubpixelQuantizeFonts(true) - - if contentsAreFlipped() { - ctx.translateBy(x: 0, y: drawingRect.height) - ctx.scaleBy(x: 1.0, y: -1.0) - } - - let drawingPath = CGPath(rect: drawingRect, transform: nil) - - let fillFrame: CTFrame? - if let setter = fillFrameSetter { - fillFrame = CTFramesetterCreateFrame(setter, CFRangeMake(0, attributedString.length), drawingPath, nil) - } else { - fillFrame = nil - } - - let strokeFrame: CTFrame? - if let setter = strokeFrameSetter { - strokeFrame = CTFramesetterCreateFrame(setter, CFRangeMake(0, attributedString.length), drawingPath, nil) - } else { - strokeFrame = nil - } - - // This fixes a vertical padding issue that arises when drawing some fonts. - // For some reason some fonts, such as Helvetica draw with and ascender that is greater than the one reported by CTFontGetAscender. - // I suspect this is actually an issue with the Attributed string, but cannot reproduce. - - if let fillFrame { - ctx.adjustWithLineOrigins(in: fillFrame, with: font) - } else if let strokeFrame { - ctx.adjustWithLineOrigins(in: strokeFrame, with: font) - } - - if !strokeOnTop, let strokeFrame { - CTFrameDraw(strokeFrame, ctx) - } - - if let fillFrame { - CTFrameDraw(fillFrame, ctx) - } - - if strokeOnTop, let strokeFrame { - CTFrameDraw(strokeFrame, ctx) - } - } - - // MARK: Private - - private var drawingRect: CGRect = .zero - private var drawingAnchor: CGPoint = .zero - private var fillFrameSetter: CTFramesetter? - private var attributedString: NSAttributedString? - private var strokeFrameSetter: CTFramesetter? - private var needsContentUpdate = false - - // Draws Debug colors for the font alignment. - @available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *) - private func drawDebug(_ ctx: CGContext) { - if let font { - let ascent = CTFontGetAscent(font) - let descent = CTFontGetDescent(font) - let capHeight = CTFontGetCapHeight(font) - let leading = CTFontGetLeading(font) - - // Ascent Red - ctx.setFillColor(CGColor(srgbRed: 1, green: 0, blue: 0, alpha: 0.5)) - ctx.fill(CGRect(x: 0, y: 0, width: drawingRect.width, height: ascent)) - - // Descent Blue - ctx.setFillColor(CGColor(srgbRed: 0, green: 0, blue: 1, alpha: 0.5)) - ctx.fill(CGRect(x: 0, y: ascent, width: drawingRect.width, height: descent)) - - // Leading Yellow - ctx.setFillColor(CGColor(srgbRed: 1, green: 1, blue: 0, alpha: 0.5)) - ctx.fill(CGRect(x: 0, y: ascent + descent, width: drawingRect.width, height: leading)) - - // Cap height Green - ctx.setFillColor(CGColor(srgbRed: 0, green: 1, blue: 0, alpha: 0.5)) - ctx.fill(CGRect(x: 0, y: ascent - capHeight, width: drawingRect.width, height: capHeight)) - - if drawingRect.height - ascent + descent + leading > 0 { - // Remainder - ctx.setFillColor(CGColor(srgbRed: 0, green: 1, blue: 1, alpha: 0.5)) - ctx - .fill(CGRect( - x: 0, - y: ascent + descent + leading, - width: drawingRect.width, - height: drawingRect.height - ascent + descent + leading)) - } - } - } - - private func updateTextContent() { - guard needsContentUpdate else { return } - needsContentUpdate = false - guard let font, let text, text.count > 0, fillColor != nil || strokeColor != nil else { - drawingRect = .zero - drawingAnchor = .zero - attributedString = nil - fillFrameSetter = nil - strokeFrameSetter = nil - return - } - - // Get Font properties - let ascent = CTFontGetAscent(font) - let descent = CTFontGetDescent(font) - let capHeight = CTFontGetCapHeight(font) - let leading = CTFontGetLeading(font) - let minLineHeight = -(ascent + descent + leading) - - // Calculate line spacing - let lineSpacing = max(CGFloat(minLineHeight) + lineHeight, CGFloat(minLineHeight)) - // Build Attributes - let paragraphStyle = NSMutableParagraphStyle() - paragraphStyle.lineSpacing = lineSpacing - paragraphStyle.lineHeightMultiple = 1 - paragraphStyle.maximumLineHeight = ascent + descent + leading - paragraphStyle.alignment = alignment - paragraphStyle.lineBreakMode = NSLineBreakMode.byWordWrapping - var attributes: [NSAttributedString.Key: Any] = [ - NSAttributedString.Key.ligature: 0, - NSAttributedString.Key.font: font, - NSAttributedString.Key.kern: tracking, - NSAttributedString.Key.paragraphStyle: paragraphStyle, - ] - - if let fillColor { - attributes[NSAttributedString.Key.foregroundColor] = fillColor - } - - let attrString = NSAttributedString(string: text, attributes: attributes) - attributedString = attrString - - if fillColor != nil { - let setter = CTFramesetterCreateWithAttributedString(attrString as CFAttributedString) - fillFrameSetter = setter - } else { - fillFrameSetter = nil - } - - if let strokeColor { - attributes[NSAttributedString.Key.foregroundColor] = nil - attributes[NSAttributedString.Key.strokeWidth] = strokeWidth - attributes[NSAttributedString.Key.strokeColor] = strokeColor - let strokeAttributedString = NSAttributedString(string: text, attributes: attributes) - strokeFrameSetter = CTFramesetterCreateWithAttributedString(strokeAttributedString as CFAttributedString) - } else { - strokeFrameSetter = nil - strokeWidth = 0 - } - - guard let setter = fillFrameSetter ?? strokeFrameSetter else { - return - } - - // Calculate drawing size and anchor offset - let textAnchor: CGPoint - if let preferredSize { - drawingRect = CGRect(origin: .zero, size: preferredSize) - drawingRect.size.height += (ascent - capHeight) - drawingRect.size.height += descent - textAnchor = CGPoint(x: 0, y: ascent - capHeight) - } else { - let size = CTFramesetterSuggestFrameSizeWithConstraints( - setter, - CFRange(location: 0, length: attrString.length), - nil, - CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), - nil) - switch alignment { - case .left: - textAnchor = CGPoint(x: 0, y: ascent) - case .right: - textAnchor = CGPoint(x: size.width, y: ascent) - case .center: - textAnchor = CGPoint(x: size.width * 0.5, y: ascent) - default: - textAnchor = .zero - } - drawingRect = CGRect( - x: 0, - y: 0, - width: ceil(size.width), - height: ceil(size.height)) - } - - // Now Calculate Anchor - drawingAnchor = CGPoint( - x: textAnchor.x.remap(fromLow: 0, fromHigh: drawingRect.size.width, toLow: 0, toHigh: 1), - y: textAnchor.y.remap(fromLow: 0, fromHigh: drawingRect.size.height, toLow: 0, toHigh: 1)) - - if fillFrameSetter != nil, strokeFrameSetter != nil { - drawingRect.size.width += strokeWidth - drawingRect.size.height += strokeWidth - } - } - -} - -extension CGContext { - - fileprivate func adjustWithLineOrigins(in frame: CTFrame, with font: CTFont?) { - guard let font else { return } - - let count = CFArrayGetCount(CTFrameGetLines(frame)) - - guard count > 0 else { return } - - var o = [CGPoint](repeating: .zero, count: 1) - CTFrameGetLineOrigins(frame, CFRange(location: count - 1, length: 1), &o) - - let diff = CTFontGetDescent(font) - o[0].y - if diff > 0 { - translateBy(x: 0, y: diff) - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift deleted file mode 100644 index c96277c1a24a38099772455fc73da32bce24fe0d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// InvertedMatteLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/28/19. -// - -import QuartzCore - -/// A layer that inverses the alpha output of its input layer. -/// -/// WARNING: This is experimental and probably not very performant. -final class InvertedMatteLayer: CALayer, CompositionLayerDelegate { - - // MARK: Lifecycle - - init(inputMatte: CompositionLayer) { - self.inputMatte = inputMatte - super.init() - inputMatte.layerDelegate = self - anchorPoint = .zero - bounds = inputMatte.bounds - setNeedsDisplay() - } - - override init(layer: Any) { - guard let layer = layer as? InvertedMatteLayer else { - fatalError("init(layer:) wrong class.") - } - inputMatte = nil - super.init(layer: layer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - let inputMatte: CompositionLayer? - - func frameUpdated(frame _: CGFloat) { - setNeedsDisplay() - displayIfNeeded() - } - - override func draw(in ctx: CGContext) { - guard let inputMatte else { return } - ctx.setFillColor(.rgb(0, 0, 0)) - ctx.fill(bounds) - ctx.setBlendMode(.destinationOut) - inputMatte.render(in: ctx) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerFontProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerFontProvider.swift deleted file mode 100644 index e054ce254f82ae2e785e47888186c3b857884e61..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerFontProvider.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// LayerFontProvider.swift -// Lottie -// -// Created by Brandon Withrow on 8/5/20. -// Copyright © 2020 YurtvilleProds. All rights reserved. -// - -/// Connects a LottieFontProvider to a group of text layers -final class LayerFontProvider { - - // MARK: Lifecycle - - init(fontProvider: AnimationFontProvider) { - self.fontProvider = fontProvider - textLayers = [] - reloadTexts() - } - - // MARK: Internal - - private(set) var textLayers: [TextCompositionLayer] - - var fontProvider: AnimationFontProvider { - didSet { - reloadTexts() - } - } - - func addTextLayers(_ layers: [TextCompositionLayer]) { - textLayers += layers - } - - func reloadTexts() { - for textLayer in textLayers { - textLayer.fontProvider = fontProvider - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerImageProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerImageProvider.swift deleted file mode 100644 index db531f85c0525fa0cca3177397e202e324ea39ce..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerImageProvider.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// LayerImageProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -/// Connects a LottieImageProvider to a group of image layers -final class LayerImageProvider { - - // MARK: Lifecycle - - init(imageProvider: AnimationImageProvider, assets: [String: ImageAsset]?) { - self.imageProvider = imageProvider - imageLayers = [ImageCompositionLayer]() - if let assets { - imageAssets = assets - } else { - imageAssets = [:] - } - reloadImages() - } - - // MARK: Internal - - private(set) var imageLayers: [ImageCompositionLayer] - let imageAssets: [String: ImageAsset] - - var imageProvider: AnimationImageProvider { - didSet { - reloadImages() - } - } - - func addImageLayers(_ layers: [ImageCompositionLayer]) { - for layer in layers { - if imageAssets[layer.imageReferenceID] != nil { - /// Found a linking asset in our asset library. Add layer - imageLayers.append(layer) - } - } - } - - func reloadImages() { - for imageLayer in imageLayers { - if let asset = imageAssets[imageLayer.imageReferenceID] { - imageLayer.image = imageProvider.imageForAsset(asset: asset) - imageLayer.imageContentsGravity = imageProvider.contentsGravity(for: asset) - } - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerTextProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerTextProvider.swift deleted file mode 100644 index 365ab26ab1dceb7306a75c795c40828f5ddacae2..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerTextProvider.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// LayerTextProvider.swift -// lottie-ios-iOS -// -// Created by Alexandr Goncharov on 07/06/2019. -// - -/// Connects a LottieTextProvider to a group of text layers -final class LayerTextProvider { - - // MARK: Lifecycle - - init(textProvider: AnimationKeypathTextProvider) { - self.textProvider = textProvider - textLayers = [] - reloadTexts() - } - - // MARK: Internal - - private(set) var textLayers: [TextCompositionLayer] - - var textProvider: AnimationKeypathTextProvider { - didSet { - reloadTexts() - } - } - - func addTextLayers(_ layers: [TextCompositionLayer]) { - textLayers += layers - } - - func reloadTexts() { - for textLayer in textLayers { - textLayer.textProvider = textProvider - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift deleted file mode 100644 index 7ef739afe8eb736eba62d0fa15036164f722b614..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +++ /dev/null @@ -1,150 +0,0 @@ -// -// LayerTransformPropertyMap.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -import QuartzCore - -// MARK: - LayerTransformProperties - -final class LayerTransformProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(transform: Transform) { - anchor = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.anchorPoint.keyframes)) - scale = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.scale.keyframes)) - rotationX = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotationX.keyframes)) - rotationY = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotationY.keyframes)) - rotationZ = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotationZ.keyframes)) - opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.opacity.keyframes)) - - var propertyMap: [String: AnyNodeProperty] = [ - "Anchor Point" : anchor, - PropertyName.scale.rawValue : scale, - PropertyName.rotation.rawValue: rotationZ, - "Rotation X" : rotationX, - "Rotation Y" : rotationY, - "Rotation Z" : rotationZ, - PropertyName.opacity.rawValue : opacity, - ] - - if - let positionKeyframesX = transform.positionX?.keyframes, - let positionKeyframesY = transform.positionY?.keyframes - { - let xPosition: NodeProperty = NodeProperty(provider: KeyframeInterpolator(keyframes: positionKeyframesX)) - let yPosition: NodeProperty = NodeProperty(provider: KeyframeInterpolator(keyframes: positionKeyframesY)) - propertyMap["X Position"] = xPosition - propertyMap["Y Position"] = yPosition - positionX = xPosition - positionY = yPosition - position = nil - } else if let positionKeyframes = transform.position?.keyframes { - let position: NodeProperty = NodeProperty(provider: KeyframeInterpolator(keyframes: positionKeyframes)) - propertyMap[PropertyName.position.rawValue] = position - self.position = position - positionX = nil - positionY = nil - } else { - position = nil - positionY = nil - positionX = nil - } - - keypathProperties = propertyMap - properties = Array(propertyMap.values) - } - - // MARK: Internal - - let keypathProperties: [String: AnyNodeProperty] - var keypathName = "Transform" - - let properties: [AnyNodeProperty] - - let anchor: NodeProperty - let scale: NodeProperty - let rotationX: NodeProperty - let rotationY: NodeProperty - let rotationZ: NodeProperty - let position: NodeProperty? - let positionX: NodeProperty? - let positionY: NodeProperty? - let opacity: NodeProperty - - var childKeypaths: [KeypathSearchable] { - [] - } -} - -// MARK: - LayerTransformNode - -class LayerTransformNode: AnimatorNode { - - // MARK: Lifecycle - - init(transform: Transform) { - transformProperties = LayerTransformProperties(transform: transform) - } - - // MARK: Internal - - let outputNode: NodeOutput = PassThroughOutputNode(parent: nil) - - let transformProperties: LayerTransformProperties - - var parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - var isEnabled = true - - var opacity: Float = 1 - var localTransform: CATransform3D = CATransform3DIdentity - var globalTransform: CATransform3D = CATransform3DIdentity - - // MARK: Animator Node Protocol - - var propertyMap: NodePropertyMap & KeypathSearchable { - transformProperties - } - - func shouldRebuildOutputs(frame _: CGFloat) -> Bool { - hasLocalUpdates || hasUpstreamUpdates - } - - func rebuildOutputs(frame _: CGFloat) { - opacity = Float(transformProperties.opacity.value.cgFloatValue) * 0.01 - - let position: CGPoint - if let point = transformProperties.position?.value.pointValue { - position = point - } else if - let xPos = transformProperties.positionX?.value.cgFloatValue, - let yPos = transformProperties.positionY?.value.cgFloatValue - { - position = CGPoint(x: xPos, y: yPos) - } else { - position = .zero - } - - localTransform = CATransform3D.makeTransform( - anchor: transformProperties.anchor.value.pointValue, - position: position, - scale: transformProperties.scale.value.sizeValue, - rotationX: transformProperties.rotationX.value.cgFloatValue, - rotationY: transformProperties.rotationY.value.cgFloatValue, - rotationZ: transformProperties.rotationZ.value.cgFloatValue, - skew: nil, - skewAxis: nil) - - if let parentNode = parentNode as? LayerTransformNode { - globalTransform = CATransform3DConcat(localTransform, parentNode.globalTransform) - } else { - globalTransform = localTransform - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift deleted file mode 100644 index 24f7930be2885ec5b190299ec8cbf2d1fae40dc9..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +++ /dev/null @@ -1,105 +0,0 @@ -// -// ItemsExtension.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/18/19. -// - -// MARK: - NodeTree - -final class NodeTree { - var rootNode: AnimatorNode? = nil - var transform: ShapeTransform? = nil - var renderContainers: [ShapeContainerLayer] = [] - var paths: [PathOutputNode] = [] - var childrenNodes: [AnimatorNode] = [] -} - -extension [ShapeItem] { - func initializeNodeTree() -> NodeTree { - let nodeTree = NodeTree() - - for item in self { - guard item.hidden == false, item.type != .unknown else { continue } - if let fill = item as? Fill { - let node = FillNode(parentNode: nodeTree.rootNode, fill: fill) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } else if let stroke = item as? Stroke { - let node = StrokeNode(parentNode: nodeTree.rootNode, stroke: stroke) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } else if let gradientFill = item as? GradientFill { - let node = GradientFillNode(parentNode: nodeTree.rootNode, gradientFill: gradientFill) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } else if let gradientStroke = item as? GradientStroke { - let node = GradientStrokeNode(parentNode: nodeTree.rootNode, gradientStroke: gradientStroke) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } else if let ellipse = item as? Ellipse { - let node = EllipseNode(parentNode: nodeTree.rootNode, ellipse: ellipse) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } else if let rect = item as? Rectangle { - let node = RectangleNode(parentNode: nodeTree.rootNode, rectangle: rect) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } else if let star = item as? Star { - switch star.starType { - case .none: - continue - case .polygon: - let node = PolygonNode(parentNode: nodeTree.rootNode, star: star) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - case .star: - let node = StarNode(parentNode: nodeTree.rootNode, star: star) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } - } else if let shape = item as? Shape { - let node = ShapeNode(parentNode: nodeTree.rootNode, shape: shape) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } else if let trim = item as? Trim { - let node = TrimPathNode(parentNode: nodeTree.rootNode, trim: trim, upstreamPaths: nodeTree.paths) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } else if let roundedCorners = item as? RoundedCorners { - let node = RoundedCornersNode( - parentNode: nodeTree.rootNode, - roundedCorners: roundedCorners, - upstreamPaths: nodeTree.paths) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - } else if let xform = item as? ShapeTransform { - nodeTree.transform = xform - continue - } else if let group = item as? Group { - let tree = group.items.initializeNodeTree() - let node = GroupNode(name: group.name, parentNode: nodeTree.rootNode, tree: tree) - nodeTree.rootNode = node - nodeTree.childrenNodes.append(node) - /// Now add all child paths to current tree - nodeTree.paths.append(contentsOf: tree.paths) - nodeTree.renderContainers.append(node.container) - } else if item is Repeater { - LottieLogger.shared.warn(""" - The Main Thread rendering engine doesn't currently support repeaters. - To play an animation with repeaters, you can use the Core Animation rendering engine instead. - """) - } - - if let pathNode = nodeTree.rootNode as? PathNode { - //// Add path container to the node tree - nodeTree.paths.append(pathNode.pathOutput) - } - - if let renderNode = nodeTree.rootNode as? RenderNode { - nodeTree.renderContainers.append(ShapeRenderLayer(renderer: renderNode.renderer)) - } - } - return nodeTree - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/NodeProperty.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/NodeProperty.swift deleted file mode 100644 index 8702f2c59c1e4d4f7b0c93bc2d48ddcc23bd6691..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/NodeProperty.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// NodeProperty.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import CoreGraphics -import Foundation - -/// A node property that holds a reference to a T ValueProvider and a T ValueContainer. -class NodeProperty: AnyNodeProperty { - - // MARK: Lifecycle - - init(provider: AnyValueProvider) { - valueProvider = provider - originalValueProvider = valueProvider - typedContainer = ValueContainer(provider.value(frame: 0) as! T) - typedContainer.setNeedsUpdate() - } - - // MARK: Internal - - var valueProvider: AnyValueProvider - var originalValueProvider: AnyValueProvider - - var valueType: Any.Type { T.self } - - var value: T { - typedContainer.outputValue - } - - var valueContainer: AnyValueContainer { - typedContainer - } - - func needsUpdate(frame: CGFloat) -> Bool { - valueContainer.needsUpdate || valueProvider.hasUpdate(frame: frame) - } - - func setProvider(provider: AnyValueProvider) { - guard provider.valueType == valueType else { return } - valueProvider = provider - valueContainer.setNeedsUpdate() - } - - func update(frame: CGFloat) { - typedContainer.setValue(valueProvider.value(frame: frame), forFrame: frame) - } - - // MARK: Fileprivate - - fileprivate var typedContainer: ValueContainer -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyNodeProperty.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyNodeProperty.swift deleted file mode 100644 index 132d96a8940dc497e3a71b0e23ca097b5405a3a4..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyNodeProperty.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// AnyNodeProperty.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import CoreGraphics -import Foundation - -// MARK: - AnyNodeProperty - -/// A property of a node. The node property holds a provider and a container -protocol AnyNodeProperty { - - /// Returns true if the property needs to recompute its stored value - func needsUpdate(frame: CGFloat) -> Bool - - /// Updates the property for the frame - func update(frame: CGFloat) - - /// The stored value container for the property - var valueContainer: AnyValueContainer { get } - - /// The value provider for the property - var valueProvider: AnyValueProvider { get } - - /// The original value provider for the property - var originalValueProvider: AnyValueProvider { get } - - /// The Type of the value provider - var valueType: Any.Type { get } - - /// Sets the value provider for the property. - func setProvider(provider: AnyValueProvider) -} - -extension AnyNodeProperty { - - /// Returns the most recently computed value for the keypath, returns nil if property wasn't found - func getValueOfType() -> T? { - valueContainer.value as? T - } - - /// Returns the most recently computed value for the keypath, returns nil if property wasn't found - func getValue() -> Any? { - valueContainer.value - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyValueContainer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyValueContainer.swift deleted file mode 100644 index 769d51cb1f19a4e04b25bd4c0071c1ac1a426745..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/AnyValueContainer.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// AnyValueContainer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import CoreGraphics -import Foundation - -/// The container for the value of a property. -protocol AnyValueContainer: AnyObject { - - /// The stored value of the container - var value: Any { get } - - /// Notifies the provider that it should update its container - func setNeedsUpdate() - - /// When true the container needs to have its value updated by its provider - var needsUpdate: Bool { get } - - /// The frame time of the last provided update - var lastUpdateFrame: CGFloat { get } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift deleted file mode 100644 index c91c99aa5baf8ea6ea8f75dd7a9499ffb96c265b..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// KeypathSettable.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -import QuartzCore - -/// Protocol that provides keypath search functionality. Returns all node properties associated with a keypath. -protocol KeypathSearchable { - - /// The name of the Keypath - var keypathName: String { get } - - /// A list of properties belonging to the keypath. - var keypathProperties: [String: AnyNodeProperty] { get } - - /// Children Keypaths - var childKeypaths: [KeypathSearchable] { get } - - var keypathLayer: CALayer? { get } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift deleted file mode 100644 index c3813d7b42179afe045a27c57366006509f7aac7..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// NodePropertyMap.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/21/19. -// - -import QuartzCore - -// MARK: - NodePropertyMap - -protocol NodePropertyMap { - var properties: [AnyNodeProperty] { get } -} - -extension NodePropertyMap { - - var childKeypaths: [KeypathSearchable] { - [] - } - - var keypathLayer: CALayer? { - nil - } - - /// Checks if the node's local contents need to be rebuilt. - func needsLocalUpdate(frame: CGFloat) -> Bool { - for property in properties { - if property.needsUpdate(frame: frame) { - return true - } - } - return false - } - - /// Rebuilds only the local nodes that have an update for the frame - func updateNodeProperties(frame: CGFloat) { - for property in properties { - property.update(frame: frame) - } - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/ValueContainer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/ValueContainer.swift deleted file mode 100644 index 7717090966cbf4b0e4a83f6edc700e8baf061be5..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/ValueContainer.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// ValueContainer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import CoreGraphics -import Foundation - -/// A container for a node value that is Typed to T. -class ValueContainer: AnyValueContainer { - - // MARK: Lifecycle - - init(_ value: T) { - outputValue = value - } - - // MARK: Internal - - private(set) var lastUpdateFrame = CGFloat.infinity - - fileprivate(set) var needsUpdate = true - - var value: Any { - outputValue as Any - } - - var outputValue: T { - didSet { - needsUpdate = false - } - } - - func setValue(_ value: Any, forFrame: CGFloat) { - if let typedValue = value as? T { - needsUpdate = false - lastUpdateFrame = forFrame - outputValue = typedValue - } - } - - func setNeedsUpdate() { - needsUpdate = true - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift deleted file mode 100644 index 53c95b834fb62bc4dd4e3280c6726f18768a8cd2..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/GroupInterpolator.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// KeyframeGroupInterpolator.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/22/19. -// - -import CoreGraphics -import Foundation - -/// A value provider that produces an array of values from an array of Keyframe Interpolators -final class GroupInterpolator: ValueProvider where ValueType: Interpolatable { - - // MARK: Lifecycle - - /// Initialize with an array of array of keyframes. - init(keyframeGroups: ContiguousArray>>) { - keyframeInterpolators = ContiguousArray(keyframeGroups.map { KeyframeInterpolator(keyframes: $0) }) - } - - // MARK: Internal - - let keyframeInterpolators: ContiguousArray> - - var valueType: Any.Type { - [ValueType].self - } - - var storage: ValueProviderStorage<[ValueType]> { - .closure { frame in - self.keyframeInterpolators.map { $0.value(frame: frame) as! ValueType } - } - } - - func hasUpdate(frame: CGFloat) -> Bool { - let updated = keyframeInterpolators.first(where: { $0.hasUpdate(frame: frame) }) - return updated != nil - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/SingleValueProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/SingleValueProvider.swift deleted file mode 100644 index b4bff3aac3c446a1fc0cd91b17f02a0a4dca0223..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/SingleValueProvider.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// SingleValueProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import Foundation -import QuartzCore - -/// Returns a value for every frame. -final class SingleValueProvider: ValueProvider { - - // MARK: Lifecycle - - init(_ value: ValueType) { - self.value = value - } - - // MARK: Internal - - var value: ValueType { - didSet { - hasUpdate = true - } - } - - var storage: ValueProviderStorage { - .singleValue(value) - } - - var valueType: Any.Type { - ValueType.self - } - - func hasUpdate(frame _: CGFloat) -> Bool { - hasUpdate - } - - // MARK: Private - - private var hasUpdate = true -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/RoundedCornersNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/RoundedCornersNode.swift deleted file mode 100644 index 67be54b5cf3ffad16d10ce8f6deeabc490831668..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/RoundedCornersNode.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// RoundedCornersNode.swift -// Lottie -// -// Created by Duolingo on 10/31/22. -// - -import Foundation -import QuartzCore - -// MARK: - RoundedCornersProperties - -final class RoundedCornersProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(roundedCorners: RoundedCorners) { - keypathName = roundedCorners.name - radius = NodeProperty(provider: KeyframeInterpolator(keyframes: roundedCorners.radius.keyframes)) - keypathProperties = ["Radius" : radius] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - let keypathName: String - - let radius: NodeProperty -} - -// MARK: - RoundedCornersNode - -final class RoundedCornersNode: AnimatorNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, roundedCorners: RoundedCorners, upstreamPaths: [PathOutputNode]) { - outputNode = PassThroughOutputNode(parent: parentNode?.outputNode) - self.parentNode = parentNode - properties = RoundedCornersProperties(roundedCorners: roundedCorners) - self.upstreamPaths = upstreamPaths - } - - // MARK: Internal - - let properties: RoundedCornersProperties - - let parentNode: AnimatorNode? - let outputNode: NodeOutput - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - var isEnabled = true - - // MARK: Animator Node - var propertyMap: NodePropertyMap & KeypathSearchable { - properties - } - - func forceUpstreamOutputUpdates() -> Bool { - hasLocalUpdates || hasUpstreamUpdates - } - - func rebuildOutputs(frame: CGFloat) { - for pathContainer in upstreamPaths { - let pathObjects = pathContainer.removePaths(updateFrame: frame) - for path in pathObjects { - let cornerRadius = properties.radius.value.cgFloatValue - if cornerRadius != 0 { - pathContainer.appendPath( - path.roundCorners(radius: cornerRadius), - updateFrame: frame) - } else { - pathContainer.appendPath(path, updateFrame: frame) - } - } - } - } - - // MARK: Fileprivate - - fileprivate let upstreamPaths: [PathOutputNode] -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift deleted file mode 100644 index 13000dc332ff411727f78d03d1ee8d19810482e1..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/ModifierNodes/TrimPathNode.swift +++ /dev/null @@ -1,280 +0,0 @@ -// -// TrimPathNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/23/19. -// - -import Foundation -import QuartzCore - -// MARK: - TrimPathProperties - -final class TrimPathProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(trim: Trim) { - keypathName = trim.name - start = NodeProperty(provider: KeyframeInterpolator(keyframes: trim.start.keyframes)) - end = NodeProperty(provider: KeyframeInterpolator(keyframes: trim.end.keyframes)) - offset = NodeProperty(provider: KeyframeInterpolator(keyframes: trim.offset.keyframes)) - type = trim.trimType - keypathProperties = [ - "Start" : start, - "End" : end, - "Offset" : offset, - ] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - let keypathName: String - - let start: NodeProperty - let end: NodeProperty - let offset: NodeProperty - let type: TrimType -} - -// MARK: - TrimPathNode - -final class TrimPathNode: AnimatorNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, trim: Trim, upstreamPaths: [PathOutputNode]) { - outputNode = PassThroughOutputNode(parent: parentNode?.outputNode) - self.parentNode = parentNode - properties = TrimPathProperties(trim: trim) - self.upstreamPaths = upstreamPaths - } - - // MARK: Internal - - let properties: TrimPathProperties - - let parentNode: AnimatorNode? - let outputNode: NodeOutput - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - var isEnabled = true - - // MARK: Animator Node - var propertyMap: NodePropertyMap & KeypathSearchable { - properties - } - - func forceUpstreamOutputUpdates() -> Bool { - hasLocalUpdates || hasUpstreamUpdates - } - - func rebuildOutputs(frame: CGFloat) { - /// Make sure there is a trim. - let startValue = properties.start.value.cgFloatValue * 0.01 - let endValue = properties.end.value.cgFloatValue * 0.01 - let start = min(startValue, endValue) - let end = max(startValue, endValue) - - let offset = properties.offset.value.cgFloatValue.truncatingRemainder(dividingBy: 360) / 360 - - /// No need to trim, it's a full path - if start == 0, end == 1 { - return - } - - /// All paths are empty. - if start == end { - for pathContainer in upstreamPaths { - pathContainer.removePaths(updateFrame: frame) - } - return - } - - if properties.type == .simultaneously { - /// Just trim each path - for pathContainer in upstreamPaths { - let pathObjects = pathContainer.removePaths(updateFrame: frame) - for path in pathObjects { - // We are treating each compount path as an individual path. Its subpaths are treated as a whole. - pathContainer.appendPath( - path.trim(fromPosition: start, toPosition: end, offset: offset, trimSimultaneously: false), - updateFrame: frame) - } - } - return - } - - /// Individual path trimming. - - /// Brace yourself for the below code. - - /// Normalize lengths with offset. - var startPosition = (start + offset).truncatingRemainder(dividingBy: 1) - var endPosition = (end + offset).truncatingRemainder(dividingBy: 1) - - if startPosition < 0 { - startPosition = 1 + startPosition - } - - if endPosition < 0 { - endPosition = 1 + endPosition - } - if startPosition == 1 { - startPosition = 0 - } - if endPosition == 0 { - endPosition = 1 - } - - /// First get the total length of all paths. - var totalLength: CGFloat = 0 - for upstreamPath in upstreamPaths { - totalLength = totalLength + upstreamPath.totalLength - } - - /// Now determine the start and end cut lengths - let startLength = startPosition * totalLength - let endLength = endPosition * totalLength - var pathStart: CGFloat = 0 - - /// Now loop through all path containers - for pathContainer in upstreamPaths { - let pathEnd = pathStart + pathContainer.totalLength - - if - !startLength.isInRange(pathStart, pathEnd) && - endLength.isInRange(pathStart, pathEnd) - { - // pathStart|=======E----------------------|pathEnd - // Cut path components, removing after end. - - let pathCutLength = endLength - pathStart - let subpaths = pathContainer.removePaths(updateFrame: frame) - var subpathStart: CGFloat = 0 - for path in subpaths { - let subpathEnd = subpathStart + path.length - if pathCutLength < subpathEnd { - /// This is the subpath that needs to be cut. - let cutLength = pathCutLength - subpathStart - let newPath = path.trim(fromPosition: 0, toPosition: cutLength / path.length, offset: 0, trimSimultaneously: false) - pathContainer.appendPath(newPath, updateFrame: frame) - break - } else { - /// Add to container and move on - pathContainer.appendPath(path, updateFrame: frame) - } - if pathCutLength == subpathEnd { - /// Right on the end. The next subpath is not included. Break. - break - } - subpathStart = subpathEnd - } - - } else if - !endLength.isInRange(pathStart, pathEnd) && - startLength.isInRange(pathStart, pathEnd) - { - // pathStart|-------S======================|pathEnd - // - - // Cut path components, removing before beginning. - let pathCutLength = startLength - pathStart - // Clear paths from container - let subpaths = pathContainer.removePaths(updateFrame: frame) - var subpathStart: CGFloat = 0 - for path in subpaths { - let subpathEnd = subpathStart + path.length - - if subpathStart < pathCutLength, pathCutLength < subpathEnd { - /// This is the subpath that needs to be cut. - let cutLength = pathCutLength - subpathStart - let newPath = path.trim(fromPosition: cutLength / path.length, toPosition: 1, offset: 0, trimSimultaneously: false) - pathContainer.appendPath(newPath, updateFrame: frame) - } else if pathCutLength <= subpathStart { - pathContainer.appendPath(path, updateFrame: frame) - } - subpathStart = subpathEnd - } - } else if - endLength.isInRange(pathStart, pathEnd) && - startLength.isInRange(pathStart, pathEnd) - { - // pathStart|-------S============E---------|endLength - // pathStart|=====E----------------S=======|endLength - // trim from path beginning to endLength. - - // Cut path components, removing before beginnings. - let startCutLength = startLength - pathStart - let endCutLength = endLength - pathStart - // Clear paths from container - let subpaths = pathContainer.removePaths(updateFrame: frame) - var subpathStart: CGFloat = 0 - for path in subpaths { - let subpathEnd = subpathStart + path.length - - if - !startCutLength.isInRange(subpathStart, subpathEnd), - !endCutLength.isInRange(subpathStart, subpathEnd) - { - // The whole path is included. Add - // S|==============================|E - pathContainer.appendPath(path, updateFrame: frame) - - } else if - startCutLength.isInRange(subpathStart, subpathEnd), - !endCutLength.isInRange(subpathStart, subpathEnd) - { - /// The start of the path needs to be trimmed - // |-------S======================|E - let cutLength = startCutLength - subpathStart - let newPath = path.trim(fromPosition: cutLength / path.length, toPosition: 1, offset: 0, trimSimultaneously: false) - pathContainer.appendPath(newPath, updateFrame: frame) - } else if - !startCutLength.isInRange(subpathStart, subpathEnd), - endCutLength.isInRange(subpathStart, subpathEnd) - { - // S|=======E----------------------| - let cutLength = endCutLength - subpathStart - let newPath = path.trim(fromPosition: 0, toPosition: cutLength / path.length, offset: 0, trimSimultaneously: false) - pathContainer.appendPath(newPath, updateFrame: frame) - break - } else if - startCutLength.isInRange(subpathStart, subpathEnd), - endCutLength.isInRange(subpathStart, subpathEnd) - { - // |-------S============E---------| - let cutFromLength = startCutLength - subpathStart - let cutToLength = endCutLength - subpathStart - let newPath = path.trim( - fromPosition: cutFromLength / path.length, - toPosition: cutToLength / path.length, - offset: 0, - trimSimultaneously: false) - pathContainer.appendPath(newPath, updateFrame: frame) - break - } - - subpathStart = subpathEnd - } - } else if - (endLength <= pathStart && pathEnd <= startLength) || - (startLength <= pathStart && endLength <= pathStart) || - (pathEnd <= startLength && pathEnd <= endLength) - { - /// The Path needs to be cleared - pathContainer.removePaths(updateFrame: frame) - } - - pathStart = pathEnd - } - } - - // MARK: Fileprivate - - fileprivate let upstreamPaths: [PathOutputNode] -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift deleted file mode 100644 index 6c54d4919ad81575f221ef31d033bf4e7569ece0..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift +++ /dev/null @@ -1,74 +0,0 @@ -// -// TransformNodeOutput.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import QuartzCore - -class GroupOutputNode: NodeOutput { - - // MARK: Lifecycle - - init(parent: NodeOutput?, rootNode: NodeOutput?) { - self.parent = parent - self.rootNode = rootNode - } - - // MARK: Internal - - let parent: NodeOutput? - let rootNode: NodeOutput? - var isEnabled = true - - private(set) var outputPath: CGPath? = nil - private(set) var transform: CATransform3D = CATransform3DIdentity - - func setTransform(_ xform: CATransform3D, forFrame _: CGFloat) { - transform = xform - outputPath = nil - } - - func hasOutputUpdates(_ forFrame: CGFloat) -> Bool { - guard isEnabled else { - let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false - outputPath = parent?.outputPath - return upstreamUpdates - } - - let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false - if upstreamUpdates { - outputPath = nil - } - let rootUpdates = rootNode?.hasOutputUpdates(forFrame) ?? false - if rootUpdates { - outputPath = nil - } - - var localUpdates = false - if outputPath == nil { - localUpdates = true - - let newPath = CGMutablePath() - if let parentNode = parent, let parentPath = parentNode.outputPath { - /// First add parent path. - newPath.addPath(parentPath) - } - var xform = CATransform3DGetAffineTransform(transform) - if - let rootNode, - let rootPath = rootNode.outputPath, - let xformedPath = rootPath.copy(using: &xform) - { - /// Now add root path. Note root path is transformed. - newPath.addPath(xformedPath) - } - - outputPath = newPath - } - - return upstreamUpdates || localUpdates - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift deleted file mode 100644 index f044b7ba4b0adcd1f4838472ed01c09fa4601324..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// PassThroughOutputNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import CoreGraphics - -class PassThroughOutputNode: NodeOutput { - - // MARK: Lifecycle - - init(parent: NodeOutput?) { - self.parent = parent - } - - // MARK: Internal - - let parent: NodeOutput? - - var hasUpdate = false - var isEnabled = true - - var outputPath: CGPath? { - if let parent { - return parent.outputPath - } - return nil - } - - func hasOutputUpdates(_ forFrame: CGFloat) -> Bool { - /// Changes to this node do not affect downstream nodes. - let parentUpdate = parent?.hasOutputUpdates(forFrame) ?? false - /// Changes to upstream nodes do, however, affect this nodes state. - hasUpdate = hasUpdate || parentUpdate - return parentUpdate - } - - func hasRenderUpdates(_ forFrame: CGFloat) -> Bool { - /// Return true if there are upstream updates or if this node has updates - let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false - hasUpdate = hasUpdate || upstreamUpdates - return hasUpdate - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift deleted file mode 100644 index b5c600c20514ee0feb0cff2e90b08b5f201a51be..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift +++ /dev/null @@ -1,89 +0,0 @@ -// -// PathNodeOutput.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import CoreGraphics - -/// A node that has an output of a BezierPath -class PathOutputNode: NodeOutput { - - // MARK: Lifecycle - - init(parent: NodeOutput?) { - self.parent = parent - } - - // MARK: Internal - - let parent: NodeOutput? - - fileprivate(set) var outputPath: CGPath? = nil - - var lastUpdateFrame: CGFloat? = nil - var lastPathBuildFrame: CGFloat? = nil - var isEnabled = true - fileprivate(set) var totalLength: CGFloat = 0 - fileprivate(set) var pathObjects: [CompoundBezierPath] = [] - - func hasOutputUpdates(_ forFrame: CGFloat) -> Bool { - guard isEnabled else { - let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false - outputPath = parent?.outputPath - return upstreamUpdates - } - - /// Ask if parent was updated - let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false - - /// If parent was updated and the path hasn't been built for this frame, clear the path. - if upstreamUpdates && lastPathBuildFrame != forFrame { - outputPath = nil - } - - if outputPath == nil { - /// If the path is clear, build the new path. - lastPathBuildFrame = forFrame - let newPath = CGMutablePath() - if let parentNode = parent, let parentPath = parentNode.outputPath { - newPath.addPath(parentPath) - } - for path in pathObjects { - for subPath in path.paths { - newPath.addPath(subPath.cgPath()) - } - } - outputPath = newPath - } - - /// Return true if there were upstream updates or if this node was updated. - return upstreamUpdates || (lastUpdateFrame == forFrame) - } - - @discardableResult - func removePaths(updateFrame: CGFloat?) -> [CompoundBezierPath] { - lastUpdateFrame = updateFrame - let returnPaths = pathObjects - outputPath = nil - totalLength = 0 - pathObjects = [] - return returnPaths - } - - func setPath(_ path: BezierPath, updateFrame: CGFloat) { - lastUpdateFrame = updateFrame - outputPath = nil - totalLength = path.length - pathObjects = [CompoundBezierPath(path: path)] - } - - func appendPath(_ path: CompoundBezierPath, updateFrame: CGFloat) { - lastUpdateFrame = updateFrame - outputPath = nil - totalLength = totalLength + path.length - pathObjects.append(path) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift deleted file mode 100644 index 44218df65049dd77a3d5eae141930bd7aab835bf..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// FillRenderer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import QuartzCore - -extension FillRule { - var cgFillRule: CGPathFillRule { - switch self { - case .evenOdd: - return .evenOdd - default: - return .winding - } - } - - var caFillRule: CAShapeLayerFillRule { - switch self { - case .evenOdd: - return CAShapeLayerFillRule.evenOdd - default: - return CAShapeLayerFillRule.nonZero - } - } -} - -// MARK: - FillRenderer - -/// A rendered for a Path Fill -final class FillRenderer: PassThroughOutputNode, Renderable { - var shouldRenderInContext = false - - var color: CGColor? { - didSet { - hasUpdate = true - } - } - - var opacity: CGFloat = 0 { - didSet { - hasUpdate = true - } - } - - var fillRule: FillRule = .none { - didSet { - hasUpdate = true - } - } - - func render(_: CGContext) { - // do nothing - } - - func setupSublayers(layer _: CAShapeLayer) { - // do nothing - } - - func updateShapeLayer(layer: CAShapeLayer) { - layer.fillColor = color - layer.opacity = Float(opacity) - layer.fillRule = fillRule.caFillRule - hasUpdate = false - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift deleted file mode 100644 index d011ad61d3d52b0fabbb10209a8b27a1a876f690..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +++ /dev/null @@ -1,246 +0,0 @@ -// -// GradientFillRenderer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import QuartzCore - -// MARK: - GradientFillLayer - -private final class GradientFillLayer: CALayer { - - var start: CGPoint = .zero { - didSet { - setNeedsDisplay() - } - } - - var numberOfColors = 0 { - didSet { - setNeedsDisplay() - } - } - - var colors: [CGFloat] = [] { - didSet { - setNeedsDisplay() - } - } - - var end: CGPoint = .zero { - didSet { - setNeedsDisplay() - } - } - - var type: GradientType = .none { - didSet { - setNeedsDisplay() - } - } - - override func draw(in ctx: CGContext) { - var alphaColors = [CGColor]() - var alphaLocations = [CGFloat]() - - var gradientColors = [CGColor]() - var colorLocations = [CGFloat]() - let maskColorSpace = CGColorSpaceCreateDeviceGray() - for i in 0.. ix { - let color = CGColor.rgb(colors[ix + 1], colors[ix + 2], colors[ix + 3]) - gradientColors.append(color) - colorLocations.append(colors[ix]) - } - } - - var drawMask = false - for i in stride(from: numberOfColors * 4, to: colors.endIndex, by: 2) { - let alpha = colors[i + 1] - if alpha < 1 { - drawMask = true - } - alphaLocations.append(colors[i]) - alphaColors.append(.gray(alpha)) - } - - /// First draw a mask is necessary. - if drawMask { - guard - let maskGradient = CGGradient( - colorsSpace: maskColorSpace, - colors: alphaColors as CFArray, - locations: alphaLocations), - let maskContext = CGContext( - data: nil, - width: ctx.width, - height: ctx.height, - bitsPerComponent: 8, - bytesPerRow: ctx.width, - space: maskColorSpace, - bitmapInfo: 0) - else { return } - let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(maskContext.height)) - maskContext.concatenate(flipVertical) - maskContext.concatenate(ctx.ctm) - if type == .linear { - maskContext.drawLinearGradient( - maskGradient, - start: start, - end: end, - options: [.drawsAfterEndLocation, .drawsBeforeStartLocation]) - } else { - maskContext.drawRadialGradient( - maskGradient, - startCenter: start, - startRadius: 0, - endCenter: start, - endRadius: start.distanceTo(end), - options: [.drawsAfterEndLocation, .drawsBeforeStartLocation]) - } - /// Clips the gradient - if let alphaMask = maskContext.makeImage() { - ctx.clip(to: ctx.boundingBoxOfClipPath, mask: alphaMask) - } - } - - /// Now draw the gradient - guard - let gradient = CGGradient( - colorsSpace: LottieConfiguration.shared.colorSpace, - colors: gradientColors as CFArray, - locations: colorLocations) - else { return } - - if type == .linear { - ctx.drawLinearGradient(gradient, start: start, end: end, options: [.drawsAfterEndLocation, .drawsBeforeStartLocation]) - } else { - ctx.drawRadialGradient( - gradient, - startCenter: start, - startRadius: 0, - endCenter: start, - endRadius: start.distanceTo(end), - options: [.drawsAfterEndLocation, .drawsBeforeStartLocation]) - } - } - -} - -// MARK: - GradientFillRenderer - -/// A rendered for a Path Fill -final class GradientFillRenderer: PassThroughOutputNode, Renderable { - - // MARK: Lifecycle - - override init(parent: NodeOutput?) { - super.init(parent: parent) - - maskLayer.fillColor = .rgb(1, 1, 1) - gradientLayer.mask = maskLayer - - maskLayer.actions = [ - "startPoint" : NSNull(), - "endPoint" : NSNull(), - "opacity" : NSNull(), - "locations" : NSNull(), - "colors" : NSNull(), - "bounds" : NSNull(), - "anchorPoint" : NSNull(), - "isRadial" : NSNull(), - "path" : NSNull(), - ] - gradientLayer.actions = maskLayer.actions - } - - // MARK: Internal - - var shouldRenderInContext = false - - var start: CGPoint = .zero { - didSet { - hasUpdate = true - } - } - - var numberOfColors = 0 { - didSet { - hasUpdate = true - } - } - - var colors: [CGFloat] = [] { - didSet { - hasUpdate = true - } - } - - var end: CGPoint = .zero { - didSet { - hasUpdate = true - } - } - - var opacity: CGFloat = 0 { - didSet { - hasUpdate = true - } - } - - var type: GradientType = .none { - didSet { - hasUpdate = true - } - } - - var fillRule: CAShapeLayerFillRule { - get { maskLayer.fillRule } - set { maskLayer.fillRule = newValue } - } - - func render(_: CGContext) { - // do nothing - } - - func setupSublayers(layer: CAShapeLayer) { - layer.addSublayer(gradientLayer) - layer.fillColor = nil - } - - func updateShapeLayer(layer: CAShapeLayer) { - hasUpdate = false - - guard let path = layer.path else { - return - } - - let frame = path.boundingBox - let anchor = CGPoint( - x: -frame.origin.x / frame.size.width, - y: -frame.origin.y / frame.size.height) - maskLayer.path = path - maskLayer.bounds = path.boundingBox - maskLayer.anchorPoint = anchor - - gradientLayer.bounds = maskLayer.bounds - gradientLayer.anchorPoint = anchor - - // setup gradient properties - gradientLayer.start = start - gradientLayer.end = end - gradientLayer.numberOfColors = numberOfColors - gradientLayer.colors = colors - gradientLayer.opacity = Float(opacity) - gradientLayer.type = type - } - - // MARK: Private - - private let gradientLayer = GradientFillLayer() - private let maskLayer = CAShapeLayer() - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift deleted file mode 100644 index 531b2559d2aeca13d45c5958ec616e0ca4395e82..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +++ /dev/null @@ -1,64 +0,0 @@ -// -// GradientStrokeRenderer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import QuartzCore - -// MARK: - Renderer - -final class GradientStrokeRenderer: PassThroughOutputNode, Renderable { - - // MARK: Lifecycle - - override init(parent: NodeOutput?) { - strokeRender = StrokeRenderer(parent: nil) - gradientRender = LegacyGradientFillRenderer(parent: nil) - strokeRender.color = .rgb(1, 1, 1) - super.init(parent: parent) - } - - // MARK: Internal - - var shouldRenderInContext = true - - let strokeRender: StrokeRenderer - let gradientRender: LegacyGradientFillRenderer - - override func hasOutputUpdates(_ forFrame: CGFloat) -> Bool { - let updates = super.hasOutputUpdates(forFrame) - return updates || strokeRender.hasUpdate || gradientRender.hasUpdate - } - - func updateShapeLayer(layer _: CAShapeLayer) { - /// Not Applicable - } - - func setupSublayers(layer _: CAShapeLayer) { - /// Not Applicable - } - - func render(_ inContext: CGContext) { - guard inContext.path != nil, inContext.path!.isEmpty == false else { - return - } - - strokeRender.hasUpdate = false - hasUpdate = false - gradientRender.hasUpdate = false - - strokeRender.setupForStroke(inContext) - - inContext.replacePathWithStrokedPath() - - /// Now draw the gradient. - gradientRender.render(inContext) - } - - func renderBoundsFor(_ boundingBox: CGRect) -> CGRect { - strokeRender.renderBoundsFor(boundingBox) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift deleted file mode 100644 index 953548bd545fefd53bf331a5b3405accb2ed683d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift +++ /dev/null @@ -1,152 +0,0 @@ -// -// LegacyGradientFillRenderer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import QuartzCore - -/// A rendered for a Path Fill -final class LegacyGradientFillRenderer: PassThroughOutputNode, Renderable { - - var shouldRenderInContext = true - - var start: CGPoint = .zero { - didSet { - hasUpdate = true - } - } - - var numberOfColors = 0 { - didSet { - hasUpdate = true - } - } - - var colors: [CGFloat] = [] { - didSet { - hasUpdate = true - } - } - - var end: CGPoint = .zero { - didSet { - hasUpdate = true - } - } - - var opacity: CGFloat = 0 { - didSet { - hasUpdate = true - } - } - - var type: GradientType = .none { - didSet { - hasUpdate = true - } - } - - func updateShapeLayer(layer _: CAShapeLayer) { - // Not applicable - } - - func setupSublayers(layer _: CAShapeLayer) { - // Not applicable - } - - func render(_ inContext: CGContext) { - guard inContext.path != nil, inContext.path!.isEmpty == false else { - return - } - hasUpdate = false - var alphaColors = [CGColor]() - var alphaLocations = [CGFloat]() - - var gradientColors = [CGColor]() - var colorLocations = [CGFloat]() - let maskColorSpace = CGColorSpaceCreateDeviceGray() - for i in 0.. ix { - let color = CGColor.rgb(colors[ix + 1], colors[ix + 2], colors[ix + 3]) - gradientColors.append(color) - colorLocations.append(colors[ix]) - } - } - - var drawMask = false - for i in stride(from: numberOfColors * 4, to: colors.endIndex, by: 2) { - let alpha = colors[i + 1] - if alpha < 1 { - drawMask = true - } - alphaLocations.append(colors[i]) - alphaColors.append(.gray(alpha)) - } - - inContext.setAlpha(opacity) - inContext.clip() - - /// First draw a mask is necessary. - if drawMask { - guard - let maskGradient = CGGradient( - colorsSpace: maskColorSpace, - colors: alphaColors as CFArray, - locations: alphaLocations), - let maskContext = CGContext( - data: nil, - width: inContext.width, - height: inContext.height, - bitsPerComponent: 8, - bytesPerRow: inContext.width, - space: maskColorSpace, - bitmapInfo: 0) - else { return } - let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(maskContext.height)) - maskContext.concatenate(flipVertical) - maskContext.concatenate(inContext.ctm) - if type == .linear { - maskContext.drawLinearGradient( - maskGradient, - start: start, - end: end, - options: [.drawsAfterEndLocation, .drawsBeforeStartLocation]) - } else { - maskContext.drawRadialGradient( - maskGradient, - startCenter: start, - startRadius: 0, - endCenter: start, - endRadius: start.distanceTo(end), - options: [.drawsAfterEndLocation, .drawsBeforeStartLocation]) - } - /// Clips the gradient - if let alphaMask = maskContext.makeImage() { - inContext.clip(to: inContext.boundingBoxOfClipPath, mask: alphaMask) - } - } - - /// Now draw the gradient - guard - let gradient = CGGradient( - colorsSpace: LottieConfiguration.shared.colorSpace, - colors: gradientColors as CFArray, - locations: colorLocations) - else { return } - - if type == .linear { - inContext.drawLinearGradient(gradient, start: start, end: end, options: [.drawsAfterEndLocation, .drawsBeforeStartLocation]) - } else { - inContext.drawRadialGradient( - gradient, - startCenter: start, - startRadius: 0, - endCenter: start, - endRadius: start.distanceTo(end), - options: [.drawsAfterEndLocation, .drawsBeforeStartLocation]) - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift deleted file mode 100644 index 342c5709c29a68ece1e644a929da9676456d61fc..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +++ /dev/null @@ -1,165 +0,0 @@ -// -// StrokeRenderer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import QuartzCore - -extension LineJoin { - var cgLineJoin: CGLineJoin { - switch self { - case .bevel: - return .bevel - case .none: - return .miter - case .miter: - return .miter - case .round: - return .round - } - } - - var caLineJoin: CAShapeLayerLineJoin { - switch self { - case .none: - return CAShapeLayerLineJoin.miter - case .miter: - return CAShapeLayerLineJoin.miter - case .round: - return CAShapeLayerLineJoin.round - case .bevel: - return CAShapeLayerLineJoin.bevel - } - } -} - -extension LineCap { - var cgLineCap: CGLineCap { - switch self { - case .none: - return .butt - case .butt: - return .butt - case .round: - return .round - case .square: - return .square - } - } - - var caLineCap: CAShapeLayerLineCap { - switch self { - case .none: - return CAShapeLayerLineCap.butt - case .butt: - return CAShapeLayerLineCap.butt - case .round: - return CAShapeLayerLineCap.round - case .square: - return CAShapeLayerLineCap.square - } - } -} - -// MARK: - StrokeRenderer - -/// A rendered that renders a stroke on a path. -final class StrokeRenderer: PassThroughOutputNode, Renderable { - - var shouldRenderInContext = false - - var color: CGColor? { - didSet { - hasUpdate = true - } - } - - var opacity: CGFloat = 0 { - didSet { - hasUpdate = true - } - } - - var width: CGFloat = 0 { - didSet { - hasUpdate = true - } - } - - var miterLimit: CGFloat = 0 { - didSet { - hasUpdate = true - } - } - - var lineCap: LineCap = .none { - didSet { - hasUpdate = true - } - } - - var lineJoin: LineJoin = .none { - didSet { - hasUpdate = true - } - } - - var dashPhase: CGFloat? { - didSet { - hasUpdate = true - } - } - - var dashLengths: [CGFloat]? { - didSet { - hasUpdate = true - } - } - - func setupSublayers(layer _: CAShapeLayer) { - // empty - } - - func renderBoundsFor(_ boundingBox: CGRect) -> CGRect { - boundingBox.insetBy(dx: -width, dy: -width) - } - - func setupForStroke(_ inContext: CGContext) { - inContext.setLineWidth(width) - inContext.setMiterLimit(miterLimit) - inContext.setLineCap(lineCap.cgLineCap) - inContext.setLineJoin(lineJoin.cgLineJoin) - if let dashPhase, let lengths = dashLengths { - inContext.setLineDash(phase: dashPhase, lengths: lengths) - } else { - inContext.setLineDash(phase: 0, lengths: []) - } - } - - func render(_ inContext: CGContext) { - guard inContext.path != nil, inContext.path!.isEmpty == false else { - return - } - guard let color else { return } - hasUpdate = false - setupForStroke(inContext) - inContext.setAlpha(opacity) - inContext.setStrokeColor(color) - inContext.strokePath() - } - - func updateShapeLayer(layer: CAShapeLayer) { - layer.strokeColor = color - layer.opacity = Float(opacity) - layer.lineWidth = width - layer.lineJoin = lineJoin.caLineJoin - layer.lineCap = lineCap.caLineCap - layer.lineDashPhase = dashPhase ?? 0 - layer.fillColor = nil - if let dashPattern = dashLengths { - layer.lineDashPattern = dashPattern.map { NSNumber(value: Double($0)) } - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift deleted file mode 100644 index a5c40e6b63bd7f93f919b4be167f5a9c2708c6cc..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +++ /dev/null @@ -1,139 +0,0 @@ -// -// EllipseNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/17/19. -// - -import Foundation -import QuartzCore - -// MARK: - EllipseNodeProperties - -final class EllipseNodeProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(ellipse: Ellipse) { - keypathName = ellipse.name - direction = ellipse.direction - position = NodeProperty(provider: KeyframeInterpolator(keyframes: ellipse.position.keyframes)) - size = NodeProperty(provider: KeyframeInterpolator(keyframes: ellipse.size.keyframes)) - keypathProperties = [ - PropertyName.position.rawValue : position, - "Size" : size, - ] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - var keypathName: String - - let direction: PathDirection - let position: NodeProperty - let size: NodeProperty - - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] -} - -// MARK: - EllipseNode - -final class EllipseNode: AnimatorNode, PathNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, ellipse: Ellipse) { - pathOutput = PathOutputNode(parent: parentNode?.outputNode) - properties = EllipseNodeProperties(ellipse: ellipse) - self.parentNode = parentNode - } - - // MARK: Internal - - static let ControlPointConstant: CGFloat = 0.55228 - - let pathOutput: PathOutputNode - - let properties: EllipseNodeProperties - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - // MARK: Animator Node - - var propertyMap: NodePropertyMap & KeypathSearchable { - properties - } - - var isEnabled = true { - didSet { - pathOutput.isEnabled = isEnabled - } - } - - func rebuildOutputs(frame: CGFloat) { - pathOutput.setPath( - .ellipse( - size: properties.size.value.sizeValue, - center: properties.position.value.pointValue, - direction: properties.direction), - updateFrame: frame) - } - -} - -extension BezierPath { - /// Constructs a `BezierPath` in the shape of an ellipse - static func ellipse( - size: CGSize, - center: CGPoint, - direction: PathDirection) - -> BezierPath - { - // Unfortunately we HAVE to manually build out the ellipse. - // Every Apple method constructs an ellipse from the 3 o-clock position - // After effects constructs from the Noon position. - // After effects does clockwise, but also has a flag for reversed. - var half = size * 0.5 - if direction == .counterClockwise { - half.width = half.width * -1 - } - - let q1 = CGPoint(x: center.x, y: center.y - half.height) - let q2 = CGPoint(x: center.x + half.width, y: center.y) - let q3 = CGPoint(x: center.x, y: center.y + half.height) - let q4 = CGPoint(x: center.x - half.width, y: center.y) - - let cp = half * EllipseNode.ControlPointConstant - - var path = BezierPath(startPoint: CurveVertex( - point: q1, - inTangentRelative: CGPoint(x: -cp.width, y: 0), - outTangentRelative: CGPoint(x: cp.width, y: 0))) - path.addVertex(CurveVertex( - point: q2, - inTangentRelative: CGPoint(x: 0, y: -cp.height), - outTangentRelative: CGPoint(x: 0, y: cp.height))) - - path.addVertex(CurveVertex( - point: q3, - inTangentRelative: CGPoint(x: cp.width, y: 0), - outTangentRelative: CGPoint(x: -cp.width, y: 0))) - - path.addVertex(CurveVertex( - point: q4, - inTangentRelative: CGPoint(x: 0, y: cp.height), - outTangentRelative: CGPoint(x: 0, y: -cp.height))) - - path.addVertex(CurveVertex( - point: q1, - inTangentRelative: CGPoint(x: -cp.width, y: 0), - outTangentRelative: CGPoint(x: cp.width, y: 0))) - path.close() - return path - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift deleted file mode 100644 index ba8aaf490de8a278816adbdf2212f39985c84e06..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +++ /dev/null @@ -1,170 +0,0 @@ -// -// PolygonNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/21/19. -// - -import Foundation -import QuartzCore - -// MARK: - PolygonNodeProperties - -final class PolygonNodeProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(star: Star) { - keypathName = star.name - direction = star.direction - position = NodeProperty(provider: KeyframeInterpolator(keyframes: star.position.keyframes)) - outerRadius = NodeProperty(provider: KeyframeInterpolator(keyframes: star.outerRadius.keyframes)) - outerRoundedness = NodeProperty(provider: KeyframeInterpolator(keyframes: star.outerRoundness.keyframes)) - rotation = NodeProperty(provider: KeyframeInterpolator(keyframes: star.rotation.keyframes)) - points = NodeProperty(provider: KeyframeInterpolator(keyframes: star.points.keyframes)) - keypathProperties = [ - PropertyName.position.rawValue : position, - "Outer Radius" : outerRadius, - "Outer Roundedness" : outerRoundedness, - PropertyName.rotation.rawValue : rotation, - "Points" : points, - ] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - var keypathName: String - - var childKeypaths: [KeypathSearchable] = [] - - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - - let direction: PathDirection - let position: NodeProperty - let outerRadius: NodeProperty - let outerRoundedness: NodeProperty - let rotation: NodeProperty - let points: NodeProperty -} - -// MARK: - PolygonNode - -final class PolygonNode: AnimatorNode, PathNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, star: Star) { - pathOutput = PathOutputNode(parent: parentNode?.outputNode) - properties = PolygonNodeProperties(star: star) - self.parentNode = parentNode - } - - // MARK: Internal - - /// Magic number needed for constructing path. - static let PolygonConstant: CGFloat = 0.25 - - let properties: PolygonNodeProperties - - let pathOutput: PathOutputNode - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - // MARK: Animator Node - - var propertyMap: NodePropertyMap & KeypathSearchable { - properties - } - - var isEnabled = true { - didSet { - pathOutput.isEnabled = isEnabled - } - } - - func rebuildOutputs(frame: CGFloat) { - let path = BezierPath.polygon( - position: properties.position.value.pointValue, - numberOfPoints: properties.points.value.cgFloatValue, - outerRadius: properties.outerRadius.value.cgFloatValue, - outerRoundedness: properties.outerRoundedness.value.cgFloatValue, - rotation: properties.rotation.value.cgFloatValue, - direction: properties.direction) - - pathOutput.setPath(path, updateFrame: frame) - } - -} - -extension BezierPath { - /// Creates a `BezierPath` in the shape of a polygon - static func polygon( - position: CGPoint, - numberOfPoints: CGFloat, - outerRadius: CGFloat, - outerRoundedness inputOuterRoundedness: CGFloat, - rotation: CGFloat, - direction: PathDirection) - -> BezierPath - { - var currentAngle = (rotation - 90).toRadians() - let anglePerPoint = ((2 * CGFloat.pi) / numberOfPoints) - let outerRoundedness = inputOuterRoundedness * 0.01 - - var point = CGPoint( - x: outerRadius * cos(currentAngle), - y: outerRadius * sin(currentAngle)) - var vertices = [CurveVertex(point: point + position, inTangentRelative: .zero, outTangentRelative: .zero)] - - var previousPoint = point - currentAngle += anglePerPoint; - for _ in 0.. - let size: NodeProperty - let cornerRadius: NodeProperty - -} - -// MARK: - RectangleNode - -final class RectangleNode: AnimatorNode, PathNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, rectangle: Rectangle) { - properties = RectNodeProperties(rectangle: rectangle) - pathOutput = PathOutputNode(parent: parentNode?.outputNode) - self.parentNode = parentNode - } - - // MARK: Internal - - let properties: RectNodeProperties - - let pathOutput: PathOutputNode - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - // MARK: Animator Node - - var propertyMap: NodePropertyMap & KeypathSearchable { - properties - } - - var isEnabled = true { - didSet { - pathOutput.isEnabled = isEnabled - } - } - - func rebuildOutputs(frame: CGFloat) { - pathOutput.setPath( - .rectangle( - position: properties.position.value.pointValue, - size: properties.size.value.sizeValue, - cornerRadius: properties.cornerRadius.value.cgFloatValue, - direction: properties.direction), - updateFrame: frame) - } - -} - -// MARK: - BezierPath + rectangle - -extension BezierPath { - /// Constructs a `BezierPath` in the shape of a rectangle, optionally with rounded corners - static func rectangle( - position: CGPoint, - size inputSize: CGSize, - cornerRadius: CGFloat, - direction: PathDirection) - -> BezierPath - { - let size = inputSize * 0.5 - let radius = min(min(cornerRadius, size.width) , size.height) - - var bezierPath = BezierPath() - let points: [CurveVertex] - - if radius <= 0 { - /// No Corners - points = [ - /// Lead In - CurveVertex( - point: CGPoint(x: size.width, y: -size.height), - inTangentRelative: .zero, - outTangentRelative: .zero) - .translated(position), - /// Corner 1 - CurveVertex( - point: CGPoint(x: size.width, y: size.height), - inTangentRelative: .zero, - outTangentRelative: .zero) - .translated(position), - /// Corner 2 - CurveVertex( - point: CGPoint(x: -size.width, y: size.height), - inTangentRelative: .zero, - outTangentRelative: .zero) - .translated(position), - /// Corner 3 - CurveVertex( - point: CGPoint(x: -size.width, y: -size.height), - inTangentRelative: .zero, - outTangentRelative: .zero) - .translated(position), - /// Corner 4 - CurveVertex( - point: CGPoint(x: size.width, y: -size.height), - inTangentRelative: .zero, - outTangentRelative: .zero) - .translated(position), - ] - } else { - let controlPoint = radius * EllipseNode.ControlPointConstant - points = [ - /// Lead In - CurveVertex( - CGPoint(x: radius, y: 0), - CGPoint(x: radius, y: 0), - CGPoint(x: radius, y: 0)) - .translated(CGPoint(x: -radius, y: radius)) - .translated(CGPoint(x: size.width, y: -size.height)) - .translated(position), - /// Corner 1 - CurveVertex( - CGPoint(x: radius, y: 0), // In tangent - CGPoint(x: radius, y: 0), // Point - CGPoint(x: radius, y: controlPoint)) - .translated(CGPoint(x: -radius, y: -radius)) - .translated(CGPoint(x: size.width, y: size.height)) - .translated(position), - CurveVertex( - CGPoint(x: controlPoint, y: radius), // In tangent - CGPoint(x: 0, y: radius), // Point - CGPoint(x: 0, y: radius)) // Out Tangent - .translated(CGPoint(x: -radius, y: -radius)) - .translated(CGPoint(x: size.width, y: size.height)) - .translated(position), - /// Corner 2 - CurveVertex( - CGPoint(x: 0, y: radius), // In tangent - CGPoint(x: 0, y: radius), // Point - CGPoint(x: -controlPoint, y: radius)) // Out tangent - .translated(CGPoint(x: radius, y: -radius)) - .translated(CGPoint(x: -size.width, y: size.height)) - .translated(position), - CurveVertex( - CGPoint(x: -radius, y: controlPoint), // In tangent - CGPoint(x: -radius, y: 0), // Point - CGPoint(x: -radius, y: 0)) // Out tangent - .translated(CGPoint(x: radius, y: -radius)) - .translated(CGPoint(x: -size.width, y: size.height)) - .translated(position), - /// Corner 3 - CurveVertex( - CGPoint(x: -radius, y: 0), // In tangent - CGPoint(x: -radius, y: 0), // Point - CGPoint(x: -radius, y: -controlPoint)) // Out tangent - .translated(CGPoint(x: radius, y: radius)) - .translated(CGPoint(x: -size.width, y: -size.height)) - .translated(position), - CurveVertex( - CGPoint(x: -controlPoint, y: -radius), // In tangent - CGPoint(x: 0, y: -radius), // Point - CGPoint(x: 0, y: -radius)) // Out tangent - .translated(CGPoint(x: radius, y: radius)) - .translated(CGPoint(x: -size.width, y: -size.height)) - .translated(position), - /// Corner 4 - CurveVertex( - CGPoint(x: 0, y: -radius), // In tangent - CGPoint(x: 0, y: -radius), // Point - CGPoint(x: controlPoint, y: -radius)) // Out tangent - .translated(CGPoint(x: -radius, y: radius)) - .translated(CGPoint(x: size.width, y: -size.height)) - .translated(position), - CurveVertex( - CGPoint(x: radius, y: -controlPoint), // In tangent - CGPoint(x: radius, y: 0), // Point - CGPoint(x: radius, y: 0)) // Out tangent - .translated(CGPoint(x: -radius, y: radius)) - .translated(CGPoint(x: size.width, y: -size.height)) - .translated(position), - ] - } - let reversed = direction == .counterClockwise - let pathPoints = reversed ? points.reversed() : points - for point in pathPoints { - bezierPath.addVertex(reversed ? point.reversed() : point) - } - bezierPath.close() - return bezierPath - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/ShapeNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/ShapeNode.swift deleted file mode 100644 index 7bc7d9055d20215916097411a5ac2d87c2ed1038..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/ShapeNode.swift +++ /dev/null @@ -1,74 +0,0 @@ -// -// PathNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/16/19. -// - -import CoreGraphics -import Foundation - -// MARK: - ShapeNodeProperties - -final class ShapeNodeProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(shape: Shape) { - keypathName = shape.name - path = NodeProperty(provider: KeyframeInterpolator(keyframes: shape.path.keyframes)) - keypathProperties = [ - "Path" : path, - ] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - var keypathName: String - - let path: NodeProperty - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - -} - -// MARK: - ShapeNode - -final class ShapeNode: AnimatorNode, PathNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, shape: Shape) { - pathOutput = PathOutputNode(parent: parentNode?.outputNode) - properties = ShapeNodeProperties(shape: shape) - self.parentNode = parentNode - } - - // MARK: Internal - - let properties: ShapeNodeProperties - - let pathOutput: PathOutputNode - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - // MARK: Animator Node - var propertyMap: NodePropertyMap & KeypathSearchable { - properties - } - - var isEnabled = true { - didSet { - pathOutput.isEnabled = isEnabled - } - } - - func rebuildOutputs(frame: CGFloat) { - pathOutput.setPath(properties.path.value, updateFrame: frame) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift deleted file mode 100644 index bf1753108fe89602b8aa6faf42f934673add4552..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +++ /dev/null @@ -1,222 +0,0 @@ -// -// StarNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/21/19. -// - -import Foundation -import QuartzCore - -// MARK: - StarNodeProperties - -final class StarNodeProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(star: Star) { - keypathName = star.name - direction = star.direction - position = NodeProperty(provider: KeyframeInterpolator(keyframes: star.position.keyframes)) - outerRadius = NodeProperty(provider: KeyframeInterpolator(keyframes: star.outerRadius.keyframes)) - outerRoundedness = NodeProperty(provider: KeyframeInterpolator(keyframes: star.outerRoundness.keyframes)) - if let innerRadiusKeyframes = star.innerRadius?.keyframes { - innerRadius = NodeProperty(provider: KeyframeInterpolator(keyframes: innerRadiusKeyframes)) - } else { - innerRadius = NodeProperty(provider: SingleValueProvider(LottieVector1D(0))) - } - if let innderRoundedness = star.innerRoundness?.keyframes { - innerRoundedness = NodeProperty(provider: KeyframeInterpolator(keyframes: innderRoundedness)) - } else { - innerRoundedness = NodeProperty(provider: SingleValueProvider(LottieVector1D(0))) - } - rotation = NodeProperty(provider: KeyframeInterpolator(keyframes: star.rotation.keyframes)) - points = NodeProperty(provider: KeyframeInterpolator(keyframes: star.points.keyframes)) - keypathProperties = [ - PropertyName.position.rawValue : position, - "Outer Radius" : outerRadius, - "Outer Roundedness" : outerRoundedness, - "Inner Radius" : innerRadius, - "Inner Roundedness" : innerRoundedness, - PropertyName.rotation.rawValue : rotation, - "Points" : points, - ] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - var keypathName: String - - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - - let direction: PathDirection - let position: NodeProperty - let outerRadius: NodeProperty - let outerRoundedness: NodeProperty - let innerRadius: NodeProperty - let innerRoundedness: NodeProperty - let rotation: NodeProperty - let points: NodeProperty -} - -// MARK: - StarNode - -final class StarNode: AnimatorNode, PathNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, star: Star) { - pathOutput = PathOutputNode(parent: parentNode?.outputNode) - properties = StarNodeProperties(star: star) - self.parentNode = parentNode - } - - // MARK: Internal - - /// Magic number needed for building path data - static let PolystarConstant: CGFloat = 0.47829 - - let properties: StarNodeProperties - - let pathOutput: PathOutputNode - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - // MARK: Animator Node - var propertyMap: NodePropertyMap & KeypathSearchable { - properties - } - - var isEnabled = true { - didSet { - pathOutput.isEnabled = isEnabled - } - } - - func rebuildOutputs(frame: CGFloat) { - let path = BezierPath.star( - position: properties.position.value.pointValue, - outerRadius: properties.outerRadius.value.cgFloatValue, - innerRadius: properties.innerRadius.value.cgFloatValue, - outerRoundedness: properties.outerRoundedness.value.cgFloatValue, - innerRoundedness: properties.innerRoundedness.value.cgFloatValue, - numberOfPoints: properties.points.value.cgFloatValue, - rotation: properties.rotation.value.cgFloatValue, - direction: properties.direction) - - pathOutput.setPath(path, updateFrame: frame) - } - -} - -extension BezierPath { - /// Constructs a `BezierPath` in the shape of a star - static func star( - position: CGPoint, - outerRadius: CGFloat, - innerRadius: CGFloat, - outerRoundedness inoutOuterRoundedness: CGFloat, - innerRoundedness inputInnerRoundedness: CGFloat, - numberOfPoints: CGFloat, - rotation: CGFloat, - direction: PathDirection) - -> BezierPath - { - var currentAngle = (rotation - 90).toRadians() - let anglePerPoint = (2 * CGFloat.pi) / numberOfPoints - let halfAnglePerPoint = anglePerPoint / 2.0 - let partialPointAmount = numberOfPoints - floor(numberOfPoints) - let outerRoundedness = inoutOuterRoundedness * 0.01 - let innerRoundedness = inputInnerRoundedness * 0.01 - - var point: CGPoint = .zero - - var partialPointRadius: CGFloat = 0 - if partialPointAmount != 0 { - currentAngle += halfAnglePerPoint * (1 - partialPointAmount) - partialPointRadius = innerRadius + partialPointAmount * (outerRadius - innerRadius) - point.x = (partialPointRadius * cos(currentAngle)) - point.y = (partialPointRadius * sin(currentAngle)) - currentAngle += anglePerPoint * partialPointAmount / 2 - } else { - point.x = (outerRadius * cos(currentAngle)) - point.y = (outerRadius * sin(currentAngle)) - currentAngle += halfAnglePerPoint - } - - var vertices = [CurveVertex]() - vertices.append(CurveVertex(point: point + position, inTangentRelative: .zero, outTangentRelative: .zero)) - - var previousPoint = point - var longSegment = false - let numPoints = Int(ceil(numberOfPoints) * 2) - for i in 0.. - let position: NodeProperty - let scale: NodeProperty - let rotationX: NodeProperty - let rotationY: NodeProperty - let rotationZ: NodeProperty - - let opacity: NodeProperty - let skew: NodeProperty - let skewAxis: NodeProperty - - var caTransform: CATransform3D { - CATransform3D.makeTransform( - anchor: anchor.value.pointValue, - position: position.value.pointValue, - scale: scale.value.sizeValue, - rotationX: rotationX.value.cgFloatValue, - rotationY: rotationY.value.cgFloatValue, - rotationZ: rotationZ.value.cgFloatValue, - skew: skew.value.cgFloatValue, - skewAxis: skewAxis.value.cgFloatValue) - } -} - -// MARK: - GroupNode - -final class GroupNode: AnimatorNode { - - // MARK: Lifecycle - - // MARK: Initializer - init(name: String, parentNode: AnimatorNode?, tree: NodeTree) { - self.parentNode = parentNode - keypathName = name - rootNode = tree.rootNode - properties = GroupNodeProperties(transform: tree.transform) - groupOutput = GroupOutputNode(parent: parentNode?.outputNode, rootNode: rootNode?.outputNode) - var childKeypaths: [KeypathSearchable] = tree.childrenNodes - childKeypaths.append(properties) - self.childKeypaths = childKeypaths - - for childContainer in tree.renderContainers { - container.insertRenderLayer(childContainer) - } - } - - // MARK: Internal - - // MARK: Properties - let groupOutput: GroupOutputNode - - let properties: GroupNodeProperties - - let rootNode: AnimatorNode? - - var container = ShapeContainerLayer() - - // MARK: Keypath Searchable - - let keypathName: String - - let childKeypaths: [KeypathSearchable] - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - var keypathLayer: CALayer? { - container - } - - // MARK: Animator Node Protocol - - var propertyMap: NodePropertyMap & KeypathSearchable { - properties - } - - var outputNode: NodeOutput { - groupOutput - } - - var isEnabled = true { - didSet { - container.isHidden = !isEnabled - } - } - - func performAdditionalLocalUpdates(frame: CGFloat, forceLocalUpdate: Bool) -> Bool { - rootNode?.updateContents(frame, forceLocalUpdate: forceLocalUpdate) ?? false - } - - func performAdditionalOutputUpdates(_ frame: CGFloat, forceOutputUpdate: Bool) { - rootNode?.updateOutputs(frame, forceOutputUpdate: forceOutputUpdate) - } - - func rebuildOutputs(frame: CGFloat) { - container.opacity = Float(properties.opacity.value.cgFloatValue) * 0.01 - container.transform = properties.caTransform - groupOutput.setTransform(container.transform, forFrame: frame) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift deleted file mode 100644 index 1b079b084a080da863b0b1466e1caa87a6fb148f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +++ /dev/null @@ -1,90 +0,0 @@ -// -// FillNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/17/19. -// - -import CoreGraphics -import Foundation - -// MARK: - FillNodeProperties - -final class FillNodeProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(fill: Fill) { - keypathName = fill.name - color = NodeProperty(provider: KeyframeInterpolator(keyframes: fill.color.keyframes)) - opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: fill.opacity.keyframes)) - type = fill.fillRule - keypathProperties = [ - PropertyName.opacity.rawValue : opacity, - PropertyName.color.rawValue : color, - ] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - var keypathName: String - - let opacity: NodeProperty - let color: NodeProperty - let type: FillRule - - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - -} - -// MARK: - FillNode - -final class FillNode: AnimatorNode, RenderNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, fill: Fill) { - fillRender = FillRenderer(parent: parentNode?.outputNode) - fillProperties = FillNodeProperties(fill: fill) - self.parentNode = parentNode - } - - // MARK: Internal - - let fillRender: FillRenderer - - let fillProperties: FillNodeProperties - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - var renderer: NodeOutput & Renderable { - fillRender - } - - // MARK: Animator Node Protocol - - var propertyMap: NodePropertyMap & KeypathSearchable { - fillProperties - } - - var isEnabled = true { - didSet { - fillRender.isEnabled = isEnabled - } - } - - func localUpdatesPermeateDownstream() -> Bool { - false - } - - func rebuildOutputs(frame _: CGFloat) { - fillRender.color = fillProperties.color.value.cgColorValue - fillRender.opacity = fillProperties.opacity.value.cgFloatValue * 0.01 - fillRender.fillRule = fillProperties.type - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift deleted file mode 100644 index 97e37ef614e208e6b5dac8af19486e50a63a5bb7..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +++ /dev/null @@ -1,105 +0,0 @@ -// -// GradientFillNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/22/19. -// - -import Foundation -import QuartzCore - -// MARK: - GradientFillProperties - -final class GradientFillProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(gradientfill: GradientFill) { - keypathName = gradientfill.name - opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientfill.opacity.keyframes)) - startPoint = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientfill.startPoint.keyframes)) - endPoint = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientfill.endPoint.keyframes)) - colors = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientfill.colors.keyframes)) - gradientType = gradientfill.gradientType - numberOfColors = gradientfill.numberOfColors - fillRule = gradientfill.fillRule - keypathProperties = [ - PropertyName.opacity.rawValue : opacity, - "Start Point" : startPoint, - "End Point" : endPoint, - PropertyName.gradientColors.rawValue : colors, - ] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - var keypathName: String - - let opacity: NodeProperty - let startPoint: NodeProperty - let endPoint: NodeProperty - let colors: NodeProperty<[Double]> - - let gradientType: GradientType - let numberOfColors: Int - let fillRule: FillRule - - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - -} - -// MARK: - GradientFillNode - -final class GradientFillNode: AnimatorNode, RenderNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, gradientFill: GradientFill) { - fillRender = GradientFillRenderer(parent: parentNode?.outputNode) - fillProperties = GradientFillProperties(gradientfill: gradientFill) - self.parentNode = parentNode - } - - // MARK: Internal - - let fillRender: GradientFillRenderer - - let fillProperties: GradientFillProperties - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - var renderer: NodeOutput & Renderable { - fillRender - } - - // MARK: Animator Node Protocol - - var propertyMap: NodePropertyMap & KeypathSearchable { - fillProperties - } - - var isEnabled = true { - didSet { - fillRender.isEnabled = isEnabled - } - } - - func localUpdatesPermeateDownstream() -> Bool { - false - } - - func rebuildOutputs(frame _: CGFloat) { - fillRender.start = fillProperties.startPoint.value.pointValue - fillRender.end = fillProperties.endPoint.value.pointValue - fillRender.opacity = fillProperties.opacity.value.cgFloatValue * 0.01 - fillRender.colors = fillProperties.colors.value.map { CGFloat($0) } - fillRender.type = fillProperties.gradientType - fillRender.numberOfColors = fillProperties.numberOfColors - fillRender.fillRule = fillProperties.fillRule.caFillRule - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift deleted file mode 100644 index 62f0dfe6c752acc78fff788231e9c18a204495b3..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +++ /dev/null @@ -1,151 +0,0 @@ -// -// GradientStrokeNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/23/19. -// - -import CoreGraphics -import Foundation - -// MARK: - GradientStrokeProperties - -final class GradientStrokeProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(gradientStroke: GradientStroke) { - keypathName = gradientStroke.name - opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientStroke.opacity.keyframes)) - startPoint = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientStroke.startPoint.keyframes)) - endPoint = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientStroke.endPoint.keyframes)) - colors = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientStroke.colors.keyframes)) - gradientType = gradientStroke.gradientType - numberOfColors = gradientStroke.numberOfColors - width = NodeProperty(provider: KeyframeInterpolator(keyframes: gradientStroke.width.keyframes)) - miterLimit = CGFloat(gradientStroke.miterLimit) - lineCap = gradientStroke.lineCap - lineJoin = gradientStroke.lineJoin - - if let dashes = gradientStroke.dashPattern { - var dashPatterns = ContiguousArray>>() - var dashPhase = ContiguousArray>() - for dash in dashes { - if dash.type == .offset { - dashPhase = dash.value.keyframes - } else { - dashPatterns.append(dash.value.keyframes) - } - } - dashPattern = NodeProperty(provider: GroupInterpolator(keyframeGroups: dashPatterns)) - self.dashPhase = NodeProperty(provider: KeyframeInterpolator(keyframes: dashPhase)) - } else { - dashPattern = NodeProperty(provider: SingleValueProvider([LottieVector1D]())) - dashPhase = NodeProperty(provider: SingleValueProvider(LottieVector1D(0))) - } - keypathProperties = [ - PropertyName.opacity.rawValue : opacity, - "Start Point" : startPoint, - "End Point" : endPoint, - PropertyName.gradientColors.rawValue : colors, - PropertyName.strokeWidth.rawValue : width, - "Dashes" : dashPattern, - "Dash Phase" : dashPhase, - ] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - var keypathName: String - - let opacity: NodeProperty - let startPoint: NodeProperty - let endPoint: NodeProperty - let colors: NodeProperty<[Double]> - let width: NodeProperty - - let dashPattern: NodeProperty<[LottieVector1D]> - let dashPhase: NodeProperty - - let lineCap: LineCap - let lineJoin: LineJoin - let miterLimit: CGFloat - let gradientType: GradientType - let numberOfColors: Int - - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - -} - -// MARK: - GradientStrokeNode - -final class GradientStrokeNode: AnimatorNode, RenderNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, gradientStroke: GradientStroke) { - strokeRender = GradientStrokeRenderer(parent: parentNode?.outputNode) - strokeProperties = GradientStrokeProperties(gradientStroke: gradientStroke) - self.parentNode = parentNode - } - - // MARK: Internal - - let strokeRender: GradientStrokeRenderer - - let strokeProperties: GradientStrokeProperties - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - var renderer: NodeOutput & Renderable { - strokeRender - } - - // MARK: Animator Node Protocol - - var propertyMap: NodePropertyMap & KeypathSearchable { - strokeProperties - } - - var isEnabled = true { - didSet { - strokeRender.isEnabled = isEnabled - } - } - - func localUpdatesPermeateDownstream() -> Bool { - false - } - - func rebuildOutputs(frame _: CGFloat) { - /// Update gradient properties - strokeRender.gradientRender.start = strokeProperties.startPoint.value.pointValue - strokeRender.gradientRender.end = strokeProperties.endPoint.value.pointValue - strokeRender.gradientRender.opacity = strokeProperties.opacity.value.cgFloatValue - strokeRender.gradientRender.colors = strokeProperties.colors.value.map { CGFloat($0) } - strokeRender.gradientRender.type = strokeProperties.gradientType - strokeRender.gradientRender.numberOfColors = strokeProperties.numberOfColors - - /// Now update stroke properties - strokeRender.strokeRender.opacity = strokeProperties.opacity.value.cgFloatValue - strokeRender.strokeRender.width = strokeProperties.width.value.cgFloatValue - strokeRender.strokeRender.miterLimit = strokeProperties.miterLimit - strokeRender.strokeRender.lineCap = strokeProperties.lineCap - strokeRender.strokeRender.lineJoin = strokeProperties.lineJoin - - /// Get dash lengths - let dashLengths = strokeProperties.dashPattern.value.map { $0.cgFloatValue } - if dashLengths.count > 0, dashLengths.isSupportedLayerDashPattern { - strokeRender.strokeRender.dashPhase = strokeProperties.dashPhase.value.cgFloatValue - strokeRender.strokeRender.dashLengths = dashLengths - } else { - strokeRender.strokeRender.dashLengths = nil - strokeRender.strokeRender.dashPhase = nil - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift deleted file mode 100644 index c3bbb5f65fc3ca6f5d7ff0f7a018a98e4a44324c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +++ /dev/null @@ -1,180 +0,0 @@ -// -// StrokeNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/22/19. -// - -import Foundation -import QuartzCore - -// MARK: - StrokeNodeProperties - -final class StrokeNodeProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(stroke: Stroke) { - keypathName = stroke.name - color = NodeProperty(provider: KeyframeInterpolator(keyframes: stroke.color.keyframes)) - opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: stroke.opacity.keyframes)) - width = NodeProperty(provider: KeyframeInterpolator(keyframes: stroke.width.keyframes)) - miterLimit = CGFloat(stroke.miterLimit) - lineCap = stroke.lineCap - lineJoin = stroke.lineJoin - - if let dashes = stroke.dashPattern { - let (dashPatterns, dashPhase) = dashes.shapeLayerConfiguration - dashPattern = NodeProperty(provider: GroupInterpolator(keyframeGroups: dashPatterns)) - if dashPhase.count == 0 { - self.dashPhase = NodeProperty(provider: SingleValueProvider(LottieVector1D(0))) - } else { - self.dashPhase = NodeProperty(provider: KeyframeInterpolator(keyframes: dashPhase)) - } - } else { - dashPattern = NodeProperty(provider: SingleValueProvider([LottieVector1D]())) - dashPhase = NodeProperty(provider: SingleValueProvider(LottieVector1D(0))) - } - keypathProperties = [ - PropertyName.opacity.rawValue : opacity, - PropertyName.color.rawValue : color, - PropertyName.strokeWidth.rawValue : width, - "Dashes" : dashPattern, - "Dash Phase" : dashPhase, - ] - properties = Array(keypathProperties.values) - } - - // MARK: Internal - - let keypathName: String - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - - let opacity: NodeProperty - let color: NodeProperty - let width: NodeProperty - - let dashPattern: NodeProperty<[LottieVector1D]> - let dashPhase: NodeProperty - - let lineCap: LineCap - let lineJoin: LineJoin - let miterLimit: CGFloat - -} - -// MARK: - StrokeNode - -/// Node that manages stroking a path -final class StrokeNode: AnimatorNode, RenderNode { - - // MARK: Lifecycle - - init(parentNode: AnimatorNode?, stroke: Stroke) { - strokeRender = StrokeRenderer(parent: parentNode?.outputNode) - strokeProperties = StrokeNodeProperties(stroke: stroke) - self.parentNode = parentNode - } - - // MARK: Internal - - let strokeRender: StrokeRenderer - - let strokeProperties: StrokeNodeProperties - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - - var renderer: NodeOutput & Renderable { - strokeRender - } - - // MARK: Animator Node Protocol - - var propertyMap: NodePropertyMap & KeypathSearchable { - strokeProperties - } - - var isEnabled = true { - didSet { - strokeRender.isEnabled = isEnabled - } - } - - func localUpdatesPermeateDownstream() -> Bool { - false - } - - func rebuildOutputs(frame _: CGFloat) { - strokeRender.color = strokeProperties.color.value.cgColorValue - strokeRender.opacity = strokeProperties.opacity.value.cgFloatValue * 0.01 - strokeRender.width = strokeProperties.width.value.cgFloatValue - strokeRender.miterLimit = strokeProperties.miterLimit - strokeRender.lineCap = strokeProperties.lineCap - strokeRender.lineJoin = strokeProperties.lineJoin - - /// Get dash lengths - let dashLengths = strokeProperties.dashPattern.value.map { $0.cgFloatValue } - if dashLengths.count > 0, dashLengths.isSupportedLayerDashPattern { - strokeRender.dashPhase = strokeProperties.dashPhase.value.cgFloatValue - strokeRender.dashLengths = dashLengths - } else { - strokeRender.dashLengths = nil - strokeRender.dashPhase = nil - } - } - -} - -// MARK: - [DashElement] + shapeLayerConfiguration - -extension [DashElement] { - typealias ShapeLayerConfiguration = ( - dashPatterns: ContiguousArray>>, - dashPhase: ContiguousArray>) - - /// Converts the `[DashElement]` data model into `lineDashPattern` and `lineDashPhase` - /// representations usable in a `CAShapeLayer` - var shapeLayerConfiguration: ShapeLayerConfiguration { - var dashPatterns = ContiguousArray>>() - var dashPhase = ContiguousArray>() - for dash in self { - if dash.type == .offset { - dashPhase = dash.value.keyframes - } else { - dashPatterns.append(dash.value.keyframes) - } - } - - dashPatterns = ContiguousArray(dashPatterns.map { pattern in - ContiguousArray(pattern.map { keyframe -> Keyframe in - // The recommended way to create a stroke of round dots, in theory, - // is to use a value of 0 followed by the stroke width, but for - // some reason Core Animation incorrectly (?) renders these as pills - // instead of circles. As a workaround, for parity with Lottie on other - // platforms, we can change `0`s to `0.01`: https://stackoverflow.com/a/38036486 - if keyframe.value.cgFloatValue == 0 { - return keyframe.withValue(LottieVector1D(0.01)) - } else { - return keyframe - } - }) - }) - - return (dashPatterns, dashPhase) - } -} - -extension [CGFloat] { - // If all of the items in the dash pattern are zeros, then we shouldn't attempt to render it. - // This causes Core Animation to have extremely poor performance for some reason, even though - // it doesn't affect the appearance of the animation. - // - We check for `== 0.01` instead of `== 0` because `dashPattern.shapeLayerConfiguration` - // converts all `0` values to `0.01` to work around a different Core Animation rendering issue. - var isSupportedLayerDashPattern: Bool { - !allSatisfy { $0 == 0.01 } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift deleted file mode 100644 index cb4b04068e8132a3ca27fc740a4e215404510b32..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +++ /dev/null @@ -1,287 +0,0 @@ -// -// TextAnimatorNode.swift -// lottie-ios-iOS -// -// Created by Brandon Withrow on 2/19/19. -// - -import QuartzCore - -// MARK: - TextAnimatorNodeProperties - -final class TextAnimatorNodeProperties: NodePropertyMap, KeypathSearchable { - - // MARK: Lifecycle - - init(textAnimator: TextAnimator) { - keypathName = textAnimator.name - var properties = [String : AnyNodeProperty]() - - if let keyframeGroup = textAnimator.anchor { - anchor = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties["Anchor"] = anchor - } else { - anchor = nil - } - - if let keyframeGroup = textAnimator.position { - position = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties[PropertyName.position.rawValue] = position - } else { - position = nil - } - - if let keyframeGroup = textAnimator.scale { - scale = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties[PropertyName.scale.rawValue] = scale - } else { - scale = nil - } - - if let keyframeGroup = textAnimator.skew { - skew = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties["Skew"] = skew - } else { - skew = nil - } - - if let keyframeGroup = textAnimator.skewAxis { - skewAxis = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties["Skew Axis"] = skewAxis - } else { - skewAxis = nil - } - - if let keyframeGroup = textAnimator.rotationX { - rotationX = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties["Rotation X"] = rotationX - } else { - rotationX = nil - } - - if let keyframeGroup = textAnimator.rotationY { - rotationY = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties["Rotation Y"] = rotationY - } else { - rotationY = nil - } - - if let keyframeGroup = textAnimator.rotationZ { - rotationZ = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties["Rotation Z"] = rotationZ - properties[PropertyName.rotation.rawValue] = rotationZ - } else { - rotationZ = nil - } - - if let keyframeGroup = textAnimator.opacity { - opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties[PropertyName.opacity.rawValue] = opacity - } else { - opacity = nil - } - - if let keyframeGroup = textAnimator.strokeColor { - strokeColor = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties["Stroke Color"] = strokeColor - } else { - strokeColor = nil - } - - if let keyframeGroup = textAnimator.fillColor { - fillColor = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties["Fill Color"] = fillColor - } else { - fillColor = nil - } - - if let keyframeGroup = textAnimator.strokeWidth { - strokeWidth = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties[PropertyName.strokeWidth.rawValue] = strokeWidth - } else { - strokeWidth = nil - } - - if let keyframeGroup = textAnimator.tracking { - tracking = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes)) - properties["Tracking"] = tracking - } else { - tracking = nil - } - - keypathProperties = properties - - self.properties = Array(keypathProperties.values) - } - - // MARK: Internal - - let keypathName: String - - let anchor: NodeProperty? - let position: NodeProperty? - let scale: NodeProperty? - let skew: NodeProperty? - let skewAxis: NodeProperty? - let rotationX: NodeProperty? - let rotationY: NodeProperty? - let rotationZ: NodeProperty? - let opacity: NodeProperty? - let strokeColor: NodeProperty? - let fillColor: NodeProperty? - let strokeWidth: NodeProperty? - let tracking: NodeProperty? - - let keypathProperties: [String: AnyNodeProperty] - let properties: [AnyNodeProperty] - - var caTransform: CATransform3D { - CATransform3D.makeTransform( - anchor: anchor?.value.pointValue ?? .zero, - position: position?.value.pointValue ?? .zero, - scale: scale?.value.sizeValue ?? CGSize(width: 100, height: 100), - rotationX: rotationX?.value.cgFloatValue ?? 0, - rotationY: rotationY?.value.cgFloatValue ?? 0, - rotationZ: rotationZ?.value.cgFloatValue ?? 0, - skew: skew?.value.cgFloatValue, - skewAxis: skewAxis?.value.cgFloatValue) - } -} - -// MARK: - TextOutputNode - -final class TextOutputNode: NodeOutput { - - // MARK: Lifecycle - - init(parent: TextOutputNode?) { - parentTextNode = parent - } - - // MARK: Internal - - var parentTextNode: TextOutputNode? - var isEnabled = true - - var outputPath: CGPath? - - var parent: NodeOutput? { - parentTextNode - } - - var xform: CATransform3D { - get { - _xform ?? parentTextNode?.xform ?? CATransform3DIdentity - } - set { - _xform = newValue - } - } - - var opacity: CGFloat { - get { - _opacity ?? parentTextNode?.opacity ?? 1 - } - set { - _opacity = newValue - } - } - - var strokeColor: CGColor? { - get { - _strokeColor ?? parentTextNode?.strokeColor - } - set { - _strokeColor = newValue - } - } - - var fillColor: CGColor? { - get { - _fillColor ?? parentTextNode?.fillColor - } - set { - _fillColor = newValue - } - } - - var tracking: CGFloat { - get { - _tracking ?? parentTextNode?.tracking ?? 0 - } - set { - _tracking = newValue - } - } - - var strokeWidth: CGFloat { - get { - _strokeWidth ?? parentTextNode?.strokeWidth ?? 0 - } - set { - _strokeWidth = newValue - } - } - - func hasOutputUpdates(_: CGFloat) -> Bool { - // TODO Fix This - true - } - - // MARK: Fileprivate - - fileprivate var _xform: CATransform3D? - fileprivate var _opacity: CGFloat? - fileprivate var _strokeColor: CGColor? - fileprivate var _fillColor: CGColor? - fileprivate var _tracking: CGFloat? - fileprivate var _strokeWidth: CGFloat? -} - -// MARK: - TextAnimatorNode - -class TextAnimatorNode: AnimatorNode { - - // MARK: Lifecycle - - init(parentNode: TextAnimatorNode?, textAnimator: TextAnimator) { - textOutputNode = TextOutputNode(parent: parentNode?.textOutputNode) - textAnimatorProperties = TextAnimatorNodeProperties(textAnimator: textAnimator) - self.parentNode = parentNode - } - - // MARK: Internal - - let textOutputNode: TextOutputNode - - let textAnimatorProperties: TextAnimatorNodeProperties - - let parentNode: AnimatorNode? - var hasLocalUpdates = false - var hasUpstreamUpdates = false - var lastUpdateFrame: CGFloat? = nil - var isEnabled = true - - var outputNode: NodeOutput { - textOutputNode - } - - // MARK: Animator Node Protocol - - var propertyMap: NodePropertyMap & KeypathSearchable { - textAnimatorProperties - } - - func localUpdatesPermeateDownstream() -> Bool { - true - } - - func rebuildOutputs(frame _: CGFloat) { - textOutputNode.xform = textAnimatorProperties.caTransform - textOutputNode.opacity = (textAnimatorProperties.opacity?.value.cgFloatValue ?? 100) * 0.01 - textOutputNode.strokeColor = textAnimatorProperties.strokeColor?.value.cgColorValue - textOutputNode.fillColor = textAnimatorProperties.fillColor?.value.cgColorValue - textOutputNode.tracking = textAnimatorProperties.tracking?.value.cgFloatValue ?? 1 - textOutputNode.strokeWidth = textAnimatorProperties.strokeWidth?.value.cgFloatValue ?? 0 - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Protocols/AnimatorNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Protocols/AnimatorNode.swift deleted file mode 100644 index 82bc247b39e12ed40f7b2f1f6db1b8d9354613c3..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Protocols/AnimatorNode.swift +++ /dev/null @@ -1,197 +0,0 @@ -// -// AnimatorNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/15/19. -// - -import QuartzCore - -// MARK: - NodeOutput - -/// Defines the basic outputs of an animator node. -/// -protocol NodeOutput { - - /// The parent node. - var parent: NodeOutput? { get } - - /// Returns true if there are any updates upstream. OutputPath must be built before returning. - func hasOutputUpdates(_ forFrame: CGFloat) -> Bool - - var outputPath: CGPath? { get } - - var isEnabled: Bool { get set } -} - -// MARK: - AnimatorNode - -/// The Animator Node is the base node in the render system tree. -/// -/// It defines a single node that has an output path and option input node. -/// At animation time the root animation node is asked to update its contents for -/// the current frame. -/// The node reaches up its chain of nodes until the first node that does not need -/// updating is found. Then each node updates its contents down the render pipeline. -/// Each node adds its local path to its input path and passes it forward. -/// -/// An animator node holds a group of interpolators. These interpolators determine -/// if the node needs an update for the current frame. -/// -protocol AnimatorNode: AnyObject, KeypathSearchable { - - /// The available properties of the Node. - /// - /// These properties are automatically updated each frame. - /// These properties are also settable and gettable through the dynamic - /// property system. - /// - var propertyMap: NodePropertyMap & KeypathSearchable { get } - - /// The upstream input node - var parentNode: AnimatorNode? { get } - - /// The output of the node. - var outputNode: NodeOutput { get } - - /// Update the outputs of the node. Called if local contents were update or if outputsNeedUpdate returns true. - func rebuildOutputs(frame: CGFloat) - - /// Setters for marking current node state. - var isEnabled: Bool { get set } - var hasLocalUpdates: Bool { get set } - var hasUpstreamUpdates: Bool { get set } - var lastUpdateFrame: CGFloat? { get set } - - // MARK: Optional - - /// Marks if updates to this node affect nodes downstream. - func localUpdatesPermeateDownstream() -> Bool - func forceUpstreamOutputUpdates() -> Bool - - /// Called at the end of this nodes update cycle. Always called. Optional. - func performAdditionalLocalUpdates(frame: CGFloat, forceLocalUpdate: Bool) -> Bool - func performAdditionalOutputUpdates(_ frame: CGFloat, forceOutputUpdate: Bool) - - /// The default simply returns `hasLocalUpdates` - func shouldRebuildOutputs(frame: CGFloat) -> Bool -} - -/// Basic Node Logic -extension AnimatorNode { - - func shouldRebuildOutputs(frame _: CGFloat) -> Bool { - hasLocalUpdates - } - - func localUpdatesPermeateDownstream() -> Bool { - /// Optional override - true - } - - func forceUpstreamOutputUpdates() -> Bool { - /// Optional - false - } - - func performAdditionalLocalUpdates(frame _: CGFloat, forceLocalUpdate: Bool) -> Bool { - /// Optional - forceLocalUpdate - } - - func performAdditionalOutputUpdates(_: CGFloat, forceOutputUpdate _: Bool) { - /// Optional - } - - @discardableResult - func updateOutputs(_ frame: CGFloat, forceOutputUpdate: Bool) -> Bool { - guard isEnabled else { - // Disabled node, pass through. - lastUpdateFrame = frame - return parentNode?.updateOutputs(frame, forceOutputUpdate: forceOutputUpdate) ?? false - } - - if forceOutputUpdate == false && lastUpdateFrame != nil && lastUpdateFrame! == frame { - /// This node has already updated for this frame. Go ahead and return the results. - return hasUpstreamUpdates || hasLocalUpdates - } - - /// Ask if this node should force output updates upstream. - let forceUpstreamUpdates = forceOutputUpdate || forceUpstreamOutputUpdates() - - /// Perform upstream output updates. Optionally mark upstream updates if any. - hasUpstreamUpdates = ( - parentNode? - .updateOutputs(frame, forceOutputUpdate: forceUpstreamUpdates) ?? false || hasUpstreamUpdates) - - /// Perform additional local output updates - performAdditionalOutputUpdates(frame, forceOutputUpdate: forceUpstreamUpdates) - - /// If there are local updates, or if updates have been force, rebuild outputs - if forceUpstreamUpdates || shouldRebuildOutputs(frame: frame) { - lastUpdateFrame = frame - rebuildOutputs(frame: frame) - } - return hasUpstreamUpdates || hasLocalUpdates - } - - /// Rebuilds the content of this node, and upstream nodes if necessary. - @discardableResult - func updateContents(_ frame: CGFloat, forceLocalUpdate: Bool) -> Bool { - guard isEnabled else { - // Disabled node, pass through. - return parentNode?.updateContents(frame, forceLocalUpdate: forceLocalUpdate) ?? false - } - - if forceLocalUpdate == false && lastUpdateFrame != nil && lastUpdateFrame! == frame { - /// This node has already updated for this frame. Go ahead and return the results. - return localUpdatesPermeateDownstream() ? hasUpstreamUpdates || hasLocalUpdates : hasUpstreamUpdates - } - - /// Are there local updates? If so mark the node. - hasLocalUpdates = forceLocalUpdate ? forceLocalUpdate : propertyMap.needsLocalUpdate(frame: frame) - - /// Were there upstream updates? If so mark the node - hasUpstreamUpdates = parentNode?.updateContents(frame, forceLocalUpdate: forceLocalUpdate) ?? false - - /// Perform property updates if necessary. - if hasLocalUpdates { - /// Rebuild local properties - propertyMap.updateNodeProperties(frame: frame) - } - - /// Ask the node to perform any other updates it might have. - hasUpstreamUpdates = performAdditionalLocalUpdates(frame: frame, forceLocalUpdate: forceLocalUpdate) || hasUpstreamUpdates - - /// If the node can update nodes downstream, notify them, otherwise pass on any upstream updates downstream. - return localUpdatesPermeateDownstream() ? hasUpstreamUpdates || hasLocalUpdates : hasUpstreamUpdates - } - - func updateTree(_ frame: CGFloat, forceUpdates: Bool = false) { - updateContents(frame, forceLocalUpdate: forceUpdates) - updateOutputs(frame, forceOutputUpdate: forceUpdates) - } - -} - -extension AnimatorNode { - /// Default implementation for Keypath searchable. - /// Forward all calls to the propertyMap. - - var keypathName: String { - propertyMap.keypathName - } - - var keypathProperties: [String: AnyNodeProperty] { - propertyMap.keypathProperties - } - - var childKeypaths: [KeypathSearchable] { - propertyMap.childKeypaths - } - - var keypathLayer: CALayer? { - nil - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Protocols/PathNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Protocols/PathNode.swift deleted file mode 100644 index defae81534c6537ffe69d5dca61bef9f61207f34..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Protocols/PathNode.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// PathNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/17/19. -// - -// MARK: - PathNode - -protocol PathNode { - var pathOutput: PathOutputNode { get } -} - -extension PathNode where Self: AnimatorNode { - - var outputNode: NodeOutput { - pathOutput - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Protocols/RenderNode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Protocols/RenderNode.swift deleted file mode 100644 index 959d47e00f6556360139f32899fb4452e19b810a..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/Protocols/RenderNode.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// RenderNode.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/17/19. -// - -import QuartzCore - -// MARK: - RenderNode - -/// A protocol that defines a node that holds render instructions -protocol RenderNode { - var renderer: Renderable & NodeOutput { get } -} - -// MARK: - Renderable - -/// A protocol that defines anything with render instructions -protocol Renderable { - - /// The last frame in which this node was updated. - var hasUpdate: Bool { get } - - func hasRenderUpdates(_ forFrame: CGFloat) -> Bool - - /// Determines if the renderer requires a custom context for drawing. - /// If yes the shape layer will perform a custom drawing pass. - /// If no the shape layer will be a standard CAShapeLayer - var shouldRenderInContext: Bool { get } - - /// Passes in the CAShapeLayer to update - func updateShapeLayer(layer: CAShapeLayer) - - /// Asks the renderer what the renderable bounds is for the given box. - func renderBoundsFor(_ boundingBox: CGRect) -> CGRect - - /// Opportunity for renderers to inject sublayers - func setupSublayers(layer: CAShapeLayer) - - /// Renders the shape in a custom context - func render(_ inContext: CGContext) -} - -extension RenderNode where Self: AnimatorNode { - - var outputNode: NodeOutput { - renderer - } - -} - -extension Renderable { - - func renderBoundsFor(_ boundingBox: CGRect) -> CGRect { - /// Optional - boundingBox - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift deleted file mode 100644 index fbe177762ca67eaaa5d9e801cd8d8e5b8f967d03..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +++ /dev/null @@ -1,78 +0,0 @@ -// -// ShapeContainerLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import QuartzCore - -/// The base layer that holds Shapes and Shape Renderers -class ShapeContainerLayer: CALayer { - - // MARK: Lifecycle - - override init() { - super.init() - actions = [ - "position" : NSNull(), - "bounds" : NSNull(), - "anchorPoint" : NSNull(), - "transform" : NSNull(), - "opacity" : NSNull(), - "hidden" : NSNull(), - ] - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override init(layer: Any) { - guard let layer = layer as? ShapeContainerLayer else { - fatalError("init(layer:) wrong class.") - } - super.init(layer: layer) - } - - // MARK: Internal - - private(set) var renderLayers: [ShapeContainerLayer] = [] - - var renderScale: CGFloat = 1 { - didSet { - updateRenderScale() - } - } - - func insertRenderLayer(_ layer: ShapeContainerLayer) { - renderLayers.append(layer) - insertSublayer(layer, at: 0) - } - - func markRenderUpdates(forFrame: CGFloat) { - if hasRenderUpdate(forFrame: forFrame) { - rebuildContents(forFrame: forFrame) - } - guard isHidden == false else { return } - for renderLayer in renderLayers { - renderLayer.markRenderUpdates(forFrame: forFrame) - } - } - - func hasRenderUpdate(forFrame _: CGFloat) -> Bool { - false - } - - func rebuildContents(forFrame _: CGFloat) { - /// Override - } - - func updateRenderScale() { - contentsScale = renderScale - for renderLayer in renderLayers { - renderLayer.renderScale = renderScale - } - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift deleted file mode 100644 index bd2eac2c5f94b8cf91842307c8c171b93b6d3e61..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// RenderLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/18/19. -// - -import QuartzCore - -/// The layer responsible for rendering shape objects -final class ShapeRenderLayer: ShapeContainerLayer { - - // MARK: Lifecycle - - init(renderer: Renderable & NodeOutput) { - self.renderer = renderer - super.init() - anchorPoint = .zero - actions = [ - "position" : NSNull(), - "bounds" : NSNull(), - "anchorPoint" : NSNull(), - "path" : NSNull(), - "transform" : NSNull(), - "opacity" : NSNull(), - "hidden" : NSNull(), - ] - shapeLayer.actions = [ - "position" : NSNull(), - "bounds" : NSNull(), - "anchorPoint" : NSNull(), - "path" : NSNull(), - "fillColor" : NSNull(), - "strokeColor" : NSNull(), - "lineWidth" : NSNull(), - "miterLimit" : NSNull(), - "lineDashPhase" : NSNull(), - "opacity": NSNull(), - "hidden" : NSNull(), - ] - addSublayer(shapeLayer) - - renderer.setupSublayers(layer: shapeLayer) - } - - override init(layer: Any) { - guard let layer = layer as? ShapeRenderLayer else { - fatalError("init(layer:) wrong class.") - } - renderer = layer.renderer - super.init(layer: layer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Internal - - fileprivate(set) var renderer: Renderable & NodeOutput - - let shapeLayer = CAShapeLayer() - - override func hasRenderUpdate(forFrame: CGFloat) -> Bool { - isHidden = !renderer.isEnabled - guard isHidden == false else { return false } - return renderer.hasRenderUpdates(forFrame) - } - - override func rebuildContents(forFrame _: CGFloat) { - if renderer.shouldRenderInContext { - if let newPath = renderer.outputPath { - bounds = renderer.renderBoundsFor(newPath.boundingBox) - } else { - bounds = .zero - } - position = bounds.origin - setNeedsDisplay() - } else { - shapeLayer.path = renderer.outputPath - renderer.updateShapeLayer(layer: shapeLayer) - } - } - - override func draw(in ctx: CGContext) { - if let path = renderer.outputPath { - if !path.isEmpty { - ctx.addPath(path) - } - } - renderer.render(ctx) - } - - override func updateRenderScale() { - super.updateRenderScale() - shapeLayer.contentsScale = renderScale - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/Asset.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/Asset.swift deleted file mode 100644 index 514f8226c44a02e3321248a13d03e9dc231a7867..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/Asset.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// Asset.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/9/19. -// - -// MARK: - Asset - -public class Asset: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - required public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Asset.CodingKeys.self) - if let id = try? container.decode(String.self, forKey: .id) { - self.id = id - } else { - id = String(try container.decode(Int.self, forKey: .id)) - } - } - - required init(dictionary: [String: Any]) throws { - if let id = dictionary[CodingKeys.id.rawValue] as? String { - self.id = id - } else if let id = dictionary[CodingKeys.id.rawValue] as? Int { - self.id = String(id) - } else { - throw InitializableError.invalidInput() - } - } - - // MARK: Public - - /// The ID of the asset - public let id: String - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case id - } -} - -// MARK: Sendable - -/// Since `Asset` isn't `final`, we have to use `@unchecked Sendable` instead of `Sendable.` -/// All `Asset` subclasses are immutable `Sendable` values. -// swiftlint:disable:next no_unchecked_sendable -extension Asset: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/AssetLibrary.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/AssetLibrary.swift deleted file mode 100644 index 7d00b0b7e181d3f819d1e7adcf83c3a62d8f347d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/AssetLibrary.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// AssetLibrary.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/9/19. -// - -final class AssetLibrary: Codable, AnyInitializable, Sendable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - var container = try decoder.unkeyedContainer() - var containerForKeys = container - - var decodedAssets = [String : Asset]() - - var imageAssets = [String : ImageAsset]() - var precompAssets = [String : PrecompAsset]() - - while - !container.isAtEnd, - let keyContainer = try? containerForKeys.nestedContainer(keyedBy: PrecompAsset.CodingKeys.self) - { - if - keyContainer.contains(.layers), - let precompAsset = try? container.decode(PrecompAsset.self) - { - decodedAssets[precompAsset.id] = precompAsset - precompAssets[precompAsset.id] = precompAsset - } else if let imageAsset = try? container.decode(ImageAsset.self) { - decodedAssets[imageAsset.id] = imageAsset - imageAssets[imageAsset.id] = imageAsset - } - } - assets = decodedAssets - self.precompAssets = precompAssets - self.imageAssets = imageAssets - } - - init(value: Any) throws { - guard let dictionaries = value as? [[String: Any]] else { - throw InitializableError.invalidInput() - } - var decodedAssets = [String : Asset]() - var imageAssets = [String : ImageAsset]() - var precompAssets = [String : PrecompAsset]() - for dictionary in dictionaries { - if dictionary[PrecompAsset.CodingKeys.layers.rawValue] != nil { - let asset = try PrecompAsset(dictionary: dictionary) - decodedAssets[asset.id] = asset - precompAssets[asset.id] = asset - } else if let asset = try? ImageAsset(dictionary: dictionary) { - decodedAssets[asset.id] = asset - imageAssets[asset.id] = asset - } - } - assets = decodedAssets - self.precompAssets = precompAssets - self.imageAssets = imageAssets - } - - // MARK: Internal - - /// The Assets - let assets: [String: Asset] - - let imageAssets: [String: ImageAsset] - let precompAssets: [String: PrecompAsset] - - func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - try container.encode(contentsOf: Array(assets.values)) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/ImageAsset.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/ImageAsset.swift deleted file mode 100644 index 4dc77d2f9db5d34a3d71c36306bbb8a1eb4e7d45..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/ImageAsset.swift +++ /dev/null @@ -1,133 +0,0 @@ -// -// ImageAsset.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/9/19. -// - -import CoreGraphics -import Foundation - -#if canImport(UIKit) -import UIKit -#elseif canImport(AppKit) -import AppKit -#endif - -// MARK: - ImageAsset - -public final class ImageAsset: Asset { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: ImageAsset.CodingKeys.self) - name = try container.decode(String.self, forKey: .name) - directory = try container.decode(String.self, forKey: .directory) - width = try container.decode(Double.self, forKey: .width) - height = try container.decode(Double.self, forKey: .height) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - name = try dictionary.value(for: CodingKeys.name) - directory = try dictionary.value(for: CodingKeys.directory) - width = try dictionary.value(for: CodingKeys.width) - height = try dictionary.value(for: CodingKeys.height) - try super.init(dictionary: dictionary) - } - - // MARK: Public - - /// Image name - public let name: String - - /// Image Directory - public let directory: String - - /// Image Size - public let width: Double - - public let height: Double - - override public func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(name, forKey: .name) - try container.encode(directory, forKey: .directory) - try container.encode(width, forKey: .width) - try container.encode(height, forKey: .height) - } - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case name = "p" - case directory = "u" - case width = "w" - case height = "h" - } -} - -extension Data { - - // MARK: Lifecycle - - /// Initializes `Data` from an `ImageAsset`. - /// - /// Returns nil when the input is not recognized as valid Data URL. - /// - parameter imageAsset: The image asset that contains Data URL. - init?(imageAsset: ImageAsset) { - self.init(dataString: imageAsset.name) - } - - /// Initializes `Data` from a [Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) String. - /// - /// Returns nil when the input is not recognized as valid Data URL. - /// - parameter dataString: The data string to parse. - /// - parameter options: Options for the string parsing. Default value is `[]`. - init?(dataString: String, options: DataURLReadOptions = []) { - let trimmedDataString = dataString.trimmingCharacters(in: .whitespacesAndNewlines) - guard - dataString.hasPrefix("data:"), - let url = URL(string: trimmedDataString) - else { - return nil - } - // The code below is needed because Data(contentsOf:) floods logs - // with messages since url doesn't have a host. This only fixes flooding logs - // when data inside Data URL is base64 encoded. - if - let base64Range = trimmedDataString.range(of: ";base64,"), - !options.contains(DataURLReadOptions.legacy) - { - let encodedString = String(trimmedDataString[base64Range.upperBound...]) - self.init(base64Encoded: encodedString) - } else { - try? self.init(contentsOf: url) - } - } - - // MARK: Internal - - struct DataURLReadOptions: OptionSet { - let rawValue: Int - - /// Will read Data URL using Data(contentsOf:) - static let legacy = DataURLReadOptions(rawValue: 1 << 0) - } - -} - -extension ImageAsset { - /// A `CGImage` loaded from this asset if represented using a Base 64 encoding - var base64Image: CGImage? { - guard let data = Data(imageAsset: self) else { return nil } - - #if canImport(UIKit) - return UIImage(data: data)?.cgImage - #elseif canImport(AppKit) - return NSImage(data: data)?.lottie_CGImage - #endif - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/PrecompAsset.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/PrecompAsset.swift deleted file mode 100644 index dfd955e3761fbb4d1dc81afb9517caf1547f2c19..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Assets/PrecompAsset.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// PrecompAsset.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/9/19. -// - -final class PrecompAsset: Asset { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: PrecompAsset.CodingKeys.self) - layers = try container.decode([LayerModel].self, ofFamily: LayerType.self, forKey: .layers) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let layerDictionaries: [[String: Any]] = try dictionary.value(for: CodingKeys.layers) - layers = try [LayerModel].fromDictionaries(layerDictionaries) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case layers - } - - /// Layers of the precomp - let layers: [LayerModel] - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(layers, forKey: .layers) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DictionaryInitializable.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DictionaryInitializable.swift deleted file mode 100644 index 992f8f87457a2e3ee4e82d83823a0759c9014f83..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DictionaryInitializable.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// DictionaryInitializable.swift -// Lottie -// -// Created by Marcelo Fabri on 5/5/22. -// - -// MARK: - InitializableError - -enum InitializableError: Error { - case invalidInput(file: StaticString = #file, line: UInt = #line) -} - -// MARK: - DictionaryInitializable - -protocol DictionaryInitializable { - - init(dictionary: [String: Any]) throws - -} - -// MARK: - AnyInitializable - -protocol AnyInitializable { - - init(value: Any) throws - -} - -extension Dictionary { - - @_disfavoredOverload - func value( - for key: KeyType, - file: StaticString = #file, - line: UInt = #line) - throws -> T where KeyType.RawValue == Key - { - guard let value = self[key.rawValue] as? T else { - throw InitializableError.invalidInput(file: file, line: line) - } - return value - } - - func value( - for key: KeyType, - file: StaticString = #file, - line: UInt = #line) - throws -> T where KeyType.RawValue == Key - { - if let value = self[key.rawValue] as? T { - return value - } - - if let value = self[key.rawValue] { - return try T(value: value) - } - - throw InitializableError.invalidInput(file: file, line: line) - } - -} - -// MARK: - AnyInitializable + AnyInitializable - -extension [Double]: AnyInitializable { - - init(value: Any) throws { - guard let array = value as? [Double] else { - throw InitializableError.invalidInput() - } - self = array - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieAnimation.swift deleted file mode 100644 index e751615d7637eaee8d0e5f6c9c6404a0abae12e8..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieAnimation.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// DotLottieAnimation.swift -// Pods -// -// Created by Evandro Harrison Hoffmann on 28/06/2021. -// - -import Foundation - -// MARK: - DotLottieAnimation - -struct DotLottieAnimation: Codable { - /// Id of Animation - var id: String - - /// Loop enabled - var loop: Bool? = false - - /// Animation Playback Speed - var speed: Double? = 1 - - /// 1 or -1 - var direction: Int? = 1 - - /// mode - "bounce" | "normal" - var mode: DotLottieAnimationMode? = .normal - - /// Loop mode for animation - var loopMode: LottieLoopMode { - switch mode { - case .bounce: - return .autoReverse - case .normal, nil: - return (loop ?? false) ? .loop : .playOnce - } - } - - /// Animation speed - var animationSpeed: Double { - (speed ?? 1) * Double(direction ?? 1) - } - - /// Loads `LottieAnimation` from `animationUrl` - /// - Returns: Deserialized `LottieAnimation`. Optional. - func animation(url: URL) throws -> LottieAnimation { - let animationUrl = url.appendingPathComponent("\(id).json") - let data = try Data(contentsOf: animationUrl) - return try LottieAnimation.from(data: data) - } -} - -// MARK: - DotLottieAnimationMode - -enum DotLottieAnimationMode: String, Codable { - case normal - case bounce -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieImageProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieImageProvider.swift deleted file mode 100644 index e426fc0a2468bc0150baae5aa1ebd750cd1317ec..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieImageProvider.swift +++ /dev/null @@ -1,89 +0,0 @@ -// -// DotLottieImageProvider.swift -// Lottie -// -// Created by Evandro Hoffmann on 20/10/22. -// - -#if canImport(UIKit) -import UIKit -#elseif canImport(AppKit) -import AppKit -#endif - -// MARK: - DotLottieImageProvider - -/// An image provider that loads the images from a DotLottieFile into memory -class DotLottieImageProvider: AnimationImageProvider { - - // MARK: Lifecycle - - /// Initializes an image provider with a specific filepath. - /// - /// - Parameter filepath: The absolute filepath containing the images. - /// - convenience init?(filepath: String) { - self.init(filepath: URL(fileURLWithPath: filepath)) - } - - init?(filepath: URL) { - guard filepath.urls.count > 0 else { return nil } - self.filepath = filepath - loadImages() - } - - // MARK: Internal - - let filepath: URL - - func imageForAsset(asset: ImageAsset) -> CGImage? { - if let base64Image = asset.base64Image { - return base64Image - } - - return images[asset.name] - } - - // MARK: Private - - /// This is intentionally a Dictionary instead of an NSCache. Files from a decompressed dotLottie zip archive - /// are only valid are deleted after being read into memory. If we used an NSCache then the OS could evict - /// the cache entries when under memory pressure, and we would have no way to reload them later. - /// - Ideally we would have a way to remove image data when under memory pressure, but this would require - /// re-decompressing the dotLottie file when requesting an image that has been loaded but then removed. - private var images = [String: CGImage]() - - private func loadImages() { - for url in filepath.urls { - #if canImport(UIKit) - if - let data = try? Data(contentsOf: url), - let image = UIImage(data: data)?.cgImage - { - images[url.lastPathComponent] = image - } - #elseif canImport(AppKit) - if - let data = try? Data(contentsOf: url), - let image = NSImage(data: data)?.lottie_CGImage - { - images[url.lastPathComponent] = image - } - #endif - } - } - -} - -// MARK: Hashable - -extension DotLottieImageProvider: Hashable { - static func ==(_ lhs: DotLottieImageProvider, _ rhs: DotLottieImageProvider) -> Bool { - lhs.filepath == rhs.filepath - } - - func hash(into hasher: inout Hasher) { - hasher.combine(filepath) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieManifest.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieManifest.swift deleted file mode 100644 index d475092852f4e0edea3033ca596aadd40d2b9e7c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieManifest.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// DotLottieManifest.swift -// Lottie -// -// Created by Evandro Harrison Hoffmann on 27/06/2020. -// - -import Foundation - -/// Manifest model for .lottie File -struct DotLottieManifest: Codable { - - var animations: [DotLottieAnimation] - var version: String? - var author: String? - var generator: String? - - /// Decodes data to Manifest model - /// - Parameter data: Data to decode - /// - Throws: Error - /// - Returns: .lottie Manifest model - static func decode(from data: Data) throws -> DotLottieManifest { - try JSONDecoder().decode(DotLottieManifest.self, from: data) - } - - /// Loads manifest from given URL - /// - Parameter path: URL path to Manifest - /// - Returns: Manifest Model - static func load(from url: URL) throws -> DotLottieManifest { - let data = try Data(contentsOf: url) - return try decode(from: data) - } - - /// Encodes to data - /// - Parameter encoder: JSONEncoder - /// - Throws: Error - /// - Returns: encoded Data - func encode(with encoder: JSONEncoder = JSONEncoder()) throws -> Data { - try encoder.encode(self) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieUtils.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieUtils.swift deleted file mode 100644 index 72994dec255a948d9574bbe788b1e7e88a9a9c5d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/DotLottie/DotLottieUtils.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// DotLottieUtils.swift -// Lottie -// -// Created by Evandro Harrison Hoffmann on 27/06/2020. -// - -import Foundation - -// MARK: - DotLottieUtils - -enum DotLottieUtils { - static let dotLottieExtension = "lottie" - static let jsonExtension = "json" - - /// Temp folder to app directory - static var tempDirectoryURL: URL { - if #available(iOS 10.0, macOS 10.12, *) { - return FileManager.default.temporaryDirectory - } - return URL(fileURLWithPath: NSTemporaryDirectory()) - } -} - -extension URL { - /// Checks if url is a lottie file - var isDotLottie: Bool { - pathExtension == DotLottieUtils.dotLottieExtension - } - - /// Checks if url is a json file - var isJsonFile: Bool { - pathExtension == DotLottieUtils.jsonExtension - } - - var urls: [URL] { - FileManager.default.urls(for: self) ?? [] - } -} - -extension FileManager { - /// Lists urls for all files in a directory - /// - Parameters: - /// - url: URL of directory to search - /// - skipsHiddenFiles: If should or not show hidden files - /// - Returns: Returns urls of all files matching criteria in the directory - func urls(for url: URL, skipsHiddenFiles: Bool = true) -> [URL]? { - try? contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: skipsHiddenFiles ? .skipsHiddenFiles : []) - } -} - -// MARK: - DotLottieError - -public enum DotLottieError: Error { - /// URL response has no data. - case noDataLoaded - /// Asset with this name was not found in the provided bundle. - case assetNotFound(name: String, bundle: Bundle?) - /// Animation loading from asset is not supported on macOS 10.10. - case loadingFromAssetNotSupported - - @available(*, deprecated, message: "Unused") - case invalidFileFormat - @available(*, deprecated, message: "Unused") - case invalidData - @available(*, deprecated, message: "Unused") - case animationNotAvailable -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Extensions/Bundle.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Extensions/Bundle.swift deleted file mode 100644 index 65f7c5b3a5cec0ec2153582eb4920418350a45eb..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Extensions/Bundle.swift +++ /dev/null @@ -1,51 +0,0 @@ -import Foundation -#if canImport(UIKit) -import UIKit -#endif - -extension Bundle { - func getAnimationData(_ name: String, subdirectory: String? = nil) throws -> Data { - // Check for files in the bundle at the given path - let name = name.removingJSONSuffix() - if let url = url(forResource: name, withExtension: "json", subdirectory: subdirectory) { - return try Data(contentsOf: url) - } - - // Check for data assets - let assetKey = subdirectory != nil ? "\(subdirectory ?? "")/\(name)" : name - return try Data(assetName: assetKey, in: self) - } - - func dotLottieData(_ name: String, subdirectory: String? = nil) throws -> Data { - // Check for files in the bundle at the given path - let name = name.removingDotLottieSuffix() - if let url = url(forResource: name, withExtension: "lottie", subdirectory: subdirectory) { - return try Data(contentsOf: url) - } - - let assetKey = subdirectory != nil ? "\(subdirectory ?? "")/\(name)" : name - return try Data(assetName: assetKey, in: self) - } -} - -extension String { - fileprivate func removingJSONSuffix() -> String { - // Allow filenames to be passed with a ".json" extension (but not other extensions) - // to keep the behavior from Lottie 2.x - instead of failing to load the animation - guard hasSuffix(".json") else { - return self - } - - return (self as NSString).deletingPathExtension - } - - fileprivate func removingDotLottieSuffix() -> String { - // Allow filenames to be passed with a ".lottie" extension (but not other extensions) - // to keep the behavior from Lottie 2.x - instead of failing to load the file - guard hasSuffix(".lottie") else { - return self - } - - return (self as NSString).deletingPathExtension - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift deleted file mode 100644 index 01e9d80cb1bcd24684a1ae8e8f5d90f067d3aa35..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift +++ /dev/null @@ -1,71 +0,0 @@ -// From: https://medium.com/@kewindannerfjordremeczki/swift-4-0-decodable-heterogeneous-collections-ecc0e6b468cf - -// MARK: - ClassFamily - -/// To support a new class family, create an enum that conforms to this protocol and contains the different types. -protocol ClassFamily: Decodable { - /// The discriminator key. - static var discriminator: Discriminator { get } - - /// The "unknown" fallback case if the type discriminator could not be parsed successfully. - static var unknown: Self { get } - - /// Returns the class type of the object corresponding to the value. - func getType() -> AnyObject.Type -} - -// MARK: - Discriminator - -/// Discriminator key enum used to retrieve discriminator fields in JSON payloads. -enum Discriminator: String, CodingKey { - case type = "ty" -} - -extension KeyedDecodingContainer { - - /// Decode a heterogeneous list of objects for a given family. - /// - Parameters: - /// - heterogeneousType: The decodable type of the list. - /// - family: The ClassFamily enum for the type family. - /// - key: The CodingKey to look up the list in the current container. - /// - Returns: The resulting list of heterogeneousType elements. - func decode(_: [T].Type, ofFamily family: U.Type, forKey key: K) throws -> [T] { - var container = try nestedUnkeyedContainer(forKey: key) - var list = [T]() - var tmpContainer = container - while !container.isAtEnd { - let typeContainer = try container.nestedContainer(keyedBy: Discriminator.self) - let family: U = (try? typeContainer.decodeIfPresent(U.self, forKey: U.discriminator)) ?? .unknown - if let type = family.getType() as? T.Type { - list.append(try tmpContainer.decode(type)) - } - } - return list - } - - /// Decode a heterogeneous list of objects for a given family if the given key is present. - /// - Parameters: - /// - heterogeneousType: The decodable type of the list. - /// - family: The ClassFamily enum for the type family. - /// - key: The CodingKey to look up the list in the current container. - /// - Returns: The resulting list of heterogeneousType elements. - func decodeIfPresent(_: [T].Type, ofFamily family: U.Type, forKey key: K) throws -> [T]? { - var container: UnkeyedDecodingContainer - do { - container = try nestedUnkeyedContainer(forKey: key) - } catch { - return nil - } - - var list = [T]() - var tmpContainer = container - while !container.isAtEnd { - let typeContainer = try container.nestedContainer(keyedBy: Discriminator.self) - let family: U = (try? typeContainer.decodeIfPresent(U.self, forKey: U.discriminator)) ?? .unknown - if let type = family.getType() as? T.Type { - list.append(try tmpContainer.decode(type)) - } - } - return list - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Keyframes/KeyframeData.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Keyframes/KeyframeData.swift deleted file mode 100644 index 753d7f028309dede72389e0f7e2c03b6d1ec3563..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Keyframes/KeyframeData.swift +++ /dev/null @@ -1,110 +0,0 @@ -// -// Keyframe.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/7/19. -// - -// MARK: - KeyframeData - -/// A generic class used to parse and remap keyframe json. -/// -/// Keyframe json has a couple of different variations and formats depending on the -/// type of keyframea and also the version of the JSON. By parsing the raw data -/// we can reconfigure it into a constant format. -final class KeyframeData { - - // MARK: Lifecycle - - init( - startValue: T?, - endValue: T?, - time: AnimationFrameTime?, - hold: Int?, - inTangent: LottieVector2D?, - outTangent: LottieVector2D?, - spatialInTangent: LottieVector3D?, - spatialOutTangent: LottieVector3D?) - { - self.startValue = startValue - self.endValue = endValue - self.time = time - self.hold = hold - self.inTangent = inTangent - self.outTangent = outTangent - self.spatialInTangent = spatialInTangent - self.spatialOutTangent = spatialOutTangent - } - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case startValue = "s" - case endValue = "e" - case time = "t" - case hold = "h" - case inTangent = "i" - case outTangent = "o" - case spatialInTangent = "ti" - case spatialOutTangent = "to" - } - - /// The start value of the keyframe - let startValue: T? - /// The End value of the keyframe. Note: Newer versions animation json do not have this field. - let endValue: T? - /// The time in frames of the keyframe. - let time: AnimationFrameTime? - /// A hold keyframe freezes interpolation until the next keyframe that is not a hold. - let hold: Int? - - /// The in tangent for the time interpolation curve. - let inTangent: LottieVector2D? - /// The out tangent for the time interpolation curve. - let outTangent: LottieVector2D? - - /// The spacial in tangent of the vector. - let spatialInTangent: LottieVector3D? - /// The spacial out tangent of the vector. - let spatialOutTangent: LottieVector3D? - - var isHold: Bool { - if let hold { - return hold > 0 - } - return false - } -} - -// MARK: Encodable - -extension KeyframeData: Encodable where T: Encodable { } - -// MARK: Decodable - -extension KeyframeData: Decodable where T: Decodable { } - -// MARK: DictionaryInitializable - -extension KeyframeData: DictionaryInitializable where T: AnyInitializable { - convenience init(dictionary: [String: Any]) throws { - let startValue = try? dictionary[CodingKeys.startValue.rawValue].flatMap(T.init) - let endValue = try? dictionary[CodingKeys.endValue.rawValue].flatMap(T.init) - let time: AnimationFrameTime? = try? dictionary.value(for: CodingKeys.time) - let hold: Int? = try? dictionary.value(for: CodingKeys.hold) - let inTangent: LottieVector2D? = try? dictionary.value(for: CodingKeys.inTangent) - let outTangent: LottieVector2D? = try? dictionary.value(for: CodingKeys.outTangent) - let spatialInTangent: LottieVector3D? = try? dictionary.value(for: CodingKeys.spatialInTangent) - let spatialOutTangent: LottieVector3D? = try? dictionary.value(for: CodingKeys.spatialOutTangent) - - self.init( - startValue: startValue, - endValue: endValue, - time: time, - hold: hold, - inTangent: inTangent, - outTangent: outTangent, - spatialInTangent: spatialInTangent, - spatialOutTangent: spatialOutTangent) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Keyframes/KeyframeGroup.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Keyframes/KeyframeGroup.swift deleted file mode 100644 index 6f02a88853e17e0926f9e8c8e5238ac77a707ace..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Keyframes/KeyframeGroup.swift +++ /dev/null @@ -1,253 +0,0 @@ -// -// KeyframeGroup.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/14/19. -// - -// MARK: - KeyframeGroup - -/// Used for coding/decoding a group of Keyframes by type. -/// -/// Keyframe data is wrapped in a dictionary { "k" : KeyframeData }. -/// The keyframe data can either be an array of keyframes or, if no animation is present, the raw value. -/// This helper object is needed to properly decode the json. -final class KeyframeGroup { - - // MARK: Lifecycle - - init( - keyframes: ContiguousArray>, - unsupportedAfterEffectsExpression: String? = nil) - { - self.keyframes = keyframes - self.unsupportedAfterEffectsExpression = unsupportedAfterEffectsExpression - } - - init( - _ value: T, - unsupportedAfterEffectsExpression: String? = nil) - { - keyframes = [Keyframe(value)] - self.unsupportedAfterEffectsExpression = unsupportedAfterEffectsExpression - } - - // MARK: Internal - - enum KeyframeWrapperKey: String, CodingKey { - case keyframeData = "k" - case unsupportedAfterEffectsExpression = "x" - } - - let keyframes: ContiguousArray> - - /// lottie-ios doesn't support After Effects expressions, but we parse them so we can log diagnostics. - /// More info: https://helpx.adobe.com/after-effects/using/expression-basics.html - let unsupportedAfterEffectsExpression: String? - -} - -// MARK: Decodable - -extension KeyframeGroup: Decodable where T: Decodable { - convenience init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: KeyframeWrapperKey.self) - let unsupportedAfterEffectsExpression = try? container.decode(String.self, forKey: .unsupportedAfterEffectsExpression) - - if let keyframeData: T = try? container.decode(T.self, forKey: .keyframeData) { - /// Try to decode raw value; No keyframe data. - self.init( - keyframes: [Keyframe(keyframeData)], - unsupportedAfterEffectsExpression: unsupportedAfterEffectsExpression) - } else { - // Decode and array of keyframes. - // - // Body Movin and Lottie deal with keyframes in different ways. - // - // A keyframe object in Body movin defines a span of time with a START - // and an END, from the current keyframe time to the next keyframe time. - // - // A keyframe object in Lottie defines a singular point in time/space. - // This point has an in-tangent and an out-tangent. - // - // To properly decode this we must iterate through keyframes while holding - // reference to the previous keyframe. - - var keyframesContainer = try container.nestedUnkeyedContainer(forKey: .keyframeData) - var keyframes = ContiguousArray>() - var previousKeyframeData: KeyframeData? - while !keyframesContainer.isAtEnd { - // Ensure that Time and Value are present. - - let keyframeData = try keyframesContainer.decode(KeyframeData.self) - - guard - let value: T = keyframeData.startValue ?? previousKeyframeData?.endValue, - let time = keyframeData.time - else { - /// Missing keyframe data. JSON must be corrupt. - throw DecodingError.dataCorruptedError( - forKey: KeyframeWrapperKey.keyframeData, - in: container, - debugDescription: "Missing keyframe data.") - } - - keyframes.append(Keyframe( - value: value, - time: AnimationFrameTime(time), - isHold: keyframeData.isHold, - inTangent: previousKeyframeData?.inTangent, - outTangent: keyframeData.outTangent, - spatialInTangent: previousKeyframeData?.spatialInTangent, - spatialOutTangent: keyframeData.spatialOutTangent)) - previousKeyframeData = keyframeData - } - self.init( - keyframes: keyframes, - unsupportedAfterEffectsExpression: unsupportedAfterEffectsExpression) - } - } -} - -// MARK: Encodable - -extension KeyframeGroup: Encodable where T: Encodable { - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: KeyframeWrapperKey.self) - - if keyframes.count == 1 { - let keyframe = keyframes[0] - try container.encode(keyframe.value, forKey: .keyframeData) - } else { - var keyframeContainer = container.nestedUnkeyedContainer(forKey: .keyframeData) - - for i in 1..( - startValue: keyframe.value, - endValue: nextKeyframe.value, - time: keyframe.time, - hold: keyframe.isHold ? 1 : nil, - inTangent: nextKeyframe.inTangent, - outTangent: keyframe.outTangent, - spatialInTangent: nil, - spatialOutTangent: nil) - try keyframeContainer.encode(keyframeData) - } - } - } -} - -// MARK: DictionaryInitializable - -extension KeyframeGroup: DictionaryInitializable where T: AnyInitializable { - convenience init(dictionary: [String: Any]) throws { - var keyframes = ContiguousArray>() - let unsupportedAfterEffectsExpression = dictionary[KeyframeWrapperKey.unsupportedAfterEffectsExpression.rawValue] as? String - if - let rawValue = dictionary[KeyframeWrapperKey.keyframeData.rawValue], - let value = try? T(value: rawValue) - { - keyframes = [Keyframe(value)] - } else { - var frameDictionaries: [[String: Any]] - if let singleFrameDictionary = dictionary[KeyframeWrapperKey.keyframeData.rawValue] as? [String: Any] { - frameDictionaries = [singleFrameDictionary] - } else { - frameDictionaries = try dictionary.value(for: KeyframeWrapperKey.keyframeData) - } - var previousKeyframeData: KeyframeData? - for frameDictionary in frameDictionaries { - let data = try KeyframeData(dictionary: frameDictionary) - guard - let value: T = data.startValue ?? previousKeyframeData?.endValue, - let time = data.time - else { - throw InitializableError.invalidInput() - } - keyframes.append(Keyframe( - value: value, - time: time, - isHold: data.isHold, - inTangent: previousKeyframeData?.inTangent, - outTangent: data.outTangent, - spatialInTangent: previousKeyframeData?.spatialInTangent, - spatialOutTangent: data.spatialOutTangent)) - previousKeyframeData = data - } - } - - self.init( - keyframes: keyframes, - unsupportedAfterEffectsExpression: unsupportedAfterEffectsExpression) - } -} - -// MARK: Equatable - -extension KeyframeGroup: Equatable where T: Equatable { - static func == (_ lhs: KeyframeGroup, _ rhs: KeyframeGroup) -> Bool { - lhs.keyframes == rhs.keyframes - } -} - -// MARK: Hashable - -extension KeyframeGroup: Hashable where T: Hashable { - func hash(into hasher: inout Hasher) { - hasher.combine(keyframes) - } -} - -// MARK: Sendable - -extension KeyframeGroup: Sendable where T: Sendable { } - -extension Keyframe { - /// Creates a copy of this `Keyframe` with the same timing data, but a different value - func withValue(_ newValue: Value) -> Keyframe { - Keyframe( - value: newValue, - time: time, - isHold: isHold, - inTangent: inTangent, - outTangent: outTangent, - spatialInTangent: spatialInTangent, - spatialOutTangent: spatialOutTangent) - } -} - -extension KeyframeGroup { - /// Maps the values of each individual keyframe in this group - func map(_ transformation: (T) throws -> NewValue) rethrows -> KeyframeGroup { - KeyframeGroup( - keyframes: ContiguousArray(try keyframes.map { keyframe in - keyframe.withValue(try transformation(keyframe.value)) - }), - unsupportedAfterEffectsExpression: unsupportedAfterEffectsExpression) - } -} - -// MARK: - AnyKeyframeGroup - -/// A type-erased wrapper for `KeyframeGroup`s -protocol AnyKeyframeGroup { - /// An untyped copy of these keyframes - var untyped: KeyframeGroup { get } - - /// An untyped `KeyframeInterpolator` for these keyframes - var interpolator: AnyValueProvider { get } -} - -// MARK: - KeyframeGroup + AnyKeyframeGroup - -extension KeyframeGroup: AnyKeyframeGroup where T: AnyInterpolatable { - var untyped: KeyframeGroup { - map { $0 as Any } - } - - var interpolator: AnyValueProvider { - KeyframeInterpolator(keyframes: keyframes) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/DropShadowEffect.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/DropShadowEffect.swift deleted file mode 100644 index 655c7f1d492eff747e203d22d34b45a3e58b9af3..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/DropShadowEffect.swift +++ /dev/null @@ -1,43 +0,0 @@ -// Created by Cal Stephens on 8/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -final class DropShadowEffect: LayerEffect { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The color of the drop shadow - var color: ColorEffectValue? { - value(named: "Shadow Color") - } - - /// Opacity between 0 and 255 - var opacity: Vector1DEffectValue? { - value(named: "Opacity") - } - - /// The direction / angle of the drop shadow, in degrees - var direction: Vector1DEffectValue? { - value(named: "Direction") - } - - /// The distance of the drop shadow - var distance: Vector1DEffectValue? { - value(named: "Distance") - } - - /// The softness of the drop shadow - var softness: Vector1DEffectValue? { - value(named: "Softness") - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/EffectValues/ColorEffectValue.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/EffectValues/ColorEffectValue.swift deleted file mode 100644 index 125c65d2c7ea3c1729e05a181f8e9c5fdce96121..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/EffectValues/ColorEffectValue.swift +++ /dev/null @@ -1,36 +0,0 @@ -// Created by Cal Stephens on 8/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -final class ColorEffectValue: EffectValue { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - value = try? container.decode(KeyframeGroup.self, forKey: .value) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let valueDictionary: [String: Any] = try dictionary.value(for: CodingKeys.value) - value = try KeyframeGroup(dictionary: valueDictionary) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The value of the color - let value: KeyframeGroup? - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(value, forKey: .value) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case value = "v" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/EffectValues/EffectValue.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/EffectValues/EffectValue.swift deleted file mode 100644 index 8cae5e599e975558a4d25b724200f793bf370885..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/EffectValues/EffectValue.swift +++ /dev/null @@ -1,97 +0,0 @@ -// Created by Cal Stephens on 8/15/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -// MARK: - EffectValueType - -/// https://lottiefiles.github.io/lottie-docs/schema/#/$defs/effect-values -enum EffectValueType: Int, Codable, Sendable { - case slider = 0 - case angle = 1 - case color = 2 - case unknown = 9999 - - init(from decoder: Decoder) throws { - self = try EffectValueType(rawValue: decoder.singleValueContainer().decode(RawValue.self)) ?? .unknown - } -} - -// MARK: ClassFamily - -extension EffectValueType: ClassFamily { - static var discriminator: Discriminator = .type - - func getType() -> AnyObject.Type { - switch self { - case .slider: - return Vector1DEffectValue.self - case .angle: - return Vector1DEffectValue.self - case .color: - return ColorEffectValue.self - case .unknown: - // Unsupported - return LayerEffect.self - } - } -} - -// MARK: - EffectValue - -class EffectValue: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: EffectValue.CodingKeys.self) - type = try container.decode(EffectValueType.self, forKey: .type) - name = try container.decode(String.self, forKey: .name) - } - - required init(dictionary: [String: Any]) throws { - type = (try? dictionary.value(for: CodingKeys.type)).flatMap(EffectValueType.init(rawValue:)) ?? .unknown - name = (try? dictionary.value(for: CodingKeys.name)) ?? "Effect" - } - - // MARK: Internal - - /// The type of effect value - let type: EffectValueType - - /// The name of the effect value - let name: String - - // MARK: Fileprivate - - fileprivate enum CodingKeys: String, CodingKey { - case type = "ty" - case name = "nm" - } -} - -extension [EffectValue] { - static func fromDictionaries(_ dictionaries: [[String: Any]]) throws -> [EffectValue] { - try dictionaries.compactMap { dictionary in - let shapeType = dictionary[EffectValue.CodingKeys.type.rawValue] as? Int - switch EffectValueType(rawValue: shapeType ?? EffectValueType.unknown.rawValue) { - case .slider: - return try Vector1DEffectValue(dictionary: dictionary) - case .angle: - return try Vector1DEffectValue(dictionary: dictionary) - case .color: - return try ColorEffectValue(dictionary: dictionary) - case .unknown: - // Unsupported - return try EffectValue(dictionary: dictionary) - case nil: - return nil - } - } - } -} - -// MARK: - EffectValue + Sendable - -/// Since `EffectValue` isn't `final`, we have to use `@unchecked Sendable` instead of `Sendable.` -/// All `EffectValue` subclasses are immutable `Sendable` values. -// swiftlint:disable:next no_unchecked_sendable -extension EffectValue: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/EffectValues/Vector1DEffectValue.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/EffectValues/Vector1DEffectValue.swift deleted file mode 100644 index 59555a495ed1fe028d1b423992a734bffb620777..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/EffectValues/Vector1DEffectValue.swift +++ /dev/null @@ -1,36 +0,0 @@ -// Created by Cal Stephens on 8/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -final class Vector1DEffectValue: EffectValue { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - value = try? container.decode(KeyframeGroup.self, forKey: .value) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let valueDictionary: [String: Any] = try dictionary.value(for: CodingKeys.value) - value = try KeyframeGroup(dictionary: valueDictionary) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The value of the slider - let value: KeyframeGroup? - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(value, forKey: .value) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case value = "v" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/LayerEffect.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/LayerEffect.swift deleted file mode 100644 index 9bb8c27c05e8cb0047fc7cac15eb79ad98999865..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerEffects/LayerEffect.swift +++ /dev/null @@ -1,102 +0,0 @@ -// Created by Cal Stephens on 8/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -// MARK: - LayerEffectType - -/// https://lottiefiles.github.io/lottie-docs/schema/#/$defs/effects -enum LayerEffectType: Int, Codable, Sendable { - case dropShadow = 25 - case unknown = 9999 - - init(from decoder: Decoder) throws { - self = try LayerEffectType(rawValue: decoder.singleValueContainer().decode(RawValue.self)) ?? .unknown - } -} - -// MARK: ClassFamily - -extension LayerEffectType: ClassFamily { - static var discriminator: Discriminator = .type - - func getType() -> AnyObject.Type { - switch self { - case .dropShadow: - return DropShadowEffect.self - case .unknown: - // Unsupported - return LayerEffect.self - } - } -} - -// MARK: - LayerEffect - -class LayerEffect: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: LayerEffect.CodingKeys.self) - name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Effect" - type = try container.decode(LayerEffectType.self, forKey: .type) - effects = try container.decodeIfPresent([EffectValue].self, ofFamily: EffectValueType.self, forKey: .effects) ?? [] - } - - required init(dictionary: [String: Any]) throws { - name = (try? dictionary.value(for: CodingKeys.name)) ?? "Layer" - type = LayerEffectType(rawValue: try dictionary.value(for: CodingKeys.type)) ?? .unknown - if let valueDictionaries = dictionary[CodingKeys.effects.rawValue] as? [[String: Any]] { - effects = try [EffectValue].fromDictionaries(valueDictionaries) - } else { - effects = [] - } - } - - // MARK: Internal - - /// The name of the effect - let name: String - - /// The type of effect - let type: LayerEffectType - - /// Values that configure the behavior of the effect - let effects: [EffectValue] - - /// Retrieves the `EffectValue` for the given name - func value(named name: String) -> ValueType? { - effects.first(where: { - $0.name == name && $0 is ValueType - }) as? ValueType - } - - // MARK: Fileprivate - - fileprivate enum CodingKeys: String, CodingKey { - case name = "nm" - case type = "ty" - case effects = "ef" - } -} - -extension [LayerEffect] { - static func fromDictionaries(_ dictionaries: [[String: Any]]) throws -> [LayerEffect] { - try dictionaries.compactMap { dictionary in - let shapeType = dictionary[LayerEffect.CodingKeys.type.rawValue] as? Int - switch LayerEffectType(rawValue: shapeType ?? LayerEffectType.unknown.rawValue) { - case .dropShadow: - return try DropShadowEffect(dictionary: dictionary) - case .unknown, nil: - // Unsupported - return try LayerEffect(dictionary: dictionary) - } - } - } -} - -// MARK: - LayerEffect + Sendable - -/// Since `LayerEffect` isn't `final`, we have to use `@unchecked Sendable` instead of `Sendable.` -/// All `LayerEffect` subclasses are immutable `Sendable` values. -// swiftlint:disable:next no_unchecked_sendable -extension LayerEffect: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerStyles/DropShadowStyle.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerStyles/DropShadowStyle.swift deleted file mode 100644 index 1f2d14a904cb904f2175a4e97e3002907ef24af5..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerStyles/DropShadowStyle.swift +++ /dev/null @@ -1,70 +0,0 @@ -// Created by Cal Stephens on 8/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -final class DropShadowStyle: LayerStyle { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: DropShadowStyle.CodingKeys.self) - opacity = try container.decode(KeyframeGroup.self, forKey: .opacity) - color = try container.decode(KeyframeGroup.self, forKey: .color) - angle = try container.decode(KeyframeGroup.self, forKey: .angle) - size = try container.decode(KeyframeGroup.self, forKey: .size) - distance = try container.decode(KeyframeGroup.self, forKey: .distance) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let opacityDictionary: [String: Any] = try dictionary.value(for: CodingKeys.opacity) - opacity = try KeyframeGroup(dictionary: opacityDictionary) - let colorDictionary: [String: Any] = try dictionary.value(for: CodingKeys.color) - color = try KeyframeGroup(dictionary: colorDictionary) - let angleDictionary: [String: Any] = try dictionary.value(for: CodingKeys.angle) - angle = try KeyframeGroup(dictionary: angleDictionary) - let sizeDictionary: [String: Any] = try dictionary.value(for: CodingKeys.size) - size = try KeyframeGroup(dictionary: sizeDictionary) - let distanceDictionary: [String: Any] = try dictionary.value(for: CodingKeys.distance) - distance = try KeyframeGroup(dictionary: distanceDictionary) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The opacity of the drop shadow - let opacity: KeyframeGroup - - /// The color of the drop shadow - let color: KeyframeGroup - - /// The angle of the drop shadow, in degrees, - /// with `0` representing a shadow straight-down from the layer - /// (`offsetY=distance, offsetX=0`). - let angle: KeyframeGroup - - /// The size of the drop shadow - let size: KeyframeGroup - - /// The distance of the drop shadow - let distance: KeyframeGroup - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(opacity, forKey: .opacity) - try container.encode(color, forKey: .color) - try container.encode(angle, forKey: .angle) - try container.encode(size, forKey: .size) - try container.encode(distance, forKey: .distance) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case color = "c" - case opacity = "o" - case angle = "a" - case size = "s" - case distance = "d" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerStyles/LayerStyle.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerStyles/LayerStyle.swift deleted file mode 100644 index b6ef1c32d4fee28979fdf73fdb14b1ff7e248c8d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/LayerStyles/LayerStyle.swift +++ /dev/null @@ -1,84 +0,0 @@ -// Created by Cal Stephens on 8/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -// MARK: - LayerStyleType - -enum LayerStyleType: Int, Codable, Sendable { - case dropShadow = 1 - case unknown = 9999 - - init(from decoder: Decoder) throws { - self = try LayerStyleType(rawValue: decoder.singleValueContainer().decode(RawValue.self)) ?? .unknown - } -} - -// MARK: ClassFamily - -extension LayerStyleType: ClassFamily { - static var discriminator: Discriminator = .type - - func getType() -> AnyObject.Type { - switch self { - case .dropShadow: - return DropShadowStyle.self - case .unknown: - // Unsupported - return LayerStyle.self - } - } -} - -// MARK: - LayerStyle - -class LayerStyle: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: LayerStyle.CodingKeys.self) - name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Style" - type = try container.decode(LayerStyleType.self, forKey: .type) - } - - required init(dictionary: [String: Any]) throws { - name = (try? dictionary.value(for: CodingKeys.name)) ?? "Layer" - type = LayerStyleType(rawValue: try dictionary.value(for: CodingKeys.type)) ?? .unknown - } - - // MARK: Internal - - /// The name of the style - let name: String - - /// The type of style - let type: LayerStyleType - - // MARK: Fileprivate - - fileprivate enum CodingKeys: String, CodingKey { - case name = "nm" - case type = "ty" - } -} - -extension [LayerStyle] { - static func fromDictionaries(_ dictionaries: [[String: Any]]) throws -> [LayerStyle] { - try dictionaries.compactMap { dictionary in - let shapeType = dictionary[LayerStyle.CodingKeys.type.rawValue] as? Int - switch LayerStyleType(rawValue: shapeType ?? LayerStyleType.unknown.rawValue) { - case .dropShadow: - return try DropShadowStyle(dictionary: dictionary) - case .unknown, nil: - // Unsupported - return try LayerStyle(dictionary: dictionary) - } - } - } -} - -// MARK: - LayerStyle + Sendable - -/// Since `LayerStyle` isn't `final`, we have to use `@unchecked Sendable` instead of `Sendable.` -/// All `LayerStyle` subclasses are immutable `Sendable` values. -// swiftlint:disable:next no_unchecked_sendable -extension LayerStyle: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/ImageLayerModel.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/ImageLayerModel.swift deleted file mode 100644 index 781e5c1f0111ba6400d524a69186885a87c7d10f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/ImageLayerModel.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// ImageLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -/// A layer that holds an image. -final class ImageLayerModel: LayerModel { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: ImageLayerModel.CodingKeys.self) - referenceID = try container.decode(String.self, forKey: .referenceID) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - referenceID = try dictionary.value(for: CodingKeys.referenceID) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The reference ID of the image. - let referenceID: String - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(referenceID, forKey: .referenceID) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case referenceID = "refId" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/LayerModel.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/LayerModel.swift deleted file mode 100644 index 836c09a1978947a6255f0c6a82bde2670c1c075b..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/LayerModel.swift +++ /dev/null @@ -1,266 +0,0 @@ -// -// Layer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/7/19. -// - -// MARK: - LayerType + ClassFamily - -/// Used for mapping a heterogeneous list to classes for parsing. -extension LayerType: ClassFamily { - static var discriminator: Discriminator = .type - - func getType() -> AnyObject.Type { - switch self { - case .precomp: - return PreCompLayerModel.self - case .solid: - return SolidLayerModel.self - case .image: - return ImageLayerModel.self - case .null: - return LayerModel.self - case .shape: - return ShapeLayerModel.self - case .text: - return TextLayerModel.self - case .unknown: - return LayerModel.self - } - } -} - -// MARK: - LayerType - -public enum LayerType: Int, Codable { - case precomp - case solid - case image - case null - case shape - case text - case unknown - - public init(from decoder: Decoder) throws { - self = try LayerType(rawValue: decoder.singleValueContainer().decode(RawValue.self)) ?? .null - } -} - -// MARK: - MatteType - -public enum MatteType: Int, Codable { - case none - case add - case invert - case unknown -} - -// MARK: - BlendMode - -public enum BlendMode: Int, Codable { - case normal - case multiply - case screen - case overlay - case darken - case lighten - case colorDodge - case colorBurn - case hardLight - case softLight - case difference - case exclusion - case hue - case saturation - case color - case luminosity -} - -// MARK: - LayerModel - -/// A base top container for shapes, images, and other view objects. -class LayerModel: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: LayerModel.CodingKeys.self) - name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Layer" - index = try container.decodeIfPresent(Int.self, forKey: .index) ?? .random(in: Int.min...Int.max) - type = try container.decode(LayerType.self, forKey: .type) - coordinateSpace = try container.decodeIfPresent(CoordinateSpace.self, forKey: .coordinateSpace) ?? .type2d - inFrame = try container.decode(Double.self, forKey: .inFrame) - outFrame = try container.decode(Double.self, forKey: .outFrame) - startTime = try container.decode(Double.self, forKey: .startTime) - transform = try container.decodeIfPresent(Transform.self, forKey: .transform) ?? .default - parent = try container.decodeIfPresent(Int.self, forKey: .parent) - blendMode = try container.decodeIfPresent(BlendMode.self, forKey: .blendMode) ?? .normal - masks = try container.decodeIfPresent([Mask].self, forKey: .masks) - timeStretch = try container.decodeIfPresent(Double.self, forKey: .timeStretch) ?? 1 - matte = try container.decodeIfPresent(MatteType.self, forKey: .matte) - hidden = try container.decodeIfPresent(Bool.self, forKey: .hidden) ?? false - styles = try container.decodeIfPresent([LayerStyle].self, ofFamily: LayerStyleType.self, forKey: .styles) ?? [] - effects = try container.decodeIfPresent([LayerEffect].self, ofFamily: LayerEffectType.self, forKey: .effects) ?? [] - } - - required init(dictionary: [String: Any]) throws { - name = (try? dictionary.value(for: CodingKeys.name)) ?? "Layer" - index = try dictionary.value(for: CodingKeys.index) ?? .random(in: Int.min...Int.max) - type = LayerType(rawValue: try dictionary.value(for: CodingKeys.type)) ?? .null - if - let coordinateSpaceRawValue = dictionary[CodingKeys.coordinateSpace.rawValue] as? Int, - let coordinateSpace = CoordinateSpace(rawValue: coordinateSpaceRawValue) - { - self.coordinateSpace = coordinateSpace - } else { - coordinateSpace = .type2d - } - inFrame = try dictionary.value(for: CodingKeys.inFrame) - outFrame = try dictionary.value(for: CodingKeys.outFrame) - startTime = try dictionary.value(for: CodingKeys.startTime) - parent = try? dictionary.value(for: CodingKeys.parent) - if - let transformDictionary: [String: Any] = try dictionary.value(for: CodingKeys.transform), - let transform = try? Transform(dictionary: transformDictionary) - { - self.transform = transform - } else { - transform = .default - } - if - let blendModeRawValue = dictionary[CodingKeys.blendMode.rawValue] as? Int, - let blendMode = BlendMode(rawValue: blendModeRawValue) - { - self.blendMode = blendMode - } else { - blendMode = .normal - } - if let maskDictionaries = dictionary[CodingKeys.masks.rawValue] as? [[String: Any]] { - masks = try maskDictionaries.map { try Mask(dictionary: $0) } - } else { - masks = nil - } - timeStretch = (try? dictionary.value(for: CodingKeys.timeStretch)) ?? 1 - if let matteRawValue = dictionary[CodingKeys.matte.rawValue] as? Int { - matte = MatteType(rawValue: matteRawValue) - } else { - matte = nil - } - hidden = (try? dictionary.value(for: CodingKeys.hidden)) ?? false - if let styleDictionaries = dictionary[CodingKeys.styles.rawValue] as? [[String: Any]] { - styles = try [LayerStyle].fromDictionaries(styleDictionaries) - } else { - styles = [] - } - if let effectDictionaries = dictionary[CodingKeys.effects.rawValue] as? [[String: Any]] { - effects = try [LayerEffect].fromDictionaries(effectDictionaries) - } else { - effects = [] - } - } - - // MARK: Internal - - /// The readable name of the layer - let name: String - - /// The index of the layer - let index: Int - - /// The type of the layer. - let type: LayerType - - /// The coordinate space - let coordinateSpace: CoordinateSpace - - /// The in time of the layer in frames. - let inFrame: Double - /// The out time of the layer in frames. - let outFrame: Double - - /// The start time of the layer in frames. - let startTime: Double - - /// The transform of the layer - let transform: Transform - - /// The index of the parent layer, if applicable. - let parent: Int? - - /// The blending mode for the layer - let blendMode: BlendMode - - /// An array of masks for the layer. - let masks: [Mask]? - - /// A number that stretches time by a multiplier - let timeStretch: Double - - /// The type of matte if any. - let matte: MatteType? - - /// Whether or not this layer is hidden, in which case it will not be rendered. - let hidden: Bool - - /// A list of styles to apply to this layer - let styles: [LayerStyle] - - /// A list of effects to apply to this layer - let effects: [LayerEffect] - - // MARK: Fileprivate - - fileprivate enum CodingKeys: String, CodingKey { - case name = "nm" - case index = "ind" - case type = "ty" - case coordinateSpace = "ddd" - case inFrame = "ip" - case outFrame = "op" - case startTime = "st" - case transform = "ks" - case parent - case blendMode = "bm" - case masks = "masksProperties" - case timeStretch = "sr" - case matte = "tt" - case hidden = "hd" - case styles = "sy" - case effects = "ef" - } -} - -extension [LayerModel] { - - static func fromDictionaries(_ dictionaries: [[String: Any]]) throws -> [LayerModel] { - try dictionaries.compactMap { dictionary in - let layerType = dictionary[LayerModel.CodingKeys.type.rawValue] as? Int - switch LayerType(rawValue: layerType ?? LayerType.null.rawValue) { - case .precomp: - return try PreCompLayerModel(dictionary: dictionary) - case .solid: - return try SolidLayerModel(dictionary: dictionary) - case .image: - return try ImageLayerModel(dictionary: dictionary) - case .null: - return try LayerModel(dictionary: dictionary) - case .shape: - return try ShapeLayerModel(dictionary: dictionary) - case .text: - return try TextLayerModel(dictionary: dictionary) - case .unknown: - return try LayerModel(dictionary: dictionary) - case .none: - return nil - } - } - } -} - -// MARK: - LayerModel + Sendable - -/// Since `LayerModel` isn't `final`, we have to use `@unchecked Sendable` instead of `Sendable.` -/// All `LayerModel` subclasses are immutable `Sendable` values. -// swiftlint:disable:next no_unchecked_sendable -extension LayerModel: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/PreCompLayerModel.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/PreCompLayerModel.swift deleted file mode 100644 index a83214d75d22697f2b5679682218f34846f13194..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/PreCompLayerModel.swift +++ /dev/null @@ -1,65 +0,0 @@ -// -// PreCompLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -/// A layer that holds another animation composition. -final class PreCompLayerModel: LayerModel { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: PreCompLayerModel.CodingKeys.self) - referenceID = try container.decode(String.self, forKey: .referenceID) - timeRemapping = try container.decodeIfPresent(KeyframeGroup.self, forKey: .timeRemapping) - width = try container.decode(Double.self, forKey: .width) - height = try container.decode(Double.self, forKey: .height) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - referenceID = try dictionary.value(for: CodingKeys.referenceID) - if let timeRemappingDictionary = dictionary[CodingKeys.timeRemapping.rawValue] as? [String: Any] { - timeRemapping = try KeyframeGroup(dictionary: timeRemappingDictionary) - } else { - timeRemapping = nil - } - width = try dictionary.value(for: CodingKeys.width) - height = try dictionary.value(for: CodingKeys.height) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The reference ID of the precomp. - let referenceID: String - - /// A value that remaps time over time. - let timeRemapping: KeyframeGroup? - - /// Precomp Width - let width: Double - - /// Precomp Height - let height: Double - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(referenceID, forKey: .referenceID) - try container.encode(timeRemapping, forKey: .timeRemapping) - try container.encode(width, forKey: .width) - try container.encode(height, forKey: .height) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case referenceID = "refId" - case timeRemapping = "tm" - case width = "w" - case height = "h" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/ShapeLayerModel.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/ShapeLayerModel.swift deleted file mode 100644 index 805da83a9547a906b8c4d9238dc21b6564335388..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/ShapeLayerModel.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// ShapeLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -/// A layer that holds vector shape objects. -final class ShapeLayerModel: LayerModel { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: ShapeLayerModel.CodingKeys.self) - items = try container.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .items) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let itemDictionaries: [[String: Any]] = try dictionary.value(for: CodingKeys.items) - items = try [ShapeItem].fromDictionaries(itemDictionaries) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// A list of shape items. - let items: [ShapeItem] - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(items, forKey: .items) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case items = "shapes" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/SolidLayerModel.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/SolidLayerModel.swift deleted file mode 100644 index 17312c90e1a3b99814d5b3045937a1f187687fdd..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/SolidLayerModel.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// SolidLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -/// A layer that holds a solid color. -final class SolidLayerModel: LayerModel { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: SolidLayerModel.CodingKeys.self) - colorHex = try container.decode(String.self, forKey: .colorHex) - width = try container.decode(Double.self, forKey: .width) - height = try container.decode(Double.self, forKey: .height) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - colorHex = try dictionary.value(for: CodingKeys.colorHex) - width = try dictionary.value(for: CodingKeys.width) - height = try dictionary.value(for: CodingKeys.height) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The color of the solid in Hex // Change to value provider. - let colorHex: String - - /// The Width of the color layer - let width: Double - - /// The height of the color layer - let height: Double - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(colorHex, forKey: .colorHex) - try container.encode(width, forKey: .width) - try container.encode(height, forKey: .height) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case colorHex = "sc" - case width = "sw" - case height = "sh" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/TextLayerModel.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/TextLayerModel.swift deleted file mode 100644 index 604a331f513686d45cd1bcc31097be4c89224a55..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Layers/TextLayerModel.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// TextLayer.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -/// A layer that holds text. -final class TextLayerModel: LayerModel { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: TextLayerModel.CodingKeys.self) - let textContainer = try container.nestedContainer(keyedBy: TextCodingKeys.self, forKey: .textGroup) - text = try textContainer.decode(KeyframeGroup.self, forKey: .text) - animators = try textContainer.decode([TextAnimator].self, forKey: .animators) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let containerDictionary: [String: Any] = try dictionary.value(for: CodingKeys.textGroup) - let textDictionary: [String: Any] = try containerDictionary.value(for: TextCodingKeys.text) - text = try KeyframeGroup(dictionary: textDictionary) - let animatorDictionaries: [[String: Any]] = try containerDictionary.value(for: TextCodingKeys.animators) - animators = try animatorDictionaries.map { try TextAnimator(dictionary: $0) } - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The text for the layer - let text: KeyframeGroup - - /// Text animators - let animators: [TextAnimator] - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - var textContainer = container.nestedContainer(keyedBy: TextCodingKeys.self, forKey: .textGroup) - try textContainer.encode(text, forKey: .text) - try textContainer.encode(animators, forKey: .animators) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case textGroup = "t" - } - - private enum TextCodingKeys: String, CodingKey { - case text = "d" - case animators = "a" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/DashPattern.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/DashPattern.swift deleted file mode 100644 index 0c2da6858ca410310d7628d5dd764dd745b7036a..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/DashPattern.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// DashPattern.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/22/19. -// - -// MARK: - DashElementType - -enum DashElementType: String, Codable { - case offset = "o" - case dash = "d" - case gap = "g" -} - -// MARK: - DashElement - -final class DashElement: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - init(dictionary: [String: Any]) throws { - let typeRawValue: String = try dictionary.value(for: CodingKeys.type) - guard let type = DashElementType(rawValue: typeRawValue) else { - throw InitializableError.invalidInput() - } - self.type = type - let valueDictionary: [String: Any] = try dictionary.value(for: CodingKeys.value) - value = try KeyframeGroup(dictionary: valueDictionary) - } - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case type = "n" - case value = "v" - } - - let type: DashElementType - let value: KeyframeGroup - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/Marker.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/Marker.swift deleted file mode 100644 index a724452695d98a494076e3ac609ba7581efe71b8..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/Marker.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// Marker.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/9/19. -// - -/// A time marker -final class Marker: Codable, Sendable, DictionaryInitializable { - - // MARK: Lifecycle - - init(dictionary: [String: Any]) throws { - name = try dictionary.value(for: CodingKeys.name) - frameTime = try dictionary.value(for: CodingKeys.frameTime) - durationFrameTime = try dictionary.value(for: CodingKeys.durationFrameTime) - } - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case name = "cm" - case frameTime = "tm" - case durationFrameTime = "dr" - } - - /// The Marker Name - let name: String - - /// The Frame time of the marker - let frameTime: AnimationFrameTime - - /// The duration of the marker, in frames. - let durationFrameTime: AnimationFrameTime -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/Mask.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/Mask.swift deleted file mode 100644 index a3fa34b990dd11c80c1ef58b2d527852abe1c25d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/Mask.swift +++ /dev/null @@ -1,80 +0,0 @@ -// -// Mask.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -// MARK: - MaskMode - -enum MaskMode: String, Codable { - case add = "a" - case subtract = "s" - case intersect = "i" - case lighten = "l" - case darken = "d" - case difference = "f" - case none = "n" -} - -// MARK: - Mask - -final class Mask: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Mask.CodingKeys.self) - mode = try container.decodeIfPresent(MaskMode.self, forKey: .mode) ?? .add - opacity = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .opacity) ?? KeyframeGroup(LottieVector1D(100)) - shape = try container.decode(KeyframeGroup.self, forKey: .shape) - inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false - expansion = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .expansion) ?? KeyframeGroup(LottieVector1D(0)) - } - - init(dictionary: [String: Any]) throws { - if - let modeRawType = dictionary[CodingKeys.mode.rawValue] as? String, - let mode = MaskMode(rawValue: modeRawType) - { - self.mode = mode - } else { - mode = .add - } - if let opacityDictionary = dictionary[CodingKeys.opacity.rawValue] as? [String: Any] { - opacity = try KeyframeGroup(dictionary: opacityDictionary) - } else { - opacity = KeyframeGroup(LottieVector1D(100)) - } - let shapeDictionary: [String: Any] = try dictionary.value(for: CodingKeys.shape) - shape = try KeyframeGroup(dictionary: shapeDictionary) - inverted = (try? dictionary.value(for: CodingKeys.inverted)) ?? false - if let expansionDictionary = dictionary[CodingKeys.expansion.rawValue] as? [String: Any] { - expansion = try KeyframeGroup(dictionary: expansionDictionary) - } else { - expansion = KeyframeGroup(LottieVector1D(0)) - } - } - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case mode - case opacity = "o" - case inverted = "inv" - case shape = "pt" - case expansion = "x" - } - - let mode: MaskMode - - let opacity: KeyframeGroup - - let shape: KeyframeGroup - - let inverted: Bool - - let expansion: KeyframeGroup -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/Transform.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/Transform.swift deleted file mode 100644 index ced097a9e61af755b93b70a8e2b87d0a01ee2ea1..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Objects/Transform.swift +++ /dev/null @@ -1,260 +0,0 @@ -// -// Transform.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/7/19. -// - -/// The animatable transform for a layer. Controls position, rotation, scale, and opacity. -final class Transform: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - /// This manual override of decode is required because we want to throw an error - /// in the case that there is not position data. - let container = try decoder.container(keyedBy: Transform.CodingKeys.self) - - // AnchorPoint - anchorPoint = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .anchorPoint) ?? - KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - - // Position - if container.contains(.positionX), container.contains(.positionY) { - // Position dimensions are split into two keyframe groups - positionX = try container.decode(KeyframeGroup.self, forKey: .positionX) - positionY = try container.decode(KeyframeGroup.self, forKey: .positionY) - position = nil - } else if let positionKeyframes = try? container.decode(KeyframeGroup.self, forKey: .position) { - // Position dimensions are a single keyframe group. - position = positionKeyframes - positionX = nil - positionY = nil - } else if - let positionContainer = try? container.nestedContainer(keyedBy: PositionCodingKeys.self, forKey: .position), - let positionX = try? positionContainer.decode(KeyframeGroup.self, forKey: .positionX), - let positionY = try? positionContainer.decode(KeyframeGroup.self, forKey: .positionY) - { - /// Position keyframes are split and nested. - self.positionX = positionX - self.positionY = positionY - position = nil - } else { - /// Default value. - position = KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - positionX = nil - positionY = nil - } - - // Scale - scale = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .scale) ?? - KeyframeGroup(LottieVector3D(x: Double(100), y: 100, z: 100)) - - // Rotation - if let rotation = try container.decodeIfPresent(KeyframeGroup.self, forKey: .rotationX) { - rotationX = rotation - } else { - rotationX = KeyframeGroup(LottieVector1D(0)) - } - - if let rotation = try container.decodeIfPresent(KeyframeGroup.self, forKey: .rotationY) { - rotationY = rotation - } else { - rotationY = KeyframeGroup(LottieVector1D(0)) - } - - if let rotation = try container.decodeIfPresent(KeyframeGroup.self, forKey: .rotationZ) { - rotationZ = rotation - } else { - rotationZ = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .rotation) ?? KeyframeGroup(LottieVector1D(0)) - } - rotation = nil - // Opacity - opacity = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .opacity) ?? KeyframeGroup(LottieVector1D(100)) - } - - init(dictionary: [String: Any]) throws { - if - let anchorPointDictionary = dictionary[CodingKeys.anchorPoint.rawValue] as? [String: Any], - let anchorPoint = try? KeyframeGroup(dictionary: anchorPointDictionary) - { - self.anchorPoint = anchorPoint - } else { - anchorPoint = Transform.default.anchorPoint - } - - if - let xDictionary = dictionary[CodingKeys.positionX.rawValue] as? [String: Any], - let yDictionary = dictionary[CodingKeys.positionY.rawValue] as? [String: Any] - { - positionX = try KeyframeGroup(dictionary: xDictionary) - positionY = try KeyframeGroup(dictionary: yDictionary) - position = nil - } else if - let positionDictionary = dictionary[CodingKeys.position.rawValue] as? [String: Any], - positionDictionary[KeyframeGroup.KeyframeWrapperKey.keyframeData.rawValue] != nil - { - position = try KeyframeGroup(dictionary: positionDictionary) - positionX = nil - positionY = nil - } else if - let positionDictionary = dictionary[CodingKeys.position.rawValue] as? [String: Any], - let xDictionary = positionDictionary[PositionCodingKeys.positionX.rawValue] as? [String: Any], - let yDictionary = positionDictionary[PositionCodingKeys.positionY.rawValue] as? [String: Any] - { - positionX = try KeyframeGroup(dictionary: xDictionary) - positionY = try KeyframeGroup(dictionary: yDictionary) - position = nil - } else { - position = Transform.default.position - positionX = nil - positionY = nil - } - - if - let scaleDictionary = dictionary[CodingKeys.scale.rawValue] as? [String: Any], - let scale = try? KeyframeGroup(dictionary: scaleDictionary) - { - self.scale = scale - } else { - scale = Transform.default.scale - } - - if - let rotationDictionary = dictionary[CodingKeys.rotationX.rawValue] as? [String: Any], - let rotation = try? KeyframeGroup(dictionary: rotationDictionary) - { - rotationX = rotation - } else { - rotationX = Transform.default.rotationX - } - - if - let rotationDictionary = dictionary[CodingKeys.rotationY.rawValue] as? [String: Any], - let rotation = try? KeyframeGroup(dictionary: rotationDictionary) - { - rotationY = rotation - } else { - rotationY = Transform.default.rotationY - } - - if - let rotationDictionary = dictionary[CodingKeys.rotation.rawValue] as? [String: Any], - let rotation = try? KeyframeGroup(dictionary: rotationDictionary) - { - rotationZ = rotation - } else if - let rotationDictionary = dictionary[CodingKeys.rotationZ.rawValue] as? [String: Any], - let rotation = try? KeyframeGroup(dictionary: rotationDictionary) - { - rotationZ = rotation - } else { - rotationZ = Transform.default.rotationZ - } - rotation = nil - if - let opacityDictionary = dictionary[CodingKeys.opacity.rawValue] as? [String: Any], - let opacity = try? KeyframeGroup(dictionary: opacityDictionary) - { - self.opacity = opacity - } else { - opacity = Transform.default.opacity - } - } - - init( - anchorPoint: KeyframeGroup, - position: KeyframeGroup?, - positionX: KeyframeGroup?, - positionY: KeyframeGroup?, - scale: KeyframeGroup, - rotationX: KeyframeGroup, - rotationY: KeyframeGroup, - rotationZ: KeyframeGroup, - opacity: KeyframeGroup, - rotation: KeyframeGroup?) - { - self.anchorPoint = anchorPoint - self.position = position - self.positionX = positionX - self.positionY = positionY - self.scale = scale - self.rotationX = rotationX - self.rotationY = rotationY - self.rotationZ = rotationZ - self.opacity = opacity - self.rotation = rotation - } - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case anchorPoint = "a" - case position = "p" - case positionX = "px" - case positionY = "py" - case scale = "s" - case rotation = "r" - case rotationX = "rx" - case rotationY = "ry" - case rotationZ = "rz" - case opacity = "o" - } - - enum PositionCodingKeys: String, CodingKey { - case split = "s" - case positionX = "x" - case positionY = "y" - } - - /// Default transform values to use if no transform is provided - static var `default`: Transform { - Transform( - anchorPoint: KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)), - position: KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)), - positionX: nil, - positionY: nil, - scale: KeyframeGroup(LottieVector3D(x: Double(100), y: 100, z: 100)), - rotationX: KeyframeGroup(LottieVector1D(0)), - rotationY: KeyframeGroup(LottieVector1D(0)), - rotationZ: KeyframeGroup(LottieVector1D(0)), - opacity: KeyframeGroup(LottieVector1D(100)), - rotation: nil) - } - - /// The anchor point of the transform. - let anchorPoint: KeyframeGroup - - /// The position of the transform. This is nil if the position data was split. - let position: KeyframeGroup? - - /// The positionX of the transform. This is nil if the position property is set. - let positionX: KeyframeGroup? - - /// The positionY of the transform. This is nil if the position property is set. - let positionY: KeyframeGroup? - - /// The scale of the transform. - let scale: KeyframeGroup - - /// The rotation of the transform on X axis. - let rotationX: KeyframeGroup - - /// The rotation of the transform on Y axis. - let rotationY: KeyframeGroup - - /// The rotation of the transform on Z axis. - let rotationZ: KeyframeGroup - - /// The opacity of the transform. - let opacity: KeyframeGroup - - // MARK: Private - - /// Here for the CodingKeys.rotation = "r". `r` and `rz` are the same. - private let rotation: KeyframeGroup? -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Ellipse.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Ellipse.swift deleted file mode 100644 index 42f4bc10d8bc53383674438d2ea3b54586edf6ae..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Ellipse.swift +++ /dev/null @@ -1,72 +0,0 @@ -// -// EllipseItem.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -// MARK: - PathDirection - -enum PathDirection: Int, Codable { - case clockwise = 1 - case userSetClockwise = 2 - case counterClockwise = 3 -} - -// MARK: - Ellipse - -final class Ellipse: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Ellipse.CodingKeys.self) - direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise - position = try container.decode(KeyframeGroup.self, forKey: .position) - size = try container.decode(KeyframeGroup.self, forKey: .size) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - if - let directionRawType = dictionary[CodingKeys.direction.rawValue] as? Int, - let direction = PathDirection(rawValue: directionRawType) - { - self.direction = direction - } else { - direction = .clockwise - } - let positionDictionary: [String: Any] = try dictionary.value(for: CodingKeys.position) - position = try KeyframeGroup(dictionary: positionDictionary) - let sizeDictionary: [String: Any] = try dictionary.value(for: CodingKeys.size) - size = try KeyframeGroup(dictionary: sizeDictionary) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The direction of the ellipse. - let direction: PathDirection - - /// The position of the ellipse - let position: KeyframeGroup - - /// The size of the ellipse - let size: KeyframeGroup - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(direction, forKey: .direction) - try container.encode(position, forKey: .position) - try container.encode(size, forKey: .size) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case direction = "d" - case position = "p" - case size = "s" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Fill.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Fill.swift deleted file mode 100644 index f0090ae1adedaa1950d37fe11c9fcdfcc0e9877c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Fill.swift +++ /dev/null @@ -1,72 +0,0 @@ -// -// FillShape.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -// MARK: - FillRule - -enum FillRule: Int, Codable { - case none - case nonZeroWinding - case evenOdd -} - -// MARK: - Fill - -final class Fill: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Fill.CodingKeys.self) - opacity = try container.decode(KeyframeGroup.self, forKey: .opacity) - color = try container.decode(KeyframeGroup.self, forKey: .color) - fillRule = try container.decodeIfPresent(FillRule.self, forKey: .fillRule) ?? .nonZeroWinding - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let opacityDictionary: [String: Any] = try dictionary.value(for: CodingKeys.opacity) - opacity = try KeyframeGroup(dictionary: opacityDictionary) - let colorDictionary: [String: Any] = try dictionary.value(for: CodingKeys.color) - color = try KeyframeGroup(dictionary: colorDictionary) - if - let fillRuleRawValue = dictionary[CodingKeys.fillRule.rawValue] as? Int, - let fillRule = FillRule(rawValue: fillRuleRawValue) - { - self.fillRule = fillRule - } else { - fillRule = .nonZeroWinding - } - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The opacity of the fill - let opacity: KeyframeGroup - - /// The color keyframes for the fill - let color: KeyframeGroup - - /// The fill rule to use when filling a path - let fillRule: FillRule - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(opacity, forKey: .opacity) - try container.encode(color, forKey: .color) - try container.encode(fillRule, forKey: .fillRule) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case opacity = "o" - case color = "c" - case fillRule = "r" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/GradientFill.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/GradientFill.swift deleted file mode 100644 index 5e83880046a01b231d839cca390a62224f736979..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/GradientFill.swift +++ /dev/null @@ -1,135 +0,0 @@ -// -// GradientFill.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -// MARK: - GradientType - -enum GradientType: Int, Codable, Sendable { - case none - case linear - case radial -} - -// MARK: - GradientFill - -final class GradientFill: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: GradientFill.CodingKeys.self) - opacity = try container.decode(KeyframeGroup.self, forKey: .opacity) - startPoint = try container.decode(KeyframeGroup.self, forKey: .startPoint) - endPoint = try container.decode(KeyframeGroup.self, forKey: .endPoint) - gradientType = try container.decode(GradientType.self, forKey: .gradientType) - highlightLength = try container.decodeIfPresent(KeyframeGroup.self, forKey: .highlightLength) - highlightAngle = try container.decodeIfPresent(KeyframeGroup.self, forKey: .highlightAngle) - fillRule = try container.decodeIfPresent(FillRule.self, forKey: .fillRule) ?? .nonZeroWinding - let colorsContainer = try container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors) - colors = try colorsContainer.decode(KeyframeGroup<[Double]>.self, forKey: .colors) - numberOfColors = try colorsContainer.decode(Int.self, forKey: .numberOfColors) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let opacityDictionary: [String: Any] = try dictionary.value(for: CodingKeys.opacity) - opacity = try KeyframeGroup(dictionary: opacityDictionary) - let startPointDictionary: [String: Any] = try dictionary.value(for: CodingKeys.startPoint) - startPoint = try KeyframeGroup(dictionary: startPointDictionary) - let endPointDictionary: [String: Any] = try dictionary.value(for: CodingKeys.endPoint) - endPoint = try KeyframeGroup(dictionary: endPointDictionary) - let gradientRawType: Int = try dictionary.value(for: CodingKeys.gradientType) - guard let gradient = GradientType(rawValue: gradientRawType) else { - throw InitializableError.invalidInput() - } - gradientType = gradient - if let highlightLengthDictionary = dictionary[CodingKeys.highlightLength.rawValue] as? [String: Any] { - highlightLength = try? KeyframeGroup(dictionary: highlightLengthDictionary) - } else { - highlightLength = nil - } - if let highlightAngleDictionary = dictionary[CodingKeys.highlightAngle.rawValue] as? [String: Any] { - highlightAngle = try? KeyframeGroup(dictionary: highlightAngleDictionary) - } else { - highlightAngle = nil - } - let colorsDictionary: [String: Any] = try dictionary.value(for: CodingKeys.colors) - let nestedColorsDictionary: [String: Any] = try colorsDictionary.value(for: GradientDataKeys.colors) - colors = try KeyframeGroup<[Double]>(dictionary: nestedColorsDictionary) - numberOfColors = try colorsDictionary.value(for: GradientDataKeys.numberOfColors) - if - let fillRuleRawValue = dictionary[CodingKeys.fillRule.rawValue] as? Int, - let fillRule = FillRule(rawValue: fillRuleRawValue) - { - self.fillRule = fillRule - } else { - fillRule = .nonZeroWinding - } - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The opacity of the fill - let opacity: KeyframeGroup - - /// The start of the gradient - let startPoint: KeyframeGroup - - /// The end of the gradient - let endPoint: KeyframeGroup - - /// The type of gradient - let gradientType: GradientType - - /// Gradient Highlight Length. Only if type is Radial - let highlightLength: KeyframeGroup? - - /// Highlight Angle. Only if type is Radial - let highlightAngle: KeyframeGroup? - - /// The number of color points in the gradient - let numberOfColors: Int - - /// The Colors of the gradient. - let colors: KeyframeGroup<[Double]> - - /// The fill rule to use when filling a path - let fillRule: FillRule - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(opacity, forKey: .opacity) - try container.encode(startPoint, forKey: .startPoint) - try container.encode(endPoint, forKey: .endPoint) - try container.encode(gradientType, forKey: .gradientType) - try container.encodeIfPresent(highlightLength, forKey: .highlightLength) - try container.encodeIfPresent(highlightAngle, forKey: .highlightAngle) - try container.encodeIfPresent(fillRule, forKey: .fillRule) - var colorsContainer = container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors) - try colorsContainer.encode(numberOfColors, forKey: .numberOfColors) - try colorsContainer.encode(colors, forKey: .colors) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case opacity = "o" - case startPoint = "s" - case endPoint = "e" - case gradientType = "t" - case highlightLength = "h" - case highlightAngle = "a" - case colors = "g" - case fillRule = "r" - } - - private enum GradientDataKeys: String, CodingKey { - case numberOfColors = "p" - case colors = "k" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/GradientStroke.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/GradientStroke.swift deleted file mode 100644 index e2ef2bda1e08cf8ad699986635807221c9ffd626..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/GradientStroke.swift +++ /dev/null @@ -1,236 +0,0 @@ -// -// GradientStroke.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -// MARK: - LineCap - -enum LineCap: Int, Codable, Sendable { - case none - case butt - case round - case square -} - -// MARK: - LineJoin - -enum LineJoin: Int, Codable, Sendable { - case none - case miter - case round - case bevel -} - -// MARK: - GradientStroke - -final class GradientStroke: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: GradientStroke.CodingKeys.self) - opacity = try container.decode(KeyframeGroup.self, forKey: .opacity) - startPoint = try container.decode(KeyframeGroup.self, forKey: .startPoint) - endPoint = try container.decode(KeyframeGroup.self, forKey: .endPoint) - gradientType = try container.decode(GradientType.self, forKey: .gradientType) - highlightLength = try container.decodeIfPresent(KeyframeGroup.self, forKey: .highlightLength) - highlightAngle = try container.decodeIfPresent(KeyframeGroup.self, forKey: .highlightAngle) - width = try container.decode(KeyframeGroup.self, forKey: .width) - lineCap = try container.decodeIfPresent(LineCap.self, forKey: .lineCap) ?? .round - lineJoin = try container.decodeIfPresent(LineJoin.self, forKey: .lineJoin) ?? .round - miterLimit = try container.decodeIfPresent(Double.self, forKey: .miterLimit) ?? 4 - // TODO Decode Color Objects instead of array. - let colorsContainer = try container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors) - colors = try colorsContainer.decode(KeyframeGroup<[Double]>.self, forKey: .colors) - numberOfColors = try colorsContainer.decode(Int.self, forKey: .numberOfColors) - dashPattern = try container.decodeIfPresent([DashElement].self, forKey: .dashPattern) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let opacityDictionary: [String: Any] = try dictionary.value(for: CodingKeys.opacity) - opacity = try KeyframeGroup(dictionary: opacityDictionary) - let startPointDictionary: [String: Any] = try dictionary.value(for: CodingKeys.startPoint) - startPoint = try KeyframeGroup(dictionary: startPointDictionary) - let endPointDictionary: [String: Any] = try dictionary.value(for: CodingKeys.endPoint) - endPoint = try KeyframeGroup(dictionary: endPointDictionary) - let gradientRawType: Int = try dictionary.value(for: CodingKeys.gradientType) - guard let gradient = GradientType(rawValue: gradientRawType) else { - throw InitializableError.invalidInput() - } - gradientType = gradient - if let highlightLengthDictionary = dictionary[CodingKeys.highlightLength.rawValue] as? [String: Any] { - highlightLength = try? KeyframeGroup(dictionary: highlightLengthDictionary) - } else { - highlightLength = nil - } - if let highlightAngleDictionary = dictionary[CodingKeys.highlightAngle.rawValue] as? [String: Any] { - highlightAngle = try? KeyframeGroup(dictionary: highlightAngleDictionary) - } else { - highlightAngle = nil - } - let widthDictionary: [String: Any] = try dictionary.value(for: CodingKeys.width) - width = try KeyframeGroup(dictionary: widthDictionary) - if - let lineCapRawValue = dictionary[CodingKeys.lineCap.rawValue] as? Int, - let lineCap = LineCap(rawValue: lineCapRawValue) - { - self.lineCap = lineCap - } else { - lineCap = .round - } - if - let lineJoinRawValue = dictionary[CodingKeys.lineJoin.rawValue] as? Int, - let lineJoin = LineJoin(rawValue: lineJoinRawValue) - { - self.lineJoin = lineJoin - } else { - lineJoin = .round - } - miterLimit = (try? dictionary.value(for: CodingKeys.miterLimit)) ?? 4 - let colorsDictionary: [String: Any] = try dictionary.value(for: CodingKeys.colors) - let nestedColorsDictionary: [String: Any] = try colorsDictionary.value(for: GradientDataKeys.colors) - colors = try KeyframeGroup<[Double]>(dictionary: nestedColorsDictionary) - numberOfColors = try colorsDictionary.value(for: GradientDataKeys.numberOfColors) - let dashPatternDictionaries = dictionary[CodingKeys.dashPattern.rawValue] as? [[String: Any]] - dashPattern = try? dashPatternDictionaries?.map { try DashElement(dictionary: $0) } - try super.init(dictionary: dictionary) - } - - init( - name: String, - hidden: Bool, - opacity: KeyframeGroup, - startPoint: KeyframeGroup, - endPoint: KeyframeGroup, - gradientType: GradientType, - highlightLength: KeyframeGroup?, - highlightAngle: KeyframeGroup?, - numberOfColors: Int, - colors: KeyframeGroup<[Double]>, - width: KeyframeGroup, - lineCap: LineCap, - lineJoin: LineJoin, - miterLimit: Double, - dashPattern: [DashElement]?) - { - self.opacity = opacity - self.startPoint = startPoint - self.endPoint = endPoint - self.gradientType = gradientType - self.highlightLength = highlightLength - self.highlightAngle = highlightAngle - self.numberOfColors = numberOfColors - self.colors = colors - self.width = width - self.lineCap = lineCap - self.lineJoin = lineJoin - self.miterLimit = miterLimit - self.dashPattern = dashPattern - super.init(name: name, type: .gradientStroke, hidden: hidden) - } - - // MARK: Internal - - /// The opacity of the fill - let opacity: KeyframeGroup - - /// The start of the gradient - let startPoint: KeyframeGroup - - /// The end of the gradient - let endPoint: KeyframeGroup - - /// The type of gradient - let gradientType: GradientType - - /// Gradient Highlight Length. Only if type is Radial - let highlightLength: KeyframeGroup? - - /// Highlight Angle. Only if type is Radial - let highlightAngle: KeyframeGroup? - - /// The number of color points in the gradient - let numberOfColors: Int - - /// The Colors of the gradient. - let colors: KeyframeGroup<[Double]> - - /// The width of the stroke - let width: KeyframeGroup - - /// Line Cap - let lineCap: LineCap - - /// Line Join - let lineJoin: LineJoin - - /// Miter Limit - let miterLimit: Double - - /// The dash pattern of the stroke - let dashPattern: [DashElement]? - - /// Creates a copy of this GradientStroke with the given updated width keyframes - func copy(width newWidth: KeyframeGroup) -> GradientStroke { - GradientStroke( - name: name, - hidden: hidden, - opacity: opacity, - startPoint: startPoint, - endPoint: endPoint, - gradientType: gradientType, - highlightLength: highlightLength, - highlightAngle: highlightAngle, - numberOfColors: numberOfColors, - colors: colors, - width: newWidth, - lineCap: lineCap, - lineJoin: lineJoin, - miterLimit: miterLimit, - dashPattern: dashPattern) - } - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(opacity, forKey: .opacity) - try container.encode(startPoint, forKey: .startPoint) - try container.encode(endPoint, forKey: .endPoint) - try container.encode(gradientType, forKey: .gradientType) - try container.encodeIfPresent(highlightLength, forKey: .highlightLength) - try container.encodeIfPresent(highlightAngle, forKey: .highlightAngle) - try container.encode(width, forKey: .width) - try container.encode(lineCap, forKey: .lineCap) - try container.encode(lineJoin, forKey: .lineJoin) - try container.encode(miterLimit, forKey: .miterLimit) - var colorsContainer = container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors) - try colorsContainer.encode(numberOfColors, forKey: .numberOfColors) - try colorsContainer.encode(colors, forKey: .colors) - try container.encodeIfPresent(dashPattern, forKey: .dashPattern) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case opacity = "o" - case startPoint = "s" - case endPoint = "e" - case gradientType = "t" - case highlightLength = "h" - case highlightAngle = "a" - case colors = "g" - case width = "w" - case lineCap = "lc" - case lineJoin = "lj" - case miterLimit = "ml" - case dashPattern = "d" - } - - private enum GradientDataKeys: String, CodingKey { - case numberOfColors = "p" - case colors = "k" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Group.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Group.swift deleted file mode 100644 index 84a48dde4d88aa77d9281e5ec2a1b285f2813e84..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Group.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// GroupItem.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -/// An item that define a a group of shape items -final class Group: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Group.CodingKeys.self) - items = try container.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .items) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let itemDictionaries: [[String: Any]] = try dictionary.value(for: CodingKeys.items) - items = try [ShapeItem].fromDictionaries(itemDictionaries) - try super.init(dictionary: dictionary) - } - - init(items: [ShapeItem], name: String) { - self.items = items - super.init(name: name, type: .group, hidden: false) - } - - // MARK: Internal - - /// A list of shape items. - let items: [ShapeItem] - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(items, forKey: .items) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case items = "it" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Merge.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Merge.swift deleted file mode 100644 index e14e5934e5cc75700ff18a1fc8c75cfc038d70bf..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Merge.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// Merge.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -// MARK: - MergeMode - -enum MergeMode: Int, Codable, Sendable { - case none - case merge - case add - case subtract - case intersect - case exclude -} - -// MARK: - Merge - -final class Merge: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Merge.CodingKeys.self) - mode = try container.decode(MergeMode.self, forKey: .mode) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let modeRawType: Int = try dictionary.value(for: CodingKeys.mode) - guard let mode = MergeMode(rawValue: modeRawType) else { - throw InitializableError.invalidInput() - } - self.mode = mode - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The mode of the merge path - let mode: MergeMode - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(mode, forKey: .mode) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case mode = "mm" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Rectangle.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Rectangle.swift deleted file mode 100644 index 339c1d7521cad406678b0c53dd1f8037301019df..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Rectangle.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// Rectangle.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -final class Rectangle: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Rectangle.CodingKeys.self) - direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise - position = try container.decode(KeyframeGroup.self, forKey: .position) - size = try container.decode(KeyframeGroup.self, forKey: .size) - cornerRadius = try container.decode(KeyframeGroup.self, forKey: .cornerRadius) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - if - let directionRawType = dictionary[CodingKeys.direction.rawValue] as? Int, - let direction = PathDirection(rawValue: directionRawType) - { - self.direction = direction - } else { - direction = .clockwise - } - let positionDictionary: [String: Any] = try dictionary.value(for: CodingKeys.position) - position = try KeyframeGroup(dictionary: positionDictionary) - let sizeDictionary: [String: Any] = try dictionary.value(for: CodingKeys.size) - size = try KeyframeGroup(dictionary: sizeDictionary) - let cornerRadiusDictionary: [String: Any] = try dictionary.value(for: CodingKeys.cornerRadius) - cornerRadius = try KeyframeGroup(dictionary: cornerRadiusDictionary) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The direction of the rect. - let direction: PathDirection - - /// The position - let position: KeyframeGroup - - /// The size - let size: KeyframeGroup - - /// The Corner radius of the rectangle - let cornerRadius: KeyframeGroup - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(direction, forKey: .direction) - try container.encode(position, forKey: .position) - try container.encode(size, forKey: .size) - try container.encode(cornerRadius, forKey: .cornerRadius) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case direction = "d" - case position = "p" - case size = "s" - case cornerRadius = "r" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Repeater.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Repeater.swift deleted file mode 100644 index 7062bdd53b43cf3c240dbf3041ab184505ef0c6c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Repeater.swift +++ /dev/null @@ -1,172 +0,0 @@ -// -// Repeater.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -final class Repeater: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Repeater.CodingKeys.self) - copies = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .copies) ?? KeyframeGroup(LottieVector1D(0)) - offset = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .offset) ?? KeyframeGroup(LottieVector1D(0)) - let transformContainer = try container.nestedContainer(keyedBy: TransformKeys.self, forKey: .transform) - startOpacity = try transformContainer - .decodeIfPresent(KeyframeGroup.self, forKey: .startOpacity) ?? KeyframeGroup(LottieVector1D(100)) - endOpacity = try transformContainer - .decodeIfPresent(KeyframeGroup.self, forKey: .endOpacity) ?? KeyframeGroup(LottieVector1D(100)) - if let rotation = try transformContainer.decodeIfPresent(KeyframeGroup.self, forKey: .rotation) { - rotationZ = rotation - } else if let rotation = try transformContainer.decodeIfPresent(KeyframeGroup.self, forKey: .rotationZ) { - rotationZ = rotation - } else { - rotationZ = KeyframeGroup(LottieVector1D(0)) - } - - rotationX = try transformContainer - .decodeIfPresent(KeyframeGroup.self, forKey: .rotationX) ?? KeyframeGroup(LottieVector1D(0)) - rotationY = try transformContainer - .decodeIfPresent(KeyframeGroup.self, forKey: .rotationY) ?? KeyframeGroup(LottieVector1D(0)) - - position = try transformContainer - .decodeIfPresent(KeyframeGroup.self, forKey: .position) ?? - KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - anchorPoint = try transformContainer - .decodeIfPresent(KeyframeGroup.self, forKey: .anchorPoint) ?? - KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - scale = try transformContainer - .decodeIfPresent(KeyframeGroup.self, forKey: .scale) ?? - KeyframeGroup(LottieVector3D(x: Double(100), y: 100, z: 100)) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - if let copiesDictionary = dictionary[CodingKeys.copies.rawValue] as? [String: Any] { - copies = try KeyframeGroup(dictionary: copiesDictionary) - } else { - copies = KeyframeGroup(LottieVector1D(0)) - } - if let offsetDictionary = dictionary[CodingKeys.offset.rawValue] as? [String: Any] { - offset = try KeyframeGroup(dictionary: offsetDictionary) - } else { - offset = KeyframeGroup(LottieVector1D(0)) - } - let transformDictionary: [String: Any] = try dictionary.value(for: CodingKeys.transform) - if let startOpacityDictionary = transformDictionary[TransformKeys.startOpacity.rawValue] as? [String: Any] { - startOpacity = try KeyframeGroup(dictionary: startOpacityDictionary) - } else { - startOpacity = KeyframeGroup(LottieVector1D(100)) - } - if let endOpacityDictionary = transformDictionary[TransformKeys.endOpacity.rawValue] as? [String: Any] { - endOpacity = try KeyframeGroup(dictionary: endOpacityDictionary) - } else { - endOpacity = KeyframeGroup(LottieVector1D(100)) - } - if let rotationDictionary = transformDictionary[TransformKeys.rotationX.rawValue] as? [String: Any] { - rotationX = try KeyframeGroup(dictionary: rotationDictionary) - } else { - rotationX = KeyframeGroup(LottieVector1D(0)) - } - if let rotationDictionary = transformDictionary[TransformKeys.rotationY.rawValue] as? [String: Any] { - rotationY = try KeyframeGroup(dictionary: rotationDictionary) - } else { - rotationY = KeyframeGroup(LottieVector1D(0)) - } - if let rotationDictionary = transformDictionary[TransformKeys.rotation.rawValue] as? [String: Any] { - rotationZ = try KeyframeGroup(dictionary: rotationDictionary) - } else if let rotationDictionary = transformDictionary[TransformKeys.rotationZ.rawValue] as? [String: Any] { - rotationZ = try KeyframeGroup(dictionary: rotationDictionary) - } else { - rotationZ = KeyframeGroup(LottieVector1D(0)) - } - if let positionDictionary = transformDictionary[TransformKeys.position.rawValue] as? [String: Any] { - position = try KeyframeGroup(dictionary: positionDictionary) - } else { - position = KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - } - if let anchorPointDictionary = transformDictionary[TransformKeys.anchorPoint.rawValue] as? [String: Any] { - anchorPoint = try KeyframeGroup(dictionary: anchorPointDictionary) - } else { - anchorPoint = KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - } - if let scaleDictionary = transformDictionary[TransformKeys.scale.rawValue] as? [String: Any] { - scale = try KeyframeGroup(dictionary: scaleDictionary) - } else { - scale = KeyframeGroup(LottieVector3D(x: Double(100), y: 100, z: 100)) - } - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The number of copies to repeat - let copies: KeyframeGroup - - /// The offset of each copy - let offset: KeyframeGroup - - /// Start Opacity - let startOpacity: KeyframeGroup - - /// End opacity - let endOpacity: KeyframeGroup - - /// The rotation on X axis - let rotationX: KeyframeGroup - - /// The rotation on Y axis - let rotationY: KeyframeGroup - - /// The rotation on Z axis - let rotationZ: KeyframeGroup - - /// Anchor Point - let anchorPoint: KeyframeGroup - - /// Position - let position: KeyframeGroup - - /// Scale - let scale: KeyframeGroup - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(copies, forKey: .copies) - try container.encode(offset, forKey: .offset) - var transformContainer = container.nestedContainer(keyedBy: TransformKeys.self, forKey: .transform) - try transformContainer.encode(startOpacity, forKey: .startOpacity) - try transformContainer.encode(endOpacity, forKey: .endOpacity) - try transformContainer.encode(rotationX, forKey: .rotationX) - try transformContainer.encode(rotationY, forKey: .rotationY) - try transformContainer.encode(rotationZ, forKey: .rotationZ) - try transformContainer.encode(position, forKey: .position) - try transformContainer.encode(anchorPoint, forKey: .anchorPoint) - try transformContainer.encode(scale, forKey: .scale) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case copies = "c" - case offset = "o" - case transform = "tr" - } - - private enum TransformKeys: String, CodingKey { - case rotation = "r" - case rotationX = "rx" - case rotationY = "ry" - case rotationZ = "rz" - case startOpacity = "so" - case endOpacity = "eo" - case anchorPoint = "a" - case position = "p" - case scale = "s" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/RoundedCorners.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/RoundedCorners.swift deleted file mode 100644 index 6cc1aa85591dc688aed03f6bb8fdc17574ad0d62..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/RoundedCorners.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// RoundedCorners.swift -// Lottie -// -// Created by Duolingo on 10/31/22. -// - -// MARK: - RoundedCorners - -final class RoundedCorners: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: RoundedCorners.CodingKeys.self) - radius = try - container.decode( - KeyframeGroup.self, - forKey: .radius) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let radiusDictionary: [String: Any] = try dictionary.value(for: CodingKeys.radius) - radius = try KeyframeGroup(dictionary: radiusDictionary) - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The radius of rounded corners - let radius: KeyframeGroup - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(radius, forKey: .radius) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case radius = "r" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Shape.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Shape.swift deleted file mode 100644 index eb5158bf11c83aeaa345b5ad996531eceda93eca..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Shape.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// VectorShape.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -/// An item that defines an custom shape -final class Shape: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Shape.CodingKeys.self) - path = try container.decode(KeyframeGroup.self, forKey: .path) - direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let pathDictionary: [String: Any] = try dictionary.value(for: CodingKeys.path) - path = try KeyframeGroup(dictionary: pathDictionary) - if - let directionRawValue = dictionary[CodingKeys.direction.rawValue] as? Int, - let direction = PathDirection(rawValue: directionRawValue) - { - self.direction = direction - } else { - direction = nil - } - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The Path - let path: KeyframeGroup - - let direction: PathDirection? - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(path, forKey: .path) - try container.encodeIfPresent(direction, forKey: .direction) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case path = "ks" - case direction = "d" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/ShapeItem.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/ShapeItem.swift deleted file mode 100644 index 5911a691476ab502d40b3e0fbfac6fb144bb60c2..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/ShapeItem.swift +++ /dev/null @@ -1,171 +0,0 @@ -// -// ShapeItem.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -// MARK: - ShapeType - -enum ShapeType: String, Codable, Sendable { - case ellipse = "el" - case fill = "fl" - case gradientFill = "gf" - case group = "gr" - case gradientStroke = "gs" - case merge = "mm" - case rectangle = "rc" - case repeater = "rp" - case round = "rd" - case shape = "sh" - case star = "sr" - case stroke = "st" - case trim = "tm" - case transform = "tr" - case unknown - - public init(from decoder: Decoder) throws { - self = try ShapeType(rawValue: decoder.singleValueContainer().decode(RawValue.self)) ?? .unknown - } -} - -// MARK: ClassFamily - -extension ShapeType: ClassFamily { - - static var discriminator: Discriminator = .type - - func getType() -> AnyObject.Type { - switch self { - case .ellipse: - return Ellipse.self - case .fill: - return Fill.self - case .gradientFill: - return GradientFill.self - case .group: - return Group.self - case .gradientStroke: - return GradientStroke.self - case .merge: - return Merge.self - case .rectangle: - return Rectangle.self - case .repeater: - return Repeater.self - case .round: - return RoundedCorners.self - case .shape: - return Shape.self - case .star: - return Star.self - case .stroke: - return Stroke.self - case .trim: - return Trim.self - case .transform: - return ShapeTransform.self - default: - return ShapeItem.self - } - } -} - -// MARK: - ShapeItem - -/// An item belonging to a Shape Layer -class ShapeItem: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: ShapeItem.CodingKeys.self) - name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Layer" - type = try container.decode(ShapeType.self, forKey: .type) - hidden = try container.decodeIfPresent(Bool.self, forKey: .hidden) ?? false - } - - required init(dictionary: [String: Any]) throws { - name = (try? dictionary.value(for: CodingKeys.name)) ?? "Layer" - type = ShapeType(rawValue: try dictionary.value(for: CodingKeys.type)) ?? .unknown - hidden = (try? dictionary.value(for: CodingKeys.hidden)) ?? false - } - - init( - name: String, - type: ShapeType, - hidden: Bool) - { - self.name = name - self.type = type - self.hidden = hidden - } - - // MARK: Internal - - /// The name of the shape - let name: String - - /// The type of shape - let type: ShapeType - - let hidden: Bool - - // MARK: Fileprivate - - fileprivate enum CodingKeys: String, CodingKey { - case name = "nm" - case type = "ty" - case hidden = "hd" - } -} - -extension [ShapeItem] { - - static func fromDictionaries(_ dictionaries: [[String: Any]]) throws -> [ShapeItem] { - try dictionaries.compactMap { dictionary in - let shapeType = dictionary[ShapeItem.CodingKeys.type.rawValue] as? String - switch ShapeType(rawValue: shapeType ?? ShapeType.unknown.rawValue) { - case .ellipse: - return try Ellipse(dictionary: dictionary) - case .fill: - return try Fill(dictionary: dictionary) - case .gradientFill: - return try GradientFill(dictionary: dictionary) - case .group: - return try Group(dictionary: dictionary) - case .gradientStroke: - return try GradientStroke(dictionary: dictionary) - case .merge: - return try Merge(dictionary: dictionary) - case .rectangle: - return try Rectangle(dictionary: dictionary) - case .repeater: - return try Repeater(dictionary: dictionary) - case .round: - return try RoundedCorners(dictionary: dictionary) - case .shape: - return try Shape(dictionary: dictionary) - case .star: - return try Star(dictionary: dictionary) - case .stroke: - return try Stroke(dictionary: dictionary) - case .trim: - return try Trim(dictionary: dictionary) - case .transform: - return try ShapeTransform(dictionary: dictionary) - case .none: - return nil - default: - return try ShapeItem(dictionary: dictionary) - } - } - } -} - -// MARK: - ShapeItem + Sendable - -/// Since `ShapeItem` isn't `final`, we have to use `@unchecked Sendable` instead of `Sendable.` -/// All `ShapeItem` subclasses are immutable `Sendable` values. -// swiftlint:disable:next no_unchecked_sendable -extension ShapeItem: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/ShapeTransform.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/ShapeTransform.swift deleted file mode 100644 index 26c13db45d38269958edf487d07d3115abd9db72..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/ShapeTransform.swift +++ /dev/null @@ -1,193 +0,0 @@ -// -// TransformItem.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -final class ShapeTransform: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: ShapeTransform.CodingKeys.self) - anchor = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .anchor) ?? - KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - position = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .position) ?? - KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - scale = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .scale) ?? - KeyframeGroup(LottieVector3D(x: Double(100), y: 100, z: 100)) - - rotationX = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .rotationX) ?? KeyframeGroup(LottieVector1D(0)) - rotationY = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .rotationY) ?? KeyframeGroup(LottieVector1D(0)) - if - let rotation = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .rotation) - { - rotationZ = rotation - } else if - let rotation = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .rotationZ) - { - rotationZ = rotation - } else { - rotationZ = KeyframeGroup(LottieVector1D(0)) - } - - opacity = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .opacity) ?? KeyframeGroup(LottieVector1D(100)) - skew = try container.decodeIfPresent(KeyframeGroup.self, forKey: .skew) ?? KeyframeGroup(LottieVector1D(0)) - skewAxis = try container - .decodeIfPresent(KeyframeGroup.self, forKey: .skewAxis) ?? KeyframeGroup(LottieVector1D(0)) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - if - let anchorDictionary = dictionary[CodingKeys.anchor.rawValue] as? [String: Any], - let anchor = try? KeyframeGroup(dictionary: anchorDictionary) - { - self.anchor = anchor - } else { - anchor = KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - } - if - let positionDictionary = dictionary[CodingKeys.position.rawValue] as? [String: Any], - let position = try? KeyframeGroup(dictionary: positionDictionary) - { - self.position = position - } else { - position = KeyframeGroup(LottieVector3D(x: Double(0), y: 0, z: 0)) - } - if - let scaleDictionary = dictionary[CodingKeys.scale.rawValue] as? [String: Any], - let scale = try? KeyframeGroup(dictionary: scaleDictionary) - { - self.scale = scale - } else { - scale = KeyframeGroup(LottieVector3D(x: Double(100), y: 100, z: 100)) - } - - if - let rotationDictionary = dictionary[CodingKeys.rotationX.rawValue] as? [String: Any], - let rotation = try? KeyframeGroup(dictionary: rotationDictionary) - { - rotationX = rotation - } else { - rotationX = KeyframeGroup(LottieVector1D(0)) - } - - if - let rotationDictionary = dictionary[CodingKeys.rotationY.rawValue] as? [String: Any], - let rotation = try? KeyframeGroup(dictionary: rotationDictionary) - { - rotationY = rotation - } else { - rotationY = KeyframeGroup(LottieVector1D(0)) - } - - if - let rotationDictionary = dictionary[CodingKeys.rotation.rawValue] as? [String: Any], - let rotation = try? KeyframeGroup(dictionary: rotationDictionary) - { - rotationZ = rotation - } else if - let rotationDictionary = dictionary[CodingKeys.rotationZ.rawValue] as? [String: Any], - let rotation = try? KeyframeGroup(dictionary: rotationDictionary) - { - rotationZ = rotation - } else { - rotationZ = KeyframeGroup(LottieVector1D(0)) - } - - if - let opacityDictionary = dictionary[CodingKeys.opacity.rawValue] as? [String: Any], - let opacity = try? KeyframeGroup(dictionary: opacityDictionary) - { - self.opacity = opacity - } else { - opacity = KeyframeGroup(LottieVector1D(100)) - } - if - let skewDictionary = dictionary[CodingKeys.skew.rawValue] as? [String: Any], - let skew = try? KeyframeGroup(dictionary: skewDictionary) - { - self.skew = skew - } else { - skew = KeyframeGroup(LottieVector1D(0)) - } - if - let skewAxisDictionary = dictionary[CodingKeys.skewAxis.rawValue] as? [String: Any], - let skewAxis = try? KeyframeGroup(dictionary: skewAxisDictionary) - { - self.skewAxis = skewAxis - } else { - skewAxis = KeyframeGroup(LottieVector1D(0)) - } - - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// Anchor Point - let anchor: KeyframeGroup - - /// Position - let position: KeyframeGroup - - /// Scale - let scale: KeyframeGroup - - /// Rotation on X axis - let rotationX: KeyframeGroup - - /// Rotation on Y axis - let rotationY: KeyframeGroup - - /// Rotation on Z axis - let rotationZ: KeyframeGroup - - /// opacity - let opacity: KeyframeGroup - - /// Skew - let skew: KeyframeGroup - - /// Skew Axis - let skewAxis: KeyframeGroup - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(anchor, forKey: .anchor) - try container.encode(position, forKey: .position) - try container.encode(scale, forKey: .scale) - try container.encode(rotationX, forKey: .rotationX) - try container.encode(rotationY, forKey: .rotationY) - try container.encode(rotationZ, forKey: .rotationZ) - try container.encode(opacity, forKey: .opacity) - try container.encode(skew, forKey: .skew) - try container.encode(skewAxis, forKey: .skewAxis) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case anchor = "a" - case position = "p" - case scale = "s" - case rotation = "r" - case rotationX = "rx" - case rotationY = "ry" - case rotationZ = "rz" - case opacity = "o" - case skew = "sk" - case skewAxis = "sa" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Star.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Star.swift deleted file mode 100644 index 06bd869d66becfbd66dca6bea22d22a0857fd415..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Star.swift +++ /dev/null @@ -1,129 +0,0 @@ -// -// Star.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -// MARK: - StarType - -enum StarType: Int, Codable, Sendable { - case none - case star - case polygon -} - -// MARK: - Star - -final class Star: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Star.CodingKeys.self) - direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise - position = try container.decode(KeyframeGroup.self, forKey: .position) - outerRadius = try container.decode(KeyframeGroup.self, forKey: .outerRadius) - outerRoundness = try container.decode(KeyframeGroup.self, forKey: .outerRoundness) - innerRadius = try container.decodeIfPresent(KeyframeGroup.self, forKey: .innerRadius) - innerRoundness = try container.decodeIfPresent(KeyframeGroup.self, forKey: .innerRoundness) - rotation = try container.decode(KeyframeGroup.self, forKey: .rotation) - points = try container.decode(KeyframeGroup.self, forKey: .points) - starType = try container.decode(StarType.self, forKey: .starType) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - if - let directionRawValue = dictionary[CodingKeys.direction.rawValue] as? Int, - let direction = PathDirection(rawValue: directionRawValue) - { - self.direction = direction - } else { - direction = .clockwise - } - let positionDictionary: [String: Any] = try dictionary.value(for: CodingKeys.position) - position = try KeyframeGroup(dictionary: positionDictionary) - let outerRadiusDictionary: [String: Any] = try dictionary.value(for: CodingKeys.outerRadius) - outerRadius = try KeyframeGroup(dictionary: outerRadiusDictionary) - let outerRoundnessDictionary: [String: Any] = try dictionary.value(for: CodingKeys.outerRoundness) - outerRoundness = try KeyframeGroup(dictionary: outerRoundnessDictionary) - if let innerRadiusDictionary = dictionary[CodingKeys.innerRadius.rawValue] as? [String: Any] { - innerRadius = try KeyframeGroup(dictionary: innerRadiusDictionary) - } else { - innerRadius = nil - } - if let innerRoundnessDictionary = dictionary[CodingKeys.innerRoundness.rawValue] as? [String: Any] { - innerRoundness = try KeyframeGroup(dictionary: innerRoundnessDictionary) - } else { - innerRoundness = nil - } - let rotationDictionary: [String: Any] = try dictionary.value(for: CodingKeys.rotation) - rotation = try KeyframeGroup(dictionary: rotationDictionary) - let pointsDictionary: [String: Any] = try dictionary.value(for: CodingKeys.points) - points = try KeyframeGroup(dictionary: pointsDictionary) - let starTypeRawValue: Int = try dictionary.value(for: CodingKeys.starType) - guard let starType = StarType(rawValue: starTypeRawValue) else { - throw InitializableError.invalidInput() - } - self.starType = starType - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The direction of the star. - let direction: PathDirection - - /// The position of the star - let position: KeyframeGroup - - /// The outer radius of the star - let outerRadius: KeyframeGroup - - /// The outer roundness of the star - let outerRoundness: KeyframeGroup - - /// The outer radius of the star - let innerRadius: KeyframeGroup? - - /// The outer roundness of the star - let innerRoundness: KeyframeGroup? - - /// The rotation of the star - let rotation: KeyframeGroup - - /// The number of points on the star - let points: KeyframeGroup - - /// The type of star - let starType: StarType - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(direction, forKey: .direction) - try container.encode(position, forKey: .position) - try container.encode(outerRadius, forKey: .outerRadius) - try container.encode(outerRoundness, forKey: .outerRoundness) - try container.encode(innerRadius, forKey: .innerRadius) - try container.encode(innerRoundness, forKey: .innerRoundness) - try container.encode(rotation, forKey: .rotation) - try container.encode(points, forKey: .points) - try container.encode(starType, forKey: .starType) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case direction = "d" - case position = "p" - case outerRadius = "or" - case outerRoundness = "os" - case innerRadius = "ir" - case innerRoundness = "is" - case rotation = "r" - case points = "pt" - case starType = "sy" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Stroke.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Stroke.swift deleted file mode 100644 index c9f5e8b1cc2e0084148c9ccbccbc5aa0d51a7b3f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Stroke.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// Stroke.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -final class Stroke: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Stroke.CodingKeys.self) - opacity = try container.decode(KeyframeGroup.self, forKey: .opacity) - color = try container.decode(KeyframeGroup.self, forKey: .color) - width = try container.decode(KeyframeGroup.self, forKey: .width) - lineCap = try container.decodeIfPresent(LineCap.self, forKey: .lineCap) ?? .round - lineJoin = try container.decodeIfPresent(LineJoin.self, forKey: .lineJoin) ?? .round - miterLimit = try container.decodeIfPresent(Double.self, forKey: .miterLimit) ?? 4 - dashPattern = try container.decodeIfPresent([DashElement].self, forKey: .dashPattern) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let opacityDictionary: [String: Any] = try dictionary.value(for: CodingKeys.opacity) - opacity = try KeyframeGroup(dictionary: opacityDictionary) - let colorDictionary: [String: Any] = try dictionary.value(for: CodingKeys.color) - color = try KeyframeGroup(dictionary: colorDictionary) - let widthDictionary: [String: Any] = try dictionary.value(for: CodingKeys.width) - width = try KeyframeGroup(dictionary: widthDictionary) - if - let lineCapRawValue = dictionary[CodingKeys.lineCap.rawValue] as? Int, - let lineCap = LineCap(rawValue: lineCapRawValue) - { - self.lineCap = lineCap - } else { - lineCap = .round - } - if - let lineJoinRawValue = dictionary[CodingKeys.lineJoin.rawValue] as? Int, - let lineJoin = LineJoin(rawValue: lineJoinRawValue) - { - self.lineJoin = lineJoin - } else { - lineJoin = .round - } - miterLimit = (try? dictionary.value(for: CodingKeys.miterLimit)) ?? 4 - let dashPatternDictionaries = dictionary[CodingKeys.dashPattern.rawValue] as? [[String: Any]] - dashPattern = try? dashPatternDictionaries?.map { try DashElement(dictionary: $0) } - try super.init(dictionary: dictionary) - } - - init( - name: String, - hidden: Bool, - opacity: KeyframeGroup, - color: KeyframeGroup, - width: KeyframeGroup, - lineCap: LineCap, - lineJoin: LineJoin, - miterLimit: Double, - dashPattern: [DashElement]?) - { - self.opacity = opacity - self.color = color - self.width = width - self.lineCap = lineCap - self.lineJoin = lineJoin - self.miterLimit = miterLimit - self.dashPattern = dashPattern - super.init(name: name, type: .stroke, hidden: hidden) - } - - // MARK: Internal - - /// The opacity of the stroke - let opacity: KeyframeGroup - - /// The Color of the stroke - let color: KeyframeGroup - - /// The width of the stroke - let width: KeyframeGroup - - /// Line Cap - let lineCap: LineCap - - /// Line Join - let lineJoin: LineJoin - - /// Miter Limit - let miterLimit: Double - - /// The dash pattern of the stroke - let dashPattern: [DashElement]? - - /// Creates a copy of this Stroke with the given updated width keyframes - func copy(width newWidth: KeyframeGroup) -> Stroke { - Stroke( - name: name, - hidden: hidden, - opacity: opacity, - color: color, - width: newWidth, - lineCap: lineCap, - lineJoin: lineJoin, - miterLimit: miterLimit, - dashPattern: dashPattern) - } - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(opacity, forKey: .opacity) - try container.encode(color, forKey: .color) - try container.encode(width, forKey: .width) - try container.encode(lineCap, forKey: .lineCap) - try container.encode(lineJoin, forKey: .lineJoin) - try container.encode(miterLimit, forKey: .miterLimit) - try container.encodeIfPresent(dashPattern, forKey: .dashPattern) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case opacity = "o" - case color = "c" - case width = "w" - case lineCap = "lc" - case lineJoin = "lj" - case miterLimit = "ml" - case dashPattern = "d" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Trim.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Trim.swift deleted file mode 100644 index 0843d8858b700bfcf124d8faa8f0c68cae79a10f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/ShapeItems/Trim.swift +++ /dev/null @@ -1,83 +0,0 @@ -// -// Trim.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -// MARK: - TrimType - -enum TrimType: Int, Codable { - case simultaneously = 1 - case individually = 2 -} - -// MARK: - Trim - -final class Trim: ShapeItem { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Trim.CodingKeys.self) - start = try container.decode(KeyframeGroup.self, forKey: .start) - end = try container.decode(KeyframeGroup.self, forKey: .end) - offset = try container.decode(KeyframeGroup.self, forKey: .offset) - trimType = try container.decode(TrimType.self, forKey: .trimType) - try super.init(from: decoder) - } - - required init(dictionary: [String: Any]) throws { - let startDictionary: [String: Any] = try dictionary.value(for: CodingKeys.start) - start = try KeyframeGroup(dictionary: startDictionary) - let endDictionary: [String: Any] = try dictionary.value(for: CodingKeys.end) - end = try KeyframeGroup(dictionary: endDictionary) - let offsetDictionary: [String: Any] = try dictionary.value(for: CodingKeys.offset) - offset = try KeyframeGroup(dictionary: offsetDictionary) - let trimTypeRawValue: Int = try dictionary.value(for: CodingKeys.trimType) - guard let trimType = TrimType(rawValue: trimTypeRawValue) else { - throw InitializableError.invalidInput() - } - self.trimType = trimType - try super.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The start of the trim - let start: KeyframeGroup - - /// The end of the trim - let end: KeyframeGroup - - /// The offset of the trim - let offset: KeyframeGroup - - let trimType: TrimType - - /// If this trim doesn't affect the path at all then we can consider it empty - var isEmpty: Bool { - start.keyframes.count == 1 - && start.keyframes[0].value.value == 0 - && end.keyframes.count == 1 - && end.keyframes[0].value.value == 100 - } - - override func encode(to encoder: Encoder) throws { - try super.encode(to: encoder) - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(start, forKey: .start) - try container.encode(end, forKey: .end) - try container.encode(offset, forKey: .offset) - try container.encode(trimType, forKey: .trimType) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case start = "s" - case end = "e" - case offset = "o" - case trimType = "m" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/Font.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/Font.swift deleted file mode 100644 index 0a1187f5bd67514c778908cceecd388c4c4b2c9f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/Font.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// Font.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/9/19. -// - -// MARK: - Font - -final class Font: Codable, Sendable, DictionaryInitializable { - - // MARK: Lifecycle - - init(dictionary: [String: Any]) throws { - name = try dictionary.value(for: CodingKeys.name) - familyName = try dictionary.value(for: CodingKeys.familyName) - style = try dictionary.value(for: CodingKeys.style) - ascent = try dictionary.value(for: CodingKeys.ascent) - } - - // MARK: Internal - - let name: String - let familyName: String - let style: String - let ascent: Double - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case name = "fName" - case familyName = "fFamily" - case style = "fStyle" - case ascent - } - -} - -// MARK: - FontList - -/// A list of fonts -final class FontList: Codable, Sendable, DictionaryInitializable { - - // MARK: Lifecycle - - init(dictionary: [String: Any]) throws { - let fontDictionaries: [[String: Any]] = try dictionary.value(for: CodingKeys.fonts) - fonts = try fontDictionaries.map { try Font(dictionary: $0) } - } - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case fonts = "list" - } - - let fonts: [Font] - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/Glyph.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/Glyph.swift deleted file mode 100644 index 7c68c0701ed88c63f37d1a856bf6580ef73d2e59..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/Glyph.swift +++ /dev/null @@ -1,94 +0,0 @@ -// -// Glyph.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/9/19. -// - -/// A model that holds a vector character -final class Glyph: Codable, Sendable, DictionaryInitializable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: Glyph.CodingKeys.self) - character = try container.decode(String.self, forKey: .character) - fontSize = try container.decode(Double.self, forKey: .fontSize) - fontFamily = try container.decode(String.self, forKey: .fontFamily) - fontStyle = try container.decode(String.self, forKey: .fontStyle) - width = try container.decode(Double.self, forKey: .width) - if - container.contains(.shapeWrapper), - let shapeContainer = try? container.nestedContainer(keyedBy: ShapeKey.self, forKey: .shapeWrapper), - shapeContainer.contains(.shapes) - { - shapes = try shapeContainer.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .shapes) - } else { - shapes = [] - } - } - - init(dictionary: [String: Any]) throws { - character = try dictionary.value(for: CodingKeys.character) - fontSize = try dictionary.value(for: CodingKeys.fontSize) - fontFamily = try dictionary.value(for: CodingKeys.fontFamily) - fontStyle = try dictionary.value(for: CodingKeys.fontStyle) - width = try dictionary.value(for: CodingKeys.width) - if - let shapes = dictionary[CodingKeys.shapeWrapper.rawValue] as? [String: Any], - let shapeDictionaries = shapes[ShapeKey.shapes.rawValue] as? [[String: Any]] - { - self.shapes = try [ShapeItem].fromDictionaries(shapeDictionaries) - } else { - shapes = [ShapeItem]() - } - } - - // MARK: Internal - - /// The character - let character: String - - /// The font size of the character - let fontSize: Double - - /// The font family of the character - let fontFamily: String - - /// The Style of the character - let fontStyle: String - - /// The Width of the character - let width: Double - - /// The Shape Data of the Character - let shapes: [ShapeItem] - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - - try container.encode(character, forKey: .character) - try container.encode(fontSize, forKey: .fontSize) - try container.encode(fontFamily, forKey: .fontFamily) - try container.encode(fontStyle, forKey: .fontStyle) - try container.encode(width, forKey: .width) - - var shapeContainer = container.nestedContainer(keyedBy: ShapeKey.self, forKey: .shapeWrapper) - try shapeContainer.encode(shapes, forKey: .shapes) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case character = "ch" - case fontSize = "size" - case fontFamily = "fFamily" - case fontStyle = "style" - case width = "w" - case shapeWrapper = "data" - } - - private enum ShapeKey: String, CodingKey { - case shapes - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/TextAnimator.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/TextAnimator.swift deleted file mode 100644 index 9e16ffe05a49e558ed196abbc1251ae647282f8a..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/TextAnimator.swift +++ /dev/null @@ -1,194 +0,0 @@ -// -// TextAnimator.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/9/19. -// - -final class TextAnimator: Codable, DictionaryInitializable { - - // MARK: Lifecycle - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: TextAnimator.CodingKeys.self) - name = try container.decodeIfPresent(String.self, forKey: .name) ?? "" - let animatorContainer = try container.nestedContainer(keyedBy: TextAnimatorKeys.self, forKey: .textAnimator) - fillColor = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .fillColor) - strokeColor = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .strokeColor) - strokeWidth = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .strokeWidth) - tracking = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .tracking) - anchor = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .anchor) - position = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .position) - scale = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .scale) - skew = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .skew) - skewAxis = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .skewAxis) - rotationX = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .rotationX) - rotationY = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .rotationY) - if let rotation = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .rotation) { - rotationZ = rotation - } else if let rotation = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .rotationZ) { - rotationZ = rotation - } else { - rotationZ = nil - } - opacity = try animatorContainer.decodeIfPresent(KeyframeGroup.self, forKey: .opacity) - } - - init(dictionary: [String: Any]) throws { - name = (try? dictionary.value(for: CodingKeys.name)) ?? "" - let animatorDictionary: [String: Any] = try dictionary.value(for: CodingKeys.textAnimator) - if let fillColorDictionary = animatorDictionary[TextAnimatorKeys.fillColor.rawValue] as? [String: Any] { - fillColor = try? KeyframeGroup(dictionary: fillColorDictionary) - } else { - fillColor = nil - } - if let strokeColorDictionary = animatorDictionary[TextAnimatorKeys.strokeColor.rawValue] as? [String: Any] { - strokeColor = try? KeyframeGroup(dictionary: strokeColorDictionary) - } else { - strokeColor = nil - } - if let strokeWidthDictionary = animatorDictionary[TextAnimatorKeys.strokeWidth.rawValue] as? [String: Any] { - strokeWidth = try? KeyframeGroup(dictionary: strokeWidthDictionary) - } else { - strokeWidth = nil - } - if let trackingDictionary = animatorDictionary[TextAnimatorKeys.tracking.rawValue] as? [String: Any] { - tracking = try? KeyframeGroup(dictionary: trackingDictionary) - } else { - tracking = nil - } - if let anchorDictionary = animatorDictionary[TextAnimatorKeys.anchor.rawValue] as? [String: Any] { - anchor = try? KeyframeGroup(dictionary: anchorDictionary) - } else { - anchor = nil - } - if let positionDictionary = animatorDictionary[TextAnimatorKeys.position.rawValue] as? [String: Any] { - position = try? KeyframeGroup(dictionary: positionDictionary) - } else { - position = nil - } - if let scaleDictionary = animatorDictionary[TextAnimatorKeys.scale.rawValue] as? [String: Any] { - scale = try? KeyframeGroup(dictionary: scaleDictionary) - } else { - scale = nil - } - if let skewDictionary = animatorDictionary[TextAnimatorKeys.skew.rawValue] as? [String: Any] { - skew = try? KeyframeGroup(dictionary: skewDictionary) - } else { - skew = nil - } - if let skewAxisDictionary = animatorDictionary[TextAnimatorKeys.skewAxis.rawValue] as? [String: Any] { - skewAxis = try? KeyframeGroup(dictionary: skewAxisDictionary) - } else { - skewAxis = nil - } - if let rotationDictionary = animatorDictionary[TextAnimatorKeys.rotationX.rawValue] as? [String: Any] { - rotationX = try? KeyframeGroup(dictionary: rotationDictionary) - } else { - rotationX = nil - } - - if let rotationDictionary = animatorDictionary[TextAnimatorKeys.rotationY.rawValue] as? [String: Any] { - rotationY = try? KeyframeGroup(dictionary: rotationDictionary) - } else { - rotationY = nil - } - - if let rotationDictionary = animatorDictionary[TextAnimatorKeys.rotation.rawValue] as? [String: Any] { - rotationZ = try? KeyframeGroup(dictionary: rotationDictionary) - } else if let rotationDictionary = animatorDictionary[TextAnimatorKeys.rotationZ.rawValue] as? [String: Any] { - rotationZ = try? KeyframeGroup(dictionary: rotationDictionary) - } else { - rotationZ = nil - } - - if let opacityDictionary = animatorDictionary[TextAnimatorKeys.opacity.rawValue] as? [String: Any] { - opacity = try KeyframeGroup(dictionary: opacityDictionary) - } else { - opacity = nil - } - } - - // MARK: Internal - - let name: String - - /// Anchor - let anchor: KeyframeGroup? - - /// Position - let position: KeyframeGroup? - - /// Scale - let scale: KeyframeGroup? - - /// Skew - let skew: KeyframeGroup? - - /// Skew Axis - let skewAxis: KeyframeGroup? - - /// Rotation on X axis - let rotationX: KeyframeGroup? - - /// Rotation on Y axis - let rotationY: KeyframeGroup? - - /// Rotation on Z axis - let rotationZ: KeyframeGroup? - - /// Opacity - let opacity: KeyframeGroup? - - /// Stroke Color - let strokeColor: KeyframeGroup? - - /// Fill Color - let fillColor: KeyframeGroup? - - /// Stroke Width - let strokeWidth: KeyframeGroup? - - /// Tracking - let tracking: KeyframeGroup? - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - var animatorContainer = container.nestedContainer(keyedBy: TextAnimatorKeys.self, forKey: .textAnimator) - try animatorContainer.encodeIfPresent(fillColor, forKey: .fillColor) - try animatorContainer.encodeIfPresent(strokeColor, forKey: .strokeColor) - try animatorContainer.encodeIfPresent(strokeWidth, forKey: .strokeWidth) - try animatorContainer.encodeIfPresent(tracking, forKey: .tracking) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { -// case textSelector = "s" TODO - case textAnimator = "a" - case name = "nm" - } - - private enum TextSelectorKeys: String, CodingKey { - case start = "s" - case end = "e" - case offset = "o" - } - - private enum TextAnimatorKeys: String, CodingKey { - case fillColor = "fc" - case strokeColor = "sc" - case strokeWidth = "sw" - case tracking = "t" - case anchor = "a" - case position = "p" - case scale = "s" - case skew = "sk" - case skewAxis = "sa" - case rotation = "r" - case rotationX = "rx" - case rotationY = "ry" - case rotationZ = "rz" - case opacity = "o" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/TextDocument.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/TextDocument.swift deleted file mode 100644 index 674c9488ca7980989519c4929195e92560067266..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Model/Text/TextDocument.swift +++ /dev/null @@ -1,121 +0,0 @@ -// -// TextDocument.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/9/19. -// - -// MARK: - TextJustification - -enum TextJustification: Int, Codable { - case left - case right - case center -} - -// MARK: - TextDocument - -final class TextDocument: Codable, DictionaryInitializable, AnyInitializable { - - // MARK: Lifecycle - - init(dictionary: [String: Any]) throws { - text = try dictionary.value(for: CodingKeys.text) - fontSize = try dictionary.value(for: CodingKeys.fontSize) - fontFamily = try dictionary.value(for: CodingKeys.fontFamily) - let justificationValue: Int = try dictionary.value(for: CodingKeys.justification) - guard let justification = TextJustification(rawValue: justificationValue) else { - throw InitializableError.invalidInput() - } - self.justification = justification - tracking = try dictionary.value(for: CodingKeys.tracking) - lineHeight = try dictionary.value(for: CodingKeys.lineHeight) - baseline = try dictionary.value(for: CodingKeys.baseline) - if let fillColorRawValue = dictionary[CodingKeys.fillColorData.rawValue] { - fillColorData = try? LottieColor(value: fillColorRawValue) - } else { - fillColorData = nil - } - if let strokeColorRawValue = dictionary[CodingKeys.strokeColorData.rawValue] { - strokeColorData = try? LottieColor(value: strokeColorRawValue) - } else { - strokeColorData = nil - } - strokeWidth = try? dictionary.value(for: CodingKeys.strokeWidth) - strokeOverFill = try? dictionary.value(for: CodingKeys.strokeOverFill) - if let textFramePositionRawValue = dictionary[CodingKeys.textFramePosition.rawValue] { - textFramePosition = try? LottieVector3D(value: textFramePositionRawValue) - } else { - textFramePosition = nil - } - if let textFrameSizeRawValue = dictionary[CodingKeys.textFrameSize.rawValue] { - textFrameSize = try? LottieVector3D(value: textFrameSizeRawValue) - } else { - textFrameSize = nil - } - } - - convenience init(value: Any) throws { - guard let dictionary = value as? [String: Any] else { - throw InitializableError.invalidInput() - } - try self.init(dictionary: dictionary) - } - - // MARK: Internal - - /// The Text - let text: String - - /// The Font size - let fontSize: Double - - /// The Font Family - let fontFamily: String - - /// Justification - let justification: TextJustification - - /// Tracking - let tracking: Int - - /// Line Height - let lineHeight: Double - - /// Baseline - let baseline: Double? - - /// Fill Color data - let fillColorData: LottieColor? - - /// Scroke Color data - let strokeColorData: LottieColor? - - /// Stroke Width - let strokeWidth: Double? - - /// Stroke Over Fill - let strokeOverFill: Bool? - - let textFramePosition: LottieVector3D? - - let textFrameSize: LottieVector3D? - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case text = "t" - case fontSize = "s" - case fontFamily = "f" - case justification = "j" - case tracking = "tr" - case lineHeight = "lh" - case baseline = "ls" - case fillColorData = "fc" - case strokeColorData = "sc" - case strokeWidth = "sw" - case strokeOverFill = "of" - case textFramePosition = "ps" - case textFrameSize = "sz" - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/RootAnimationLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/RootAnimationLayer.swift deleted file mode 100644 index aa1854162c13c022a748a0ef18062c1268406b82..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/RootAnimationLayer.swift +++ /dev/null @@ -1,53 +0,0 @@ -// Created by Cal Stephens on 12/13/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -// MARK: - RootAnimationLayer - -/// A root `CALayer` responsible for playing a Lottie animation -protocol RootAnimationLayer: CALayer { - var lottieAnimationLayer: LottieAnimationLayer? { get set } - - var currentFrame: AnimationFrameTime { get set } - var renderScale: CGFloat { get set } - var respectAnimationFrameRate: Bool { get set } - - var _animationLayers: [CALayer] { get } - var imageProvider: AnimationImageProvider { get set } - var textProvider: AnimationKeypathTextProvider { get set } - var fontProvider: AnimationFontProvider { get set } - - /// The `CAAnimation` key corresponding to the primary animation. - /// - `LottieAnimationView` uses this key to check if the animation is still active - var primaryAnimationKey: AnimationKey { get } - - /// Whether or not this layer is currently playing an animation - /// - If the layer returns `nil`, `LottieAnimationView` determines if an animation - /// is playing by checking if there is an active animation for `primaryAnimationKey` - var isAnimationPlaying: Bool? { get } - - /// Instructs this layer to remove all `CAAnimation`s, - /// other than the `CAAnimation` managed by `LottieAnimationView` (if applicable) - func removeAnimations() - - func reloadImages() - func forceDisplayUpdate() - func logHierarchyKeypaths() - func allHierarchyKeypaths() -> [String] - func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) - func getValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? - func getOriginalValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? - - func layer(for keypath: AnimationKeypath) -> CALayer? - func animatorNodes(for keypath: AnimationKeypath) -> [AnimatorNode]? -} - -// MARK: - AnimationKey - -enum AnimationKey { - /// The primary animation and its key should be managed by `LottieAnimationView` - case managed - /// The primary animation always uses the given key - case specific(String) -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Debugging/AnimatorNodeDebugging.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Debugging/AnimatorNodeDebugging.swift deleted file mode 100644 index 79b7f5c04f251aaf41284c8b2914c242d1ae7dac..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Debugging/AnimatorNodeDebugging.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// AnimatorNodeDebugging.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/18/19. -// - -extension AnimatorNode { - - func printNodeTree() { - parentNode?.printNodeTree() - LottieLogger.shared.info(String(describing: type(of: self))) - - if let group = self as? GroupNode { - LottieLogger.shared.info("* |Children") - group.rootNode?.printNodeTree() - LottieLogger.shared.info("*") - } else { - LottieLogger.shared.info("|") - } - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Debugging/LayerDebugging.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Debugging/LayerDebugging.swift deleted file mode 100644 index 5081ee985df788ebe26b7c2d5e565975e88f8b8f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Debugging/LayerDebugging.swift +++ /dev/null @@ -1,222 +0,0 @@ -// -// LayerDebugging.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/24/19. -// - -import QuartzCore - -// MARK: - LayerDebugStyle - -struct LayerDebugStyle { - let anchorColor: CGColor - let boundsColor: CGColor - let anchorWidth: CGFloat - let boundsWidth: CGFloat -} - -// MARK: - LayerDebugging - -protocol LayerDebugging { - var debugStyle: LayerDebugStyle { get } -} - -// MARK: - CustomLayerDebugging - -protocol CustomLayerDebugging { - func layerForDebugging() -> CALayer -} - -// MARK: - DebugLayer - -class DebugLayer: CALayer { - init(style: LayerDebugStyle) { - super.init() - zPosition = 1000 - bounds = CGRect(x: 0, y: 0, width: style.anchorWidth, height: style.anchorWidth) - backgroundColor = style.anchorColor - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -extension CALayer { - - @nonobjc - public func logLayerTree(withIndent: Int = 0) { - var string = "" - for _ in 0...withIndent { - string = string + " " - } - string = string + "|_" + String(describing: self) - LottieLogger.shared.info(string) - if let sublayers { - for sublayer in sublayers { - sublayer.logLayerTree(withIndent: withIndent + 1) - } - } - } - -} - -// MARK: - CompositionLayer + CustomLayerDebugging - -extension CompositionLayer: CustomLayerDebugging { - func layerForDebugging() -> CALayer { - contentsLayer - } -} - -extension CALayer { - - @nonobjc - func setDebuggingState(visible: Bool) { - var sublayers = sublayers - if let cust = self as? CustomLayerDebugging { - sublayers = cust.layerForDebugging().sublayers - } - - if let sublayers { - for i in 0.. LayerDebugStyle { - let anchorColor = CGColor.rgb(1, 0, 0) - let boundsColor = CGColor.rgb(1, 1, 0) - return LayerDebugStyle( - anchorColor: anchorColor, - boundsColor: boundsColor, - anchorWidth: 10, - boundsWidth: 2) - } - - static func topLayerStyle() -> LayerDebugStyle { - let anchorColor = CGColor.rgba(1, 0.5, 0, 0) - let boundsColor = CGColor.rgb(0, 1, 0) - - return LayerDebugStyle( - anchorColor: anchorColor, - boundsColor: boundsColor, - anchorWidth: 10, - boundsWidth: 2) - } - - static func nullLayerStyle() -> LayerDebugStyle { - let anchorColor = CGColor.rgba(0, 0, 1, 0) - let boundsColor = CGColor.rgb(0, 1, 0) - - return LayerDebugStyle( - anchorColor: anchorColor, - boundsColor: boundsColor, - anchorWidth: 10, - boundsWidth: 2) - } - - static func shapeLayerStyle() -> LayerDebugStyle { - let anchorColor = CGColor.rgba(0, 1, 0, 0) - let boundsColor = CGColor.rgb(0, 1, 0) - - return LayerDebugStyle( - anchorColor: anchorColor, - boundsColor: boundsColor, - anchorWidth: 10, - boundsWidth: 2) - } - - static func shapeRenderLayerStyle() -> LayerDebugStyle { - let anchorColor = CGColor.rgba(0, 1, 1, 0) - let boundsColor = CGColor.rgb(0, 1, 0) - - return LayerDebugStyle( - anchorColor: anchorColor, - boundsColor: boundsColor, - anchorWidth: 10, - boundsWidth: 2) - } -} - -extension [LayerModel] { - - var parents: [Int] { - var array = [Int]() - for layer in self { - if let parent = layer.parent { - array.append(parent) - } else { - array.append(-1) - } - } - return array - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Debugging/TestHelpers.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Debugging/TestHelpers.swift deleted file mode 100644 index cfe5d4813e7fb078d923392934609663e5cc9786..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Debugging/TestHelpers.swift +++ /dev/null @@ -1,10 +0,0 @@ -// Created by Cal Stephens on 1/28/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -enum TestHelpers { - /// Whether or not snapshot tests are currently running in a test target - static var snapshotTestsAreRunning = false - - /// Whether or not performance tests are currently running in a test target - static var performanceTestsAreRunning = false -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/AnimationKeypathExtension.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/AnimationKeypathExtension.swift deleted file mode 100644 index 669c8e600e19d678253d7583ea77dd1c3a5bd3f4..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/AnimationKeypathExtension.swift +++ /dev/null @@ -1,303 +0,0 @@ -// -// KeypathSearchableExtension.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -import QuartzCore - -extension KeypathSearchable { - - func animatorNodes(for keyPath: AnimationKeypath) -> [AnimatorNode]? { - // Make sure there is a current key path. - guard let currentKey = keyPath.currentKey else { return nil } - - // Now try popping the keypath for wildcard / child search - guard let nextKeypath = keyPath.popKey(keypathName) else { - // We may be on the final keypath. Check for match. - if - let node = self as? AnimatorNode, - currentKey.equalsKeypath(keypathName) - { - // This is the final keypath and matches self. Return.s - return [node] - } - /// Nope. Stop Search - return nil - } - - var results: [AnimatorNode] = [] - - if - let node = self as? AnimatorNode, - nextKeypath.currentKey == nil - { - // Keypath matched self and was the final keypath. - results.append(node) - } - - for childNode in childKeypaths { - // Check if the child has any nodes matching the next keypath. - if let foundNodes = childNode.animatorNodes(for: nextKeypath) { - results.append(contentsOf: foundNodes) - } - - // In this case the current key is fuzzy, and both child and self match the next keyname. Keep digging! - if - currentKey.keyPathType == .fuzzyWildcard, - let nextKeypath = keyPath.nextKeypath, - nextKeypath.equalsKeypath(childNode.keypathName), - let foundNodes = childNode.animatorNodes(for: keyPath) - { - results.append(contentsOf: foundNodes) - } - } - - guard results.count > 0 else { - return nil - } - - return results - } - - func nodeProperties(for keyPath: AnimationKeypath) -> [AnyNodeProperty]? { - guard let nextKeypath = keyPath.popKey(keypathName) else { - /// Nope. Stop Search - return nil - } - - /// Keypath matches in some way. Continue the search. - var results: [AnyNodeProperty] = [] - - /// Check if we have a property keypath yet - if - let propertyKey = nextKeypath.propertyKey, - let property = keypathProperties[propertyKey] - { - /// We found a property! - results.append(property) - } - - if nextKeypath.nextKeypath != nil { - /// Now check child keypaths. - for child in childKeypaths { - if let childProperties = child.nodeProperties(for: nextKeypath) { - results.append(contentsOf: childProperties) - } - } - } - - guard results.count > 0 else { - return nil - } - - return results - } - - func layer(for keyPath: AnimationKeypath) -> CALayer? { - if keyPath.nextKeypath == nil, let layerKey = keyPath.currentKey, layerKey.equalsKeypath(keypathName) { - /// We found our layer! - return keypathLayer - } - guard let nextKeypath = keyPath.popKey(keypathName) else { - /// Nope. Stop Search - return nil - } - - /// Now check child keypaths. - for child in childKeypaths { - if let layer = child.layer(for: nextKeypath) { - return layer - } - } - return nil - } - - /// Searches this layer's keypaths to find the keypath for the given layer - func keypath(for layer: CALayer) -> AnimationKeypath? { - let allKeypaths = layerKeypaths() - return allKeypaths[layer] - } - - /// Computes the list of animation keypaths that descend from this layer - func allKeypaths(for keyPath: AnimationKeypath? = nil) -> [String] { - var allKeypaths: [String] = [] - - let newKeypath: AnimationKeypath - if let previousKeypath = keyPath { - newKeypath = previousKeypath.appendingKey(keypathName) - } else { - newKeypath = AnimationKeypath(keys: [keypathName]) - } - - allKeypaths.append(newKeypath.fullPath) - - for key in keypathProperties.keys { - allKeypaths.append(newKeypath.appendingKey(key).fullPath) - } - - for child in childKeypaths { - allKeypaths.append(contentsOf: child.allKeypaths(for: newKeypath)) - } - - return allKeypaths - } - - /// Computes the list of animation keypaths that descend from this layer - func layerKeypaths(for keyPath: AnimationKeypath? = nil) -> [CALayer: AnimationKeypath] { - var allKeypaths: [CALayer: AnimationKeypath] = [:] - - let newKeypath: AnimationKeypath - if let previousKeypath = keyPath { - newKeypath = previousKeypath.appendingKey(keypathName) - } else { - newKeypath = AnimationKeypath(keys: [keypathName]) - } - - if let layer = self as? CALayer { - allKeypaths[layer] = newKeypath - } - - for child in childKeypaths { - for (layer, keypath) in child.layerKeypaths(for: newKeypath) { - allKeypaths[layer] = keypath - } - } - - return allKeypaths - } -} - -extension AnimationKeypath { - var currentKey: String? { - keys.first - } - - var nextKeypath: String? { - guard keys.count > 1 else { - return nil - } - return keys[1] - } - - var propertyKey: String? { - if nextKeypath == nil { - /// There are no more keypaths. This is a property key. - return currentKey - } - if keys.count == 2, currentKey?.keyPathType == .fuzzyWildcard { - /// The next keypath is the last and the current is a fuzzy key. - return nextKeypath - } - return nil - } - - var fullPath: String { - keys.joined(separator: ".") - } - - // Pops the top keypath from the stack if the keyname matches. - func popKey(_ keyname: String) -> AnimationKeypath? { - guard - let currentKey, - currentKey.equalsKeypath(keyname), - keys.count > 1 - else { - // Current key either doesnt match or we are on the last key. - return nil - } - - // Pop the keypath from the stack and return the new stack. - let newKeys: [String] - - if currentKey.keyPathType == .fuzzyWildcard { - /// Dont remove if current key is a fuzzy wildcard, and if the next keypath doesnt equal keypathname - if - let nextKeypath, - nextKeypath.equalsKeypath(keyname) - { - /// Remove next two keypaths. This keypath breaks the wildcard. - var oldKeys = keys - oldKeys.remove(at: 0) - oldKeys.remove(at: 0) - newKeys = oldKeys - } else { - newKeys = keys - } - } else { - var oldKeys = keys - oldKeys.remove(at: 0) - newKeys = oldKeys - } - - return AnimationKeypath(keys: newKeys) - } - - func appendingKey(_ key: String) -> AnimationKeypath { - var newKeys = keys - newKeys.append(key) - return AnimationKeypath(keys: newKeys) - } -} - -extension String { - var keyPathType: KeyType { - switch self { - case "*": - return .wildcard - case "**": - return .fuzzyWildcard - default: - return .specific - } - } - - func equalsKeypath(_ keyname: String) -> Bool { - if keyPathType == .wildcard || keyPathType == .fuzzyWildcard { - return true - } - if self == keyname { - return true - } - if let index = firstIndex(of: "*") { - // Wildcard search. - let prefix = String(prefix(upTo: index)) - let suffix = String(suffix(from: self.index(after: index))) - - if prefix.count > 0 { - // Match prefix. - if keyname.count < prefix.count { - return false - } - let testPrefix = String(keyname.prefix(upTo: keyname.index(keyname.startIndex, offsetBy: prefix.count))) - if testPrefix != prefix { - // Prefix doesnt match - return false - } - } - if suffix.count > 0 { - // Match suffix. - if keyname.count < suffix.count { - // Suffix doesnt match - return false - } - let index = keyname.index(keyname.endIndex, offsetBy: -suffix.count) - let testSuffix = String(keyname.suffix(from: index)) - if testSuffix != suffix { - return false - } - } - return true - } - return false - } -} - -// MARK: - KeyType - -enum KeyType { - case specific - case wildcard - case fuzzyWildcard -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/BlendMode+Filter.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/BlendMode+Filter.swift deleted file mode 100644 index ef93a39c25d84d12eca7cb32cae1cc786126e877..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/BlendMode+Filter.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// File.swift -// -// -// Created by Denis Koryttsev on 10.05.2022. -// - -extension BlendMode { - /// The Core Image filter name for this `BlendMode`, that can be applied to a `CALayer`'s `compositingFilter`. - /// Supported compositing filters are defined here: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/uid/TP30000136-SW71 - var filterName: String? { - switch self { - case .normal: return nil - case .multiply: return "multiplyBlendMode" - case .screen: return "screenBlendMode" - case .overlay: return "overlayBlendMode" - case .darken: return "darkenBlendMode" - case .lighten: return "lightenBlendMode" - case .colorDodge: return "colorDodgeBlendMode" - case .colorBurn: return "colorBurnBlendMode" - case .hardLight: return "hardLightBlendMode" - case .softLight: return "softLightBlendMode" - case .difference: return "differenceBlendMode" - case .exclusion: return "exclusionBlendMode" - case .hue: return "hueBlendMode" - case .saturation: return "saturationBlendMode" - case .color: return "colorBlendMode" - case .luminosity: return "luminosityBlendMode" - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/CGColor+RGB.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/CGColor+RGB.swift deleted file mode 100644 index 0b5720909ba4b03e597c6f8f9bc392a047dfe91b..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/CGColor+RGB.swift +++ /dev/null @@ -1,25 +0,0 @@ -// Created by Cal Stephens on 1/7/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import QuartzCore - -extension CGColor { - /// Initializes a `CGColor` using the given `RGB` values - static func rgb(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat) -> CGColor { - rgba(red, green, blue, 1.0) - } - - /// Initializes a `CGColor` using the given grayscale value - static func gray(_ gray: CGFloat) -> CGColor { - CGColor( - colorSpace: CGColorSpaceCreateDeviceGray(), - components: [gray, 1.0])! - } - - /// Initializes a `CGColor` using the given `RGBA` values - static func rgba(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat, _ alpha: CGFloat) -> CGColor { - CGColor( - colorSpace: LottieConfiguration.shared.colorSpace, - components: [red, green, blue, alpha])! - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/CGFloatExtensions.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/CGFloatExtensions.swift deleted file mode 100644 index 015a10ce45e97246cfd2d7086986dfd7eb764721..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/CGFloatExtensions.swift +++ /dev/null @@ -1,152 +0,0 @@ -// -// CGFloatExtensions.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/14/19. -// - -import Foundation -import QuartzCore - -extension CGFloat { - - // MARK: Internal - - var squared: CGFloat { - self * self - } - - var cubed: CGFloat { - self * self * self - } - - var cubicRoot: CGFloat { - CGFloat(pow(Double(self), 1.0 / 3.0)) - } - - func isInRangeOrEqual(_ from: CGFloat, _ to: CGFloat) -> Bool { - from <= self && self <= to - } - - func isInRange(_ from: CGFloat, _ to: CGFloat) -> Bool { - from < self && self < to - } - - func cubicBezierInterpolate(_ P0: CGPoint, _ P1: CGPoint, _ P2: CGPoint, _ P3: CGPoint) -> CGFloat { - var t: CGFloat - if self == P0.x { - // Handle corner cases explicitly to prevent rounding errors - t = 0 - } else if self == P3.x { - t = 1 - } else { - // Calculate t - let a = -P0.x + 3 * P1.x - 3 * P2.x + P3.x; - let b = 3 * P0.x - 6 * P1.x + 3 * P2.x; - let c = -3 * P0.x + 3 * P1.x; - let d = P0.x - self; - let tTemp = CGFloat.SolveCubic(a, b, c, d); - if tTemp == -1 { - return -1; - } - t = tTemp - } - - // Calculate y from t - return (1 - t).cubed * P0.y + 3 * t * (1 - t).squared * P1.y + 3 * t.squared * (1 - t) * P2.y + t.cubed * P3.y; - } - - func cubicBezier(_ t: CGFloat, _ c1: CGFloat, _ c2: CGFloat, _ end: CGFloat) -> CGFloat { - let t_ = (1.0 - t) - let tt_ = t_ * t_ - let ttt_ = t_ * t_ * t_ - let tt = t * t - let ttt = t * t * t - - return self * ttt_ - + 3.0 * c1 * tt_ * t - + 3.0 * c2 * t_ * tt - + end * ttt; - } - - // MARK: Fileprivate - - fileprivate static func SolveQuadratic(_ a: CGFloat, _ b: CGFloat, _ c: CGFloat) -> CGFloat { - var result = (-b + sqrt(b.squared - 4 * a * c)) / (2 * a); - guard !result.isInRangeOrEqual(0, 1) else { - return result - } - - result = (-b - sqrt(b.squared - 4 * a * c)) / (2 * a); - guard !result.isInRangeOrEqual(0, 1) else { - return result - } - - return -1; - } - - fileprivate static func SolveCubic(_ a: CGFloat, _ b: CGFloat, _ c: CGFloat, _ d: CGFloat) -> CGFloat { - if a == 0 { - return SolveQuadratic(b, c, d) - } - if d == 0 { - return 0 - } - let a = a - var b = b - var c = c - var d = d - b /= a - c /= a - d /= a - var q = (3.0 * c - b.squared) / 9.0 - let r = (-27.0 * d + b * (9.0 * c - 2.0 * b.squared)) / 54.0 - let disc = q.cubed + r.squared - let term1 = b / 3.0 - - if disc > 0 { - var s = r + sqrt(disc) - s = (s < 0) ? -((-s).cubicRoot) : s.cubicRoot - var t = r - sqrt(disc) - t = (t < 0) ? -((-t).cubicRoot) : t.cubicRoot - - let result = -term1 + s + t; - if result.isInRangeOrEqual(0, 1) { - return result - } - } else if disc == 0 { - let r13 = (r < 0) ? -((-r).cubicRoot) : r.cubicRoot; - - var result = -term1 + 2.0 * r13; - if result.isInRangeOrEqual(0, 1) { - return result - } - - result = -(r13 + term1); - if result.isInRangeOrEqual(0, 1) { - return result - } - - } else { - q = -q; - var dum1 = q * q * q; - dum1 = acos(r / sqrt(dum1)); - let r13 = 2.0 * sqrt(q); - - var result = -term1 + r13 * cos(dum1 / 3.0); - if result.isInRangeOrEqual(0, 1) { - return result - } - result = -term1 + r13 * cos((dum1 + 2.0 * .pi) / 3.0); - if result.isInRangeOrEqual(0, 1) { - return result - } - result = -term1 + r13 * cos((dum1 + 4.0 * .pi) / 3.0); - if result.isInRangeOrEqual(0, 1) { - return result - } - } - - return -1; - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/DataExtension.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/DataExtension.swift deleted file mode 100644 index 19b7d524d24592d1f5fa883725d38347e1365c94..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/DataExtension.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// DataExtension.swift -// Lottie -// -// Created by René Fouquet on 03.05.21. -// - -#if canImport(UIKit) -import UIKit -#elseif canImport(AppKit) -import AppKit -#endif - -extension Data { - - init(assetName: String, in bundle: Bundle) throws { - #if canImport(UIKit) - if let asset = NSDataAsset(name: assetName, bundle: bundle) { - self = asset.data - return - } else { - throw DotLottieError.assetNotFound(name: assetName, bundle: bundle) - } - #else - if #available(macOS 10.11, *) { - if let asset = NSDataAsset(name: assetName, bundle: bundle) { - self = asset.data - return - } else { - throw DotLottieError.assetNotFound(name: assetName, bundle: bundle) - } - } - throw DotLottieError.loadingFromAssetNotSupported - #endif - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/MathKit.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/MathKit.swift deleted file mode 100644 index e512cfa9aad7aacc71295a2227eb9c2fc191cd7e..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/MathKit.swift +++ /dev/null @@ -1,450 +0,0 @@ -// -// MathKit.swift -// UIToolBox -// -// Created by Brandon Withrow on 10/10/18. -// -// From https://github.com/buba447/UIToolBox - -import CoreGraphics -import Foundation - -extension Int { - var cgFloat: CGFloat { - CGFloat(self) - } -} - -extension Double { - var cgFloat: CGFloat { - CGFloat(self) - } -} - -// MARK: - CGFloat + Interpolatable - -extension CGFloat { - - func remap(fromLow: CGFloat, fromHigh: CGFloat, toLow: CGFloat, toHigh: CGFloat) -> CGFloat { - guard (fromHigh - fromLow) != 0 else { - // Would produce NAN - return 0 - } - return toLow + (self - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) - } - - /// Returns a value that is clamped between the two numbers - /// - /// 1. The order of arguments does not matter. - func clamp(_ a: CGFloat, _ b: CGFloat) -> CGFloat { - CGFloat(Double(self).clamp(Double(a), Double(b))) - } - - /// Returns the difference between the receiver and the given number. - /// - Parameter absolute: If *true* (Default) the returned value will always be positive. - func diff(_ a: CGFloat, absolute: Bool = true) -> CGFloat { - absolute ? abs(a - self) : a - self - } - - func toRadians() -> CGFloat { self * .pi / 180 } - func toDegrees() -> CGFloat { self * 180 / .pi } - -} - -// MARK: - Double - -extension Double { - - func remap(fromLow: Double, fromHigh: Double, toLow: Double, toHigh: Double) -> Double { - toLow + (self - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) - } - - /// Returns a value that is clamped between the two numbers - /// - /// 1. The order of arguments does not matter. - func clamp(_ a: Double, _ b: Double) -> Double { - let minValue = a <= b ? a : b - let maxValue = a <= b ? b : a - return max(min(self, maxValue), minValue) - } - -} - -extension CGRect { - - // MARK: Lifecycle - - /// Initializes a new CGRect with a center point and size. - init(center: CGPoint, size: CGSize) { - self.init( - x: center.x - (size.width * 0.5), - y: center.y - (size.height * 0.5), - width: size.width, - height: size.height) - } - - // MARK: Internal - - /// Returns the total area of the rect. - var area: CGFloat { - width * height - } - - /// The center point of the rect. Settable. - var center: CGPoint { - get { - CGPoint(x: midX, y: midY) - } - set { - origin = CGPoint( - x: newValue.x - (size.width * 0.5), - y: newValue.y - (size.height * 0.5)) - } - } - - /// The top left point of the rect. Settable. - var topLeft: CGPoint { - get { - CGPoint(x: minX, y: minY) - } - set { - origin = CGPoint( - x: newValue.x, - y: newValue.y) - } - } - - /// The bottom left point of the rect. Settable. - var bottomLeft: CGPoint { - get { - CGPoint(x: minX, y: maxY) - } - set { - origin = CGPoint( - x: newValue.x, - y: newValue.y - size.height) - } - } - - /// The top right point of the rect. Settable. - var topRight: CGPoint { - get { - CGPoint(x: maxX, y: minY) - } - set { - origin = CGPoint( - x: newValue.x - size.width, - y: newValue.y) - } - } - - /// The bottom right point of the rect. Settable. - var bottomRight: CGPoint { - get { - CGPoint(x: maxX, y: maxY) - } - set { - origin = CGPoint( - x: newValue.x - size.width, - y: newValue.y - size.height) - } - } - -} - -extension CGSize { - - /// Operator convenience to add sizes with + - static func +(left: CGSize, right: CGSize) -> CGSize { - left.add(right) - } - - /// Operator convenience to subtract sizes with - - static func -(left: CGSize, right: CGSize) -> CGSize { - left.subtract(right) - } - - /// Operator convenience to multiply sizes with * - static func *(left: CGSize, right: CGFloat) -> CGSize { - CGSize(width: left.width * right, height: left.height * right) - } - - /// Returns the scale float that will fit the receive inside of the given size. - func scaleThatFits(_ size: CGSize) -> CGFloat { - CGFloat.minimum(width / size.width, height / size.height) - } - - /// Adds receiver size to give size. - func add(_ size: CGSize) -> CGSize { - CGSize(width: width + size.width, height: height + size.height) - } - - /// Subtracts given size from receiver size. - func subtract(_ size: CGSize) -> CGSize { - CGSize(width: width - size.width, height: height - size.height) - } - - /// Multiplies receiver size by the given size. - func multiply(_ size: CGSize) -> CGSize { - CGSize(width: width * size.width, height: height * size.height) - } -} - -// MARK: - CGLine - -/// A struct that defines a line segment with two CGPoints -struct CGLine { - - // MARK: Lifecycle - - /// Initializes a line segment with start and end points - init(start: CGPoint, end: CGPoint) { - self.start = start - self.end = end - } - - // MARK: Internal - - /// The Start of the line segment. - var start: CGPoint - /// The End of the line segment. - var end: CGPoint - - /// The length of the line segment. - var length: CGFloat { - end.distanceTo(start) - } - - /// Returns a line segment that is normalized to a length of 1 - func normalize() -> CGLine { - let len = length - guard len > 0 else { - return self - } - let relativeEnd = end - start - let relativeVector = CGPoint(x: relativeEnd.x / len, y: relativeEnd.y / len) - let absoluteVector = relativeVector + start - return CGLine(start: start, end: absoluteVector) - } - - /// Trims a line segment to the given length - func trimmedToLength(_ toLength: CGFloat) -> CGLine { - let len = length - guard len > 0 else { - return self - } - let relativeEnd = end - start - let relativeVector = CGPoint(x: relativeEnd.x / len, y: relativeEnd.y / len) - let sizedVector = CGPoint(x: relativeVector.x * toLength, y: relativeVector.y * toLength) - let absoluteVector = sizedVector + start - return CGLine(start: start, end: absoluteVector) - } - - /// Flips a line vertically and horizontally from the start point. - func flipped() -> CGLine { - let relativeEnd = end - start - let flippedEnd = CGPoint(x: relativeEnd.x * -1, y: relativeEnd.y * -1) - return CGLine(start: start, end: flippedEnd + start) - } - - /// Move the line to the new start point. - func transpose(_ toPoint: CGPoint) -> CGLine { - let diff = toPoint - start - let newEnd = end + diff - return CGLine(start: toPoint, end: newEnd) - } - -} - -infix operator +| -infix operator +- - -extension CGPoint { - - /// Returns the length between the receiver and *CGPoint.zero* - var vectorLength: CGFloat { - distanceTo(.zero) - } - - var isZero: Bool { - x == 0 && y == 0 - } - - /// Operator convenience to divide points with / - static func / (lhs: CGPoint, rhs: CGFloat) -> CGPoint { - CGPoint(x: lhs.x / CGFloat(rhs), y: lhs.y / CGFloat(rhs)) - } - - /// Operator convenience to multiply points with * - static func * (lhs: CGPoint, rhs: CGFloat) -> CGPoint { - CGPoint(x: lhs.x * CGFloat(rhs), y: lhs.y * CGFloat(rhs)) - } - - /// Operator convenience to add points with + - static func +(left: CGPoint, right: CGPoint) -> CGPoint { - left.add(right) - } - - /// Operator convenience to subtract points with - - static func -(left: CGPoint, right: CGPoint) -> CGPoint { - left.subtract(right) - } - - static func +|(left: CGPoint, right: CGFloat) -> CGPoint { - CGPoint(x: left.x, y: left.y + right) - } - - static func +-(left: CGPoint, right: CGFloat) -> CGPoint { - CGPoint(x: left.x + right, y: left.y) - } - - /// Returns the distance between the receiver and the given point. - func distanceTo(_ a: CGPoint) -> CGFloat { - let xDist = a.x - x - let yDist = a.y - y - return CGFloat(sqrt((xDist * xDist) + (yDist * yDist))) - } - - func rounded(decimal: CGFloat) -> CGPoint { - CGPoint(x: round(decimal * x) / decimal, y: round(decimal * y) / decimal) - } - - func interpolate( - _ to: CGPoint, - outTangent: CGPoint, - inTangent: CGPoint, - amount: CGFloat, - maxIterations: Int = 3, - samples: Int = 20, - accuracy: CGFloat = 1) - -> CGPoint - { - if amount == 0 { - return self - } - if amount == 1 { - return to - } - - if - colinear(outTangent, inTangent) == true, - outTangent.colinear(inTangent, to) == true - { - return interpolate(to: to, amount: amount) - } - - let step = 1 / CGFloat(samples) - - var points: [(point: CGPoint, distance: CGFloat)] = [(point: self, distance: 0)] - var totalLength: CGFloat = 0 - - var previousPoint = self - var previousAmount = CGFloat(0) - - var closestPoint = 0 - - while previousAmount < 1 { - previousAmount = previousAmount + step - - if previousAmount < amount { - closestPoint = closestPoint + 1 - } - - let newPoint = pointOnPath(to, outTangent: outTangent, inTangent: inTangent, amount: previousAmount) - let distance = previousPoint.distanceTo(newPoint) - totalLength = totalLength + distance - points.append((point: newPoint, distance: totalLength)) - previousPoint = newPoint - } - - let accurateDistance = amount * totalLength - var point = points[closestPoint] - - var foundPoint = false - - var pointAmount = CGFloat(closestPoint) * step - var nextPointAmount: CGFloat = pointAmount + step - - var refineIterations = 0 - while foundPoint == false { - refineIterations = refineIterations + 1 - /// First see if the next point is still less than the projected length. - let nextPoint = points[min(closestPoint + 1, points.indices.last!)] - if nextPoint.distance < accurateDistance { - point = nextPoint - closestPoint = closestPoint + 1 - pointAmount = CGFloat(closestPoint) * step - nextPointAmount = pointAmount + step - if closestPoint == points.count { - foundPoint = true - } - continue - } - if accurateDistance < point.distance { - closestPoint = closestPoint - 1 - if closestPoint < 0 { - foundPoint = true - continue - } - point = points[closestPoint] - pointAmount = CGFloat(closestPoint) * step - nextPointAmount = pointAmount + step - continue - } - - /// Now we are certain the point is the closest point under the distance - let pointDiff = nextPoint.distance - point.distance - let proposedPointAmount = ((accurateDistance - point.distance) / pointDiff) - .remap(fromLow: 0, fromHigh: 1, toLow: pointAmount, toHigh: nextPointAmount) - - let newPoint = pointOnPath(to, outTangent: outTangent, inTangent: inTangent, amount: proposedPointAmount) - let newDistance = point.distance + point.point.distanceTo(newPoint) - pointAmount = proposedPointAmount - point = (point: newPoint, distance: newDistance) - if - accurateDistance - newDistance <= accuracy || - newDistance - accurateDistance <= accuracy - { - foundPoint = true - } - - if refineIterations == maxIterations { - foundPoint = true - } - } - return point.point - } - - func pointOnPath(_ to: CGPoint, outTangent: CGPoint, inTangent: CGPoint, amount: CGFloat) -> CGPoint { - let a = interpolate(to: outTangent, amount: amount) - let b = outTangent.interpolate(to: inTangent, amount: amount) - let c = inTangent.interpolate(to: to, amount: amount) - let d = a.interpolate(to: b, amount: amount) - let e = b.interpolate(to: c, amount: amount) - let f = d.interpolate(to: e, amount: amount) - return f - } - - func colinear(_ a: CGPoint, _ b: CGPoint) -> Bool { - let area = x * (a.y - b.y) + a.x * (b.y - y) + b.x * (y - a.y); - let accuracy: CGFloat = 0.05 - if area < accuracy, area > -accuracy { - return true - } - return false - } - - /// Subtracts the given point from the receiving point. - func subtract(_ point: CGPoint) -> CGPoint { - CGPoint( - x: x - point.x, - y: y - point.y) - } - - /// Adds the given point from the receiving point. - func add(_ point: CGPoint) -> CGPoint { - CGPoint( - x: x + point.x, - y: y + point.y) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/StringExtensions.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/StringExtensions.swift deleted file mode 100644 index 8d33cee2499b7598a4281cb795621b093270a696..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Extensions/StringExtensions.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// StringExtensions.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -import CoreGraphics -import Foundation - -extension String { - - var cgColor: CGColor { - let (red, green, blue) = hexColorComponents() - return .rgb(red, green, blue) - } - - var lottieColor: LottieColor { - let (red, green, blue) = hexColorComponents() - return .init(r: red, g: green, b: blue, a: 1.0) - } - - func hexColorComponents() -> (red: CGFloat, green: CGFloat, blue: CGFloat) { - var cString: String = trimmingCharacters(in: .whitespacesAndNewlines).uppercased() - - if cString.hasPrefix("#") { - cString.remove(at: cString.startIndex) - } - - if (cString.count) != 6 { - return (red: 0, green: 0, blue: 0) - } - - var rgbValue: UInt64 = 0 - Scanner(string: cString).scanHexInt64(&rgbValue) - - return ( - red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, - green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, - blue: CGFloat(rgbValue & 0x0000FF) / 255.0) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/AnimationContext.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/AnimationContext.swift deleted file mode 100644 index 8d6cba046c3bcbf8fdac192380a71b781386e197..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/AnimationContext.swift +++ /dev/null @@ -1,92 +0,0 @@ -// -// AnimationContext.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/1/19. -// - -import Foundation -import QuartzCore - -/// A completion block for animations. -/// - `true` is passed in if the animation completed playing. -/// - `false` is passed in if the animation was interrupted and did not complete playing. -public typealias LottieCompletionBlock = (_ completed: Bool) -> Void - -// MARK: - AnimationContext - -struct AnimationContext { - - init( - playFrom: AnimationFrameTime, - playTo: AnimationFrameTime, - closure: LottieCompletionBlock?) - { - self.playTo = playTo - self.playFrom = playFrom - self.closure = AnimationCompletionDelegate(completionBlock: closure) - } - - var playFrom: AnimationFrameTime - var playTo: AnimationFrameTime - var closure: AnimationCompletionDelegate - -} - -// MARK: Equatable - -extension AnimationContext: Equatable { - /// Whether or not the two given `AnimationContext`s are functionally equivalent - /// - This checks whether or not a completion handler was provided, - /// but does not check whether or not the two completion handlers are equivalent. - static func == (_ lhs: AnimationContext, _ rhs: AnimationContext) -> Bool { - lhs.playTo == rhs.playTo - && lhs.playFrom == rhs.playFrom - && (lhs.closure.completionBlock == nil) == (rhs.closure.completionBlock == nil) - } -} - -// MARK: - AnimationContextState - -enum AnimationContextState { - case playing - case cancelled - case complete -} - -// MARK: - AnimationCompletionDelegate - -class AnimationCompletionDelegate: NSObject, CAAnimationDelegate { - - // MARK: Lifecycle - - init(completionBlock: LottieCompletionBlock?) { - self.completionBlock = completionBlock - super.init() - } - - // MARK: Public - - public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { - guard ignoreDelegate == false else { return } - animationState = flag ? .complete : .cancelled - if let animationLayer, let key = animationKey { - animationLayer.removeAnimation(forKey: key) - if flag { - animationLayer.currentFrame = (anim as! CABasicAnimation).toValue as! CGFloat - } - } - if let completionBlock { - completionBlock(flag) - } - } - - // MARK: Internal - - var animationLayer: RootAnimationLayer? - var animationKey: String? - var ignoreDelegate = false - var animationState: AnimationContextState = .playing - - let completionBlock: LottieCompletionBlock? -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/AnyEquatable.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/AnyEquatable.swift deleted file mode 100644 index e695eb8cee6073e10145b5ae7d5ee84a1a373a30..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/AnyEquatable.swift +++ /dev/null @@ -1,22 +0,0 @@ -// Created by miguel_jimenez on 8/2/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -// MARK: - AnyEquatable - -struct AnyEquatable { - private let value: Any - private let equals: (Any) -> Bool - - init(_ value: T) { - self.value = value - equals = { $0 as? T == value } - } -} - -// MARK: Equatable - -extension AnyEquatable: Equatable { - static func ==(lhs: AnyEquatable, rhs: AnyEquatable) -> Bool { - lhs.equals(rhs.value) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/Binding+Map.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/Binding+Map.swift deleted file mode 100644 index 5dba75478ac625c97fd2da09f80b8578b9d5a80b..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/Binding+Map.swift +++ /dev/null @@ -1,20 +0,0 @@ -// Created by miguel_jimenez on 7/27/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension Binding { - - /// Helper to transform a `Binding` from one `Value` type to another. - func map(transform: @escaping (Value) -> Transformed) -> Binding { - .init { - transform(wrappedValue) - } set: { newValue in - guard let newValue = newValue as? Value else { return } - self.wrappedValue = newValue - } - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/View+ValueChanged.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/View+ValueChanged.swift deleted file mode 100644 index 68d6a86a35edf6a1fa86bc42ac3d3a198ce55706..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Helpers/View+ValueChanged.swift +++ /dev/null @@ -1,22 +0,0 @@ -// Created by miguel_jimenez on 7/26/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -#if canImport(Combine) && canImport(SwiftUI) -import Combine -import SwiftUI - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension View { - /// A backwards compatible wrapper for iOS 14 `onChange` - @ViewBuilder - func valueChanged(value: T, onChange: @escaping (T) -> Void) -> some View { - if #available(iOS 14.0, *, macOS 11.0, tvOS 14.0) { - self.onChange(of: value, perform: onChange) - } else { - onReceive(Just(value)) { value in - onChange(value) - } - } - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Interpolatable/InterpolatableExtensions.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Interpolatable/InterpolatableExtensions.swift deleted file mode 100644 index b390b56a5e4662b03a7fb5da0d0887072fcaf041..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Interpolatable/InterpolatableExtensions.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// InterpolatableExtensions.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/14/19. -// - -import CoreGraphics -import Foundation - -extension LottieColor { - - // MARK: Lifecycle - - /// Initialize a new color with Hue Saturation and Value - init(h: Double, s: Double, v: Double, a: Double) { - let i = floor(h * 6) - let f = h * 6 - i - let p = v * (1 - s); - let q = v * (1 - f * s) - let t = v * (1 - (1 - f) * s) - - switch i.truncatingRemainder(dividingBy: 6) { - case 0: - r = v - g = t - b = p - case 1: - r = q - g = v - b = p - case 2: - r = p - g = v - b = t - case 3: - r = p - g = q - b = v - case 4: - r = t - g = p - b = v - case 5: - r = v - g = p - b = q - default: - r = 0 - g = 0 - b = 0 - } - self.a = a - } - - init(y: Double, u: Double, v: Double, a: Double) { - // From https://www.fourcc.org/fccyvrgb.php - r = y + 1.403 * v - g = y - 0.344 * u - b = y + 1.770 * u - self.a = a - } - - // MARK: Internal - - /// Hue Saturation Value of the color. - var hsva: (h: Double, s: Double, v: Double, a: Double) { - let maxValue = max(r, g, b) - let minValue = min(r, g, b) - - var h: Double, s: Double, v: Double = maxValue - - let d = maxValue - minValue - s = maxValue == 0 ? 0 : d / maxValue; - - if maxValue == minValue { - h = 0; // achromatic - } else { - switch maxValue { - case r: h = (g - b) / d + (g < b ? 6 : 0) - case g: h = (b - r) / d + 2 - case b: h = (r - g) / d + 4 - default: h = maxValue - } - h = h / 6 - } - return (h: h, s: s, v: v, a: a) - } - - var yuv: (y: Double, u: Double, v: Double, a: Double) { - /// From https://www.fourcc.org/fccyvrgb.php - let y = 0.299 * r + 0.587 * g + 0.114 * b - let u = -0.14713 * r - 0.28886 * g + 0.436 * b - let v = 0.615 * r - 0.51499 * g - 0.10001 * b - return (y: y, u: u, v: v, a: a) - } - -} - -// MARK: - CurveVertex + Interpolatable - -extension CurveVertex: Interpolatable { - func interpolate(to: CurveVertex, amount: CGFloat) -> CurveVertex { - CurveVertex( - point: point.interpolate(to: to.point, amount: amount), - inTangent: inTangent.interpolate(to: to.inTangent, amount: amount), - outTangent: outTangent.interpolate(to: to.outTangent, amount: amount)) - } -} - -// MARK: - BezierPath + Interpolatable - -extension BezierPath: Interpolatable { - func interpolate(to: BezierPath, amount: CGFloat) -> BezierPath { - var newPath = BezierPath() - for i in 0.. TextDocument { - if amount == 1 { - return to - } - return self - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Interpolatable/KeyframeExtensions.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Interpolatable/KeyframeExtensions.swift deleted file mode 100644 index e6e0c1811ff54bbc9b8877d7f70bc02cb39e42e3..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Interpolatable/KeyframeExtensions.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// KeyframeExtensions.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/14/19. -// - -import CoreGraphics -import Foundation - -extension Keyframe where T: AnyInterpolatable { - func interpolate(to: Keyframe, progress: CGFloat) -> T { - value._interpolate( - to: to.value, - amount: progress, - spatialOutTangent: spatialOutTangent?.pointValue, - spatialInTangent: to.spatialInTangent?.pointValue) - } -} - -extension Keyframe { - /// Interpolates the keyTime into a value from 0-1 - func interpolatedProgress(_ to: Keyframe, keyTime: CGFloat) -> CGFloat { - let startTime = time - let endTime = to.time - if keyTime <= startTime { - return 0 - } - if endTime <= keyTime { - return 1 - } - - if isHold { - return 0 - } - - let outTanPoint = outTangent?.pointValue ?? .zero - let inTanPoint = to.inTangent?.pointValue ?? CGPoint(x: 1, y: 1) - var progress: CGFloat = keyTime.remap(fromLow: startTime, fromHigh: endTime, toLow: 0, toHigh: 1) - if !outTanPoint.isZero || !inTanPoint.equalTo(CGPoint(x: 1, y: 1)) { - /// Cubic interpolation - progress = progress.cubicBezierInterpolate(.zero, outTanPoint, inTanPoint, CGPoint(x: 1, y: 1)) - } - return progress - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Interpolatable/KeyframeInterpolator.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Interpolatable/KeyframeInterpolator.swift deleted file mode 100644 index 93ba7378ed105a578f439d5b592b58324bcf9ac9..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Interpolatable/KeyframeInterpolator.swift +++ /dev/null @@ -1,250 +0,0 @@ -// -// KeyframeInterpolator.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/15/19. -// - -import CoreGraphics -import Foundation - -// MARK: - KeyframeInterpolator - -/// A value provider that produces a value at Time from a group of keyframes -final class KeyframeInterpolator: ValueProvider where ValueType: AnyInterpolatable { - - // MARK: Lifecycle - - init(keyframes: ContiguousArray>) { - self.keyframes = keyframes - } - - // MARK: Internal - - let keyframes: ContiguousArray> - - var valueType: Any.Type { - ValueType.self - } - - var storage: ValueProviderStorage { - .closure { [self] frame in - // First set the keyframe span for the frame. - updateSpanIndices(frame: frame) - lastUpdatedFrame = frame - // If only one keyframe return its value - let progress: CGFloat - let value: ValueType - - if - let leading = leadingKeyframe, - let trailing = trailingKeyframe - { - /// We have leading and trailing keyframe. - progress = leading.interpolatedProgress(trailing, keyTime: frame) - value = leading.interpolate(to: trailing, progress: progress) - } else if let leading = leadingKeyframe { - progress = 0 - value = leading.value - } else if let trailing = trailingKeyframe { - progress = 1 - value = trailing.value - } else { - /// Satisfy the compiler. - progress = 0 - value = keyframes[0].value - } - return value - } - } - - /// Returns true to trigger a frame update for this interpolator. - /// - /// An interpolator will be asked if it needs to update every frame. - /// If the interpolator needs updating it will be asked to compute its value for - /// the given frame. - /// - /// Cases a keyframe should not be updated: - /// - If time is in span and leading keyframe is hold - /// - If time is after the last keyframe. - /// - If time is before the first keyframe - /// - /// Cases for updating a keyframe: - /// - If time is in the span, and is not a hold - /// - If time is outside of the span, and there are more keyframes - /// - If a value delegate is set - /// - If leading and trailing are both nil. - func hasUpdate(frame: CGFloat) -> Bool { - if lastUpdatedFrame == nil { - return true - } - - if - let leading = leadingKeyframe, - trailingKeyframe == nil, - leading.time < frame - { - /// Frame is after bounds of keyframes - return false - } - if - let trailing = trailingKeyframe, - leadingKeyframe == nil, - frame < trailing.time - { - /// Frame is before bounds of keyframes - return false - } - if - let leading = leadingKeyframe, - let trailing = trailingKeyframe, - leading.isHold, - leading.time < frame, - frame < trailing.time - { - return false - } - return true - } - - // MARK: Fileprivate - - fileprivate var lastUpdatedFrame: CGFloat? - - fileprivate var leadingIndex: Int? = nil - fileprivate var trailingIndex: Int? = nil - fileprivate var leadingKeyframe: Keyframe? = nil - fileprivate var trailingKeyframe: Keyframe? = nil - - /// Finds the appropriate Leading and Trailing keyframe index for the given time. - fileprivate func updateSpanIndices(frame: CGFloat) { - guard keyframes.count > 0 else { - leadingIndex = nil - trailingIndex = nil - leadingKeyframe = nil - trailingKeyframe = nil - return - } - - // This function searches through the array to find the span of two keyframes - // that contain the current time. - // - // We could use Array.first(where:) but that would search through the entire array - // each frame. - // Instead we track the last used index and search either forwards or - // backwards from there. This reduces the iterations and complexity from - // - // O(n), where n is the length of the sequence to - // O(n), where n is the number of items after or before the last used index. - // - - if keyframes.count == 1 { - /// Only one keyframe. Set it as first and move on. - leadingIndex = 0 - trailingIndex = nil - leadingKeyframe = keyframes[0] - trailingKeyframe = nil - return - } - - /// Sets the initial keyframes. This is often only needed for the first check. - if - leadingIndex == nil, - trailingIndex == nil - { - if frame < keyframes[0].time { - /// Time is before the first keyframe. Set it as the trailing. - trailingIndex = 0 - } else { - /// Time is after the first keyframe. Set the keyframe and the trailing. - leadingIndex = 0 - trailingIndex = 1 - } - } - - if - let currentTrailing = trailingIndex, - keyframes[currentTrailing].time <= frame - { - /// Time is after the current span. Iterate forward. - var newLeading = currentTrailing - var keyframeFound = false - while !keyframeFound { - leadingIndex = newLeading - trailingIndex = keyframes.validIndex(newLeading + 1) - - guard let trailing = trailingIndex else { - /// We have reached the end of our keyframes. Time is after the last keyframe. - keyframeFound = true - continue - } - if frame < keyframes[trailing].time { - /// Keyframe in current span. - keyframeFound = true - continue - } - /// Advance the array. - newLeading = trailing - } - - } else if - let currentLeading = leadingIndex, - frame < keyframes[currentLeading].time - { - /// Time is before the current span. Iterate backwards - var newTrailing = currentLeading - - var keyframeFound = false - while !keyframeFound { - leadingIndex = keyframes.validIndex(newTrailing - 1) - trailingIndex = newTrailing - - guard let leading = leadingIndex else { - /// We have reached the end of our keyframes. Time is after the last keyframe. - keyframeFound = true - continue - } - if keyframes[leading].time <= frame { - /// Keyframe in current span. - keyframeFound = true - continue - } - /// Step back - newTrailing = leading - } - } - if let keyFrame = leadingIndex { - leadingKeyframe = keyframes[keyFrame] - } else { - leadingKeyframe = nil - } - - if let keyFrame = trailingIndex { - trailingKeyframe = keyframes[keyFrame] - } else { - trailingKeyframe = nil - } - } -} - -extension Array { - - fileprivate func validIndex(_ index: Int) -> Int? { - if 0 <= index, index < endIndex { - return index - } - return nil - } - -} - -extension ContiguousArray { - - fileprivate func validIndex(_ index: Int) -> Int? { - if 0 <= index, index < endIndex { - return index - } - return nil - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/LottieAnimationSource.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/LottieAnimationSource.swift deleted file mode 100644 index 167483485bab8b946ffbb66a1bd0bf9db798d6ae..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/LottieAnimationSource.swift +++ /dev/null @@ -1,51 +0,0 @@ -// Created by Cal Stephens on 7/26/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -// MARK: - LottieAnimationSource - -/// A data source for a Lottie animation. -/// Either a `LottieAnimation` loaded from a `.json` file, -/// or a `DotLottieFile` loaded from a `.lottie` file. -public enum LottieAnimationSource: Sendable { - /// A `LottieAnimation` loaded from a `.json` file - case lottieAnimation(LottieAnimation) - - /// A `DotLottieFile` loaded from a `.lottie` file - case dotLottieFile(DotLottieFile) -} - -extension LottieAnimationSource { - /// The default animation displayed by this data source - var animation: LottieAnimation? { - switch self { - case .lottieAnimation(let animation): - return animation - case .dotLottieFile: - return dotLottieAnimation?.animation - } - } - - /// The `DotLottieFile.Animation`, if this is a dotLottie animation - var dotLottieAnimation: DotLottieFile.Animation? { - switch self { - case .lottieAnimation: - return nil - case .dotLottieFile(let dotLottieFile): - return dotLottieFile.animation() - } - } -} - -extension LottieAnimation { - /// This animation represented as a `LottieAnimationSource` - public var animationSource: LottieAnimationSource { - .lottieAnimation(self) - } -} - -extension DotLottieFile { - /// This animation represented as a `LottieAnimationSource` - public var animationSource: LottieAnimationSource { - .dotLottieFile(self) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/BezierPath.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/BezierPath.swift deleted file mode 100644 index 54a509cf8d65cc078e8dd97b8a7378c9cd39c057..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/BezierPath.swift +++ /dev/null @@ -1,486 +0,0 @@ -// -// Shape.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/8/19. -// - -import CoreGraphics - -// MARK: - BezierPath - -/// A container that holds instructions for creating a single, unbroken Bezier Path. -struct BezierPath { - - // MARK: Lifecycle - - /// Initializes a new Bezier Path. - init(startPoint: CurveVertex) { - elements = [PathElement(vertex: startPoint)] - length = 0 - closed = false - } - - init() { - elements = [] - length = 0 - closed = false - } - - // MARK: Internal - - /// The elements of the path - private(set) var elements: [PathElement] - - /// If the path is closed or not. - private(set) var closed: Bool - - /// The total length of the path. - private(set) var length: CGFloat - - mutating func moveToStartPoint(_ vertex: CurveVertex) { - elements = [PathElement(vertex: vertex)] - length = 0 - } - - mutating func addVertex(_ vertex: CurveVertex) { - guard let previous = elements.last else { - addElement(PathElement(vertex: vertex)) - return - } - addElement(previous.pathElementTo(vertex)) - } - - mutating func addCurve(toPoint: CGPoint, outTangent: CGPoint, inTangent: CGPoint) { - guard let previous = elements.last else { return } - let newVertex = CurveVertex(inTangent, toPoint, toPoint) - updateVertex( - CurveVertex(previous.vertex.inTangent, previous.vertex.point, outTangent), - atIndex: elements.endIndex - 1, - remeasure: false) - addVertex(newVertex) - } - - mutating func addLine(toPoint: CGPoint) { - guard let previous = elements.last else { return } - let newVertex = CurveVertex(point: toPoint, inTangentRelative: .zero, outTangentRelative: .zero) - updateVertex( - CurveVertex(previous.vertex.inTangent, previous.vertex.point, previous.vertex.point), - atIndex: elements.endIndex - 1, - remeasure: false) - addVertex(newVertex) - } - - mutating func close() { - closed = true - } - - mutating func addElement(_ pathElement: PathElement) { - elements.append(pathElement) - length = length + pathElement.length - } - - mutating func updateVertex(_ vertex: CurveVertex, atIndex: Int, remeasure: Bool) { - if remeasure { - var newElement: PathElement - if atIndex > 0 { - let previousElement = elements[atIndex - 1] - newElement = previousElement.pathElementTo(vertex) - } else { - newElement = PathElement(vertex: vertex) - } - elements[atIndex] = newElement - - if atIndex + 1 < elements.count { - let nextElement = elements[atIndex + 1] - elements[atIndex + 1] = newElement.pathElementTo(nextElement.vertex) - } - - } else { - let oldElement = elements[atIndex] - elements[atIndex] = oldElement.updateVertex(newVertex: vertex) - } - } - - /// Trims a path fromLength toLength with an offset. - /// - /// Length and offset are defined in the length coordinate space. - /// If any argument is outside the range of this path, then it will be looped over the path from finish to start. - /// - /// Cutting the curve when fromLength is less than toLength - /// x x x x - /// ~~~~~~~~~~~~~~~ooooooooooooooooooooooooooooooooooooooooooooooooo------------------- - /// |Offset |fromLength toLength| | - /// - /// Cutting the curve when from Length is greater than toLength - /// x x x x x - /// oooooooooooooooooo--------------------~~~~~~~~~~~~~~~~ooooooooooooooooooooooooooooo - /// | toLength| |Offset |fromLength | - /// - func trim(fromLength: CGFloat, toLength: CGFloat, offsetLength: CGFloat) -> [BezierPath] { - guard elements.count > 1 else { - return [] - } - - if fromLength == toLength { - return [] - } - - /// Normalize lengths to the curve length. - var start = (fromLength + offsetLength).truncatingRemainder(dividingBy: length) - var end = (toLength + offsetLength).truncatingRemainder(dividingBy: length) - - if start < 0 { - start = length + start - } - - if end < 0 { - end = length + end - } - - if start == length { - start = 0 - } - if end == 0 { - end = length - } - - if - start == 0 && end == length || - start == end || - start == length && end == 0 - { - /// The trim encompasses the entire path. Return. - return [self] - } - - if start > end { - // Start is greater than end. Two paths are returned. - return trimPathAtLengths(positions: [(start: 0, end: end), (start: start, end: length)]) - } - - return trimPathAtLengths(positions: [(start: start, end: end)]) - } - - // MARK: Private - - private func trimPathAtLengths(positions: [(start: CGFloat, end: CGFloat)]) -> [BezierPath] { - guard positions.count > 0 else { - return [] - } - var remainingPositions = positions - - var trim = remainingPositions.remove(at: 0) - - var paths = [BezierPath]() - - var runningLength: CGFloat = 0 - var finishedTrimming = false - var pathElements = elements - - var currentPath = BezierPath() - var i = 0 - - while !finishedTrimming { - if pathElements.count <= i { - /// Do this for rounding errors - paths.append(currentPath) - finishedTrimming = true - continue - } - /// Loop through and add elements within start->end range. - /// Get current element - let element = pathElements[i] - - /// Calculate new running length. - let newLength = runningLength + element.length - - if newLength < trim.start { - /// Element is not included in the trim, continue. - runningLength = newLength - i = i + 1 - /// Increment index, we are done with this element. - continue - } - - if newLength == trim.start { - /// Current element IS the start element. - /// For start we want to add a zero length element. - currentPath.moveToStartPoint(element.vertex) - runningLength = newLength - i = i + 1 - /// Increment index, we are done with this element. - continue - } - - if runningLength < trim.start, trim.start < newLength, currentPath.elements.count == 0 { - /// The start of the trim is between this element and the previous, trim. - /// Get previous element. - let previousElement = pathElements[i - 1] - /// Trim it - let trimLength = trim.start - runningLength - let trimResults = element.splitElementAtPosition(fromElement: previousElement, atLength: trimLength) - /// Add the right span start. - currentPath.moveToStartPoint(trimResults.rightSpan.start.vertex) - - pathElements[i] = trimResults.rightSpan.end - pathElements[i - 1] = trimResults.rightSpan.start - runningLength = runningLength + trimResults.leftSpan.end.length - /// Dont increment index or the current length, the end of this path can be within this span. - continue - } - - if trim.start < newLength, newLength < trim.end { - /// Element lies within the trim span. - currentPath.addElement(element) - runningLength = newLength - i = i + 1 - continue - } - - if newLength == trim.end { - /// Element is the end element. - /// The element could have a new length if it's added right after the start node. - currentPath.addElement(element) - /// We are done with this span. - runningLength = newLength - i = i + 1 - /// Allow the path to be finalized. - /// Fall through to finalize path and move to next position - } - - if runningLength < trim.end, trim.end < newLength { - /// New element must be cut for end. - /// Get previous element. - let previousElement = pathElements[i - 1] - /// Trim it - let trimLength = trim.end - runningLength - let trimResults = element.splitElementAtPosition(fromElement: previousElement, atLength: trimLength) - /// Add the left span end. - - currentPath.updateVertex(trimResults.leftSpan.start.vertex, atIndex: currentPath.elements.count - 1, remeasure: false) - currentPath.addElement(trimResults.leftSpan.end) - - pathElements[i] = trimResults.rightSpan.end - pathElements[i - 1] = trimResults.rightSpan.start - runningLength = runningLength + trimResults.leftSpan.end.length - /// Dont increment index or the current length, the start of the next path can be within this span. - /// We are done with this span. - /// Allow the path to be finalized. - /// Fall through to finalize path and move to next position - } - - paths.append(currentPath) - currentPath = BezierPath() - if remainingPositions.count > 0 { - trim = remainingPositions.remove(at: 0) - } else { - finishedTrimming = true - } - } - return paths - } - -} - -// MARK: Codable - -extension BezierPath: Codable { - - // MARK: Lifecycle - - init(from decoder: Decoder) throws { - let container: KeyedDecodingContainer - - if let keyedContainer = try? decoder.container(keyedBy: BezierPath.CodingKeys.self) { - container = keyedContainer - } else { - var unkeyedContainer = try decoder.unkeyedContainer() - container = try unkeyedContainer.nestedContainer(keyedBy: BezierPath.CodingKeys.self) - } - - closed = try container.decodeIfPresent(Bool.self, forKey: .closed) ?? true - - var vertexContainer = try container.nestedUnkeyedContainer(forKey: .vertices) - var inPointsContainer = try container.nestedUnkeyedContainer(forKey: .inPoints) - var outPointsContainer = try container.nestedUnkeyedContainer(forKey: .outPoints) - - guard vertexContainer.count == inPointsContainer.count, inPointsContainer.count == outPointsContainer.count else { - /// Will throw an error if vertex, inpoints, and outpoints are not the same length. - /// This error is to be expected. - throw DecodingError.dataCorruptedError( - forKey: CodingKeys.vertices, - in: container, - debugDescription: "Vertex data does not match In Tangents and Out Tangents") - } - - guard let count = vertexContainer.count, count > 0 else { - length = 0 - elements = [] - return - } - - var decodedElements = [PathElement]() - - /// Create first point - let firstVertex = CurveVertex( - point: try vertexContainer.decode(CGPoint.self), - inTangentRelative: try inPointsContainer.decode(CGPoint.self), - outTangentRelative: try outPointsContainer.decode(CGPoint.self)) - var previousElement = PathElement(vertex: firstVertex) - decodedElements.append(previousElement) - - var totalLength: CGFloat = 0 - while !vertexContainer.isAtEnd { - /// Get the next vertex data. - let vertex = CurveVertex( - point: try vertexContainer.decode(CGPoint.self), - inTangentRelative: try inPointsContainer.decode(CGPoint.self), - outTangentRelative: try outPointsContainer.decode(CGPoint.self)) - let pathElement = previousElement.pathElementTo(vertex) - decodedElements.append(pathElement) - previousElement = pathElement - totalLength = totalLength + pathElement.length - } - if closed { - let closeElement = previousElement.pathElementTo(firstVertex) - decodedElements.append(closeElement) - totalLength = totalLength + closeElement.length - } - length = totalLength - elements = decodedElements - } - - // MARK: Internal - - /// The BezierPath container is encoded and decoded from the JSON format - /// that defines points for a lottie animation. - /// - /// { - /// "c" = Bool - /// "i" = [[Double]], - /// "o" = [[Double]], - /// "v" = [[Double]] - /// } - /// - - enum CodingKeys: String, CodingKey { - case closed = "c" - case inPoints = "i" - case outPoints = "o" - case vertices = "v" - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: BezierPath.CodingKeys.self) - try container.encode(closed, forKey: .closed) - - var vertexContainer = container.nestedUnkeyedContainer(forKey: .vertices) - var inPointsContainer = container.nestedUnkeyedContainer(forKey: .inPoints) - var outPointsContainer = container.nestedUnkeyedContainer(forKey: .outPoints) - - /// If closed path, ignore the final element. - let finalIndex = closed ? elements.endIndex - 1 : elements.endIndex - for i in 0.. 0 else { - length = 0 - elements = [] - return - } - - var decodedElements = [PathElement]() - let firstVertexDictionary = vertexDictionaries.removeFirst() - let firstInPointsDictionary = inPointsDictionaries.removeFirst() - let firstOutPointsDictionary = outPointsDictionaries.removeFirst() - let firstVertex = CurveVertex( - point: try CGPoint(value: firstVertexDictionary), - inTangentRelative: try CGPoint(value: firstInPointsDictionary), - outTangentRelative: try CGPoint(value: firstOutPointsDictionary)) - var previousElement = PathElement(vertex: firstVertex) - decodedElements.append(previousElement) - - var totalLength: CGFloat = 0 - while vertexDictionaries.count > 0 { - let vertexDictionary = vertexDictionaries.removeFirst() - let inPointsDictionary = inPointsDictionaries.removeFirst() - let outPointsDictionary = outPointsDictionaries.removeFirst() - let vertex = CurveVertex( - point: try CGPoint(value: vertexDictionary), - inTangentRelative: try CGPoint(value: inPointsDictionary), - outTangentRelative: try CGPoint(value: outPointsDictionary)) - let pathElement = previousElement.pathElementTo(vertex) - decodedElements.append(pathElement) - previousElement = pathElement - totalLength = totalLength + pathElement.length - } - if closed { - let closeElement = previousElement.pathElementTo(firstVertex) - decodedElements.append(closeElement) - totalLength = totalLength + closeElement.length - } - - length = totalLength - elements = decodedElements - } - -} - -extension BezierPath { - - func cgPath() -> CGPath { - let cgPath = CGMutablePath() - - var previousElement: PathElement? - for element in elements { - if let previous = previousElement { - if previous.vertex.outTangentRelative.isZero, element.vertex.inTangentRelative.isZero { - cgPath.addLine(to: element.vertex.point) - } else { - cgPath.addCurve(to: element.vertex.point, control1: previous.vertex.outTangent, control2: element.vertex.inTangent) - } - } else { - cgPath.move(to: element.vertex.point) - } - previousElement = element - } - if closed { - cgPath.closeSubpath() - } - return cgPath - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/BezierPathRoundExtension.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/BezierPathRoundExtension.swift deleted file mode 100644 index 01c5d5ee6c7d7278f1397a28cecbf12e3df790ba..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/BezierPathRoundExtension.swift +++ /dev/null @@ -1,158 +0,0 @@ -// -// BezierPathRoundExtension.swift -// Lottie -// -// Created by Duolingo on 11/1/22. -// - -import CoreGraphics -import Foundation - -// Adapted to Swift from lottie-web & lottie-android: - -// Rounded corner algorithm: -// Iterate through each vertex. -// If a vertex is a sharp corner, it rounds it. -// If a vertex has control points, it is already rounded, so it does nothing. -// -// To round a vertex: -// Split the vertex into two. -// Move vertex 1 directly towards the previous vertex. -// Set vertex 1's in control point to itself so it is not rounded on that side. -// Extend vertex 1's out control point towards the original vertex. -// -// Repeat for vertex 2: -// Move vertex 2 directly towards the next vertex. -// Set vertex 2's out point to itself so it is not rounded on that side. -// Extend vertex 2's in control point towards the original vertex. -// -// The distance that the vertices and control points are moved are relative to the -// shape's vertex distances and the roundedness set in the animation. - -extension CompoundBezierPath { - // Round corners of a compound bezier - func roundCorners(radius: CGFloat) -> CompoundBezierPath { - var newPaths = [BezierPath]() - for path in paths { - newPaths.append( - path.roundCorners(radius: radius)) - } - - return CompoundBezierPath(paths: newPaths) - } -} - -extension BezierPath { - // Computes a new `BezierPath` with each corner rounded based on the given `radius` - func roundCorners(radius: CGFloat) -> BezierPath { - var newPath = BezierPath() - var uniquePath = BezierPath() - - var currentVertex: CurveVertex - var closestVertex: CurveVertex - var distance: CGFloat - var newPosPerc: CGFloat - var closestIndex: Int - - var iX: CGFloat - var iY: CGFloat - var vX: CGFloat - var vY: CGFloat - var oX: CGFloat - var oY: CGFloat - - var startIndex = 0 - - let TANGENT_LENGTH = 0.5519 - - // If start and end are the same we close the path - if - elements[0].vertex.point == elements[elements.count - 1].vertex.point, - elements[0].vertex.inTangent == elements[elements.count - 1].vertex.inTangent, - elements[0].vertex.outTangent == elements[elements.count - 1].vertex.outTangent - { - startIndex = 1 - newPath.close() - } - - guard elements.count - startIndex > 1 else { - return self - } - - for i in startIndex.. 1 - { - self.init(x: array[0], y: array[1]) - } else { - throw InitializableError.invalidInput() - } - } - - // MARK: Private - - private enum CodingKeys: String { - case x - case y - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/ColorExtension.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/ColorExtension.swift deleted file mode 100644 index 286f0d93473620a4e3f140ff573680b6b98bcf65..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/ColorExtension.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// LottieColor.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/14/19. -// - -import CoreGraphics - -// MARK: - LottieColor + Codable - -extension LottieColor: Codable { - - // MARK: Lifecycle - - public init(from decoder: Decoder) throws { - var container = try decoder.unkeyedContainer() - - var r1: Double - if !container.isAtEnd { - r1 = try container.decode(Double.self) - } else { - r1 = 0 - } - - var g1: Double - if !container.isAtEnd { - g1 = try container.decode(Double.self) - } else { - g1 = 0 - } - - var b1: Double - if !container.isAtEnd { - b1 = try container.decode(Double.self) - } else { - b1 = 0 - } - - if r1 > 1, g1 > 1, b1 > 1 { - r1 = r1 / 255 - g1 = g1 / 255 - b1 = b1 / 255 - } - r = r1 - g = g1 - b = b1 - - // The Lottie JSON schema supports alpha values in theory, as the fourth value in this array. - // We intentionally do not support this, though, for consistency with Lottie on other platforms. - a = 1 - } - - // MARK: Public - - public func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - try container.encode(r) - try container.encode(g) - try container.encode(b) - try container.encode(a) - } - -} - -// MARK: - LottieColor + AnyInitializable - -extension LottieColor: AnyInitializable { - - init(value: Any) throws { - guard var array = value as? [Double] else { - throw InitializableError.invalidInput() - } - var r: Double = array.count > 0 ? array.removeFirst() : 0 - var g: Double = array.count > 0 ? array.removeFirst() : 0 - var b: Double = array.count > 0 ? array.removeFirst() : 0 - if r > 1, g > 1, b > 1 { - r /= 255 - g /= 255 - b /= 255 - } - self.r = r - self.g = g - self.b = b - - // The Lottie JSON schema supports alpha values in theory, as the fourth value in this array. - // We intentionally do not support this, though, for consistency with Lottie on other platforms. - a = 1 - } - -} - -extension LottieColor { - static var clearColor: CGColor { - .rgba(0, 0, 0, 0) - } - - var cgColorValue: CGColor { - .rgba(CGFloat(r), CGFloat(g), CGFloat(b), CGFloat(a)) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/CompoundBezierPath.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/CompoundBezierPath.swift deleted file mode 100644 index 14e465d66504959a0a0922dddfcd69a0d2cd63fe..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/CompoundBezierPath.swift +++ /dev/null @@ -1,167 +0,0 @@ -// -// CompoundBezierPath.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/14/19. -// - -import CoreGraphics -import Foundation - -/// A collection of BezierPath objects that can be trimmed and added. -/// -struct CompoundBezierPath { - - // MARK: Lifecycle - - init() { - paths = [] - length = 0 - } - - init(path: BezierPath) { - paths = [path] - length = path.length - } - - init(paths: [BezierPath], length: CGFloat) { - self.paths = paths - self.length = length - } - - init(paths: [BezierPath]) { - self.paths = paths - var l: CGFloat = 0 - for path in paths { - l = l + path.length - } - length = l - } - - // MARK: Internal - - let paths: [BezierPath] - - let length: CGFloat - - func addPath(path: BezierPath) -> CompoundBezierPath { - var newPaths = paths - newPaths.append(path) - return CompoundBezierPath(paths: newPaths, length: length + path.length) - } - - func combine(_ compoundBezier: CompoundBezierPath) -> CompoundBezierPath { - var newPaths = paths - newPaths.append(contentsOf: compoundBezier.paths) - return CompoundBezierPath(paths: newPaths, length: length + compoundBezier.length) - } - - func trim(fromPosition: CGFloat, toPosition: CGFloat, offset: CGFloat, trimSimultaneously: Bool) -> CompoundBezierPath { - if fromPosition == toPosition { - return CompoundBezierPath() - } - - if trimSimultaneously { - /// Trim each path individually. - var newPaths = [BezierPath]() - for path in paths { - newPaths.append(contentsOf: path.trim( - fromLength: fromPosition * path.length, - toLength: toPosition * path.length, - offsetLength: offset * path.length)) - } - return CompoundBezierPath(paths: newPaths) - } - - /// Normalize lengths to the curve length. - var startPosition = (fromPosition + offset).truncatingRemainder(dividingBy: 1) - var endPosition = (toPosition + offset).truncatingRemainder(dividingBy: 1) - - if startPosition < 0 { - startPosition = 1 + startPosition - } - - if endPosition < 0 { - endPosition = 1 + endPosition - } - - if startPosition == 1 { - startPosition = 0 - } - if endPosition == 0 { - endPosition = 1 - } - - if - startPosition == 0 && endPosition == 1 || - startPosition == endPosition || - startPosition == 1 && endPosition == 0 - { - /// The trim encompasses the entire path. Return. - return self - } - - var positions: [(start: CGFloat, end: CGFloat)] - if endPosition < startPosition { - positions = [ - (start: 0, end: endPosition * length), - (start: startPosition * length, end: length), - ] - } else { - positions = [(start: startPosition * length, end: endPosition * length)] - } - - var compoundPath = CompoundBezierPath() - var trim = positions.remove(at: 0) - var pathStartPosition: CGFloat = 0 - - var finishedTrimming = false - var i = 0 - - while !finishedTrimming { - if paths.count <= i { - /// Rounding errors - finishedTrimming = true - continue - } - let path = paths[i] - - let pathEndPosition = pathStartPosition + path.length - - if pathEndPosition < trim.start { - /// Path is not included in the trim, continue. - pathStartPosition = pathEndPosition - i = i + 1 - continue - - } else if trim.start <= pathStartPosition, pathEndPosition <= trim.end { - /// Full Path is inside of trim. Add full path. - compoundPath = compoundPath.addPath(path: path) - } else { - if - let trimPath = path.trim( - fromLength: trim.start > pathStartPosition ? (trim.start - pathStartPosition) : 0, - toLength: trim.end < pathEndPosition ? (trim.end - pathStartPosition) : path.length, - offsetLength: 0).first - { - compoundPath = compoundPath.addPath(path: trimPath) - } - } - - if trim.end <= pathEndPosition { - /// We are done with the current trim. - /// Advance trim but remain on the same path in case the next trim overlaps it. - if positions.count > 0 { - trim = positions.remove(at: 0) - } else { - finishedTrimming = true - } - } else { - pathStartPosition = pathEndPosition - i = i + 1 - } - } - return compoundPath - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/CurveVertex.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/CurveVertex.swift deleted file mode 100644 index 32afadb0a0676212465e77b2866f371ceff34728..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/CurveVertex.swift +++ /dev/null @@ -1,184 +0,0 @@ -// -// CurveVertex.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/11/19. -// - -import CoreGraphics -import Foundation - -/// A single vertex with an in and out tangent -struct CurveVertex { - - // MARK: Lifecycle - - /// Initializes a curve point with absolute values - init(_ inTangent: CGPoint, _ point: CGPoint, _ outTangent: CGPoint) { - self.point = point - self.inTangent = inTangent - self.outTangent = outTangent - } - - /// Initializes a curve point with relative values - init(point: CGPoint, inTangentRelative: CGPoint, outTangentRelative: CGPoint) { - self.point = point - inTangent = point.add(inTangentRelative) - outTangent = point.add(outTangentRelative) - } - - /// Initializes a curve point with absolute values - init(point: CGPoint, inTangent: CGPoint, outTangent: CGPoint) { - self.point = point - self.inTangent = inTangent - self.outTangent = outTangent - } - - // MARK: Internal - - let point: CGPoint - - let inTangent: CGPoint - let outTangent: CGPoint - - var inTangentRelative: CGPoint { - inTangent.subtract(point) - } - - var outTangentRelative: CGPoint { - outTangent.subtract(point) - } - - func reversed() -> CurveVertex { - CurveVertex(point: point, inTangent: outTangent, outTangent: inTangent) - } - - func translated(_ translation: CGPoint) -> CurveVertex { - CurveVertex(point: point + translation, inTangent: inTangent + translation, outTangent: outTangent + translation) - } - - /// Trims a path defined by two Vertices at a specific position, from 0 to 1 - /// - /// The path can be visualized below. - /// - /// F is fromVertex. - /// V is the vertex of the receiver. - /// P is the position from 0-1. - /// O is the outTangent of fromVertex. - /// F====O=========P=======I====V - /// - /// After trimming the curve can be visualized below. - /// - /// S is the returned Start vertex. - /// E is the returned End vertex. - /// T is the trim point. - /// TI and TO are the new tangents for the trimPoint - /// NO and NI are the new tangents for the startPoint and endPoints - /// S==NO=========TI==T==TO=======NI==E - func splitCurve(toVertex: CurveVertex, position: CGFloat) -> - (start: CurveVertex, trimPoint: CurveVertex, end: CurveVertex) - { - /// If position is less than or equal to 0, trim at start. - if position <= 0 { - return ( - start: CurveVertex(point: point, inTangentRelative: inTangentRelative, outTangentRelative: .zero), - trimPoint: CurveVertex(point: point, inTangentRelative: .zero, outTangentRelative: outTangentRelative), - end: toVertex) - } - - /// If position is greater than or equal to 1, trim at end. - if position >= 1 { - return ( - start: self, - trimPoint: CurveVertex( - point: toVertex.point, - inTangentRelative: toVertex.inTangentRelative, - outTangentRelative: .zero), - end: CurveVertex( - point: toVertex.point, - inTangentRelative: .zero, - outTangentRelative: toVertex.outTangentRelative)) - } - - if outTangentRelative.isZero, toVertex.inTangentRelative.isZero { - /// If both tangents are zero, then span to be trimmed is a straight line. - let trimPoint = point.interpolate(to: toVertex.point, amount: position) - return ( - start: self, - trimPoint: CurveVertex(point: trimPoint, inTangentRelative: .zero, outTangentRelative: .zero), - end: toVertex) - } - /// Cutting by amount gives incorrect length.... - /// One option is to cut by a stride until it gets close then edge it down. - /// Measuring a percentage of the spans does not equal the same as measuring a percentage of length. - /// This is where the historical trim path bugs come from. - let a = point.interpolate(to: outTangent, amount: position) - let b = outTangent.interpolate(to: toVertex.inTangent, amount: position) - let c = toVertex.inTangent.interpolate(to: toVertex.point, amount: position) - let d = a.interpolate(to: b, amount: position) - let e = b.interpolate(to: c, amount: position) - let f = d.interpolate(to: e, amount: position) - return ( - start: CurveVertex(point: point, inTangent: inTangent, outTangent: a), - trimPoint: CurveVertex(point: f, inTangent: d, outTangent: e), - end: CurveVertex(point: toVertex.point, inTangent: c, outTangent: toVertex.outTangent)) - } - - /// Trims a curve of a known length to a specific length and returns the points. - /// - /// There is not a performant yet accurate way to cut a curve to a specific length. - /// This calls splitCurve(toVertex: position:) to split the curve and then measures - /// the length of the new curve. The function then iterates through the samples, - /// adjusting the position of the cut for a more precise cut. - /// Usually a single iteration is enough to get within 0.5 points of the desired - /// length. - /// - /// This function should probably live in PathElement, since it deals with curve - /// lengths. - func trimCurve(toVertex: CurveVertex, atLength: CGFloat, curveLength: CGFloat, maxSamples: Int, accuracy: CGFloat = 1) -> - (start: CurveVertex, trimPoint: CurveVertex, end: CurveVertex) - { - var currentPosition = atLength / curveLength - var results = splitCurve(toVertex: toVertex, position: currentPosition) - - if maxSamples == 0 { - return results - } - - for _ in 1...maxSamples { - let length = results.start.distanceTo(results.trimPoint) - let lengthDiff = atLength - length - /// Check if length is correct. - if lengthDiff < accuracy { - return results - } - let diffPosition = max(min((currentPosition / length) * lengthDiff, currentPosition * 0.5), currentPosition * -0.5) - currentPosition = diffPosition + currentPosition - results = splitCurve(toVertex: toVertex, position: currentPosition) - } - return results - } - - /// The distance from the receiver to the provided vertex. - /// - /// For lines (zeroed tangents) the distance between the two points is measured. - /// For curves the curve is iterated over by sample count and the points are measured. - /// This is ~99% accurate at a sample count of 30 - func distanceTo(_ toVertex: CurveVertex, sampleCount: Int = 25) -> CGFloat { - if outTangentRelative.isZero, toVertex.inTangentRelative.isZero { - /// Return a linear distance. - return point.distanceTo(toVertex.point) - } - - var distance: CGFloat = 0 - - var previousPoint = point - for i in 0.. PathElement { - PathElement(length: vertex.distanceTo(toVertex), vertex: toVertex) - } - - func updateVertex(newVertex: CurveVertex) -> PathElement { - PathElement(length: length, vertex: newVertex) - } - - /// Splits an element span defined by the receiver and fromElement to a position 0-1 - func splitElementAtPosition(fromElement: PathElement, atLength: CGFloat) -> - (leftSpan: (start: PathElement, end: PathElement), rightSpan: (start: PathElement, end: PathElement)) - { - /// Trim the span. Start and trim go into the first, trim and end go into second. - let trimResults = fromElement.vertex.trimCurve(toVertex: vertex, atLength: atLength, curveLength: length, maxSamples: 3) - - /// Create the elements for the break - let spanAStart = PathElement( - length: fromElement.length, - vertex: CurveVertex( - point: fromElement.vertex.point, - inTangent: fromElement.vertex.inTangent, - outTangent: trimResults.start.outTangent)) - /// Recalculating the length here is a waste as the trimCurve function also accurately calculates this length. - let spanAEnd = spanAStart.pathElementTo(trimResults.trimPoint) - - let spanBStart = PathElement(vertex: trimResults.trimPoint) - let spanBEnd = spanBStart.pathElementTo(trimResults.end) - return ( - leftSpan: (start: spanAStart, end: spanAEnd), - rightSpan: (start: spanBStart, end: spanBEnd)) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/UnitBezier.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/UnitBezier.swift deleted file mode 100644 index 8b14fa1525af3823cb0d1e67e8d7296d7ebc3d85..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/UnitBezier.swift +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (C) 2008 Apple Inc. All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import CoreGraphics -import Foundation - -/// Defines a cubic-bezier where the endpoints are (0, 0) and (1, 1) -/// -/// The main use case is computing the progress of an animation at a given percent completion. For instance, -/// for a linear animation, the expected progress at `0.5` is `0.5`. -/// -/// - Note: This is a Swift port of [Apple's WebKit code]( -/// http://svn.webkit.org/repository/webkit/trunk/Source/WebCore/platform/graphics/UnitBezier.h -/// ) -/// -struct UnitBezier { - - // MARK: Lifecycle - - init(controlPoint1: CGPoint, controlPoint2: CGPoint) { - cx = 3.0 * controlPoint1.x - bx = 3.0 * (controlPoint2.x - controlPoint1.x) - cx - ax = 1.0 - cx - bx - cy = 3.0 * controlPoint1.y - by = 3.0 * (controlPoint2.y - controlPoint1.y) - cy - ay = 1.0 - cy - by - } - - // MARK: Internal - - /// Computes the progress `y` value for a given `x` value - func value(for x: CGFloat, epsilon: CGFloat) -> CGFloat { - sampleCurveY(solveCurveX(x, epsilon: epsilon)) - } - - // MARK: Private - - private let ax: CGFloat - private let bx: CGFloat - private let cx: CGFloat - private let ay: CGFloat - private let by: CGFloat - private let cy: CGFloat - - /// Compute `x(t)` for a given `t` - private func sampleCurveX(_ t: CGFloat) -> CGFloat { - // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule. - ((ax * t + bx) * t + cx) * t - } - - /// Compute `y(t)` for a given `t` - private func sampleCurveY(_ t: CGFloat) -> CGFloat { - ((ay * t + by) * t + cy) * t - } - - /// Compute `x'(t)` for a given `t` - private func sampleCurveDerivativeX(_ t: CGFloat) -> CGFloat { - (3.0 * ax * t + 2.0 * bx) * t + cx - } - - /// Given an `x` value solve for the parametric value `t` - private func solveCurveX(_ x: CGFloat, epsilon: CGFloat) -> CGFloat { - var t0, t1, t2, x2, d2: CGFloat - - // First try a few iterations of Newton-Raphson -- normally very fast. - t2 = x - for _ in 0..<8 { - x2 = sampleCurveX(t2) - x - guard abs(x2) >= epsilon else { return t2 } - d2 = sampleCurveDerivativeX(t2) - guard abs(d2) >= 1e-6 else { break } - t2 = t2 - x2 / d2 - } - - // Fall back to the bisection method for reliability. - t0 = 0.0 - t1 = 1.0 - t2 = x - guard t2 >= t0 else { return t0 } - guard t2 <= t1 else { return t1 } - - while t0 < t1 { - x2 = sampleCurveX(t2) - guard abs(x2 - x) >= epsilon else { return t2 } - if x > x2 { - t0 = t2 - } else { - t1 = t2 - } - t2 = (t1 - t0) * 0.5 + t0 - } - - return t2 - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/VectorsExtensions.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/VectorsExtensions.swift deleted file mode 100644 index 626fd33ec4a2ba66a9e64f84b256e0944c67110f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Private/Utility/Primitives/VectorsExtensions.swift +++ /dev/null @@ -1,363 +0,0 @@ -// -// Vector.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/7/19. -// - -import CoreGraphics -import Foundation -import QuartzCore - -// MARK: - LottieVector1D + Codable - -/// Single value container. Needed because lottie sometimes wraps a Double in an array. -extension LottieVector1D: Codable { - - // MARK: Lifecycle - - public init(from decoder: Decoder) throws { - /// Try to decode an array of doubles - do { - var container = try decoder.unkeyedContainer() - value = try container.decode(Double.self) - } catch { - value = try decoder.singleValueContainer().decode(Double.self) - } - } - - // MARK: Public - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(value) - } - - // MARK: Internal - - var cgFloatValue: CGFloat { - CGFloat(value) - } - -} - -// MARK: - LottieVector1D + AnyInitializable - -extension LottieVector1D: AnyInitializable { - - init(value: Any) throws { - if - let array = value as? [Double], - let double = array.first - { - self.value = double - } else if let double = value as? Double { - self.value = double - } else { - throw InitializableError.invalidInput() - } - } - -} - -extension Double { - var vectorValue: LottieVector1D { - LottieVector1D(self) - } -} - -// MARK: - LottieVector2D - -/// Needed for decoding json {x: y:} to a CGPoint -public struct LottieVector2D: Codable, Hashable, Sendable { - - // MARK: Lifecycle - - init(x: Double, y: Double) { - self.x = x - self.y = y - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: LottieVector2D.CodingKeys.self) - - do { - let xValue: [Double] = try container.decode([Double].self, forKey: .x) - x = xValue[0] - } catch { - x = try container.decode(Double.self, forKey: .x) - } - - do { - let yValue: [Double] = try container.decode([Double].self, forKey: .y) - y = yValue[0] - } catch { - y = try container.decode(Double.self, forKey: .y) - } - } - - // MARK: Public - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: LottieVector2D.CodingKeys.self) - try container.encode(x, forKey: .x) - try container.encode(y, forKey: .y) - } - - // MARK: Internal - - var x: Double - var y: Double - - var pointValue: CGPoint { - CGPoint(x: x, y: y) - } - - // MARK: Private - - private enum CodingKeys: String, CodingKey { - case x - case y - } -} - -// MARK: AnyInitializable - -extension LottieVector2D: AnyInitializable { - - init(value: Any) throws { - guard let dictionary = value as? [String: Any] else { - throw InitializableError.invalidInput() - } - - if - let array = dictionary[CodingKeys.x.rawValue] as? [Double], - let double = array.first - { - x = double - } else if let double = dictionary[CodingKeys.x.rawValue] as? Double { - x = double - } else { - throw InitializableError.invalidInput() - } - if - let array = dictionary[CodingKeys.y.rawValue] as? [Double], - let double = array.first - { - y = double - } else if let double = dictionary[CodingKeys.y.rawValue] as? Double { - y = double - } else { - throw InitializableError.invalidInput() - } - } -} - -extension CGPoint { - var vector2dValue: LottieVector2D { - LottieVector2D(x: Double(x), y: Double(y)) - } -} - -// MARK: - LottieVector3D + Codable - -/// A three dimensional vector. -/// These vectors are encoded and decoded from [Double] - -extension LottieVector3D: Codable { - - // MARK: Lifecycle - - init(x: CGFloat, y: CGFloat, z: CGFloat) { - self.x = Double(x) - self.y = Double(y) - self.z = Double(z) - } - - public init(from decoder: Decoder) throws { - var container = try decoder.unkeyedContainer() - - if !container.isAtEnd { - x = try container.decode(Double.self) - } else { - x = 0 - } - - if !container.isAtEnd { - y = try container.decode(Double.self) - } else { - y = 0 - } - - if !container.isAtEnd { - z = try container.decode(Double.self) - } else { - z = 0 - } - } - - // MARK: Public - - public func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - try container.encode(x) - try container.encode(y) - try container.encode(z) - } - -} - -// MARK: - LottieVector3D + AnyInitializable - -extension LottieVector3D: AnyInitializable { - - init(value: Any) throws { - guard var array = value as? [Double] else { - throw InitializableError.invalidInput() - } - x = array.count > 0 ? array.removeFirst() : 0 - y = array.count > 0 ? array.removeFirst() : 0 - z = array.count > 0 ? array.removeFirst() : 0 - } - -} - -extension LottieVector3D { - public var pointValue: CGPoint { - CGPoint(x: x, y: y) - } - - public var sizeValue: CGSize { - CGSize(width: x, height: y) - } -} - -extension CGPoint { - var vector3dValue: LottieVector3D { - LottieVector3D(x: x, y: y, z: 0) - } -} - -extension CGSize { - var vector3dValue: LottieVector3D { - LottieVector3D(x: width, y: height, z: 1) - } -} - -extension CATransform3D { - - enum Axis { - case x, y, z - } - - static func makeSkew(skew: CGFloat, skewAxis: CGFloat) -> CATransform3D { - let mCos = cos(skewAxis.toRadians()) - let mSin = sin(skewAxis.toRadians()) - let aTan = tan(skew.toRadians()) - - let transform1 = CATransform3D( - m11: mCos, - m12: mSin, - m13: 0, - m14: 0, - m21: -mSin, - m22: mCos, - m23: 0, - m24: 0, - m31: 0, - m32: 0, - m33: 1, - m34: 0, - m41: 0, - m42: 0, - m43: 0, - m44: 1) - - let transform2 = CATransform3D( - m11: 1, - m12: 0, - m13: 0, - m14: 0, - m21: aTan, - m22: 1, - m23: 0, - m24: 0, - m31: 0, - m32: 0, - m33: 1, - m34: 0, - m41: 0, - m42: 0, - m43: 0, - m44: 1) - - let transform3 = CATransform3D( - m11: mCos, - m12: -mSin, - m13: 0, - m14: 0, - m21: mSin, - m22: mCos, - m23: 0, - m24: 0, - m31: 0, - m32: 0, - m33: 1, - m34: 0, - m41: 0, - m42: 0, - m43: 0, - m44: 1) - return CATransform3DConcat(transform3, CATransform3DConcat(transform2, transform1)) - } - - static func makeTransform( - anchor: CGPoint, - position: CGPoint, - scale: CGSize, - rotationX: CGFloat, - rotationY: CGFloat, - rotationZ: CGFloat, - skew: CGFloat?, - skewAxis: CGFloat?) - -> CATransform3D - { - if let skew, let skewAxis { - return CATransform3DMakeTranslation(position.x, position.y, 0) - .rotated(rotationX, axis: .x) - .rotated(rotationY, axis: .y) - .rotated(rotationZ, axis: .z) - .skewed(skew: -skew, skewAxis: skewAxis) - .scaled(scale * 0.01) - .translated(anchor * -1) - } - return CATransform3DMakeTranslation(position.x, position.y, 0) - .rotated(rotationX, axis: .x) - .rotated(rotationY, axis: .y) - .rotated(rotationZ, axis: .z) - .scaled(scale * 0.01) - .translated(anchor * -1) - } - - func rotated(_ degrees: CGFloat, axis: Axis) -> CATransform3D { - CATransform3DRotate( - self, - degrees.toRadians(), - axis == .x ? 1 : 0, - axis == .y ? 1 : 0, - axis == .z ? 1 : 0) - } - - func translated(_ translation: CGPoint) -> CATransform3D { - CATransform3DTranslate(self, translation.x, translation.y, 0) - } - - func scaled(_ scale: CGSize) -> CATransform3D { - CATransform3DScale(self, scale.width, scale.height, 1) - } - - func skewed(skew: CGFloat, skewAxis: CGFloat) -> CATransform3D { - CATransform3DConcat(CATransform3D.makeSkew(skew: skew, skewAxis: skewAxis), self) - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimation.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimation.swift deleted file mode 100644 index 0893eeeeabae9f1a49024fa82250d4d58e87ce9d..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimation.swift +++ /dev/null @@ -1,179 +0,0 @@ -// -// LottieAnimation.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/7/19. -// - -import Foundation - -// MARK: - CoordinateSpace - -public enum CoordinateSpace: Int, Codable, Sendable { - case type2d - case type3d -} - -// MARK: - LottieAnimation - -/// The `LottieAnimation` model is the top level model object in Lottie. -/// -/// A `LottieAnimation` holds all of the animation data backing a Lottie Animation. -/// Codable, see JSON schema [here](https://github.com/airbnb/lottie-web/tree/master/docs/json). -public final class LottieAnimation: Codable, Sendable, DictionaryInitializable { - - // MARK: Lifecycle - - required public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: LottieAnimation.CodingKeys.self) - version = try container.decode(String.self, forKey: .version) - type = try container.decodeIfPresent(CoordinateSpace.self, forKey: .type) ?? .type2d - startFrame = try container.decode(AnimationFrameTime.self, forKey: .startFrame) - endFrame = try container.decode(AnimationFrameTime.self, forKey: .endFrame) - framerate = try container.decode(Double.self, forKey: .framerate) - width = try container.decode(Double.self, forKey: .width) - height = try container.decode(Double.self, forKey: .height) - layers = try container.decode([LayerModel].self, ofFamily: LayerType.self, forKey: .layers) - glyphs = try container.decodeIfPresent([Glyph].self, forKey: .glyphs) - fonts = try container.decodeIfPresent(FontList.self, forKey: .fonts) - assetLibrary = try container.decodeIfPresent(AssetLibrary.self, forKey: .assetLibrary) - markers = try container.decodeIfPresent([Marker].self, forKey: .markers) - - if let markers { - var markerMap: [String: Marker] = [:] - for marker in markers { - markerMap[marker.name] = marker - } - self.markerMap = markerMap - } else { - markerMap = nil - } - } - - public init(dictionary: [String: Any]) throws { - version = try dictionary.value(for: CodingKeys.version) - if - let typeRawValue = dictionary[CodingKeys.type.rawValue] as? Int, - let type = CoordinateSpace(rawValue: typeRawValue) - { - self.type = type - } else { - type = .type2d - } - startFrame = try dictionary.value(for: CodingKeys.startFrame) - endFrame = try dictionary.value(for: CodingKeys.endFrame) - framerate = try dictionary.value(for: CodingKeys.framerate) - width = try dictionary.value(for: CodingKeys.width) - height = try dictionary.value(for: CodingKeys.height) - let layerDictionaries: [[String: Any]] = try dictionary.value(for: CodingKeys.layers) - layers = try [LayerModel].fromDictionaries(layerDictionaries) - if let glyphDictionaries = dictionary[CodingKeys.glyphs.rawValue] as? [[String: Any]] { - glyphs = try glyphDictionaries.map { try Glyph(dictionary: $0) } - } else { - glyphs = nil - } - if let fontsDictionary = dictionary[CodingKeys.fonts.rawValue] as? [String: Any] { - fonts = try FontList(dictionary: fontsDictionary) - } else { - fonts = nil - } - if let assetLibraryDictionaries = dictionary[CodingKeys.assetLibrary.rawValue] as? [[String: Any]] { - assetLibrary = try AssetLibrary(value: assetLibraryDictionaries) - } else { - assetLibrary = nil - } - if let markerDictionaries = dictionary[CodingKeys.markers.rawValue] as? [[String: Any]] { - let markers = try markerDictionaries.map { try Marker(dictionary: $0) } - var markerMap: [String: Marker] = [:] - for marker in markers { - markerMap[marker.name] = marker - } - self.markers = markers - self.markerMap = markerMap - } else { - markers = nil - markerMap = nil - } - } - - // MARK: Public - - /// The start time of the composition in frameTime. - public let startFrame: AnimationFrameTime - - /// The end time of the composition in frameTime. - public let endFrame: AnimationFrameTime - - /// The frame rate of the composition. - public let framerate: Double - - /// Return all marker names, in order, or an empty list if none are specified - public var markerNames: [String] { - guard let markers else { return [] } - return markers.map { $0.name } - } - - // MARK: Internal - - enum CodingKeys: String, CodingKey { - case version = "v" - case type = "ddd" - case startFrame = "ip" - case endFrame = "op" - case framerate = "fr" - case width = "w" - case height = "h" - case layers - case glyphs = "chars" - case fonts - case assetLibrary = "assets" - case markers - } - - /// The version of the JSON Schema. - let version: String - - /// The coordinate space of the composition. - let type: CoordinateSpace - - /// The height of the composition in points. - let width: Double - - /// The width of the composition in points. - let height: Double - - /// The list of animation layers - let layers: [LayerModel] - - /// The list of glyphs used for text rendering - let glyphs: [Glyph]? - - /// The list of fonts used for text rendering - let fonts: FontList? - - /// Asset Library - let assetLibrary: AssetLibrary? - - /// Markers - let markers: [Marker]? - let markerMap: [String: Marker]? - - /// The marker to use if "reduced motion" is enabled. - /// Supported marker names are case insensitive, and include: - /// - reduced motion - /// - reducedMotion - /// - reduced_motion - /// - reduced-motion - var reducedMotionMarker: Marker? { - let allowedReducedMotionMarkerNames = Set([ - "reduced motion", - "reduced_motion", - "reduced-motion", - "reducedmotion", - ]) - - return markers?.first(where: { marker in - allowedReducedMotionMarkerNames.contains(marker.name.lowercased()) - }) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationHelpers.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationHelpers.swift deleted file mode 100644 index a052ed4ae84162f17fc6fbefdc38c4f4f765f3bb..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationHelpers.swift +++ /dev/null @@ -1,321 +0,0 @@ -// -// AnimationPublic.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/5/19. -// - -import CoreGraphics -import Foundation - -extension LottieAnimation { - - /// A closure for an Animation download. The closure is passed `nil` if there was an error. - public typealias DownloadClosure = (LottieAnimation?) -> Void - - /// The duration in seconds of the animation. - public var duration: TimeInterval { - Double(endFrame - startFrame) / framerate - } - - /// The natural bounds in points of the animation. - public var bounds: CGRect { - CGRect(x: 0, y: 0, width: width, height: height) - } - - /// The natural size in points of the animation. - public var size: CGSize { - CGSize(width: width, height: height) - } - - // MARK: Animation (Loading) - - /// Loads an animation model from a bundle by its name. Returns `nil` if an animation is not found. - /// - /// - Parameter name: The name of the json file without the json extension. EG "StarAnimation" - /// - Parameter bundle: The bundle in which the animation is located. Defaults to `Bundle.main` - /// - Parameter subdirectory: A subdirectory in the bundle in which the animation is located. Optional. - /// - Parameter animationCache: A cache for holding loaded animations. Defaults to `LottieAnimationCache.shared`. Optional. - /// - /// - Returns: Deserialized `LottieAnimation`. Optional. - public static func named( - _ name: String, - bundle: Bundle = Bundle.main, - subdirectory: String? = nil, - animationCache: AnimationCacheProvider? = LottieAnimationCache.shared) - -> LottieAnimation? - { - /// Create a cache key for the animation. - let cacheKey = bundle.bundlePath + (subdirectory ?? "") + "/" + name - - /// Check cache for animation - if - let animationCache, - let animation = animationCache.animation(forKey: cacheKey) - { - /// If found, return the animation. - return animation - } - - do { - /// Decode animation. - let json = try bundle.getAnimationData(name, subdirectory: subdirectory) - let animation = try LottieAnimation.from(data: json) - animationCache?.setAnimation(animation, forKey: cacheKey) - return animation - } catch { - /// Decoding error. - LottieLogger.shared.warn("Error when decoding animation \"\(name)\": \(error)") - return nil - } - } - - /// Loads an animation from a specific filepath. - /// - Parameter filepath: The absolute filepath of the animation to load. EG "/User/Me/starAnimation.json" - /// - Parameter animationCache: A cache for holding loaded animations. Defaults to `LottieAnimationCache.shared`. Optional. - /// - /// - Returns: Deserialized `LottieAnimation`. Optional. - public static func filepath( - _ filepath: String, - animationCache: AnimationCacheProvider? = LottieAnimationCache.shared) - -> LottieAnimation? - { - /// Check cache for animation - if - let animationCache, - let animation = animationCache.animation(forKey: filepath) - { - return animation - } - - do { - /// Decode the animation. - let json = try Data(contentsOf: URL(fileURLWithPath: filepath)) - let animation = try LottieAnimation.from(data: json) - animationCache?.setAnimation(animation, forKey: filepath) - return animation - } catch { - LottieLogger.shared.warn(""" - Failed to load animation from filepath \(filepath) - with underlying error: \(error.localizedDescription) - """) - return nil - } - } - - /// Loads an animation model from the asset catalog by its name. Returns `nil` if an animation is not found. - /// - Parameter name: The name of the json file in the asset catalog. EG "StarAnimation" - /// - Parameter bundle: The bundle in which the animation is located. Defaults to `Bundle.main` - /// - Parameter animationCache: A cache for holding loaded animations. Defaults to `LottieAnimationCache.shared` Optional. - /// - Returns: Deserialized `LottieAnimation`. Optional. - public static func asset( - _ name: String, - bundle: Bundle = Bundle.main, - animationCache: AnimationCacheProvider? = LottieAnimationCache.shared) - -> LottieAnimation? - { - /// Create a cache key for the animation. - let cacheKey = bundle.bundlePath + "/" + name - - /// Check cache for animation - if - let animationCache, - let animation = animationCache.animation(forKey: cacheKey) - { - /// If found, return the animation. - return animation - } - - do { - /// Load jsonData from Asset - let json = try Data(assetName: name, in: bundle) - /// Decode animation. - let animation = try LottieAnimation.from(data: json) - animationCache?.setAnimation(animation, forKey: cacheKey) - return animation - } catch { - LottieLogger.shared.warn(""" - Failed to load animation with asset name \(name) - in \(bundle.bundlePath) - with underlying error: \(error.localizedDescription) - """) - return nil - } - } - - /// Loads a Lottie animation from a `Data` object containing a JSON animation. - /// - /// - Parameter data: The object to load the animation from. - /// - Parameter strategy: How the data should be decoded. Defaults to using the strategy set in `LottieConfiguration.shared`. - /// - Returns: Deserialized `LottieAnimation`. Optional. - /// - public static func from( - data: Data, - strategy: DecodingStrategy = LottieConfiguration.shared.decodingStrategy) - throws -> LottieAnimation - { - switch strategy { - case .legacyCodable: - return try JSONDecoder().decode(LottieAnimation.self, from: data) - case .dictionaryBased: - let json = try JSONSerialization.jsonObject(with: data) - guard let dict = json as? [String: Any] else { - throw InitializableError.invalidInput() - } - return try LottieAnimation(dictionary: dict) - } - } - - /// Loads a Lottie animation asynchronously from the URL. - /// - /// - Parameter url: The url to load the animation from. - /// - Parameter animationCache: A cache for holding loaded animations. Defaults to `LottieAnimationCache.shared`. Optional. - /// - @available(iOS 13.0, macOS 10.15, tvOS 13.0, *) - public static func loadedFrom( - url: URL, - session: URLSession = .shared, - animationCache: AnimationCacheProvider? = LottieAnimationCache.shared) - async -> LottieAnimation? - { - await withCheckedContinuation { continuation in - LottieAnimation.loadedFrom( - url: url, - session: session, - closure: { result in - continuation.resume(returning: result) - }, - animationCache: animationCache) - } - } - - /// Loads a Lottie animation asynchronously from the URL. - /// - /// - Parameter url: The url to load the animation from. - /// - Parameter closure: A closure to be called when the animation has loaded. - /// - Parameter animationCache: A cache for holding loaded animations. Defaults to `LottieAnimationCache.shared`. Optional. - /// - public static func loadedFrom( - url: URL, - session: URLSession = .shared, - closure: @escaping LottieAnimation.DownloadClosure, - animationCache: AnimationCacheProvider? = LottieAnimationCache.shared) - { - if let animationCache, let animation = animationCache.animation(forKey: url.absoluteString) { - closure(animation) - } else { - let task = session.dataTask(with: url) { data, _, error in - guard error == nil, let jsonData = data else { - DispatchQueue.main.async { - closure(nil) - } - return - } - do { - let animation = try LottieAnimation.from(data: jsonData) - DispatchQueue.main.async { - animationCache?.setAnimation(animation, forKey: url.absoluteString) - closure(animation) - } - } catch { - DispatchQueue.main.async { - closure(nil) - } - } - } - task.resume() - } - } - - // MARK: Animation (Helpers) - - /// Markers are a way to describe a point in time by a key name. - /// - /// Markers are encoded into animation JSON. By using markers a designer can mark - /// playback points for a developer to use without having to worry about keeping - /// track of animation frames. If the animation file is updated, the developer - /// does not need to update playback code. - /// - /// Returns the Progress Time for the marker named. Returns nil if no marker found. - public func progressTime(forMarker named: String) -> AnimationProgressTime? { - guard let markers = markerMap, let marker = markers[named] else { - return nil - } - return progressTime(forFrame: marker.frameTime) - } - - /// Markers are a way to describe a point in time by a key name. - /// - /// Markers are encoded into animation JSON. By using markers a designer can mark - /// playback points for a developer to use without having to worry about keeping - /// track of animation frames. If the animation file is updated, the developer - /// does not need to update playback code. - /// - /// Returns the Frame Time for the marker named. Returns nil if no marker found. - public func frameTime(forMarker named: String) -> AnimationFrameTime? { - guard let markers = markerMap, let marker = markers[named] else { - return nil - } - return marker.frameTime - } - - /// Markers are a way to describe a point in time and a duration by a key name. - /// - /// Markers are encoded into animation JSON. By using markers a designer can mark - /// playback points for a developer to use without having to worry about keeping - /// track of animation frames. If the animation file is updated, the developer - /// does not need to update playback code. - /// - /// - Returns: The duration frame time for the marker, or `nil` if no marker found. - public func durationFrameTime(forMarker named: String) -> AnimationFrameTime? { - guard let marker = markerMap?[named] else { - return nil - } - return marker.durationFrameTime - } - - /// Converts Frame Time (Seconds * Framerate) into Progress Time - /// (optionally clamped to between 0 and 1). - public func progressTime( - forFrame frameTime: AnimationFrameTime, - clamped: Bool = true) - -> AnimationProgressTime - { - let progressTime = ((frameTime - startFrame) / (endFrame - startFrame)) - - if clamped { - return progressTime.clamp(0, 1) - } else { - return progressTime - } - } - - /// Converts Progress Time (0 to 1) into Frame Time (Seconds * Framerate) - public func frameTime(forProgress progressTime: AnimationProgressTime) -> AnimationFrameTime { - ((endFrame - startFrame) * progressTime) + startFrame - } - - /// Converts Frame Time (Seconds * Framerate) into Time (Seconds) - public func time(forFrame frameTime: AnimationFrameTime) -> TimeInterval { - Double(frameTime - startFrame) / framerate - } - - /// Converts Time (Seconds) into Frame Time (Seconds * Framerate) - public func frameTime(forTime time: TimeInterval) -> AnimationFrameTime { - CGFloat(time * framerate) + startFrame - } -} - -// MARK: - Foundation.Bundle + Sendable - -/// Necessary to suppress warnings like: -/// ``` -/// Non-sendable type 'Bundle' exiting main actor-isolated context in call to non-isolated -/// static method 'named(_:bundle:subdirectory:dotLottieCache:)' cannot cross actor boundary -/// ``` -/// This retroactive conformance is safe because Sendable is a marker protocol that doesn't -/// include any runtime component. Multiple modules in the same package graph can provide this -/// conformance without causing any conflicts. -/// -// swiftlint:disable:next no_unchecked_sendable -extension Foundation.Bundle: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationLayer.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationLayer.swift deleted file mode 100644 index 8126d419e2a6acddbd33ed72be4a2af75a48b789..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationLayer.swift +++ /dev/null @@ -1,1517 +0,0 @@ -// -// LottieAnimationLayer.swift -// Lottie -// - -import QuartzCore - -// MARK: - LottieAnimationLayer - -/// A CALayer subclass for rendering Lottie animations. -/// - Also available as a SwiftUI view (`LottieView`) and a UIView subclass (`LottieAnimationView`) -public class LottieAnimationLayer: CALayer { - - // MARK: Lifecycle - - /// Initializes a LottieAnimationLayer with an animation. - public init( - animation: LottieAnimation?, - imageProvider: AnimationImageProvider? = nil, - textProvider: AnimationKeypathTextProvider = DefaultTextProvider(), - fontProvider: AnimationFontProvider = DefaultFontProvider(), - configuration: LottieConfiguration = .shared, - logger: LottieLogger = .shared) - { - self.animation = animation - self.imageProvider = imageProvider ?? BundleImageProvider(bundle: Bundle.main, searchPath: nil) - self.textProvider = textProvider - self.fontProvider = fontProvider - self.configuration = configuration - screenScale = 1 - self.logger = logger - super.init() - makeAnimationLayer(usingEngine: configuration.renderingEngine) - if let animation { - frame = animation.bounds - } - } - - /// Initializes an LottieAnimationLayer with a .lottie file. - public init( - dotLottie: DotLottieFile?, - animationId: String? = nil, - textProvider: AnimationKeypathTextProvider = DefaultTextProvider(), - fontProvider: AnimationFontProvider = DefaultFontProvider(), - configuration: LottieConfiguration = .shared, - logger: LottieLogger = .shared) - { - let dotLottieAnimation = dotLottie?.animation(for: animationId) - animation = dotLottieAnimation?.animation - imageProvider = dotLottie?.imageProvider ?? BundleImageProvider(bundle: Bundle.main, searchPath: nil) - self.textProvider = textProvider - self.fontProvider = fontProvider - self.configuration = configuration - screenScale = 1 - self.logger = logger - super.init() - loopMode = dotLottieAnimation?.configuration.loopMode ?? .playOnce - animationSpeed = CGFloat(dotLottieAnimation?.configuration.speed ?? 1) - makeAnimationLayer(usingEngine: configuration.renderingEngine) - if let animation { - frame = animation.bounds - } - } - - public init( - configuration: LottieConfiguration = .shared, - logger: LottieLogger = .shared) - { - animation = nil - imageProvider = BundleImageProvider(bundle: Bundle.main, searchPath: nil) - textProvider = DefaultTextProvider() - fontProvider = DefaultFontProvider() - self.configuration = configuration - screenScale = 1 - self.logger = logger - super.init() - } - - /// Called by CoreAnimation to create a shadow copy of this layer - /// More details: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init - override init(layer: Any) { - guard let typedLayer = layer as? Self else { - fatalError("\(Self.self).init(layer:) incorrectly called with \(type(of: layer))") - } - - animation = typedLayer.animation - imageProvider = typedLayer.imageProvider - textProvider = typedLayer.textProvider - fontProvider = typedLayer.fontProvider - logger = typedLayer.logger - screenScale = typedLayer.screenScale - configuration = typedLayer.configuration - super.init(layer: typedLayer) - } - - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: Open - - /// Plays the animation from its current state to the end. - /// - /// - Parameter completion: An optional completion closure to be called when the animation completes playing. - open func play(completion: LottieCompletionBlock? = nil) { - guard let animation else { return } - - defer { - currentPlaybackMode = .playing(.fromProgress(nil, toProgress: 1, loopMode: loopMode)) - } - - if shouldOverrideWithReducedMotionAnimation { - playReducedMotionAnimation(completion: completion) - return - } - - /// Build a context for the animation. - let context = AnimationContext( - playFrom: CGFloat(animation.startFrame), - playTo: CGFloat(animation.endFrame), - closure: completion) - removeCurrentAnimationIfNecessary() - addNewAnimationForContext(context) - } - - /// Plays the animation from a progress (0-1) to a progress (0-1). - /// - /// - Parameter fromProgress: The start progress of the animation. If `nil` the animation will start at the current progress. - /// - Parameter toProgress: The end progress of the animation. - /// - Parameter loopMode: The loop behavior of the animation. If `nil` the layer's `loopMode` property will be used. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - fromProgress: AnimationProgressTime? = nil, - toProgress: AnimationProgressTime, - loopMode: LottieLoopMode? = nil, - completion: LottieCompletionBlock? = nil) - { - guard let animation else { return } - - defer { - currentPlaybackMode = .playing(.fromProgress(fromProgress, toProgress: toProgress, loopMode: loopMode ?? self.loopMode)) - } - - if shouldOverrideWithReducedMotionAnimation { - playReducedMotionAnimation(completion: completion) - return - } - - removeCurrentAnimationIfNecessary() - if let loopMode { - /// Set the loop mode, if one was supplied - self.loopMode = loopMode - } - let context = AnimationContext( - playFrom: animation.frameTime(forProgress: fromProgress ?? currentProgress), - playTo: animation.frameTime(forProgress: toProgress), - closure: completion) - addNewAnimationForContext(context) - } - - /// Plays the animation from a start frame to an end frame in the animation's framerate. - /// - /// - Parameter fromFrame: The start frame of the animation. If `nil` the animation will start at the current frame. - /// - Parameter toFrame: The end frame of the animation. - /// - Parameter loopMode: The loop behavior of the animation. If `nil` the layer's `loopMode` property will be used. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - fromFrame: AnimationFrameTime? = nil, - toFrame: AnimationFrameTime, - loopMode: LottieLoopMode? = nil, - completion: LottieCompletionBlock? = nil) - { - defer { - currentPlaybackMode = .playing(.fromFrame(fromFrame, toFrame: toFrame, loopMode: loopMode ?? self.loopMode)) - } - - if shouldOverrideWithReducedMotionAnimation { - playReducedMotionAnimation(completion: completion) - return - } - - removeCurrentAnimationIfNecessary() - if let loopMode { - /// Set the loop mode, if one was supplied - self.loopMode = loopMode - } - - let context = AnimationContext( - playFrom: fromFrame ?? currentFrame, - playTo: toFrame, - closure: completion) - addNewAnimationForContext(context) - } - - /// Plays the animation from a named marker to another marker. - /// - /// Markers are point in time that are encoded into the Animation data and assigned - /// a name. - /// - /// NOTE: If markers are not found the play command will exit. - /// - /// - Parameter fromMarker: The start marker for the animation playback. If `nil` the - /// animation will start at the current progress. - /// - Parameter toMarker: The end marker for the animation playback. - /// - Parameter playEndMarkerFrame: A flag to determine whether or not to play the frame of the end marker. If the - /// end marker represents the end of the section to play, it should be to true. If the provided end marker - /// represents the beginning of the next section, it should be false. - /// - Parameter loopMode: The loop behavior of the animation. If `nil` the layer's `loopMode` property will be used. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - fromMarker: String? = nil, - toMarker: String, - playEndMarkerFrame: Bool = true, - loopMode: LottieLoopMode? = nil, - completion: LottieCompletionBlock? = nil) - { - defer { - currentPlaybackMode = .playing(.fromMarker( - fromMarker, - toMarker: toMarker, - playEndMarkerFrame: playEndMarkerFrame, - loopMode: loopMode ?? self.loopMode)) - } - - if shouldOverrideWithReducedMotionAnimation { - playReducedMotionAnimation(completion: completion) - return - } - - guard let animation, let markers = animation.markerMap, let to = markers[toMarker] else { - return - } - - removeCurrentAnimationIfNecessary() - if let loopMode { - /// Set the loop mode, if one was supplied - self.loopMode = loopMode - } - - let fromTime: CGFloat - if let fromName = fromMarker, let from = markers[fromName] { - fromTime = CGFloat(from.frameTime) - } else { - fromTime = currentFrame - } - - let playTo = playEndMarkerFrame ? CGFloat(to.frameTime) : CGFloat(to.frameTime) - 1 - let context = AnimationContext( - playFrom: fromTime, - playTo: playTo, - closure: completion) - addNewAnimationForContext(context) - } - - /// Plays the animation from a named marker to the end of the marker's duration. - /// - /// A marker is a point in time with an associated duration that is encoded into the - /// animation data and assigned a name. - /// - /// NOTE: If marker is not found the play command will exit. - /// - /// - Parameter marker: The start marker for the animation playback. - /// - Parameter loopMode: The loop behavior of the animation. If `nil` the layer's `loopMode` property will be used. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - marker: String, - loopMode: LottieLoopMode? = nil, - completion: LottieCompletionBlock? = nil) - { - guard let from = animation?.markerMap?[marker] else { - return - } - - defer { - currentPlaybackMode = .playing(.marker(marker, loopMode: loopMode ?? self.loopMode)) - } - - if shouldOverrideWithReducedMotionAnimation { - playReducedMotionAnimation(completion: completion) - return - } - - play( - fromFrame: from.frameTime, - toFrame: from.frameTime + from.durationFrameTime, - loopMode: loopMode, - completion: completion) - } - - /// Plays the given markers sequentially in order. - /// - /// A marker is a point in time with an associated duration that is encoded into the - /// animation data and assigned a name. Multiple markers can be played sequentially - /// to create programmable animations. - /// - /// If a marker is not found, it will be skipped. - /// - /// If a marker doesn't have a duration value, it will play with a duration of 0 - /// (effectively being skipped). - /// - /// If another animation is played (by calling any `play` method) while this - /// marker sequence is playing, the marker sequence will be cancelled. - /// - /// - Parameter markers: The list of markers to play sequentially. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - markers: [String], - completion: LottieCompletionBlock? = nil) - { - guard !markers.isEmpty else { return } - - defer { - currentPlaybackMode = .playing(.markers(markers)) - } - - if shouldOverrideWithReducedMotionAnimation { - playReducedMotionAnimation(completion: nil) - return - } - - let markerToPlay = markers[0] - let followingMarkers = Array(markers.dropFirst()) - - guard animation?.markerMap?[markerToPlay] != nil else { - play(markers: followingMarkers, completion: completion) - return - } - - play(marker: markerToPlay, loopMode: .playOnce, completion: { [weak self] completed in - // If the completion handler is called with `completed: false` (which typically means - // that another animation was played by calling some `play` method), - // we should cancel the marker sequence and not play the next marker. - guard completed, let self else { - completion?(false) - return - } - - if followingMarkers.isEmpty { - // If we don't have any more markers to play, then the marker sequence has completed. - completion?(completed) - } else { - self.play(markers: followingMarkers, completion: completion) - } - }) - } - - /// Stops the animation and resets the layer to its start frame. - /// - /// The completion closure will be called with `false` - open func stop() { - removeCurrentAnimation() - currentFrame = 0 - } - - /// Pauses the animation in its current state. - /// - /// The completion closure will be called with `false` - open func pause() { - pause(at: .currentFrame) - } - - /// Pauses the animation at a given state. - open func pause(at state: LottiePlaybackMode.PausedState) { - switch state { - case .currentFrame: - removeCurrentAnimation() - - case .progress(let animationProgressTime): - currentProgress = animationProgressTime - - case .frame(let animationFrameTime): - currentFrame = animationFrameTime - case .time(let timeInterval): - currentTime = timeInterval - - case .marker(let name, let position): - guard let from = animation?.markerMap?[name] else { - return - } - - switch position { - case .start: - currentTime = from.frameTime - case .end: - currentTime = from.frameTime + from.durationFrameTime - } - } - - currentPlaybackMode = .paused(at: state) - } - - @available(*, deprecated, renamed: "setPlaybackMode(_:completion:)", message: "Will be removed in a future major release.") - open func play( - _ playbackMode: LottiePlaybackMode, - animationCompletionHandler: LottieCompletionBlock? = nil) - { - setPlaybackMode(playbackMode, completion: animationCompletionHandler) - } - - /// Applies the given `LottiePlaybackMode` to this layer. - /// - Parameter playbackMode: The playback mode to apply - /// - Parameter completion: A closure that is called after - /// an animation triggered by this method completes. - open func setPlaybackMode( - _ playbackMode: LottiePlaybackMode, - completion: LottieCompletionBlock? = nil) - { - switch playbackMode { - case .paused(at: let state): - pause(at: state) - - case .playing(let mode): - play(mode, completion: completion) - - case .progress(let progress): - pause(at: .progress(progress)) - - case .frame(let frame): - pause(at: .frame(frame)) - - case .time(let time): - pause(at: .time(time)) - - case .pause: - pause(at: .currentFrame) - - case .fromProgress(let from, let to, let loopMode): - play(.fromProgress(from, toProgress: to, loopMode: loopMode), completion: completion) - - case .fromFrame(let from, let to, let loopMode): - play(.fromFrame(from, toFrame: to, loopMode: loopMode), completion: completion) - - case .fromMarker(let from, let to, let playEndMarkerFrame, let loopMode): - play(.fromMarker(from, toMarker: to, playEndMarkerFrame: playEndMarkerFrame, loopMode: loopMode), completion: completion) - - case .marker(let name, let loopMode): - play(.marker(name, loopMode: loopMode), completion: completion) - - case .markers(let names): - play(.markers(names), completion: completion) - } - } - - /// Applies the given `LottiePlaybackMode` to this layer. - /// - Parameter playbackMode: The playback mode to apply - /// - Parameter completion: A closure that is called after - /// an animation triggered by this method completes. - open func play(_ playbackMode: LottiePlaybackMode.PlaybackMode, completion: LottieCompletionBlock? = nil) { - switch playbackMode { - case .fromProgress(let from, let to, let loopMode): - play( - fromProgress: from, - toProgress: to, - loopMode: loopMode, - completion: completion) - - case .fromFrame(let from, let to, let loopMode): - play( - fromFrame: from, - toFrame: to, - loopMode: loopMode, - completion: completion) - - case .fromMarker(let from, let to, let playEndMarkerFrame, let loopMode): - play( - fromMarker: from, - toMarker: to, - playEndMarkerFrame: playEndMarkerFrame, - loopMode: loopMode, - completion: completion) - - case .marker(let name, loopMode: let loopMode): - play(marker: name, loopMode: loopMode, completion: completion) - - case .markers(let names): - play(markers: names, completion: completion) - } - } - - // MARK: Public - - /// The current `LottiePlaybackMode` that is being used - public private(set) var currentPlaybackMode: LottiePlaybackMode? - - /// Value Providers that have been registered using `setValueProvider(_:keypath:)` - public private(set) var valueProviders = [AnimationKeypath: AnyValueProvider]() - - /// A closure called when the animation layer has been loaded. - /// Will inform the receiver the type of rendering engine that is used for the layer. - public var animationLayerDidLoad: ((_ animationLayer: LottieAnimationLayer, _ renderingEngine: RenderingEngineOption) -> Void)? - - /// The configuration that this `LottieAnimationView` uses when playing its animation - public var configuration: LottieConfiguration { - didSet { - if configuration.renderingEngine != oldValue.renderingEngine { - makeAnimationLayer(usingEngine: configuration.renderingEngine) - } - } - } - - /// The underlying CALayer created to display the content. - /// Use this property to change CALayer props like the content's transform, anchor point, etc. - public var animationLayer: CALayer? { rootAnimationLayer } - - public var screenScale: CGFloat { - didSet { - rootAnimationLayer?.renderScale = screenScale - } - } - - /// Describes the behavior of an AnimationView when the app is moved to the background. - /// - /// The default for the Main Thread animation engine is `pause`, - /// which pauses the animation when the application moves to - /// the background. This prevents the animation from consuming CPU - /// resources when not on-screen. The completion block is called with - /// `false` for completed. - /// - /// The default for the Core Animation engine is `continuePlaying`, - /// since the Core Animation engine does not have any CPU overhead. - public var backgroundBehavior: LottieBackgroundBehavior { - get { - let currentBackgroundBehavior = _backgroundBehavior ?? .default(for: currentRenderingEngine ?? .mainThread) - - if - currentRenderingEngine == .mainThread, - _backgroundBehavior == .continuePlaying - { - logger.assertionFailure(""" - `LottieBackgroundBehavior.continuePlaying` should not be used with the Main Thread - rendering engine, since this would waste CPU resources on playing an animation - that is not visible. Consider using a different background mode, or switching to - the Core Animation rendering engine (which does not have any CPU overhead). - """) - } - - return currentBackgroundBehavior - } - set { - _backgroundBehavior = newValue - } - } - - /// Sets the animation backing the animation layer. Setting this will clear the - /// layer's contents, completion blocks and current state. The new animation will - /// be loaded up and set to the beginning of its timeline. - public var animation: LottieAnimation? { - didSet { - makeAnimationLayer(usingEngine: configuration.renderingEngine) - - if let animation { - animationLoaded?(self, animation) - } - } - } - - /// A closure that is called when `self.animation` is loaded. When setting this closure, - /// it is called immediately if `self.animation` is non-nil. - /// - /// When initializing a `LottieAnimationView`, the animation will either be loaded - /// synchronously (when loading a `LottieAnimation` from a .json file on disk) - /// or asynchronously (when loading a `DotLottieFile` from disk, or downloading - /// an animation from a URL). This closure is called in both cases once the - /// animation is loaded and applied, so can be a useful way to configure this - /// `LottieAnimationView` regardless of which initializer was used. For example: - /// - /// ``` - /// let animationView: LottieAnimationView - /// - /// if loadDotLottieFile { - /// // Loads the .lottie file asynchronously - /// animationView = LottieAnimationView(dotLottieName: "animation") - /// } else { - /// // Loads the .json file synchronously - /// animationView = LottieAnimationView(name: "animation") - /// } - /// - /// animationView.animationLoaded = { animationView, animation in - /// // If using a .lottie file, this is called once the file finishes loading. - /// // If using a .json file, this is called immediately (since the animation is loaded synchronously). - /// animationView.play() - /// } - /// ``` - public var animationLoaded: ((_ animationLayer: LottieAnimationLayer, _ animation: LottieAnimation) -> Void)? { - didSet { - if let animation { - animationLoaded?(self, animation) - } - } - } - - /// Sets the image provider for the animation layer. An image provider provides the - /// animation with its required image data. - /// - /// Setting this will cause the animation to reload its image contents. - public var imageProvider: AnimationImageProvider { - didSet { - rootAnimationLayer?.imageProvider = imageProvider.cachedImageProvider - reloadImages() - } - } - - /// Sets the text provider for animation layer. A text provider provides the - /// animation with values for text layers - public var textProvider: AnimationKeypathTextProvider { - didSet { - rootAnimationLayer?.textProvider = textProvider - } - } - - /// Sets the text provider for animation layer. A text provider provides the - /// animation with values for text layers - public var fontProvider: AnimationFontProvider { - didSet { - rootAnimationLayer?.fontProvider = fontProvider - } - } - - /// Whether or not the animation is masked to the bounds. Defaults to true. - public var maskAnimationToBounds = true { - didSet { - animationLayer?.masksToBounds = maskAnimationToBounds - } - } - - /// Returns `true` if the animation is currently playing. - public var isAnimationPlaying: Bool { - guard let animationLayer = rootAnimationLayer else { - return false - } - - if let valueFromLayer = animationLayer.isAnimationPlaying { - return valueFromLayer - } else { - return animationLayer.animation(forKey: activeAnimationName) != nil - } - } - - /// Sets the loop behavior for `play` calls. Defaults to `playOnce` - public var loopMode: LottieLoopMode = .playOnce { - didSet { - updateInFlightAnimation() - } - } - - /// When `true` the animation layer will rasterize its contents when not animating. - /// Rasterizing will improve performance of static animations. - /// - /// Note: this will not produce crisp results at resolutions above the animations natural resolution. - /// - /// Defaults to `false` - public var shouldRasterizeWhenIdle = false { - didSet { - updateRasterizationState() - } - } - - /// Sets the current animation time with a Progress Time - /// - /// Note: Setting this will stop the current animation, if any. - /// Note 2: If `animation` is nil, setting this will fallback to 0 - public var currentProgress: AnimationProgressTime { - set { - if let animation { - currentFrame = animation.frameTime(forProgress: newValue) - currentPlaybackMode = .paused(at: .progress(newValue)) - } else { - currentFrame = 0 - } - } - get { - if let animation { - return animation.progressTime(forFrame: currentFrame) - } else { - return 0 - } - } - } - - /// Sets the current animation time with a time in seconds. - /// - /// Note: Setting this will stop the current animation, if any. - /// Note 2: If `animation` is nil, setting this will fallback to 0 - public var currentTime: TimeInterval { - set { - if let animation { - currentFrame = animation.frameTime(forTime: newValue) - currentPlaybackMode = .paused(at: .time(newValue)) - } else { - currentFrame = 0 - } - } - get { - if let animation { - return animation.time(forFrame: currentFrame) - } else { - return 0 - } - } - } - - /// Sets the current animation time with a frame in the animations framerate. - /// - /// Note: Setting this will stop the current animation, if any. - public var currentFrame: AnimationFrameTime { - set { - removeCurrentAnimationIfNecessary() - updateAnimationFrame(newValue) - currentPlaybackMode = .paused(at: .frame(currentFrame)) - } - get { - rootAnimationLayer?.currentFrame ?? 0 - } - } - - /// Returns the current animation frame while an animation is playing. - public var realtimeAnimationFrame: AnimationFrameTime { - isAnimationPlaying ? rootAnimationLayer?.presentation()?.currentFrame ?? currentFrame : currentFrame - } - - /// Returns the current animation frame while an animation is playing. - public var realtimeAnimationProgress: AnimationProgressTime { - if let animation { - return animation.progressTime(forFrame: realtimeAnimationFrame) - } - return 0 - } - - /// Sets the speed of the animation playback. Defaults to 1 - public var animationSpeed: CGFloat = 1 { - didSet { - updateInFlightAnimation() - } - } - - /// When `true` the animation will play back at the framerate encoded in the - /// `LottieAnimation` model. When `false` the animation will play at the framerate - /// of the device. - /// - /// Defaults to false - public var respectAnimationFrameRate = false { - didSet { - rootAnimationLayer?.respectAnimationFrameRate = respectAnimationFrameRate - } - } - - /// The rendering engine currently being used by this layer. - /// - This will only be `nil` in cases where the configuration is `automatic` - /// but a `RootAnimationLayer` hasn't been constructed yet - public var currentRenderingEngine: RenderingEngine? { - switch configuration.renderingEngine { - case .specific(let engine): - return engine - - case .automatic: - guard let animationLayer else { - return nil - } - - if animationLayer is CoreAnimationLayer { - return .coreAnimation - } else { - return .mainThread - } - } - } - - /// Whether or not the Main Thread rendering engine should use `forceDisplayUpdate()` - /// when rendering each individual frame. - /// - The main thread rendering engine implements optimizations to decrease the amount - /// of properties that have to be re-rendered on each frame. There are some cases - /// where this can result in bugs / incorrect behavior, so we allow it to be disabled. - /// - Forcing a full render on every frame will decrease performance, and is not recommended - /// except as a workaround to a bug in the main thread rendering engine. - /// - Has no effect when using the Core Animation rendering engine. - public var mainThreadRenderingEngineShouldForceDisplayUpdateOnEachFrame = false { - didSet { - (rootAnimationLayer as? MainThreadAnimationLayer)?.forceDisplayUpdateOnEachFrame - = mainThreadRenderingEngineShouldForceDisplayUpdateOnEachFrame - } - } - - /// Sets the lottie file backing the animation layer. Setting this will clear the - /// layer's contents, completion blocks and current state. The new animation will - /// be loaded up and set to the beginning of its timeline. - /// The loopMode, animationSpeed and imageProvider will be set according - /// to lottie file settings - /// - Parameters: - /// - animationId: Internal animation id to play. Optional - /// Defaults to play first animation in file. - /// - dotLottieFile: Lottie file to play - public func loadAnimation( - _ animationId: String? = nil, - from dotLottieFile: DotLottieFile) - { - guard let dotLottieAnimation = dotLottieFile.animation(for: animationId) else { return } - loadAnimation(dotLottieAnimation) - } - - /// Sets the lottie file backing the animation layer. Setting this will clear the - /// layer's contents, completion blocks and current state. The new animation will - /// be loaded up and set to the beginning of its timeline. - /// The loopMode, animationSpeed and imageProvider will be set according - /// to lottie file settings - /// - Parameters: - /// - atIndex: Internal animation index to play. - /// Defaults to play first animation in file. - /// - dotLottieFile: Lottie file to play - public func loadAnimation( - atIndex index: Int, - from dotLottieFile: DotLottieFile) - { - guard let dotLottieAnimation = dotLottieFile.animation(at: index) else { return } - loadAnimation(dotLottieAnimation) - } - - /// Reloads the images supplied to the animation from the `imageProvider` - public func reloadImages() { - rootAnimationLayer?.reloadImages() - } - - /// Forces the LottieAnimationView to redraw its contents. - public func forceDisplayUpdate() { - rootAnimationLayer?.forceDisplayUpdate() - } - - /// Sets a ValueProvider for the specified keypath. The value provider will be set - /// on all properties that match the keypath. - /// - /// Nearly all properties of a Lottie animation can be changed at runtime using a - /// combination of `Animation Keypaths` and `Value Providers`. - /// Setting a ValueProvider on a keypath will cause the animation to update its - /// contents and read the new Value Provider. - /// - /// A value provider provides a typed value on a frame by frame basis. - /// - /// - Parameter valueProvider: The new value provider for the properties. - /// - Parameter keypath: The keypath used to search for properties. - /// - /// Example: - /// ``` - /// /// A keypath that finds the color value for all `Fill 1` nodes. - /// let fillKeypath = AnimationKeypath(keypath: "**.Fill 1.Color") - /// /// A Color Value provider that returns a reddish color. - /// let redValueProvider = ColorValueProvider(Color(r: 1, g: 0.2, b: 0.3, a: 1)) - /// /// Set the provider on the animationView. - /// animationView.setValueProvider(redValueProvider, keypath: fillKeypath) - /// ``` - public func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) { - guard let animationLayer = rootAnimationLayer else { return } - - valueProviders[keypath] = valueProvider - animationLayer.setValueProvider(valueProvider, keypath: keypath) - } - - /// Reads the value of a property specified by the Keypath. - /// Returns nil if no property is found. - /// - /// - Parameter for: The keypath used to search for the property. - /// - Parameter atFrame: The Frame Time of the value to query. If nil then the current frame is used. - public func getValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? { - rootAnimationLayer?.getValue(for: keypath, atFrame: atFrame) - } - - /// Reads the original value of a property specified by the Keypath. - /// This will ignore any value providers and can be useful when implementing a value providers that makes change to the original value from the animation. - /// Returns nil if no property is found. - /// - /// - Parameter for: The keypath used to search for the property. - /// - Parameter atFrame: The Frame Time of the value to query. If nil then the current frame is used. - public func getOriginalValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? { - rootAnimationLayer?.getOriginalValue(for: keypath, atFrame: atFrame) - } - - /// Logs all child keypaths. - public func logHierarchyKeypaths() { - rootAnimationLayer?.logHierarchyKeypaths() - } - - /// Computes and returns a list of all child keypaths in the current animation. - /// The returned list is the same as the log output of `logHierarchyKeypaths()` - public func allHierarchyKeypaths() -> [String] { - rootAnimationLayer?.allHierarchyKeypaths() ?? [] - } - - /// Converts a CGRect from the LottieAnimationView's coordinate space into the - /// coordinate space of the layer found at Keypath. - /// - /// If no layer is found, nil is returned - /// - /// - Parameter rect: The CGRect to convert. - /// - Parameter toLayerAt: The keypath used to find the layer. - public func convert(_ rect: CGRect, toLayerAt keypath: AnimationKeypath?) -> CGRect? { - guard let animationLayer = rootAnimationLayer else { return nil } - guard let keypath else { - return convert(rect, to: animationLayer) - } - guard let sublayer = animationLayer.layer(for: keypath) else { - return nil - } - setNeedsLayout() - layoutIfNeeded() - forceDisplayUpdate() - return animationLayer.convert(rect, to: sublayer) - } - - /// Converts a CGPoint from the LottieAnimationView's coordinate space into the - /// coordinate space of the layer found at Keypath. - /// - /// If no layer is found, nil is returned - /// - /// - Parameter point: The CGPoint to convert. - /// - Parameter toLayerAt: The keypath used to find the layer. - public func convert(_ point: CGPoint, toLayerAt keypath: AnimationKeypath?) -> CGPoint? { - guard let animationLayer = rootAnimationLayer else { return nil } - guard let keypath else { - return convert(point, to: animationLayer) - } - guard let sublayer = animationLayer.layer(for: keypath) else { - return nil - } - setNeedsLayout() - layoutIfNeeded() - forceDisplayUpdate() - return animationLayer.convert(point, to: sublayer) - } - - /// Sets the enabled state of all animator nodes found with the keypath search. - /// This can be used to interactively enable / disable parts of the animation. - /// - /// - Parameter isEnabled: When true the animator nodes affect the rendering tree. When false the node is removed from the tree. - /// - Parameter keypath: The keypath used to find the node(s). - public func setNodeIsEnabled(isEnabled: Bool, keypath: AnimationKeypath) { - guard let animationLayer = rootAnimationLayer else { return } - let nodes = animationLayer.animatorNodes(for: keypath) - if let nodes { - for node in nodes { - node.isEnabled = isEnabled - } - forceDisplayUpdate() - } - } - - /// Markers are a way to describe a point in time by a key name. - /// - /// Markers are encoded into animation JSON. By using markers a designer can mark - /// playback points for a developer to use without having to worry about keeping - /// track of animation frames. If the animation file is updated, the developer - /// does not need to update playback code. - /// - /// Returns the Progress Time for the marker named. Returns nil if no marker found. - public func progressTime(forMarker named: String) -> AnimationProgressTime? { - guard let animation else { - return nil - } - return animation.progressTime(forMarker: named) - } - - /// Markers are a way to describe a point in time by a key name. - /// - /// Markers are encoded into animation JSON. By using markers a designer can mark - /// playback points for a developer to use without having to worry about keeping - /// track of animation frames. If the animation file is updated, the developer - /// does not need to update playback code. - /// - /// Returns the Frame Time for the marker named. Returns nil if no marker found. - public func frameTime(forMarker named: String) -> AnimationFrameTime? { - guard let animation else { - return nil - } - return animation.frameTime(forMarker: named) - } - - /// Markers are a way to describe a point in time and a duration by a key name. - /// - /// Markers are encoded into animation JSON. By using markers a designer can mark - /// playback points for a developer to use without having to worry about keeping - /// track of animation frames. If the animation file is updated, the developer - /// does not need to update playback code. - /// - /// - Returns: The duration frame time for the marker, or `nil` if no marker found. - public func durationFrameTime(forMarker named: String) -> AnimationFrameTime? { - guard let animation else { - return nil - } - return animation.durationFrameTime(forMarker: named) - } - - public func updateAnimationForBackgroundState() { - if let currentContext = animationContext { - switch backgroundBehavior { - case .stop: - removeCurrentAnimation() - updateAnimationFrame(currentContext.playFrom) - case .pause: - removeCurrentAnimation() - case .pauseAndRestore: - currentContext.closure.ignoreDelegate = true - removeCurrentAnimation() - /// Keep the stale context around for when the app enters the foreground. - animationContext = currentContext - case .forceFinish: - removeCurrentAnimation() - updateAnimationFrame(currentContext.playTo) - case .continuePlaying: - break - } - } - } - - public func updateAnimationForForegroundState(wasWaitingToPlayAnimation: Bool) { - if let currentContext = animationContext { - if wasWaitingToPlayAnimation { - addNewAnimationForContext(currentContext) - } else if backgroundBehavior == .pauseAndRestore { - /// Restore animation from saved state - updateInFlightAnimation() - } - } - } - - // MARK: Internal - - var rootAnimationLayer: RootAnimationLayer? = nil - - /// Context describing the animation that is currently playing in this `LottieAnimationView` - /// - When non-nil, an animation is currently playing in this layer. Otherwise, - /// the layer is paused on a specific frame. - fileprivate(set) var animationContext: AnimationContext? - - var hasAnimationContext: Bool { - animationContext != nil - } - - /// Set animation name from Interface Builder - var animationName: String? { - didSet { - animation = animationName.flatMap { - LottieAnimation.named($0, animationCache: nil) - } - } - } - - /// Updates the animation frame. Does not affect any current animations - func updateAnimationFrame(_ newFrame: CGFloat) { - // In performance tests, we have to wrap the animation layer setup - // in a `CATransaction` in order for the layers to be deallocated at - // the correct time. The `CATransaction`s in this method interfere - // with the ones managed by the performance test, and aren't actually - // necessary in a headless environment, so we disable them. - if TestHelpers.performanceTestsAreRunning { - rootAnimationLayer?.currentFrame = newFrame - rootAnimationLayer?.forceDisplayUpdate() - return - } - - CATransaction.begin() - CATransaction.setCompletionBlock { - self.rootAnimationLayer?.forceDisplayUpdate() - } - CATransaction.setDisableActions(true) - rootAnimationLayer?.currentFrame = newFrame - CATransaction.commit() - } - - /// Updates an in flight animation. - func updateInFlightAnimation() { - guard let animationContext else { return } - - guard animationContext.closure.animationState != .complete else { - // Tried to re-add an already completed animation. Cancel. - self.animationContext = nil - return - } - - /// Tell existing context to ignore its closure - animationContext.closure.ignoreDelegate = true - - /// Make a new context, stealing the completion block from the previous. - let newContext = AnimationContext( - playFrom: animationContext.playFrom, - playTo: animationContext.playTo, - closure: animationContext.closure.completionBlock) - - /// Remove current animation, and freeze the current frame. - let pauseFrame = realtimeAnimationFrame - rootAnimationLayer?.removeAnimation(forKey: activeAnimationName) - rootAnimationLayer?.currentFrame = pauseFrame - - addNewAnimationForContext(newContext) - } - - func updateRasterizationState() { - if isAnimationPlaying { - animationLayer?.shouldRasterize = false - } else { - animationLayer?.shouldRasterize = shouldRasterizeWhenIdle - } - } - - func loadAnimation(_ animationSource: LottieAnimationSource?) { - switch animationSource { - case .lottieAnimation(let animation): - self.animation = animation - case .dotLottieFile(let dotLottieFile): - loadAnimation(from: dotLottieFile) - case nil: - animation = nil - } - } - - // MARK: Fileprivate - - fileprivate var _activeAnimationName: String = LottieAnimationLayer.animationName - fileprivate var animationID = 0 - - fileprivate var activeAnimationName: String { - switch rootAnimationLayer?.primaryAnimationKey { - case .specific(let animationKey): - return animationKey - case .managed, nil: - return _activeAnimationName - } - } - - /// Stops the current in flight animation and freezes the animation in its current state. - fileprivate func removeCurrentAnimation() { - guard animationContext != nil else { return } - let pauseFrame = realtimeAnimationFrame - animationLayer?.removeAnimation(forKey: activeAnimationName) - updateAnimationFrame(pauseFrame) - animationContext = nil - } - - fileprivate func makeAnimationLayer(usingEngine renderingEngine: RenderingEngineOption) { - /// Disable the default implicit crossfade animation Core Animation creates - /// when adding or removing sublayers. - actions = ["sublayers": NSNull()] - - /// Remove current animation if any - removeCurrentAnimation() - - if let oldAnimation = animationLayer { - oldAnimation.removeFromSuperlayer() - rootAnimationLayer = nil - } - - guard let animation else { - return - } - let rootAnimationLayer: RootAnimationLayer? - switch renderingEngine { - case .automatic: - rootAnimationLayer = makeAutomaticEngineLayer(for: animation) - case .specific(.coreAnimation): - rootAnimationLayer = makeCoreAnimationLayer(for: animation) - case .specific(.mainThread): - rootAnimationLayer = makeMainThreadAnimationLayer(for: animation) - } - - guard let animationLayer = rootAnimationLayer else { - return - } - - animationLayer.lottieAnimationLayer = self - - for (keypath, valueProvider) in valueProviders { - animationLayer.setValueProvider(valueProvider, keypath: keypath) - } - - animationLayerDidLoad?(self, renderingEngine) - - animationLayer.renderScale = screenScale - - addSublayer(animationLayer) - self.rootAnimationLayer = animationLayer - reloadImages() - animationLayer.setNeedsDisplay() - setNeedsLayout() - currentFrame = CGFloat(animation.startFrame) - } - - fileprivate func makeMainThreadAnimationLayer(for animation: LottieAnimation) -> MainThreadAnimationLayer { - let mainThreadAnimationLayer = MainThreadAnimationLayer( - animation: animation, - imageProvider: imageProvider.cachedImageProvider, - textProvider: textProvider, - fontProvider: fontProvider, - maskAnimationToBounds: maskAnimationToBounds, - logger: logger) - - mainThreadAnimationLayer.forceDisplayUpdateOnEachFrame = mainThreadRenderingEngineShouldForceDisplayUpdateOnEachFrame - return mainThreadAnimationLayer - } - - fileprivate func makeCoreAnimationLayer(for animation: LottieAnimation) -> CoreAnimationLayer? { - do { - let coreAnimationLayer = try CoreAnimationLayer( - animation: animation, - imageProvider: imageProvider.cachedImageProvider, - textProvider: textProvider, - fontProvider: fontProvider, - maskAnimationToBounds: maskAnimationToBounds, - compatibilityTrackerMode: .track, - logger: logger) - - coreAnimationLayer.didSetUpAnimation = { [logger] compatibilityIssues in - logger.assert( - compatibilityIssues.isEmpty, - "Encountered Core Animation compatibility issues while setting up animation:\n" - + compatibilityIssues.map { $0.description }.joined(separator: "\n") + "\n\n" - + """ - This animation cannot be rendered correctly by the Core Animation engine. - To resolve this issue, you can use `RenderingEngineOption.automatic`, which automatically falls back - to the Main Thread rendering engine when necessary, or just use `RenderingEngineOption.mainThread`. - - """) - } - - return coreAnimationLayer - } catch { - // This should never happen, because we initialize the `CoreAnimationLayer` with - // `CompatibilityTracker.Mode.track` (which reports errors in `didSetUpAnimation`, - // not by throwing). - logger.assertionFailure("Encountered unexpected error \(error)") - return nil - } - } - - fileprivate func makeAutomaticEngineLayer(for animation: LottieAnimation) -> CoreAnimationLayer? { - do { - // Attempt to set up the Core Animation layer. This can either throw immediately in `init`, - // or throw an error later in `CALayer.display()` that will be reported in `didSetUpAnimation`. - let coreAnimationLayer = try CoreAnimationLayer( - animation: animation, - imageProvider: imageProvider.cachedImageProvider, - textProvider: textProvider, - fontProvider: fontProvider, - maskAnimationToBounds: maskAnimationToBounds, - compatibilityTrackerMode: .abort, - logger: logger) - - coreAnimationLayer.didSetUpAnimation = { [weak self] issues in - self?.automaticEngineLayerDidSetUpAnimation(issues) - } - - return coreAnimationLayer - } catch { - if case CompatibilityTracker.Error.encounteredCompatibilityIssue(let compatibilityIssue) = error { - automaticEngineLayerDidSetUpAnimation([compatibilityIssue]) - } else { - // This should never happen, because we expect `CoreAnimationLayer` to only throw - // `CompatibilityTracker.Error.encounteredCompatibilityIssue` errors. - logger.assertionFailure("Encountered unexpected error \(error)") - automaticEngineLayerDidSetUpAnimation([]) - } - - return nil - } - } - - // Handles any compatibility issues with the Core Animation engine - // by falling back to the Main Thread engine - fileprivate func automaticEngineLayerDidSetUpAnimation(_ compatibilityIssues: [CompatibilityIssue]) { - // If there weren't any compatibility issues, then there's nothing else to do - if compatibilityIssues.isEmpty { - return - } - - logger.warn( - "Encountered Core Animation compatibility issue while setting up animation:\n" - + compatibilityIssues.map { $0.description }.joined(separator: "\n") + "\n" - + """ - This animation may have additional compatibility issues, but animation setup was cancelled early to avoid wasted work. - - Automatically falling back to Main Thread rendering engine. This fallback comes with some additional performance - overhead, which can be reduced by manually specifying that this animation should always use the Main Thread engine. - - """) - - let animationContext = animationContext - let currentFrame = currentFrame - - // Disable the completion handler delegate before tearing down the `CoreAnimationLayer` - // and building the `MainThreadAnimationLayer`. Otherwise deinitializing the - // `CoreAnimationLayer` would trigger the animation completion handler even though - // the animation hasn't even started playing yet. - animationContext?.closure.ignoreDelegate = true - - makeAnimationLayer(usingEngine: .mainThread) - - // Set up the Main Thread animation layer using the same configuration that - // was being used by the previous Core Animation layer - self.currentFrame = currentFrame - - if let animationContext { - // `AnimationContext.closure` (`AnimationCompletionDelegate`) is a reference type - // that is the animation layer's `CAAnimationDelegate`, and holds a reference to - // the animation layer. Reusing a single instance across different animation layers - // can cause the animation setup to fail, so we create a copy of the `animationContext`: - addNewAnimationForContext(AnimationContext( - playFrom: animationContext.playFrom, - playTo: animationContext.playTo, - closure: animationContext.closure.completionBlock)) - } - } - - /// Removes the current animation and pauses the animation at the current frame - /// if necessary before setting up a new animation. - /// - This is not necessary with the Core Animation engine, and skipping - /// this step lets us avoid building the animations twice (once paused - /// and once again playing) - /// - This method should only be called immediately before setting up another - /// animation -- otherwise this LottieAnimationView could be put in an inconsistent state. - fileprivate func removeCurrentAnimationIfNecessary() { - switch currentRenderingEngine { - case .mainThread: - removeCurrentAnimation() - case .coreAnimation, nil: - // We still need to remove the `animationContext`, since it should only be present - // when an animation is actually playing. Without this calling `removeCurrentAnimationIfNecessary()` - // and then setting the animation to a specific paused frame would put this - // `LottieAnimationView` in an inconsistent state. - animationContext = nil - } - } - - /// Adds animation to animation layer and sets the delegate. If animation layer or animation are nil, exits. - fileprivate func addNewAnimationForContext(_ animationContext: AnimationContext) { - guard let animationlayer = rootAnimationLayer, let animation else { - return - } - - self.animationContext = animationContext - - animationID = animationID + 1 - _activeAnimationName = LottieAnimationLayer.animationName + String(animationID) - - if let coreAnimationLayer = animationlayer as? CoreAnimationLayer { - var animationContext = animationContext - - // Core Animation doesn't natively support negative speed values, - // so instead we can swap `playFrom` / `playTo` - if animationSpeed < 0 { - let temp = animationContext.playFrom - animationContext.playFrom = animationContext.playTo - animationContext.playTo = temp - } - - var timingConfiguration = CoreAnimationLayer.CAMediaTimingConfiguration( - autoreverses: loopMode.caAnimationConfiguration.autoreverses, - repeatCount: loopMode.caAnimationConfiguration.repeatCount, - speed: abs(Float(animationSpeed))) - - // The animation should start playing from the `currentFrame`, - // if `currentFrame` is included in the time range being played. - let lowerBoundTime = min(animationContext.playFrom, animationContext.playTo) - let upperBoundTime = max(animationContext.playFrom, animationContext.playTo) - if (lowerBoundTime ..< upperBoundTime).contains(round(currentFrame)) { - // We have to configure this differently depending on the loop mode: - switch loopMode { - // When playing exactly once (and not looping), we can just set the - // `playFrom` time to be the `currentFrame`. Since the animation duration - // is based on `playFrom` and `playTo`, this automatically truncates the - // duration (so the animation stops playing at `playFrom`). - // - Don't do this if the animation is already at that frame - // (e.g. playing from 100% to 0% when the animation is already at 0%) - // since that would cause the animation to not play at all. - case .playOnce: - if animationContext.playTo != currentFrame { - animationContext.playFrom = currentFrame - } - - // When looping, we specifically _don't_ want to affect the duration of the animation, - // since that would affect the duration of all subsequent loops. We just want to adjust - // the duration of the _first_ loop. Instead of setting `playFrom`, we just add a `timeOffset` - // so the first loop begins at `currentTime` but all subsequent loops are the standard duration. - default: - if animationSpeed < 0 { - timingConfiguration.timeOffset = animation.time(forFrame: animationContext.playFrom) - currentTime - } else { - timingConfiguration.timeOffset = currentTime - animation.time(forFrame: animationContext.playFrom) - } - } - } - - // If attempting to play a zero-duration animation, just pause on that single frame instead - if animationContext.playFrom == animationContext.playTo { - currentFrame = animationContext.playTo - animationContext.closure.completionBlock?(true) - return - } - - coreAnimationLayer.playAnimation(configuration: .init( - animationContext: animationContext, - timingConfiguration: timingConfiguration)) - - return - } - - /// At this point there is no animation on animationLayer and its state is set. - - let framerate = animation.framerate - - let playFrom = animationContext.playFrom.clamp(animation.startFrame, animation.endFrame) - let playTo = animationContext.playTo.clamp(animation.startFrame, animation.endFrame) - - let duration = ((max(playFrom, playTo) - min(playFrom, playTo)) / CGFloat(framerate)) - - let playingForward: Bool = - ( - (animationSpeed > 0 && playFrom < playTo) || - (animationSpeed < 0 && playTo < playFrom)) - - var startFrame = currentFrame.clamp(min(playFrom, playTo), max(playFrom, playTo)) - if startFrame == playTo { - startFrame = playFrom - } - - let timeOffset: TimeInterval = playingForward - ? Double(startFrame - min(playFrom, playTo)) / framerate - : Double(max(playFrom, playTo) - startFrame) / framerate - - let layerAnimation = CABasicAnimation(keyPath: "currentFrame") - layerAnimation.fromValue = playFrom - layerAnimation.toValue = playTo - layerAnimation.speed = Float(animationSpeed) - layerAnimation.duration = TimeInterval(duration) - layerAnimation.fillMode = CAMediaTimingFillMode.both - layerAnimation.repeatCount = loopMode.caAnimationConfiguration.repeatCount - layerAnimation.autoreverses = loopMode.caAnimationConfiguration.autoreverses - - layerAnimation.isRemovedOnCompletion = false - if timeOffset != 0 { - let currentLayerTime = convertTime(CACurrentMediaTime(), from: nil) - layerAnimation.beginTime = currentLayerTime - (timeOffset * 1 / Double(abs(animationSpeed))) - } - layerAnimation.delegate = animationContext.closure - animationContext.closure.animationLayer = animationlayer - animationContext.closure.animationKey = activeAnimationName - - animationlayer.add(layerAnimation, forKey: activeAnimationName) - updateRasterizationState() - } - - // MARK: Private - - static private let animationName = "Lottie" - - private let logger: LottieLogger - - /// The `LottieBackgroundBehavior` that was specified manually by setting `self.backgroundBehavior` - private var _backgroundBehavior: LottieBackgroundBehavior? - - /// Whether or not the current animation should be overridden with - /// the marker matching the current "reduced motion" mode. - private var shouldOverrideWithReducedMotionAnimation: Bool { - reducedMotionMarker != nil - } - - /// The marker that corresponds to the current "reduced motion" mode. - private var reducedMotionMarker: Marker? { - switch configuration.reducedMotionOption.currentReducedMotionMode { - case .standardMotion: - return nil - case .reducedMotion: - return animation?.reducedMotionMarker - } - } - - private func loadAnimation(_ dotLottieAnimation: DotLottieFile.Animation) { - loopMode = dotLottieAnimation.configuration.loopMode - animationSpeed = CGFloat(dotLottieAnimation.configuration.speed) - - if let imageProvider = dotLottieAnimation.configuration.imageProvider { - self.imageProvider = imageProvider - } - - animation = dotLottieAnimation.animation - } - - /// Plays the marker that corresponds to the current "reduced motion" mode if present. - private func playReducedMotionAnimation(completion: LottieCompletionBlock?) { - guard let reducedMotionMarker else { return } - - // `play(marker:)` calls the `play(fromFrame:toFrame:)` method which calls this - // `playReducedMotionAnimation` method when `shouldOverrideWithReducedMotionAnimation` - // is `true`. To prevent infinite recursion, disable the reduced motion functionality - // until the end of this function. - let currentConfiguration = configuration - configuration.reducedMotionOption = .standardMotion - defer { configuration = currentConfiguration } - - play(marker: reducedMotionMarker.name, completion: completion) - } - -} - -// MARK: - LottieLoopMode + caAnimationConfiguration - -extension LottieLoopMode { - /// The `CAAnimation` configuration that reflects this mode - var caAnimationConfiguration: (repeatCount: Float, autoreverses: Bool) { - switch self { - case .playOnce: - return (repeatCount: 1, autoreverses: false) - case .loop: - return (repeatCount: .greatestFiniteMagnitude, autoreverses: false) - case .autoReverse: - return (repeatCount: .greatestFiniteMagnitude, autoreverses: true) - case .repeat(let amount): - return (repeatCount: amount, autoreverses: false) - case .repeatBackwards(let amount): - return (repeatCount: amount, autoreverses: true) - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationView.swift deleted file mode 100644 index f5db6b48daa295b60d18b311586fe87c9c7656e7..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationView.swift +++ /dev/null @@ -1,1054 +0,0 @@ -// -// LottieAnimationView.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/23/19. -// - -import QuartzCore - -// MARK: - LottieBackgroundBehavior - -/// Describes the behavior of an AnimationView when the app is moved to the background. -public enum LottieBackgroundBehavior { - /// Stop the animation and reset it to the beginning of its current play time. The completion block is called. - case stop - - /// Pause the animation in its current state. The completion block is called. - case pause - - /// Pause the animation and restart it when the application moves to the foreground. - /// The completion block is stored and called when the animation completes. - /// - This is the default when using the Main Thread rendering engine. - case pauseAndRestore - - /// Stops the animation and sets it to the end of its current play time. The completion block is called. - case forceFinish - - /// The animation continues playing in the background. - /// - This is the default when using the Core Animation rendering engine. - /// Playing an animation using the Core Animation engine doesn't come with any CPU overhead, - /// so using `.continuePlaying` avoids the need to stop and then resume the animation - /// (which does come with some CPU overhead). - /// - This mode should not be used with the Main Thread rendering engine. - case continuePlaying - - // MARK: Public - - /// The default background behavior, based on the rendering engine being used to play the animation. - /// - Playing an animation using the Main Thread rendering engine comes with CPU overhead, - /// so the animation should be paused or stopped when the `LottieAnimationView` is not visible. - /// - Playing an animation using the Core Animation rendering engine does not come with any - /// CPU overhead, so these animations do not need to be paused in the background. - public static func `default`(for renderingEngine: RenderingEngine) -> LottieBackgroundBehavior { - switch renderingEngine { - case .mainThread: - return .pauseAndRestore - case .coreAnimation: - return .continuePlaying - } - } -} - -// MARK: - LottieLoopMode - -/// Defines animation loop behavior -public enum LottieLoopMode: Hashable { - /// Animation is played once then stops. - case playOnce - /// Animation will loop from beginning to end until stopped. - case loop - /// Animation will play forward, then backwards and loop until stopped. - case autoReverse - /// Animation will loop from beginning to end up to defined amount of times. - case `repeat`(Float) - /// Animation will play forward, then backwards a defined amount of times. - case repeatBackwards(Float) -} - -// MARK: Equatable - -extension LottieLoopMode: Equatable { - public static func == (lhs: LottieLoopMode, rhs: LottieLoopMode) -> Bool { - switch (lhs, rhs) { - case (.repeat(let lhsAmount), .repeat(let rhsAmount)), - (.repeatBackwards(let lhsAmount), .repeatBackwards(let rhsAmount)): - return lhsAmount == rhsAmount - case (.playOnce, .playOnce), - (.loop, .loop), - (.autoReverse, .autoReverse): - return true - default: - return false - } - } -} - -// MARK: - LottieAnimationView - -/// A UIView subclass for rendering Lottie animations. -/// - Also available as a SwiftUI view (`LottieView`) and a CALayer subclass (`LottieAnimationLayer`) -@IBDesignable -open class LottieAnimationView: LottieAnimationViewBase { - - // MARK: Lifecycle - - // MARK: - Public (Initializers) - - /// Initializes an AnimationView with an animation. - public init( - animation: LottieAnimation?, - imageProvider: AnimationImageProvider? = nil, - textProvider: AnimationKeypathTextProvider = DefaultTextProvider(), - fontProvider: AnimationFontProvider = DefaultFontProvider(), - configuration: LottieConfiguration = .shared, - logger: LottieLogger = .shared) - { - lottieAnimationLayer = LottieAnimationLayer( - animation: animation, - imageProvider: imageProvider, - textProvider: textProvider, - fontProvider: fontProvider, - configuration: configuration, - logger: logger) - self.logger = logger - super.init(frame: .zero) - commonInit() - if let animation { - frame = animation.bounds - } - } - - /// Initializes an AnimationView with a .lottie file. - public init( - dotLottie: DotLottieFile?, - animationId: String? = nil, - textProvider: AnimationKeypathTextProvider = DefaultTextProvider(), - fontProvider: AnimationFontProvider = DefaultFontProvider(), - configuration: LottieConfiguration = .shared, - logger: LottieLogger = .shared) - { - lottieAnimationLayer = LottieAnimationLayer( - dotLottie: dotLottie, - animationId: animationId, - textProvider: textProvider, - fontProvider: fontProvider, - configuration: configuration, - logger: logger) - self.logger = logger - super.init(frame: .zero) - commonInit() - if let animation { - frame = animation.bounds - } - } - - public init( - configuration: LottieConfiguration = .shared, - logger: LottieLogger = .shared) - { - lottieAnimationLayer = LottieAnimationLayer(configuration: configuration, logger: logger) - self.logger = logger - super.init(frame: .zero) - commonInit() - } - - public override init(frame: CGRect) { - lottieAnimationLayer = LottieAnimationLayer( - animation: nil, - imageProvider: BundleImageProvider(bundle: Bundle.main, searchPath: nil), - textProvider: DefaultTextProvider(), - fontProvider: DefaultFontProvider(), - configuration: .shared, - logger: .shared) - logger = .shared - super.init(frame: frame) - commonInit() - } - - required public init?(coder aDecoder: NSCoder) { - lottieAnimationLayer = LottieAnimationLayer( - animation: nil, - imageProvider: BundleImageProvider(bundle: Bundle.main, searchPath: nil), - textProvider: DefaultTextProvider(), - fontProvider: DefaultFontProvider(), - configuration: .shared, - logger: .shared) - logger = .shared - super.init(coder: aDecoder) - commonInit() - } - - convenience init( - animationSource: LottieAnimationSource?, - imageProvider: AnimationImageProvider? = nil, - textProvider: AnimationKeypathTextProvider = DefaultTextProvider(), - fontProvider: AnimationFontProvider = DefaultFontProvider(), - configuration: LottieConfiguration = .shared, - logger: LottieLogger = .shared) - { - switch animationSource { - case .lottieAnimation(let animation): - self.init( - animation: animation, - imageProvider: imageProvider, - textProvider: textProvider, - fontProvider: fontProvider, - configuration: configuration, - logger: logger) - - case .dotLottieFile(let dotLottieFile): - self.init( - dotLottie: dotLottieFile, - textProvider: textProvider, - fontProvider: fontProvider, - configuration: configuration, - logger: logger) - - case nil: - self.init( - animation: nil, - imageProvider: imageProvider, - textProvider: textProvider, - fontProvider: fontProvider, - configuration: configuration, - logger: logger) - } - } - - // MARK: Open - - /// Applies the given `LottiePlaybackMode` to this layer. - /// - Parameter completion: A closure that is called after - /// an animation triggered by this method completes. - open func play(_ mode: LottiePlaybackMode.PlaybackMode, completion: LottieCompletionBlock? = nil) { - lottieAnimationLayer.play(mode, completion: completion) - } - - /// Plays the animation from its current state to the end. - /// - /// - Parameter completion: An optional completion closure to be called when the animation completes playing. - open func play(completion: LottieCompletionBlock? = nil) { - lottieAnimationLayer.play(completion: completion) - } - - /// Plays the animation from a progress (0-1) to a progress (0-1). - /// - /// - Parameter fromProgress: The start progress of the animation. If `nil` the animation will start at the current progress. - /// - Parameter toProgress: The end progress of the animation. - /// - Parameter loopMode: The loop behavior of the animation. If `nil` the view's `loopMode` property will be used. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - fromProgress: AnimationProgressTime? = nil, - toProgress: AnimationProgressTime, - loopMode: LottieLoopMode? = nil, - completion: LottieCompletionBlock? = nil) - { - lottieAnimationLayer.play(fromProgress: fromProgress, toProgress: toProgress, loopMode: loopMode, completion: completion) - } - - /// Plays the animation from a start frame to an end frame in the animation's framerate. - /// - /// - Parameter fromFrame: The start frame of the animation. If `nil` the animation will start at the current frame. - /// - Parameter toFrame: The end frame of the animation. - /// - Parameter loopMode: The loop behavior of the animation. If `nil` the view's `loopMode` property will be used. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - fromFrame: AnimationFrameTime? = nil, - toFrame: AnimationFrameTime, - loopMode: LottieLoopMode? = nil, - completion: LottieCompletionBlock? = nil) - { - lottieAnimationLayer.play(fromFrame: fromFrame, toFrame: toFrame, loopMode: loopMode, completion: completion) - } - - /// Plays the animation from a named marker to another marker. - /// - /// Markers are point in time that are encoded into the Animation data and assigned - /// a name. - /// - /// NOTE: If markers are not found the play command will exit. - /// - /// - Parameter fromMarker: The start marker for the animation playback. If `nil` the - /// animation will start at the current progress. - /// - Parameter toMarker: The end marker for the animation playback. - /// - Parameter playEndMarkerFrame: A flag to determine whether or not to play the frame of the end marker. If the - /// end marker represents the end of the section to play, it should be to true. If the provided end marker - /// represents the beginning of the next section, it should be false. - /// - Parameter loopMode: The loop behavior of the animation. If `nil` the view's `loopMode` property will be used. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - fromMarker: String? = nil, - toMarker: String, - playEndMarkerFrame: Bool = true, - loopMode: LottieLoopMode? = nil, - completion: LottieCompletionBlock? = nil) - { - lottieAnimationLayer.play( - fromMarker: fromMarker, - toMarker: toMarker, - playEndMarkerFrame: playEndMarkerFrame, - loopMode: loopMode, - completion: completion) - } - - /// Plays the animation from a named marker to the end of the marker's duration. - /// - /// A marker is a point in time with an associated duration that is encoded into the - /// animation data and assigned a name. - /// - /// NOTE: If marker is not found the play command will exit. - /// - /// - Parameter marker: The start marker for the animation playback. - /// - Parameter loopMode: The loop behavior of the animation. If `nil` the view's `loopMode` property will be used. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - marker: String, - loopMode: LottieLoopMode? = nil, - completion: LottieCompletionBlock? = nil) - { - lottieAnimationLayer.play(marker: marker, loopMode: loopMode, completion: completion) - } - - /// Plays the given markers sequentially in order. - /// - /// A marker is a point in time with an associated duration that is encoded into the - /// animation data and assigned a name. Multiple markers can be played sequentially - /// to create programmable animations. - /// - /// If a marker is not found, it will be skipped. - /// - /// If a marker doesn't have a duration value, it will play with a duration of 0 - /// (effectively being skipped). - /// - /// If another animation is played (by calling any `play` method) while this - /// marker sequence is playing, the marker sequence will be cancelled. - /// - /// - Parameter markers: The list of markers to play sequentially. - /// - Parameter completion: An optional completion closure to be called when the animation stops. - open func play( - markers: [String], - completion: LottieCompletionBlock? = nil) - { - lottieAnimationLayer.play(markers: markers, completion: completion) - } - - /// Stops the animation and resets the view to its start frame. - /// - /// The completion closure will be called with `false` - open func stop() { - lottieAnimationLayer.stop() - } - - /// Pauses the animation in its current state. - /// - /// The completion closure will be called with `false` - open func pause() { - lottieAnimationLayer.pause() - } - - @available(*, deprecated, renamed: "setPlaybackMode(_:completion:)", message: "Will be removed in a future major release.") - open func play( - _ playbackMode: LottiePlaybackMode, - animationCompletionHandler: LottieCompletionBlock? = nil) - { - lottieAnimationLayer.setPlaybackMode(playbackMode, completion: animationCompletionHandler) - } - - /// Applies the given `LottiePlaybackMode` to this layer. - /// - Parameter completion: A closure that is called after - /// an animation triggered by this method completes. - open func setPlaybackMode( - _ playbackMode: LottiePlaybackMode, - completion: LottieCompletionBlock? = nil) - { - lottieAnimationLayer.setPlaybackMode(playbackMode, completion: completion) - } - - // MARK: Public - - /// Whether or not transform and position changes of the view should animate alongside - /// any existing animation context. - /// - Defaults to `true` which will grab the current animation context and animate position and - /// transform changes matching the current context's curve and duration. - /// `false` will cause transform and position changes to happen unanimated - public var animateLayoutChangesWithCurrentCoreAnimationContext = true - - /// The configuration that this `LottieAnimationView` uses when playing its animation - public var configuration: LottieConfiguration { - get { lottieAnimationLayer.configuration } - set { lottieAnimationLayer.configuration = newValue } - } - - /// Value Providers that have been registered using `setValueProvider(_:keypath:)` - public var valueProviders: [AnimationKeypath: AnyValueProvider] { - lottieAnimationLayer.valueProviders - } - - /// Describes the behavior of an AnimationView when the app is moved to the background. - /// - /// The default for the Main Thread animation engine is `pause`, - /// which pauses the animation when the application moves to - /// the background. This prevents the animation from consuming CPU - /// resources when not on-screen. The completion block is called with - /// `false` for completed. - /// - /// The default for the Core Animation engine is `continuePlaying`, - /// since the Core Animation engine does not have any CPU overhead. - public var backgroundBehavior: LottieBackgroundBehavior { - get { lottieAnimationLayer.backgroundBehavior } - set { lottieAnimationLayer.backgroundBehavior = newValue } - } - - /// Sets the animation backing the animation view. Setting this will clear the - /// view's contents, completion blocks and current state. The new animation will - /// be loaded up and set to the beginning of its timeline. - public var animation: LottieAnimation? { - get { lottieAnimationLayer.animation } - set { lottieAnimationLayer.animation = newValue } - } - - /// A closure that is called when `self.animation` is loaded. When setting this closure, - /// it is called immediately if `self.animation` is non-nil. - /// - /// When initializing a `LottieAnimationView`, the animation will either be loaded - /// synchronously (when loading a `LottieAnimation` from a .json file on disk) - /// or asynchronously (when loading a `DotLottieFile` from disk, or downloading - /// an animation from a URL). This closure is called in both cases once the - /// animation is loaded and applied, so can be a useful way to configure this - /// `LottieAnimationView` regardless of which initializer was used. For example: - /// - /// ``` - /// let animationView: LottieAnimationView - /// - /// if loadDotLottieFile { - /// // Loads the .lottie file asynchronously - /// animationView = LottieAnimationView(dotLottieName: "animation") - /// } else { - /// // Loads the .json file synchronously - /// animationView = LottieAnimationView(name: "animation") - /// } - /// - /// animationView.animationLoaded = { animationView, animation in - /// // If using a .lottie file, this is called once the file finishes loading. - /// // If using a .json file, this is called immediately (since the animation is loaded synchronously). - /// animationView.play() - /// } - /// ``` - public var animationLoaded: ((_ animationView: LottieAnimationView, _ animation: LottieAnimation) -> Void)? { - didSet { - if let animation { - animationLoaded?(self, animation) - } - } - } - - /// Sets the image provider for the animation view. An image provider provides the - /// animation with its required image data. - /// - /// Setting this will cause the animation to reload its image contents. - public var imageProvider: AnimationImageProvider { - get { lottieAnimationLayer.imageProvider } - set { lottieAnimationLayer.imageProvider = newValue } - } - - /// Sets the text provider for animation view. A text provider provides the - /// animation with values for text layers - public var textProvider: AnimationKeypathTextProvider { - get { lottieAnimationLayer.textProvider } - set { lottieAnimationLayer.textProvider = newValue } - } - - /// Sets the text provider for animation view. A text provider provides the - /// animation with values for text layers - public var fontProvider: AnimationFontProvider { - get { lottieAnimationLayer.fontProvider } - set { lottieAnimationLayer.fontProvider = newValue } - } - - /// Whether or not the animation is masked to the bounds. Defaults to true. - public var maskAnimationToBounds: Bool { - get { lottieAnimationLayer.maskAnimationToBounds } - set { lottieAnimationLayer.maskAnimationToBounds = newValue } - } - - /// Returns `true` if the animation is currently playing. - public var isAnimationPlaying: Bool { - lottieAnimationLayer.isAnimationPlaying - } - - /// Returns `true` if the animation will start playing when this view is added to a window. - public var isAnimationQueued: Bool { - lottieAnimationLayer.hasAnimationContext && waitingToPlayAnimation - } - - /// Sets the loop behavior for `play` calls. Defaults to `playOnce` - public var loopMode: LottieLoopMode { - get { lottieAnimationLayer.loopMode } - set { lottieAnimationLayer.loopMode = newValue } - } - - /// When `true` the animation view will rasterize its contents when not animating. - /// Rasterizing will improve performance of static animations. - /// - /// Note: this will not produce crisp results at resolutions above the animations natural resolution. - /// - /// Defaults to `false` - public var shouldRasterizeWhenIdle: Bool { - get { lottieAnimationLayer.shouldRasterizeWhenIdle } - set { lottieAnimationLayer.shouldRasterizeWhenIdle = newValue } - } - - /// Sets the current animation time with a Progress Time - /// - /// Note: Setting this will stop the current animation, if any. - /// Note 2: If `animation` is nil, setting this will fallback to 0 - public var currentProgress: AnimationProgressTime { - get { lottieAnimationLayer.currentProgress } - set { lottieAnimationLayer.currentProgress = newValue } - } - - /// Sets the current animation time with a time in seconds. - /// - /// Note: Setting this will stop the current animation, if any. - /// Note 2: If `animation` is nil, setting this will fallback to 0 - public var currentTime: TimeInterval { - get { lottieAnimationLayer.currentTime } - set { lottieAnimationLayer.currentTime = newValue } - } - - /// Sets the current animation time with a frame in the animations framerate. - /// - /// Note: Setting this will stop the current animation, if any. - public var currentFrame: AnimationFrameTime { - get { lottieAnimationLayer.currentFrame } - set { lottieAnimationLayer.currentFrame = newValue } - } - - /// Returns the current animation frame while an animation is playing. - public var realtimeAnimationFrame: AnimationFrameTime { - lottieAnimationLayer.realtimeAnimationFrame - } - - /// Returns the current animation frame while an animation is playing. - public var realtimeAnimationProgress: AnimationProgressTime { - lottieAnimationLayer.realtimeAnimationProgress - } - - /// Sets the speed of the animation playback. Defaults to 1 - public var animationSpeed: CGFloat { - get { lottieAnimationLayer.animationSpeed } - set { lottieAnimationLayer.animationSpeed = newValue } - } - - /// When `true` the animation will play back at the framerate encoded in the - /// `LottieAnimation` model. When `false` the animation will play at the framerate - /// of the device. - /// - /// Defaults to false - public var respectAnimationFrameRate: Bool { - get { lottieAnimationLayer.respectAnimationFrameRate } - set { lottieAnimationLayer.respectAnimationFrameRate = newValue } - } - - /// Controls the cropping of an Animation. Setting this property will crop the animation - /// to the current views bounds by the viewport frame. The coordinate space is specified - /// in the animation's coordinate space. - /// - /// Animatable. - public var viewportFrame: CGRect? { - didSet { - // This is really ugly, but is needed to trigger a layout pass within an animation block. - // Typically this happens automatically, when layout objects are UIView based. - // The animation layer is a CALayer which will not implicitly grab the animation - // duration of a UIView animation block. - // - // By setting bounds and then resetting bounds the UIView animation block's - // duration and curve are captured and added to the layer. This is used in the - // layout block to animate the animationLayer's position and size. - let rect = bounds - self.bounds = CGRect.zero - self.bounds = rect - self.setNeedsLayout() - } - } - - override public var intrinsicContentSize: CGSize { - if let animation = lottieAnimationLayer.animation { - return animation.bounds.size - } - return .zero - } - - /// The rendering engine currently being used by this view. - /// - This will only be `nil` in cases where the configuration is `automatic` - /// but a `RootAnimationLayer` hasn't been constructed yet - public var currentRenderingEngine: RenderingEngine? { - lottieAnimationLayer.currentRenderingEngine - } - - /// The current `LottiePlaybackMode` that is being used - public var currentPlaybackMode: LottiePlaybackMode? { - lottieAnimationLayer.currentPlaybackMode - } - - /// Whether or not the Main Thread rendering engine should use `forceDisplayUpdate()` - /// when rendering each individual frame. - /// - The main thread rendering engine implements optimizations to decrease the amount - /// of properties that have to be re-rendered on each frame. There are some cases - /// where this can result in bugs / incorrect behavior, so we allow it to be disabled. - /// - Forcing a full render on every frame will decrease performance, and is not recommended - /// except as a workaround to a bug in the main thread rendering engine. - /// - Has no effect when using the Core Animation rendering engine. - public var mainThreadRenderingEngineShouldForceDisplayUpdateOnEachFrame: Bool { - get { lottieAnimationLayer.mainThreadRenderingEngineShouldForceDisplayUpdateOnEachFrame } - set { lottieAnimationLayer.mainThreadRenderingEngineShouldForceDisplayUpdateOnEachFrame = newValue } - } - - /// Sets the lottie file backing the animation view. Setting this will clear the - /// view's contents, completion blocks and current state. The new animation will - /// be loaded up and set to the beginning of its timeline. - /// The loopMode, animationSpeed and imageProvider will be set according - /// to lottie file settings - /// - Parameters: - /// - animationId: Internal animation id to play. Optional - /// Defaults to play first animation in file. - /// - dotLottieFile: Lottie file to play - public func loadAnimation( - _ animationId: String? = nil, - from dotLottieFile: DotLottieFile) - { - lottieAnimationLayer.loadAnimation(animationId, from: dotLottieFile) - } - - /// Sets the lottie file backing the animation view. Setting this will clear the - /// view's contents, completion blocks and current state. The new animation will - /// be loaded up and set to the beginning of its timeline. - /// The loopMode, animationSpeed and imageProvider will be set according - /// to lottie file settings - /// - Parameters: - /// - atIndex: Internal animation index to play. Optional - /// Defaults to play first animation in file. - /// - dotLottieFile: Lottie file to play - public func loadAnimation( - atIndex index: Int, - from dotLottieFile: DotLottieFile) - { - lottieAnimationLayer.loadAnimation(atIndex: index, from: dotLottieFile) - } - - /// Reloads the images supplied to the animation from the `imageProvider` - public func reloadImages() { - lottieAnimationLayer.reloadImages() - } - - /// Forces the LottieAnimationView to redraw its contents. - public func forceDisplayUpdate() { - lottieAnimationLayer.forceDisplayUpdate() - } - - /// Sets a ValueProvider for the specified keypath. The value provider will be set - /// on all properties that match the keypath. - /// - /// Nearly all properties of a Lottie animation can be changed at runtime using a - /// combination of `Animation Keypaths` and `Value Providers`. - /// Setting a ValueProvider on a keypath will cause the animation to update its - /// contents and read the new Value Provider. - /// - /// A value provider provides a typed value on a frame by frame basis. - /// - /// - Parameter valueProvider: The new value provider for the properties. - /// - Parameter keypath: The keypath used to search for properties. - /// - /// Example: - /// ``` - /// /// A keypath that finds the color value for all `Fill 1` nodes. - /// let fillKeypath = AnimationKeypath(keypath: "**.Fill 1.Color") - /// /// A Color Value provider that returns a reddish color. - /// let redValueProvider = ColorValueProvider(Color(r: 1, g: 0.2, b: 0.3, a: 1)) - /// /// Set the provider on the animationView. - /// animationView.setValueProvider(redValueProvider, keypath: fillKeypath) - /// ``` - public func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) { - lottieAnimationLayer.setValueProvider(valueProvider, keypath: keypath) - } - - /// Reads the value of a property specified by the Keypath. - /// Returns nil if no property is found. - /// - /// - Parameter for: The keypath used to search for the property. - /// - Parameter atFrame: The Frame Time of the value to query. If nil then the current frame is used. - public func getValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? { - lottieAnimationLayer.getValue(for: keypath, atFrame: atFrame) - } - - /// Reads the original value of a property specified by the Keypath. - /// This will ignore any value providers and can be useful when implementing a value providers that makes change to the original value from the animation. - /// Returns nil if no property is found. - /// - /// - Parameter for: The keypath used to search for the property. - /// - Parameter atFrame: The Frame Time of the value to query. If nil then the current frame is used. - public func getOriginalValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? { - lottieAnimationLayer.getOriginalValue(for: keypath, atFrame: atFrame) - } - - /// Logs all child keypaths. - /// Logs the result of `allHierarchyKeypaths()` to the `LottieLogger`. - public func logHierarchyKeypaths() { - lottieAnimationLayer.logHierarchyKeypaths() - } - - /// Computes and returns a list of all child keypaths in the current animation. - /// The returned list is the same as the log output of `logHierarchyKeypaths()` - public func allHierarchyKeypaths() -> [String] { - lottieAnimationLayer.allHierarchyKeypaths() - } - - /// Searches for the nearest child layer to the first Keypath and adds the subview - /// to that layer. The subview will move and animate with the child layer. - /// Furthermore the subview will be in the child layers coordinate space. - /// - /// Note: if no layer is found for the keypath, then nothing happens. - /// - /// - Parameter subview: The subview to add to the found animation layer. - /// - Parameter keypath: The keypath used to find the animation layer. - /// - /// Example: - /// ``` - /// /// A keypath that finds `Layer 1` - /// let layerKeypath = AnimationKeypath(keypath: "Layer 1") - /// - /// /// Wrap the custom view in an `AnimationSubview` - /// let subview = AnimationSubview() - /// subview.addSubview(customView) - /// - /// /// Set the provider on the animationView. - /// animationView.addSubview(subview, forLayerAt: layerKeypath) - /// ``` - public func addSubview(_ subview: AnimationSubview, forLayerAt keypath: AnimationKeypath) { - guard let sublayer = lottieAnimationLayer.rootAnimationLayer?.layer(for: keypath) else { - return - } - setNeedsLayout() - layoutIfNeeded() - lottieAnimationLayer.forceDisplayUpdate() - addSubview(subview) - if let subViewLayer = subview.viewLayer { - sublayer.addSublayer(subViewLayer) - } - } - - /// Converts a CGRect from the LottieAnimationView's coordinate space into the - /// coordinate space of the layer found at Keypath. - /// - /// If no layer is found, nil is returned - /// - /// - Parameter rect: The CGRect to convert. - /// - Parameter toLayerAt: The keypath used to find the layer. - public func convert(_ rect: CGRect, toLayerAt keypath: AnimationKeypath?) -> CGRect? { - let convertedRect = lottieAnimationLayer.convert(rect, toLayerAt: keypath) - setNeedsLayout() - layoutIfNeeded() - return convertedRect - } - - /// Converts a CGPoint from the LottieAnimationView's coordinate space into the - /// coordinate space of the layer found at Keypath. - /// - /// If no layer is found, nil is returned - /// - /// - Parameter point: The CGPoint to convert. - /// - Parameter toLayerAt: The keypath used to find the layer. - public func convert(_ point: CGPoint, toLayerAt keypath: AnimationKeypath?) -> CGPoint? { - let convertedRect = lottieAnimationLayer.convert(point, toLayerAt: keypath) - setNeedsLayout() - layoutIfNeeded() - return convertedRect - } - - /// Sets the enabled state of all animator nodes found with the keypath search. - /// This can be used to interactively enable / disable parts of the animation. - /// - /// - Parameter isEnabled: When true the animator nodes affect the rendering tree. When false the node is removed from the tree. - /// - Parameter keypath: The keypath used to find the node(s). - public func setNodeIsEnabled(isEnabled: Bool, keypath: AnimationKeypath) { - lottieAnimationLayer.setNodeIsEnabled(isEnabled: isEnabled, keypath: keypath) - } - - /// Markers are a way to describe a point in time by a key name. - /// - /// Markers are encoded into animation JSON. By using markers a designer can mark - /// playback points for a developer to use without having to worry about keeping - /// track of animation frames. If the animation file is updated, the developer - /// does not need to update playback code. - /// - /// Returns the Progress Time for the marker named. Returns nil if no marker found. - public func progressTime(forMarker named: String) -> AnimationProgressTime? { - lottieAnimationLayer.progressTime(forMarker: named) - } - - /// Markers are a way to describe a point in time by a key name. - /// - /// Markers are encoded into animation JSON. By using markers a designer can mark - /// playback points for a developer to use without having to worry about keeping - /// track of animation frames. If the animation file is updated, the developer - /// does not need to update playback code. - /// - /// Returns the Frame Time for the marker named. Returns nil if no marker found. - public func frameTime(forMarker named: String) -> AnimationFrameTime? { - lottieAnimationLayer.frameTime(forMarker: named) - } - - /// Markers are a way to describe a point in time and a duration by a key name. - /// - /// Markers are encoded into animation JSON. By using markers a designer can mark - /// playback points for a developer to use without having to worry about keeping - /// track of animation frames. If the animation file is updated, the developer - /// does not need to update playback code. - /// - /// - Returns: The duration frame time for the marker, or `nil` if no marker found. - public func durationFrameTime(forMarker named: String) -> AnimationFrameTime? { - lottieAnimationLayer.durationFrameTime(forMarker: named) - } - - // MARK: Internal - - // The backing CALayer for this animation view. - let lottieAnimationLayer: LottieAnimationLayer - - var animationLayer: RootAnimationLayer? { - lottieAnimationLayer.rootAnimationLayer - } - - /// Set animation name from Interface Builder - @IBInspectable var animationName: String? { - didSet { - self.lottieAnimationLayer.animation = animationName.flatMap { LottieAnimation.named($0, animationCache: nil) - } - } - } - - override func commonInit() { - super.commonInit() - lottieAnimationLayer.screenScale = screenScale - viewLayer?.addSublayer(lottieAnimationLayer) - - lottieAnimationLayer.animationLoaded = { [weak self] _, animation in - guard let self else { return } - self.animationLoaded?(self, animation) - self.invalidateIntrinsicContentSize() - self.setNeedsLayout() - } - - lottieAnimationLayer.animationLayerDidLoad = { [weak self] _, _ in - guard let self else { return } - self.invalidateIntrinsicContentSize() - self.setNeedsLayout() - } - } - - override func layoutAnimation() { - guard let animation = lottieAnimationLayer.animation, let animationLayer = lottieAnimationLayer.animationLayer else { return } - - var position = animation.bounds.center - let xform: CATransform3D - var shouldForceUpdates = false - - if let viewportFrame { - shouldForceUpdates = contentMode == .redraw - - let compAspect = viewportFrame.size.width / viewportFrame.size.height - let viewAspect = bounds.size.width / bounds.size.height - let dominantDimension = compAspect > viewAspect ? bounds.size.width : bounds.size.height - let compDimension = compAspect > viewAspect ? viewportFrame.size.width : viewportFrame.size.height - let scale = dominantDimension / compDimension - - let viewportOffset = animation.bounds.center - viewportFrame.center - xform = CATransform3DTranslate(CATransform3DMakeScale(scale, scale, 1), viewportOffset.x, viewportOffset.y, 0) - position = bounds.center - } else { - switch contentMode { - case .scaleToFill: - position = bounds.center - xform = CATransform3DMakeScale( - bounds.size.width / animation.size.width, - bounds.size.height / animation.size.height, - 1) - case .scaleAspectFit: - position = bounds.center - let compAspect = animation.size.width / animation.size.height - let viewAspect = bounds.size.width / bounds.size.height - let dominantDimension = compAspect > viewAspect ? bounds.size.width : bounds.size.height - let compDimension = compAspect > viewAspect ? animation.size.width : animation.size.height - let scale = dominantDimension / compDimension - xform = CATransform3DMakeScale(scale, scale, 1) - case .scaleAspectFill: - position = bounds.center - let compAspect = animation.size.width / animation.size.height - let viewAspect = bounds.size.width / bounds.size.height - let scaleWidth = compAspect < viewAspect - let dominantDimension = scaleWidth ? bounds.size.width : bounds.size.height - let compDimension = scaleWidth ? animation.size.width : animation.size.height - let scale = dominantDimension / compDimension - xform = CATransform3DMakeScale(scale, scale, 1) - case .redraw: - shouldForceUpdates = true - xform = CATransform3DIdentity - case .center: - position = bounds.center - xform = CATransform3DIdentity - case .top: - position.x = bounds.center.x - xform = CATransform3DIdentity - case .bottom: - position.x = bounds.center.x - position.y = bounds.maxY - animation.bounds.midY - xform = CATransform3DIdentity - case .left: - position.y = bounds.center.y - xform = CATransform3DIdentity - case .right: - position.y = bounds.center.y - position.x = bounds.maxX - animation.bounds.midX - xform = CATransform3DIdentity - case .topLeft: - xform = CATransform3DIdentity - case .topRight: - position.x = bounds.maxX - animation.bounds.midX - xform = CATransform3DIdentity - case .bottomLeft: - position.y = bounds.maxY - animation.bounds.midY - xform = CATransform3DIdentity - case .bottomRight: - position.x = bounds.maxX - animation.bounds.midX - position.y = bounds.maxY - animation.bounds.midY - xform = CATransform3DIdentity - - #if canImport(UIKit) - @unknown default: - logger.assertionFailure("unsupported contentMode: \(contentMode.rawValue)") - xform = CATransform3DIdentity - #endif - } - } - - // UIView Animation does not implicitly set CAAnimation time or timing fuctions. - // If layout is changed in an animation we must get the current animation duration - // and timing function and then manually create a CAAnimation to match the UIView animation. - // If layout is changed without animation, explicitly set animation duration to 0.0 - // inside CATransaction to avoid unwanted artifacts. - /// Check if any animation exist on the view's layer, and match it. - if - let key = lottieAnimationLayer.animationKeys()?.first, - let animation = lottieAnimationLayer.animation(forKey: key), - animateLayoutChangesWithCurrentCoreAnimationContext - { - // The layout is happening within an animation block. Grab the animation data. - - let positionKey = "LayoutPositionAnimation" - let transformKey = "LayoutTransformAnimation" - animationLayer.removeAnimation(forKey: positionKey) - animationLayer.removeAnimation(forKey: transformKey) - - let positionAnimation = animation.copy() as? CABasicAnimation ?? CABasicAnimation(keyPath: "position") - positionAnimation.keyPath = "position" - positionAnimation.isAdditive = false - positionAnimation.fromValue = (animationLayer.presentation() ?? animationLayer).position - positionAnimation.toValue = position - positionAnimation.isRemovedOnCompletion = true - - let xformAnimation = animation.copy() as? CABasicAnimation ?? CABasicAnimation(keyPath: "transform") - xformAnimation.keyPath = "transform" - xformAnimation.isAdditive = false - xformAnimation.fromValue = (animationLayer.presentation() ?? animationLayer).transform - xformAnimation.toValue = xform - xformAnimation.isRemovedOnCompletion = true - - animationLayer.position = position - animationLayer.transform = xform - animationLayer.anchorPoint = lottieAnimationLayer.anchorPoint - animationLayer.add(positionAnimation, forKey: positionKey) - animationLayer.add(xformAnimation, forKey: transformKey) - } else { - // In performance tests, we have to wrap the animation view setup - // in a `CATransaction` in order for the layers to be deallocated at - // the correct time. The `CATransaction`s in this method interfere - // with the ones managed by the performance test, and aren't actually - // necessary in a headless environment, so we disable them. - if TestHelpers.performanceTestsAreRunning { - animationLayer.position = position - animationLayer.transform = xform - } else { - CATransaction.begin() - CATransaction.setAnimationDuration(0.0) - CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear)) - animationLayer.position = position - animationLayer.transform = xform - CATransaction.commit() - } - } - - if shouldForceUpdates { - lottieAnimationLayer.forceDisplayUpdate() - } - } - - func updateRasterizationState() { - lottieAnimationLayer.updateRasterizationState() - } - - /// Updates the animation frame. Does not affect any current animations - func updateAnimationFrame(_ newFrame: CGFloat) { - lottieAnimationLayer.updateAnimationFrame(newFrame) - } - - @objc - override func animationWillMoveToBackground() { - updateAnimationForBackgroundState() - } - - @objc - override func animationWillEnterForeground() { - updateAnimationForForegroundState() - } - - override func animationMovedToWindow() { - /// Don't update any state if the `superview` is `nil` - /// When A viewA owns superViewB, it removes the superViewB from the window. At this point, viewA still owns superViewB and triggers the viewA method: -didmovetowindow - guard superview != nil else { return } - - if window != nil { - updateAnimationForForegroundState() - } else { - updateAnimationForBackgroundState() - } - } - - func updateInFlightAnimation() { - lottieAnimationLayer.updateInFlightAnimation() - } - - func loadAnimation(_ animationSource: LottieAnimationSource?) { - lottieAnimationLayer.loadAnimation(animationSource) - } - - // MARK: Fileprivate - - fileprivate var waitingToPlayAnimation = false - - fileprivate func updateAnimationForBackgroundState() { - lottieAnimationLayer.updateAnimationForBackgroundState() - } - - fileprivate func updateAnimationForForegroundState() { - let wasWaitingToPlayAnimation = waitingToPlayAnimation - if waitingToPlayAnimation { - waitingToPlayAnimation = false - } - lottieAnimationLayer.updateAnimationForForegroundState(wasWaitingToPlayAnimation: wasWaitingToPlayAnimation) - } - - // MARK: Private - - private let logger: LottieLogger -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationViewInitializers.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationViewInitializers.swift deleted file mode 100644 index a2bc01dbd85b03e7497f2da6cd4ad84e9e800096..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieAnimationViewInitializers.swift +++ /dev/null @@ -1,222 +0,0 @@ -// -// AnimationViewInitializers.swift -// lottie-swift-iOS -// -// Created by Brandon Withrow on 2/6/19. -// - -import Foundation - -extension LottieAnimationView { - - // MARK: Lifecycle - - /// Loads a Lottie animation from a JSON file in the supplied bundle. - /// - /// - Parameter name: The string name of the lottie animation with no file extension provided. - /// - Parameter bundle: The bundle in which the animation is located. Defaults to the Main bundle. - /// - Parameter subdirectory: A subdirectory in the bundle in which the animation is located. Optional. - /// - Parameter imageProvider: An image provider for the animation's image data. - /// If none is supplied Lottie will search in the supplied bundle for images. - public convenience init( - name: String, - bundle: Bundle = Bundle.main, - subdirectory: String? = nil, - imageProvider: AnimationImageProvider? = nil, - animationCache: AnimationCacheProvider? = LottieAnimationCache.shared, - configuration: LottieConfiguration = .shared) - { - let animation = LottieAnimation.named(name, bundle: bundle, subdirectory: subdirectory, animationCache: animationCache) - let provider = imageProvider ?? BundleImageProvider(bundle: bundle, searchPath: nil) - self.init(animation: animation, imageProvider: provider, configuration: configuration) - } - - /// Loads a Lottie animation from a JSON file in a specific path on disk. - /// - /// - Parameter name: The absolute path of the Lottie Animation. - /// - Parameter imageProvider: An image provider for the animation's image data. - /// If none is supplied Lottie will search in the supplied filepath for images. - public convenience init( - filePath: String, - imageProvider: AnimationImageProvider? = nil, - animationCache: AnimationCacheProvider? = LottieAnimationCache.shared, - configuration: LottieConfiguration = .shared) - { - let animation = LottieAnimation.filepath(filePath, animationCache: animationCache) - let provider = imageProvider ?? - FilepathImageProvider(filepath: URL(fileURLWithPath: filePath).deletingLastPathComponent().path) - self.init(animation: animation, imageProvider: provider, configuration: configuration) - } - - /// Loads a Lottie animation asynchronously from the URL - /// - /// - Parameter url: The url to load the animation from. - /// - Parameter imageProvider: An image provider for the animation's image data. - /// If none is supplied Lottie will search in the main bundle for images. - /// - Parameter closure: A closure to be called when the animation has loaded. - public convenience init( - url: URL, - imageProvider: AnimationImageProvider? = nil, - session: URLSession = .shared, - closure: @escaping LottieAnimationView.DownloadClosure, - animationCache: AnimationCacheProvider? = LottieAnimationCache.shared, - configuration: LottieConfiguration = .shared) - { - if let animationCache, let animation = animationCache.animation(forKey: url.absoluteString) { - self.init(animation: animation, imageProvider: imageProvider, configuration: configuration) - closure(nil) - } else { - self.init(animation: nil, imageProvider: imageProvider, configuration: configuration) - - LottieAnimation.loadedFrom(url: url, session: session, closure: { animation in - if let animation { - self.animation = animation - closure(nil) - } else { - closure(LottieDownloadError.downloadFailed) - } - }, animationCache: animationCache) - } - } - - /// Loads a Lottie animation from a JSON file located in the Asset catalog of the supplied bundle. - /// - Parameter name: The string name of the lottie animation in the asset catalog. - /// - Parameter bundle: The bundle in which the animation is located. - /// Defaults to the Main bundle. - /// - Parameter imageProvider: An image provider for the animation's image data. - /// If none is supplied Lottie will search in the supplied bundle for images. - public convenience init( - asset name: String, - bundle: Bundle = Bundle.main, - imageProvider: AnimationImageProvider? = nil, - animationCache: AnimationCacheProvider? = LottieAnimationCache.shared, - configuration: LottieConfiguration = .shared) - { - let animation = LottieAnimation.asset(name, bundle: bundle, animationCache: animationCache) - let provider = imageProvider ?? BundleImageProvider(bundle: bundle, searchPath: nil) - self.init(animation: animation, imageProvider: provider, configuration: configuration) - } - - // MARK: DotLottie - - /// Loads a Lottie animation from a .lottie file in the supplied bundle. - /// - /// - Parameter dotLottieName: The name of the lottie file without the lottie extension. EG "StarAnimation" - /// - Parameter bundle: The bundle in which the lottie is located. Defaults to `Bundle.main` - /// - Parameter subdirectory: A subdirectory in the bundle in which the lottie is located. Optional. - /// - Parameter animationId: Animation id to play. Optional - /// - Parameter completion: A closure that is called when the .lottie file is finished loading - /// Defaults to first animation in file - public convenience init( - dotLottieName name: String, - bundle: Bundle = Bundle.main, - subdirectory: String? = nil, - animationId: String? = nil, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache, - configuration: LottieConfiguration = .shared, - completion: ((LottieAnimationView, Error?) -> Void)? = nil) - { - self.init(dotLottie: nil, animationId: animationId, configuration: configuration) - DotLottieFile.named(name, bundle: bundle, subdirectory: subdirectory, dotLottieCache: dotLottieCache) { result in - switch result { - case .success(let dotLottieFile): - self.loadAnimation(animationId, from: dotLottieFile) - completion?(self, nil) - case .failure(let error): - completion?(self, error) - } - } - } - - /// Loads a Lottie from a .lottie file in a specific path on disk. - /// - /// - Parameter dotLottieFilePath: The absolute path of the Lottie file. - /// - Parameter animationId: Animation id to play. Optional - /// - Parameter completion: A closure that is called when the .lottie file is finished loading - /// Defaults to first animation in file - public convenience init( - dotLottieFilePath filePath: String, - animationId: String? = nil, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache, - configuration: LottieConfiguration = .shared, - completion: ((LottieAnimationView, Error?) -> Void)? = nil) - { - self.init(dotLottie: nil, animationId: animationId, configuration: configuration) - DotLottieFile.loadedFrom(filepath: filePath, dotLottieCache: dotLottieCache) { result in - switch result { - case .success(let dotLottieFile): - self.loadAnimation(animationId, from: dotLottieFile) - completion?(self, nil) - case .failure(let error): - completion?(self, error) - } - } - } - - /// Loads a Lottie file asynchronously from the URL - /// - /// - Parameter dotLottieUrl: The url to load the lottie file from. - /// - Parameter animationId: Animation id to play. Optional. Defaults to first animation in file. - /// - Parameter completion: A closure to be called when the animation has loaded. - public convenience init( - dotLottieUrl url: URL, - animationId: String? = nil, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache, - configuration: LottieConfiguration = .shared, - session: URLSession = .shared, - completion: ((LottieAnimationView, Error?) -> Void)? = nil) - { - if let dotLottieCache, let lottie = dotLottieCache.file(forKey: url.absoluteString) { - self.init(dotLottie: lottie, animationId: animationId, configuration: configuration) - completion?(self, nil) - } else { - self.init(dotLottie: nil, configuration: configuration) - DotLottieFile.loadedFrom(url: url, session: session, dotLottieCache: dotLottieCache) { result in - switch result { - case .success(let lottie): - self.loadAnimation(animationId, from: lottie) - completion?(self, nil) - case .failure(let error): - completion?(self, error) - } - } - } - } - - /// Loads a Lottie from a .lottie file located in the Asset catalog of the supplied bundle. - /// - Parameter name: The string name of the lottie file in the asset catalog. - /// - Parameter bundle: The bundle in which the file is located. Defaults to the Main bundle. - /// - Parameter animationId: Animation id to play. Optional - /// - Parameter completion: A closure that is called when the .lottie file is finished loading - /// Defaults to first animation in file - public convenience init( - dotLottieAsset name: String, - bundle: Bundle = Bundle.main, - animationId: String? = nil, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache, - configuration: LottieConfiguration = .shared, - completion: ((LottieAnimationView, Error?) -> Void)? = nil) - { - self.init(dotLottie: nil, animationId: animationId, configuration: configuration) - DotLottieFile.asset(named: name, bundle: bundle, dotLottieCache: dotLottieCache) { result in - switch result { - case .success(let dotLottieFile): - self.loadAnimation(animationId, from: dotLottieFile) - completion?(self, nil) - case .failure(let error): - completion?(self, error) - } - } - } - - // MARK: Public - - public typealias DownloadClosure = (Error?) -> Void - -} - -// MARK: - LottieDownloadError - -enum LottieDownloadError: Error { - case downloadFailed -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottiePlaybackMode.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottiePlaybackMode.swift deleted file mode 100644 index dd93a95e70c7c65b72de59ba09d412ac03bebce4..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottiePlaybackMode.swift +++ /dev/null @@ -1,260 +0,0 @@ -// Created by Cal Stephens on 8/3/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -import Foundation - -// MARK: - LottiePlaybackMode - -/// Configuration for how a Lottie animation should be played -public enum LottiePlaybackMode: Hashable { - - /// The animation is paused at the given state (e.g. paused at a specific frame) - case paused(at: PausedState) - - /// The animation is playing using the given playback mode (e.g. looping from the start to the end) - case playing(_ mode: PlaybackMode) - - @available(*, deprecated, renamed: "LottiePlaybackMode.paused(at:)", message: "Will be removed in a future major release.") - case progress(_ progress: AnimationProgressTime) - - @available(*, deprecated, renamed: "LottiePlaybackMode.paused(at:)", message: "Will be removed in a future major release.") - case frame(_ frame: AnimationFrameTime) - - @available(*, deprecated, renamed: "LottiePlaybackMode.paused(at:)", message: "Will be removed in a future major release.") - case time(_ time: TimeInterval) - - @available(*, deprecated, renamed: "LottiePlaybackMode.paused(at:)", message: "Will be removed in a future major release.") - case pause - - @available(*, deprecated, renamed: "LottiePlaybackMode.playing(_:)", message: "Will be removed in a future major release.") - case fromProgress(_ fromProgress: AnimationProgressTime?, toProgress: AnimationProgressTime, loopMode: LottieLoopMode) - - @available(*, deprecated, renamed: "LottiePlaybackMode.playing(_:)", message: "Will be removed in a future major release.") - case fromFrame(_ fromFrame: AnimationFrameTime?, toFrame: AnimationFrameTime, loopMode: LottieLoopMode) - - @available(*, deprecated, renamed: "LottiePlaybackMode.playing(_:)", message: "Will be removed in a future major release.") - case fromMarker( - _ fromMarker: String?, - toMarker: String, - playEndMarkerFrame: Bool = true, - loopMode: LottieLoopMode) - - @available(*, deprecated, renamed: "LottiePlaybackMode.playing(_:)", message: "Will be removed in a future major release.") - case marker(_ marker: String, loopMode: LottieLoopMode) - - @available(*, deprecated, renamed: "LottiePlaybackMode.playing(_:)", message: "Will be removed in a future major release.") - case markers(_ markers: [String]) - - // MARK: Public - - public enum PausedState: Hashable { - /// Any existing animation will be paused at the current frame. - case currentFrame - - /// The animation is paused at the given progress value, - /// a value between 0.0 (0% progress) and 1.0 (100% progress). - case progress(_ progress: AnimationProgressTime) - - /// The animation is paused at the given frame of the animation. - case frame(_ frame: AnimationFrameTime) - - /// The animation is paused at the given time value from the start of the animation. - case time(_ time: TimeInterval) - - /// Pauses the animation at a given marker and position - case marker(_ name: String, position: LottieMarkerPosition = .start) - } - - public enum PlaybackMode: Hashable { - /// Plays the animation from a progress (0-1) to a progress (0-1). - /// - Parameter fromProgress: The start progress of the animation. If `nil` the animation will start at the current progress. - /// - Parameter toProgress: The end progress of the animation. - /// - Parameter loopMode: The loop behavior of the animation. - case fromProgress( - _ fromProgress: AnimationProgressTime?, - toProgress: AnimationProgressTime, - loopMode: LottieLoopMode) - - /// The animation plays from the given `fromFrame` to the given `toFrame`. - /// - Parameter fromFrame: The start frame of the animation. If `nil` the animation will start at the current frame. - /// - Parameter toFrame: The end frame of the animation. - /// - Parameter loopMode: The loop behavior of the animation. - case fromFrame( - _ fromFrame: AnimationFrameTime?, - toFrame: AnimationFrameTime, - loopMode: LottieLoopMode) - - /// Plays the animation from a named marker to another marker. - /// - /// Markers are point in time that are encoded into the Animation data and assigned a name. - /// - /// NOTE: If markers are not found the play command will exit. - /// - /// - Parameter fromMarker: The start marker for the animation playback. If `nil` the - /// animation will start at the current progress. - /// - Parameter toMarker: The end marker for the animation playback. - /// - Parameter playEndMarkerFrame: A flag to determine whether or not to play the frame of the end marker. If the - /// end marker represents the end of the section to play, it should be to true. If the provided end marker - /// represents the beginning of the next section, it should be false. - /// - Parameter loopMode: The loop behavior of the animation. - case fromMarker( - _ fromMarker: String?, - toMarker: String, - playEndMarkerFrame: Bool = true, - loopMode: LottieLoopMode) - - /// Plays the animation from a named marker to the end of the marker's duration. - /// - /// A marker is a point in time with an associated duration that is encoded into the - /// animation data and assigned a name. - /// - /// NOTE: If marker is not found the play command will exit. - /// - /// - Parameter marker: The start marker for the animation playback. - /// - Parameter loopMode: The loop behavior of the animation. - case marker( - _ marker: String, - loopMode: LottieLoopMode) - - /// Plays the given markers sequentially in order. - /// - /// A marker is a point in time with an associated duration that is encoded into the - /// animation data and assigned a name. Multiple markers can be played sequentially - /// to create programmable animations. - /// - /// If a marker is not found, it will be skipped. - /// - /// If a marker doesn't have a duration value, it will play with a duration of 0 - /// (effectively being skipped). - /// - /// If another animation is played (by calling any `play` method) while this - /// marker sequence is playing, the marker sequence will be cancelled. - /// - /// - Parameter markers: The list of markers to play sequentially. - case markers(_ markers: [String]) - } - -} - -extension LottiePlaybackMode { - public static var paused: Self { - .paused(at: .currentFrame) - } - - @available(*, deprecated, renamed: "LottiePlaybackMode.playing(_:)", message: "Will be removed in a future major release.") - public static func toProgress(_ toProgress: AnimationProgressTime, loopMode: LottieLoopMode) -> LottiePlaybackMode { - .playing(.fromProgress(nil, toProgress: toProgress, loopMode: loopMode)) - } - - @available(*, deprecated, renamed: "LottiePlaybackMode.playing(_:)", message: "Will be removed in a future major release.") - public static func toFrame(_ toFrame: AnimationFrameTime, loopMode: LottieLoopMode) -> LottiePlaybackMode { - .playing(.fromFrame(nil, toFrame: toFrame, loopMode: loopMode)) - } - - @available(*, deprecated, renamed: "LottiePlaybackMode.playing(_:)", message: "Will be removed in a future major release.") - public static func toMarker( - _ toMarker: String, - playEndMarkerFrame: Bool = true, - loopMode: LottieLoopMode) - -> LottiePlaybackMode - { - .playing(.fromMarker(nil, toMarker: toMarker, playEndMarkerFrame: playEndMarkerFrame, loopMode: loopMode)) - } -} - -extension LottiePlaybackMode.PlaybackMode { - /// Plays the animation from the current progress to a progress value (0-1). - /// - Parameter toProgress: The end progress of the animation. - /// - Parameter loopMode: The loop behavior of the animation. - public static func toProgress(_ toProgress: AnimationProgressTime, loopMode: LottieLoopMode) -> Self { - .fromProgress(nil, toProgress: toProgress, loopMode: loopMode) - } - - // Plays the animation from the current frame to the given frame. - /// - Parameter toFrame: The end frame of the animation. - /// - Parameter loopMode: The loop behavior of the animation. - public static func toFrame(_ toFrame: AnimationFrameTime, loopMode: LottieLoopMode) -> Self { - .fromFrame(nil, toFrame: toFrame, loopMode: loopMode) - } - - /// Plays the animation from the current frame to some marker. - /// - /// Markers are point in time that are encoded into the Animation data and assigned a name. - /// - /// NOTE: If the marker isn't found the play command will exit. - /// - /// - Parameter toMarker: The end marker for the animation playback. - /// - Parameter playEndMarkerFrame: A flag to determine whether or not to play the frame of the end marker. If the - /// end marker represents the end of the section to play, it should be to true. If the provided end marker - /// represents the beginning of the next section, it should be false. - /// - Parameter loopMode: The loop behavior of the animation. - public static func toMarker( - _ toMarker: String, - playEndMarkerFrame: Bool = true, - loopMode: LottieLoopMode) - -> Self - { - .fromMarker(nil, toMarker: toMarker, playEndMarkerFrame: playEndMarkerFrame, loopMode: loopMode) - } -} - -// MARK: - LottieMarkerPosition - -/// The position within a marker. -public enum LottieMarkerPosition: Hashable { - case start - case end -} - -extension LottiePlaybackMode { - /// Returns a copy of this `PlaybackMode` with the `LottieLoopMode` updated to the given value - func loopMode(_ updatedLoopMode: LottieLoopMode) -> LottiePlaybackMode { - switch self { - case .playing(let playbackMode): - return .playing(playbackMode.loopMode(updatedLoopMode)) - - case .fromProgress(let fromProgress, toProgress: let toProgress, _): - return .playing(.fromProgress( - fromProgress, - toProgress: toProgress, - loopMode: updatedLoopMode)) - - case .fromFrame(let fromFrame, toFrame: let toFrame, _): - return .playing(.fromFrame( - fromFrame, - toFrame: toFrame, - loopMode: updatedLoopMode)) - - case .fromMarker(let fromMarker, let toMarker, let playEndMarkerFrame, _): - return .playing(.fromMarker( - fromMarker, - toMarker: toMarker, - playEndMarkerFrame: playEndMarkerFrame, - loopMode: updatedLoopMode)) - - case .marker(let marker, _): - return .playing(.marker(marker, loopMode: updatedLoopMode)) - - case .pause, .paused, .progress(_), .time(_), .frame(_), .markers: - return self - } - } -} - -extension LottiePlaybackMode.PlaybackMode { - /// Returns a copy of this `PlaybackMode` with the `LottieLoopMode` updated to the given value - func loopMode(_ updatedLoopMode: LottieLoopMode) -> LottiePlaybackMode.PlaybackMode { - switch self { - case .fromProgress(let fromProgress, let toProgress, _): - return .fromProgress(fromProgress, toProgress: toProgress, loopMode: updatedLoopMode) - case .fromFrame(let fromFrame, let toFrame, _): - return .fromFrame(fromFrame, toFrame: toFrame, loopMode: updatedLoopMode) - case .fromMarker(let fromMarker, let toMarker, let playEndMarkerFrame, _): - return .fromMarker(fromMarker, toMarker: toMarker, playEndMarkerFrame: playEndMarkerFrame, loopMode: updatedLoopMode) - case .marker(let marker, _): - return .marker(marker, loopMode: updatedLoopMode) - case .markers: - return self - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieView.swift deleted file mode 100644 index 463c0ed5c694a1a6ee6075da77213463401ce8ce..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Animation/LottieView.swift +++ /dev/null @@ -1,579 +0,0 @@ -// Created by Bryn Bodayle on 1/20/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -// MARK: - LottieView - -/// A wrapper which exposes Lottie's `LottieAnimationView` to SwiftUI -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -public struct LottieView: UIViewConfiguringSwiftUIView { - - // MARK: Lifecycle - - /// Creates a `LottieView` that displays the given animation - public init(animation: LottieAnimation?) where Placeholder == EmptyView { - _animationSource = State(initialValue: animation.map(LottieAnimationSource.lottieAnimation)) - placeholder = nil - } - - /// Initializes a `LottieView` with the provided `DotLottieFile` for display. - /// - /// - Important: Avoid using this initializer with the `SynchronouslyBlockingCurrentThread` APIs. - /// If decompression of a `.lottie` file is necessary, prefer using the `.init(_ loadAnimation:)` - /// initializer, which takes an asynchronous closure: - /// ``` - /// LottieView { - /// try await DotLottieFile.named(name) - /// } - /// ``` - public init(dotLottieFile: DotLottieFile?) where Placeholder == EmptyView { - _animationSource = State(initialValue: dotLottieFile.map(LottieAnimationSource.dotLottieFile)) - placeholder = nil - } - - /// Creates a `LottieView` that asynchronously loads and displays the given `LottieAnimation`. - /// The `loadAnimation` closure is called exactly once in `onAppear`. - /// If you wish to call `loadAnimation` again at a different time, you can use `.reloadAnimationTrigger(...)`. - public init(_ loadAnimation: @escaping () async throws -> LottieAnimation?) where Placeholder == EmptyView { - self.init(loadAnimation, placeholder: EmptyView.init) - } - - /// Creates a `LottieView` that asynchronously loads and displays the given `LottieAnimation`. - /// The `loadAnimation` closure is called exactly once in `onAppear`. - /// If you wish to call `loadAnimation` again at a different time, you can use `.reloadAnimationTrigger(...)`. - /// While the animation is loading, the `placeholder` view is shown in place of the `LottieAnimationView`. - public init( - _ loadAnimation: @escaping () async throws -> LottieAnimation?, - @ViewBuilder placeholder: @escaping (() -> Placeholder)) - { - self.init { - try await loadAnimation().map(LottieAnimationSource.lottieAnimation) - } placeholder: { - placeholder() - } - } - - /// Creates a `LottieView` that asynchronously loads and displays the given `DotLottieFile`. - /// The `loadDotLottieFile` closure is called exactly once in `onAppear`. - /// If you wish to call `loadAnimation` again at a different time, you can use `.reloadAnimationTrigger(...)`. - /// You can use the `DotLottieFile` static methods API which use Swift concurrency to load your `.lottie` files: - /// ``` - /// LottieView { - /// try await DotLottieFile.named(name) - /// } - /// ``` - public init(_ loadDotLottieFile: @escaping () async throws -> DotLottieFile?) where Placeholder == EmptyView { - self.init(loadDotLottieFile, placeholder: EmptyView.init) - } - - /// Creates a `LottieView` that asynchronously loads and displays the given `DotLottieFile`. - /// The `loadDotLottieFile` closure is called exactly once in `onAppear`. - /// If you wish to call `loadAnimation` again at a different time, you can use `.reloadAnimationTrigger(...)`. - /// While the animation is loading, the `placeholder` view is shown in place of the `LottieAnimationView`. - /// You can use the `DotLottieFile` static methods API which use Swift concurrency to load your `.lottie` files: - /// ``` - /// LottieView { - /// try await DotLottieFile.named(name) - /// } placeholder: { - /// LoadingView() - /// } - /// ``` - public init( - _ loadDotLottieFile: @escaping () async throws -> DotLottieFile?, - @ViewBuilder placeholder: @escaping (() -> Placeholder)) - { - self.init { - try await loadDotLottieFile().map(LottieAnimationSource.dotLottieFile) - } placeholder: { - placeholder() - } - } - - /// Creates a `LottieView` that asynchronously loads and displays the given `LottieAnimationSource`. - /// The `loadAnimation` closure is called exactly once in `onAppear`. - /// If you wish to call `loadAnimation` again at a different time, you can use `.reloadAnimationTrigger(...)`. - /// While the animation is loading, the `placeholder` view is shown in place of the `LottieAnimationView`. - public init(_ loadAnimation: @escaping () async throws -> LottieAnimationSource?) where Placeholder == EmptyView { - self.init(loadAnimation, placeholder: EmptyView.init) - } - - /// Creates a `LottieView` that asynchronously loads and displays the given `LottieAnimationSource`. - /// The `loadAnimation` closure is called exactly once in `onAppear`. - /// If you wish to call `loadAnimation` again at a different time, you can use `.reloadAnimationTrigger(...)`. - /// While the animation is loading, the `placeholder` view is shown in place of the `LottieAnimationView`. - public init( - _ loadAnimation: @escaping () async throws -> LottieAnimationSource?, - @ViewBuilder placeholder: @escaping () -> Placeholder) - { - self.loadAnimation = loadAnimation - self.placeholder = placeholder - _animationSource = State(initialValue: nil) - } - - // MARK: Public - - public var body: some View { - LottieAnimationView.swiftUIView { - LottieAnimationView( - animationSource: animationSource, - imageProvider: imageProviderConfiguration?.imageProvider, - textProvider: textProvider, - fontProvider: fontProvider, - configuration: configuration, - logger: logger) - } - .sizing(sizing) - .configure { context in - applyCurrentAnimationConfiguration(to: context.view) - } - .configurations(configurations) - .opacity(animationSource == nil ? 0 : 1) - .overlay { - placeholder?() - .opacity(animationSource == nil ? 1 : 0) - } - .onAppear { - loadAnimationIfNecessary() - } - .valueChanged(value: reloadAnimationTrigger) { _ in - reloadAnimationTriggerDidChange() - } - } - - /// Returns a copy of this `LottieView` updated to have the given closure applied to its - /// represented `LottieAnimationView` whenever it is updated via the `updateUIView(…)` - /// or `updateNSView(…)` method. - public func configure(_ configure: @escaping (LottieAnimationView) -> Void) -> Self { - var copy = self - copy.configurations.append { context in - configure(context.view) - } - return copy - } - - /// Returns a copy of this view that can be resized by scaling its animation to fit the size - /// offered by its parent. - public func resizable() -> Self { - var copy = self - copy.sizing = .proposed - return copy - } - - @available(*, deprecated, renamed: "playing()", message: "Will be removed in a future major release.") - public func play() -> Self { - playbackMode(.playing(.fromProgress(nil, toProgress: 1, loopMode: .playOnce))) - } - - /// Returns a copy of this view that loops its animation from the start to end whenever visible - public func looping() -> Self { - playbackMode(.playing(.fromProgress(0, toProgress: 1, loopMode: .loop))) - } - - @available(*, deprecated, renamed: "playing(_:)", message: "Will be removed in a future major release.") - public func play(loopMode: LottieLoopMode = .playOnce) -> Self { - playbackMode(.playing(.fromProgress(nil, toProgress: 1, loopMode: loopMode))) - } - - @available(*, deprecated, renamed: "playbackMode(_:)", message: "Will be removed in a future major release.") - public func play(_ playbackMode: LottiePlaybackMode) -> Self { - self.playbackMode(playbackMode) - } - - /// Returns a copy of this view playing with the given playback mode - public func playing(_ mode: LottiePlaybackMode.PlaybackMode) -> Self { - playbackMode(.playing(mode)) - } - - /// Returns a copy of this view playing from the current frame to the end frame, - /// with the given `LottiePlaybackMode`. - public func playing(loopMode: LottieLoopMode) -> Self { - playbackMode(.playing(.fromProgress(nil, toProgress: 1, loopMode: loopMode))) - } - - // Returns a copy of this view playing once from the current frame to the end frame - public func playing() -> Self { - playbackMode(.playing(.fromProgress(nil, toProgress: 1, loopMode: .playOnce))) - } - - /// Returns a copy of this view paused with the given state - public func paused(at state: LottiePlaybackMode.PausedState = .currentFrame) -> Self { - playbackMode(.paused(at: state)) - } - - /// Returns a copy of this view using the given `LottiePlaybackMode` - public func playbackMode(_ playbackMode: LottiePlaybackMode) -> Self { - var copy = self - copy.playbackMode = playbackMode - return copy - } - - /// Returns a copy of this view playing its animation at the given speed - public func animationSpeed(_ animationSpeed: Double) -> Self { - var copy = self - copy.animationSpeed = animationSpeed - return copy - } - - /// Returns a copy of this view with the given closure that is called whenever the - /// `LottieAnimationSource` provided via `init` is loaded and applied to the underlying `LottieAnimationView`. - public func animationDidLoad(_ animationDidLoad: @escaping (LottieAnimationSource) -> Void) -> Self { - var copy = self - copy.animationDidLoad = animationDidLoad - return copy - } - - /// Returns a copy of this view with the given `LottieCompletionBlock` that is called - /// when an animation finishes playing. - public func animationDidFinish(_ animationCompletionHandler: LottieCompletionBlock?) -> Self { - var copy = self - copy.animationCompletionHandler = { [previousCompletionHandler = self.animationCompletionHandler] completed in - previousCompletionHandler?(completed) - animationCompletionHandler?(completed) - } - return copy - } - - /// Returns a copy of this view updated to have the provided background behavior. - public func backgroundBehavior(_ value: LottieBackgroundBehavior) -> Self { - configure { view in - view.backgroundBehavior = value - } - } - - /// Returns a copy of this view with its accessibility label updated to the given value. - public func accessibilityLabel(_ accessibilityLabel: String?) -> Self { - configure { view in - #if os(macOS) - view.setAccessibilityElement(accessibilityLabel != nil) - view.setAccessibilityLabel(accessibilityLabel) - #else - view.isAccessibilityElement = accessibilityLabel != nil - view.accessibilityLabel = accessibilityLabel - #endif - } - } - - /// Returns a copy of this view with its `LottieConfiguration` updated to the given value. - public func configuration(_ configuration: LottieConfiguration) -> Self { - var copy = self - copy.configuration = configuration - - copy = copy.configure { view in - if view.configuration != configuration { - view.configuration = configuration - } - } - - return copy - } - - /// Returns a copy of this view with its `LottieLogger` updated to the given value. - /// - The underlying `LottieAnimationView`'s `LottieLogger` is immutable after configured, - /// so this value is only used when initializing the `LottieAnimationView` for the first time. - public func logger(_ logger: LottieLogger) -> Self { - var copy = self - copy.logger = logger - return copy - } - - /// Returns a copy of this view with its image provider updated to the given value. - /// The image provider must be `Equatable` to avoid unnecessary state updates / re-renders. - public func imageProvider(_ imageProvider: ImageProvider) -> Self { - var copy = self - - copy.imageProviderConfiguration = ( - imageProvider: imageProvider, - imageProvidersAreEqual: { untypedLHS, untypedRHS in - guard - let lhs = untypedLHS as? ImageProvider, - let rhs = untypedRHS as? ImageProvider - else { return false } - - return lhs == rhs - }) - - return copy - } - - /// Returns a copy of this view with its text provider updated to the given value. - /// The image provider must be `Equatable` to avoid unnecessary state updates / re-renders. - public func textProvider(_ textProvider: TextProvider) -> Self { - var copy = self - copy.textProvider = textProvider - - copy = copy.configure { view in - if (view.textProvider as? TextProvider) != textProvider { - view.textProvider = textProvider - } - } - - return copy - } - - /// Returns a copy of this view with its image provider updated to the given value. - /// The image provider must be `Equatable` to avoid unnecessary state updates / re-renders. - public func fontProvider(_ fontProvider: FontProvider) -> Self { - var copy = self - copy.fontProvider = fontProvider - - copy = configure { view in - if (view.fontProvider as? FontProvider) != fontProvider { - view.fontProvider = fontProvider - } - } - - return copy - } - - /// Returns a copy of this view using the given value provider for the given keypath. - /// The value provider must be `Equatable` to avoid unnecessary state updates / re-renders. - public func valueProvider( - _ valueProvider: ValueProvider, - for keypath: AnimationKeypath) - -> Self - { - configure { view in - if (view.valueProviders[keypath] as? ValueProvider) != valueProvider { - view.setValueProvider(valueProvider, keypath: keypath) - } - } - } - - /// Returns a copy of this view updated to display the given `AnimationProgressTime`. - /// - If the `currentProgress` value is provided, the `currentProgress` of the - /// underlying `LottieAnimationView` is updated. This will pause any existing animations. - /// - If the `animationProgress` is `nil`, no changes will be made and any existing animations - /// will continue playing uninterrupted. - public func currentProgress(_ currentProgress: AnimationProgressTime?) -> Self { - guard let currentProgress else { return self } - var copy = self - copy.playbackMode = .paused(at: .progress(currentProgress)) - return copy - } - - /// Returns a copy of this view updated to display the given `AnimationFrameTime`. - /// - If the `currentFrame` value is provided, the `currentFrame` of the - /// underlying `LottieAnimationView` is updated. This will pause any existing animations. - /// - If the `currentFrame` is `nil`, no changes will be made and any existing animations - /// will continue playing uninterrupted. - public func currentFrame(_ currentFrame: AnimationFrameTime?) -> Self { - guard let currentFrame else { return self } - var copy = self - copy.playbackMode = .paused(at: .frame(currentFrame)) - return copy - } - - /// Returns a copy of this view updated to display the given time value. - /// - If the `currentTime` value is provided, the `currentTime` of the - /// underlying `LottieAnimationView` is updated. This will pause any existing animations. - /// - If the `currentTime` is `nil`, no changes will be made and any existing animations - /// will continue playing uninterrupted. - public func currentTime(_ currentTime: TimeInterval?) -> Self { - guard let currentTime else { return self } - var copy = self - copy.playbackMode = .paused(at: .time(currentTime)) - return copy - } - - /// Returns a new instance of this view, which will invoke the provided `loadAnimation` closure - /// whenever the `binding` value is updated. - /// - /// - Note: This function requires a valid `loadAnimation` closure provided during view initialization, - /// otherwise `reloadAnimationTrigger` will have no effect. - /// - Parameters: - /// - binding: The binding that triggers the reloading when its value changes. - /// - showPlaceholder: When `true`, the current animation will be removed before invoking `loadAnimation`, - /// displaying the `Placeholder` until the new animation loads. - /// When `false`, the previous animation remains visible while the new one loads. - public func reloadAnimationTrigger(_ value: some Equatable, showPlaceholder: Bool = true) -> Self { - var copy = self - copy.reloadAnimationTrigger = AnyEquatable(value) - copy.showPlaceholderWhileReloading = showPlaceholder - return copy - } - - /// Returns a view that updates the given binding each frame with the animation's `realtimeAnimationProgress`. - /// The `LottieView` is wrapped in a `TimelineView` with the `.animation` schedule. - /// - This is a one-way binding. Its value is updated but never read. - /// - If provided, the binding will be updated each frame with the `realtimeAnimationProgress` - /// of the underlying `LottieAnimationView`. This is potentially expensive since it triggers - /// a state update every frame. - /// - If the binding is `nil`, the `TimelineView` will be paused and no updates will occur to the binding. - @available(iOS 15.0, tvOS 15.0, macOS 12.0, *) - public func getRealtimeAnimationProgress(_ realtimeAnimationProgress: Binding?) -> some View { - TimelineView(.animation(paused: realtimeAnimationProgress == nil)) { _ in - configure { view in - if let realtimeAnimationProgress { - DispatchQueue.main.async { - realtimeAnimationProgress.wrappedValue = view.realtimeAnimationProgress - } - } - } - } - } - - /// Returns a view that updates the given binding each frame with the animation's `realtimeAnimationProgress`. - /// The `LottieView` is wrapped in a `TimelineView` with the `.animation` schedule. - /// - This is a one-way binding. Its value is updated but never read. - /// - If provided, the binding will be updated each frame with the `realtimeAnimationProgress` - /// of the underlying `LottieAnimationView`. This is potentially expensive since it triggers - /// a state update every frame. - /// - If the binding is `nil`, the `TimelineView` will be paused and no updates will occur to the binding. - @available(iOS 15.0, tvOS 15.0, macOS 12.0, *) - public func getRealtimeAnimationFrame(_ realtimeAnimationFrame: Binding?) -> some View { - TimelineView(.animation(paused: realtimeAnimationFrame == nil)) { _ in - configure { view in - if let realtimeAnimationFrame { - DispatchQueue.main.async { - realtimeAnimationFrame.wrappedValue = view.realtimeAnimationFrame - } - } - } - } - } - - /// Returns a copy of this view with the `DotLottieConfigurationComponents` - /// updated to the given value. - /// - Defaults to `[.imageProvider]` - /// - If a component is specified here, that value in the `DotLottieConfiguration` - /// of an active dotLottie animation will override any value provided via other methods. - public func dotLottieConfigurationComponents( - _ dotLottieConfigurationComponents: DotLottieConfigurationComponents) - -> Self - { - var copy = self - copy.dotLottieConfigurationComponents = dotLottieConfigurationComponents - return copy - } - - // MARK: Internal - - var configurations = [SwiftUIView.Configuration]() - - // MARK: Private - - @State private var animationSource: LottieAnimationSource? - private var playbackMode: LottiePlaybackMode? - private var animationSpeed: Double? - private var reloadAnimationTrigger: AnyEquatable? - private var loadAnimation: (() async throws -> LottieAnimationSource?)? - private var animationDidLoad: ((LottieAnimationSource) -> Void)? - private var animationCompletionHandler: LottieCompletionBlock? - private var showPlaceholderWhileReloading = false - private var textProvider: AnimationKeypathTextProvider = DefaultTextProvider() - private var fontProvider: AnimationFontProvider = DefaultFontProvider() - private var configuration: LottieConfiguration = .shared - private var dotLottieConfigurationComponents: DotLottieConfigurationComponents = .imageProvider - private var logger: LottieLogger = .shared - private var sizing = SwiftUIMeasurementContainerStrategy.automatic - private let placeholder: (() -> Placeholder)? - - private var imageProviderConfiguration: ( - imageProvider: AnimationImageProvider, - imageProvidersAreEqual: (AnimationImageProvider, AnimationImageProvider) -> Bool)? - - private func loadAnimationIfNecessary() { - guard let loadAnimation else { return } - - Task { - do { - animationSource = try await loadAnimation() - } catch { - logger.warn("Failed to load asynchronous Lottie animation with error: \(error)") - } - } - } - - private func reloadAnimationTriggerDidChange() { - guard loadAnimation != nil else { return } - - if showPlaceholderWhileReloading { - animationSource = nil - } - - loadAnimationIfNecessary() - } - - /// Applies playback configuration for the current animation to the `LottieAnimationView` - private func applyCurrentAnimationConfiguration(to view: LottieAnimationView) { - guard let animationSource else { return } - var imageProviderConfiguration = imageProviderConfiguration - var playbackMode = playbackMode - var animationSpeed = animationSpeed - - // When playing a dotLottie animation, its `DotLottieConfiguration` - // can override some behavior of the animation. - if let dotLottieConfiguration = animationSource.dotLottieAnimation?.configuration { - // Only use the value from the `DotLottieConfiguration` is that component - // is specified in the list of `dotLottieConfigurationComponents`. - if dotLottieConfigurationComponents.contains(.loopMode) { - playbackMode = playbackMode?.loopMode(dotLottieConfiguration.loopMode) - } - - if dotLottieConfigurationComponents.contains(.animationSpeed) { - animationSpeed = dotLottieConfiguration.speed - } - - if - dotLottieConfigurationComponents.contains(.imageProvider), - let dotLottieImageProvider = dotLottieConfiguration.dotLottieImageProvider - { - imageProviderConfiguration = ( - imageProvider: dotLottieImageProvider, - imageProvidersAreEqual: { untypedLHS, untypedRHS in - guard - let lhs = untypedLHS as? DotLottieImageProvider, - let rhs = untypedRHS as? DotLottieImageProvider - else { return false } - - return lhs == rhs - }) - } - } - - // We check referential equality of the animation before updating as updating the - // animation has a side-effect of rebuilding the animation layer, and it would be - // prohibitive to do so on every state update. - if animationSource.animation !== view.animation { - view.loadAnimation(animationSource) - animationDidLoad?(animationSource) - } - - if - let playbackMode, - playbackMode != view.currentPlaybackMode - { - view.setPlaybackMode(playbackMode, completion: animationCompletionHandler) - } - - if - let (imageProvider, imageProvidersAreEqual) = imageProviderConfiguration, - !imageProvidersAreEqual(imageProvider, view.imageProvider) - { - view.imageProvider = imageProvider - } - - if - let animationSpeed, - animationSpeed != view.animationSpeed - { - view.animationSpeed = animationSpeed - } - } -} - -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -extension View { - - /// The `.overlay` modifier that uses a `ViewBuilder` is available in iOS 15+, this helper function helps us to use the same API in older OSs - fileprivate func overlay( - @ViewBuilder content: () -> some View) - -> some View - { - overlay(content(), alignment: .center) - } -} - -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/AnimationCacheProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/AnimationCacheProvider.swift deleted file mode 100644 index ba6e3768d00b6b8940cceb780fd12f81cd8ea58c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/AnimationCacheProvider.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// AnimationCacheProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/5/19. -// - -/// `AnimationCacheProvider` is a protocol that describes an Animation Cache. -/// Animation Cache is used when loading `LottieAnimation` models. Using an Animation Cache -/// can increase performance when loading an animation multiple times. -/// -/// Lottie comes with a prebuilt LRU Animation Cache. -public protocol AnimationCacheProvider: AnyObject, Sendable { - - func animation(forKey: String) -> LottieAnimation? - - func setAnimation(_ animation: LottieAnimation, forKey: String) - - func clearCache() - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/DefaultAnimationCache.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/DefaultAnimationCache.swift deleted file mode 100644 index 57f2a9b4c8bfa44d638a01f8dc94be3b8dd24be2..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/DefaultAnimationCache.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// DefaultAnimationCache.swift -// Lottie -// -// Created by Marcelo Fabri on 10/18/22. -// - -import Foundation - -// MARK: - DefaultAnimationCache - -/// A thread-safe Animation Cache that will store animations up to `cacheSize`. -/// -/// Once `cacheSize` is reached, animations can be ejected. -/// The default size of the cache is 100. -/// -/// This cache implementation also responds to memory pressure. -public class DefaultAnimationCache: AnimationCacheProvider { - - // MARK: Lifecycle - - public init() { - cache.countLimit = Self.defaultCacheCountLimit - } - - // MARK: Public - - /// The global shared Cache. - public static let sharedCache = DefaultAnimationCache() - - /// The maximum number of animations that can be stored in the cache. - public var cacheSize: Int { - get { cache.countLimit } - set { cache.countLimit = newValue } - } - - /// Clears the Cache. - public func clearCache() { - cache.removeAllValues() - } - - public func animation(forKey key: String) -> LottieAnimation? { - cache.value(forKey: key) - } - - public func setAnimation(_ animation: LottieAnimation, forKey key: String) { - cache.setValue(animation, forKey: key) - } - - // MARK: Private - - private static let defaultCacheCountLimit = 100 - - /// The underlying storage of this cache. - /// - We use the `LRUCache` library instead of `NSCache`, because `NSCache` - /// clears all cached values when the app is backgrounded instead of - /// only when the app receives a memory warning notification. - private let cache = LRUCache() -} - -// MARK: Sendable - -// LottieAnimationCache has a Sendable requirement, but we can't -// redesign DefaultAnimationCache to be properly Sendable without -// making breaking changes. -// swiftlint:disable:next no_unchecked_sendable -extension DefaultAnimationCache: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/LRUAnimationCache.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/LRUAnimationCache.swift deleted file mode 100644 index ebf1f5ee56c44360ff68c7c28d65c189e96dc932..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/LRUAnimationCache.swift +++ /dev/null @@ -1,11 +0,0 @@ -// -// LRUAnimationCache.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/5/19. -// - -@available(*, deprecated, message: """ - Use DefaultAnimationCache instead, which is thread-safe and automatically responds to memory pressure. - """) -public typealias LRUAnimationCache = DefaultAnimationCache diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/LottieAnimationCache.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/LottieAnimationCache.swift deleted file mode 100644 index efb6a3ee39507907aadef903dfd867d391d31f6e..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/AnimationCache/LottieAnimationCache.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// LottieAnimationCache.swift -// Lottie -// -// Created by Marcelo Fabri on 10/17/22. -// - -/// A customization point to configure which `AnimationCacheProvider` will be used. -public enum LottieAnimationCache { - - /// The animation cache that will be used when loading `LottieAnimation` models. - /// Using an Animation Cache can increase performance when loading an animation multiple times. - /// Defaults to DefaultAnimationCache.sharedCache. - public static var shared: AnimationCacheProvider? = DefaultAnimationCache.sharedCache -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/DecodingStrategy.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/DecodingStrategy.swift deleted file mode 100644 index f1cfe3c4b007da40b8c159dbba837aabdbec66bb..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/DecodingStrategy.swift +++ /dev/null @@ -1,15 +0,0 @@ -// Created by Cal Stephens on 7/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -/// How animation files should be decoded -public enum DecodingStrategy: Hashable { - /// Use Codable. This is was the default strategy introduced on Lottie 3, but should be rarely - /// used as it's slower than `dictionaryBased`. Kept here for any possible compatibility issues - /// that may come up, but consider it soft-deprecated. - case legacyCodable - - /// Manually deserialize a dictionary into an Animation. - /// This should be at least 2-3x faster than using Codable and due to that - /// it's the default as of Lottie 4.x. - case dictionaryBased -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/LottieConfiguration.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/LottieConfiguration.swift deleted file mode 100644 index 646ace717ac137ed5be24bf55adfe699cb601df4..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/LottieConfiguration.swift +++ /dev/null @@ -1,47 +0,0 @@ -// Created by Cal Stephens on 12/13/21. -// Copyright © 2021 Airbnb Inc. All rights reserved. - -import QuartzCore - -/// Global configuration options for Lottie animations -public struct LottieConfiguration: Hashable { - - // MARK: Lifecycle - - public init( - renderingEngine: RenderingEngineOption = .automatic, - decodingStrategy: DecodingStrategy = .dictionaryBased, - colorSpace: CGColorSpace = CGColorSpaceCreateDeviceRGB(), - reducedMotionOption: ReducedMotionOption = .systemReducedMotionToggle) - { - self.renderingEngine = renderingEngine - self.decodingStrategy = decodingStrategy - self.colorSpace = colorSpace - self.reducedMotionOption = reducedMotionOption - } - - // MARK: Public - - /// The global configuration of Lottie, - /// which applies to all `LottieAnimationView`s by default. - public static var shared = LottieConfiguration() - - /// The rendering engine implementation to use when displaying an animation - /// - Defaults to `RenderingEngineOption.automatic`, which uses the - /// Core Animation rendering engine for supported animations, and - /// falls back to using the Main Thread rendering engine for - /// animations that use features not supported by the Core Animation engine. - public var renderingEngine: RenderingEngineOption - - /// The decoding implementation to use when parsing an animation JSON file - public var decodingStrategy: DecodingStrategy - - /// Options for controlling animation behavior in response to user / system "reduced motion" configuration. - /// - Defaults to `ReducedMotionOption.systemReducedMotionToggle`, which returns `.reducedMotion` - /// when the system `UIAccessibility.isReduceMotionEnabled` option is `true`. - public var reducedMotionOption: ReducedMotionOption - - /// The color space to be used for rendering - /// - Defaults to `CGColorSpaceCreateDeviceRGB()` - public var colorSpace: CGColorSpace -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/ReducedMotionOption.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/ReducedMotionOption.swift deleted file mode 100644 index 0101dc9bda1e70c805065b89187ce8625ca0a6b9..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/ReducedMotionOption.swift +++ /dev/null @@ -1,114 +0,0 @@ -// Created by Cal Stephens on 7/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -#if canImport(UIKit) -import UIKit -#elseif canImport(AppKit) -import AppKit -#endif - -// MARK: - ReducedMotionOption - -/// Options for controlling animation behavior in response to user / system "reduced motion" configuration -public enum ReducedMotionOption { - /// Always use the specific given `ReducedMotionMode` value. - case specific(ReducedMotionMode) - - /// Dynamically check the given `ReducedMotionOptionProvider` each time an animation begins. - /// - Includes a Hashable `dataID` to support `ReducedMotionOption`'s `Hashable` requirement, - /// which is required due to `LottieConfiguration`'s existing `Hashable` requirement. - case dynamic(ReducedMotionOptionProvider, dataID: AnyHashable) -} - -extension ReducedMotionOption { - /// The standard behavior where Lottie animations play normally with no overrides. - /// By default this mode is used when the system "reduced motion" option is disabled. - public static var standardMotion: ReducedMotionOption { .specific(.standardMotion) } - - /// Lottie animations with a "reduced motion" marker will play that marker instead of any other animations. - /// By default this mode is used when the system "reduced motion" option is enabled. - /// - Valid marker names include "reduced motion", "reducedMotion", "reduced_motion" (case insensitive). - public static var reducedMotion: ReducedMotionOption { .specific(.reducedMotion) } - - /// A `ReducedMotionOptionProvider` that returns `.reducedMotion` when - /// the system `UIAccessibility.isReduceMotionEnabled` option is `true`. - /// This is the default option of `LottieConfiguration`. - public static var systemReducedMotionToggle: ReducedMotionOption { - .dynamic(SystemReducedMotionOptionProvider(), dataID: ObjectIdentifier(SystemReducedMotionOptionProvider.self)) - } -} - -extension ReducedMotionOption { - /// The current `ReducedMotionMode` based on the currently selected option. - public var currentReducedMotionMode: ReducedMotionMode { - switch self { - case .specific(let specificMode): - return specificMode - case .dynamic(let optionProvider, _): - return optionProvider.currentReducedMotionMode - } - } -} - -// MARK: Hashable - -extension ReducedMotionOption: Hashable { - public static func ==(_ lhs: ReducedMotionOption, _ rhs: ReducedMotionOption) -> Bool { - switch (lhs, rhs) { - case (.specific(let lhsMode), .specific(let rhsMode)): - return lhsMode == rhsMode - case (.dynamic(_, let lhsDataID), .dynamic(_, dataID: let rhsDataID)): - return lhsDataID == rhsDataID - case (.dynamic, .specific), (.specific, .dynamic): - return false - } - } - - public func hash(into hasher: inout Hasher) { - switch self { - case .specific(let mode): - hasher.combine(mode) - case .dynamic(_, let dataID): - hasher.combine(dataID) - } - } -} - -// MARK: - ReducedMotionMode - -public enum ReducedMotionMode: Hashable { - /// The default behavior where Lottie animations play normally with no overrides - /// By default this mode is used when the system "reduced motion" option is disabled. - case standardMotion - - /// Lottie animations with a "reduced motion" marker will play that marker instead of any other animations. - /// By default this mode is used when the system "reduced motion" option is enabled. - case reducedMotion -} - -// MARK: - ReducedMotionOptionProvider - -/// A type that returns a dynamic `ReducedMotionMode` which is checked when playing a Lottie animation. -public protocol ReducedMotionOptionProvider { - var currentReducedMotionMode: ReducedMotionMode { get } -} - -// MARK: - SystemReducedMotionOptionProvider - -/// A `ReducedMotionOptionProvider` that returns `.reducedMotion` when -/// the system `UIAccessibility.isReduceMotionEnabled` option is `true`. -public struct SystemReducedMotionOptionProvider: ReducedMotionOptionProvider { - public init() { } - - public var currentReducedMotionMode: ReducedMotionMode { - #if canImport(UIKit) - if UIAccessibility.isReduceMotionEnabled { - return .reducedMotion - } else { - return .standardMotion - } - #else - return .standardMotion - #endif - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/RenderingEngineOption.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/RenderingEngineOption.swift deleted file mode 100644 index 187303d8c5cf5c22e6243b60ef4d1ce95df44246..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Configuration/RenderingEngineOption.swift +++ /dev/null @@ -1,113 +0,0 @@ -// Created by Cal Stephens on 7/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -// MARK: - RenderingEngineOption - -public enum RenderingEngineOption: Hashable { - /// Uses the Core Animation engine for supported animations, and falls back to using - /// the Main Thread engine for animations that use features not supported by the - /// Core Animation engine. - case automatic - - /// Uses the specified rendering engine - case specific(RenderingEngine) - - // MARK: Public - - /// The Main Thread rendering engine, which supports all Lottie features - /// but runs on the main thread, which comes with some CPU overhead and - /// can cause the animation to play at a low framerate when the CPU is busy. - public static var mainThread: RenderingEngineOption { .specific(.mainThread) } - - /// The Core Animation rendering engine, that animates using Core Animation - /// and has better performance characteristics than the Main Thread engine, - /// but doesn't support all Lottie features. - /// - In general, prefer using `RenderingEngineOption.automatic` over - /// `RenderingEngineOption.coreAnimation`. The Core Animation rendering - /// engine doesn't support all features supported by the Main Thread - /// rendering engine. When using `RenderingEngineOption.automatic`, - /// Lottie will automatically fall back to the Main Thread engine - /// when necessary. - public static var coreAnimation: RenderingEngineOption { .specific(.coreAnimation) } -} - -// MARK: - RenderingEngine - -/// The rendering engine implementation to use when displaying an animation -public enum RenderingEngine: Hashable { - /// The Main Thread rendering engine, which supports all Lottie features - /// but runs on the main thread, which comes with some CPU overhead and - /// can cause the animation to play at a low framerate when the CPU is busy. - case mainThread - - /// The Core Animation rendering engine, that animates using Core Animation - /// and has better performance characteristics than the Main Thread engine, - /// but doesn't support all Lottie features. - case coreAnimation -} - -// MARK: - RenderingEngineOption + RawRepresentable, CustomStringConvertible - -extension RenderingEngineOption: RawRepresentable, CustomStringConvertible { - - // MARK: Lifecycle - - public init?(rawValue: String) { - if rawValue == "Automatic" { - self = .automatic - } else if let engine = RenderingEngine(rawValue: rawValue) { - self = .specific(engine) - } else { - return nil - } - } - - // MARK: Public - - public var rawValue: String { - switch self { - case .automatic: - return "Automatic" - case .specific(let engine): - return engine.rawValue - } - } - - public var description: String { - rawValue - } - -} - -// MARK: - RenderingEngine + RawRepresentable, CustomStringConvertible - -extension RenderingEngine: RawRepresentable, CustomStringConvertible { - - // MARK: Lifecycle - - public init?(rawValue: String) { - switch rawValue { - case "Main Thread": - self = .mainThread - case "Core Animation": - self = .coreAnimation - default: - return nil - } - } - - // MARK: Public - - public var rawValue: String { - switch self { - case .mainThread: - return "Main Thread" - case .coreAnimation: - return "Core Animation" - } - } - - public var description: String { - rawValue - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/AnimatedButton.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/AnimatedButton.swift deleted file mode 100644 index 1e91c67acd224347b0717c11c39d560255c17f80..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/AnimatedButton.swift +++ /dev/null @@ -1,127 +0,0 @@ -// -// AnimatedButton.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -#if canImport(UIKit) -import UIKit -#elseif canImport(AppKit) -import AppKit -#endif - -// MARK: - AnimatedButton - -/// An interactive button that plays an animation when pressed. -open class AnimatedButton: AnimatedControl { - - // MARK: Lifecycle - - public override init( - animation: LottieAnimation?, - configuration: LottieConfiguration = .shared) - { - super.init(animation: animation, configuration: configuration) - - #if canImport(UIKit) - isAccessibilityElement = true - #elseif canImport(AppKit) - setAccessibilityElement(true) - #endif - } - - public override init() { - super.init() - - #if canImport(UIKit) - isAccessibilityElement = true - #elseif canImport(AppKit) - setAccessibilityElement(true) - #endif - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - - #if canImport(UIKit) - isAccessibilityElement = true - #elseif canImport(AppKit) - setAccessibilityElement(true) - #endif - } - - // MARK: Open - - #if canImport(UIKit) - open override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { - let _ = super.beginTracking(touch, with: event) - let touchEvent = UIControl.Event.touchDown - if let playRange = rangesForEvents[touchEvent.id] { - animationView.play(fromProgress: playRange.from, toProgress: playRange.to, loopMode: .playOnce) - } - return true - } - - open override func endTracking(_ touch: UITouch?, with event: UIEvent?) { - super.endTracking(touch, with: event) - let touchEvent: UIControl.Event - if let touch, bounds.contains(touch.location(in: self)) { - touchEvent = UIControl.Event.touchUpInside - performAction?() - } else { - touchEvent = UIControl.Event.touchUpOutside - } - - if let playRange = rangesForEvents[touchEvent.id] { - animationView.play(fromProgress: playRange.from, toProgress: playRange.to, loopMode: .playOnce) - } - } - - #elseif canImport(AppKit) - open override func handle(_ event: LottieNSControlEvent) { - super.handle(event) - - if let playRange = rangesForEvents[event.id] { - animationView.play(fromProgress: playRange.from, toProgress: playRange.to, loopMode: .playOnce) - } - - if event == .touchUpInside { - performAction?() - } - } - #endif - - // MARK: Public - - /// A closure that is called when the button is pressed / clicked - public var performAction: (() -> Void)? - - #if canImport(UIKit) - public override var accessibilityTraits: UIAccessibilityTraits { - set { super.accessibilityTraits = newValue } - get { super.accessibilityTraits.union(.button) } - } - #endif - - /// Sets the play range for the given UIControlEvent. - public func setPlayRange(fromProgress: AnimationProgressTime, toProgress: AnimationProgressTime, event: LottieControlEvent) { - rangesForEvents[event.id] = (from: fromProgress, to: toProgress) - } - - /// Sets the play range for the given UIControlEvent. - public func setPlayRange(fromMarker fromName: String, toMarker toName: String, event: LottieControlEvent) { - if - let start = animationView.progressTime(forMarker: fromName), - let end = animationView.progressTime(forMarker: toName) - { - rangesForEvents[event.id] = (from: start, to: end) - } - } - - // MARK: Private - - private var rangesForEvents: [AnyHashable: (from: CGFloat, to: CGFloat)] = [LottieControlEvent.touchUpInside.id: ( - from: 0, - to: 1)] -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/AnimatedControl.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/AnimatedControl.swift deleted file mode 100644 index ae2cdd563fad6e3490b83da334523ef3a06918d3..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/AnimatedControl.swift +++ /dev/null @@ -1,245 +0,0 @@ -// -// AnimatedControl.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -#if canImport(UIKit) -import UIKit -#elseif canImport(AppKit) -import AppKit -#endif - -// MARK: - AnimatedControl - -/// Lottie comes prepacked with a two Animated Controls, `AnimatedSwitch` and -/// `AnimatedButton`. Both of these controls are built on top of `AnimatedControl` -/// -/// `AnimatedControl` is a subclass of `UIControl` that provides an interactive -/// mechanism for controlling the visual state of an animation in response to -/// user actions. -/// -/// The `AnimatedControl` will show and hide layers depending on the current -/// `UIControl.State` of the control. -/// -/// Users of `AnimationControl` can set a Layer Name for each `UIControl.State`. -/// When the state is change the `AnimationControl` will change the visibility -/// of its layers. -/// -/// NOTE: Do not initialize directly. This is intended to be subclassed. -open class AnimatedControl: LottieControlType { - - // MARK: Lifecycle - - // MARK: Initializers - - public init( - animation: LottieAnimation?, - configuration: LottieConfiguration = .shared) - { - animationView = LottieAnimationView( - animation: animation, - configuration: configuration) - - super.init(frame: animation?.bounds ?? .zero) - commonInit() - } - - public init() { - animationView = LottieAnimationView() - super.init(frame: .zero) - commonInit() - } - - required public init?(coder aDecoder: NSCoder) { - animationView = LottieAnimationView() - super.init(coder: aDecoder) - commonInit() - } - - // MARK: Open - - // MARK: UIControl Overrides - - open override var isEnabled: Bool { - didSet { - updateForState() - } - } - - #if canImport(UIKit) - open override var isSelected: Bool { - didSet { - updateForState() - } - } - #endif - - open override var isHighlighted: Bool { - didSet { - updateForState() - } - } - - open override var intrinsicContentSize: CGSize { - animationView.intrinsicContentSize - } - - #if canImport(UIKit) - open override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { - updateForState() - return super.beginTracking(touch, with: event) - } - - open override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { - updateForState() - return super.continueTracking(touch, with: event) - } - - open override func endTracking(_ touch: UITouch?, with event: UIEvent?) { - updateForState() - return super.endTracking(touch, with: event) - } - - open override func cancelTracking(with event: UIEvent?) { - updateForState() - super.cancelTracking(with: event) - } - - #elseif canImport(AppKit) - open override func mouseDown(with mouseDownEvent: NSEvent) { - guard let window else { return } - - currentState = .highlighted - updateForState() - handle(LottieControlEvent(mouseDownEvent.type, inside: eventIsInside(mouseDownEvent))) - - // AppKit mouse-tracking loop from: - // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html#//apple_ref/doc/uid/10000060i-CH6-SW4 - var keepOn = true - while - keepOn, - let event = window.nextEvent( - matching: .any, - until: .distantFuture, - inMode: .eventTracking, - dequeue: true) - { - if event.type == .leftMouseUp { - keepOn = false - } - - let isInside = eventIsInside(event) - handle(LottieControlEvent(event.type, inside: isInside)) - - let expectedState = (isInside && keepOn) ? LottieNSControlState.highlighted : .normal - if currentState != expectedState { - currentState = expectedState - updateForState() - } - } - } - - func handle(_: LottieNSControlEvent) { - // To be overridden in subclasses - } - - private func eventIsInside(_ event: NSEvent) -> Bool { - let mouseLocation = convert(event.locationInWindow, from: nil) - return isMousePoint(mouseLocation, in: bounds) - } - #endif - - open func animationDidSet() { } - - // MARK: Public - - /// The animation view in which the animation is rendered. - public let animationView: LottieAnimationView - - /// The animation backing the animated control. - public var animation: LottieAnimation? { - didSet { - animationView.animation = animation - animationView.bounds = animation?.bounds ?? .zero - #if canImport(UIKit) - setNeedsLayout() - #elseif canImport(AppKit) - needsLayout = true - #endif - updateForState() - animationDidSet() - } - } - - /// The speed of the animation playback. Defaults to 1 - public var animationSpeed: CGFloat { - set { animationView.animationSpeed = newValue } - get { animationView.animationSpeed } - } - - /// Sets which Animation Layer should be visible for the given state. - public func setLayer(named: String, forState: LottieControlState) { - stateMap[forState.rawValue] = named - updateForState() - } - - /// Sets a ValueProvider for the specified keypath - public func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) { - animationView.setValueProvider(valueProvider, keypath: keypath) - } - - // MARK: Internal - - var stateMap: [UInt: String] = [:] - - #if canImport(UIKit) - var currentState: LottieControlState { - state - } - - #elseif canImport(AppKit) - var currentState = LottieControlState.normal - #endif - - func updateForState() { - guard let animationLayer = animationView.animationLayer else { return } - if - let layerName = stateMap[currentState.rawValue], - let stateLayer = animationLayer.layer(for: AnimationKeypath(keypath: layerName)) - { - for layer in animationLayer._animationLayers { - layer.isHidden = true - } - stateLayer.isHidden = false - } else { - for layer in animationLayer._animationLayers { - layer.isHidden = false - } - } - } - - // MARK: Private - - private func commonInit() { - #if canImport(UIKit) - animationView.clipsToBounds = false - clipsToBounds = true - #endif - - animationView.translatesAutoresizingMaskIntoConstraints = false - animationView.backgroundBehavior = .forceFinish - addSubview(animationView) - animationView.contentMode = .scaleAspectFit - - #if canImport(UIKit) - animationView.isUserInteractionEnabled = false - #endif - - animationView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - animationView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true - animationView.topAnchor.constraint(equalTo: topAnchor).isActive = true - animationView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/AnimatedSwitch.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/AnimatedSwitch.swift deleted file mode 100644 index 899e2bd823fb76238a094c3eae96f77e2503fc4a..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/AnimatedSwitch.swift +++ /dev/null @@ -1,271 +0,0 @@ -// -// AnimatedSwitch.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -#if canImport(UIKit) -import UIKit -#elseif canImport(AppKit) -import AppKit -#endif - -// MARK: - AnimatedSwitch - -/// An interactive switch with an 'On' and 'Off' state. When the user taps on the -/// switch the state is toggled and the appropriate animation is played. -/// -/// Both the 'On' and 'Off' have an animation play range associated with their state. -/// -/// Also available as a SwiftUI view (`LottieSwitch`). -open class AnimatedSwitch: AnimatedControl { - - // MARK: Lifecycle - - public override init( - animation: LottieAnimation?, - configuration: LottieConfiguration = .shared) - { - /// Generate a haptic generator if available. - #if os(iOS) - hapticGenerator = HapticGenerator() - #else - hapticGenerator = NullHapticGenerator() - #endif - super.init(animation: animation, configuration: configuration) - - #if canImport(UIKit) - isAccessibilityElement = true - #elseif canImport(AppKit) - setAccessibilityElement(true) - #endif - - updateOnState(isOn: _isOn, animated: false, shouldFireHaptics: false) - } - - public override init() { - /// Generate a haptic generator if available. - #if os(iOS) - hapticGenerator = HapticGenerator() - #else - hapticGenerator = NullHapticGenerator() - #endif - - super.init() - - #if canImport(UIKit) - isAccessibilityElement = true - #elseif canImport(AppKit) - setAccessibilityElement(true) - #endif - - updateOnState(isOn: _isOn, animated: false, shouldFireHaptics: false) - } - - required public init?(coder aDecoder: NSCoder) { - /// Generate a haptic generator if available. - #if os(iOS) - hapticGenerator = HapticGenerator() - #else - hapticGenerator = NullHapticGenerator() - #endif - super.init(coder: aDecoder) - - #if canImport(UIKit) - isAccessibilityElement = true - #elseif canImport(AppKit) - setAccessibilityElement(true) - #endif - } - - // MARK: Open - - open override func animationDidSet() { - updateOnState(isOn: _isOn, animated: animateUpdateWhenChangingAnimation, shouldFireHaptics: false) - } - - #if canImport(UIKit) - open override func endTracking(_ touch: UITouch?, with event: UIEvent?) { - super.endTracking(touch, with: event) - updateOnState(isOn: !_isOn, animated: true, shouldFireHaptics: true) - sendActions(for: .valueChanged) - } - - #elseif canImport(AppKit) - open override func handle(_ event: LottieNSControlEvent) { - super.handle(event) - - if event == .touchUpInside { - updateOnState(isOn: !_isOn, animated: true, shouldFireHaptics: true) - } - } - #endif - - // MARK: Public - - /// Defines what happens when the user taps the switch while an - /// animation is still in flight - public enum CancelBehavior { - case reverse // default - plays the current animation in reverse - case none // does not update the animation when canceled - } - - /// The cancel behavior for the switch. See CancelBehavior for options - public var cancelBehavior: CancelBehavior = .reverse - - /// If `false` the switch will not play the animation when changing between animations. - public var animateUpdateWhenChangingAnimation = true - - #if canImport(UIKit) - public override var accessibilityTraits: UIAccessibilityTraits { - set { super.accessibilityTraits = newValue } - get { super.accessibilityTraits.union(.button) } - } - #endif - - /// A closure that is called when the `isOn` state is updated - public var stateUpdated: ((_ isOn: Bool) -> Void)? - - /// The current state of the switch. - public var isOn: Bool { - set { - /// This is forwarded to a private variable because the animation needs to be updated without animation when set externally and with animation when set internally. - guard _isOn != newValue else { return } - updateOnState(isOn: newValue, animated: false, shouldFireHaptics: false) - } - get { - _isOn - } - } - - /// Set the state of the switch and specify animation and haptics - public func setIsOn(_ isOn: Bool, animated: Bool, shouldFireHaptics: Bool = true) { - guard isOn != _isOn else { return } - updateOnState(isOn: isOn, animated: animated, shouldFireHaptics: shouldFireHaptics) - } - - /// Sets the play range for the given state. When the switch is toggled, the animation range is played. - public func setProgressForState( - fromProgress: AnimationProgressTime, - toProgress: AnimationProgressTime, - forOnState: Bool) - { - if forOnState { - onStartProgress = fromProgress - onEndProgress = toProgress - } else { - offStartProgress = fromProgress - offEndProgress = toProgress - } - - updateOnState(isOn: _isOn, animated: false, shouldFireHaptics: false) - } - - // MARK: Internal - - private(set) var onStartProgress: CGFloat = 0 - private(set) var onEndProgress: CGFloat = 1 - private(set) var offStartProgress: CGFloat = 1 - private(set) var offEndProgress: CGFloat = 0 - - // MARK: Animation State - - func updateOnState(isOn: Bool, animated: Bool, shouldFireHaptics: Bool) { - _isOn = isOn - var startProgress = isOn ? onStartProgress : offStartProgress - var endProgress = isOn ? onEndProgress : offEndProgress - let finalProgress = endProgress - - if cancelBehavior == .reverse { - let realtimeProgress = animationView.realtimeAnimationProgress - - let previousStateStart = isOn ? offStartProgress : onStartProgress - let previousStateEnd = isOn ? offEndProgress : onEndProgress - if - realtimeProgress.isInRange( - min(previousStateStart, previousStateEnd), - max(previousStateStart, previousStateEnd)) - { - /// Animation is currently in the previous time range. Reverse the previous play. - startProgress = previousStateEnd - endProgress = previousStateStart - } - } - - updateAccessibilityLabel() - - guard animated == true else { - animationView.currentProgress = finalProgress - return - } - - if shouldFireHaptics { - hapticGenerator.generateImpact() - } - - animationView.play( - fromProgress: startProgress, - toProgress: endProgress, - loopMode: LottieLoopMode.playOnce, - completion: { [weak self] finished in - guard let self else { return } - - // For the Main Thread rendering engine, we freeze the animation at the expected final progress - // once the animation is complete. This isn't necessary on the Core Animation engine. - if finished, !(self.animationView.animationLayer is CoreAnimationLayer) { - self.animationView.currentProgress = finalProgress - } - }) - } - - // MARK: Fileprivate - - fileprivate var hapticGenerator: ImpactGenerator - - fileprivate var _isOn = false { - didSet { - stateUpdated?(_isOn) - } - } - - // MARK: Private - - private func updateAccessibilityLabel() { - let value = _isOn ? NSLocalizedString("On", comment: "On") : NSLocalizedString("Off", comment: "Off") - - #if canImport(UIKit) - accessibilityValue = value - #elseif canImport(AppKit) - setAccessibilityValue(value) - #endif - } - -} - -// MARK: - ImpactGenerator - -protocol ImpactGenerator { - func generateImpact() -} - -#if os(iOS) -class HapticGenerator: ImpactGenerator { - - // MARK: Internal - - func generateImpact() { - impact.impactOccurred() - } - - // MARK: Fileprivate - - fileprivate let impact = UIImpactFeedbackGenerator(style: .light) -} -#else -// MARK: - NullHapticGenerator - -class NullHapticGenerator: ImpactGenerator { - func generateImpact() { } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/LottieButton.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/LottieButton.swift deleted file mode 100644 index 577f9db43211e2bc43f41d950a8a3095e7713807..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/LottieButton.swift +++ /dev/null @@ -1,123 +0,0 @@ -// Created by Cal Stephens on 8/14/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -/// A wrapper which exposes Lottie's `AnimatedButton` to SwiftUI -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -public struct LottieButton: UIViewConfiguringSwiftUIView { - - // MARK: Lifecycle - - public init(animation: LottieAnimation?, action: @escaping () -> Void) { - self.animation = animation - self.action = action - } - - // MARK: Public - - public var body: some View { - AnimatedButton.swiftUIView { - let button = AnimatedButton(animation: animation, configuration: configuration) - button.performAction = action - return button - } - .configure { context in - // We check referential equality of the animation before updating as updating the - // animation has a side-effect of rebuilding the animation layer, and it would be - // prohibitive to do so on every state update. - if animation !== context.view.animationView.animation { - context.view.animationView.animation = animation - } - - #if os(macOS) - // Disable the intrinsic content size constraint on the inner animation view, - // or the Epoxy `SwiftUIMeasurementContainer` won't size this view correctly. - context.view.animationView.isVerticalContentSizeConstraintActive = false - context.view.animationView.isHorizontalContentSizeConstraintActive = false - #endif - } - .configurations(configurations) - } - - /// Returns a copy of this `LottieView` updated to have the given closure applied to its - /// represented `LottieAnimationView` whenever it is updated via the `updateUIView(…)` - /// or `updateNSView(…)` method. - public func configure(_ configure: @escaping (AnimatedButton) -> Void) -> Self { - var copy = self - copy.configurations.append { context in - configure(context.view) - } - return copy - } - - /// Returns a copy of this view with its `LottieConfiguration` updated to the given value. - public func configuration(_ configuration: LottieConfiguration) -> Self { - var copy = self - copy.configuration = configuration - - copy = copy.configure { view in - if view.animationView.configuration != configuration { - view.animationView.configuration = configuration - } - } - - return copy - } - - /// Returns a copy of this view configured to animate between the - /// given progress values when the given event is triggered - public func animate( - fromProgress: AnimationProgressTime, - toProgress: AnimationProgressTime, - on event: LottieControlEvent) - -> Self - { - configure { view in - // `setPlayRange` just modifies a dictionary, - // so we can just call it on every state update without diffing - view.setPlayRange(fromProgress: fromProgress, toProgress: toProgress, event: event) - } - } - - /// Returns a copy of this view configured to animate between the - /// given markers when the given event is triggered - public func animate( - fromMarker: String, - toMarker: String, - on event: LottieControlEvent) - -> Self - { - configure { view in - // `setPlayRange` just modifies a dictionary, - // so we can just call it on every state update without diffing - view.setPlayRange(fromMarker: fromMarker, toMarker: toMarker, event: event) - } - } - - /// Returns a copy of this view using the given value provider for the given keypath. - /// The value provider must be `Equatable` to avoid unnecessary state updates / re-renders. - public func valueProvider( - _ valueProvider: ValueProvider, - for keypath: AnimationKeypath) - -> Self - { - configure { view in - if (view.animationView.valueProviders[keypath] as? ValueProvider) != valueProvider { - view.animationView.setValueProvider(valueProvider, keypath: keypath) - } - } - } - - // MARK: Internal - - var configurations = [SwiftUIView.Configuration]() - - // MARK: Private - - private let animation: LottieAnimation? - private let action: () -> Void - private var configuration: LottieConfiguration = .shared -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/LottieSwitch.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/LottieSwitch.swift deleted file mode 100644 index ffb026955cd28bb7ff6bc440b1cc291e37047daf..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/LottieSwitch.swift +++ /dev/null @@ -1,146 +0,0 @@ -// Created by Cal Stephens on 8/11/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -#if canImport(SwiftUI) -import SwiftUI - -/// A wrapper which exposes Lottie's `AnimatedSwitch` to SwiftUI -@available(iOS 13.0, tvOS 13.0, macOS 10.15, *) -public struct LottieSwitch: UIViewConfiguringSwiftUIView { - - // MARK: Lifecycle - - public init(animation: LottieAnimation?) { - self.animation = animation - } - - // MARK: Public - - public var body: some View { - AnimatedSwitch.swiftUIView { - let animatedSwitch = AnimatedSwitch(animation: animation, configuration: configuration) - animatedSwitch.isOn = isOn?.wrappedValue ?? false - return animatedSwitch - } - .configure { context in - // We check referential equality of the animation before updating as updating the - // animation has a side-effect of rebuilding the animation layer, and it would be - // prohibitive to do so on every state update. - if animation !== context.view.animationView.animation { - context.view.animationView.animation = animation - } - - #if os(macOS) - // Disable the intrinsic content size constraint on the inner animation view, - // or the Epoxy `SwiftUIMeasurementContainer` won't size this view correctly. - context.view.animationView.isVerticalContentSizeConstraintActive = false - context.view.animationView.isHorizontalContentSizeConstraintActive = false - #endif - - if let isOn = isOn?.wrappedValue, isOn != context.view.isOn { - context.view.setIsOn(isOn, animated: true) - } - } - .configurations(configurations) - } - - /// Returns a copy of this `LottieView` updated to have the given closure applied to its - /// represented `LottieAnimationView` whenever it is updated via the `updateUIView(…)` - /// or `updateNSView(…)` method. - public func configure(_ configure: @escaping (AnimatedSwitch) -> Void) -> Self { - var copy = self - copy.configurations.append { context in - configure(context.view) - } - return copy - } - - /// Returns a copy of this view with its `LottieConfiguration` updated to the given value. - public func configuration(_ configuration: LottieConfiguration) -> Self { - var copy = self - copy.configuration = configuration - - copy = copy.configure { view in - if view.animationView.configuration != configuration { - view.animationView.configuration = configuration - } - } - - return copy - } - - /// Returns a copy of this view with the given `Binding` reflecting the `isOn` state of the switch. - public func isOn(_ binding: Binding) -> Self { - var copy = self - copy.isOn = binding - return copy.configure { view in - view.stateUpdated = { isOn in - DispatchQueue.main.async { - binding.wrappedValue = isOn - } - } - } - } - - /// Returns a copy of this view with the "on" animation configured - /// to start and end at the given progress values. - /// Defaults to playing the entire animation forwards (0...1). - public func onAnimation( - fromProgress onStartProgress: AnimationProgressTime, - toProgress onEndProgress: AnimationProgressTime) - -> Self - { - configure { view in - if onStartProgress != view.onStartProgress || onEndProgress != view.onEndProgress { - view.setProgressForState( - fromProgress: onStartProgress, - toProgress: onEndProgress, - forOnState: true) - } - } - } - - /// Returns a copy of this view with the "on" animation configured - /// to start and end at the given progress values. - /// Defaults to playing the entire animation backwards (1...0). - public func offAnimation( - fromProgress offStartProgress: AnimationProgressTime, - toProgress offEndProgress: AnimationProgressTime) - -> Self - { - configure { view in - if offStartProgress != view.offStartProgress || offEndProgress != view.offEndProgress { - view.setProgressForState( - fromProgress: offStartProgress, - toProgress: offEndProgress, - forOnState: false) - } - } - } - - /// Returns a copy of this view using the given value provider for the given keypath. - /// The value provider must be `Equatable` to avoid unnecessary state updates / re-renders. - public func valueProvider( - _ valueProvider: ValueProvider, - for keypath: AnimationKeypath) - -> Self - { - configure { view in - if (view.animationView.valueProviders[keypath] as? ValueProvider) != valueProvider { - view.animationView.setValueProvider(valueProvider, keypath: keypath) - } - } - } - - // MARK: Internal - - var configurations = [SwiftUIView.Configuration]() - - // MARK: Private - - private let animation: LottieAnimation? - private var configuration: LottieConfiguration = .shared - private var isOn: Binding? - -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/LottieViewType.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/LottieViewType.swift deleted file mode 100644 index 363183f71152bfe5af3f2ef25f6bfea08b404f83..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Controls/LottieViewType.swift +++ /dev/null @@ -1,79 +0,0 @@ -// Created by Cal Stephens on 8/11/23. -// Copyright © 2023 Airbnb Inc. All rights reserved. - -#if canImport(UIKit) -import UIKit - -/// The control base type for this platform. -/// - `UIControl` on iOS / tvOS and `NSControl` on macOS. -public typealias LottieControlType = UIControl - -/// The `State` type of `LottieControlType` -/// - `UIControl.State` on iOS / tvOS and `NSControl.StateValue` on macOS. -public typealias LottieControlState = UIControl.State - -/// The event type handled by the `LottieControlType` component for this platform. -/// - `UIControl.Event` on iOS / tvOS and `LottieNSControlEvent` on macOS. -public typealias LottieControlEvent = UIControl.Event - -extension LottieControlEvent { - var id: AnyHashable { - rawValue - } -} -#else -import AppKit - -/// The control base type for this platform. -/// - `UIControl` on iOS / tvOS and `NSControl` on macOS. -public typealias LottieControlType = NSControl - -/// The `State` type of `LottieControlType` -/// - `UIControl.State` on iOS / tvOS and `NSControl.StateValue` on macOS. -public typealias LottieControlState = LottieNSControlState - -/// AppKit equivalent of `UIControl.State` for `AnimatedControl` -public enum LottieNSControlState: UInt, RawRepresentable { - /// The normal, or default, state of a control where the control is enabled but neither selected nor highlighted. - case normal - /// The highlighted state of a control. - case highlighted -} - -/// The event type handled by the `LottieControlType` component for this platform. -/// - `UIControl.Event` on iOS / tvOS and `LottieNSControlEvent` on macOS. -public typealias LottieControlEvent = LottieNSControlEvent - -public struct LottieNSControlEvent: Equatable { - - // MARK: Lifecycle - - public init(_ event: NSEvent.EventType, inside: Bool) { - self.event = event - self.inside = inside - } - - // MARK: Public - - /// macOS equivalent to `UIControl.Event.touchDown` - public static let touchDown = LottieNSControlEvent(.leftMouseDown, inside: true) - - /// macOS equivalent to `UIControl.Event.touchUpInside` - public static let touchUpInside = LottieNSControlEvent(.leftMouseUp, inside: true) - - /// macOS equivalent to `UIControl.Event.touchUpInside` - public static let touchUpOutside = LottieNSControlEvent(.leftMouseUp, inside: false) - - /// The underlying `NSEvent.EventType` of this event, which is roughly equivalent to `UIControl.Event` - public var event: NSEvent.EventType - - /// Whether or not the mouse must be inside the control. - public var inside: Bool - - // MARK: Internal - - var id: AnyHashable { - [AnyHashable(event.rawValue), AnyHashable(inside)] - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/Cache/DotLottieCache.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/Cache/DotLottieCache.swift deleted file mode 100644 index 1e7d00b11be9b50b41a17929e9cdae00ad1581be..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/Cache/DotLottieCache.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// LRUDotLottieCache.swift -// Lottie -// -// Created by Evandro Hoffmann on 20/10/22. -// - -import Foundation - -// MARK: - DotLottieCache - -/// A DotLottie Cache that will store lottie files up to `cacheSize`. -/// -/// Once `cacheSize` is reached, the least recently used lottie will be ejected. -/// The default size of the cache is 100. -public class DotLottieCache: DotLottieCacheProvider { - - // MARK: Lifecycle - - public init() { - cache.countLimit = Self.defaultCacheCountLimit - } - - // MARK: Public - - /// The global shared Cache. - public static let sharedCache = DotLottieCache() - - /// The size of the cache. - public var cacheSize = defaultCacheCountLimit { - didSet { - cache.countLimit = cacheSize - } - } - - /// Clears the Cache. - public func clearCache() { - cache.removeAllValues() - } - - public func file(forKey key: String) -> DotLottieFile? { - cache.value(forKey: key) - } - - public func setFile(_ lottie: DotLottieFile, forKey key: String) { - cache.setValue(lottie, forKey: key) - } - - // MARK: Private - - private static let defaultCacheCountLimit = 100 - - /// The underlying storage of this cache. - /// - We use the `LRUCache` library instead of `NSCache`, because `NSCache` - /// clears all cached values when the app is backgrounded instead of - /// only when the app receives a memory warning notification. - private var cache = LRUCache() - -} - -// MARK: Sendable - -// DotLottieCacheProvider has a Sendable requirement, but we can't -// redesign DotLottieCache to be properly Sendable without making breaking changes. -// swiftlint:disable:next no_unchecked_sendable -extension DotLottieCache: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/Cache/DotLottieCacheProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/Cache/DotLottieCacheProvider.swift deleted file mode 100644 index 6a59cba287d44e2859bac5ac101cb2158d3decac..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/Cache/DotLottieCacheProvider.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// DotLottieCacheProvider.swift -// Lottie -// -// Created by Evandro Hoffmann on 20/10/22. -// - -/// `DotLottieCacheProvider` is a protocol that describes a DotLottie Cache. -/// DotLottie Cache is used when loading `DotLottie` models. Using a DotLottie Cache -/// can increase performance when loading an animation multiple times. -/// -/// Lottie comes with a prebuilt LRU DotLottie Cache. -public protocol DotLottieCacheProvider: Sendable { - - func file(forKey: String) -> DotLottieFile? - - func setFile(_ lottie: DotLottieFile, forKey: String) - - func clearCache() - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/DotLottieConfiguration.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/DotLottieConfiguration.swift deleted file mode 100644 index 2de4b746c95ee9bd8caec0899fc20487c647bde7..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/DotLottieConfiguration.swift +++ /dev/null @@ -1,72 +0,0 @@ -// -// DotLottieConfiguration.swift -// Lottie -// -// Created by Evandro Hoffmann on 19/10/22. -// - -// MARK: - DotLottieConfiguration - -/// The `DotLottieConfiguration` model holds the presets extracted from DotLottieAnimation -/// - The presets are used as input to setup `LottieAnimationView` before playing the animation. -public struct DotLottieConfiguration { - - // MARK: Public - - /// id of the animation - public var id: String - - /// Loop behavior of animation - public var loopMode: LottieLoopMode - - /// Playback speed of animation - public var speed: Double - - /// Animation Image Provider - public var imageProvider: AnimationImageProvider? { - dotLottieImageProvider - } - - // MARK: Internal - - /// The underlying `DotLottieImageProvider` used by this dotLottie animation - var dotLottieImageProvider: DotLottieImageProvider? -} - -// MARK: - DotLottieConfigurationComponents - -/// Components of the `DotLottieConfiguration` to apply to the `LottieAnimationView`. -/// - When using `LottieView`, if the component is selected to be applied it will -/// override any value provided via other `LottieView` APIs. -public struct DotLottieConfigurationComponents: OptionSet { - - // MARK: Lifecycle - - public init(rawValue: Int) { - self.rawValue = rawValue - } - - // MARK: Public - - /// `DotLottieConfiguration.imageProvider` will be applied to the `LottieAnimationView` - /// - When using `LottieView`, the image provider from the dotLottie animation will override - /// the image provider applied manually using `LottieView.imageProvider(...)`. - public static let imageProvider = DotLottieConfigurationComponents(rawValue: 1 << 0) - - /// `DotLottieConfigurationMode.loopMode` will be applied to the `LottieAnimationView`. - /// - When using `LottieView`, the loop mode from the dotLottie animation will override - /// the loopMode applied by any playback method. - public static let loopMode = DotLottieConfigurationComponents(rawValue: 1 << 1) - - /// `DotLottieConfigurationMode.speed` will be applied to the `LottieAnimationView`. - /// - When using `LottieView`, the speed from the dotLottie animation will override - /// the speed applied manually using `LottieView.animationSpeed(...)`. - public static let animationSpeed = DotLottieConfigurationComponents(rawValue: 1 << 2) - - public static let all: DotLottieConfigurationComponents = [.imageProvider, .loopMode, .animationSpeed] - - public static let none: DotLottieConfigurationComponents = [] - - public let rawValue: Int - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/DotLottieFile.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/DotLottieFile.swift deleted file mode 100644 index d774d094ac921b5a3feda2cdc5b320ba63279067..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/DotLottieFile.swift +++ /dev/null @@ -1,154 +0,0 @@ -// -// DotLottie.swift -// Lottie -// -// Created by Evandro Harrison Hoffmann on 27/06/2020. -// - -import Foundation - -// MARK: - DotLottieFile - -/// Detailed .lottie file structure -public final class DotLottieFile { - - // MARK: Lifecycle - - /// Loads `DotLottie` from `Data` object containing a compressed animation. - /// - /// - Parameters: - /// - data: Data of .lottie file - /// - filename: Name of .lottie file - /// - Returns: Deserialized `DotLottie`. Optional. - init(data: Data, filename: String) throws { - fileUrl = DotLottieUtils.tempDirectoryURL.appendingPathComponent(filename.asFilename()) - try decompress(data: data, to: fileUrl) - } - - // MARK: Public - - /// Definition for a single animation within a `DotLottieFile` - public struct Animation { - public let animation: LottieAnimation - public let configuration: DotLottieConfiguration - } - - /// List of `LottieAnimation` in the file - public private(set) var animations: [Animation] = [] - - // MARK: Internal - - /// Image provider for animations - private(set) var imageProvider: DotLottieImageProvider? - - /// Animations folder url - lazy var animationsUrl: URL = fileUrl.appendingPathComponent("\(DotLottieFile.animationsFolderName)") - - /// All files in animations folder - lazy var animationUrls: [URL] = FileManager.default.urls(for: animationsUrl) ?? [] - - /// Images folder url - lazy var imagesUrl: URL = fileUrl.appendingPathComponent("\(DotLottieFile.imagesFolderName)") - - /// All images in images folder - lazy var imageUrls: [URL] = FileManager.default.urls(for: imagesUrl) ?? [] - - /// The `LottieAnimation` and `DotLottieConfiguration` for the given animation ID in this file - func animation(for id: String? = nil) -> DotLottieFile.Animation? { - if let id { - return animations.first(where: { $0.configuration.id == id }) - } else { - return animations.first - } - } - - /// The `LottieAnimation` and `DotLottieConfiguration` for the given animation index in this file - func animation(at index: Int) -> DotLottieFile.Animation? { - guard index < animations.count else { return nil } - return animations[index] - } - - // MARK: Private - - private static let manifestFileName = "manifest.json" - private static let animationsFolderName = "animations" - private static let imagesFolderName = "images" - - private let fileUrl: URL - - /// Decompresses .lottie file from `URL` and saves to local temp folder - /// - /// - Parameters: - /// - url: url to .lottie file - /// - destinationURL: url to destination of decompression contents - private func decompress(from url: URL, to destinationURL: URL) throws { - try? FileManager.default.removeItem(at: destinationURL) - try FileManager.default.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil) - try FileManager.default.unzipItem(at: url, to: destinationURL) - try loadContent() - try? FileManager.default.removeItem(at: destinationURL) - try? FileManager.default.removeItem(at: url) - } - - /// Decompresses .lottie file from `Data` and saves to local temp folder - /// - /// - Parameters: - /// - url: url to .lottie file - /// - destinationURL: url to destination of decompression contents - private func decompress(data: Data, to destinationURL: URL) throws { - let url = destinationURL.appendingPathExtension("lottie") - try FileManager.default.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil) - try data.write(to: url) - try decompress(from: url, to: destinationURL) - } - - /// Loads file content to memory - private func loadContent() throws { - imageProvider = DotLottieImageProvider(filepath: imagesUrl) - - animations = try loadManifest().animations.map { dotLottieAnimation in - let animation = try dotLottieAnimation.animation(url: animationsUrl) - let configuration = DotLottieConfiguration( - id: dotLottieAnimation.id, - loopMode: dotLottieAnimation.loopMode, - speed: dotLottieAnimation.animationSpeed, - dotLottieImageProvider: imageProvider) - - return DotLottieFile.Animation( - animation: animation, - configuration: configuration) - } - } - - private func loadManifest() throws -> DotLottieManifest { - let path = fileUrl.appendingPathComponent(DotLottieFile.manifestFileName) - return try DotLottieManifest.load(from: path) - } -} - -extension String { - - // MARK: Fileprivate - - fileprivate func asFilename() -> String { - lastPathComponent().removingPathExtension() - } - - // MARK: Private - - private func lastPathComponent() -> String { - (self as NSString).lastPathComponent - } - - private func removingPathExtension() -> String { - (self as NSString).deletingPathExtension - } -} - -// MARK: - DotLottieFile + Sendable - -// Mark `DotLottieFile` as `@unchecked Sendable` to allow it to be used when strict concurrency is enabled. -// In the future, it may be necessary to make changes to the internal implementation of `DotLottieFile` -// to make it truly thread-safe. -// swiftlint:disable:next no_unchecked_sendable -extension DotLottieFile: @unchecked Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/DotLottieFileHelpers.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/DotLottieFileHelpers.swift deleted file mode 100644 index bd9c09f38afe86f8f26cfc270ac57f5a2d789d6a..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DotLottie/DotLottieFileHelpers.swift +++ /dev/null @@ -1,378 +0,0 @@ -// -// DotLottieFileHelpers.swift -// Lottie -// -// Created by Evandro Hoffmann on 20/10/22. -// - -import Foundation - -extension DotLottieFile { - - public enum SynchronouslyBlockingCurrentThread { - /// Loads an DotLottie from a specific filepath synchronously. Returns a `Result` - /// Please use the asynchronous methods whenever possible. This operation will block the Thread it is running in. - /// - /// - Parameter filepath: The absolute filepath of the lottie to load. EG "/User/Me/starAnimation.lottie" - /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional. - public static func loadedFrom( - filepath: String, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache) - -> Result - { - LottieLogger.shared.assert( - !Thread.isMainThread, - "`DotLottieFile.SynchronouslyBlockingCurrentThread` methods shouldn't be called on the main thread.") - - /// Check cache for lottie - if - let dotLottieCache, - let lottie = dotLottieCache.file(forKey: filepath) - { - return .success(lottie) - } - - do { - /// Decode the lottie. - let url = URL(fileURLWithPath: filepath) - let data = try Data(contentsOf: url) - let lottie = try DotLottieFile(data: data, filename: url.deletingPathExtension().lastPathComponent) - dotLottieCache?.setFile(lottie, forKey: filepath) - return .success(lottie) - } catch { - /// Decoding Error. - return .failure(error) - } - } - - /// Loads a DotLottie model from a bundle by its name synchronously. Returns a `Result` - /// Please use the asynchronous methods whenever possible. This operation will block the Thread it is running in. - /// - /// - Parameter name: The name of the lottie file without the lottie extension. EG "StarAnimation" - /// - Parameter bundle: The bundle in which the lottie is located. Defaults to `Bundle.main` - /// - Parameter subdirectory: A subdirectory in the bundle in which the lottie is located. Optional. - /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional. - public static func named( - _ name: String, - bundle: Bundle = Bundle.main, - subdirectory: String? = nil, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache) - -> Result - { - LottieLogger.shared.assert( - !Thread.isMainThread, - "`DotLottieFile.SynchronouslyBlockingCurrentThread` methods shouldn't be called on the main thread.") - - /// Create a cache key for the lottie. - let cacheKey = bundle.bundlePath + (subdirectory ?? "") + "/" + name - - /// Check cache for lottie - if - let dotLottieCache, - let lottie = dotLottieCache.file(forKey: cacheKey) - { - return .success(lottie) - } - - do { - /// Decode animation. - let data = try bundle.dotLottieData(name, subdirectory: subdirectory) - let lottie = try DotLottieFile(data: data, filename: name) - dotLottieCache?.setFile(lottie, forKey: cacheKey) - return .success(lottie) - } catch { - /// Decoding error. - LottieLogger.shared.warn("Error when decoding lottie \"\(name)\": \(error)") - return .failure(error) - } - } - - /// Loads an DotLottie from a data synchronously. Returns a `Result` - /// - /// Please use the asynchronous methods whenever possible. This operation will block the Thread it is running in. - /// - /// - Parameters: - /// - data: The data(`Foundation.Data`) object to load DotLottie from - /// - filename: The name of the lottie file without the lottie extension. eg. "StarAnimation" - public static func loadedFrom( - data: Data, - filename: String) - -> Result - { - LottieLogger.shared.assert( - !Thread.isMainThread, - "`DotLottieFile.SynchronouslyBlockingCurrentThread` methods shouldn't be called on the main thread.") - - do { - let dotLottieFile = try DotLottieFile(data: data, filename: filename) - return .success(dotLottieFile) - } catch { - return .failure(error) - } - } - } - - /// Loads a DotLottie model from a bundle by its name. Returns `nil` if a file is not found. - /// - /// - Parameter name: The name of the lottie file without the lottie extension. EG "StarAnimation" - /// - Parameter bundle: The bundle in which the lottie is located. Defaults to `Bundle.main` - /// - Parameter subdirectory: A subdirectory in the bundle in which the lottie is located. Optional. - /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional. - @available(iOS 13.0, macOS 10.15, tvOS 13.0, *) - public static func named( - _ name: String, - bundle: Bundle = Bundle.main, - subdirectory: String? = nil, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache) - async throws -> DotLottieFile - { - try await withCheckedThrowingContinuation { continuation in - DotLottieFile.named(name, bundle: bundle, subdirectory: subdirectory, dotLottieCache: dotLottieCache) { result in - continuation.resume(with: result) - } - } - } - - /// Loads a DotLottie model from a bundle by its name. Returns `nil` if a file is not found. - /// - /// - Parameter name: The name of the lottie file without the lottie extension. EG "StarAnimation" - /// - Parameter bundle: The bundle in which the lottie is located. Defaults to `Bundle.main` - /// - Parameter subdirectory: A subdirectory in the bundle in which the lottie is located. Optional. - /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional. - /// - Parameter dispatchQueue: A dispatch queue used to load animations. Defaults to `DispatchQueue.global()`. Optional. - /// - Parameter handleResult: A closure to be called when the file has loaded. - public static func named( - _ name: String, - bundle: Bundle = Bundle.main, - subdirectory: String? = nil, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache, - dispatchQueue: DispatchQueue = .dotLottie, - handleResult: @escaping (Result) -> Void) - { - dispatchQueue.async { - let result = SynchronouslyBlockingCurrentThread.named( - name, - bundle: bundle, - subdirectory: subdirectory, - dotLottieCache: dotLottieCache) - - DispatchQueue.main.async { - handleResult(result) - } - } - } - - /// Loads an DotLottie from a specific filepath. - /// - Parameter filepath: The absolute filepath of the lottie to load. EG "/User/Me/starAnimation.lottie" - /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional. - @available(iOS 13.0, macOS 10.15, tvOS 13.0, *) - public static func loadedFrom( - filepath: String, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache) - async throws -> DotLottieFile - { - try await withCheckedThrowingContinuation { continuation in - DotLottieFile.loadedFrom(filepath: filepath, dotLottieCache: dotLottieCache) { result in - continuation.resume(with: result) - } - } - } - - /// Loads an DotLottie from a specific filepath. - /// - Parameter filepath: The absolute filepath of the lottie to load. EG "/User/Me/starAnimation.lottie" - /// - Parameter dotLottieCache: A cache for holding loaded lotties. Defaults to `LRUDotLottieCache.sharedCache`. Optional. - /// - Parameter dispatchQueue: A dispatch queue used to load animations. Defaults to `DispatchQueue.global()`. Optional. - /// - Parameter handleResult: A closure to be called when the file has loaded. - public static func loadedFrom( - filepath: String, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache, - dispatchQueue: DispatchQueue = .dotLottie, - handleResult: @escaping (Result) -> Void) - { - dispatchQueue.async { - let result = SynchronouslyBlockingCurrentThread.loadedFrom( - filepath: filepath, - dotLottieCache: dotLottieCache) - - DispatchQueue.main.async { - handleResult(result) - } - } - } - - /// Loads a DotLottie model from the asset catalog by its name. Returns `nil` if a lottie is not found. - /// - Parameter name: The name of the lottie file in the asset catalog. EG "StarAnimation" - /// - Parameter bundle: The bundle in which the lottie is located. Defaults to `Bundle.main` - /// - Parameter dotLottieCache: A cache for holding loaded lottie files. Defaults to `LRUDotLottieCache.sharedCache` Optional. - @available(iOS 13.0, macOS 10.15, tvOS 13.0, *) - public static func asset( - named name: String, - bundle: Bundle = Bundle.main, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache) - async throws -> DotLottieFile - { - try await withCheckedThrowingContinuation { continuation in - DotLottieFile.asset(named: name, bundle: bundle, dotLottieCache: dotLottieCache) { result in - continuation.resume(with: result) - } - } - } - - /// Loads a DotLottie model from the asset catalog by its name. Returns `nil` if a lottie is not found. - /// - Parameter name: The name of the lottie file in the asset catalog. EG "StarAnimation" - /// - Parameter bundle: The bundle in which the lottie is located. Defaults to `Bundle.main` - /// - Parameter dotLottieCache: A cache for holding loaded lottie files. Defaults to `LRUDotLottieCache.sharedCache` Optional. - /// - Parameter dispatchQueue: A dispatch queue used to load animations. Defaults to `DispatchQueue.global()`. Optional. - /// - Parameter handleResult: A closure to be called when the file has loaded. - public static func asset( - named name: String, - bundle: Bundle = Bundle.main, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache, - dispatchQueue: DispatchQueue = .dotLottie, - handleResult: @escaping (Result) -> Void) - { - dispatchQueue.async { - /// Create a cache key for the lottie. - let cacheKey = bundle.bundlePath + "/" + name - - /// Check cache for lottie - if - let dotLottieCache, - let lottie = dotLottieCache.file(forKey: cacheKey) - { - /// If found, return the lottie. - DispatchQueue.main.async { - handleResult(.success(lottie)) - } - return - } - - do { - /// Load data from Asset - let data = try Data(assetName: name, in: bundle) - - /// Decode lottie. - let lottie = try DotLottieFile(data: data, filename: name) - dotLottieCache?.setFile(lottie, forKey: cacheKey) - DispatchQueue.main.async { - handleResult(.success(lottie)) - } - } catch { - /// Decoding error. - DispatchQueue.main.async { - handleResult(.failure(error)) - } - } - } - } - - /// Loads a DotLottie animation asynchronously from the URL. - /// - /// - Parameter url: The url to load the animation from. - /// - Parameter animationCache: A cache for holding loaded animations. Defaults to `LRUAnimationCache.sharedCache`. Optional. - @available(iOS 13.0, macOS 10.15, tvOS 13.0, *) - public static func loadedFrom( - url: URL, - session: URLSession = .shared, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache) - async throws -> DotLottieFile - { - try await withCheckedThrowingContinuation { continuation in - DotLottieFile.loadedFrom(url: url, session: session, dotLottieCache: dotLottieCache) { result in - continuation.resume(with: result) - } - } - } - - /// Loads a DotLottie animation asynchronously from the URL. - /// - /// - Parameter url: The url to load the animation from. - /// - Parameter animationCache: A cache for holding loaded animations. Defaults to `LRUAnimationCache.sharedCache`. Optional. - /// - Parameter handleResult: A closure to be called when the animation has loaded. - public static func loadedFrom( - url: URL, - session: URLSession = .shared, - dotLottieCache: DotLottieCacheProvider? = DotLottieCache.sharedCache, - handleResult: @escaping (Result) -> Void) - { - if let dotLottieCache, let lottie = dotLottieCache.file(forKey: url.absoluteString) { - handleResult(.success(lottie)) - } else { - let task = session.dataTask(with: url) { data, _, error in - do { - if let error { - throw error - } - guard let data else { - throw DotLottieError.noDataLoaded - } - let lottie = try DotLottieFile(data: data, filename: url.deletingPathExtension().lastPathComponent) - DispatchQueue.main.async { - dotLottieCache?.setFile(lottie, forKey: url.absoluteString) - handleResult(.success(lottie)) - } - } catch { - DispatchQueue.main.async { - handleResult(.failure(error)) - } - } - } - task.resume() - } - } - - /// Loads an DotLottie from a data asynchronously. - /// - /// - Parameters: - /// - data: The data(`Foundation.Data`) object to load DotLottie from - /// - filename: The name of the lottie file without the lottie extension. eg. "StarAnimation" - /// - dispatchQueue: A dispatch queue used to load animations. Defaults to `DispatchQueue.global()`. Optional. - /// - handleResult: A closure to be called when the file has loaded. - public static func loadedFrom( - data: Data, - filename: String, - dispatchQueue: DispatchQueue = .dotLottie, - handleResult: @escaping (Result) -> Void) - { - dispatchQueue.async { - do { - let dotLottie = try DotLottieFile(data: data, filename: filename) - DispatchQueue.main.async { - handleResult(.success(dotLottie)) - } - } catch { - DispatchQueue.main.async { - handleResult(.failure(error)) - } - } - } - } - - /// Loads an DotLottie from a data asynchronously. - /// - /// - Parameters: - /// - data: The data(`Foundation.Data`) object to load DotLottie from - /// - filename: The name of the lottie file without the lottie extension. eg. "StarAnimation" - /// - dispatchQueue: A dispatch queue used to load animations. Defaults to `DispatchQueue.global()`. Optional. - @available(iOS 13.0, macOS 10.15, tvOS 13.0, *) - public static func loadedFrom( - data: Data, - filename: String, - dispatchQueue: DispatchQueue = .dotLottie) - async throws -> DotLottieFile - { - try await withCheckedThrowingContinuation { continuation in - loadedFrom(data: data, filename: filename, dispatchQueue: dispatchQueue) { result in - continuation.resume(with: result) - } - } - } -} - -extension DispatchQueue { - /// A serial dispatch queue ensures that IO related to loading dot Lottie files don't overlap, - /// which can trigger file loading errors due to concurrent unzipping on a single archive. - public static let dotLottie = DispatchQueue( - label: "com.airbnb.lottie.dot-lottie", - qos: .userInitiated) -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/AnimationKeypath.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/AnimationKeypath.swift deleted file mode 100644 index 425c1564845966b71783e3c3b708450a42644f63..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/AnimationKeypath.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// AnimationKeypath.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -/// `AnimationKeypath` is an object that describes a keypath search for nodes in the -/// animation JSON. `AnimationKeypath` matches views and properties inside of `LottieAnimationView` -/// to their backing `LottieAnimation` model by name. -/// -/// A keypath can be used to set properties on an existing animation, or can be validated -/// with an existing `LottieAnimation`. -/// -/// `AnimationKeypath` can describe a specific object, or can use wildcards for fuzzy matching -/// of objects. Acceptable wildcards are either "*" (star) or "**" (double star). -/// Single star will search a single depth for the next object. -/// Double star will search any depth. -/// -/// Read More at https://airbnb.io/lottie/#/ios?id=dynamic-animation-properties -/// -/// EG: -/// @"Layer.Shape Group.Stroke 1.Color" -/// Represents a specific color node on a specific stroke. -/// -/// @"**.Stroke 1.Color" -/// Represents the color node for every Stroke named "Stroke 1" in the animation. -public struct AnimationKeypath: Hashable, ExpressibleByStringLiteral { - - // MARK: Lifecycle - - /// Creates a keypath from a dot-separated string. The string is separated by "." - public init(keypath: String) { - keys = keypath.components(separatedBy: ".") - } - - /// Creates a keypath from a dot-separated string - public init(stringLiteral: String) { - self.init(keypath: stringLiteral) - } - - /// Creates a keypath from a list of strings. - public init(keys: [String]) { - self.keys = keys - } - - // MARK: Public - - /// The dot-separated key values that represent this keypath. - public internal(set) var keys: [String] - - /// The `String` representation of this keypath - public var string: String { - keys.joined(separator: ".") - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/AnyValueProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/AnyValueProvider.swift deleted file mode 100644 index 4bd912bdce1acba6e71c159fe2c2e773a4567074..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/AnyValueProvider.swift +++ /dev/null @@ -1,131 +0,0 @@ -// -// AnyValueProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/30/19. -// - -import Foundation - -// MARK: - AnyValueProvider - -/// `AnyValueProvider` is a protocol that return animation data for a property at a -/// given time. Every frame a `LottieAnimationView` queries all of its properties and asks -/// if their ValueProvider has an update. If it does the LottieAnimationView will read the -/// property and update that portion of the animation. -/// -/// Value Providers can be used to dynamically set animation properties at run time. -public protocol AnyValueProvider { - - /// The Type of the value provider - var valueType: Any.Type { get } - - /// The type-erased storage for this Value Provider - var typeErasedStorage: AnyValueProviderStorage { get } - - /// Asks the provider if it has an update for the given frame. - func hasUpdate(frame: AnimationFrameTime) -> Bool - -} - -extension AnyValueProvider { - /// Asks the provider to update the container with its value for the frame. - public func value(frame: AnimationFrameTime) -> Any { - typeErasedStorage.value(frame: frame) - } -} - -// MARK: - ValueProvider - -/// A base protocol for strongly-typed Value Providers -protocol ValueProvider: AnyValueProvider { - associatedtype Value: AnyInterpolatable - - /// The strongly-typed storage for this Value Provider - var storage: ValueProviderStorage { get } -} - -extension ValueProvider { - public var typeErasedStorage: AnyValueProviderStorage { - switch storage { - case .closure(let typedClosure): - return .closure(typedClosure) - - case .singleValue(let typedValue): - return .singleValue(typedValue) - - case .keyframes(let keyframes): - return .keyframes( - keyframes.map { keyframe in - keyframe.withValue(keyframe.value as Any) - }, - interpolate: storage.value(frame:)) - } - } -} - -// MARK: - ValueProviderStorage - -/// The underlying storage of a `ValueProvider` -public enum ValueProviderStorage { - /// The value provider stores a single value that is used on all frames - case singleValue(T) - - /// The value provider stores a group of keyframes - /// - The main-thread rendering engine interpolates values in these keyframes - /// using `T`'s `Interpolatable` implementation. - /// - The Core Animation rendering engine constructs a `CAKeyframeAnimation` - /// using these keyframes. The Core Animation render server performs - /// the interpolation, without calling `T`'s `Interpolatable` implementation. - case keyframes([Keyframe]) - - /// The value provider stores a closure that is invoked on every frame - /// - This is only supported by the main-thread rendering engine - case closure((AnimationFrameTime) -> T) - - // MARK: Internal - - func value(frame: AnimationFrameTime) -> T { - switch self { - case .singleValue(let value): - return value - - case .closure(let closure): - return closure(frame) - - case .keyframes(let keyframes): - return KeyframeInterpolator(keyframes: ContiguousArray(keyframes)).storage.value(frame: frame) - } - } -} - -// MARK: - AnyValueProviderStorage - -/// A type-erased representation of `ValueProviderStorage` -public enum AnyValueProviderStorage { - /// The value provider stores a single value that is used on all frames - case singleValue(Any) - - /// The value provider stores a group of keyframes - /// - Since we can't interpolate a type-erased `KeyframeGroup`, - /// the interpolation has to be performed in the `interpolate` closure. - case keyframes([Keyframe], interpolate: (AnimationFrameTime) -> Any) - - /// The value provider stores a closure that is invoked on every frame - case closure((AnimationFrameTime) -> Any) - - // MARK: Internal - - func value(frame: AnimationFrameTime) -> Any { - switch self { - case .singleValue(let value): - return value - - case .closure(let closure): - return closure(frame) - - case .keyframes(_, let valueForFrame): - return valueForFrame(frame) - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift deleted file mode 100644 index a8680986c97be03db73286dfb589aaa5549fc62a..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// ColorValueProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -import CoreGraphics -import Foundation - -// MARK: - ColorValueProvider - -/// A `ValueProvider` that returns a CGColor Value -public final class ColorValueProvider: ValueProvider { - - // MARK: Lifecycle - - /// Initializes with a block provider - public init(block: @escaping ColorValueBlock) { - self.block = block - color = LottieColor(r: 0, g: 0, b: 0, a: 1) - keyframes = nil - identity = UUID() - } - - /// Initializes with a single color. - public init(_ color: LottieColor) { - self.color = color - block = nil - keyframes = nil - hasUpdate = true - identity = color - } - - /// Initializes with multiple colors, with timing information - public init(_ keyframes: [Keyframe]) { - self.keyframes = keyframes - color = LottieColor(r: 0, g: 0, b: 0, a: 1) - block = nil - hasUpdate = true - identity = keyframes - } - - // MARK: Public - - /// Returns a LottieColor for a CGColor(Frame Time) - public typealias ColorValueBlock = (CGFloat) -> LottieColor - - /// The color value of the provider. - public var color: LottieColor { - didSet { - hasUpdate = true - } - } - - // MARK: ValueProvider Protocol - - public var valueType: Any.Type { - LottieColor.self - } - - public var storage: ValueProviderStorage { - if let block { - return .closure { frame in - self.hasUpdate = false - return block(frame) - } - } else if let keyframes { - return .keyframes(keyframes) - } else { - hasUpdate = false - return .singleValue(color) - } - } - - public func hasUpdate(frame _: CGFloat) -> Bool { - if block != nil { - return true - } - return hasUpdate - } - - // MARK: Private - - private var hasUpdate = true - - private var block: ColorValueBlock? - private var keyframes: [Keyframe]? - private var identity: AnyHashable -} - -// MARK: Equatable - -extension ColorValueProvider: Equatable { - public static func ==(_ lhs: ColorValueProvider, _ rhs: ColorValueProvider) -> Bool { - lhs.identity == rhs.identity - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift deleted file mode 100644 index fb22c2b9efdf90ed2211c10d48ce7bfc8951cb15..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift +++ /dev/null @@ -1,83 +0,0 @@ -// -// DoubleValueProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -import CoreGraphics -import Foundation - -// MARK: - FloatValueProvider - -/// A `ValueProvider` that returns a CGFloat Value -public final class FloatValueProvider: ValueProvider { - - // MARK: Lifecycle - - /// Initializes with a block provider - public init(block: @escaping CGFloatValueBlock) { - self.block = block - float = 0 - identity = UUID() - } - - /// Initializes with a single float. - public init(_ float: CGFloat) { - self.float = float - block = nil - hasUpdate = true - identity = float - } - - // MARK: Public - - /// Returns a CGFloat for a CGFloat(Frame Time) - public typealias CGFloatValueBlock = (CGFloat) -> CGFloat - - public var float: CGFloat { - didSet { - hasUpdate = true - } - } - - // MARK: ValueProvider Protocol - - public var valueType: Any.Type { - LottieVector1D.self - } - - public var storage: ValueProviderStorage { - if let block { - return .closure { frame in - self.hasUpdate = false - return LottieVector1D(Double(block(frame))) - } - } else { - hasUpdate = false - return .singleValue(LottieVector1D(Double(float))) - } - } - - public func hasUpdate(frame _: CGFloat) -> Bool { - if block != nil { - return true - } - return hasUpdate - } - - // MARK: Private - - private var hasUpdate = true - - private var block: CGFloatValueBlock? - private var identity: AnyHashable -} - -// MARK: Equatable - -extension FloatValueProvider: Equatable { - public static func ==(_ lhs: FloatValueProvider, _ rhs: FloatValueProvider) -> Bool { - lhs.identity == rhs.identity - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift deleted file mode 100644 index d15891b5d3f2833b85c3ee7ed53bdadd4589613f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +++ /dev/null @@ -1,140 +0,0 @@ -// -// GradientValueProvider.swift -// lottie-swift -// -// Created by Enrique Bermúdez on 10/27/19. -// - -import CoreGraphics -import Foundation - -// MARK: - GradientValueProvider - -/// A `ValueProvider` that returns a Gradient Color Value. -public final class GradientValueProvider: ValueProvider { - - // MARK: Lifecycle - - /// Initializes with a block provider. - public init( - block: @escaping ColorsValueBlock, - locations: ColorLocationsBlock? = nil) - { - self.block = block - locationsBlock = locations - colors = [] - self.locations = [] - identity = UUID() - } - - /// Initializes with an array of colors. - public init( - _ colors: [LottieColor], - locations: [Double] = []) - { - self.colors = colors - self.locations = locations - identity = [AnyHashable(colors), AnyHashable(locations)] - updateValueArray() - hasUpdate = true - } - - // MARK: Public - - /// Returns a [LottieColor] for a CGFloat(Frame Time). - public typealias ColorsValueBlock = (CGFloat) -> [LottieColor] - /// Returns a [Double](Color locations) for a CGFloat(Frame Time). - public typealias ColorLocationsBlock = (CGFloat) -> [Double] - - /// The colors values of the provider. - public var colors: [LottieColor] { - didSet { - updateValueArray() - hasUpdate = true - } - } - - /// The color location values of the provider. - public var locations: [Double] { - didSet { - updateValueArray() - hasUpdate = true - } - } - - // MARK: ValueProvider Protocol - - public var valueType: Any.Type { - [Double].self - } - - public var storage: ValueProviderStorage<[Double]> { - if let block { - return .closure { [self] frame in - hasUpdate = false - - let newColors = block(frame) - let newLocations = locationsBlock?(frame) ?? [] - value = value(from: newColors, locations: newLocations) - - return value - } - } else { - return .singleValue(value) - } - } - - public func hasUpdate(frame _: CGFloat) -> Bool { - if block != nil || locationsBlock != nil { - return true - } - return hasUpdate - } - - // MARK: Private - - private var hasUpdate = true - - private var block: ColorsValueBlock? - private var locationsBlock: ColorLocationsBlock? - private var value: [Double] = [] - - private let identity: AnyHashable - - private func value(from colors: [LottieColor], locations: [Double]) -> [Double] { - var colorValues = [Double]() - var alphaValues = [Double]() - var shouldAddAlphaValues = false - - for i in 0.. i - ? locations[i] - : (Double(i) / Double(colors.count - 1)) - - colorValues.append(location) - colorValues.append(colors[i].r) - colorValues.append(colors[i].g) - colorValues.append(colors[i].b) - - alphaValues.append(location) - alphaValues.append(colors[i].a) - } - - return colorValues + (shouldAddAlphaValues ? alphaValues : []) - } - - private func updateValueArray() { - value = value(from: colors, locations: locations) - } - -} - -// MARK: Equatable - -extension GradientValueProvider: Equatable { - public static func ==(_ lhs: GradientValueProvider, _ rhs: GradientValueProvider) -> Bool { - lhs.identity == rhs.identity - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/PointValueProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/PointValueProvider.swift deleted file mode 100644 index 8b9703bfe85913ea84cc7a7a202bee5263f4f9ee..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/PointValueProvider.swift +++ /dev/null @@ -1,83 +0,0 @@ -// -// PointValueProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -import CoreGraphics -import Foundation - -// MARK: - PointValueProvider - -/// A `ValueProvider` that returns a CGPoint Value -public final class PointValueProvider: ValueProvider { - - // MARK: Lifecycle - - /// Initializes with a block provider - public init(block: @escaping PointValueBlock) { - self.block = block - point = .zero - identity = UUID() - } - - /// Initializes with a single point. - public init(_ point: CGPoint) { - self.point = point - block = nil - hasUpdate = true - identity = [point.x, point.y] - } - - // MARK: Public - - /// Returns a CGPoint for a CGFloat(Frame Time) - public typealias PointValueBlock = (CGFloat) -> CGPoint - - public var point: CGPoint { - didSet { - hasUpdate = true - } - } - - // MARK: ValueProvider Protocol - - public var valueType: Any.Type { - LottieVector3D.self - } - - public var storage: ValueProviderStorage { - if let block { - return .closure { frame in - self.hasUpdate = false - return block(frame).vector3dValue - } - } else { - hasUpdate = false - return .singleValue(point.vector3dValue) - } - } - - public func hasUpdate(frame _: CGFloat) -> Bool { - if block != nil { - return true - } - return hasUpdate - } - - // MARK: Private - - private var hasUpdate = true - - private var block: PointValueBlock? - private let identity: AnyHashable -} - -// MARK: Equatable - -extension PointValueProvider: Equatable { - public static func ==(_ lhs: PointValueProvider, _ rhs: PointValueProvider) -> Bool { - lhs.identity == rhs.identity - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift deleted file mode 100644 index aa5cac9498bc86e2e8ab0b6d600fec9dce416c0c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift +++ /dev/null @@ -1,83 +0,0 @@ -// -// SizeValueProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -import CoreGraphics -import Foundation - -// MARK: - SizeValueProvider - -/// A `ValueProvider` that returns a CGSize Value -public final class SizeValueProvider: ValueProvider { - - // MARK: Lifecycle - - /// Initializes with a block provider - public init(block: @escaping SizeValueBlock) { - self.block = block - size = .zero - identity = UUID() - } - - /// Initializes with a single size. - public init(_ size: CGSize) { - self.size = size - block = nil - hasUpdate = true - identity = [size.width, size.height] - } - - // MARK: Public - - /// Returns a CGSize for a CGFloat(Frame Time) - public typealias SizeValueBlock = (CGFloat) -> CGSize - - public var size: CGSize { - didSet { - hasUpdate = true - } - } - - // MARK: ValueProvider Protocol - - public var valueType: Any.Type { - LottieVector3D.self - } - - public var storage: ValueProviderStorage { - if let block { - return .closure { frame in - self.hasUpdate = false - return block(frame).vector3dValue - } - } else { - hasUpdate = false - return .singleValue(size.vector3dValue) - } - } - - public func hasUpdate(frame _: CGFloat) -> Bool { - if block != nil { - return true - } - return hasUpdate - } - - // MARK: Private - - private var hasUpdate = true - - private var block: SizeValueBlock? - private let identity: AnyHashable -} - -// MARK: Equatable - -extension SizeValueProvider: Equatable { - public static func ==(_ lhs: SizeValueProvider, _ rhs: SizeValueProvider) -> Bool { - lhs.identity == rhs.identity - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/FontProvider/AnimationFontProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/FontProvider/AnimationFontProvider.swift deleted file mode 100644 index d9e1e8ea394ceb921b4656f4cb5ccfefe010c16f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/FontProvider/AnimationFontProvider.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// AnimationFontProvider.swift -// Lottie -// -// Created by Brandon Withrow on 8/5/20. -// Copyright © 2020 YurtvilleProds. All rights reserved. -// - -import CoreText - -// MARK: - AnimationFontProvider - -/// Font provider is a protocol that is used to supply fonts to `LottieAnimationView`. -/// -public protocol AnimationFontProvider { - func fontFor(family: String, size: CGFloat) -> CTFont? -} - -// MARK: - DefaultFontProvider - -/// Default Font provider. -public final class DefaultFontProvider: AnimationFontProvider { - - // MARK: Lifecycle - - public init() { } - - // MARK: Public - - public func fontFor(family: String, size: CGFloat) -> CTFont? { - CTFontCreateWithName(family as CFString, size, nil) - } -} - -// MARK: Equatable - -extension DefaultFontProvider: Equatable { - public static func ==(_: DefaultFontProvider, _: DefaultFontProvider) -> Bool { - true - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/ImageProvider/AnimationImageProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/ImageProvider/AnimationImageProvider.swift deleted file mode 100644 index 7f7477003ebded23c22c6a07cf7b7bf9fa515e44..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/ImageProvider/AnimationImageProvider.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// LottieImageProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -import QuartzCore - -// MARK: - AnimationImageProvider - -/// Image provider is a protocol that is used to supply images to `LottieAnimationView`. -/// -/// Some animations require a reference to an image. The image provider loads and -/// provides those images to the `LottieAnimationView`. Lottie includes a couple of -/// prebuilt Image Providers that supply images from a Bundle, or from a FilePath. -/// -/// Additionally custom Image Providers can be made to load images from a URL, -/// or to Cache images. -public protocol AnimationImageProvider { - - /// Whether or not the resulting image of this image provider can be cached by Lottie. Defaults to true. - /// If true, Lottie may internally cache the result of `imageForAsset` - var cacheEligible: Bool { get } - - /// The image to display for the given `ImageAsset` defined in the `LottieAnimation` JSON file. - func imageForAsset(asset: ImageAsset) -> CGImage? - - /// Specifies how the layer's contents are positioned or scaled within its bounds for a given asset. - /// Defaults to `.resize`, which stretches the image to fill the layer. - func contentsGravity(for asset: ImageAsset) -> CALayerContentsGravity -} - -extension AnimationImageProvider { - public var cacheEligible: Bool { - true - } - - /// The default value is `.resize`, similar to that of `CALayer`. - public func contentsGravity(for _: ImageAsset) -> CALayerContentsGravity { - .resize - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Keyframes/Interpolatable.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Keyframes/Interpolatable.swift deleted file mode 100644 index bb53c13d1da8abe217b4feeaa1880e021bc954fe..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Keyframes/Interpolatable.swift +++ /dev/null @@ -1,279 +0,0 @@ -// Created by Cal Stephens on 1/24/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import CoreGraphics - -// MARK: - Interpolatable - -/// A type that can be interpolated between two values -public protocol Interpolatable: AnyInterpolatable { - /// Interpolates the `self` to the given number by `amount`. - /// - Parameter to: The number to interpolate to. - /// - Parameter amount: The amount to interpolate, - /// relative to 0.0 (self) and 1.0 (to). - /// `amount` can be greater than one and less than zero, - /// and interpolation should not be clamped. - /// - /// ``` - /// let number = 5 - /// let interpolated = number.interpolateTo(10, amount: 0.5) - /// print(interpolated) // 7.5 - /// ``` - /// - /// ``` - /// let number = 5 - /// let interpolated = number.interpolateTo(10, amount: 1.5) - /// print(interpolated) // 12.5 - /// ``` - func interpolate(to: Self, amount: CGFloat) -> Self -} - -// MARK: - SpatialInterpolatable - -/// A type that can be interpolated between two values, -/// additionally using optional `spatialOutTangent` and `spatialInTangent` values. -/// - If your implementation doesn't use the `spatialOutTangent` and `spatialInTangent` -/// parameters, prefer implementing the simpler `Interpolatable` protocol. -public protocol SpatialInterpolatable: AnyInterpolatable { - /// Interpolates the `self` to the given number by `amount`. - /// - Parameter to: The number to interpolate to. - /// - Parameter amount: The amount to interpolate, - /// relative to 0.0 (self) and 1.0 (to). - /// `amount` can be greater than one and less than zero, - /// and interpolation should not be clamped. - func interpolate( - to: Self, - amount: CGFloat, - spatialOutTangent: CGPoint?, - spatialInTangent: CGPoint?) - -> Self -} - -// MARK: - AnyInterpolatable - -/// The base protocol that is implemented by both `Interpolatable` and `SpatialInterpolatable` -/// Types should not directly implement this protocol. -public protocol AnyInterpolatable { - /// Interpolates by calling either `Interpolatable.interpolate` - /// or `SpatialInterpolatable.interpolate`. - /// Should not be implemented or called by consumers. - func _interpolate( - to: Self, - amount: CGFloat, - spatialOutTangent: CGPoint?, - spatialInTangent: CGPoint?) - -> Self -} - -extension Interpolatable { - public func _interpolate( - to: Self, - amount: CGFloat, - spatialOutTangent _: CGPoint?, - spatialInTangent _: CGPoint?) - -> Self - { - interpolate(to: to, amount: amount) - } -} - -extension SpatialInterpolatable { - /// Helper that interpolates this `SpatialInterpolatable` - /// with `nil` spatial in/out tangents - public func interpolate(to: Self, amount: CGFloat) -> Self { - interpolate( - to: to, - amount: amount, - spatialOutTangent: nil, - spatialInTangent: nil) - } - - public func _interpolate( - to: Self, - amount: CGFloat, - spatialOutTangent: CGPoint?, - spatialInTangent: CGPoint?) - -> Self - { - interpolate( - to: to, - amount: amount, - spatialOutTangent: spatialOutTangent, - spatialInTangent: spatialInTangent) - } -} - -// MARK: - Double + Interpolatable - -extension Double: Interpolatable { } - -// MARK: - CGFloat + Interpolatable - -extension CGFloat: Interpolatable { } - -// MARK: - Float + Interpolatable - -extension Float: Interpolatable { } - -extension Interpolatable where Self: BinaryFloatingPoint { - public func interpolate(to: Self, amount: CGFloat) -> Self { - self + ((to - self) * Self(amount)) - } -} - -// MARK: - CGRect + Interpolatable - -extension CGRect: Interpolatable { - public func interpolate(to: CGRect, amount: CGFloat) -> CGRect { - CGRect( - x: origin.x.interpolate(to: to.origin.x, amount: amount), - y: origin.y.interpolate(to: to.origin.y, amount: amount), - width: width.interpolate(to: to.width, amount: amount), - height: height.interpolate(to: to.height, amount: amount)) - } -} - -// MARK: - CGSize + Interpolatable - -extension CGSize: Interpolatable { - public func interpolate(to: CGSize, amount: CGFloat) -> CGSize { - CGSize( - width: width.interpolate(to: to.width, amount: amount), - height: height.interpolate(to: to.height, amount: amount)) - } -} - -// MARK: - CGPoint + SpatialInterpolatable - -extension CGPoint: SpatialInterpolatable { - public func interpolate( - to: CGPoint, - amount: CGFloat, - spatialOutTangent: CGPoint?, - spatialInTangent: CGPoint?) - -> CGPoint - { - guard - let outTan = spatialOutTangent, - let inTan = spatialInTangent - else { - return CGPoint( - x: x.interpolate(to: to.x, amount: amount), - y: y.interpolate(to: to.y, amount: amount)) - } - - let cp1 = self + outTan - let cp2 = to + inTan - return interpolate(to, outTangent: cp1, inTangent: cp2, amount: amount) - } -} - -// MARK: - LottieColor + Interpolatable - -extension LottieColor: Interpolatable { - public func interpolate(to: LottieColor, amount: CGFloat) -> LottieColor { - LottieColor( - r: r.interpolate(to: to.r, amount: amount), - g: g.interpolate(to: to.g, amount: amount), - b: b.interpolate(to: to.b, amount: amount), - a: a.interpolate(to: to.a, amount: amount)) - } -} - -// MARK: - LottieVector1D + Interpolatable - -extension LottieVector1D: Interpolatable { - public func interpolate(to: LottieVector1D, amount: CGFloat) -> LottieVector1D { - value.interpolate(to: to.value, amount: amount).vectorValue - } -} - -// MARK: - LottieVector2D + SpatialInterpolatable - -extension LottieVector2D: SpatialInterpolatable { - public func interpolate( - to: LottieVector2D, - amount: CGFloat, - spatialOutTangent: CGPoint?, - spatialInTangent: CGPoint?) - -> LottieVector2D - { - pointValue.interpolate( - to: to.pointValue, - amount: amount, - spatialOutTangent: spatialOutTangent, - spatialInTangent: spatialInTangent) - .vector2dValue - } -} - -// MARK: - LottieVector3D + SpatialInterpolatable - -extension LottieVector3D: SpatialInterpolatable { - public func interpolate( - to: LottieVector3D, - amount: CGFloat, - spatialOutTangent: CGPoint?, - spatialInTangent: CGPoint?) - -> LottieVector3D - { - if spatialInTangent != nil || spatialOutTangent != nil { - // TODO Support third dimension spatial interpolation - let point = pointValue.interpolate( - to: to.pointValue, - amount: amount, - spatialOutTangent: spatialOutTangent, - spatialInTangent: spatialInTangent) - - return LottieVector3D( - x: point.x, - y: point.y, - z: CGFloat(z.interpolate(to: to.z, amount: amount))) - } - - return LottieVector3D( - x: x.interpolate(to: to.x, amount: amount), - y: y.interpolate(to: to.y, amount: amount), - z: z.interpolate(to: to.z, amount: amount)) - } -} - -// MARK: - Array + Interpolatable, AnyInterpolatable - -extension Array: Interpolatable, AnyInterpolatable where Element: Interpolatable { - public func interpolate(to: [Element], amount: CGFloat) -> [Element] { - LottieLogger.shared.assert( - count == to.count, - "When interpolating Arrays, both array sound have the same element count.") - - return zip(self, to).map { lhs, rhs in - lhs.interpolate(to: rhs, amount: amount) - } - } -} - -// MARK: - Optional + Interpolatable, AnyInterpolatable - -extension Optional: Interpolatable, AnyInterpolatable where Wrapped: Interpolatable { - public func interpolate(to: Wrapped?, amount: CGFloat) -> Wrapped? { - guard let self, let to else { return nil } - return self.interpolate(to: to, amount: amount) - } -} - -// MARK: - Hold - -/// An `Interpolatable` container that animates using "hold" keyframes. -/// The keyframes do not animate, and instead always display the value from the most recent keyframe. -/// This is necessary when passing non-interpolatable values to a method that requires an `Interpolatable` conformance. -struct Hold: Interpolatable { - let value: T - - func interpolate(to: Hold, amount: CGFloat) -> Hold { - if amount < 1 { - return self - } else { - return to - } - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Keyframes/Keyframe.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Keyframes/Keyframe.swift deleted file mode 100644 index 626260cd5d235c08379a8eb67e60342deb02ac89..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Keyframes/Keyframe.swift +++ /dev/null @@ -1,98 +0,0 @@ -// Created by Cal Stephens on 1/24/22. -// Copyright © 2022 Airbnb Inc. All rights reserved. - -import CoreFoundation - -// MARK: - Keyframe - -/// A keyframe with a single value, and timing information -/// about when the value should be displayed and how it -/// should be interpolated. -public final class Keyframe { - - // MARK: Lifecycle - - /// Initialize a value-only keyframe with no time data. - public init( - _ value: T, - spatialInTangent: LottieVector3D? = nil, - spatialOutTangent: LottieVector3D? = nil) - { - self.value = value - time = 0 - isHold = true - inTangent = nil - outTangent = nil - self.spatialInTangent = spatialInTangent - self.spatialOutTangent = spatialOutTangent - } - - /// Initialize a keyframe - public init( - value: T, - time: AnimationFrameTime, - isHold: Bool = false, - inTangent: LottieVector2D? = nil, - outTangent: LottieVector2D? = nil, - spatialInTangent: LottieVector3D? = nil, - spatialOutTangent: LottieVector3D? = nil) - { - self.value = value - self.time = time - self.isHold = isHold - self.outTangent = outTangent - self.inTangent = inTangent - self.spatialInTangent = spatialInTangent - self.spatialOutTangent = spatialOutTangent - } - - // MARK: Public - - /// The value of the keyframe - public let value: T - /// The time in frames of the keyframe. - public let time: AnimationFrameTime - /// A hold keyframe freezes interpolation until the next keyframe that is not a hold. - public let isHold: Bool - /// The in tangent for the time interpolation curve. - public let inTangent: LottieVector2D? - /// The out tangent for the time interpolation curve. - public let outTangent: LottieVector2D? - - /// The spatial in tangent of the vector. - public let spatialInTangent: LottieVector3D? - /// The spatial out tangent of the vector. - public let spatialOutTangent: LottieVector3D? -} - -// MARK: Equatable - -extension Keyframe: Equatable where T: Equatable { - public static func == (lhs: Keyframe, rhs: Keyframe) -> Bool { - lhs.value == rhs.value - && lhs.time == rhs.time - && lhs.isHold == rhs.isHold - && lhs.inTangent == rhs.inTangent - && lhs.outTangent == rhs.outTangent - && lhs.spatialInTangent == rhs.spatialOutTangent - && lhs.spatialOutTangent == rhs.spatialOutTangent - } -} - -// MARK: Hashable - -extension Keyframe: Hashable where T: Hashable { - public func hash(into hasher: inout Hasher) { - hasher.combine(value) - hasher.combine(time) - hasher.combine(isHold) - hasher.combine(inTangent) - hasher.combine(outTangent) - hasher.combine(spatialInTangent) - hasher.combine(spatialOutTangent) - } -} - -// MARK: Sendable - -extension Keyframe: Sendable where T: Sendable { } diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Logging/LottieLogger.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Logging/LottieLogger.swift deleted file mode 100644 index cddde2dd76375e3e4dce8015dcfd68cbead77680..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Logging/LottieLogger.swift +++ /dev/null @@ -1,137 +0,0 @@ -// Created by eric_horacek on 12/9/20. -// Copyright © 2020 Airbnb Inc. All rights reserved. - -// MARK: - LottieLogger - -/// A shared logger that allows consumers to intercept Lottie assertions and warning messages to pipe -/// into their own logging systems. -public final class LottieLogger { - - // MARK: Lifecycle - - public init( - assert: @escaping Assert = { condition, message, file, line in - // If we default to `Swift.assert` directly with `assert: Assert = Swift.assert`, - // the call will unexpectedly not respect the -O flag and will crash in release - // https://github.com/apple/swift/issues/60249 - Swift.assert(condition(), message(), file: file, line: line) - }, - assertionFailure: @escaping AssertionFailure = { message, file, line in - // If we default to `Swift.assertionFailure` directly with - // `assertionFailure: AssertionFailure = Swift.assertionFailure`, - // the call will unexpectedly not respect the -O flag and will crash in release - // https://github.com/apple/swift/issues/60249 - Swift.assertionFailure(message(), file: file, line: line) - }, - warn: @escaping Warn = { message, _, _ in - #if DEBUG - // swiftlint:disable:next no_direct_standard_out_logs - print(message()) - #endif - }, - info: @escaping Info = { message in - #if DEBUG - // swiftlint:disable:next no_direct_standard_out_logs - print(message()) - #endif - }) - { - _assert = assert - _assertionFailure = assertionFailure - _warn = warn - _info = info - } - - // MARK: Public - - /// Logs that an assertion occurred. - public typealias Assert = ( - _ condition: @autoclosure () -> Bool, - _ message: @autoclosure () -> String, - _ fileID: StaticString, - _ line: UInt) - -> Void - - /// Logs that an assertion failure occurred. - public typealias AssertionFailure = ( - _ message: @autoclosure () -> String, - _ fileID: StaticString, - _ line: UInt) - -> Void - - /// Logs a warning message. - public typealias Warn = ( - _ message: @autoclosure () -> String, - _ fileID: StaticString, - _ line: UInt) - -> Void - - /// Prints a purely informational message. - public typealias Info = (_ message: @autoclosure () -> String) -> Void - - /// The shared instance used to log Lottie assertions and warnings. - /// - /// Set this to a new logger instance to intercept assertions and warnings logged by Lottie. - public static var shared = LottieLogger() - - /// Logs that an assertion occurred. - public func assert( - _ condition: @autoclosure () -> Bool, - _ message: @autoclosure () -> String = String(), - fileID: StaticString = #fileID, - line: UInt = #line) - { - _assert(condition(), message(), fileID, line) - } - - /// Logs that an assertion failure occurred. - public func assertionFailure( - _ message: @autoclosure () -> String = String(), - fileID: StaticString = #fileID, - line: UInt = #line) - { - _assertionFailure(message(), fileID, line) - } - - /// Logs a warning message. - public func warn( - _ message: @autoclosure () -> String = String(), - fileID: StaticString = #fileID, - line: UInt = #line) - { - _warn(message(), fileID, line) - } - - /// Logs a purely informational message. - public func info(_ message: @autoclosure () -> String = String()) { - _info(message()) - } - - // MARK: Private - - private let _assert: Assert - private let _assertionFailure: AssertionFailure - private let _warn: Warn - private let _info: Info - -} - -// MARK: - LottieLogger + printToConsole - -extension LottieLogger { - /// A `LottieLogger` instance that always prints to the console (by calling `print`) - /// instead of calling `assert` / `assertionFailure`, which halt execution in debug builds. - public static var printToConsole: LottieLogger { - LottieLogger( - assert: { condition, message, _, _ in - if !condition() { - // swiftlint:disable:next no_direct_standard_out_logs - print(message()) - } - }, - assertionFailure: { message, _, _ in - // swiftlint:disable:next no_direct_standard_out_logs - print(message()) - }) - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Primitives/AnimationTime.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Primitives/AnimationTime.swift deleted file mode 100644 index 2c33e2b452894a311d16776d60f8160359622597..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Primitives/AnimationTime.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// AnimationTime.swift -// lottie-swift-iOS -// -// Created by Brandon Withrow on 2/6/19. -// - -import CoreGraphics -import Foundation - -/// Defines animation time in Frames (Seconds * Framerate). -public typealias AnimationFrameTime = CGFloat - -/// Defines animation time by a progress from 0 (beginning of the animation) to 1 (end of the animation) -public typealias AnimationProgressTime = CGFloat diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Primitives/LottieColor.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Primitives/LottieColor.swift deleted file mode 100644 index 3af8ab1a14daf806b54af6ff166d9ea12a745312..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Primitives/LottieColor.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// LottieColor.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -// MARK: - ColorFormatDenominator - -public enum ColorFormatDenominator: Hashable { - case One - case OneHundred - case TwoFiftyFive - - var value: Double { - switch self { - case .One: - return 1.0 - case .OneHundred: - return 100.0 - case .TwoFiftyFive: - return 255.0 - } - } -} - -// MARK: - LottieColor - -public struct LottieColor: Hashable { - - public var r: Double - public var g: Double - public var b: Double - public var a: Double - - public init(r: Double, g: Double, b: Double, a: Double, denominator: ColorFormatDenominator = .One) { - self.r = r / denominator.value - self.g = g / denominator.value - self.b = b / denominator.value - self.a = a / denominator.value - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Primitives/Vectors.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Primitives/Vectors.swift deleted file mode 100644 index af5d956630b8d14424005d2ad3582a23979176f5..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/Primitives/Vectors.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// Vectors.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -// MARK: - LottieVector1D - -public struct LottieVector1D: Hashable, Sendable { - - public init(_ value: Double) { - self.value = value - } - - public let value: Double - -} - -// MARK: - LottieVector3D - -/// A three dimensional vector. -/// These vectors are encoded and decoded from [Double] -public struct LottieVector3D: Hashable, Sendable { - - public let x: Double - public let y: Double - public let z: Double - - public init(x: Double, y: Double, z: Double) { - self.x = x - self.y = y - self.z = z - } - -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/TextProvider/AnimationTextProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/TextProvider/AnimationTextProvider.swift deleted file mode 100644 index cd41545e8fd7a00798301f7088968480806dbc70..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/TextProvider/AnimationTextProvider.swift +++ /dev/null @@ -1,124 +0,0 @@ -// -// AnimationImageProvider.swift -// Lottie_iOS -// -// Created by Alexandr Goncharov on 07/06/2019. -// - -// MARK: - AnimationKeypathTextProvider - -/// Protocol for providing dynamic text to for a Lottie animation. -public protocol AnimationKeypathTextProvider: AnyObject { - /// The text to display for the given `AnimationKeypath`. - /// If `nil` is returned, continues using the existing default text value. - func text(for keypath: AnimationKeypath, sourceText: String) -> String? -} - -// MARK: - AnimationKeypathTextProvider - -/// Legacy protocol for providing dynamic text for a Lottie animation. -/// Instead prefer conforming to `AnimationKeypathTextProvider`. -@available(*, deprecated, message: """ - `AnimationKeypathTextProvider` has been deprecated and renamed to `LegacyAnimationTextProvider`. \ - Instead, conform to `AnimationKeypathTextProvider` instead or conform to `LegacyAnimationTextProvider` explicitly. - """) -public typealias AnimationTextProvider = LegacyAnimationTextProvider - -// MARK: - LegacyAnimationTextProvider - -/// Legacy protocol for providing dynamic text for a Lottie animation. -/// Instead prefer conforming to `AnimationKeypathTextProvider`. -public protocol LegacyAnimationTextProvider: AnimationKeypathTextProvider { - /// Legacy method to look up the text to display for the given keypath. - /// Instead, prefer implementing `AnimationKeypathTextProvider.` - /// The behavior of this method depends on the current rendering engine: - /// - The Core Animation rendering engine always calls this method - /// with the full keypath (e.g. `MY_LAYER.text_value`). - /// - The Main Thread rendering engine always calls this method - /// with the final component of the key path (e.g. just `text_value`). - func textFor(keypathName: String, sourceText: String) -> String -} - -extension LegacyAnimationTextProvider { - public func text(for _: AnimationKeypath, sourceText _: String) -> String? { - nil - } -} - -// MARK: - DictionaryTextProvider - -/// Text provider that simply map values from dictionary. -/// - The dictionary keys can either be the full layer keypath string (e.g. `MY_LAYER.text_value`) -/// or simply the final path component of the keypath (e.g. `text_value`). -public final class DictionaryTextProvider: AnimationKeypathTextProvider, LegacyAnimationTextProvider { - - // MARK: Lifecycle - - public init(_ values: [String: String]) { - self.values = values - } - - // MARK: Public - - public func text(for keypath: AnimationKeypath, sourceText: String) -> String? { - if let valueForFullKeypath = values[keypath.fullPath] { - return valueForFullKeypath - } - - else if - let lastKeypathComponent = keypath.keys.last, - let valueForLastComponent = values[lastKeypathComponent] - { - return valueForLastComponent - } - - else { - return sourceText - } - } - - // Never called directly by Lottie, but we continue to implement this conformance for backwards compatibility. - public func textFor(keypathName: String, sourceText: String) -> String { - values[keypathName] ?? sourceText - } - - // MARK: Internal - - let values: [String: String] -} - -// MARK: Equatable - -extension DictionaryTextProvider: Equatable { - public static func ==(_ lhs: DictionaryTextProvider, _ rhs: DictionaryTextProvider) -> Bool { - lhs.values == rhs.values - } -} - -// MARK: - DefaultTextProvider - -/// Default text provider. Uses text in the animation file -public final class DefaultTextProvider: AnimationKeypathTextProvider, LegacyAnimationTextProvider { - - // MARK: Lifecycle - - public init() { } - - // MARK: Public - - public func textFor(keypathName _: String, sourceText: String) -> String { - sourceText - } - - public func text(for _: AnimationKeypath, sourceText: String) -> String { - sourceText - } -} - -// MARK: Equatable - -extension DefaultTextProvider: Equatable { - public static func ==(_: DefaultTextProvider, _: DefaultTextProvider) -> Bool { - true - } -} diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/AnimationSubview.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/AnimationSubview.swift deleted file mode 100644 index 93264ef259d7f3fefb2bf609e60d8c5ecb2dbb70..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/AnimationSubview.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// AnimationSubview.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -#if canImport(UIKit) -import UIKit - -/// A view that can be added to a keypath of an AnimationView -public final class AnimationSubview: UIView { - - var viewLayer: CALayer? { - layer - } - -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/BundleImageProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/BundleImageProvider.swift deleted file mode 100644 index 3317e0b1964a0ad1395ecbb44a1bf386bba1e1d1..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/BundleImageProvider.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// LottieBundleImageProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -#if canImport(UIKit) -import UIKit - -/// An `AnimationImageProvider` that provides images by name from a specific bundle. -/// The BundleImageProvider is initialized with a bundle and an optional searchPath. -public class BundleImageProvider: AnimationImageProvider { - - // MARK: Lifecycle - - /// Initializes an image provider with a bundle and an optional subpath. - /// - /// Provides images for an animation from a bundle. Additionally the provider can - /// search a specific subpath for the images. - /// - /// - Parameter bundle: The bundle containing images for the provider. - /// - Parameter searchPath: The subpath is a path within the bundle to search for image assets. - /// - Parameter contentsGravity: The contents gravity to use when rendering the image. - /// - public init(bundle: Bundle, searchPath: String?, contentsGravity: CALayerContentsGravity = .resize) { - self.bundle = bundle - self.searchPath = searchPath - self.contentsGravity = contentsGravity - } - - // MARK: Public - - public func imageForAsset(asset: ImageAsset) -> CGImage? { - if let base64Image = asset.base64Image { - return base64Image - } - - let imagePath: String? - /// Try to find the image in the bundle. - if let searchPath { - /// Search in the provided search path for the image - var directoryPath = URL(fileURLWithPath: searchPath) - directoryPath.appendPathComponent(asset.directory) - - if let path = bundle.path(forResource: asset.name, ofType: nil, inDirectory: directoryPath.path) { - /// First search for the image in the asset provided sub directory. - imagePath = path - } else if let path = bundle.path(forResource: asset.name, ofType: nil, inDirectory: searchPath) { - /// Try finding the image in the search path. - imagePath = path - } else { - imagePath = bundle.path(forResource: asset.name, ofType: nil) - } - } else { - if let path = bundle.path(forResource: asset.name, ofType: nil, inDirectory: asset.directory) { - /// First search for the image in the asset provided sub directory. - imagePath = path - } else { - /// First search for the image in bundle. - imagePath = bundle.path(forResource: asset.name, ofType: nil) - } - } - - if imagePath == nil { - guard let image = UIImage(named: asset.name, in: bundle, compatibleWith: nil) else { - LottieLogger.shared.warn("Could not find image \"\(asset.name)\" in bundle") - return nil - } - return image.cgImage - } - - guard let foundPath = imagePath, let image = UIImage(contentsOfFile: foundPath) else { - /// No image found. - LottieLogger.shared.warn("Could not find image \"\(asset.name)\" in bundle") - return nil - } - return image.cgImage - } - - public func contentsGravity(for _: ImageAsset) -> CALayerContentsGravity { - contentsGravity - } - - // MARK: Internal - - let bundle: Bundle - let searchPath: String? - let contentsGravity: CALayerContentsGravity -} - -extension BundleImageProvider: Equatable { - public static func ==(_ lhs: BundleImageProvider, _ rhs: BundleImageProvider) -> Bool { - lhs.bundle == rhs.bundle - && lhs.searchPath == rhs.searchPath - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/Compatibility/CompatibleAnimationKeypath.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/Compatibility/CompatibleAnimationKeypath.swift deleted file mode 100644 index facb4e647b17cfcc337d0bd380ebb194b4593991..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/Compatibility/CompatibleAnimationKeypath.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// CompatibleAnimationKeypath.swift -// Lottie_iOS -// -// Created by Tyler Hedrick on 3/6/19. -// - -import Foundation -#if canImport(UIKit) - -/// An Objective-C compatible wrapper around Lottie's AnimationKeypath -@objc -public final class CompatibleAnimationKeypath: NSObject { - - // MARK: Lifecycle - - /// Creates a keypath from a dot separated string. The string is separated by "." - @objc - public init(keypath: String) { - animationKeypath = AnimationKeypath(keypath: keypath) - } - - /// Creates a keypath from a list of strings. - @objc - public init(keys: [String]) { - animationKeypath = AnimationKeypath(keys: keys) - } - - // MARK: Public - - public let animationKeypath: AnimationKeypath -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/Compatibility/CompatibleAnimationView.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/Compatibility/CompatibleAnimationView.swift deleted file mode 100644 index 9b788fc6c280620a057542f9111cd426a1e32f85..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/Compatibility/CompatibleAnimationView.swift +++ /dev/null @@ -1,542 +0,0 @@ -// -// CompatibleAnimationView.swift -// Lottie_iOS -// -// Created by Tyler Hedrick on 3/6/19. -// - -import Foundation -#if canImport(UIKit) -import UIKit - -/// An Objective-C compatible wrapper around Lottie's Animation class. -/// Use in tandem with CompatibleAnimationView when using Lottie in Objective-C -@objc -public final class CompatibleAnimation: NSObject { - - // MARK: Lifecycle - - @objc - public init( - name: String, - subdirectory: String? = nil, - bundle: Bundle = Bundle.main) - { - self.name = name - self.subdirectory = subdirectory - self.bundle = bundle - super.init() - } - - // MARK: Internal - - var animation: LottieAnimation? { - LottieAnimation.named(name, bundle: bundle, subdirectory: subdirectory) - } - - @objc - static func named(_ name: String) -> CompatibleAnimation { - CompatibleAnimation(name: name) - } - - // MARK: Private - - private let name: String - private let subdirectory: String? - private let bundle: Bundle -} - -/// An Objective-C compatible wrapper around Lottie's RenderingEngineOption enum. Pass in an option -/// to the CompatibleAnimationView initializers to configure the rendering engine for the view. -@objc -public enum CompatibleRenderingEngineOption: Int { - /// Uses the rendering engine specified in LottieConfiguration.shared. - case shared - - /// Uses the library default rendering engine, coreAnimation. - case defaultEngine - - /// Optimizes rendering performance by using the Core Animation rendering engine for animations it - /// can render while falling back to the main thread renderer for all other animations. - case automatic - - /// Only renders animations using the main thread rendering engine. - case mainThread - - /// Only renders animations using the Core Animation rendering engine. Those animations that use - /// features not yet supported on this renderer will not be rendered. - case coreAnimation - - // MARK: Public - - /// Converts a CompatibleRenderingEngineOption to the corresponding LottieConfiguration for - /// internal rendering engine configuration. - public static func generateLottieConfiguration( - _ configuration: CompatibleRenderingEngineOption) - -> LottieConfiguration - { - switch configuration { - case .shared: - return LottieConfiguration.shared - case .defaultEngine: - return LottieConfiguration(renderingEngine: .coreAnimation) - case .automatic: - return LottieConfiguration(renderingEngine: .automatic) - case .mainThread: - return LottieConfiguration(renderingEngine: .mainThread) - case .coreAnimation: - return LottieConfiguration(renderingEngine: .coreAnimation) - } - } -} - -/// An Objective-C compatible version of `LottieBackgroundBehavior`. -@objc -public enum CompatibleBackgroundBehavior: Int { - /// Stop the animation and reset it to the beginning of its current play time. The completion block is called. - case stop - - /// Pause the animation in its current state. The completion block is called. - case pause - - /// Pause the animation and restart it when the application moves to the foreground. - /// The completion block is stored and called when the animation completes. - /// - This is the default when using the Main Thread rendering engine. - case pauseAndRestore - - /// Stops the animation and sets it to the end of its current play time. The completion block is called. - case forceFinish - - /// The animation continues playing in the background. - /// - This is the default when using the Core Animation rendering engine. - /// Playing an animation using the Core Animation engine doesn't come with any CPU overhead, - /// so using `.continuePlaying` avoids the need to stop and then resume the animation - /// (which does come with some CPU overhead). - /// - This mode should not be used with the Main Thread rendering engine. - case continuePlaying -} - -/// An Objective-C compatible wrapper around Lottie's LottieAnimationView. -@objc -public final class CompatibleAnimationView: UIView { - - // MARK: Lifecycle - - /// Initializes a compatible AnimationView with a given compatible animation. Defaults to using - /// the rendering engine specified in LottieConfiguration.shared. - @objc - public convenience init(compatibleAnimation: CompatibleAnimation) { - self.init(compatibleAnimation: compatibleAnimation, compatibleRenderingEngineOption: .shared) - } - - /// Initializes a compatible AnimationView with a given compatible animation and rendering engine - /// configuration. - @objc - public init( - compatibleAnimation: CompatibleAnimation, - compatibleRenderingEngineOption: CompatibleRenderingEngineOption) - { - animationView = LottieAnimationView( - animation: compatibleAnimation.animation, - configuration: CompatibleRenderingEngineOption.generateLottieConfiguration(compatibleRenderingEngineOption)) - self.compatibleAnimation = compatibleAnimation - super.init(frame: .zero) - commonInit() - } - - /// Initializes a compatible AnimationView with the resources asynchronously loaded from a given - /// URL. Defaults to using the rendering engine specified in LottieConfiguration.shared. - @objc - public convenience init(url: URL) { - self.init(url: url, compatibleRenderingEngineOption: .shared) - } - - /// Initializes a compatible AnimationView with the resources asynchronously loaded from a given - /// URL using the given rendering engine configuration. - @objc - public init(url: URL, compatibleRenderingEngineOption: CompatibleRenderingEngineOption) { - animationView = LottieAnimationView( - url: url, - closure: { _ in }, - configuration: CompatibleRenderingEngineOption.generateLottieConfiguration(compatibleRenderingEngineOption)) - super.init(frame: .zero) - commonInit() - } - - /// Initializes a compatible AnimationView from a given Data object specifying the Lottie - /// animation. Defaults to using the rendering engine specified in LottieConfiguration.shared. - @objc - public convenience init(data: Data) { - self.init(data: data, compatibleRenderingEngineOption: .shared) - } - - /// Initializes a compatible AnimationView from a given Data object specifying the Lottie - /// animation using the given rendering engine configuration. - @objc - public init(data: Data, compatibleRenderingEngineOption: CompatibleRenderingEngineOption) { - if let animation = try? LottieAnimation.from(data: data) { - animationView = LottieAnimationView( - animation: animation, - configuration: CompatibleRenderingEngineOption.generateLottieConfiguration(compatibleRenderingEngineOption)) - } else { - animationView = LottieAnimationView( - configuration: CompatibleRenderingEngineOption.generateLottieConfiguration(compatibleRenderingEngineOption)) - } - super.init(frame: .zero) - commonInit() - } - - @objc - public override init(frame: CGRect) { - animationView = LottieAnimationView() - super.init(frame: frame) - commonInit() - } - - required init?(coder: NSCoder) { - animationView = LottieAnimationView() - super.init(coder: coder) - commonInit() - } - - // MARK: Public - - @objc public var compatibleAnimation: CompatibleAnimation? { - didSet { - animationView.animation = compatibleAnimation?.animation - } - } - - @objc public var loopAnimationCount: CGFloat = 0 { - didSet { - animationView.loopMode = loopAnimationCount == -1 ? .loop : .repeat(Float(loopAnimationCount)) - } - } - - @objc public var compatibleDictionaryTextProvider: CompatibleDictionaryTextProvider? { - didSet { - animationView.textProvider = compatibleDictionaryTextProvider?.textProvider ?? DefaultTextProvider() - } - } - - @objc public override var contentMode: UIView.ContentMode { - set { animationView.contentMode = newValue } - get { animationView.contentMode } - } - - @objc - public var shouldRasterizeWhenIdle: Bool { - set { animationView.shouldRasterizeWhenIdle = newValue } - get { animationView.shouldRasterizeWhenIdle } - } - - @objc - public var currentProgress: CGFloat { - set { animationView.currentProgress = newValue } - get { animationView.currentProgress } - } - - @objc - public var duration: CGFloat { - animationView.animation?.duration ?? 0.0 - } - - @objc - public var currentTime: TimeInterval { - set { animationView.currentTime = newValue } - get { animationView.currentTime } - } - - @objc - public var currentFrame: CGFloat { - set { animationView.currentFrame = newValue } - get { animationView.currentFrame } - } - - @objc - public var realtimeAnimationFrame: CGFloat { - animationView.realtimeAnimationFrame - } - - @objc - public var realtimeAnimationProgress: CGFloat { - animationView.realtimeAnimationProgress - } - - @objc - public var animationSpeed: CGFloat { - set { animationView.animationSpeed = newValue } - get { animationView.animationSpeed } - } - - @objc - public var respectAnimationFrameRate: Bool { - set { animationView.respectAnimationFrameRate = newValue } - get { animationView.respectAnimationFrameRate } - } - - @objc - public var isAnimationPlaying: Bool { - animationView.isAnimationPlaying - } - - @objc - public var backgroundMode: CompatibleBackgroundBehavior { - get { - switch animationView.backgroundBehavior { - case .stop: - return .stop - case .pause: - return .pause - case .pauseAndRestore: - return .pauseAndRestore - case .forceFinish: - return .forceFinish - case .continuePlaying: - return .continuePlaying - } - } - set { - switch newValue { - case .stop: - animationView.backgroundBehavior = .stop - case .pause: - animationView.backgroundBehavior = .pause - case .pauseAndRestore: - animationView.backgroundBehavior = .pauseAndRestore - case .forceFinish: - animationView.backgroundBehavior = .forceFinish - case .continuePlaying: - animationView.backgroundBehavior = .continuePlaying - } - } - } - - @objc - public func play() { - play(completion: nil) - } - - @objc - public func play(completion: ((Bool) -> Void)?) { - animationView.play(completion: completion) - } - - /// Note: When calling this code from Objective-C, the method signature is - /// playFromProgress:toProgress:completion which drops the standard "With" naming convention. - @objc - public func play( - fromProgress: CGFloat, - toProgress: CGFloat, - completion: ((Bool) -> Void)? = nil) - { - animationView.play( - fromProgress: fromProgress, - toProgress: toProgress, - loopMode: nil, - completion: completion) - } - - /// Note: When calling this code from Objective-C, the method signature is - /// playFromFrame:toFrame:completion which drops the standard "With" naming convention. - @objc - public func play( - fromFrame: CGFloat, - toFrame: CGFloat, - completion: ((Bool) -> Void)? = nil) - { - animationView.play( - fromFrame: fromFrame, - toFrame: toFrame, - loopMode: nil, - completion: completion) - } - - /// Note: When calling this code from Objective-C, the method signature is - /// playFromMarker:toMarker:completion which drops the standard "With" naming convention. - @objc - public func play( - fromMarker: String, - toMarker: String, - completion: ((Bool) -> Void)? = nil) - { - animationView.play( - fromMarker: fromMarker, - toMarker: toMarker, - completion: completion) - } - - @objc - public func play( - marker: String, - completion: ((Bool) -> Void)? = nil) - { - animationView.play( - marker: marker, - completion: completion) - } - - @objc - public func stop() { - animationView.stop() - } - - @objc - public func pause() { - animationView.pause() - } - - @objc - public func reloadImages() { - animationView.reloadImages() - } - - @objc - public func forceDisplayUpdate() { - animationView.forceDisplayUpdate() - } - - @objc - public func getValue( - for keypath: CompatibleAnimationKeypath, - atFrame: CGFloat) - -> Any? - { - animationView.getValue( - for: keypath.animationKeypath, - atFrame: atFrame) - } - - @objc - public func logHierarchyKeypaths() { - animationView.logHierarchyKeypaths() - } - - @objc - public func setColorValue(_ color: UIColor, forKeypath keypath: CompatibleAnimationKeypath) { - var red: CGFloat = 0 - var green: CGFloat = 0 - var blue: CGFloat = 0 - var alpha: CGFloat = 0 - - let colorspace = LottieConfiguration.shared.colorSpace - - let convertedColor = color.cgColor.converted(to: colorspace, intent: .defaultIntent, options: nil) - - if let components = convertedColor?.components, components.count == 4 { - red = components[0] - green = components[1] - blue = components[2] - alpha = components[3] - } else { - color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) - } - - let valueProvider = ColorValueProvider(LottieColor(r: Double(red), g: Double(green), b: Double(blue), a: Double(alpha))) - animationView.setValueProvider(valueProvider, keypath: keypath.animationKeypath) - } - - @objc - public func getColorValue(for keypath: CompatibleAnimationKeypath, atFrame: CGFloat) -> UIColor? { - let value = animationView.getValue(for: keypath.animationKeypath, atFrame: atFrame) - guard let colorValue = value as? LottieColor else { - return nil; - } - - return UIColor( - red: CGFloat(colorValue.r), - green: CGFloat(colorValue.g), - blue: CGFloat(colorValue.b), - alpha: CGFloat(colorValue.a)) - } - - @objc - public func addSubview( - _ subview: AnimationSubview, - forLayerAt keypath: CompatibleAnimationKeypath) - { - animationView.addSubview( - subview, - forLayerAt: keypath.animationKeypath) - } - - @objc - public func convert( - rect: CGRect, - toLayerAt keypath: CompatibleAnimationKeypath?) - -> CGRect - { - animationView.convert( - rect, - toLayerAt: keypath?.animationKeypath) ?? .zero - } - - @objc - public func convert( - point: CGPoint, - toLayerAt keypath: CompatibleAnimationKeypath?) - -> CGPoint - { - animationView.convert( - point, - toLayerAt: keypath?.animationKeypath) ?? .zero - } - - @objc - public func progressTime(forMarker named: String) -> CGFloat { - animationView.progressTime(forMarker: named) ?? 0 - } - - @objc - public func frameTime(forMarker named: String) -> CGFloat { - animationView.frameTime(forMarker: named) ?? 0 - } - - @objc - public func durationFrameTime(forMarker named: String) -> CGFloat { - animationView.durationFrameTime(forMarker: named) ?? 0 - } - - // MARK: Private - - private let animationView: LottieAnimationView - - private func commonInit() { - setUpViews() - } - - private func setUpViews() { - animationView.translatesAutoresizingMaskIntoConstraints = false - addSubview(animationView) - animationView.topAnchor.constraint(equalTo: topAnchor).isActive = true - animationView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true - animationView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - animationView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true - } -} - -/// An Objective-C compatible wrapper around Lottie's DictionaryTextProvider. -/// Use in tandem with CompatibleAnimationView to supply text to LottieAnimationView -/// when using Lottie in Objective-C. -@objc -public final class CompatibleDictionaryTextProvider: NSObject { - - // MARK: Lifecycle - - @objc - public init(values: [String: String]) { - self.values = values - super.init() - } - - // MARK: Internal - - var textProvider: AnimationKeypathTextProvider? { - DictionaryTextProvider(values) - } - - // MARK: Private - - private let values: [String: String] -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/FilepathImageProvider.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/FilepathImageProvider.swift deleted file mode 100644 index 32ec3c3b16cdb07eaa9fa8785847bb7e94c573c3..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/FilepathImageProvider.swift +++ /dev/null @@ -1,78 +0,0 @@ -// -// FilepathImageProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/1/19. -// - -import Foundation -#if canImport(UIKit) -import UIKit - -/// Provides an image for a lottie animation from a provided Bundle. -public class FilepathImageProvider: AnimationImageProvider { - - // MARK: Lifecycle - - /// Initializes an image provider with a specific filepath. - /// - /// - Parameter filepath: The absolute filepath containing the images. - /// - Parameter contentsGravity: The contents gravity to use when rendering the images. - /// - public init(filepath: String, contentsGravity: CALayerContentsGravity = .resize) { - self.filepath = URL(fileURLWithPath: filepath) - self.contentsGravity = contentsGravity - } - - /// Initializes an image provider with a specific filepath. - /// - /// - Parameter filepath: The absolute filepath containing the images. - /// - Parameter contentsGravity: The contents gravity to use when rendering the images. - /// - public init(filepath: URL, contentsGravity: CALayerContentsGravity = .resize) { - self.filepath = filepath - self.contentsGravity = contentsGravity - } - - // MARK: Public - - public func imageForAsset(asset: ImageAsset) -> CGImage? { - if - asset.name.hasPrefix("data:"), - let url = URL(string: asset.name), - let data = try? Data(contentsOf: url), - let image = UIImage(data: data) - { - return image.cgImage - } - - let directPath = filepath.appendingPathComponent(asset.name).path - if FileManager.default.fileExists(atPath: directPath) { - return UIImage(contentsOfFile: directPath)?.cgImage - } - - let pathWithDirectory = filepath.appendingPathComponent(asset.directory).appendingPathComponent(asset.name).path - if FileManager.default.fileExists(atPath: pathWithDirectory) { - return UIImage(contentsOfFile: pathWithDirectory)?.cgImage - } - - LottieLogger.shared.warn("Could not find image \"\(asset.name)\" in bundle") - return nil - } - - public func contentsGravity(for _: ImageAsset) -> CALayerContentsGravity { - contentsGravity - } - - // MARK: Internal - - let filepath: URL - let contentsGravity: CALayerContentsGravity -} - -extension FilepathImageProvider: Equatable { - public static func ==(_ lhs: FilepathImageProvider, _ rhs: FilepathImageProvider) -> Bool { - lhs.filepath == rhs.filepath - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/LottieAnimationViewBase.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/LottieAnimationViewBase.swift deleted file mode 100644 index 4ec8cad665a099ae991190f3524e5cb94ecafb3c..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/LottieAnimationViewBase.swift +++ /dev/null @@ -1,87 +0,0 @@ -// -// LottieAnimationViewBase.swift -// lottie-swift-iOS -// -// Created by Brandon Withrow on 2/6/19. -// - -#if canImport(UIKit) -import UIKit - -/// The base view for `LottieAnimationView` on iOS, tvOS, watchOS, and macCatalyst. -/// -/// Enables the `LottieAnimationView` implementation to be shared across platforms. -open class LottieAnimationViewBase: UIView { - - // MARK: Public - - public override var contentMode: UIView.ContentMode { - didSet { - setNeedsLayout() - } - } - - public override func didMoveToWindow() { - super.didMoveToWindow() - animationMovedToWindow() - } - - public override func layoutSubviews() { - super.layoutSubviews() - layoutAnimation() - } - - // MARK: Internal - - var viewLayer: CALayer? { - layer - } - - var screenScale: CGFloat { - #if os(iOS) || os(tvOS) - if #available(iOS 13.0, tvOS 13.0, *) { - return max(UITraitCollection.current.displayScale, 1) - } else { - return UIScreen.main.scale - } - #else // if os(visionOS) - // We intentionally don't check `#if os(visionOS)`, because that emits - // a warning when building on Xcode 14 and earlier. - 1.0 - #endif - } - - func layoutAnimation() { - // Implemented by subclasses. - } - - func animationMovedToWindow() { - // Implemented by subclasses. - } - - func commonInit() { - contentMode = .scaleAspectFit - clipsToBounds = true - NotificationCenter.default.addObserver( - self, - selector: #selector(animationWillEnterForeground), - name: UIApplication.willEnterForegroundNotification, - object: nil) - NotificationCenter.default.addObserver( - self, - selector: #selector(animationWillMoveToBackground), - name: UIApplication.didEnterBackgroundNotification, - object: nil) - } - - @objc - func animationWillMoveToBackground() { - // Implemented by subclasses. - } - - @objc - func animationWillEnterForeground() { - // Implemented by subclasses. - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/UIColorExtension.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/UIColorExtension.swift deleted file mode 100644 index b4b81d7f6ffa4ed6a13f273ca6e078785a4e766b..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/iOS/UIColorExtension.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// UIColorExtension.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/4/19. -// - -#if canImport(UIKit) -import UIKit - -extension UIColor { - - public var lottieColorValue: LottieColor { - var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0 - getRed(&r, green: &g, blue: &b, alpha: &a) - return LottieColor(r: Double(r), g: Double(g), b: Double(b), a: Double(a)) - } - -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/AnimationSubview.macOS.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/AnimationSubview.macOS.swift deleted file mode 100644 index 119388425ce2c58d20304f646cd5b75f93493848..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/AnimationSubview.macOS.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// AnimationSubview.swift -// lottie-swift-iOS -// -// Created by Brandon Withrow on 2/5/19. -// - -#if os(macOS) -import AppKit - -/// A view that can be added to a keypath of an AnimationView -public final class AnimationSubview: NSView { - - var viewLayer: CALayer? { - layer - } - -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/BundleImageProvider.macOS.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/BundleImageProvider.macOS.swift deleted file mode 100644 index 343664de00c21f4346bd8d731cd4381a6ce5db1f..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/BundleImageProvider.macOS.swift +++ /dev/null @@ -1,90 +0,0 @@ -// -// LottieBundleImageProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 1/25/19. -// - -#if os(macOS) -import AppKit - -/// Provides an image for a lottie animation from a provided Bundle. -public class BundleImageProvider: AnimationImageProvider { - - // MARK: Lifecycle - - /// Initializes an image provider with a bundle and an optional subpath. - /// - /// Provides images for an animation from a bundle. Additionally the provider can - /// search a specific subpath for the images. - /// - /// - Parameter bundle: The bundle containing images for the provider. - /// - Parameter searchPath: The subpath is a path within the bundle to search for image assets. - /// - Parameter contentsGravity: The contents gravity to use when rendering the image. - /// - public init(bundle: Bundle, searchPath: String?, contentsGravity: CALayerContentsGravity = .resize) { - self.bundle = bundle - self.searchPath = searchPath - self.contentsGravity = contentsGravity - } - - // MARK: Public - - public func imageForAsset(asset: ImageAsset) -> CGImage? { - if let base64Image = asset.base64Image { - return base64Image - } - - let imagePath: String? - /// Try to find the image in the bundle. - if let searchPath { - /// Search in the provided search path for the image - var directoryPath = URL(fileURLWithPath: searchPath) - directoryPath.appendPathComponent(asset.directory) - - if let path = bundle.path(forResource: asset.name, ofType: nil, inDirectory: directoryPath.path) { - /// First search for the image in the asset provided sub directory. - imagePath = path - } else if let path = bundle.path(forResource: asset.name, ofType: nil, inDirectory: searchPath) { - /// Try finding the image in the search path. - imagePath = path - } else { - imagePath = bundle.path(forResource: asset.name, ofType: nil) - } - } else { - if let path = bundle.path(forResource: asset.name, ofType: nil, inDirectory: asset.directory) { - /// First search for the image in the asset provided sub directory. - imagePath = path - } else { - /// First search for the image in bundle. - imagePath = bundle.path(forResource: asset.name, ofType: nil) - } - } - - guard let foundPath = imagePath, let image = NSImage(contentsOfFile: foundPath) else { - /// No image found. - LottieLogger.shared.warn("Could not find image \"\(asset.name)\" in bundle") - return nil - } - return image.lottie_CGImage - } - - public func contentsGravity(for _: ImageAsset) -> CALayerContentsGravity { - contentsGravity - } - - // MARK: Internal - - let bundle: Bundle - let searchPath: String? - let contentsGravity: CALayerContentsGravity -} - -extension BundleImageProvider: Equatable { - public static func ==(_ lhs: BundleImageProvider, _ rhs: BundleImageProvider) -> Bool { - lhs.bundle == rhs.bundle - && lhs.searchPath == rhs.searchPath - } -} - -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/FilepathImageProvider.macOS.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/FilepathImageProvider.macOS.swift deleted file mode 100644 index 53aedbb2c2d74a3236d8837a9f093171c5900784..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/FilepathImageProvider.macOS.swift +++ /dev/null @@ -1,86 +0,0 @@ -// -// FilepathImageProvider.swift -// lottie-swift -// -// Created by Brandon Withrow on 2/1/19. -// - -#if os(macOS) -import AppKit - -/// An `AnimationImageProvider` that provides images by name from a specific filepath. -public class FilepathImageProvider: AnimationImageProvider { - - // MARK: Lifecycle - - /// Initializes an image provider with a specific filepath. - /// - /// - Parameter filepath: The absolute filepath containing the images. - /// - Parameter contentsGravity: The contents gravity to use when rendering the images. - /// - public init(filepath: String, contentsGravity: CALayerContentsGravity = .resize) { - self.filepath = URL(fileURLWithPath: filepath) - self.contentsGravity = contentsGravity - } - - /// Initializes an image provider with a specific filepath. - /// - /// - Parameter filepath: The absolute filepath containing the images. - /// - Parameter contentsGravity: The contents gravity to use when rendering the images. - /// - public init(filepath: URL, contentsGravity: CALayerContentsGravity = .resize) { - self.filepath = filepath - self.contentsGravity = contentsGravity - } - - // MARK: Public - - public func imageForAsset(asset: ImageAsset) -> CGImage? { - if - asset.name.hasPrefix("data:"), - let url = URL(string: asset.name), - let data = try? Data(contentsOf: url), - let image = NSImage(data: data) - { - return image.lottie_CGImage - } - - let directPath = filepath.appendingPathComponent(asset.name).path - if FileManager.default.fileExists(atPath: directPath) { - return NSImage(contentsOfFile: directPath)?.lottie_CGImage - } - - let pathWithDirectory = filepath.appendingPathComponent(asset.directory).appendingPathComponent(asset.name).path - if FileManager.default.fileExists(atPath: pathWithDirectory) { - return NSImage(contentsOfFile: pathWithDirectory)?.lottie_CGImage - } - - LottieLogger.shared.warn("Could not find image \"\(asset.name)\" in bundle") - return nil - } - - public func contentsGravity(for _: ImageAsset) -> CALayerContentsGravity { - contentsGravity - } - - // MARK: Internal - - let filepath: URL - let contentsGravity: CALayerContentsGravity -} - -extension FilepathImageProvider: Equatable { - public static func ==(_ lhs: FilepathImageProvider, _ rhs: FilepathImageProvider) -> Bool { - lhs.filepath == rhs.filepath - } -} - -extension NSImage { - @nonobjc - var lottie_CGImage: CGImage? { - guard let imageData = tiffRepresentation else { return nil } - guard let sourceData = CGImageSourceCreateWithData(imageData as CFData, nil) else { return nil } - return CGImageSourceCreateImageAtIndex(sourceData, 0, nil) - } -} -#endif diff --git a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/LottieAnimationViewBase.macOS.swift b/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/LottieAnimationViewBase.macOS.swift deleted file mode 100644 index d51e5c67f5fd0a66a652be559076237675e3cef2..0000000000000000000000000000000000000000 --- a/uni_modules/uni-animation-view/utssdk/app-ios/lottie-ios/Public/macOS/LottieAnimationViewBase.macOS.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// LottieAnimationViewBase.swift -// lottie-swift-iOS -// -// Created by Brandon Withrow on 2/6/19. -// - -#if os(macOS) -import AppKit - -public enum LottieContentMode: Int { - case scaleToFill - case scaleAspectFit - case scaleAspectFill - case redraw - case center - case top - case bottom - case left - case right - case topLeft - case topRight - case bottomLeft - case bottomRight -} - -/// The base view for `LottieAnimationView` on macOs. -/// -/// Enables the `LottieAnimationView` implementation to be shared across platforms. -open class LottieAnimationViewBase: NSView { - - // MARK: Public - - public override var wantsUpdateLayer: Bool { - true - } - - public override var isFlipped: Bool { - true - } - - public var contentMode: LottieContentMode = .scaleAspectFit { - didSet { - setNeedsLayout() - } - } - - public override func viewDidMoveToWindow() { - super.viewDidMoveToWindow() - animationMovedToWindow() - } - - public override func layout() { - super.layout() - CATransaction.begin() - CATransaction.setDisableActions(true) - layoutAnimation() - CATransaction.commit() - } - - // MARK: Internal - - var screenScale: CGFloat { - NSApp.mainWindow?.backingScaleFactor ?? 1 - } - - var viewLayer: CALayer? { - layer - } - - func layoutAnimation() { - // Implemented by subclasses. - } - - func animationMovedToWindow() { - // Implemented by subclasses. - } - - func commonInit() { - wantsLayer = true - } - - func setNeedsLayout() { - needsLayout = true - } - - func layoutIfNeeded() { - // Implemented by subclasses. - } - - @objc - func animationWillMoveToBackground() { - // Implemented by subclasses. - } - - @objc - func animationWillEnterForeground() { - // Implemented by subclasses. - } - -} -#endif