先提交
This commit is contained in:
1
Podfile
1
Podfile
@@ -14,6 +14,7 @@ target 'keyBoard' do
|
||||
pod 'MJRefresh', '3.7.9'
|
||||
pod 'SDWebImage', '5.21.1'
|
||||
pod 'DZNEmptyDataSet', '1.8.1'
|
||||
pod 'lottie-ios', :git => 'https://github.com/airbnb/lottie-ios.git', :branch => 'lottie/objectiveC'
|
||||
pod 'LookinServer', :configurations => ['Debug']
|
||||
end
|
||||
|
||||
|
||||
15
Podfile.lock
15
Podfile.lock
@@ -19,6 +19,7 @@ PODS:
|
||||
- LookinServer (1.2.8):
|
||||
- LookinServer/Core (= 1.2.8)
|
||||
- LookinServer/Core (1.2.8)
|
||||
- lottie-ios (2.5.3)
|
||||
- Masonry (1.1.0)
|
||||
- MBProgressHUD (1.2.0)
|
||||
- MJExtension (3.4.2)
|
||||
@@ -32,6 +33,7 @@ DEPENDENCIES:
|
||||
- Bugly
|
||||
- DZNEmptyDataSet (= 1.8.1)
|
||||
- LookinServer
|
||||
- lottie-ios (from `https://github.com/airbnb/lottie-ios.git`, branch `lottie/objectiveC`)
|
||||
- Masonry (= 1.1.0)
|
||||
- MBProgressHUD (= 1.2.0)
|
||||
- MJExtension (= 3.4.2)
|
||||
@@ -50,17 +52,28 @@ SPEC REPOS:
|
||||
- MJRefresh
|
||||
- SDWebImage
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
lottie-ios:
|
||||
:branch: lottie/objectiveC
|
||||
:git: https://github.com/airbnb/lottie-ios.git
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
lottie-ios:
|
||||
:commit: e44ed5a2a0bffa588933e0ca1bd1f0171ffaa096
|
||||
:git: https://github.com/airbnb/lottie-ios.git
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58
|
||||
Bugly: 217ac2ce5f0f2626d43dbaa4f70764c953a26a31
|
||||
DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7
|
||||
LookinServer: 1b2b61c6402ae29fa22182d48f5cd067b4e99e80
|
||||
lottie-ios: b8e2ada09dfff3d1ad5df18d27e1adb7e690680d
|
||||
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
|
||||
MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406
|
||||
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
|
||||
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
|
||||
PODFILE CHECKSUM: e80851eaead44de926040a227bf16809774cc3d2
|
||||
PODFILE CHECKSUM: 049030aa18b7c16780ea2521136c0b79261ff26b
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
52
Pods/Local Podspecs/lottie-ios.podspec.json
generated
Normal file
52
Pods/Local Podspecs/lottie-ios.podspec.json
generated
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "lottie-ios",
|
||||
"version": "2.5.3",
|
||||
"summary": "Used to natively render vector animations exported from After Effects.",
|
||||
"description": "Lottie is a mobile library for Android and iOS that parses Adobe After Effects animations exported as json with bodymovin and renders the vector animations natively on mobile and through React Native!\n\nFor the first time, designers can create and ship beautiful animations without an engineer painstakingly recreating it be hand. Since the animation is backed by JSON they are extremely small in size but can be large in complexity! Animations can be played, resized, looped, sped up, slowed down, and even interactively scrubbed.",
|
||||
"homepage": "https://github.com/airbnb/lottie-ios",
|
||||
"license": {
|
||||
"type": "Apache",
|
||||
"file": "LICENSE"
|
||||
},
|
||||
"authors": {
|
||||
"Brandon Withrow": "buba447@gmail.com"
|
||||
},
|
||||
"source": {
|
||||
"git": "https://github.com/airbnb/lottie-ios.git",
|
||||
"tag": "2.5.3"
|
||||
},
|
||||
"platforms": {
|
||||
"ios": "8.0",
|
||||
"osx": "10.9",
|
||||
"tvos": "9.0"
|
||||
},
|
||||
"exclude_files": "lottie-ios/Classes/include/**/*",
|
||||
"source_files": "lottie-ios/Classes/**/*",
|
||||
"osx": {
|
||||
"exclude_files": [
|
||||
"lottie-ios/Classes/PublicHeaders/LOTAnimationTransitionController.h",
|
||||
"lottie-ios/Classes/Private/LOTAnimationTransitionController.m",
|
||||
"lottie-ios/Classes/PublicHeaders/LOTCacheProvider.h",
|
||||
"lottie-ios/Classes/Private/LOTCacheProvider.m",
|
||||
"lottie-ios/Classes/PublicHeaders/LOTAnimatedSwitch.h",
|
||||
"lottie-ios/Classes/Private/LOTAnimatedSwitch.m",
|
||||
"lottie-ios/Classes/PublicHeaders/LOTAnimatedControl.h",
|
||||
"lottie-ios/Classes/Private/LOTAnimatedControl.m"
|
||||
],
|
||||
"frameworks": [
|
||||
"AppKit",
|
||||
"CoreVideo"
|
||||
]
|
||||
},
|
||||
"resource_bundles": {
|
||||
"Lottie": [
|
||||
"Lottie/PrivacyInfo.xcprivacy"
|
||||
]
|
||||
},
|
||||
"public_header_files": "lottie-ios/Classes/PublicHeaders/*.h",
|
||||
"ios": {
|
||||
"frameworks": "UIKit"
|
||||
},
|
||||
"module_name": "Lottie",
|
||||
"header_dir": "Lottie"
|
||||
}
|
||||
15
Pods/Manifest.lock
generated
15
Pods/Manifest.lock
generated
@@ -19,6 +19,7 @@ PODS:
|
||||
- LookinServer (1.2.8):
|
||||
- LookinServer/Core (= 1.2.8)
|
||||
- LookinServer/Core (1.2.8)
|
||||
- lottie-ios (2.5.3)
|
||||
- Masonry (1.1.0)
|
||||
- MBProgressHUD (1.2.0)
|
||||
- MJExtension (3.4.2)
|
||||
@@ -32,6 +33,7 @@ DEPENDENCIES:
|
||||
- Bugly
|
||||
- DZNEmptyDataSet (= 1.8.1)
|
||||
- LookinServer
|
||||
- lottie-ios (from `https://github.com/airbnb/lottie-ios.git`, branch `lottie/objectiveC`)
|
||||
- Masonry (= 1.1.0)
|
||||
- MBProgressHUD (= 1.2.0)
|
||||
- MJExtension (= 3.4.2)
|
||||
@@ -50,17 +52,28 @@ SPEC REPOS:
|
||||
- MJRefresh
|
||||
- SDWebImage
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
lottie-ios:
|
||||
:branch: lottie/objectiveC
|
||||
:git: https://github.com/airbnb/lottie-ios.git
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
lottie-ios:
|
||||
:commit: e44ed5a2a0bffa588933e0ca1bd1f0171ffaa096
|
||||
:git: https://github.com/airbnb/lottie-ios.git
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58
|
||||
Bugly: 217ac2ce5f0f2626d43dbaa4f70764c953a26a31
|
||||
DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7
|
||||
LookinServer: 1b2b61c6402ae29fa22182d48f5cd067b4e99e80
|
||||
lottie-ios: b8e2ada09dfff3d1ad5df18d27e1adb7e690680d
|
||||
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
|
||||
MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406
|
||||
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
|
||||
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
|
||||
PODFILE CHECKSUM: e80851eaead44de926040a227bf16809774cc3d2
|
||||
PODFILE CHECKSUM: 049030aa18b7c16780ea2521136c0b79261ff26b
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
4867
Pods/Pods.xcodeproj/project.pbxproj
generated
4867
Pods/Pods.xcodeproj/project.pbxproj
generated
File diff suppressed because it is too large
Load Diff
58
Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/lottie-ios-Lottie.xcscheme
generated
Normal file
58
Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/lottie-ios-Lottie.xcscheme
generated
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1600"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "136FDD82F26C77E0886BF3ECAE2ADFC9"
|
||||
BuildableName = "Lottie.bundle"
|
||||
BlueprintName = "lottie-ios-Lottie"
|
||||
ReferencedContainer = "container:Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
58
Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/lottie-ios.xcscheme
generated
Normal file
58
Pods/Pods.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/lottie-ios.xcscheme
generated
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1600"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0B967D7F8561D42493EE289EC8D450D1"
|
||||
BuildableName = "Lottie.framework"
|
||||
BlueprintName = "lottie-ios"
|
||||
ReferencedContainer = "container:Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -175,6 +175,211 @@ THE SOFTWARE.
|
||||
|
||||
|
||||
|
||||
## lottie-ios
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2018 Airbnb, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
## Bugly
|
||||
|
||||
Copyright (C) 2017 Tencent Bugly, Inc. All rights reserved.
|
||||
|
||||
@@ -234,6 +234,217 @@ THE SOFTWARE.
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string> Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2018 Airbnb, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
</string>
|
||||
<key>License</key>
|
||||
<string>Apache</string>
|
||||
<key>Title</key>
|
||||
<string>lottie-ios</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright (C) 2017 Tencent Bugly, Inc. All rights reserved.
|
||||
|
||||
@@ -6,4 +6,5 @@ ${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework
|
||||
${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework
|
||||
${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
|
||||
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
|
||||
${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework
|
||||
${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework
|
||||
${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
|
||||
@@ -5,4 +5,5 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
|
||||
@@ -5,4 +5,5 @@ ${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework
|
||||
${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework
|
||||
${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
|
||||
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
|
||||
${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework
|
||||
${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework
|
||||
${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
|
||||
@@ -4,4 +4,5 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework
|
||||
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
|
||||
@@ -184,6 +184,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework"
|
||||
fi
|
||||
if [[ "$CONFIGURATION" == "Release" ]]; then
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework"
|
||||
@@ -193,6 +194,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework"
|
||||
install_framework "${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework"
|
||||
fi
|
||||
if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
|
||||
wait
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/LookinServer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/LookinServer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LookinServer/LookinServer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers"
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LookinServer/LookinServer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "ImageIO" -framework "LookinServer" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "UIKit"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/LookinServer" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage"
|
||||
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "ImageIO" -framework "LookinServer" -framework "Lottie" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "UIKit"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/LookinServer" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_ROOT}/Bugly"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_ROOT}/Bugly"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers"
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"z" -framework "AFNetworking" -framework "Bugly" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "ImageIO" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "Security" -framework "SystemConfiguration" -framework "UIKit"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/Bugly" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"z" -framework "AFNetworking" -framework "Bugly" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "ImageIO" -framework "Lottie" -framework "MBProgressHUD" -framework "MJExtension" -framework "MJRefresh" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "Security" -framework "SystemConfiguration" -framework "UIKit"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/Bugly" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
|
||||
24
Pods/Target Support Files/lottie-ios/ResourceBundle-Lottie-lottie-ios-Info.plist
generated
Normal file
24
Pods/Target Support Files/lottie-ios/ResourceBundle-Lottie-lottie-ios-Info.plist
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>${PODS_DEVELOPMENT_LANGUAGE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.5.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
26
Pods/Target Support Files/lottie-ios/lottie-ios-Info.plist
generated
Normal file
26
Pods/Target Support Files/lottie-ios/lottie-ios-Info.plist
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>${PODS_DEVELOPMENT_LANGUAGE}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.5.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${CURRENT_PROJECT_VERSION}</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
5
Pods/Target Support Files/lottie-ios/lottie-ios-dummy.m
generated
Normal file
5
Pods/Target Support Files/lottie-ios/lottie-ios-dummy.m
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
@interface PodsDummy_lottie_ios : NSObject
|
||||
@end
|
||||
@implementation PodsDummy_lottie_ios
|
||||
@end
|
||||
12
Pods/Target Support Files/lottie-ios/lottie-ios-prefix.pch
generated
Normal file
12
Pods/Target Support Files/lottie-ios/lottie-ios-prefix.pch
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
30
Pods/Target Support Files/lottie-ios/lottie-ios-umbrella.h
generated
Normal file
30
Pods/Target Support Files/lottie-ios/lottie-ios-umbrella.h
generated
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#import "LOTAnimatedControl.h"
|
||||
#import "LOTAnimatedSwitch.h"
|
||||
#import "LOTAnimationCache.h"
|
||||
#import "LOTAnimationTransitionController.h"
|
||||
#import "LOTAnimationView.h"
|
||||
#import "LOTAnimationView_Compat.h"
|
||||
#import "LOTBlockCallback.h"
|
||||
#import "LOTCacheProvider.h"
|
||||
#import "LOTComposition.h"
|
||||
#import "LOTInterpolatorCallback.h"
|
||||
#import "LOTKeypath.h"
|
||||
#import "Lottie.h"
|
||||
#import "LOTValueCallback.h"
|
||||
#import "LOTValueDelegate.h"
|
||||
|
||||
FOUNDATION_EXPORT double LottieVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char LottieVersionString[];
|
||||
|
||||
13
Pods/Target Support Files/lottie-ios/lottie-ios.debug.xcconfig
generated
Normal file
13
Pods/Target Support Files/lottie-ios/lottie-ios.debug.xcconfig
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
OTHER_LDFLAGS = $(inherited) -framework "UIKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/lottie-ios
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
6
Pods/Target Support Files/lottie-ios/lottie-ios.modulemap
generated
Normal file
6
Pods/Target Support Files/lottie-ios/lottie-ios.modulemap
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
framework module Lottie {
|
||||
umbrella header "lottie-ios-umbrella.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
13
Pods/Target Support Files/lottie-ios/lottie-ios.release.xcconfig
generated
Normal file
13
Pods/Target Support Files/lottie-ios/lottie-ios.release.xcconfig
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
OTHER_LDFLAGS = $(inherited) -framework "UIKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/lottie-ios
|
||||
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
201
Pods/lottie-ios/LICENSE
generated
Normal file
201
Pods/lottie-ios/LICENSE
generated
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2018 Airbnb, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
14
Pods/lottie-ios/Lottie/PrivacyInfo.xcprivacy
generated
Normal file
14
Pods/lottie-ios/Lottie/PrivacyInfo.xcprivacy
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyTrackingDomains</key>
|
||||
<array/>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array/>
|
||||
</dict>
|
||||
</plist>
|
||||
631
Pods/lottie-ios/README.md
generated
Normal file
631
Pods/lottie-ios/README.md
generated
Normal file
@@ -0,0 +1,631 @@
|
||||
# Lottie for iOS, macOS (and [Android](https://github.com/airbnb/lottie-android) and [React Native](https://github.com/airbnb/lottie-react-native))
|
||||
|
||||
### Table of Contents
|
||||
- [Introduction](#introduction)
|
||||
- [Installing Lottie](#installing-lottie)
|
||||
- [iOS Sample App](#ios-sample-app)
|
||||
- [macOS Sample App](#macos-sample-app)
|
||||
- [Objective C Examples](#objective-c-examples)
|
||||
- [Swift Examples](#swift-examples)
|
||||
- [Debugging Lottie](#debugging)
|
||||
- [iOS View Controller Transitioning](#ios-view-controller-transitioning)
|
||||
- [Changing Animations At Runtime](#changing-animations-at-runtime)
|
||||
- [Animated Controls and Switches](#animated-controls-and-switches)
|
||||
- [Adding Subviews to Animation](#adding-views-to-an-animation-at-runtime)
|
||||
- [Supported After Effects Features](#supported-after-effects-features)
|
||||
- [Currently Unsupported After Effects Features](#currently-unsupported-after-effects-features)
|
||||
- [Community Contributions](#community-contributions)
|
||||
- [Alternatives](#alternatives)
|
||||
- [Why is it called Lottie?](#why-is-it-called-lottie)
|
||||
- [Contributing](#contributing)
|
||||
- [Issues or feature requests?](#issues-or-feature-requests)
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
Lottie is a mobile library for Android and iOS that parses [Adobe After Effects](http://www.adobe.com/products/aftereffects.html) animations exported as json with [bodymovin](https://github.com/bodymovin/bodymovin) and renders the vector animations natively on mobile and through React Native!
|
||||
|
||||
For the first time, designers can create **and ship** beautiful animations without an engineer painstakingly recreating it by hand.
|
||||
Since the animation is backed by JSON they are extremely small in size but can be large in complexity!
|
||||
Animations can be played, resized, looped, sped up, slowed down, reversed, and even interactively scrubbed.
|
||||
Lottie can play or loop just a portion of the animation as well, the possibilities are endless!
|
||||
Animations can even be ***changed at runtime*** in various ways! Change the color, position or any keyframable value!
|
||||
Lottie also supports native UIViewController Transitions out of the box!
|
||||
|
||||
Here is just a small sampling of the power of Lottie
|
||||
|
||||

|
||||

|
||||
|
||||
<img src="_Gifs/Community 2_3.gif" />
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Installing Lottie
|
||||
|
||||
### Github Repo
|
||||
You can pull the [Lottie Github Repo](https://github.com/airbnb/lottie-ios/) and include the Lottie.xcodeproj to build a dynamic or static library.
|
||||
|
||||
### Cocoapods
|
||||
Get [Cocoapods](https://cocoapods.org/)
|
||||
Add the pod to your podfile
|
||||
```
|
||||
pod 'lottie-ios'
|
||||
```
|
||||
run
|
||||
```
|
||||
pod install
|
||||
```
|
||||
|
||||
After installing the cocoapod into your project import Lottie with
|
||||
Objective C
|
||||
`#import <Lottie/Lottie.h>`
|
||||
Swift
|
||||
`import Lottie`
|
||||
|
||||
### Carthage
|
||||
Get [Carthage](https://github.com/Carthage/Carthage)
|
||||
|
||||
Add Lottie to your Cartfile
|
||||
```
|
||||
github "airbnb/lottie-ios" "master"
|
||||
```
|
||||
run
|
||||
```
|
||||
carthage update
|
||||
```
|
||||
|
||||
In your application targets “General” tab under the “Linked Frameworks and Libraries” section, drag and drop lottie-ios.framework from the Carthage/Build/iOS directory that `carthage update` produced.
|
||||
|
||||
## iOS Sample App
|
||||
|
||||
Clone this repo and try out [the Sample App](https://github.com/airbnb/lottie-ios/tree/master/Example)
|
||||
The repo can build a macOS Example and an iOS Example
|
||||
|
||||
The iOS Example App demos several of the features of Lottie
|
||||
|
||||

|
||||

|
||||
|
||||
The animation Explorer allows you to scrub, play, loop, and resize animations.
|
||||
Animations can be loaded from the app bundle or from [Lottie Files](http://www.lottiefiles.com) using the built in QR Code reader.
|
||||
|
||||
## macOS Sample App
|
||||
|
||||
Clone this repo and try out [the Sample App](https://github.com/airbnb/lottie-ios/tree/master/Example)
|
||||
The repo can build a macOS Example and an iOS Example
|
||||
|
||||

|
||||
|
||||
The Lottie Viewer for macOS allows you to drag and drop JSON files to open, play, scrub and loop animations. This app is backed by the same animation code as the iOS app, so you will get an accurate representation of Mac and iOS animations.
|
||||
|
||||
|
||||
## Objective C Examples
|
||||
|
||||
|
||||
Lottie animations can be loaded from bundled JSON or from a URL
|
||||
To bundle JSON just add it and any images that the animation requires to your target in xcode.
|
||||
|
||||
```objective-c
|
||||
LOTAnimationView *animation = [LOTAnimationView animationNamed:@"Lottie"];
|
||||
[self.view addSubview:animation];
|
||||
[animation playWithCompletion:^(BOOL animationFinished) {
|
||||
// Do Something
|
||||
}];
|
||||
```
|
||||
|
||||
If you are working with multiple bundles you can use.
|
||||
|
||||
```objective-c
|
||||
LOTAnimationView *animation = [LOTAnimationView animationNamed:@"Lottie" inBundle:[NSBundle YOUR_BUNDLE]];
|
||||
[self.view addSubview:animation];
|
||||
[animation playWithCompletion:^(BOOL animationFinished) {
|
||||
// Do Something
|
||||
}];
|
||||
```
|
||||
|
||||
Or you can load it programmatically from a NSURL
|
||||
```objective-c
|
||||
LOTAnimationView *animation = [[LOTAnimationView alloc] initWithContentsOfURL:[NSURL URLWithString:URL]];
|
||||
[self.view addSubview:animation];
|
||||
```
|
||||
|
||||
Lottie supports the iOS `UIViewContentModes` aspectFit, aspectFill and scaleFill
|
||||
|
||||
You can also set the animation progress interactively.
|
||||
```objective-c
|
||||
CGPoint translation = [gesture getTranslationInView:self.view];
|
||||
CGFloat progress = translation.y / self.view.bounds.size.height;
|
||||
animationView.animationProgress = progress;
|
||||
```
|
||||
|
||||
Or you can play just a portion of the animation:
|
||||
```objective-c
|
||||
[lottieAnimation playFromProgress:0.25 toProgress:0.5 withCompletion:^(BOOL animationFinished) {
|
||||
// Do Something
|
||||
}];
|
||||
```
|
||||
## Swift Examples
|
||||
|
||||
Lottie animations can be loaded from bundled JSON or from a URL
|
||||
To bundle JSON just add it and any images that the animation requires to your target in xcode.
|
||||
|
||||
```swift
|
||||
let animationView = LOTAnimationView(name: "LottieLogo")
|
||||
self.view.addSubview(animationView)
|
||||
animationView.play{ (finished) in
|
||||
// Do Something
|
||||
}
|
||||
```
|
||||
|
||||
If your animation is in another bundle you can use
|
||||
```swift
|
||||
let animationView = LOTAnimationView(name: "LottieLogo", bundle: yourBundle)
|
||||
self.view.addSubview(animationView)
|
||||
animationView.play()
|
||||
```
|
||||
|
||||
Or you can load it asynchronously from a URL
|
||||
```swift
|
||||
let animationView = LOTAnimationView(contentsOf: WebURL)
|
||||
self.view.addSubview(animationView)
|
||||
animationView.play()
|
||||
```
|
||||
|
||||
You can also set the animation progress interactively.
|
||||
```swift
|
||||
let translation = gesture.getTranslationInView(self.view)
|
||||
let progress = translation.y / self.view.bounds.size.height
|
||||
animationView.animationProgress = progress
|
||||
```
|
||||
|
||||
Or you can play just a portion of the animation:
|
||||
```swift
|
||||
animationView.play(fromProgress: 0.25, toProgress: 0.5, withCompletion: nil)
|
||||
```
|
||||
|
||||
## iOS View Controller Transitioning
|
||||
|
||||
Lottie comes with a `UIViewController` animation-controller for making custom viewController transitions!
|
||||
|
||||

|
||||

|
||||
|
||||
Just become the delegate for a transition
|
||||
|
||||
```objective-c
|
||||
- (void)_showTransitionA {
|
||||
ToAnimationViewController *vc = [[ToAnimationViewController alloc] init];
|
||||
vc.transitioningDelegate = self;
|
||||
[self presentViewController:vc animated:YES completion:NULL];
|
||||
}
|
||||
```
|
||||
|
||||
And implement the delegate methods with a `LOTAnimationTransitionController`
|
||||
|
||||
```objective-c
|
||||
#pragma mark -- View Controller Transitioning
|
||||
|
||||
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
|
||||
LOTAnimationTransitionController *animationController = [[LOTAnimationTransitionController alloc] initWithAnimationNamed:@"vcTransition1" fromLayerNamed:@"outLayer" toLayerNamed:@"inLayer" applyAnimationTransform:NO];
|
||||
return animationController;
|
||||
}
|
||||
|
||||
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
|
||||
LOTAnimationTransitionController *animationController = [[LOTAnimationTransitionController alloc] initWithAnimationNamed:@"vcTransition2" fromLayerNamed:@"outLayer" toLayerNamed:@"inLayer" applyAnimationTransform:NO];
|
||||
return animationController;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
By setting `applyAnimationTransform` to YES you can make the Lottie animation move the from and to view controllers. They will be positioned at the origin of the layer. When set to NO Lottie just masks the view controller with the specified layer while respecting z order.
|
||||
|
||||
## Debugging
|
||||
Lottie has a couple of debugging features to know about.
|
||||
When an animation is loaded unsupported features are logged out in the console with their function names.
|
||||
|
||||
If you checkout LOTHelpers.h you will see two debug flags. `ENABLE_DEBUG_LOGGING` and `ENABLE_DEBUG_SHAPES`.
|
||||
`ENABLE_DEBUG_LOGGING` increases the verbosity of Lottie Logging. It logs anytime an animation node is set during animation. If your animation if not working, turn this on and play your animation. The console log might give you some clues as to whats going on.
|
||||
|
||||
`ENABLE_DEBUG_SHAPES` Draws a colored square for the anchor-point of every layer and shape. This is helpful to see if anything is on screen.
|
||||
|
||||
### Keypaths
|
||||
|
||||
LOTAnimationView provides `- (void)logHierarchyKeypaths` which will recursively log all settable keypaths for the animation. This is helpful for changing animations at runtime.
|
||||
|
||||
## Adding Views to an Animation at Runtime
|
||||
|
||||
Not only can you [change animations at runtime](#changing-animations-at-runtime) with Lottie, you can also add custom UI to a LOTAnimation at runtime.
|
||||
The example below shows some advance uses of this to create a dynamic image loader.
|
||||
|
||||
## A Dynamic Image Loading Spinner
|
||||
|
||||

|
||||
|
||||
The example above shows a single LOTAnimationView that is set with a loading spinner animation. The loading spinner loops a portion of its animation while an image is downloaded asynchronously. When the download is complete, the image is added to the animation and the rest of the animation is played seamlessly. The image is cleanly animated in and a completion block is called.
|
||||
|
||||

|
||||
|
||||
Now, the animation has been changed by a designer and needs to be updated. All that is required is updating the JSON file in the bundle. No code change needed!
|
||||
|
||||

|
||||
|
||||
Here, the design has decided to add a 'Dark Mode' to the app. Just a few lines of code change the color of the animation at runtime.
|
||||
|
||||
|
||||
Pretty powerful eh?
|
||||
|
||||
Check out the code below for an example!
|
||||
|
||||
```swift
|
||||
|
||||
import UIKit
|
||||
import Lottie
|
||||
|
||||
class ViewController: UIViewController {
|
||||
|
||||
var animationView: LOTAnimationView = LOTAnimationView(name: "SpinnerSpin");
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Setup our animation view
|
||||
animationView.contentMode = .scaleAspectFill
|
||||
animationView.frame = CGRect(x: 20, y: 20, width: 200, height: 200)
|
||||
|
||||
self.view.addSubview(animationView)
|
||||
// Lets change some of the properties of the animation
|
||||
// We aren't going to use the MaskLayer, so let's just hide it
|
||||
animationView.setValue(0, forKeypath: "MaskLayer.Ellipse 1.Transform.Opacity", atFrame: 0)
|
||||
// All of the strokes and fills are white, lets make them DarkGrey
|
||||
animationView.setValue(UIColor.darkGray, forKeypath: "OuterRing.Stroke.Color", atFrame: 0)
|
||||
animationView.setValue(UIColor.darkGray, forKeypath: "InnerRing.Stroke.Color", atFrame: 0)
|
||||
animationView.setValue(UIColor.darkGray, forKeypath: "InnerRing.Fill.Color", atFrame: 0)
|
||||
|
||||
// Lets turn looping on, since we want it to repeat while the image is 'Downloading'
|
||||
animationView.loopAnimation = true
|
||||
// Now play from 0 to 0.5 progress and loop indefinitely.
|
||||
animationView.play(fromProgress: 0, toProgress: 0.5, withCompletion: nil)
|
||||
|
||||
// Lets simulate a download that finishes in 4 seconds.
|
||||
let dispatchTime = DispatchTime.now() + 4.0
|
||||
DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
|
||||
self.simulateImageDownloaded()
|
||||
}
|
||||
}
|
||||
|
||||
func simulateImageDownloaded() {
|
||||
// Our downloaded image
|
||||
let image = UIImage(named: "avatar.jpg")
|
||||
let imageView = UIImageView(image: image)
|
||||
|
||||
// We want the image to show up centered in the animation view at 150Px150P
|
||||
// Convert that rect to the animations coordinate space
|
||||
// The origin is set to -75, -75 because the origin is centered in the animation view
|
||||
let imageRect = animationView.convert(CGRect(x: -75, y: -75, width: 150, height: 150), toLayerNamed: nil)
|
||||
|
||||
// Setup our image view with the rect and add rounded corners
|
||||
imageView.frame = imageRect
|
||||
imageView.layer.masksToBounds = true
|
||||
imageView.layer.cornerRadius = imageRect.width / 2;
|
||||
|
||||
// Now we set the completion block on the currently running animation
|
||||
animationView.completionBlock = { (result: Bool) in ()
|
||||
// Add the image view to the layer named "TransformLayer"
|
||||
self.animationView.addSubview(imageView, toLayerNamed: "TransformLayer", applyTransform: true)
|
||||
// Now play the last half of the animation
|
||||
self.animationView.play(fromProgress: 0.5, toProgress: 1, withCompletion: { (complete: Bool) in
|
||||
// Now the animation has finished and our image is displayed on screen
|
||||
print("Image Downloaded and Displayed")
|
||||
})
|
||||
}
|
||||
|
||||
// Turn looping off. Once the current loop finishes the animation will stop
|
||||
// and the completion block will be called.
|
||||
animationView.loopAnimation = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Changing Animations At Runtime
|
||||
|
||||
Lottie can do more than just play beautiful animations. Lottie allows you to **change** animations at runtime.
|
||||
|
||||
### Say we want to create 4 toggle switches.
|
||||

|
||||
Its easy to create the four switches and play them:
|
||||
|
||||
```swift
|
||||
let animationView = LOTAnimationView(name: "toggle");
|
||||
self.view.addSubview(animationView)
|
||||
animationView.frame.origin.x = 40
|
||||
animationView.frame.origin.y = 20
|
||||
animationView.autoReverseAnimation = true
|
||||
animationView.loopAnimation = true
|
||||
animationView.play()
|
||||
|
||||
let animationView2 = LOTAnimationView(name: "toggle");
|
||||
self.view.addSubview(animationView2)
|
||||
animationView2.frame.origin.x = 40
|
||||
animationView2.frame.origin.y = animationView.frame.maxY + 4
|
||||
animationView2.autoReverseAnimation = true
|
||||
animationView2.loopAnimation = true
|
||||
animationView2.play()
|
||||
|
||||
let animationView3 = LOTAnimationView(name: "toggle");
|
||||
self.view.addSubview(animationView3)
|
||||
animationView3.frame.origin.x = 40
|
||||
animationView3.frame.origin.y = animationView2.frame.maxY + 4
|
||||
animationView3.autoReverseAnimation = true
|
||||
animationView3.loopAnimation = true
|
||||
animationView3.play()
|
||||
|
||||
let animationView4 = LOTAnimationView(name: "toggle");
|
||||
self.view.addSubview(animationView4)
|
||||
animationView4.frame.origin.x = 40
|
||||
animationView4.frame.origin.y = animationView3.frame.maxY + 4
|
||||
animationView4.autoReverseAnimation = true
|
||||
animationView4.loopAnimation = true
|
||||
animationView4.play()
|
||||
|
||||
```
|
||||
### Now lets change their colors
|
||||

|
||||
|
||||
**NB**: `animationView.setValue(YOUR_COLOR, forKeypath: "YOUR_PATH.Color", atFrame: 0)` is now deprecated.
|
||||
|
||||
```swift
|
||||
class GreenDelegate : NSObject, LOTColorValueDelegate {
|
||||
func color(forFrame currentFrame: CGFloat, startKeyframe: CGFloat, endKeyframe: CGFloat, interpolatedProgress: CGFloat, start startColor: CGColor!, end endColor: CGColor!, currentColor interpolatedColor: CGColor!) -> Unmanaged<CGColor>! {
|
||||
return Unmanaged.passRetained(UIColor.green.cgColor)
|
||||
}
|
||||
}
|
||||
animationView2.setValueDelegate(GreenDelegate(), for: LOTKeypath(string: "BG-On.Group 1.Fill 1.Color"))
|
||||
|
||||
class RedDelegate : NSObject, LOTColorValueDelegate {
|
||||
func color(forFrame currentFrame: CGFloat, startKeyframe: CGFloat, endKeyframe: CGFloat, interpolatedProgress: CGFloat, start startColor: CGColor!, end endColor: CGColor!, currentColor interpolatedColor: CGColor!) -> Unmanaged<CGColor>! {
|
||||
return Unmanaged.passRetained(UIColor.red.cgColor)
|
||||
}
|
||||
}
|
||||
animationView3.setValueDelegate(RedDelegate(), for: LOTKeypath(string: "BG-On.Group 1.Fill 1.Color"))
|
||||
|
||||
class OrangeDelegate : NSObject, LOTColorValueDelegate {
|
||||
func color(forFrame currentFrame: CGFloat, startKeyframe: CGFloat, endKeyframe: CGFloat, interpolatedProgress: CGFloat, start startColor: CGColor!, end endColor: CGColor!, currentColor interpolatedColor: CGColor!) -> Unmanaged<CGColor>! {
|
||||
return Unmanaged.passRetained(UIColor.orange.cgColor)
|
||||
}
|
||||
}
|
||||
animationView4.setValueDelegate(OrangeDelegate(), for: LOTKeypath(string: "BG-On.Group 1.Fill 1.Color"))
|
||||
```
|
||||
The keyPath is a dot separated path of layer and property names from After Effects.
|
||||
LOTAnimationView provides `- (void)logHierarchyKeypaths` which will recursively log all settable keypaths for the animation.
|
||||

|
||||
"BG-On.Group 1.Fill 1.Color"
|
||||
|
||||
### Now lets change a couple of properties
|
||||

|
||||
|
||||
```swift
|
||||
animationView2.setValueDelegate(delegate, for: LOTKeypath(string: YOUR_PATH))
|
||||
```
|
||||
|
||||
Lottie allows you to change **any** property that is animatable in After Effects. If a keyframe does not exist, a linear keyframe is created for you. If a keyframe does exist then just its data is replaced.
|
||||
|
||||
For this you need to use a `LOTValueDelegate` there are many already available:
|
||||
* `LOTColorValueDelegate`
|
||||
* `LOTNumberValueDelegate`
|
||||
* `LOTPointValueDelegate`
|
||||
* `LOTSizeValueDelegate`
|
||||
* `LOTPathValueDelegate`
|
||||
|
||||
## Animated Controls and Switches
|
||||
|
||||

|
||||
|
||||
Lottie also has a custom subclass of UIControl for creating custom animatable interactive controls.
|
||||
Currently Lottie has `LOTAnimatedSwitch` which is a toggle style switch control. Tapping on the switch plays either the On-Off or Off-On animation and sends out a UIControlStateValueChanged broadcast to all targets. It is used in the same way UISwitch is used with a few additions to setup the animation with Lottie.
|
||||
|
||||
You initialize the switch either using the convenience method or by supplying the animation directly.
|
||||
|
||||
```
|
||||
// Convenience
|
||||
LOTAnimatedSwitch *toggle1 = [LOTAnimatedSwitch switchNamed:@"Switch"];
|
||||
|
||||
// Manually
|
||||
LOTComposition *comp = [LOTComposition animationNamed:@"Switch"];
|
||||
LOTAnimatedSwitch *toggle1 = [[LOTAnimatedSwitch alloc] initWithFrame:CGRectZero];
|
||||
[toggle1 setAnimationComp:comp];
|
||||
```
|
||||
|
||||
You can also specify a specific portion of the animation's timeline for the On and Off animation.
|
||||
By default `LOTAnimatedSwitch` will play the animation forward for On and backwards for off.
|
||||
|
||||
Lets say that the supplied animation animates ON from 0.5-1 progress and OFF from 0-0.5:
|
||||
|
||||
```
|
||||
/// On animation is 0.5 to 1 progress.
|
||||
[toggle1 setProgressRangeForOnState:0.5 toProgress:1];
|
||||
|
||||
/// Off animation is 0 to 0.5 progress.
|
||||
[toggle1 setProgressRangeForOffState:0 toProgress:0.5];
|
||||
```
|
||||
|
||||
Also, all LOTAnimatedControls add support for changing appearance for state changes. This requires some setup in After Effects. Lottie will switch visible animated layers based on the controls state. This can be used to have Disabled, selected, or Highlighted states. These states are associated with layer names in After Effects, and are dynamically displayed as the control changes states.
|
||||
|
||||
Lets say we have a toggle switch with a Normal and Disabled state. In Effects we have a composition that contains Precomps of the regular "Button" and disabled "Disabled" states. They have different visual styles.
|
||||
|
||||

|
||||

|
||||
|
||||
Now in code we can associate `UIControlState` with these layers
|
||||
|
||||
```
|
||||
// Specify the layer names for different states
|
||||
[statefulSwitch setLayerName:@"Button" forState:UIControlStateNormal];
|
||||
[statefulSwitch setLayerName:@"Disabled" forState:UIControlStateDisabled];
|
||||
|
||||
// Changes visual appearance by switching animation layer to "Disabled"
|
||||
statefulSwitch.enabled = NO;
|
||||
|
||||
// Changes visual appearance by switching animation layer to "Button"
|
||||
statefulSwitch.enabled = YES;
|
||||
```
|
||||
|
||||
## Supported After Effects Features
|
||||
|
||||
### Keyframe Interpolation
|
||||
|
||||
---
|
||||
|
||||
* Linear Interpolation
|
||||
* Bezier Interpolation
|
||||
* Hold Interpolation
|
||||
* Rove Across Time
|
||||
* Spatial Bezier
|
||||
|
||||
### Solids
|
||||
|
||||
---
|
||||
|
||||
* Transform Anchor Point
|
||||
* Transform Position
|
||||
* Transform Scale
|
||||
* Transform Rotation
|
||||
* Transform Opacity
|
||||
|
||||
### Masks
|
||||
|
||||
---
|
||||
|
||||
* Path
|
||||
* Opacity
|
||||
* Multiple Masks (additive, subtractive and intersection)
|
||||
|
||||
### Track Mattes
|
||||
|
||||
---
|
||||
|
||||
* Alpha Matte
|
||||
|
||||
### Parenting
|
||||
|
||||
---
|
||||
|
||||
* Multiple Parenting
|
||||
* Nulls
|
||||
|
||||
### Shape Layers
|
||||
|
||||
---
|
||||
|
||||
* Anchor Point
|
||||
* Position
|
||||
* Scale
|
||||
* Rotation
|
||||
* Opacity
|
||||
* Path
|
||||
* Group Transforms (Anchor point, position, scale etc)
|
||||
* Rectangle (All properties)
|
||||
* Eclipse (All properties)
|
||||
* Multiple paths in one group
|
||||
* Even-Odd winding paths
|
||||
* Reverse Fill Rule
|
||||
|
||||
#### Stroke (shape layer)
|
||||
|
||||
---
|
||||
|
||||
* Stroke Color
|
||||
* Stroke Opacity
|
||||
* Stroke Width
|
||||
* Line Cap
|
||||
* Dashes (Now Animated!)
|
||||
|
||||
#### Fill (shape layer)
|
||||
|
||||
---
|
||||
|
||||
* Fill Color
|
||||
* Fill Opacity
|
||||
|
||||
#### Trim Paths (shape layer)
|
||||
|
||||
---
|
||||
|
||||
* Trim Paths Start
|
||||
* Trim Paths End
|
||||
* Trim Paths Offset
|
||||
|
||||
### Repeaters
|
||||
|
||||
---
|
||||
|
||||
* Supports repeater transforms
|
||||
* Offset currently not supported.
|
||||
|
||||
### Gradients
|
||||
|
||||
---
|
||||
|
||||
* Support for Linear Gradients
|
||||
* Support for Radial Gradients
|
||||
|
||||
### Polystar and Polygon
|
||||
|
||||
---
|
||||
|
||||
* Supported! Theres a known bug if the roundness is greater than 100 percent.
|
||||
|
||||
#### Layer Features
|
||||
|
||||
---
|
||||
|
||||
* Precomps
|
||||
* Image Layers
|
||||
* Shape Layers
|
||||
* Null Layers
|
||||
* Solid Layers
|
||||
* Parenting Layers
|
||||
* Alpha Matte Layers
|
||||
|
||||
## Currently Unsupported After Effects Features
|
||||
|
||||
* Merge Shapes
|
||||
* Alpha Inverted Masks
|
||||
* Trim Shapes Individually feature of Trim Paths
|
||||
* Expressions
|
||||
* 3d Layer support
|
||||
* Time remapping / Layer Reverse
|
||||
* Layer Blend Modes
|
||||
* Layer Effects
|
||||
|
||||
|
||||
## Community Contributions
|
||||
* [Xamarin bindings](https://github.com/martijn00/LottieXamarin)
|
||||
* [NativeScript bindings](https://github.com/bradmartin/nativescript-lottie)
|
||||
* [Appcelerator Titanium bindings](https://github.com/m1ga/ti.animation)
|
||||
* macOS Support added by [Alex Pawlowski](https://github.com/pawlowskialex)
|
||||
|
||||
## Alternatives
|
||||
1. Build animations by hand. Building animations by hand is a huge time commitment for design and engineering across Android and iOS. It's often hard or even impossible to justify spending so much time to get an animation right.
|
||||
2. [Facebook Keyframes](https://github.com/facebookincubator/Keyframes). Keyframes is a wonderful new library from Facebook that they built for reactions. However, Keyframes doesn't support some of Lottie's features such as masks, mattes, trim paths, dash patterns, and more.
|
||||
2. Gifs. Gifs are more than double the size of a bodymovin JSON and are rendered at a fixed size that can't be scaled up to match large and high density screens.
|
||||
3. Png sequences. Png sequences are even worse than gifs in that their file sizes are often 30-50x the size of the bodymovin json and also can't be scaled up.
|
||||
|
||||
## Why is it called Lottie?
|
||||
Lottie is named after a German film director and the foremost pioneer of silhouette animation. Her best known films are The Adventures of Prince Achmed (1926) – the oldest surviving feature-length animated film, preceding Walt Disney's feature-length Snow White and the Seven Dwarfs (1937) by over ten years
|
||||
[The art of Lotte Reineger](https://www.youtube.com/watch?v=LvU55CUw5Ck&feature=youtu.be)
|
||||
|
||||
## Contributing
|
||||
Contributors are more than welcome. Just upload a PR with a description of your changes.
|
||||
|
||||
If you would like to add more JSON files feel free to do so!
|
||||
|
||||
## Issues or feature requests?
|
||||
File github issues for anything that is unexpectedly broken. If an After Effects file is not working, please attach it to your issue. Debugging without the original file is much more difficult. Lottie is developed and maintained by [Brandon Withrow](mailto:brandon@withrow.io). Feel free to reach out via email or [Twitter](https://twitter.com/theWithra)
|
||||
|
||||
## Roadmap (In no particular order)
|
||||
- Add support for interactive animated transitions
|
||||
46
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTCompositionContainer.h
generated
Normal file
46
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTCompositionContainer.h
generated
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// LOTCompositionContainer.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/18/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTLayerContainer.h"
|
||||
#import "LOTAssetGroup.h"
|
||||
|
||||
@interface LOTCompositionContainer : LOTLayerContainer
|
||||
|
||||
- (instancetype _Nonnull)initWithModel:(LOTLayer * _Nullable)layer
|
||||
inLayerGroup:(LOTLayerGroup * _Nullable)layerGroup
|
||||
withLayerGroup:(LOTLayerGroup * _Nullable)childLayerGroup
|
||||
withAssestGroup:(LOTAssetGroup * _Nullable)assetGroup;
|
||||
|
||||
- (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent;
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent;
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent;
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent;
|
||||
|
||||
- (void)addSublayer:(nonnull CALayer *)subLayer
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
- (void)maskSublayer:(nonnull CALayer *)subLayer
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath;
|
||||
|
||||
@property (nonatomic, readonly, nonnull) NSArray<LOTLayerContainer *> *childLayers;
|
||||
@property (nonatomic, readonly, nonnull) NSDictionary *childMap;
|
||||
|
||||
@end
|
||||
239
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTCompositionContainer.m
generated
Normal file
239
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTCompositionContainer.m
generated
Normal file
@@ -0,0 +1,239 @@
|
||||
//
|
||||
// LOTCompositionContainer.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/18/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTCompositionContainer.h"
|
||||
#import "LOTAsset.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
#import "LOTHelpers.h"
|
||||
#import "LOTValueInterpolator.h"
|
||||
#import "LOTAnimatorNode.h"
|
||||
#import "LOTRenderNode.h"
|
||||
#import "LOTRenderGroup.h"
|
||||
#import "LOTNumberInterpolator.h"
|
||||
|
||||
@implementation LOTCompositionContainer {
|
||||
NSNumber *_frameOffset;
|
||||
CALayer *DEBUG_Center;
|
||||
NSMutableDictionary *_keypathCache;
|
||||
LOTNumberInterpolator *_timeInterpolator;
|
||||
}
|
||||
|
||||
- (instancetype)initWithModel:(LOTLayer *)layer
|
||||
inLayerGroup:(LOTLayerGroup *)layerGroup
|
||||
withLayerGroup:(LOTLayerGroup *)childLayerGroup
|
||||
withAssestGroup:(LOTAssetGroup *)assetGroup {
|
||||
self = [super initWithModel:layer inLayerGroup:layerGroup];
|
||||
if (self) {
|
||||
DEBUG_Center = [CALayer layer];
|
||||
|
||||
DEBUG_Center.bounds = CGRectMake(0, 0, 20, 20);
|
||||
DEBUG_Center.borderColor = [UIColor orangeColor].CGColor;
|
||||
DEBUG_Center.borderWidth = 2;
|
||||
DEBUG_Center.masksToBounds = YES;
|
||||
if (ENABLE_DEBUG_SHAPES) {
|
||||
[self.wrapperLayer addSublayer:DEBUG_Center];
|
||||
}
|
||||
if (layer.startFrame != nil) {
|
||||
_frameOffset = layer.startFrame;
|
||||
} else {
|
||||
_frameOffset = @0;
|
||||
}
|
||||
|
||||
if (layer.timeRemapping) {
|
||||
_timeInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:layer.timeRemapping.keyframes];
|
||||
}
|
||||
|
||||
[self initializeWithChildGroup:childLayerGroup withAssetGroup:assetGroup];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)initializeWithChildGroup:(LOTLayerGroup *)childGroup
|
||||
withAssetGroup:(LOTAssetGroup *)assetGroup {
|
||||
NSMutableDictionary *childMap = [NSMutableDictionary dictionary];
|
||||
NSMutableArray *children = [NSMutableArray array];
|
||||
NSArray *reversedItems = [[childGroup.layers reverseObjectEnumerator] allObjects];
|
||||
|
||||
CALayer *maskedLayer = nil;
|
||||
for (LOTLayer *layer in reversedItems) {
|
||||
LOTAsset *asset;
|
||||
if (layer.referenceID) {
|
||||
// Get relevant Asset
|
||||
asset = [assetGroup assetModelForID:layer.referenceID];
|
||||
}
|
||||
|
||||
LOTLayerContainer *child = nil;
|
||||
if (asset.layerGroup) {
|
||||
// Layer is a precomp
|
||||
LOTCompositionContainer *compLayer = [[LOTCompositionContainer alloc] initWithModel:layer inLayerGroup:childGroup withLayerGroup:asset.layerGroup withAssestGroup:assetGroup];
|
||||
child = compLayer;
|
||||
} else {
|
||||
child = [[LOTLayerContainer alloc] initWithModel:layer inLayerGroup:childGroup];
|
||||
}
|
||||
if (maskedLayer) {
|
||||
maskedLayer.mask = child;
|
||||
maskedLayer = nil;
|
||||
} else {
|
||||
if (layer.matteType == LOTMatteTypeAdd) {
|
||||
maskedLayer = child;
|
||||
}
|
||||
[self.wrapperLayer addSublayer:child];
|
||||
}
|
||||
[children addObject:child];
|
||||
if (child.layerName) {
|
||||
[childMap setObject:child forKey:child.layerName];
|
||||
}
|
||||
}
|
||||
_childMap = childMap;
|
||||
_childLayers = children;
|
||||
}
|
||||
|
||||
- (void)displayWithFrame:(NSNumber *)frame forceUpdate:(BOOL)forceUpdate {
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- Composition Displaying Frame %@ --------------------", frame);
|
||||
[super displayWithFrame:frame forceUpdate:forceUpdate];
|
||||
NSNumber *newFrame = @((frame.floatValue - _frameOffset.floatValue) / self.timeStretchFactor.floatValue);
|
||||
if (_timeInterpolator) {
|
||||
newFrame = @([_timeInterpolator floatValueForFrame:newFrame]);
|
||||
}
|
||||
for (LOTLayerContainer *child in _childLayers) {
|
||||
[child displayWithFrame:newFrame forceUpdate:forceUpdate];
|
||||
}
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- ------------------------------- --------------------");
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- ------------------------------- --------------------");
|
||||
}
|
||||
|
||||
- (void)setViewportBounds:(CGRect)viewportBounds {
|
||||
[super setViewportBounds:viewportBounds];
|
||||
for (LOTLayerContainer *layer in _childLayers) {
|
||||
layer.viewportBounds = viewportBounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath {
|
||||
if (self.layerName != nil) {
|
||||
[super searchNodesForKeypath:keypath];
|
||||
}
|
||||
if (self.layerName == nil ||
|
||||
[keypath pushKey:self.layerName]) {
|
||||
for (LOTLayerContainer *child in _childLayers) {
|
||||
[child searchNodesForKeypath:keypath];
|
||||
}
|
||||
if (self.layerName != nil) {
|
||||
[keypath popKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setValueDelegate:(id<LOTValueDelegate> _Nonnull)delegate
|
||||
forKeypath:(LOTKeypath * _Nonnull)keypath {
|
||||
if (self.layerName != nil) {
|
||||
[super setValueDelegate:delegate forKeypath:keypath];
|
||||
}
|
||||
if (self.layerName == nil ||
|
||||
[keypath pushKey:self.layerName]) {
|
||||
for (LOTLayerContainer *child in _childLayers) {
|
||||
[child setValueDelegate:delegate forKeypath:keypath];
|
||||
}
|
||||
if (self.layerName != nil) {
|
||||
[keypath popKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath {
|
||||
if (_keypathCache == nil) {
|
||||
_keypathCache = [NSMutableDictionary dictionary];
|
||||
}
|
||||
[self searchNodesForKeypath:keypath];
|
||||
[_keypathCache addEntriesFromDictionary:keypath.searchResults];
|
||||
return keypath.searchResults.allKeys;
|
||||
}
|
||||
|
||||
- (CALayer *)_layerForKeypath:(nonnull LOTKeypath *)keypath {
|
||||
id node = _keypathCache[keypath.absoluteKeypath];
|
||||
if (node == nil) {
|
||||
[self keysForKeyPath:keypath];
|
||||
node = _keypathCache[keypath.absoluteKeypath];
|
||||
}
|
||||
if (node == nil) {
|
||||
NSLog(@"LOTComposition could not find layer for keypath:%@", keypath.absoluteKeypath);
|
||||
return nil;
|
||||
}
|
||||
if ([node isKindOfClass:[CALayer class]]) {
|
||||
return (CALayer *)node;
|
||||
}
|
||||
if (![node isKindOfClass:[LOTRenderNode class]]) {
|
||||
NSLog(@"LOTComposition: Keypath return non-layer node:%@ ", keypath.absoluteKeypath);
|
||||
return nil;
|
||||
}
|
||||
if ([node isKindOfClass:[LOTRenderGroup class]]) {
|
||||
return [(LOTRenderGroup *)node containerLayer];
|
||||
}
|
||||
LOTRenderNode *renderNode = (LOTRenderNode *)node;
|
||||
return renderNode.outputLayer;
|
||||
}
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent{
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (!layer) {
|
||||
return CGPointZero;
|
||||
}
|
||||
return [parent convertPoint:point toLayer:layer];
|
||||
}
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent{
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (!layer) {
|
||||
return CGRectZero;
|
||||
}
|
||||
return [parent convertRect:rect toLayer:layer];
|
||||
}
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent{
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (!layer) {
|
||||
return CGPointZero;
|
||||
}
|
||||
return [parent convertPoint:point fromLayer:layer];
|
||||
}
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath
|
||||
withParentLayer:(CALayer *_Nonnull)parent{
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (!layer) {
|
||||
return CGRectZero;
|
||||
}
|
||||
return [parent convertRect:rect fromLayer:layer];
|
||||
}
|
||||
|
||||
- (void)addSublayer:(nonnull CALayer *)subLayer
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (layer) {
|
||||
[layer addSublayer:subLayer];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)maskSublayer:(nonnull CALayer *)subLayer
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
CALayer *layer = [self _layerForKeypath:keypath];
|
||||
if (layer) {
|
||||
[layer.superlayer addSublayer:subLayer];
|
||||
[layer removeFromSuperlayer];
|
||||
subLayer.mask = layer;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
37
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTLayerContainer.h
generated
Normal file
37
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTLayerContainer.h
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// LOTLayerContainer.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/18/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTPlatformCompat.h"
|
||||
#import "LOTLayer.h"
|
||||
#import "LOTLayerGroup.h"
|
||||
#import "LOTKeypath.h"
|
||||
#import "LOTValueDelegate.h"
|
||||
|
||||
@class LOTValueCallback;
|
||||
|
||||
@interface LOTLayerContainer : CALayer
|
||||
|
||||
- (instancetype _Nonnull)initWithModel:(LOTLayer * _Nullable)layer
|
||||
inLayerGroup:(LOTLayerGroup * _Nullable)layerGroup;
|
||||
|
||||
@property (nonatomic, readonly, strong, nullable) NSString *layerName;
|
||||
@property (nonatomic, nullable) NSNumber *currentFrame;
|
||||
@property (nonatomic, readonly, nonnull) NSNumber *timeStretchFactor;
|
||||
@property (nonatomic, assign) CGRect viewportBounds;
|
||||
@property (nonatomic, readonly, nonnull) CALayer *wrapperLayer;
|
||||
@property (nonatomic, readonly, nonnull) NSDictionary *valueInterpolators;
|
||||
|
||||
- (void)displayWithFrame:(NSNumber * _Nonnull)frame;
|
||||
- (void)displayWithFrame:(NSNumber * _Nonnull)frame forceUpdate:(BOOL)forceUpdate;
|
||||
|
||||
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath;
|
||||
|
||||
- (void)setValueDelegate:(id<LOTValueDelegate> _Nonnull)delegate
|
||||
forKeypath:(LOTKeypath * _Nonnull)keypath;
|
||||
|
||||
@end
|
||||
336
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTLayerContainer.m
generated
Normal file
336
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTLayerContainer.m
generated
Normal file
@@ -0,0 +1,336 @@
|
||||
//
|
||||
// LOTLayerContainer.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/18/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTLayerContainer.h"
|
||||
#import "LOTTransformInterpolator.h"
|
||||
#import "LOTNumberInterpolator.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
#import "LOTRenderGroup.h"
|
||||
#import "LOTHelpers.h"
|
||||
#import "LOTMaskContainer.h"
|
||||
#import "LOTAsset.h"
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
#import "LOTCacheProvider.h"
|
||||
#endif
|
||||
|
||||
@implementation LOTLayerContainer {
|
||||
LOTTransformInterpolator *_transformInterpolator;
|
||||
LOTNumberInterpolator *_opacityInterpolator;
|
||||
NSNumber *_inFrame;
|
||||
NSNumber *_outFrame;
|
||||
CALayer *DEBUG_Center;
|
||||
LOTRenderGroup *_contentsGroup;
|
||||
LOTMaskContainer *_maskLayer;
|
||||
}
|
||||
|
||||
@dynamic currentFrame;
|
||||
|
||||
- (instancetype)initWithModel:(LOTLayer *)layer
|
||||
inLayerGroup:(LOTLayerGroup *)layerGroup {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_wrapperLayer = [CALayer new];
|
||||
[self addSublayer:_wrapperLayer];
|
||||
DEBUG_Center = [CALayer layer];
|
||||
|
||||
DEBUG_Center.bounds = CGRectMake(0, 0, 20, 20);
|
||||
DEBUG_Center.borderColor = [UIColor blueColor].CGColor;
|
||||
DEBUG_Center.borderWidth = 2;
|
||||
DEBUG_Center.masksToBounds = YES;
|
||||
|
||||
if (ENABLE_DEBUG_SHAPES) {
|
||||
[_wrapperLayer addSublayer:DEBUG_Center];
|
||||
}
|
||||
self.actions = @{@"hidden" : [NSNull null], @"opacity" : [NSNull null], @"transform" : [NSNull null]};
|
||||
_wrapperLayer.actions = [self.actions copy];
|
||||
_timeStretchFactor = @1;
|
||||
[self commonInitializeWith:layer inLayerGroup:layerGroup];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)commonInitializeWith:(LOTLayer *)layer
|
||||
inLayerGroup:(LOTLayerGroup *)layerGroup {
|
||||
if (layer == nil) {
|
||||
return;
|
||||
}
|
||||
_layerName = layer.layerName;
|
||||
if (layer.layerType == LOTLayerTypeImage ||
|
||||
layer.layerType == LOTLayerTypeSolid ||
|
||||
layer.layerType == LOTLayerTypePrecomp) {
|
||||
_wrapperLayer.bounds = CGRectMake(0, 0, layer.layerWidth.floatValue, layer.layerHeight.floatValue);
|
||||
_wrapperLayer.anchorPoint = CGPointMake(0, 0);
|
||||
_wrapperLayer.masksToBounds = YES;
|
||||
DEBUG_Center.position = LOT_RectGetCenterPoint(self.bounds);
|
||||
}
|
||||
|
||||
if (layer.layerType == LOTLayerTypeImage) {
|
||||
[self _setImageForAsset:layer.imageAsset];
|
||||
}
|
||||
|
||||
_inFrame = [layer.inFrame copy];
|
||||
_outFrame = [layer.outFrame copy];
|
||||
|
||||
_timeStretchFactor = [layer.timeStretch copy];
|
||||
_transformInterpolator = [LOTTransformInterpolator transformForLayer:layer];
|
||||
|
||||
if (layer.parentID != nil) {
|
||||
NSNumber *parentID = layer.parentID;
|
||||
LOTTransformInterpolator *childInterpolator = _transformInterpolator;
|
||||
while (parentID != nil) {
|
||||
LOTLayer *parentModel = [layerGroup layerModelForID:parentID];
|
||||
LOTTransformInterpolator *interpolator = [LOTTransformInterpolator transformForLayer:parentModel];
|
||||
childInterpolator.inputNode = interpolator;
|
||||
childInterpolator = interpolator;
|
||||
parentID = parentModel.parentID;
|
||||
}
|
||||
}
|
||||
_opacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:layer.opacity.keyframes];
|
||||
if (layer.layerType == LOTLayerTypeShape &&
|
||||
layer.shapes.count) {
|
||||
[self buildContents:layer.shapes];
|
||||
}
|
||||
if (layer.layerType == LOTLayerTypeSolid) {
|
||||
_wrapperLayer.backgroundColor = layer.solidColor.CGColor;
|
||||
}
|
||||
if (layer.masks.count) {
|
||||
_maskLayer = [[LOTMaskContainer alloc] initWithMasks:layer.masks];
|
||||
_wrapperLayer.mask = _maskLayer;
|
||||
}
|
||||
|
||||
NSMutableDictionary *interpolators = [NSMutableDictionary dictionary];
|
||||
interpolators[@"Opacity"] = _opacityInterpolator;
|
||||
interpolators[@"Anchor Point"] = _transformInterpolator.anchorInterpolator;
|
||||
interpolators[@"Scale"] = _transformInterpolator.scaleInterpolator;
|
||||
interpolators[@"Rotation"] = _transformInterpolator.rotationInterpolator;
|
||||
if (_transformInterpolator.positionXInterpolator &&
|
||||
_transformInterpolator.positionYInterpolator) {
|
||||
interpolators[@"X Position"] = _transformInterpolator.positionXInterpolator;
|
||||
interpolators[@"Y Position"] = _transformInterpolator.positionYInterpolator;
|
||||
} else if (_transformInterpolator.positionInterpolator) {
|
||||
interpolators[@"Position"] = _transformInterpolator.positionInterpolator;
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
interpolators[@"Transform.Opacity"] = _opacityInterpolator;
|
||||
interpolators[@"Transform.Anchor Point"] = _transformInterpolator.anchorInterpolator;
|
||||
interpolators[@"Transform.Scale"] = _transformInterpolator.scaleInterpolator;
|
||||
interpolators[@"Transform.Rotation"] = _transformInterpolator.rotationInterpolator;
|
||||
if (_transformInterpolator.positionXInterpolator &&
|
||||
_transformInterpolator.positionYInterpolator) {
|
||||
interpolators[@"Transform.X Position"] = _transformInterpolator.positionXInterpolator;
|
||||
interpolators[@"Transform.Y Position"] = _transformInterpolator.positionYInterpolator;
|
||||
} else if (_transformInterpolator.positionInterpolator) {
|
||||
interpolators[@"Transform.Position"] = _transformInterpolator.positionInterpolator;
|
||||
}
|
||||
_valueInterpolators = interpolators;
|
||||
}
|
||||
|
||||
- (void)buildContents:(NSArray *)contents {
|
||||
_contentsGroup = [[LOTRenderGroup alloc] initWithInputNode:nil contents:contents keyname:_layerName];
|
||||
[_wrapperLayer addSublayer:_contentsGroup.containerLayer];
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
|
||||
- (void)_setImageForAsset:(LOTAsset *)asset {
|
||||
if (asset.imageName) {
|
||||
UIImage *image;
|
||||
if ([asset.imageName hasPrefix:@"data:"]) {
|
||||
// Contents look like a data: URL. Ignore asset.imageDirectory and simply load the image directly.
|
||||
NSURL *imageUrl = [NSURL URLWithString:asset.imageName];
|
||||
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
|
||||
image = [UIImage imageWithData:imageData];
|
||||
} else if (asset.rootDirectory.length > 0) {
|
||||
NSString *rootDirectory = asset.rootDirectory;
|
||||
if (asset.imageDirectory.length > 0) {
|
||||
rootDirectory = [rootDirectory stringByAppendingPathComponent:asset.imageDirectory];
|
||||
}
|
||||
NSString *imagePath = [rootDirectory stringByAppendingPathComponent:asset.imageName];
|
||||
|
||||
id<LOTImageCache> imageCache = [LOTCacheProvider imageCache];
|
||||
if (imageCache) {
|
||||
image = [imageCache imageForKey:imagePath];
|
||||
if (!image) {
|
||||
image = [UIImage imageWithContentsOfFile:imagePath];
|
||||
[imageCache setImage:image forKey:imagePath];
|
||||
}
|
||||
} else {
|
||||
image = [UIImage imageWithContentsOfFile:imagePath];
|
||||
}
|
||||
} else {
|
||||
NSString *imagePath = [asset.assetBundle pathForResource:asset.imageName ofType:nil];
|
||||
image = [UIImage imageWithContentsOfFile:imagePath];
|
||||
}
|
||||
|
||||
//try loading from asset catalogue instead if all else fails
|
||||
if (!image) {
|
||||
image = [UIImage imageNamed:asset.imageName inBundle: asset.assetBundle compatibleWithTraitCollection:nil];
|
||||
}
|
||||
|
||||
if (image) {
|
||||
_wrapperLayer.contents = (__bridge id _Nullable)(image.CGImage);
|
||||
} else {
|
||||
NSLog(@"%s: Warn: image not found: %@", __PRETTY_FUNCTION__, asset.imageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
- (void)_setImageForAsset:(LOTAsset *)asset {
|
||||
if (asset.imageName) {
|
||||
NSImage *image;
|
||||
if ([asset.imageName hasPrefix:@"data:"]) {
|
||||
// Contents look like a data: URL. Ignore asset.imageDirectory and simply load the image directly.
|
||||
NSURL *imageUrl = [NSURL URLWithString:asset.imageName];
|
||||
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
|
||||
image = [[NSImage alloc] initWithData:imageData];
|
||||
} else {
|
||||
image = [NSImage imageNamed:[asset.imageName stringByDeletingPathExtension]];
|
||||
}
|
||||
if (image == nil) {
|
||||
if (asset.rootDirectory.length > 0 && asset.imageDirectory.length > 0) {
|
||||
NSString *imagePath = [[asset.rootDirectory stringByAppendingPathComponent:asset.imageDirectory] stringByAppendingPathComponent:asset.imageName];
|
||||
image = [[NSImage alloc] initWithContentsOfFile:imagePath];
|
||||
}
|
||||
}
|
||||
if (image) {
|
||||
NSWindow *window = [NSApp mainWindow];
|
||||
CGFloat desiredScaleFactor = [window backingScaleFactor];
|
||||
CGFloat actualScaleFactor = [image recommendedLayerContentsScale:desiredScaleFactor];
|
||||
id layerContents = [image layerContentsForContentsScale:actualScaleFactor];
|
||||
_wrapperLayer.contents = layerContents;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK - Animation
|
||||
|
||||
+ (BOOL)needsDisplayForKey:(NSString *)key {
|
||||
if ([key isEqualToString:@"currentFrame"]) {
|
||||
return YES;
|
||||
}
|
||||
return [super needsDisplayForKey:key];
|
||||
}
|
||||
|
||||
- (id<CAAction>)actionForKey:(NSString *)event {
|
||||
if ([event isEqualToString:@"currentFrame"]) {
|
||||
CABasicAnimation *theAnimation = [CABasicAnimation
|
||||
animationWithKeyPath:event];
|
||||
theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
||||
theAnimation.fromValue = [[self presentationLayer] valueForKey:event];
|
||||
return theAnimation;
|
||||
}
|
||||
return [super actionForKey:event];
|
||||
}
|
||||
|
||||
- (id)initWithLayer:(id)layer {
|
||||
if (self = [super initWithLayer:layer]) {
|
||||
if ([layer isKindOfClass:[LOTLayerContainer class]]) {
|
||||
LOTLayerContainer *other = (LOTLayerContainer *)layer;
|
||||
self.currentFrame = [other.currentFrame copy];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)display {
|
||||
@synchronized(self) {
|
||||
LOTLayerContainer *presentation = self;
|
||||
if (self.animationKeys.count &&
|
||||
self.presentationLayer) {
|
||||
presentation = (LOTLayerContainer *)self.presentationLayer;
|
||||
}
|
||||
[self displayWithFrame:presentation.currentFrame];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)displayWithFrame:(NSNumber *)frame {
|
||||
[self displayWithFrame:frame forceUpdate:NO];
|
||||
}
|
||||
|
||||
- (void)displayWithFrame:(NSNumber *)frame forceUpdate:(BOOL)forceUpdate {
|
||||
NSNumber *newFrame = @(frame.floatValue / self.timeStretchFactor.floatValue);
|
||||
if (ENABLE_DEBUG_LOGGING) NSLog(@"View %@ Displaying Frame %@, with local time %@", self, frame, newFrame);
|
||||
BOOL hidden = NO;
|
||||
if (_inFrame && _outFrame) {
|
||||
hidden = (frame.floatValue < _inFrame.floatValue ||
|
||||
frame.floatValue > _outFrame.floatValue);
|
||||
}
|
||||
self.hidden = hidden;
|
||||
if (hidden) {
|
||||
return;
|
||||
}
|
||||
if (_opacityInterpolator && [_opacityInterpolator hasUpdateForFrame:newFrame]) {
|
||||
self.opacity = [_opacityInterpolator floatValueForFrame:newFrame];
|
||||
}
|
||||
if (_transformInterpolator && [_transformInterpolator hasUpdateForFrame:newFrame]) {
|
||||
_wrapperLayer.transform = [_transformInterpolator transformForFrame:newFrame];
|
||||
}
|
||||
[_contentsGroup updateWithFrame:newFrame withModifierBlock:nil forceLocalUpdate:forceUpdate];
|
||||
_maskLayer.currentFrame = newFrame;
|
||||
}
|
||||
|
||||
- (void)setViewportBounds:(CGRect)viewportBounds {
|
||||
_viewportBounds = viewportBounds;
|
||||
if (_maskLayer) {
|
||||
CGPoint center = LOT_RectGetCenterPoint(viewportBounds);
|
||||
viewportBounds.origin = CGPointMake(-center.x, -center.y);
|
||||
_maskLayer.bounds = viewportBounds;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath {
|
||||
if (_contentsGroup == nil && [keypath pushKey:self.layerName]) {
|
||||
// Matches self.
|
||||
if ([keypath pushKey:@"Transform"]) {
|
||||
// Is a transform node, check interpolators
|
||||
LOTValueInterpolator *interpolator = _valueInterpolators[keypath.currentKey];
|
||||
if (interpolator) {
|
||||
// We have a match!
|
||||
[keypath pushKey:keypath.currentKey];
|
||||
[keypath addSearchResultForCurrentPath:_wrapperLayer];
|
||||
[keypath popKey];
|
||||
}
|
||||
if (keypath.endOfKeypath) {
|
||||
[keypath addSearchResultForCurrentPath:_wrapperLayer];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
if (keypath.endOfKeypath) {
|
||||
[keypath addSearchResultForCurrentPath:_wrapperLayer];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
[_contentsGroup searchNodesForKeypath:keypath];
|
||||
}
|
||||
|
||||
- (void)setValueDelegate:(id<LOTValueDelegate> _Nonnull)delegate
|
||||
forKeypath:(LOTKeypath * _Nonnull)keypath {
|
||||
if ([keypath pushKey:self.layerName]) {
|
||||
// Matches self.
|
||||
if ([keypath pushKey:@"Transform"]) {
|
||||
// Is a transform node, check interpolators
|
||||
LOTValueInterpolator *interpolator = _valueInterpolators[keypath.currentKey];
|
||||
if (interpolator) {
|
||||
// We have a match!
|
||||
[interpolator setValueDelegate:delegate];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
[keypath popKey];
|
||||
}
|
||||
[_contentsGroup setValueDelegate:delegate forKeypath:keypath];
|
||||
}
|
||||
|
||||
@end
|
||||
18
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTMaskContainer.h
generated
Normal file
18
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTMaskContainer.h
generated
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// LOTMaskContainer.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/19/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import "LOTMask.h"
|
||||
|
||||
@interface LOTMaskContainer : CALayer
|
||||
|
||||
- (instancetype _Nonnull)initWithMasks:(NSArray<LOTMask *> * _Nonnull)masks;
|
||||
|
||||
@property (nonatomic, strong, nullable) NSNumber *currentFrame;
|
||||
|
||||
@end
|
||||
107
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTMaskContainer.m
generated
Normal file
107
Pods/lottie-ios/lottie-ios/Classes/AnimatableLayers/LOTMaskContainer.m
generated
Normal file
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// LOTMaskContainer.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/19/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTMaskContainer.h"
|
||||
#import "LOTPathInterpolator.h"
|
||||
#import "LOTNumberInterpolator.h"
|
||||
|
||||
@interface LOTMaskNodeLayer : CAShapeLayer
|
||||
|
||||
@property (nonatomic, readonly) LOTMask *maskNode;
|
||||
|
||||
- (instancetype)initWithMask:(LOTMask *)maskNode;
|
||||
- (BOOL)hasUpdateForFrame:(NSNumber *)frame;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTMaskNodeLayer {
|
||||
LOTPathInterpolator *_pathInterpolator;
|
||||
LOTNumberInterpolator *_opacityInterpolator;
|
||||
LOTNumberInterpolator *_expansionInterpolator;
|
||||
}
|
||||
|
||||
- (instancetype)initWithMask:(LOTMask *)maskNode {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_pathInterpolator = [[LOTPathInterpolator alloc] initWithKeyframes:maskNode.maskPath.keyframes];
|
||||
_opacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:maskNode.opacity.keyframes];
|
||||
_expansionInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:maskNode.expansion.keyframes];
|
||||
_maskNode = maskNode;
|
||||
self.fillColor = [UIColor blueColor].CGColor;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)updateForFrame:(NSNumber *)frame withViewBounds:(CGRect)viewBounds {
|
||||
if ([self hasUpdateForFrame:frame]) {
|
||||
LOTBezierPath *path = [_pathInterpolator pathForFrame:frame cacheLengths:NO];
|
||||
|
||||
if (self.maskNode.maskMode == LOTMaskModeSubtract) {
|
||||
CGMutablePathRef pathRef = CGPathCreateMutable();
|
||||
CGPathAddRect(pathRef, NULL, viewBounds);
|
||||
CGPathAddPath(pathRef, NULL, path.CGPath);
|
||||
self.path = pathRef;
|
||||
self.fillRule = @"even-odd";
|
||||
CGPathRelease(pathRef);
|
||||
} else {
|
||||
self.path = path.CGPath;
|
||||
}
|
||||
|
||||
self.opacity = [_opacityInterpolator floatValueForFrame:frame];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)hasUpdateForFrame:(NSNumber *)frame {
|
||||
return ([_pathInterpolator hasUpdateForFrame:frame] ||
|
||||
[_opacityInterpolator hasUpdateForFrame:frame]);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTMaskContainer {
|
||||
NSArray<LOTMaskNodeLayer *> *_masks;
|
||||
}
|
||||
|
||||
- (instancetype)initWithMasks:(NSArray<LOTMask *> *)masks {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
NSMutableArray *maskNodes = [NSMutableArray array];
|
||||
CALayer *containerLayer = [CALayer layer];
|
||||
|
||||
for (LOTMask *mask in masks) {
|
||||
LOTMaskNodeLayer *node = [[LOTMaskNodeLayer alloc] initWithMask:mask];
|
||||
[maskNodes addObject:node];
|
||||
if (mask.maskMode == LOTMaskModeAdd ||
|
||||
mask == masks.firstObject) {
|
||||
[containerLayer addSublayer:node];
|
||||
} else {
|
||||
containerLayer.mask = node;
|
||||
CALayer *newContainer = [CALayer layer];
|
||||
[newContainer addSublayer:containerLayer];
|
||||
containerLayer = newContainer;
|
||||
}
|
||||
}
|
||||
[self addSublayer:containerLayer];
|
||||
_masks = maskNodes;
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setCurrentFrame:(NSNumber *)currentFrame {
|
||||
if (_currentFrame == currentFrame) {
|
||||
return;
|
||||
}
|
||||
_currentFrame = currentFrame;
|
||||
|
||||
for (LOTMaskNodeLayer *nodeLayer in _masks) {
|
||||
[nodeLayer updateForFrame:currentFrame withViewBounds:self.bounds];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
27
Pods/lottie-ios/lottie-ios/Classes/AnimatableProperties/LOTBezierData.h
generated
Normal file
27
Pods/lottie-ios/lottie-ios/Classes/AnimatableProperties/LOTBezierData.h
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// LOTBezierData.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/10/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LOTBezierData : NSObject
|
||||
|
||||
- (instancetype)initWithData:(NSDictionary *)bezierData;
|
||||
|
||||
@property (nonatomic, readonly) NSInteger count;
|
||||
@property (nonatomic, readonly) BOOL closed;
|
||||
|
||||
- (CGPoint)vertexAtIndex:(NSInteger)index;
|
||||
- (CGPoint)inTangentAtIndex:(NSInteger)index;
|
||||
- (CGPoint)outTangentAtIndex:(NSInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
100
Pods/lottie-ios/lottie-ios/Classes/AnimatableProperties/LOTBezierData.m
generated
Normal file
100
Pods/lottie-ios/lottie-ios/Classes/AnimatableProperties/LOTBezierData.m
generated
Normal file
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// LOTBezierData.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/10/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTBezierData.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTBezierData {
|
||||
CGPoint *_vertices;
|
||||
CGPoint *_inTangents;
|
||||
CGPoint *_outTangents;
|
||||
}
|
||||
|
||||
- (instancetype)initWithData:(NSDictionary *)bezierData
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self initializeData:bezierData];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
free(_vertices);
|
||||
free(_inTangents);
|
||||
free(_outTangents);
|
||||
}
|
||||
|
||||
- (CGPoint)vertexAtIndex:(NSInteger)index {
|
||||
NSAssert((index < _count &&
|
||||
index >= 0),
|
||||
@"Lottie: Index out of bounds");
|
||||
return _vertices[index];
|
||||
}
|
||||
|
||||
- (CGPoint)inTangentAtIndex:(NSInteger)index {
|
||||
NSAssert((index < _count &&
|
||||
index >= 0),
|
||||
@"Lottie: Index out of bounds");
|
||||
return _inTangents[index];
|
||||
}
|
||||
|
||||
- (CGPoint)outTangentAtIndex:(NSInteger)index {
|
||||
NSAssert((index < _count &&
|
||||
index >= 0),
|
||||
@"Lottie: Index out of bounds");
|
||||
return _outTangents[index];
|
||||
}
|
||||
|
||||
- (void)initializeData:(NSDictionary *)bezierData {
|
||||
|
||||
NSArray *pointsArray = bezierData[@"v"];
|
||||
NSArray *inTangents = bezierData[@"i"];
|
||||
NSArray *outTangents = bezierData[@"o"];
|
||||
|
||||
if (pointsArray.count == 0) {
|
||||
NSLog(@"%s: Warning: shape has no vertices", __PRETTY_FUNCTION__);
|
||||
return ;
|
||||
}
|
||||
|
||||
NSAssert((pointsArray.count == inTangents.count &&
|
||||
pointsArray.count == outTangents.count),
|
||||
@"Lottie: Incorrect number of points and tangents");
|
||||
_count = pointsArray.count;
|
||||
_vertices = (CGPoint *)malloc(sizeof(CGPoint) * pointsArray.count);
|
||||
_inTangents = (CGPoint *)malloc(sizeof(CGPoint) * pointsArray.count);
|
||||
_outTangents = (CGPoint *)malloc(sizeof(CGPoint) * pointsArray.count);
|
||||
if (bezierData[@"c"]) {
|
||||
_closed = [bezierData[@"c"] boolValue];
|
||||
}
|
||||
for (int i = 0; i < pointsArray.count; i ++) {
|
||||
CGPoint vertex = [self _vertexAtIndex:i inArray:pointsArray];
|
||||
CGPoint outTan = LOT_PointAddedToPoint(vertex, [self _vertexAtIndex:i inArray:outTangents]);
|
||||
CGPoint inTan = LOT_PointAddedToPoint(vertex, [self _vertexAtIndex:i inArray:inTangents]);
|
||||
// BW BUG Straight Lines - Test Later
|
||||
// Bake fix for lines here
|
||||
_vertices[i] = vertex;
|
||||
_inTangents[i] = inTan;
|
||||
_outTangents[i] = outTan;
|
||||
}
|
||||
}
|
||||
|
||||
- (CGPoint)_vertexAtIndex:(NSInteger)idx inArray:(NSArray *)points {
|
||||
NSAssert((idx < points.count),
|
||||
@"Lottie: Vertex Point out of bounds");
|
||||
|
||||
NSArray *pointArray = points[idx];
|
||||
|
||||
NSAssert((pointArray.count >= 2 &&
|
||||
[pointArray.firstObject isKindOfClass:[NSNumber class]]),
|
||||
@"Lottie: Point Data Malformed");
|
||||
|
||||
return CGPointMake([(NSNumber *)pointArray[0] floatValue], [(NSNumber *)pointArray[1] floatValue]);
|
||||
}
|
||||
|
||||
@end
|
||||
49
Pods/lottie-ios/lottie-ios/Classes/AnimatableProperties/LOTKeyframe.h
generated
Normal file
49
Pods/lottie-ios/lottie-ios/Classes/AnimatableProperties/LOTKeyframe.h
generated
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// LOTKeyframe.h
|
||||
// Pods
|
||||
//
|
||||
// Created by brandon_withrow on 7/10/17.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import "LOTPlatformCompat.h"
|
||||
#import "LOTBezierData.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LOTKeyframe : NSObject
|
||||
|
||||
- (instancetype)initWithKeyframe:(NSDictionary *)keyframe;
|
||||
- (instancetype)initWithValue:(id)value;
|
||||
- (void)remapValueWithBlock:(CGFloat (^)(CGFloat inValue))remapBlock;
|
||||
- (LOTKeyframe *)copyWithData:(id)data;
|
||||
|
||||
@property (nonatomic, readonly) NSNumber *keyframeTime;
|
||||
@property (nonatomic, readonly) BOOL isHold;
|
||||
@property (nonatomic, readonly) CGPoint inTangent;
|
||||
@property (nonatomic, readonly) CGPoint outTangent;
|
||||
@property (nonatomic, readonly) CGPoint spatialInTangent;
|
||||
@property (nonatomic, readonly) CGPoint spatialOutTangent;
|
||||
|
||||
@property (nonatomic, readonly) CGFloat floatValue;
|
||||
@property (nonatomic, readonly) CGPoint pointValue;
|
||||
@property (nonatomic, readonly) CGSize sizeValue;
|
||||
@property (nonatomic, readonly) UIColor *colorValue;
|
||||
@property (nonatomic, readonly, nullable) LOTBezierData *pathData;
|
||||
@property (nonatomic, readonly) NSArray *arrayValue;
|
||||
|
||||
@end
|
||||
|
||||
@interface LOTKeyframeGroup : NSObject
|
||||
|
||||
- (instancetype)initWithData:(id)data;
|
||||
|
||||
- (void)remapKeyframesWithBlock:(CGFloat (^)(CGFloat inValue))remapBlock;
|
||||
|
||||
@property (nonatomic, readonly) NSArray<LOTKeyframe *> *keyframes;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
242
Pods/lottie-ios/lottie-ios/Classes/AnimatableProperties/LOTKeyframe.m
generated
Normal file
242
Pods/lottie-ios/lottie-ios/Classes/AnimatableProperties/LOTKeyframe.m
generated
Normal file
@@ -0,0 +1,242 @@
|
||||
//
|
||||
// LOTKeyframe.m
|
||||
// Pods
|
||||
//
|
||||
// Created by brandon_withrow on 7/10/17.
|
||||
//
|
||||
//
|
||||
|
||||
#import "LOTKeyframe.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTKeyframe
|
||||
|
||||
- (instancetype)initWithKeyframe:(NSDictionary *)keyframe {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_keyframeTime = keyframe[@"t"];
|
||||
_inTangent = CGPointZero;
|
||||
_outTangent = CGPointZero;
|
||||
_spatialInTangent = CGPointZero;
|
||||
_spatialOutTangent = CGPointZero;
|
||||
NSDictionary *timingOutTangent = keyframe[@"o"];
|
||||
NSDictionary *timingInTangent = keyframe[@"i"];
|
||||
if (timingInTangent) {
|
||||
_inTangent = [self _pointFromValueDict:timingInTangent];
|
||||
}
|
||||
if (timingOutTangent) {
|
||||
_outTangent = [self _pointFromValueDict:timingOutTangent];
|
||||
}
|
||||
if ([keyframe[@"h"] boolValue]) {
|
||||
_isHold = YES;
|
||||
}
|
||||
if (keyframe[@"to"]) {
|
||||
NSArray *to = keyframe[@"to"];
|
||||
_spatialOutTangent = [self _pointFromValueArray:to];
|
||||
}
|
||||
if (keyframe[@"ti"]) {
|
||||
NSArray *ti = keyframe[@"ti"];
|
||||
_spatialInTangent = [self _pointFromValueArray:ti];
|
||||
}
|
||||
id data = keyframe[@"s"];
|
||||
if (data) {
|
||||
[self setupOutputWithData:data];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithValue:(id)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_keyframeTime = @0;
|
||||
_isHold = YES;
|
||||
[self setupOutputWithData:value];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithLOTKeyframe:(LOTKeyframe *)keyframe {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_keyframeTime = [keyframe.keyframeTime copy];
|
||||
_inTangent = keyframe.inTangent;
|
||||
_outTangent = keyframe.outTangent;
|
||||
_spatialInTangent = keyframe.spatialInTangent;
|
||||
_spatialOutTangent = keyframe.spatialOutTangent;
|
||||
_isHold = keyframe.isHold;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (LOTKeyframe *)copyWithData:(id)data {
|
||||
LOTKeyframe *newFrame = [[LOTKeyframe alloc] initWithLOTKeyframe:self];
|
||||
[newFrame setData:data];
|
||||
return newFrame;
|
||||
}
|
||||
|
||||
- (void)setData:(id)data {
|
||||
[self setupOutputWithData:data];
|
||||
}
|
||||
|
||||
- (void)remapValueWithBlock:(CGFloat (^)(CGFloat inValue))remapBlock {
|
||||
_floatValue = remapBlock(_floatValue);
|
||||
_pointValue = CGPointMake(remapBlock(_pointValue.x), remapBlock(_pointValue.y));
|
||||
_sizeValue = CGSizeMake(remapBlock(_sizeValue.width), remapBlock(_sizeValue.height));
|
||||
}
|
||||
|
||||
- (void)setupOutputWithData:(id)data {
|
||||
if ([data isKindOfClass:[NSNumber class]]) {
|
||||
_floatValue = [(NSNumber *)data floatValue];
|
||||
}
|
||||
if ([data isKindOfClass:[NSArray class]] &&
|
||||
[[(NSArray *)data firstObject] isKindOfClass:[NSNumber class]]) {
|
||||
NSArray *numberArray = (NSArray *)data;
|
||||
if (numberArray.count > 0) {
|
||||
_floatValue = [(NSNumber *)numberArray[0] floatValue];
|
||||
}
|
||||
if (numberArray.count > 1) {
|
||||
_pointValue = CGPointMake(_floatValue = [(NSNumber *)numberArray[0] floatValue],
|
||||
_floatValue = [(NSNumber *)numberArray[1] floatValue]);
|
||||
_sizeValue = CGSizeMake(_pointValue.x, _pointValue.y);
|
||||
}
|
||||
if (numberArray.count > 3) {
|
||||
_colorValue = [self _colorValueFromArray:numberArray];
|
||||
}
|
||||
_arrayValue = numberArray;
|
||||
} else if ([data isKindOfClass:[NSArray class]] &&
|
||||
[[(NSArray *)data firstObject] isKindOfClass:[NSDictionary class]]) {
|
||||
_pathData = [[LOTBezierData alloc] initWithData:[(NSArray *)data firstObject]];
|
||||
} else if ([data isKindOfClass:[NSDictionary class]]) {
|
||||
_pathData = [[LOTBezierData alloc] initWithData:data];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGPoint)_pointFromValueArray:(NSArray *)values {
|
||||
CGPoint returnPoint = CGPointZero;
|
||||
if (values.count > 1) {
|
||||
returnPoint.x = [(NSNumber *)values[0] floatValue];
|
||||
returnPoint.y = [(NSNumber *)values[1] floatValue];
|
||||
}
|
||||
return returnPoint;
|
||||
}
|
||||
|
||||
- (CGPoint)_pointFromValueDict:(NSDictionary *)values {
|
||||
NSNumber *xValue = @0, *yValue = @0;
|
||||
if ([values[@"x"] isKindOfClass:[NSNumber class]]) {
|
||||
xValue = values[@"x"];
|
||||
} else if ([values[@"x"] isKindOfClass:[NSArray class]]) {
|
||||
xValue = values[@"x"][0];
|
||||
}
|
||||
|
||||
if ([values[@"y"] isKindOfClass:[NSNumber class]]) {
|
||||
yValue = values[@"y"];
|
||||
} else if ([values[@"y"] isKindOfClass:[NSArray class]]) {
|
||||
yValue = values[@"y"][0];
|
||||
}
|
||||
|
||||
return CGPointMake([xValue floatValue], [yValue floatValue]);
|
||||
}
|
||||
|
||||
- (UIColor *)_colorValueFromArray:(NSArray<NSNumber *> *)colorArray {
|
||||
if (colorArray.count == 4) {
|
||||
BOOL shouldUse255 = NO;
|
||||
for (NSNumber *number in colorArray) {
|
||||
if (number.floatValue > 1) {
|
||||
shouldUse255 = YES;
|
||||
}
|
||||
}
|
||||
return [UIColor colorWithRed:colorArray[0].floatValue / (shouldUse255 ? 255.f : 1.f)
|
||||
green:colorArray[1].floatValue / (shouldUse255 ? 255.f : 1.f)
|
||||
blue:colorArray[2].floatValue / (shouldUse255 ? 255.f : 1.f)
|
||||
alpha:colorArray[3].floatValue / (shouldUse255 ? 255.f : 1.f)];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTKeyframeGroup
|
||||
|
||||
- (instancetype)initWithData:(id)data {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if ([data isKindOfClass:[NSDictionary class]] &&
|
||||
[(NSDictionary *)data valueForKey:@"k"]) {
|
||||
[self buildKeyframesFromData:[(NSDictionary *)data valueForKey:@"k"]];
|
||||
} else {
|
||||
[self buildKeyframesFromData:data];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)buildKeyframesFromData:(id)data {
|
||||
if ([data isKindOfClass:[NSArray class]] &&
|
||||
[[(NSArray *)data firstObject] isKindOfClass:[NSDictionary class]] &&
|
||||
[(NSArray *)data firstObject][@"t"]) {
|
||||
// Array of Keyframes
|
||||
NSArray *keyframes = (NSArray *)data;
|
||||
NSMutableArray *keys = [NSMutableArray array];
|
||||
NSDictionary *previousFrame = nil;
|
||||
for (NSDictionary *keyframe in keyframes) {
|
||||
NSMutableDictionary *currentFrame = [NSMutableDictionary dictionary];
|
||||
if (keyframe[@"t"]) {
|
||||
// Set time
|
||||
currentFrame[@"t"] = keyframe[@"t"];
|
||||
}
|
||||
if (keyframe[@"s"]) {
|
||||
// Set Value for Keyframe
|
||||
currentFrame[@"s"] = keyframe[@"s"];
|
||||
} else if (previousFrame[@"e"]) {
|
||||
// Set Value for Keyframe
|
||||
currentFrame[@"s"] = previousFrame[@"e"];
|
||||
}
|
||||
if (keyframe[@"o"]) {
|
||||
// Set out tangent
|
||||
currentFrame[@"o"] = keyframe[@"o"];
|
||||
}
|
||||
if (previousFrame[@"i"]) {
|
||||
currentFrame[@"i"] = previousFrame[@"i"];
|
||||
}
|
||||
if (keyframe[@"to"]) {
|
||||
// Set out tangent
|
||||
currentFrame[@"to"] = keyframe[@"to"];
|
||||
}
|
||||
if (previousFrame[@"ti"]) {
|
||||
currentFrame[@"ti"] = previousFrame[@"ti"];
|
||||
}
|
||||
if (keyframe[@"h"]) {
|
||||
currentFrame[@"h"] = keyframe[@"h"];
|
||||
}
|
||||
LOTKeyframe *key = [[LOTKeyframe alloc] initWithKeyframe:currentFrame];
|
||||
[keys addObject:key];
|
||||
previousFrame = keyframe;
|
||||
}
|
||||
_keyframes = keys;
|
||||
|
||||
} else {
|
||||
LOTKeyframe *key = [[LOTKeyframe alloc] initWithValue:data];
|
||||
_keyframes = @[key];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)remapKeyframesWithBlock:(CGFloat (^)(CGFloat))remapBlock {
|
||||
for (LOTKeyframe *keyframe in _keyframes) {
|
||||
[keyframe remapValueWithBlock:remapBlock];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
/*
|
||||
+KeyFrameObject has
|
||||
+ i (PointObject) // Timing curve in tangent
|
||||
+ o (PointObject) // Timing curve out tangent
|
||||
+ n (array of string) // String representation of timing curve
|
||||
+ t (integer) // Keyframe time for start of keyframe
|
||||
+ s (float or array of float or PathObject) // The key information
|
||||
+ e (float or array of float or PathObject) // The end key information
|
||||
+ to (array of float) // For spacial bezier path interpolation, the in tangent
|
||||
+ ti (array of float) // For spacial bezier path interpolation, the out tangent
|
||||
+ h (integer) // If the keyframe is a Hold keyframe or not
|
||||
*/
|
||||
98
Pods/lottie-ios/lottie-ios/Classes/Extensions/CGGeometry+LOTAdditions.h
generated
Normal file
98
Pods/lottie-ios/lottie-ios/Classes/Extensions/CGGeometry+LOTAdditions.h
generated
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
#import "LOTPlatformCompat.h"
|
||||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
//
|
||||
// Core Graphics Geometry Additions
|
||||
//
|
||||
|
||||
extern const CGSize CGSizeMax;
|
||||
|
||||
CGRect LOT_RectIntegral(CGRect rect);
|
||||
|
||||
// Centering
|
||||
|
||||
// Returns a rectangle of the given size, centered at a point
|
||||
CGRect LOT_RectCenteredAtPoint(CGPoint center, CGSize size, BOOL integral);
|
||||
|
||||
// Returns the center point of a CGRect
|
||||
CGPoint LOT_RectGetCenterPoint(CGRect rect);
|
||||
|
||||
// Insetting
|
||||
|
||||
// Inset the rectangle on a single edge
|
||||
CGRect LOT_RectInsetLeft(CGRect rect, CGFloat inset);
|
||||
CGRect LOT_RectInsetRight(CGRect rect, CGFloat inset);
|
||||
CGRect LOT_RectInsetTop(CGRect rect, CGFloat inset);
|
||||
CGRect LOT_RectInsetBottom(CGRect rect, CGFloat inset);
|
||||
|
||||
// Inset the rectangle on two edges
|
||||
CGRect LOT_RectInsetHorizontal(CGRect rect, CGFloat leftInset, CGFloat rightInset);
|
||||
CGRect LOT_RectInsetVertical(CGRect rect, CGFloat topInset, CGFloat bottomInset);
|
||||
|
||||
// Inset the rectangle on all edges
|
||||
CGRect LOT_RectInsetAll(CGRect rect, CGFloat leftInset, CGFloat rightInset, CGFloat topInset, CGFloat bottomInset);
|
||||
|
||||
// Framing
|
||||
|
||||
// Returns a rectangle of size framed in the center of the given rectangle
|
||||
CGRect LOT_RectFramedCenteredInRect(CGRect rect, CGSize size, BOOL integral);
|
||||
|
||||
// Returns a rectangle of size framed in the given rectangle and inset
|
||||
CGRect LOT_RectFramedLeftInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral);
|
||||
CGRect LOT_RectFramedRightInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral);
|
||||
CGRect LOT_RectFramedTopInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral);
|
||||
CGRect LOT_RectFramedBottomInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral);
|
||||
|
||||
CGRect LOT_RectFramedTopLeftInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral);
|
||||
CGRect LOT_RectFramedTopRightInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral);
|
||||
CGRect LOT_RectFramedBottomLeftInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral);
|
||||
CGRect LOT_RectFramedBottomRightInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral);
|
||||
|
||||
// Divides a rect into sections and returns the section at specified index
|
||||
|
||||
CGRect LOT_RectDividedSection(CGRect rect, NSInteger sections, NSInteger index, CGRectEdge fromEdge);
|
||||
|
||||
// Returns a rectangle of size attached to the given rectangle
|
||||
CGRect LOT_RectAttachedLeftToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral);
|
||||
CGRect LOT_RectAttachedRightToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral);
|
||||
CGRect LOT_RectAttachedTopToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral);
|
||||
CGRect LOT_RectAttachedBottomToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral);
|
||||
|
||||
CGRect LOT_RectAttachedBottomLeftToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral);
|
||||
CGRect LOT_RectAttachedBottomRightToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral);
|
||||
CGRect LOT_RectAttachedTopRightToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral);
|
||||
CGRect LOT_RectAttachedTopLeftToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral);
|
||||
|
||||
BOOL LOT_CGPointIsZero(CGPoint point);
|
||||
|
||||
// Combining
|
||||
// Adds all values of the 2nd rect to the first rect
|
||||
CGRect LOT_RectAddRect(CGRect rect, CGRect other);
|
||||
CGRect LOT_RectAddPoint(CGRect rect, CGPoint point);
|
||||
CGRect LOT_RectAddSize(CGRect rect, CGSize size);
|
||||
CGRect LOT_RectBounded(CGRect rect);
|
||||
|
||||
CGPoint LOT_PointAddedToPoint(CGPoint point1, CGPoint point2);
|
||||
|
||||
CGRect LOT_RectSetHeight(CGRect rect, CGFloat height);
|
||||
|
||||
CGFloat LOT_PointDistanceFromPoint(CGPoint point1, CGPoint point2);
|
||||
CGFloat LOT_DegreesToRadians(CGFloat degrees);
|
||||
|
||||
CGFloat LOT_RemapValue(CGFloat value, CGFloat low1, CGFloat high1, CGFloat low2, CGFloat high2 );
|
||||
CGPoint LOT_PointByLerpingPoints(CGPoint point1, CGPoint point2, CGFloat value);
|
||||
|
||||
CGPoint LOT_PointInLine(CGPoint A, CGPoint B, CGFloat T);
|
||||
CGPoint LOT_PointInCubicCurve(CGPoint start, CGPoint cp1, CGPoint cp2, CGPoint end, CGFloat T);
|
||||
|
||||
CGFloat LOT_CubicBezierInterpolate(CGPoint P0, CGPoint P1, CGPoint P2, CGPoint P3, CGFloat x);
|
||||
CGFloat LOT_SolveCubic(CGFloat a, CGFloat b, CGFloat c, CGFloat d);
|
||||
CGFloat LOT_SolveQuadratic(CGFloat a, CGFloat b, CGFloat c);
|
||||
CGFloat LOT_Squared(CGFloat f);
|
||||
CGFloat LOT_Cubed(CGFloat f);
|
||||
CGFloat LOT_CubicRoot(CGFloat f);
|
||||
|
||||
CGFloat LOT_CubicLength(CGPoint fromPoint, CGPoint toPoint, CGPoint controlPoint1, CGPoint controlPoint2);
|
||||
CGFloat LOT_CubicLengthWithPrecision(CGPoint fromPoint, CGPoint toPoint, CGPoint controlPoint1, CGPoint controlPoint2, CGFloat iterations);
|
||||
480
Pods/lottie-ios/lottie-ios/Classes/Extensions/CGGeometry+LOTAdditions.m
generated
Normal file
480
Pods/lottie-ios/lottie-ios/Classes/Extensions/CGGeometry+LOTAdditions.m
generated
Normal file
@@ -0,0 +1,480 @@
|
||||
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
const CGSize CGSizeMax = {CGFLOAT_MAX, CGFLOAT_MAX};
|
||||
//
|
||||
// Core Graphics Geometry Additions
|
||||
//
|
||||
|
||||
// CGRectIntegral returns a rectangle with the smallest integer values for its origin and size that contains the source rectangle.
|
||||
// For a rect with .origin={5, 5.5}, .size=(10, 10), it will return .origin={5,5}, .size={10, 11};
|
||||
// LOT_RectIntegral will return {5,5}, {10, 10}.
|
||||
CGRect LOT_RectIntegral(CGRect rect) {
|
||||
rect.origin = CGPointMake(rintf(rect.origin.x), rintf(rect.origin.y));
|
||||
rect.size = CGSizeMake(ceilf(rect.size.width), ceil(rect.size.height));
|
||||
return rect;
|
||||
}
|
||||
|
||||
//
|
||||
// Centering
|
||||
|
||||
// Returns a rectangle of the given size, centered at a point
|
||||
|
||||
CGRect LOT_RectCenteredAtPoint(CGPoint center, CGSize size, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = center.x - 0.5f * size.width;
|
||||
result.origin.y = center.y - 0.5f * size.height;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the center point of a CGRect
|
||||
CGPoint LOT_RectGetCenterPoint(CGRect rect) {
|
||||
return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
|
||||
}
|
||||
|
||||
//
|
||||
// Insetting
|
||||
|
||||
// Inset the rectangle on a single edge
|
||||
|
||||
CGRect LOT_RectInsetLeft(CGRect rect, CGFloat inset) {
|
||||
rect.origin.x += inset;
|
||||
rect.size.width -= inset;
|
||||
return rect;
|
||||
}
|
||||
|
||||
CGRect LOT_RectInsetRight(CGRect rect, CGFloat inset) {
|
||||
rect.size.width -= inset;
|
||||
return rect;
|
||||
}
|
||||
|
||||
CGRect LOT_RectInsetTop(CGRect rect, CGFloat inset) {
|
||||
rect.origin.y += inset;
|
||||
rect.size.height -= inset;
|
||||
return rect;
|
||||
}
|
||||
|
||||
CGRect LOT_RectInsetBottom(CGRect rect, CGFloat inset) {
|
||||
rect.size.height -= inset;
|
||||
return rect;
|
||||
}
|
||||
|
||||
// Inset the rectangle on two edges
|
||||
|
||||
CGRect LOT_RectInsetHorizontal(CGRect rect, CGFloat leftInset, CGFloat rightInset) {
|
||||
rect.origin.x += leftInset;
|
||||
rect.size.width -= (leftInset + rightInset);
|
||||
return rect;
|
||||
}
|
||||
|
||||
CGRect LOT_RectInsetVertical(CGRect rect, CGFloat topInset, CGFloat bottomInset) {
|
||||
rect.origin.y += topInset;
|
||||
rect.size.height -= (topInset + bottomInset);
|
||||
return rect;
|
||||
}
|
||||
|
||||
// Inset the rectangle on all edges
|
||||
|
||||
CGRect LOT_RectInsetAll(CGRect rect, CGFloat leftInset, CGFloat rightInset, CGFloat topInset, CGFloat bottomInset) {
|
||||
rect.origin.x += leftInset;
|
||||
rect.origin.y += topInset;
|
||||
rect.size.width -= (leftInset + rightInset);
|
||||
rect.size.height -= (topInset + bottomInset);
|
||||
return rect;
|
||||
}
|
||||
|
||||
//
|
||||
// Framing
|
||||
|
||||
// Returns a rectangle of size framed in the center of the given rectangle
|
||||
|
||||
CGRect LOT_RectFramedCenteredInRect(CGRect rect, CGSize size, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rintf(0.5f * (rect.size.width - size.width));
|
||||
result.origin.y = rect.origin.y + rintf(0.5f * (rect.size.height - size.height));
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns a rectangle of size framed in the given rectangle and inset
|
||||
|
||||
CGRect LOT_RectFramedLeftInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + inset;
|
||||
result.origin.y = rect.origin.y + rintf(0.5f * (rect.size.height - size.height));
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectFramedRightInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rect.size.width - size.width - inset;
|
||||
result.origin.y = rect.origin.y + rintf(0.5f * (rect.size.height - size.height));
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectFramedTopInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rintf(0.5f * (rect.size.width - size.width));
|
||||
result.origin.y = rect.origin.y + inset;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectFramedBottomInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rintf(0.5f * (rect.size.width - size.width));
|
||||
result.origin.y = rect.origin.y + rect.size.height - size.height - inset;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectFramedTopLeftInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + insetWidth;
|
||||
result.origin.y = rect.origin.y + insetHeight;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectFramedTopRightInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rect.size.width - size.width - insetWidth;
|
||||
result.origin.y = rect.origin.y + insetHeight;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectFramedBottomLeftInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + insetWidth;
|
||||
result.origin.y = rect.origin.y + rect.size.height - size.height - insetHeight;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectFramedBottomRightInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rect.size.width - size.width - insetWidth;
|
||||
result.origin.y = rect.origin.y + rect.size.height - size.height - insetHeight;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns a rectangle of size attached to the given rectangle
|
||||
|
||||
CGRect LOT_RectAttachedLeftToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x - size.width - margin;
|
||||
result.origin.y = rect.origin.y + rintf(0.5f * (rect.size.height - size.height));
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectAttachedRightToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rect.size.width + margin;
|
||||
result.origin.y = rect.origin.y + rintf(0.5f * (rect.size.height - size.height));
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectAttachedTopToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rintf(0.5f * (rect.size.width - size.width));
|
||||
result.origin.y = rect.origin.y - size.height - margin;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectAttachedTopLeftToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + marginWidth;
|
||||
result.origin.y = rect.origin.y - size.height - marginHeight;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectAttachedTopRightToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rect.size.width - size.width - marginWidth;
|
||||
result.origin.y = rect.origin.y - rect.size.height - marginHeight;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectAttachedBottomToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rintf(0.5f * (rect.size.width - size.width));
|
||||
result.origin.y = rect.origin.y + rect.size.height + margin;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectAttachedBottomLeftToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + marginWidth;
|
||||
result.origin.y = rect.origin.y + rect.size.height + marginHeight;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
CGRect LOT_RectAttachedBottomRightToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral) {
|
||||
CGRect result;
|
||||
result.origin.x = rect.origin.x + rect.size.width - size.width - marginWidth;
|
||||
result.origin.y = rect.origin.y + rect.size.height + marginHeight;
|
||||
result.size = size;
|
||||
|
||||
if (integral) { result = LOT_RectIntegral(result); }
|
||||
return result;
|
||||
}
|
||||
|
||||
// Divides a rect into sections and returns the section at specified index
|
||||
|
||||
CGRect LOT_RectDividedSection(CGRect rect, NSInteger sections, NSInteger index, CGRectEdge fromEdge) {
|
||||
if (sections == 0) {
|
||||
return CGRectZero;
|
||||
}
|
||||
CGRect r = rect;
|
||||
if (fromEdge == CGRectMaxXEdge || fromEdge == CGRectMinXEdge) {
|
||||
r.size.width = rect.size.width / sections;
|
||||
r.origin.x += r.size.width * index;
|
||||
} else {
|
||||
r.size.height = rect.size.height / sections;
|
||||
r.origin.y += r.size.height * index;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
CGRect LOT_RectAddRect(CGRect rect, CGRect other) {
|
||||
return CGRectMake(rect.origin.x + other.origin.x, rect.origin.y + other.origin.y,
|
||||
rect.size.width + other.size.width, rect.size.height + other.size.height);
|
||||
}
|
||||
|
||||
CGRect LOT_RectAddPoint(CGRect rect, CGPoint point) {
|
||||
return CGRectMake(rect.origin.x + point.x, rect.origin.y + point.y,
|
||||
rect.size.width, rect.size.height);
|
||||
}
|
||||
|
||||
CGRect LOT_RectAddSize(CGRect rect, CGSize size) {
|
||||
return CGRectMake(rect.origin.x, rect.origin.y,
|
||||
rect.size.width + size.width, rect.size.height + size.height);
|
||||
}
|
||||
|
||||
CGRect LOT_RectBounded(CGRect rect) {
|
||||
CGRect returnRect = rect;
|
||||
returnRect.origin = CGPointZero;
|
||||
return returnRect;
|
||||
}
|
||||
|
||||
CGPoint LOT_PointAddedToPoint(CGPoint point1, CGPoint point2) {
|
||||
CGPoint returnPoint = point1;
|
||||
returnPoint.x += point2.x;
|
||||
returnPoint.y += point2.y;
|
||||
return returnPoint;
|
||||
}
|
||||
|
||||
CGRect LOT_RectSetHeight(CGRect rect, CGFloat height) {
|
||||
return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, height);
|
||||
}
|
||||
|
||||
CGFloat LOT_DegreesToRadians(CGFloat degrees) {
|
||||
return degrees * M_PI / 180;
|
||||
}
|
||||
|
||||
CGFloat LOT_PointDistanceFromPoint(CGPoint point1, CGPoint point2) {
|
||||
CGFloat xDist = (point2.x - point1.x);
|
||||
CGFloat yDist = (point2.y - point1.y);
|
||||
CGFloat distance = sqrt((xDist * xDist) + (yDist * yDist));
|
||||
return distance;
|
||||
}
|
||||
|
||||
CGFloat LOT_RemapValue(CGFloat value, CGFloat low1, CGFloat high1, CGFloat low2, CGFloat high2 ) {
|
||||
return low2 + (value - low1) * (high2 - low2) / (high1 - low1);
|
||||
}
|
||||
|
||||
CGPoint LOT_PointByLerpingPoints(CGPoint point1, CGPoint point2, CGFloat value) {
|
||||
CGFloat xDiff = point2.x - point1.x;
|
||||
CGFloat yDiff = point2.y - point1.y;
|
||||
CGPoint transposed = CGPointMake(fabs(xDiff), fabs(yDiff));
|
||||
CGPoint returnPoint;
|
||||
if (xDiff == 0 || yDiff == 0) {
|
||||
returnPoint.x = xDiff == 0 ? point1.x : LOT_RemapValue(value, 0, 1, point1.x, point2.x);
|
||||
returnPoint.y = yDiff == 0 ? point1.y : LOT_RemapValue(value, 0, 1, point1.y, point2.y);
|
||||
} else {
|
||||
CGFloat rx = transposed.x / transposed.y;
|
||||
CGFloat yLerp = LOT_RemapValue(value, 0, 1, 0, transposed.y);
|
||||
CGFloat xLerp = yLerp * rx;
|
||||
CGPoint interpolatedPoint = CGPointMake(point2.x < point1.x ? xLerp * -1 : xLerp,
|
||||
point2.y < point1.y ? yLerp * -1 : yLerp);
|
||||
returnPoint = LOT_PointAddedToPoint(point1, interpolatedPoint);
|
||||
}
|
||||
return returnPoint;
|
||||
}
|
||||
|
||||
CGPoint LOT_PointInLine(CGPoint A, CGPoint B, CGFloat T) {
|
||||
CGPoint C;
|
||||
C.x = A.x - ((A.x - B.x) * T);
|
||||
C.y = A.y - ((A.y - B.y) * T);
|
||||
return C;
|
||||
}
|
||||
|
||||
CGFloat LOT_CubicBezierGetY(CGPoint cp1, CGPoint cp2, CGFloat T) {
|
||||
// (1-x)^3 * y0 + 3*(1-x)^2 * x * y1 + 3*(1-x) * x^2 * y2 + x^3 * y3
|
||||
return 3 * powf(1.f - T, 2.f) * T * cp1.y + 3.f * (1.f - T) * powf(T, 2.f) * cp2.y + powf(T, 3.f);
|
||||
}
|
||||
|
||||
CGPoint LOT_PointInCubicCurve(CGPoint start, CGPoint cp1, CGPoint cp2, CGPoint end, CGFloat T) {
|
||||
CGPoint A = LOT_PointInLine(start, cp1, T);
|
||||
CGPoint B = LOT_PointInLine(cp1, cp2, T);
|
||||
CGPoint C = LOT_PointInLine(cp2, end, T);
|
||||
CGPoint D = LOT_PointInLine(A, B, T);
|
||||
CGPoint E = LOT_PointInLine(B, C, T);
|
||||
CGPoint F = LOT_PointInLine(D, E, T);
|
||||
return F;
|
||||
}
|
||||
|
||||
CGFloat LOT_SolveCubic(CGFloat a, CGFloat b, CGFloat c, CGFloat d) {
|
||||
if (a == 0) return LOT_SolveQuadratic(b, c, d);
|
||||
if (d == 0) return 0;
|
||||
|
||||
b /= a;
|
||||
c /= a;
|
||||
d /= a;
|
||||
CGFloat q = (3.0 * c - LOT_Squared(b)) / 9.0;
|
||||
CGFloat r = (-27.0 * d + b * (9.0 * c - 2.0 * LOT_Squared(b))) / 54.0;
|
||||
CGFloat disc = LOT_Cubed(q) + LOT_Squared(r);
|
||||
CGFloat term1 = b / 3.0;
|
||||
|
||||
if (disc > 0) {
|
||||
double s = r + sqrtf(disc);
|
||||
s = (s < 0) ? - LOT_CubicRoot(-s) : LOT_CubicRoot(s);
|
||||
double t = r - sqrtf(disc);
|
||||
t = (t < 0) ? - LOT_CubicRoot(-t) : LOT_CubicRoot(t);
|
||||
|
||||
double result = -term1 + s + t;
|
||||
if (result >= 0 && result <= 1) return result;
|
||||
} else if (disc == 0) {
|
||||
double r13 = (r < 0) ? - LOT_CubicRoot(-r) : LOT_CubicRoot(r);
|
||||
|
||||
double result = -term1 + 2.0 * r13;
|
||||
if (result >= 0 && result <= 1) return result;
|
||||
|
||||
result = -(r13 + term1);
|
||||
if (result >= 0 && result <= 1) return result;
|
||||
} else {
|
||||
q = -q;
|
||||
double dum1 = q * q * q;
|
||||
dum1 = acosf(r / sqrtf(dum1));
|
||||
double r13 = 2.0 * sqrtf(q);
|
||||
|
||||
double result = -term1 + r13 * cos(dum1 / 3.0);
|
||||
if (result >= 0 && result <= 1) return result;
|
||||
|
||||
result = -term1 + r13 * cos((dum1 + 2.0 * M_PI) / 3.0);
|
||||
if (result >= 0 && result <= 1) return result;
|
||||
|
||||
result = -term1 + r13 * cos((dum1 + 4.0 * M_PI) / 3.0);
|
||||
if (result >= 0 && result <= 1) return result;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
CGFloat LOT_SolveQuadratic(CGFloat a, CGFloat b, CGFloat c) {
|
||||
CGFloat result = (-b + sqrtf(LOT_Squared(b) - 4 * a * c)) / (2 * a);
|
||||
if (result >= 0 && result <= 1) return result;
|
||||
|
||||
result = (-b - sqrtf(LOT_Squared(b) - 4 * a * c)) / (2 * a);
|
||||
if (result >= 0 && result <= 1) return result;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
CGFloat LOT_Squared(CGFloat f) { return f * f; }
|
||||
|
||||
CGFloat LOT_Cubed(CGFloat f) { return f * f * f; }
|
||||
|
||||
CGFloat LOT_CubicRoot(CGFloat f) { return powf(f, 1.0 / 3.0); }
|
||||
|
||||
CGFloat LOT_CubicBezierInterpolate(CGPoint P0, CGPoint P1, CGPoint P2, CGPoint P3, CGFloat x) {
|
||||
CGFloat t;
|
||||
if (x == P0.x) {
|
||||
// Handle corner cases explicitly to prevent rounding errors
|
||||
t = 0;
|
||||
} else if (x == P3.x) {
|
||||
t = 1;
|
||||
} else {
|
||||
// Calculate t
|
||||
CGFloat a = -P0.x + 3 * P1.x - 3 * P2.x + P3.x;
|
||||
CGFloat b = 3 * P0.x - 6 * P1.x + 3 * P2.x;
|
||||
CGFloat c = -3 * P0.x + 3 * P1.x;
|
||||
CGFloat d = P0.x - x;
|
||||
CGFloat tTemp = LOT_SolveCubic(a, b, c, d);
|
||||
if (tTemp == -1) return -1;
|
||||
t = tTemp;
|
||||
}
|
||||
|
||||
// Calculate y from t
|
||||
return LOT_Cubed(1 - t) * P0.y + 3 * t * LOT_Squared(1 - t) * P1.y + 3 * LOT_Squared(t) * (1 - t) * P2.y + LOT_Cubed(t) * P3.y;
|
||||
}
|
||||
|
||||
CGFloat LOT_CubicLengthWithPrecision(CGPoint fromPoint, CGPoint toPoint, CGPoint controlPoint1, CGPoint controlPoint2, CGFloat iterations) {
|
||||
CGFloat length = 0;
|
||||
CGPoint previousPoint = fromPoint;
|
||||
iterations = ceilf(iterations);
|
||||
for (int i = 1; i <= iterations; ++i) {
|
||||
float s = (float)i / iterations;
|
||||
|
||||
CGPoint p = LOT_PointInCubicCurve(fromPoint, controlPoint1, controlPoint2, toPoint, s);
|
||||
|
||||
length += LOT_PointDistanceFromPoint(previousPoint, p);
|
||||
previousPoint = p;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
CGFloat LOT_CubicLength(CGPoint fromPoint, CGPoint toPoint, CGPoint controlPoint1, CGPoint controlPoint2) {
|
||||
return LOT_CubicLengthWithPrecision(fromPoint, toPoint, controlPoint1, controlPoint2, 20);
|
||||
}
|
||||
|
||||
BOOL LOT_CGPointIsZero(CGPoint point) {
|
||||
return CGPointEqualToPoint(point, CGPointZero);
|
||||
}
|
||||
54
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTBezierPath.h
generated
Normal file
54
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTBezierPath.h
generated
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// LOTBezierPath.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/20/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTPlatformCompat.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LOTBezierPath : NSObject
|
||||
|
||||
+ (instancetype)pathWithCGPath:(CGPathRef)path;
|
||||
|
||||
+ (instancetype)newPath;
|
||||
|
||||
- (void)LOT_moveToPoint:(CGPoint)point;
|
||||
|
||||
- (void)LOT_addLineToPoint:(CGPoint)point;
|
||||
|
||||
- (void)LOT_addCurveToPoint:(CGPoint)point
|
||||
controlPoint1:(CGPoint)cp1
|
||||
controlPoint2:(CGPoint)cp2;
|
||||
|
||||
- (void)LOT_closePath;
|
||||
|
||||
- (void)LOT_removeAllPoints;
|
||||
|
||||
- (void)LOT_appendPath:(LOTBezierPath *)bezierPath;
|
||||
|
||||
- (void)trimPathFromT:(CGFloat)fromT toT:(CGFloat)toT offset:(CGFloat)offset;
|
||||
|
||||
- (void)LOT_applyTransform:(CGAffineTransform)transform;
|
||||
|
||||
@property (nonatomic, assign) BOOL cacheLengths;
|
||||
|
||||
@property (nonatomic, readonly) CGFloat length;
|
||||
|
||||
@property (nonatomic, readonly) CGPathRef CGPath;
|
||||
@property (nonatomic, readonly) CGPoint currentPoint;
|
||||
@property (nonatomic) CGFloat lineWidth;
|
||||
@property (nonatomic) CGLineCap lineCapStyle;
|
||||
@property (nonatomic) CGLineJoin lineJoinStyle;
|
||||
@property (nonatomic) CGFloat miterLimit;
|
||||
@property (nonatomic) CGFloat flatness;
|
||||
@property (nonatomic) BOOL usesEvenOddFillRule;
|
||||
@property (readonly, getter=isEmpty) BOOL empty;
|
||||
@property (nonatomic, readonly) CGRect bounds;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
471
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTBezierPath.m
generated
Normal file
471
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTBezierPath.m
generated
Normal file
@@ -0,0 +1,471 @@
|
||||
//
|
||||
// LOTBezierPath.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/20/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTBezierPath.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
typedef struct LOT_Subpath LOT_Subpath;
|
||||
typedef void(^LOTBezierPathEnumerationHandler)(const CGPathElement *element);
|
||||
|
||||
struct LOT_Subpath {
|
||||
CGPathElementType type;
|
||||
CGFloat length;
|
||||
CGPoint endPoint;
|
||||
CGPoint controlPoint1;
|
||||
CGPoint controlPoint2;
|
||||
LOT_Subpath *nextSubpath;
|
||||
};
|
||||
|
||||
@interface LOTBezierPath ()
|
||||
@property (nonatomic, readonly) LOT_Subpath *headSubpath;
|
||||
@end
|
||||
|
||||
@implementation LOTBezierPath {
|
||||
LOT_Subpath *headSubpath_;
|
||||
LOT_Subpath *tailSubpath_;
|
||||
CGPoint subpathStartPoint_;
|
||||
CGFloat *_lineDashPattern;
|
||||
NSInteger _lineDashCount;
|
||||
CGFloat _lineDashPhase;
|
||||
CGMutablePathRef _path;
|
||||
}
|
||||
|
||||
// MARK - Lifecycle
|
||||
|
||||
+ (instancetype)pathWithCGPath:(CGPathRef)path {
|
||||
LOTBezierPath *returnPath = [LOTBezierPath newPath];
|
||||
[returnPath setWithCGPath:path];
|
||||
return returnPath;
|
||||
}
|
||||
|
||||
+ (instancetype)newPath {
|
||||
return [[LOTBezierPath alloc] init];
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_length = 0;
|
||||
headSubpath_ = NULL;
|
||||
tailSubpath_ = NULL;
|
||||
_path = CGPathCreateMutable();
|
||||
_lineWidth = 1;
|
||||
_lineCapStyle = kCGLineCapButt;
|
||||
_lineJoinStyle = kCGLineJoinMiter;
|
||||
_miterLimit = 10;
|
||||
_flatness = 0.6;
|
||||
_usesEvenOddFillRule = NO;
|
||||
_lineDashPattern = NULL;
|
||||
_lineDashCount = 0;
|
||||
_lineDashPhase = 0;
|
||||
_cacheLengths = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self removeAllSubpaths];
|
||||
if (_path) CGPathRelease(_path);
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
LOTBezierPath *copy = [[self class] new];
|
||||
|
||||
copy.cacheLengths = self.cacheLengths;
|
||||
copy.lineWidth = self.lineWidth;
|
||||
copy.lineCapStyle = self.lineCapStyle;
|
||||
copy.lineJoinStyle = self.lineJoinStyle;
|
||||
copy.miterLimit = self.miterLimit;
|
||||
copy.flatness = self.flatness;
|
||||
copy.usesEvenOddFillRule = self.usesEvenOddFillRule;
|
||||
|
||||
[copy LOT_appendPath:self];
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
// MARK - Subpaths List
|
||||
|
||||
- (void)removeAllSubpaths {
|
||||
LOT_Subpath *node = headSubpath_;
|
||||
while (node) {
|
||||
LOT_Subpath *nextNode = node->nextSubpath;
|
||||
node->nextSubpath = NULL;
|
||||
free(node);
|
||||
node = nextNode;
|
||||
}
|
||||
headSubpath_ = NULL;
|
||||
tailSubpath_ = NULL;
|
||||
}
|
||||
|
||||
- (void)addSubpathWithType:(CGPathElementType)type
|
||||
length:(CGFloat)length
|
||||
endPoint:(CGPoint)endPoint
|
||||
controlPoint1:(CGPoint)controlPoint1
|
||||
controlPoint1:(CGPoint)controlPoint2 {
|
||||
LOT_Subpath *subPath = (LOT_Subpath *)malloc(sizeof(LOT_Subpath));
|
||||
subPath->type = type;
|
||||
subPath->length = length;
|
||||
subPath->endPoint = endPoint;
|
||||
subPath->controlPoint1 = controlPoint1;
|
||||
subPath->controlPoint2 = controlPoint2;
|
||||
subPath->nextSubpath = NULL;
|
||||
if (tailSubpath_ == NULL) {
|
||||
headSubpath_ = subPath;
|
||||
tailSubpath_ = subPath;
|
||||
} else {
|
||||
tailSubpath_->nextSubpath = subPath;
|
||||
tailSubpath_ = subPath;
|
||||
}
|
||||
}
|
||||
|
||||
// MARK Getters Setters
|
||||
|
||||
- (CGPoint)currentPoint {
|
||||
CGPoint previousPoint = tailSubpath_ ? tailSubpath_->endPoint : CGPointZero;
|
||||
return previousPoint;
|
||||
}
|
||||
|
||||
- (CGPathRef)CGPath {
|
||||
return _path;
|
||||
}
|
||||
|
||||
- (LOT_Subpath *)headSubpath {
|
||||
return headSubpath_;
|
||||
}
|
||||
|
||||
// MARK - External
|
||||
|
||||
- (void)LOT_moveToPoint:(CGPoint)point {
|
||||
subpathStartPoint_ = point;
|
||||
[self addSubpathWithType:kCGPathElementMoveToPoint length:0 endPoint:point controlPoint1:CGPointZero controlPoint1:CGPointZero];
|
||||
CGPathMoveToPoint(_path, NULL, point.x, point.y);
|
||||
}
|
||||
|
||||
- (void)LOT_addLineToPoint:(CGPoint)point {
|
||||
CGFloat length = 0;
|
||||
if (_cacheLengths) {
|
||||
length = LOT_PointDistanceFromPoint(self.currentPoint, point);
|
||||
_length = _length + length;
|
||||
}
|
||||
[self addSubpathWithType:kCGPathElementAddLineToPoint length:length endPoint:point controlPoint1:CGPointZero controlPoint1:CGPointZero];
|
||||
CGPathAddLineToPoint(_path, NULL, point.x, point.y);
|
||||
}
|
||||
|
||||
- (void)LOT_addCurveToPoint:(CGPoint)point
|
||||
controlPoint1:(CGPoint)cp1
|
||||
controlPoint2:(CGPoint)cp2 {
|
||||
CGFloat length = 0;
|
||||
if (_cacheLengths) {
|
||||
length = LOT_CubicLengthWithPrecision(self.currentPoint, point, cp1, cp2, 5);
|
||||
_length = _length + length;
|
||||
}
|
||||
[self addSubpathWithType:kCGPathElementAddCurveToPoint length:length endPoint:point controlPoint1:cp1 controlPoint1:cp2];
|
||||
CGPathAddCurveToPoint(_path, NULL, cp1.x, cp1.y, cp2.x, cp2.y, point.x, point.y);
|
||||
}
|
||||
|
||||
- (void)LOT_closePath {
|
||||
CGFloat length = 0;
|
||||
if (_cacheLengths) {
|
||||
length = LOT_PointDistanceFromPoint(self.currentPoint, subpathStartPoint_);
|
||||
_length = _length + length;
|
||||
}
|
||||
[self addSubpathWithType:kCGPathElementCloseSubpath length:length endPoint:subpathStartPoint_ controlPoint1:CGPointZero controlPoint1:CGPointZero];
|
||||
CGPathCloseSubpath(_path);
|
||||
}
|
||||
|
||||
- (void)_clearPathData {
|
||||
_length = 0;
|
||||
subpathStartPoint_ = CGPointZero;
|
||||
CGPathRelease(_path);
|
||||
_path = CGPathCreateMutable();
|
||||
}
|
||||
|
||||
- (void)LOT_removeAllPoints {
|
||||
[self removeAllSubpaths];
|
||||
[self _clearPathData];
|
||||
}
|
||||
|
||||
- (BOOL)containsPoint:(CGPoint)point {
|
||||
return CGPathContainsPoint(_path, NULL, point, _usesEvenOddFillRule);
|
||||
}
|
||||
|
||||
- (BOOL)isEmpty {
|
||||
return CGPathIsEmpty(_path);
|
||||
}
|
||||
|
||||
- (CGRect)bounds {
|
||||
return CGPathGetBoundingBox(_path);
|
||||
}
|
||||
|
||||
- (void)LOT_applyTransform:(CGAffineTransform)transform {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutable();
|
||||
CGPathAddPath(mutablePath, &transform, _path);
|
||||
CGPathRelease(_path);
|
||||
_path = mutablePath;
|
||||
}
|
||||
|
||||
- (void)LOT_appendPath:(LOTBezierPath *)bezierPath {
|
||||
CGPathAddPath(_path, NULL, bezierPath.CGPath);
|
||||
|
||||
LOT_Subpath *nextSubpath = bezierPath.headSubpath;
|
||||
while (nextSubpath) {
|
||||
CGFloat length = 0;
|
||||
if (self.cacheLengths) {
|
||||
if (bezierPath.cacheLengths) {
|
||||
length = nextSubpath->length;
|
||||
} else {
|
||||
// No previous length data, measure.
|
||||
if (nextSubpath->type == kCGPathElementAddLineToPoint) {
|
||||
length = LOT_PointDistanceFromPoint(self.currentPoint, nextSubpath->endPoint);
|
||||
} else if (nextSubpath->type == kCGPathElementAddCurveToPoint) {
|
||||
length = LOT_CubicLengthWithPrecision(self.currentPoint, nextSubpath->endPoint, nextSubpath->controlPoint1, nextSubpath->controlPoint2, 5);
|
||||
} else if (nextSubpath->type == kCGPathElementCloseSubpath) {
|
||||
length = LOT_PointDistanceFromPoint(self.currentPoint, nextSubpath->endPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
_length = _length + length;
|
||||
[self addSubpathWithType:nextSubpath->type
|
||||
length:length
|
||||
endPoint:nextSubpath->endPoint
|
||||
controlPoint1:nextSubpath->controlPoint1
|
||||
controlPoint1:nextSubpath->controlPoint2];
|
||||
|
||||
nextSubpath = nextSubpath->nextSubpath;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)trimPathFromT:(CGFloat)fromT toT:(CGFloat)toT offset:(CGFloat)offset {
|
||||
fromT = MIN(MAX(0, fromT), 1);
|
||||
toT = MIN(MAX(0, toT), 1);
|
||||
if (fromT > toT) {
|
||||
CGFloat to = fromT;
|
||||
fromT = toT;
|
||||
toT = to;
|
||||
}
|
||||
|
||||
offset = offset - floor(offset);
|
||||
CGFloat fromLength = fromT + offset;
|
||||
CGFloat toLength = toT + offset;
|
||||
|
||||
if (toT - fromT == 1) {
|
||||
// Do Nothing, Full Path returned.
|
||||
return;
|
||||
}
|
||||
|
||||
if (fromLength == toLength) {
|
||||
// Empty Path
|
||||
[self LOT_removeAllPoints];
|
||||
return;
|
||||
}
|
||||
|
||||
if (fromLength >= 1) {
|
||||
fromLength = fromLength - floor(fromLength);
|
||||
}
|
||||
if (toLength > 1) {
|
||||
toLength = toLength - floor(toLength);
|
||||
}
|
||||
|
||||
if (fromLength == 0 &&
|
||||
toLength == 1) {
|
||||
// Do Nothing. Full Path returned.
|
||||
return;
|
||||
}
|
||||
|
||||
if (fromLength == toLength) {
|
||||
// Empty Path
|
||||
[self LOT_removeAllPoints];
|
||||
return;
|
||||
}
|
||||
|
||||
CGFloat totalLength = _length;
|
||||
|
||||
[self _clearPathData];
|
||||
|
||||
LOT_Subpath *subpath = headSubpath_;
|
||||
headSubpath_ = NULL;
|
||||
tailSubpath_ = NULL;
|
||||
|
||||
fromLength = fromLength * totalLength;
|
||||
toLength = toLength * totalLength;
|
||||
|
||||
CGFloat currentStartLength = fromLength < toLength ? fromLength : 0;
|
||||
CGFloat currentEndLength = toLength;
|
||||
|
||||
CGFloat subpathBeginningLength = 0;
|
||||
CGPoint currentPoint = CGPointZero;
|
||||
|
||||
while (subpath) {
|
||||
|
||||
CGFloat pathLength = subpath->length;
|
||||
if (!_cacheLengths) {
|
||||
if (subpath->type == kCGPathElementAddLineToPoint) {
|
||||
pathLength = LOT_PointDistanceFromPoint(currentPoint, subpath->endPoint);
|
||||
} else if (subpath->type == kCGPathElementAddCurveToPoint) {
|
||||
pathLength = LOT_CubicLengthWithPrecision(currentPoint, subpath->endPoint, subpath->controlPoint1, subpath->controlPoint2, 5);
|
||||
} else if (subpath->type == kCGPathElementCloseSubpath) {
|
||||
pathLength = LOT_PointDistanceFromPoint(currentPoint, subpath->endPoint);
|
||||
}
|
||||
}
|
||||
CGFloat subpathEndLength = subpathBeginningLength + pathLength;
|
||||
|
||||
if (subpath->type != kCGPathElementMoveToPoint &&
|
||||
subpathEndLength > currentStartLength) {
|
||||
// The end of this path overlaps the current drawing region
|
||||
|
||||
// x x x x
|
||||
// ---------------ooooooooooooooooooooooooooooooooooooooooooooooooo-------------------
|
||||
// Start |currentStartLength currentEndLength| End
|
||||
|
||||
CGFloat currentSpanStartT = LOT_RemapValue(currentStartLength, subpathBeginningLength, subpathEndLength, 0, 1);
|
||||
CGFloat currentSpanEndT = LOT_RemapValue(currentEndLength, subpathBeginningLength, subpathEndLength, 0, 1);
|
||||
|
||||
// At this point currentSpan start and end T can be less than 0 or greater than 1
|
||||
|
||||
if (subpath->type == kCGPathElementAddLineToPoint) {
|
||||
|
||||
if (currentSpanStartT >= 0) {
|
||||
// The current drawable span either starts with this subpath or along this subpath.
|
||||
// If this is the middle of a segment then currentSpanStartT would be less than 0
|
||||
if (currentSpanStartT > 0) {
|
||||
currentPoint = LOT_PointInLine(currentPoint, subpath->endPoint, currentSpanStartT);
|
||||
}
|
||||
[self LOT_moveToPoint:currentPoint];
|
||||
// Now we are ready to draw a line
|
||||
}
|
||||
|
||||
CGPoint toPoint = subpath->endPoint;
|
||||
if (currentSpanEndT < 1) {
|
||||
// The end of the span is inside of the current subpath. Find it.
|
||||
toPoint = LOT_PointInLine(currentPoint, subpath->endPoint, currentSpanEndT);
|
||||
}
|
||||
[self LOT_addLineToPoint:toPoint];
|
||||
currentPoint = toPoint;
|
||||
} else if (subpath->type == kCGPathElementAddCurveToPoint) {
|
||||
|
||||
CGPoint cp1, cp2, end;
|
||||
cp1 = subpath->controlPoint1;
|
||||
cp2 = subpath->controlPoint2;
|
||||
end = subpath->endPoint;
|
||||
|
||||
if (currentSpanStartT >= 0) {
|
||||
// The current drawable span either starts with this subpath or along this subpath.
|
||||
// If this is the middle of a segment then currentSpanStartT would be less than 0
|
||||
// Beginning of a segment Move start point and calculate cp1 and 2 is necessary
|
||||
if (currentSpanStartT > 0) {
|
||||
CGPoint A = LOT_PointInLine(currentPoint, cp1, currentSpanStartT);
|
||||
CGPoint B = LOT_PointInLine(cp1, cp2, currentSpanStartT);
|
||||
CGPoint C = LOT_PointInLine(cp2, end, currentSpanStartT);
|
||||
CGPoint D = LOT_PointInLine(A, B, currentSpanStartT);
|
||||
CGPoint E = LOT_PointInLine(B, C, currentSpanStartT);
|
||||
CGPoint F = LOT_PointInLine(D, E, currentSpanStartT);
|
||||
currentPoint = F;
|
||||
cp1 = E;
|
||||
cp2 = C;
|
||||
currentSpanEndT = LOT_RemapValue(currentSpanEndT, currentSpanStartT, 1, 0, 1);
|
||||
}
|
||||
[self LOT_moveToPoint:currentPoint];
|
||||
}
|
||||
|
||||
if (currentSpanEndT < 1) {
|
||||
CGPoint A = LOT_PointInLine(currentPoint, cp1, currentSpanEndT);
|
||||
CGPoint B = LOT_PointInLine(cp1, cp2, currentSpanEndT);
|
||||
CGPoint C = LOT_PointInLine(cp2, end, currentSpanEndT);
|
||||
CGPoint D = LOT_PointInLine(A, B, currentSpanEndT);
|
||||
CGPoint E = LOT_PointInLine(B, C, currentSpanEndT);
|
||||
CGPoint F = LOT_PointInLine(D, E, currentSpanEndT);
|
||||
cp1 = A;
|
||||
cp2 = D;
|
||||
end = F;
|
||||
}
|
||||
[self LOT_addCurveToPoint:end controlPoint1:cp1 controlPoint2:cp2];
|
||||
}
|
||||
|
||||
if (currentSpanEndT <= 1) {
|
||||
// We have possibly reached the end.
|
||||
// Current From and To will possibly need to be reset.
|
||||
if (fromLength < toLength) {
|
||||
while (subpath) {
|
||||
LOT_Subpath *nextNode = subpath->nextSubpath;
|
||||
subpath->nextSubpath = NULL;
|
||||
free(subpath);
|
||||
subpath = nextNode;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
currentStartLength = fromLength;
|
||||
currentEndLength = totalLength;
|
||||
if (fromLength < (subpathBeginningLength + pathLength) &&
|
||||
fromLength > subpathBeginningLength &&
|
||||
currentSpanEndT < 1) {
|
||||
// Loop over this subpath one more time.
|
||||
// In this case the path start and end trim fall within this subpath bounds
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
currentPoint = subpath->endPoint;
|
||||
subpathBeginningLength = subpathEndLength;
|
||||
|
||||
LOT_Subpath *nextNode = subpath->nextSubpath;
|
||||
subpath->nextSubpath = NULL;
|
||||
free(subpath);
|
||||
subpath = nextNode;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - From CGPath
|
||||
|
||||
- (void)setWithCGPath:(CGPathRef)path {
|
||||
[self lot_enumeratePath:path elementsUsingBlock:^(const CGPathElement *element) {
|
||||
switch (element->type) {
|
||||
case kCGPathElementMoveToPoint: {
|
||||
CGPoint point = element ->points[0];
|
||||
[self LOT_moveToPoint:point];
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddLineToPoint: {
|
||||
CGPoint point = element ->points[0];
|
||||
[self LOT_addLineToPoint:point];
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddQuadCurveToPoint: {
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddCurveToPoint: {
|
||||
CGPoint point1 = element->points[0];
|
||||
CGPoint point2 = element->points[1];
|
||||
CGPoint point3 = element->points[2];
|
||||
[self LOT_addCurveToPoint:point3 controlPoint1:point1 controlPoint2:point2];
|
||||
break;
|
||||
}
|
||||
case kCGPathElementCloseSubpath: {
|
||||
[self LOT_closePath];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)lot_enumeratePath:(CGPathRef)cgPath elementsUsingBlock:(LOTBezierPathEnumerationHandler)handler {
|
||||
void CGPathEnumerationCallback(void *info, const CGPathElement *element);
|
||||
CGPathApply(cgPath, (__bridge void * _Nullable)(handler), CGPathEnumerationCallback);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void CGPathEnumerationCallback(void *info, const CGPathElement *element)
|
||||
{
|
||||
LOTBezierPathEnumerationHandler handler = (__bridge LOTBezierPathEnumerationHandler)(info);
|
||||
if (handler) {
|
||||
handler(element);
|
||||
}
|
||||
}
|
||||
26
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTHelpers.h
generated
Normal file
26
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTHelpers.h
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// LOTHelpers.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by Brandon Withrow on 7/28/16.
|
||||
// Copyright © 2016 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef LOTHelpers_h
|
||||
#define LOTHelpers_h
|
||||
|
||||
#import "UIColor+Expanded.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
#import "LOTBezierPath.h"
|
||||
|
||||
#define ENABLE_DEBUG_LOGGING NO
|
||||
#define ENABLE_DEBUG_SHAPES NO
|
||||
|
||||
#endif /* LOTHelpers_h */
|
||||
|
||||
// TODO Feature Phase
|
||||
/*
|
||||
- Trim Path individually
|
||||
- Image Cache Support
|
||||
- Skew transform
|
||||
*/
|
||||
20
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTRadialGradientLayer.h
generated
Executable file
20
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTRadialGradientLayer.h
generated
Executable file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// LOTAnimationView
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface LOTRadialGradientLayer : CALayer
|
||||
|
||||
@property CGPoint startPoint;
|
||||
@property CGPoint endPoint;
|
||||
|
||||
@property (nonatomic, copy) NSArray *colors;
|
||||
@property (nonatomic, copy) NSArray<NSNumber *> *locations;
|
||||
@property (nonatomic, assign) BOOL isRadial;
|
||||
|
||||
@end
|
||||
89
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTRadialGradientLayer.m
generated
Executable file
89
Pods/lottie-ios/lottie-ios/Classes/Extensions/LOTRadialGradientLayer.m
generated
Executable file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// LOTAnimationView
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTRadialGradientLayer.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTRadialGradientLayer
|
||||
|
||||
@dynamic isRadial;
|
||||
@dynamic startPoint;
|
||||
@dynamic endPoint;
|
||||
@dynamic colors;
|
||||
@dynamic locations;
|
||||
|
||||
+ (BOOL)needsDisplayForKey:(NSString *)key {
|
||||
if ([key isEqualToString:@"startPoint"] ||
|
||||
[key isEqualToString:@"endPoint"] ||
|
||||
[key isEqualToString:@"colors"] ||
|
||||
[key isEqualToString:@"locations"] ||
|
||||
[key isEqualToString:@"isRadial"]) {
|
||||
return YES;
|
||||
}
|
||||
return [super needsDisplayForKey:key];
|
||||
}
|
||||
|
||||
- (id)actionForKey:(NSString *)key {
|
||||
id action = self.actions[key];
|
||||
if (action) {
|
||||
if (action == [NSNull null]) {
|
||||
return nil;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
if ([key isEqualToString:@"startPoint"] ||
|
||||
[key isEqualToString:@"endPoint"] ||
|
||||
[key isEqualToString:@"colors"] ||
|
||||
[key isEqualToString:@"locations"] ||
|
||||
[key isEqualToString:@"isRadial"]) {
|
||||
CABasicAnimation *theAnimation = [CABasicAnimation animationWithKeyPath:key];
|
||||
theAnimation.fromValue = [self.presentationLayer valueForKey:key];
|
||||
return theAnimation;
|
||||
}
|
||||
return [super actionForKey:key];
|
||||
}
|
||||
|
||||
- (void)drawInContext:(CGContextRef)ctx {
|
||||
if (self.colors.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSInteger numberOfLocations = self.locations.count;
|
||||
CGColorRef colorRef = (__bridge CGColorRef)[self.colors objectAtIndex:0];
|
||||
NSInteger numberOfComponents = CGColorGetNumberOfComponents(colorRef);
|
||||
CGColorSpaceRef colorSpace = CGColorGetColorSpace(colorRef);
|
||||
|
||||
CGPoint origin = self.startPoint;
|
||||
CGFloat radius = LOT_PointDistanceFromPoint(self.startPoint, self.endPoint);
|
||||
|
||||
CGFloat gradientLocations[numberOfLocations];
|
||||
CGFloat gradientComponents[numberOfLocations * numberOfComponents];
|
||||
|
||||
for (NSInteger locationIndex = 0; locationIndex < numberOfLocations; locationIndex++) {
|
||||
|
||||
gradientLocations[locationIndex] = [self.locations[locationIndex] floatValue];
|
||||
const CGFloat *colorComponents = CGColorGetComponents((__bridge CGColorRef)self.colors[locationIndex]);
|
||||
|
||||
for (NSInteger componentIndex = 0; componentIndex < numberOfComponents; componentIndex++) {
|
||||
gradientComponents[numberOfComponents * locationIndex + componentIndex] = colorComponents[componentIndex];
|
||||
}
|
||||
}
|
||||
|
||||
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradientComponents, gradientLocations, numberOfLocations);
|
||||
|
||||
if (self.isRadial) {
|
||||
CGContextDrawRadialGradient(ctx, gradient, origin, 0, origin, radius, kCGGradientDrawsAfterEndLocation);
|
||||
} else {
|
||||
CGContextDrawLinearGradient(ctx, gradient, self.startPoint, self.endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
|
||||
}
|
||||
|
||||
CGGradientRelease(gradient);
|
||||
}
|
||||
|
||||
@end
|
||||
51
Pods/lottie-ios/lottie-ios/Classes/Extensions/UIColor+Expanded.h
generated
Normal file
51
Pods/lottie-ios/lottie-ios/Classes/Extensions/UIColor+Expanded.h
generated
Normal file
@@ -0,0 +1,51 @@
|
||||
#import "LOTPlatformCompat.h"
|
||||
|
||||
// From http://github.com/ars/uicolor-utilities
|
||||
#define CLAMP(val,min,max) MIN(MAX(val,min),max)
|
||||
|
||||
@interface UIColor (UIColor_Expanded)
|
||||
@property (nonatomic, readonly) CGColorSpaceModel colorSpaceModel;
|
||||
@property (nonatomic, readonly) BOOL canProvideRGBComponents;
|
||||
@property (nonatomic, readonly) CGFloat red; // Only valid if canProvideRGBComponents is YES
|
||||
@property (nonatomic, readonly) CGFloat green; // Only valid if canProvideRGBComponents is YES
|
||||
@property (nonatomic, readonly) CGFloat blue; // Only valid if canProvideRGBComponents is YES
|
||||
@property (nonatomic, readonly) CGFloat white; // Only valid if colorSpaceModel == kCGColorSpaceModelMonochrome
|
||||
@property (nonatomic, readonly) CGFloat alpha;
|
||||
@property (nonatomic, readonly) UInt32 rgbHex;
|
||||
|
||||
- (NSString *)LOT_colorSpaceString;
|
||||
|
||||
- (NSArray *)LOT_arrayFromRGBAComponents;
|
||||
|
||||
- (BOOL)LOT_red:(CGFloat *)r green:(CGFloat *)g blue:(CGFloat *)b alpha:(CGFloat *)a;
|
||||
|
||||
- (UIColor *)LOT_colorByLuminanceMapping;
|
||||
|
||||
- (UIColor *)LOT_colorByMultiplyingByRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
|
||||
- (UIColor *) LOT_colorByAddingRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
|
||||
- (UIColor *) LOT_colorByLighteningToRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
|
||||
- (UIColor *) LOT_colorByDarkeningToRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
|
||||
|
||||
- (UIColor *)LOT_colorByMultiplyingBy:(CGFloat)f;
|
||||
- (UIColor *) LOT_colorByAdding:(CGFloat)f;
|
||||
- (UIColor *) LOT_colorByLighteningTo:(CGFloat)f;
|
||||
- (UIColor *) LOT_colorByDarkeningTo:(CGFloat)f;
|
||||
|
||||
- (UIColor *)LOT_colorByMultiplyingByColor:(UIColor *)color;
|
||||
- (UIColor *) LOT_colorByAddingColor:(UIColor *)color;
|
||||
- (UIColor *) LOT_colorByLighteningToColor:(UIColor *)color;
|
||||
- (UIColor *) LOT_colorByDarkeningToColor:(UIColor *)color;
|
||||
|
||||
- (NSString *)LOT_stringFromColor;
|
||||
- (NSString *)LOT_hexStringValue;
|
||||
|
||||
+ (UIColor *)LOT_randomColor;
|
||||
+ (UIColor *)LOT_colorWithString:(NSString *)stringToConvert;
|
||||
+ (UIColor *)LOT_colorWithRGBHex:(UInt32)hex;
|
||||
+ (UIColor *)LOT_colorWithHexString:(NSString *)stringToConvert;
|
||||
|
||||
+ (UIColor *)LOT_colorWithName:(NSString *)cssColorName;
|
||||
|
||||
+ (UIColor *)LOT_colorByLerpingFromColor:(UIColor *)fromColor toColor:(UIColor *)toColor amount:(CGFloat)amount;
|
||||
|
||||
@end
|
||||
480
Pods/lottie-ios/lottie-ios/Classes/Extensions/UIColor+Expanded.m
generated
Normal file
480
Pods/lottie-ios/lottie-ios/Classes/Extensions/UIColor+Expanded.m
generated
Normal file
@@ -0,0 +1,480 @@
|
||||
#import "UIColor+Expanded.h"
|
||||
|
||||
/*
|
||||
|
||||
Thanks to Poltras, Millenomi, Eridius, Nownot, WhatAHam, jberry,
|
||||
and everyone else who helped out but whose name is inadvertently omitted
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Current outstanding request list:
|
||||
|
||||
- PolarBearFarm - color descriptions ([UIColor warmGrayWithHintOfBlueTouchOfRedAndSplashOfYellowColor])
|
||||
- Crayola color set
|
||||
- Eridius - UIColor needs a method that takes 2 colors and gives a third complementary one
|
||||
- Consider UIMutableColor that can be adjusted (brighter, cooler, warmer, thicker-alpha, etc)
|
||||
*/
|
||||
|
||||
/*
|
||||
FOR REFERENCE: Color Space Models: enum CGColorSpaceModel {
|
||||
kCGColorSpaceModelUnknown = -1,
|
||||
kCGColorSpaceModelMonochrome,
|
||||
kCGColorSpaceModelRGB,
|
||||
kCGColorSpaceModelCMYK,
|
||||
kCGColorSpaceModelLab,
|
||||
kCGColorSpaceModelDeviceN,
|
||||
kCGColorSpaceModelIndexed,
|
||||
kCGColorSpaceModelPattern
|
||||
};
|
||||
*/
|
||||
|
||||
// Static cache of looked up color names. Used with +LOT_colorWithName:
|
||||
static NSMutableDictionary *colorNameCache = nil;
|
||||
|
||||
@interface UIColor (UIColor_Expanded_Support)
|
||||
+ (UIColor *)searchForColorByName:(NSString *)cssColorName;
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation UIColor (UIColor_Expanded)
|
||||
|
||||
- (CGColorSpaceModel)colorSpaceModel {
|
||||
return CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor));
|
||||
}
|
||||
|
||||
- (NSString *)LOT_colorSpaceString {
|
||||
switch (self.colorSpaceModel) {
|
||||
case kCGColorSpaceModelUnknown:
|
||||
return @"kCGColorSpaceModelUnknown";
|
||||
case kCGColorSpaceModelMonochrome:
|
||||
return @"kCGColorSpaceModelMonochrome";
|
||||
case kCGColorSpaceModelRGB:
|
||||
return @"kCGColorSpaceModelRGB";
|
||||
case kCGColorSpaceModelCMYK:
|
||||
return @"kCGColorSpaceModelCMYK";
|
||||
case kCGColorSpaceModelLab:
|
||||
return @"kCGColorSpaceModelLab";
|
||||
case kCGColorSpaceModelDeviceN:
|
||||
return @"kCGColorSpaceModelDeviceN";
|
||||
case kCGColorSpaceModelIndexed:
|
||||
return @"kCGColorSpaceModelIndexed";
|
||||
case kCGColorSpaceModelPattern:
|
||||
return @"kCGColorSpaceModelPattern";
|
||||
default:
|
||||
return @"Not a valid color space";
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)canProvideRGBComponents {
|
||||
switch (self.colorSpaceModel) {
|
||||
case kCGColorSpaceModelRGB:
|
||||
case kCGColorSpaceModelMonochrome:
|
||||
return YES;
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)LOT_arrayFromRGBAComponents {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be an RGB color to use -LOT_arrayFromRGBAComponents");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
return [NSArray arrayWithObjects:
|
||||
[NSNumber numberWithFloat:r],
|
||||
[NSNumber numberWithFloat:g],
|
||||
[NSNumber numberWithFloat:b],
|
||||
[NSNumber numberWithFloat:a],
|
||||
nil];
|
||||
}
|
||||
|
||||
- (BOOL)LOT_red:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha {
|
||||
const CGFloat *components = CGColorGetComponents(self.CGColor);
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
|
||||
switch (self.colorSpaceModel) {
|
||||
case kCGColorSpaceModelMonochrome:
|
||||
r = g = b = components[0];
|
||||
a = components[1];
|
||||
break;
|
||||
case kCGColorSpaceModelRGB:
|
||||
r = components[0];
|
||||
g = components[1];
|
||||
b = components[2];
|
||||
a = components[3];
|
||||
break;
|
||||
default: // We don't know how to handle this model
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (red) *red = r;
|
||||
if (green) *green = g;
|
||||
if (blue) *blue = b;
|
||||
if (alpha) *alpha = a;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CGFloat)red {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be an RGB color to use -red");
|
||||
const CGFloat *c = CGColorGetComponents(self.CGColor);
|
||||
return c[0];
|
||||
}
|
||||
|
||||
- (CGFloat)green {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be an RGB color to use -green");
|
||||
const CGFloat *c = CGColorGetComponents(self.CGColor);
|
||||
if (self.colorSpaceModel == kCGColorSpaceModelMonochrome) return c[0];
|
||||
return c[1];
|
||||
}
|
||||
|
||||
- (CGFloat)blue {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be an RGB color to use -blue");
|
||||
const CGFloat *c = CGColorGetComponents(self.CGColor);
|
||||
if (self.colorSpaceModel == kCGColorSpaceModelMonochrome) return c[0];
|
||||
return c[2];
|
||||
}
|
||||
|
||||
- (CGFloat)white {
|
||||
NSAssert(self.colorSpaceModel == kCGColorSpaceModelMonochrome, @"Must be a Monochrome color to use -white");
|
||||
const CGFloat *c = CGColorGetComponents(self.CGColor);
|
||||
return c[0];
|
||||
}
|
||||
|
||||
- (CGFloat)alpha {
|
||||
return CGColorGetAlpha(self.CGColor);
|
||||
}
|
||||
|
||||
- (UInt32)rgbHex {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use rgbHex");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return 0;
|
||||
|
||||
r = MIN(MAX(self.red, 0.0f), 1.0f);
|
||||
g = MIN(MAX(self.green, 0.0f), 1.0f);
|
||||
b = MIN(MAX(self.blue, 0.0f), 1.0f);
|
||||
|
||||
return (((int)roundf(r * 255)) << 16)
|
||||
| (((int)roundf(g * 255)) << 8)
|
||||
| (((int)roundf(b * 255)));
|
||||
}
|
||||
|
||||
#pragma mark Arithmetic operations
|
||||
|
||||
- (UIColor *)LOT_colorByLuminanceMapping {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use arithmetic operations");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
// http://en.wikipedia.org/wiki/Luma_(video)
|
||||
// Y = 0.2126 R + 0.7152 G + 0.0722 B
|
||||
return [UIColor colorWithWhite:r*0.2126f + g*0.7152f + b*0.0722f
|
||||
alpha:a];
|
||||
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByMultiplyingByRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use arithmetic operations");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
return [UIColor colorWithRed:MAX(0.0, MIN(1.0, r * red))
|
||||
green:MAX(0.0, MIN(1.0, g * green))
|
||||
blue:MAX(0.0, MIN(1.0, b * blue))
|
||||
alpha:MAX(0.0, MIN(1.0, a * alpha))];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByAddingRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use arithmetic operations");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
return [UIColor colorWithRed:MAX(0.0, MIN(1.0, r + red))
|
||||
green:MAX(0.0, MIN(1.0, g + green))
|
||||
blue:MAX(0.0, MIN(1.0, b + blue))
|
||||
alpha:MAX(0.0, MIN(1.0, a + alpha))];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByLighteningToRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use arithmetic operations");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
return [UIColor colorWithRed:MAX(r, red)
|
||||
green:MAX(g, green)
|
||||
blue:MAX(b, blue)
|
||||
alpha:MAX(a, alpha)];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByDarkeningToRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use arithmetic operations");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
return [UIColor colorWithRed:MIN(r, red)
|
||||
green:MIN(g, green)
|
||||
blue:MIN(b, blue)
|
||||
alpha:MIN(a, alpha)];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByMultiplyingBy:(CGFloat)f {
|
||||
return [self LOT_colorByMultiplyingByRed:f green:f blue:f alpha:1.0f];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByAdding:(CGFloat)f {
|
||||
return [self LOT_colorByMultiplyingByRed:f green:f blue:f alpha:0.0f];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByLighteningTo:(CGFloat)f {
|
||||
return [self LOT_colorByLighteningToRed:f green:f blue:f alpha:0.0f];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByDarkeningTo:(CGFloat)f {
|
||||
return [self LOT_colorByDarkeningToRed:f green:f blue:f alpha:1.0f];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByMultiplyingByColor:(UIColor *)color {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use arithmetic operations");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
return [self LOT_colorByMultiplyingByRed:r green:g blue:b alpha:1.0f];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByAddingColor:(UIColor *)color {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use arithmetic operations");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
return [self LOT_colorByAddingRed:r green:g blue:b alpha:0.0f];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByLighteningToColor:(UIColor *)color {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use arithmetic operations");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
return [self LOT_colorByLighteningToRed:r green:g blue:b alpha:0.0f];
|
||||
}
|
||||
|
||||
- (UIColor *)LOT_colorByDarkeningToColor:(UIColor *)color {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use arithmetic operations");
|
||||
|
||||
CGFloat r,g,b,a;
|
||||
if (![self LOT_red:&r green:&g blue:&b alpha:&a]) return nil;
|
||||
|
||||
return [self LOT_colorByDarkeningToRed:r green:g blue:b alpha:1.0f];
|
||||
}
|
||||
|
||||
#pragma mark String utilities
|
||||
|
||||
- (NSString *)LOT_stringFromColor {
|
||||
NSAssert(self.canProvideRGBComponents, @"Must be an RGB color to use -LOT_stringFromColor");
|
||||
NSString *result;
|
||||
switch (self.colorSpaceModel) {
|
||||
case kCGColorSpaceModelRGB:
|
||||
result = [NSString stringWithFormat:@"{%0.3f, %0.3f, %0.3f, %0.3f}", self.red, self.green, self.blue, self.alpha];
|
||||
break;
|
||||
case kCGColorSpaceModelMonochrome:
|
||||
result = [NSString stringWithFormat:@"{%0.3f, %0.3f}", self.white, self.alpha];
|
||||
break;
|
||||
default:
|
||||
result = nil;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString *)LOT_hexStringValue {
|
||||
return [NSString stringWithFormat:@"%0.6X", (unsigned int)self.rgbHex];
|
||||
}
|
||||
|
||||
+ (UIColor *)LOT_colorWithString:(NSString *)stringToConvert {
|
||||
NSScanner *scanner = [NSScanner scannerWithString:stringToConvert];
|
||||
if (![scanner scanString:@"{" intoString:NULL]) return nil;
|
||||
const NSUInteger kMaxComponents = 4;
|
||||
float c[kMaxComponents];
|
||||
NSUInteger i = 0;
|
||||
if (![scanner scanFloat:&c[i++]]) return nil;
|
||||
while (1) {
|
||||
if ([scanner scanString:@"}" intoString:NULL]) break;
|
||||
if (i >= kMaxComponents) return nil;
|
||||
if ([scanner scanString:@"," intoString:NULL]) {
|
||||
if (![scanner scanFloat:&c[i++]]) return nil;
|
||||
} else {
|
||||
// either we're at the end of there's an unexpected character here
|
||||
// both cases are error conditions
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
if (![scanner isAtEnd]) return nil;
|
||||
UIColor *color;
|
||||
switch (i) {
|
||||
case 2: // monochrome
|
||||
color = [UIColor colorWithWhite:c[0] alpha:c[1]];
|
||||
break;
|
||||
case 4: // RGB
|
||||
color = [UIColor colorWithRed:c[0] green:c[1] blue:c[2] alpha:c[3]];
|
||||
break;
|
||||
default:
|
||||
color = nil;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
#pragma mark Class methods
|
||||
|
||||
+ (UIColor *)LOT_randomColor {
|
||||
return [UIColor colorWithRed:(CGFloat)random() / (CGFloat)RAND_MAX
|
||||
green:(CGFloat)random() / (CGFloat)RAND_MAX
|
||||
blue:(CGFloat)random() / (CGFloat)RAND_MAX
|
||||
alpha:1.0f];
|
||||
}
|
||||
|
||||
+ (UIColor *)LOT_colorWithRGBHex:(UInt32)hex {
|
||||
int r = (hex >> 16) & 0xFF;
|
||||
int g = (hex >> 8) & 0xFF;
|
||||
int b = (hex) & 0xFF;
|
||||
|
||||
return [UIColor colorWithRed:r / 255.0f
|
||||
green:g / 255.0f
|
||||
blue:b / 255.0f
|
||||
alpha:1.0f];
|
||||
}
|
||||
|
||||
// Returns a UIColor by scanning the string for a hex number and passing that to +[UIColor LOT_colorWithRGBHex:]
|
||||
// Skips any leading whitespace and ignores any trailing characters
|
||||
+ (UIColor *)LOT_colorWithHexString:(NSString *)stringToConvert {
|
||||
NSString *strippedString = [stringToConvert stringByReplacingOccurrencesOfString:@"#" withString:@""];
|
||||
NSScanner *scanner = [NSScanner scannerWithString:strippedString];
|
||||
unsigned hexNum;
|
||||
if (![scanner scanHexInt:&hexNum]) return nil;
|
||||
return [UIColor LOT_colorWithRGBHex:hexNum];
|
||||
}
|
||||
|
||||
// Lookup a color using css 3/svg color name
|
||||
+ (UIColor *)LOT_colorWithName:(NSString *)cssColorName {
|
||||
UIColor *color;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
colorNameCache = [[NSMutableDictionary alloc] init];
|
||||
});
|
||||
|
||||
@synchronized(colorNameCache) {
|
||||
// Look for the color in the cache
|
||||
color = [colorNameCache objectForKey:cssColorName];
|
||||
|
||||
if ((id)color == [NSNull null]) {
|
||||
// If it wasn't there previously, it's still not there now
|
||||
color = nil;
|
||||
} else if (!color) {
|
||||
// Color not in cache, so search for it now
|
||||
color = [self searchForColorByName:cssColorName];
|
||||
|
||||
// Set the value in cache, storing NSNull on failure
|
||||
[colorNameCache setObject:(color ?: (id)[NSNull null])
|
||||
forKey:cssColorName];
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
+ (UIColor *)LOT_colorByLerpingFromColor:(UIColor *)fromColor toColor:(UIColor *)toColor amount:(CGFloat)amount {
|
||||
NSAssert((toColor != nil && fromColor != nil), @"Passing Nil Color");
|
||||
amount = CLAMP(amount, 0.f, 1.f);
|
||||
const CGFloat *fromComponents = CGColorGetComponents(fromColor.CGColor);
|
||||
const CGFloat *toComponents = CGColorGetComponents(toColor.CGColor);
|
||||
float r = fromComponents[0] + ((toComponents[0] - fromComponents[0]) * amount);
|
||||
float g = fromComponents[1] + ((toComponents[1] - fromComponents[1]) * amount);
|
||||
float b = fromComponents[2] + ((toComponents[2] - fromComponents[2]) * amount);
|
||||
float a = fromComponents[3] + ((toComponents[3] - fromComponents[3]) * amount);
|
||||
return [UIColor colorWithRed:r green:g blue:b alpha:a];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation UIColor (UIColor_Expanded_Support)
|
||||
/*
|
||||
* Database of color names and hex rgb values, derived
|
||||
* from the css 3 color spec:
|
||||
* http://www.w3.org/TR/css3-color/
|
||||
*
|
||||
* We think this is a very compact way of storing
|
||||
* this information, and relatively cheap to lookup.
|
||||
*
|
||||
* Note that we search for color names starting with ','
|
||||
* and terminated by '#', so that we don't get false matches.
|
||||
* For this reason, the database begins with ','.
|
||||
*/
|
||||
static const char *colorNameDB = ","
|
||||
"aliceblue#f0f8ff,antiquewhite#faebd7,aqua#00ffff,aquamarine#7fffd4,azure#f0ffff,"
|
||||
"beige#f5f5dc,bisque#ffe4c4,black#000000,blanchedalmond#ffebcd,blue#0000ff,"
|
||||
"blueviolet#8a2be2,brown#a52a2a,burlywood#deb887,cadetblue#5f9ea0,chartreuse#7fff00,"
|
||||
"chocolate#d2691e,coral#ff7f50,cornflowerblue#6495ed,cornsilk#fff8dc,crimson#dc143c,"
|
||||
"cyan#00ffff,darkblue#00008b,darkcyan#008b8b,darkgoldenrod#b8860b,darkgray#a9a9a9,"
|
||||
"darkgreen#006400,darkgrey#a9a9a9,darkkhaki#bdb76b,darkmagenta#8b008b,"
|
||||
"darkolivegreen#556b2f,darkorange#ff8c00,darkorchid#9932cc,darkred#8b0000,"
|
||||
"darksalmon#e9967a,darkseagreen#8fbc8f,darkslateblue#483d8b,darkslategray#2f4f4f,"
|
||||
"darkslategrey#2f4f4f,darkturquoise#00ced1,darkviolet#9400d3,deeppink#ff1493,"
|
||||
"deepskyblue#00bfff,dimgray#696969,dimgrey#696969,dodgerblue#1e90ff,"
|
||||
"firebrick#b22222,floralwhite#fffaf0,forestgreen#228b22,fuchsia#ff00ff,"
|
||||
"gainsboro#dcdcdc,ghostwhite#f8f8ff,gold#ffd700,goldenrod#daa520,gray#808080,"
|
||||
"green#008000,greenyellow#adff2f,grey#808080,honeydew#f0fff0,hotpink#ff69b4,"
|
||||
"indianred#cd5c5c,indigo#4b0082,ivory#fffff0,khaki#f0e68c,lavender#e6e6fa,"
|
||||
"lavenderblush#fff0f5,lawngreen#7cfc00,lemonchiffon#fffacd,lightblue#add8e6,"
|
||||
"lightcoral#f08080,lightcyan#e0ffff,lightgoldenrodyellow#fafad2,lightgray#d3d3d3,"
|
||||
"lightgreen#90ee90,lightgrey#d3d3d3,lightpink#ffb6c1,lightsalmon#ffa07a,"
|
||||
"lightseagreen#20b2aa,lightskyblue#87cefa,lightslategray#778899,"
|
||||
"lightslategrey#778899,lightsteelblue#b0c4de,lightyellow#ffffe0,lime#00ff00,"
|
||||
"limegreen#32cd32,linen#faf0e6,magenta#ff00ff,maroon#800000,mediumaquamarine#66cdaa,"
|
||||
"mediumblue#0000cd,mediumorchid#ba55d3,mediumpurple#9370db,mediumseagreen#3cb371,"
|
||||
"mediumslateblue#7b68ee,mediumspringgreen#00fa9a,mediumturquoise#48d1cc,"
|
||||
"mediumvioletred#c71585,midnightblue#191970,mintcream#f5fffa,mistyrose#ffe4e1,"
|
||||
"moccasin#ffe4b5,navajowhite#ffdead,navy#000080,oldlace#fdf5e6,olive#808000,"
|
||||
"olivedrab#6b8e23,orange#ffa500,orangered#ff4500,orchid#da70d6,palegoldenrod#eee8aa,"
|
||||
"palegreen#98fb98,paleturquoise#afeeee,palevioletred#db7093,papayawhip#ffefd5,"
|
||||
"peachpuff#ffdab9,peru#cd853f,pink#ffc0cb,plum#dda0dd,powderblue#b0e0e6,"
|
||||
"purple#800080,red#ff0000,rosybrown#bc8f8f,royalblue#4169e1,saddlebrown#8b4513,"
|
||||
"salmon#fa8072,sandybrown#f4a460,seagreen#2e8b57,seashell#fff5ee,sienna#a0522d,"
|
||||
"silver#c0c0c0,skyblue#87ceeb,slateblue#6a5acd,slategray#708090,slategrey#708090,"
|
||||
"snow#fffafa,springgreen#00ff7f,steelblue#4682b4,tan#d2b48c,teal#008080,"
|
||||
"thistle#d8bfd8,tomato#ff6347,turquoise#40e0d0,violet#ee82ee,wheat#f5deb3,"
|
||||
"white#ffffff,whitesmoke#f5f5f5,yellow#ffff00,yellowgreen#9acd32";
|
||||
|
||||
+ (UIColor *)searchForColorByName:(NSString *)cssColorName {
|
||||
UIColor *result = nil;
|
||||
|
||||
// Compile the string we'll use to search against the database
|
||||
// We search for ",<colorname>#" to avoid false matches
|
||||
const char *searchString = [[NSString stringWithFormat:@",%@#", cssColorName] UTF8String];
|
||||
|
||||
// Search for the color name
|
||||
const char *found = strstr(colorNameDB, searchString);
|
||||
|
||||
// If found, step past the search string and grab the hex representation
|
||||
if (found) {
|
||||
const char *after = found + strlen(searchString);
|
||||
int hex;
|
||||
if (sscanf(after, "%x", &hex) == 1) {
|
||||
result = [self LOT_colorWithRGBHex:hex];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@end
|
||||
18
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/CALayer+Compat.h
generated
Normal file
18
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/CALayer+Compat.h
generated
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Created by Oleksii Pavlovskyi on 2/2/17.
|
||||
// Copyright (c) 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
@interface CALayer (Compat)
|
||||
|
||||
@property (nonatomic, assign) BOOL allowsEdgeAntialiasing;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
18
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/CALayer+Compat.m
generated
Normal file
18
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/CALayer+Compat.m
generated
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Created by Oleksii Pavlovskyi on 2/2/17.
|
||||
// Copyright (c) 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import "CALayer+Compat.h"
|
||||
|
||||
@implementation CALayer (Compat)
|
||||
|
||||
- (BOOL)allowsEdgeAntialiasing { return NO; }
|
||||
- (void)setAllowsEdgeAntialiasing:(BOOL)allowsEdgeAntialiasing { }
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
37
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/LOTPlatformCompat.h
generated
Normal file
37
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/LOTPlatformCompat.h
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// LOTPlatformCompat.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by Oleksii Pavlovskyi on 2/2/17.
|
||||
// Copyright (c) 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef LOTPlatformCompat_h
|
||||
#define LOTPlatformCompat_h
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#else
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import "UIColor.h"
|
||||
#import "CALayer+Compat.h"
|
||||
#import "NSValue+Compat.h"
|
||||
#import "UIBezierPath.h"
|
||||
|
||||
NS_INLINE NSString *NSStringFromCGRect(CGRect rect) {
|
||||
return NSStringFromRect(rect);
|
||||
}
|
||||
|
||||
NS_INLINE NSString *NSStringFromCGPoint(CGPoint point) {
|
||||
return NSStringFromPoint(point);
|
||||
}
|
||||
|
||||
typedef NSEdgeInsets UIEdgeInsets;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
22
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/NSValue+Compat.h
generated
Normal file
22
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/NSValue+Compat.h
generated
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by Oleksii Pavlovskyi on 2/2/17.
|
||||
// Copyright (c) 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSValue (Compat)
|
||||
|
||||
+ (NSValue *)valueWithCGRect:(CGRect)rect;
|
||||
+ (NSValue *)valueWithCGPoint:(CGPoint)point;
|
||||
|
||||
@property (nonatomic, readonly) CGRect CGRectValue;
|
||||
@property(nonatomic, readonly) CGPoint CGPointValue;
|
||||
@property (nonatomic, readonly) CGSize CGSizeValue;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
35
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/NSValue+Compat.m
generated
Normal file
35
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/NSValue+Compat.m
generated
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Created by Oleksii Pavlovskyi on 2/2/17.
|
||||
// Copyright (c) 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import "NSValue+Compat.h"
|
||||
|
||||
@implementation NSValue (Compat)
|
||||
|
||||
+ (NSValue *)valueWithCGRect:(CGRect)rect {
|
||||
return [self valueWithRect:rect];
|
||||
}
|
||||
|
||||
+ (NSValue *)valueWithCGPoint:(CGPoint)point {
|
||||
return [self valueWithPoint:point];
|
||||
}
|
||||
|
||||
- (CGRect)CGRectValue {
|
||||
return self.rectValue;
|
||||
}
|
||||
|
||||
- (CGPoint)CGPointValue {
|
||||
return self.pointValue;
|
||||
}
|
||||
|
||||
- (CGSize)CGSizeValue {
|
||||
return self.sizeValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
80
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/UIBezierPath.h
generated
Executable file
80
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/UIBezierPath.h
generated
Executable file
@@ -0,0 +1,80 @@
|
||||
// Kindly stolen from https://github.com/BigZaphod/Chameleon
|
||||
/*
|
||||
* Copyright (c) 2011, The Iconfactory. 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.
|
||||
*
|
||||
* 3. Neither the name of The Iconfactory nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE ICONFACTORY 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.
|
||||
*/
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
|
||||
UIRectCornerTopLeft = 1 << 0,
|
||||
UIRectCornerTopRight = 1 << 1,
|
||||
UIRectCornerBottomLeft = 1 << 2,
|
||||
UIRectCornerBottomRight = 1 << 3,
|
||||
UIRectCornerAllCorners = UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight
|
||||
};
|
||||
|
||||
@interface UIBezierPath : NSObject <NSCopying>
|
||||
|
||||
+ (UIBezierPath *)bezierPath;
|
||||
+ (UIBezierPath *)bezierPathWithRect:(CGRect)rect;
|
||||
+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect;
|
||||
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;
|
||||
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
|
||||
+ (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
|
||||
+ (UIBezierPath *)bezierPathWithCGPath:(CGPathRef)CGPath;
|
||||
|
||||
- (void)moveToPoint:(CGPoint)point;
|
||||
- (void)addLineToPoint:(CGPoint)point;
|
||||
- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
|
||||
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
|
||||
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;
|
||||
- (void)closePath;
|
||||
- (void)removeAllPoints;
|
||||
- (void)appendPath:(UIBezierPath *)bezierPath;
|
||||
- (void)setLineDash:(const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase;
|
||||
- (void)getLineDash:(CGFloat *)pattern count:(NSInteger *)count phase:(CGFloat *)phase;
|
||||
- (BOOL)containsPoint:(CGPoint)point;
|
||||
- (void)applyTransform:(CGAffineTransform)transform;
|
||||
|
||||
@property (nonatomic) CGPathRef CGPath;
|
||||
@property (nonatomic, readonly) CGPoint currentPoint;
|
||||
@property (nonatomic) CGFloat lineWidth;
|
||||
@property (nonatomic) CGLineCap lineCapStyle;
|
||||
@property (nonatomic) CGLineJoin lineJoinStyle;
|
||||
@property (nonatomic) CGFloat miterLimit;
|
||||
@property (nonatomic) CGFloat flatness;
|
||||
@property (nonatomic) BOOL usesEvenOddFillRule;
|
||||
@property (readonly, getter=isEmpty) BOOL empty;
|
||||
@property (nonatomic, readonly) CGRect bounds;
|
||||
@end
|
||||
|
||||
#endif
|
||||
312
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/UIBezierPath.m
generated
Executable file
312
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/UIBezierPath.m
generated
Executable file
@@ -0,0 +1,312 @@
|
||||
// Kindly stolen from https://github.com/BigZaphod/Chameleon
|
||||
/*
|
||||
* Copyright (c) 2011, The Iconfactory. 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.
|
||||
*
|
||||
* 3. Neither the name of The Iconfactory nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE ICONFACTORY 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.
|
||||
*/
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import "UIBezierPath.h"
|
||||
|
||||
@implementation UIBezierPath {
|
||||
CGFloat *_lineDashPattern;
|
||||
NSInteger _lineDashCount;
|
||||
CGFloat _lineDashPhase;
|
||||
}
|
||||
@synthesize CGPath = _path;
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_path = CGPathCreateMutable();
|
||||
_lineWidth = 1;
|
||||
_lineCapStyle = kCGLineCapButt;
|
||||
_lineJoinStyle = kCGLineJoinMiter;
|
||||
_miterLimit = 10;
|
||||
_flatness = 0.6;
|
||||
_usesEvenOddFillRule = NO;
|
||||
_lineDashPattern = NULL;
|
||||
_lineDashCount = 0;
|
||||
_lineDashPhase = 0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (_path) CGPathRelease(_path);
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
UIBezierPath *copy = [[self class] new];
|
||||
|
||||
copy.CGPath = self.CGPath;
|
||||
copy.lineWidth = self.lineWidth;
|
||||
copy.lineCapStyle = self.lineCapStyle;
|
||||
copy.lineJoinStyle = self.lineJoinStyle;
|
||||
copy.miterLimit = self.miterLimit;
|
||||
copy.flatness = self.flatness;
|
||||
copy.usesEvenOddFillRule = self.usesEvenOddFillRule;
|
||||
|
||||
NSInteger lineDashCount = 0;
|
||||
[self getLineDash:NULL count:&lineDashCount phase:NULL];
|
||||
|
||||
if (lineDashCount > 0) {
|
||||
CGFloat *lineDashPattern = malloc(sizeof(CGFloat) * lineDashCount);
|
||||
CGFloat lineDashPhase = 0;
|
||||
[self getLineDash:lineDashPattern count:NULL phase:&lineDashPhase];
|
||||
[copy setLineDash:lineDashPattern count:lineDashCount phase:lineDashPhase];
|
||||
free(lineDashPattern);
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
+ (UIBezierPath *)bezierPathWithCGPath:(CGPathRef)CGPath {
|
||||
NSAssert(CGPath != NULL, @"CGPath must not be NULL");
|
||||
UIBezierPath *bezierPath = [[self alloc] init];
|
||||
bezierPath.CGPath = CGPath;
|
||||
return bezierPath;
|
||||
}
|
||||
|
||||
+ (UIBezierPath *)bezierPath {
|
||||
UIBezierPath *bezierPath = [[self alloc] init];
|
||||
return bezierPath;
|
||||
}
|
||||
|
||||
+ (UIBezierPath *)bezierPathWithRect:(CGRect)rect {
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGPathAddRect(path, NULL, rect);
|
||||
|
||||
UIBezierPath *bezierPath = [[self alloc] init];
|
||||
bezierPath->_path = path;
|
||||
return bezierPath;
|
||||
}
|
||||
|
||||
+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect {
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGPathAddEllipseInRect(path, NULL, rect);
|
||||
|
||||
UIBezierPath *bezierPath = [[self alloc] init];
|
||||
bezierPath->_path = path;
|
||||
return bezierPath;
|
||||
}
|
||||
|
||||
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect
|
||||
cornerRadius:(CGFloat)cornerRadius {
|
||||
return [self bezierPathWithRoundedRect:rect
|
||||
byRoundingCorners:UIRectCornerAllCorners
|
||||
cornerRadii:CGSizeMake(cornerRadius, cornerRadius)];
|
||||
}
|
||||
|
||||
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect
|
||||
byRoundingCorners:(UIRectCorner)corners
|
||||
cornerRadii:(CGSize)cornerRadii {
|
||||
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
|
||||
const CGPoint topLeft = rect.origin;
|
||||
const CGPoint topRight = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
|
||||
const CGPoint bottomRight = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
|
||||
const CGPoint bottomLeft = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
|
||||
|
||||
if (corners & UIRectCornerTopLeft) {
|
||||
CGPathMoveToPoint(path, NULL, topLeft.x + cornerRadii.width, topLeft.y);
|
||||
} else {
|
||||
CGPathMoveToPoint(path, NULL, topLeft.x, topLeft.y);
|
||||
}
|
||||
|
||||
if (corners & UIRectCornerTopRight) {
|
||||
CGPathAddLineToPoint(path, NULL, topRight.x - cornerRadii.width, topRight.y);
|
||||
CGPathAddCurveToPoint(path, NULL, topRight.x, topRight.y, topRight.x, topRight.y + cornerRadii.height, topRight.x, topRight.y + cornerRadii.height);
|
||||
} else {
|
||||
CGPathAddLineToPoint(path, NULL, topRight.x, topRight.y);
|
||||
}
|
||||
|
||||
if (corners & UIRectCornerBottomRight) {
|
||||
CGPathAddLineToPoint(path, NULL, bottomRight.x, bottomRight.y - cornerRadii.height);
|
||||
CGPathAddCurveToPoint(path, NULL, bottomRight.x, bottomRight.y, bottomRight.x - cornerRadii.width, bottomRight.y, bottomRight.x - cornerRadii.width, bottomRight.y);
|
||||
} else {
|
||||
CGPathAddLineToPoint(path, NULL, bottomRight.x, bottomRight.y);
|
||||
}
|
||||
|
||||
if (corners & UIRectCornerBottomLeft) {
|
||||
CGPathAddLineToPoint(path, NULL, bottomLeft.x + cornerRadii.width, bottomLeft.y);
|
||||
CGPathAddCurveToPoint(path, NULL, bottomLeft.x, bottomLeft.y, bottomLeft.x, bottomLeft.y - cornerRadii.height, bottomLeft.x, bottomLeft.y - cornerRadii.height);
|
||||
} else {
|
||||
CGPathAddLineToPoint(path, NULL, bottomLeft.x, bottomLeft.y);
|
||||
}
|
||||
|
||||
if (corners & UIRectCornerTopLeft) {
|
||||
CGPathAddLineToPoint(path, NULL, topLeft.x, topLeft.y + cornerRadii.height);
|
||||
CGPathAddCurveToPoint(path, NULL, topLeft.x, topLeft.y, topLeft.x + cornerRadii.width, topLeft.y, topLeft.x + cornerRadii.width, topLeft.y);
|
||||
} else {
|
||||
CGPathAddLineToPoint(path, NULL, topLeft.x, topLeft.y);
|
||||
}
|
||||
|
||||
CGPathCloseSubpath(path);
|
||||
|
||||
UIBezierPath *bezierPath = [[self alloc] init];
|
||||
bezierPath->_path = path;
|
||||
return bezierPath;
|
||||
}
|
||||
|
||||
+ (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center
|
||||
radius:(CGFloat)radius
|
||||
startAngle:(CGFloat)startAngle
|
||||
endAngle:(CGFloat)endAngle
|
||||
clockwise:(BOOL)clockwise {
|
||||
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGPathAddArc(path, NULL, center.x, center.y, radius, startAngle, endAngle, clockwise);
|
||||
|
||||
UIBezierPath *bezierPath = [[self alloc] init];
|
||||
bezierPath->_path = path;
|
||||
return bezierPath;
|
||||
}
|
||||
|
||||
- (void)moveToPoint:(CGPoint)point {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutableCopy(_path);
|
||||
CGPathMoveToPoint(mutablePath, NULL, point.x, point.y);
|
||||
self.CGPath = mutablePath;
|
||||
CGPathRelease(mutablePath);
|
||||
}
|
||||
|
||||
- (void)addLineToPoint:(CGPoint)point {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutableCopy(_path);
|
||||
CGPathAddLineToPoint(mutablePath, NULL, point.x, point.y);
|
||||
self.CGPath = mutablePath;
|
||||
CGPathRelease(mutablePath);
|
||||
}
|
||||
|
||||
- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutableCopy(_path);
|
||||
CGPathAddArc(mutablePath, NULL, center.x, center.y, radius, startAngle, endAngle, clockwise);
|
||||
self.CGPath = mutablePath;
|
||||
CGPathRelease(mutablePath);
|
||||
}
|
||||
|
||||
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2 {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutableCopy(_path);
|
||||
CGPathAddCurveToPoint(mutablePath, NULL, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y);
|
||||
self.CGPath = mutablePath;
|
||||
CGPathRelease(mutablePath);
|
||||
}
|
||||
|
||||
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutableCopy(_path);
|
||||
CGPathAddQuadCurveToPoint(mutablePath, NULL, controlPoint.x, controlPoint.y, endPoint.x, endPoint.y);
|
||||
self.CGPath = mutablePath;
|
||||
CGPathRelease(mutablePath);
|
||||
}
|
||||
|
||||
- (void)closePath {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutableCopy(_path);
|
||||
CGPathCloseSubpath(mutablePath);
|
||||
self.CGPath = mutablePath;
|
||||
CGPathRelease(mutablePath);
|
||||
}
|
||||
|
||||
- (void)removeAllPoints {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutable();
|
||||
self.CGPath = mutablePath;
|
||||
CGPathRelease(mutablePath);
|
||||
}
|
||||
|
||||
- (void)appendPath:(UIBezierPath *)bezierPath {
|
||||
if (bezierPath) {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutableCopy(_path);
|
||||
CGPathAddPath(mutablePath, NULL, bezierPath.CGPath);
|
||||
self.CGPath = mutablePath;
|
||||
CGPathRelease(mutablePath);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setCGPath:(CGPathRef)path {
|
||||
NSAssert(path != NULL, @"path must not be NULL");
|
||||
if (path != _path) {
|
||||
if (_path) CGPathRelease(_path);
|
||||
_path = CGPathCreateCopy(path);
|
||||
}
|
||||
}
|
||||
|
||||
- (CGPoint)currentPoint {
|
||||
return CGPathGetCurrentPoint(_path);
|
||||
}
|
||||
|
||||
- (void)setLineDash:(const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase {
|
||||
free(_lineDashPattern);
|
||||
|
||||
if (pattern && count > 0) {
|
||||
const size_t size = sizeof(CGFloat) * count;
|
||||
_lineDashPattern = malloc(size);
|
||||
bcopy(pattern, _lineDashPattern, size);
|
||||
} else {
|
||||
_lineDashPattern = NULL;
|
||||
}
|
||||
|
||||
_lineDashCount = count;
|
||||
_lineDashPhase = phase;
|
||||
}
|
||||
|
||||
- (void)getLineDash:(CGFloat *)pattern count:(NSInteger *)count phase:(CGFloat *)phase {
|
||||
if (pattern && _lineDashPattern && _lineDashCount > 0) {
|
||||
const size_t size = sizeof(CGFloat) * _lineDashCount;
|
||||
bcopy(_lineDashPattern, pattern, size);
|
||||
}
|
||||
|
||||
if (count) {
|
||||
*count = _lineDashCount;
|
||||
}
|
||||
|
||||
if (phase) {
|
||||
*phase = _lineDashPhase;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)containsPoint:(CGPoint)point {
|
||||
return CGPathContainsPoint(_path, NULL, point, _usesEvenOddFillRule);
|
||||
}
|
||||
|
||||
- (BOOL)isEmpty {
|
||||
return CGPathIsEmpty(_path);
|
||||
}
|
||||
|
||||
- (CGRect)bounds {
|
||||
return CGPathGetBoundingBox(_path);
|
||||
}
|
||||
|
||||
- (void)applyTransform:(CGAffineTransform)transform {
|
||||
CGMutablePathRef mutablePath = CGPathCreateMutable();
|
||||
CGPathAddPath(mutablePath, &transform, _path);
|
||||
self.CGPath = mutablePath;
|
||||
CGPathRelease(mutablePath);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
44
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/UIColor.h
generated
Normal file
44
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/UIColor.h
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// UIColor.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by Oleksii Pavlovskyi on 2/2/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
@interface UIColor : NSObject <NSCopying>
|
||||
|
||||
+ (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha;
|
||||
+ (UIColor *)colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha;
|
||||
+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
|
||||
+ (UIColor *)colorWithCGColor:(CGColorRef)cgColor;
|
||||
|
||||
+ (UIColor *)blackColor;
|
||||
+ (UIColor *)darkGrayColor;
|
||||
+ (UIColor *)lightGrayColor;
|
||||
+ (UIColor *)whiteColor;
|
||||
+ (UIColor *)grayColor;
|
||||
+ (UIColor *)redColor;
|
||||
+ (UIColor *)greenColor;
|
||||
+ (UIColor *)blueColor;
|
||||
+ (UIColor *)cyanColor;
|
||||
+ (UIColor *)yellowColor;
|
||||
+ (UIColor *)magentaColor;
|
||||
+ (UIColor *)orangeColor;
|
||||
+ (UIColor *)purpleColor;
|
||||
+ (UIColor *)brownColor;
|
||||
+ (UIColor *)clearColor;
|
||||
|
||||
- (UIColor *)colorWithAlphaComponent:(CGFloat)alpha;
|
||||
|
||||
@property (nonatomic, readonly) CGColorRef CGColor;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
158
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/UIColor.m
generated
Normal file
158
Pods/lottie-ios/lottie-ios/Classes/MacCompatibility/UIColor.m
generated
Normal file
@@ -0,0 +1,158 @@
|
||||
//
|
||||
// UIColor.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by Oleksii Pavlovskyi on 2/2/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
|
||||
#import "UIColor.h"
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
#define StaticColor(staticColor) \
|
||||
static UIColor *color = nil; \
|
||||
static dispatch_once_t onceToken; \
|
||||
dispatch_once(&onceToken, ^{ \
|
||||
color = NSColor.staticColor.UIColor; \
|
||||
}); \
|
||||
return color; \
|
||||
|
||||
@interface UIColor ()
|
||||
|
||||
@property (nonatomic, strong) NSColor *color;
|
||||
|
||||
- (instancetype)initWithNSColor:(NSColor *)color;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSColor (UIColor)
|
||||
|
||||
@property (nonatomic, readonly) UIColor *UIColor;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIColor
|
||||
|
||||
- (instancetype)initWithNSColor:(NSColor *)color {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.color = color;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (UIColor *)colorWithNSColor:(NSColor *)color {
|
||||
return [[self alloc] initWithNSColor:color];
|
||||
}
|
||||
|
||||
+ (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha {
|
||||
return [[NSColor colorWithWhite:white alpha:alpha] UIColor];
|
||||
}
|
||||
|
||||
+ (UIColor *)colorWithHue:(CGFloat)hue
|
||||
saturation:(CGFloat)saturation
|
||||
brightness:(CGFloat)brightness
|
||||
alpha:(CGFloat)alpha {
|
||||
return [[NSColor colorWithHue:hue
|
||||
saturation:saturation
|
||||
brightness:brightness
|
||||
alpha:alpha] UIColor];
|
||||
}
|
||||
|
||||
+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha {
|
||||
return [[NSColor colorWithRed:red
|
||||
green:green
|
||||
blue:blue
|
||||
alpha:alpha] UIColor];
|
||||
}
|
||||
|
||||
+ (UIColor *)colorWithCGColor:(CGColorRef)cgColor {
|
||||
return [[NSColor colorWithCGColor:cgColor] UIColor];
|
||||
}
|
||||
|
||||
+ (UIColor *)blackColor {
|
||||
StaticColor(blackColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)darkGrayColor {
|
||||
StaticColor(darkGrayColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)lightGrayColor {
|
||||
StaticColor(lightGrayColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)whiteColor {
|
||||
StaticColor(whiteColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)grayColor {
|
||||
StaticColor(grayColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)redColor {
|
||||
StaticColor(redColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)greenColor {
|
||||
StaticColor(greenColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)blueColor {
|
||||
StaticColor(blueColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)cyanColor {
|
||||
StaticColor(cyanColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)yellowColor {
|
||||
StaticColor(yellowColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)magentaColor {
|
||||
StaticColor(magentaColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)orangeColor {
|
||||
StaticColor(orangeColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)purpleColor {
|
||||
StaticColor(purpleColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)brownColor {
|
||||
StaticColor(brownColor)
|
||||
}
|
||||
|
||||
+ (UIColor *)clearColor {
|
||||
StaticColor(clearColor)
|
||||
}
|
||||
|
||||
- (CGColorRef)CGColor {
|
||||
return self.color.CGColor;
|
||||
}
|
||||
|
||||
- (UIColor *)colorWithAlphaComponent:(CGFloat)alpha {
|
||||
return [self.color colorWithAlphaComponent:alpha].UIColor;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
return [[self.color copyWithZone:zone] UIColor];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSColor (UIColor)
|
||||
|
||||
- (UIColor *)UIColor {
|
||||
return [UIColor colorWithNSColor:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
38
Pods/lottie-ios/lottie-ios/Classes/Models/LOTAsset.h
generated
Normal file
38
Pods/lottie-ios/lottie-ios/Classes/Models/LOTAsset.h
generated
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// LOTAsset.h
|
||||
// Pods
|
||||
//
|
||||
// Created by Brandon Withrow on 2/16/17.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class LOTLayerGroup;
|
||||
@class LOTLayer;
|
||||
@class LOTAssetGroup;
|
||||
|
||||
@interface LOTAsset : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withAssetBundle:(NSBundle *_Nonnull)bundle
|
||||
withFramerate:(NSNumber *)framerate;
|
||||
|
||||
@property (nonatomic, readonly, nullable) NSString *referenceID;
|
||||
@property (nonatomic, readonly, nullable) NSNumber *assetWidth;
|
||||
@property (nonatomic, readonly, nullable) NSNumber *assetHeight;
|
||||
|
||||
@property (nonatomic, readonly, nullable) NSString *imageName;
|
||||
@property (nonatomic, readonly, nullable) NSString *imageDirectory;
|
||||
|
||||
@property (nonatomic, readonly, nullable) LOTLayerGroup *layerGroup;
|
||||
|
||||
@property (nonatomic, readwrite) NSString *rootDirectory;
|
||||
@property (nonatomic, readonly) NSBundle *assetBundle;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
59
Pods/lottie-ios/lottie-ios/Classes/Models/LOTAsset.m
generated
Normal file
59
Pods/lottie-ios/lottie-ios/Classes/Models/LOTAsset.m
generated
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// LOTAsset.m
|
||||
// Pods
|
||||
//
|
||||
// Created by Brandon Withrow on 2/16/17.
|
||||
//
|
||||
//
|
||||
|
||||
#import "LOTAsset.h"
|
||||
#import "LOTLayer.h"
|
||||
#import "LOTLayerGroup.h"
|
||||
#import "LOTAssetGroup.h"
|
||||
|
||||
@implementation LOTAsset
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withAssetBundle:(NSBundle *_Nonnull)bundle
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_assetBundle = bundle;
|
||||
[self _mapFromJSON:jsonDictionary
|
||||
withAssetGroup:assetGroup
|
||||
withFramerate:framerate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
_referenceID = [jsonDictionary[@"id"] copy];
|
||||
|
||||
if (jsonDictionary[@"w"]) {
|
||||
_assetWidth = [jsonDictionary[@"w"] copy];
|
||||
}
|
||||
|
||||
if (jsonDictionary[@"h"]) {
|
||||
_assetHeight = [jsonDictionary[@"h"] copy];
|
||||
}
|
||||
|
||||
if (jsonDictionary[@"u"]) {
|
||||
_imageDirectory = [jsonDictionary[@"u"] copy];
|
||||
}
|
||||
|
||||
if (jsonDictionary[@"p"]) {
|
||||
_imageName = [jsonDictionary[@"p"] copy];
|
||||
}
|
||||
|
||||
NSArray *layersJSON = jsonDictionary[@"layers"];
|
||||
if (layersJSON) {
|
||||
_layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON
|
||||
withAssetGroup:assetGroup
|
||||
withFramerate:framerate];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
28
Pods/lottie-ios/lottie-ios/Classes/Models/LOTAssetGroup.h
generated
Normal file
28
Pods/lottie-ios/lottie-ios/Classes/Models/LOTAssetGroup.h
generated
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// LOTAssetGroup.h
|
||||
// Pods
|
||||
//
|
||||
// Created by Brandon Withrow on 2/17/17.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
@class LOTAsset;
|
||||
@class LOTLayerGroup;
|
||||
@interface LOTAssetGroup : NSObject
|
||||
@property (nonatomic, readwrite) NSString * _Nullable rootDirectory;
|
||||
@property (nonatomic, readonly, nullable) NSBundle *assetBundle;
|
||||
|
||||
- (instancetype _Nonnull)initWithJSON:(NSArray * _Nonnull)jsonArray
|
||||
withAssetBundle:(NSBundle *_Nullable)bundle
|
||||
withFramerate:(NSNumber * _Nonnull)framerate;
|
||||
|
||||
- (void)buildAssetNamed:(NSString * _Nonnull)refID withFramerate:(NSNumber * _Nonnull)framerate;
|
||||
|
||||
- (void)finalizeInitializationWithFramerate:(NSNumber * _Nonnull)framerate;
|
||||
|
||||
- (LOTAsset * _Nullable)assetModelForID:(NSString * _Nonnull)assetID;
|
||||
|
||||
@end
|
||||
70
Pods/lottie-ios/lottie-ios/Classes/Models/LOTAssetGroup.m
generated
Normal file
70
Pods/lottie-ios/lottie-ios/Classes/Models/LOTAssetGroup.m
generated
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// LOTAssetGroup.m
|
||||
// Pods
|
||||
//
|
||||
// Created by Brandon Withrow on 2/17/17.
|
||||
//
|
||||
//
|
||||
|
||||
#import "LOTAssetGroup.h"
|
||||
#import "LOTAsset.h"
|
||||
|
||||
@implementation LOTAssetGroup {
|
||||
NSMutableDictionary<NSString *, LOTAsset *> *_assetMap;
|
||||
NSDictionary<NSString *, NSDictionary *> *_assetJSONMap;
|
||||
}
|
||||
|
||||
- (instancetype _Nonnull)initWithJSON:(NSArray * _Nonnull)jsonArray
|
||||
withAssetBundle:(NSBundle * _Nullable)bundle
|
||||
withFramerate:(NSNumber * _Nonnull)framerate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_assetBundle = bundle;
|
||||
_assetMap = [NSMutableDictionary dictionary];
|
||||
NSMutableDictionary *assetJSONMap = [NSMutableDictionary dictionary];
|
||||
for (NSDictionary<NSString *, NSString *> *assetDictionary in jsonArray) {
|
||||
NSString *referenceID = assetDictionary[@"id"];
|
||||
if (referenceID) {
|
||||
assetJSONMap[referenceID] = assetDictionary;
|
||||
}
|
||||
}
|
||||
_assetJSONMap = assetJSONMap;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)buildAssetNamed:(NSString *)refID
|
||||
withFramerate:(NSNumber * _Nonnull)framerate {
|
||||
|
||||
if ([self assetModelForID:refID]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSDictionary *assetDictionary = _assetJSONMap[refID];
|
||||
if (assetDictionary) {
|
||||
LOTAsset *asset = [[LOTAsset alloc] initWithJSON:assetDictionary
|
||||
withAssetGroup:self
|
||||
withAssetBundle:_assetBundle
|
||||
withFramerate:framerate];
|
||||
_assetMap[refID] = asset;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)finalizeInitializationWithFramerate:(NSNumber * _Nonnull)framerate {
|
||||
for (NSString *refID in _assetJSONMap.allKeys) {
|
||||
[self buildAssetNamed:refID withFramerate:framerate];
|
||||
}
|
||||
_assetJSONMap = nil;
|
||||
}
|
||||
|
||||
- (LOTAsset *)assetModelForID:(NSString *)assetID {
|
||||
return _assetMap[assetID];
|
||||
}
|
||||
|
||||
- (void)setRootDirectory:(NSString *)rootDirectory {
|
||||
_rootDirectory = rootDirectory;
|
||||
[_assetMap enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, LOTAsset * _Nonnull obj, BOOL * _Nonnull stop) {
|
||||
obj.rootDirectory = rootDirectory;
|
||||
}];
|
||||
}
|
||||
@end
|
||||
76
Pods/lottie-ios/lottie-ios/Classes/Models/LOTLayer.h
generated
Normal file
76
Pods/lottie-ios/lottie-ios/Classes/Models/LOTLayer.h
generated
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// LOTLayer.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTPlatformCompat.h"
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
@class LOTShapeGroup;
|
||||
@class LOTMask;
|
||||
@class LOTAsset;
|
||||
@class LOTAssetGroup;
|
||||
|
||||
typedef enum : NSInteger {
|
||||
LOTLayerTypePrecomp,
|
||||
LOTLayerTypeSolid,
|
||||
LOTLayerTypeImage,
|
||||
LOTLayerTypeNull,
|
||||
LOTLayerTypeShape,
|
||||
LOTLayerTypeUnknown
|
||||
} LOTLayerType;
|
||||
|
||||
typedef enum : NSInteger {
|
||||
LOTMatteTypeNone,
|
||||
LOTMatteTypeAdd,
|
||||
LOTMatteTypeInvert,
|
||||
LOTMatteTypeUnknown
|
||||
} LOTMatteType;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LOTLayer : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate;
|
||||
|
||||
@property (nonatomic, readonly) NSString *layerName;
|
||||
@property (nonatomic, readonly, nullable) NSString *referenceID;
|
||||
@property (nonatomic, readonly) NSNumber *layerID;
|
||||
@property (nonatomic, readonly) LOTLayerType layerType;
|
||||
@property (nonatomic, readonly, nullable) NSNumber *parentID;
|
||||
@property (nonatomic, readonly) NSNumber *startFrame;
|
||||
@property (nonatomic, readonly) NSNumber *inFrame;
|
||||
@property (nonatomic, readonly) NSNumber *outFrame;
|
||||
@property (nonatomic, readonly) NSNumber *timeStretch;
|
||||
@property (nonatomic, readonly) CGRect layerBounds;
|
||||
|
||||
@property (nonatomic, readonly, nullable) NSArray<LOTShapeGroup *> *shapes;
|
||||
@property (nonatomic, readonly, nullable) NSArray<LOTMask *> *masks;
|
||||
|
||||
@property (nonatomic, readonly, nullable) NSNumber *layerWidth;
|
||||
@property (nonatomic, readonly, nullable) NSNumber *layerHeight;
|
||||
@property (nonatomic, readonly, nullable) UIColor *solidColor;
|
||||
@property (nonatomic, readonly, nullable) LOTAsset *imageAsset;
|
||||
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *timeRemapping;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *rotation;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *position;
|
||||
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *positionX;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *positionY;
|
||||
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *anchor;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *scale;
|
||||
|
||||
@property (nonatomic, readonly) LOTMatteType matteType;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
183
Pods/lottie-ios/lottie-ios/Classes/Models/LOTLayer.m
generated
Normal file
183
Pods/lottie-ios/lottie-ios/Classes/Models/LOTLayer.m
generated
Normal file
@@ -0,0 +1,183 @@
|
||||
//
|
||||
// LOTLayer.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTLayer.h"
|
||||
#import "LOTAsset.h"
|
||||
#import "LOTAssetGroup.h"
|
||||
#import "LOTShapeGroup.h"
|
||||
#import "LOTComposition.h"
|
||||
#import "LOTHelpers.h"
|
||||
#import "LOTMask.h"
|
||||
#import "LOTHelpers.h"
|
||||
|
||||
@implementation LOTLayer
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup *)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary
|
||||
withAssetGroup:assetGroup
|
||||
withFramerate:framerate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetGroup:(LOTAssetGroup *)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
|
||||
_layerName = [jsonDictionary[@"nm"] copy];
|
||||
_layerID = [jsonDictionary[@"ind"] copy];
|
||||
|
||||
NSNumber *layerType = jsonDictionary[@"ty"];
|
||||
_layerType = layerType.integerValue;
|
||||
|
||||
if (jsonDictionary[@"refId"]) {
|
||||
_referenceID = [jsonDictionary[@"refId"] copy];
|
||||
}
|
||||
|
||||
_parentID = [jsonDictionary[@"parent"] copy];
|
||||
|
||||
if (jsonDictionary[@"st"]) {
|
||||
_startFrame = [jsonDictionary[@"st"] copy];
|
||||
}
|
||||
_inFrame = [jsonDictionary[@"ip"] copy];
|
||||
_outFrame = [jsonDictionary[@"op"] copy];
|
||||
|
||||
if (jsonDictionary[@"sr"]) {
|
||||
_timeStretch = [jsonDictionary[@"sr"] copy];
|
||||
} else {
|
||||
_timeStretch = @1;
|
||||
}
|
||||
|
||||
if (_layerType == LOTLayerTypePrecomp) {
|
||||
_layerHeight = [jsonDictionary[@"h"] copy];
|
||||
_layerWidth = [jsonDictionary[@"w"] copy];
|
||||
[assetGroup buildAssetNamed:_referenceID withFramerate:framerate];
|
||||
} else if (_layerType == LOTLayerTypeImage) {
|
||||
[assetGroup buildAssetNamed:_referenceID withFramerate:framerate];
|
||||
_imageAsset = [assetGroup assetModelForID:_referenceID];
|
||||
_layerWidth = [_imageAsset.assetWidth copy];
|
||||
_layerHeight = [_imageAsset.assetHeight copy];
|
||||
} else if (_layerType == LOTLayerTypeSolid) {
|
||||
_layerWidth = jsonDictionary[@"sw"];
|
||||
_layerHeight = jsonDictionary[@"sh"];
|
||||
NSString *solidColor = jsonDictionary[@"sc"];
|
||||
_solidColor = [UIColor LOT_colorWithHexString:solidColor];
|
||||
}
|
||||
|
||||
_layerBounds = CGRectMake(0, 0, _layerWidth.floatValue, _layerHeight.floatValue);
|
||||
|
||||
NSDictionary *ks = jsonDictionary[@"ks"];
|
||||
|
||||
NSDictionary *opacity = ks[@"o"];
|
||||
if (opacity) {
|
||||
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
|
||||
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, 0, 100, 0, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *timeRemap = jsonDictionary[@"tm"];
|
||||
if (timeRemap) {
|
||||
_timeRemapping = [[LOTKeyframeGroup alloc] initWithData:timeRemap];
|
||||
[_timeRemapping remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return inValue * framerate.doubleValue;
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *rotation = ks[@"r"];
|
||||
if (rotation == nil) {
|
||||
rotation = ks[@"rz"];
|
||||
}
|
||||
if (rotation) {
|
||||
_rotation = [[LOTKeyframeGroup alloc] initWithData:rotation];
|
||||
[_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_DegreesToRadians(inValue);
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *position = ks[@"p"];
|
||||
if ([position[@"s"] boolValue]) {
|
||||
// Separate dimensions
|
||||
_positionX = [[LOTKeyframeGroup alloc] initWithData:position[@"x"]];
|
||||
_positionY = [[LOTKeyframeGroup alloc] initWithData:position[@"y"]];
|
||||
} else {
|
||||
_position = [[LOTKeyframeGroup alloc] initWithData:position ];
|
||||
}
|
||||
|
||||
NSDictionary *anchor = ks[@"a"];
|
||||
if (anchor) {
|
||||
_anchor = [[LOTKeyframeGroup alloc] initWithData:anchor];
|
||||
}
|
||||
|
||||
NSDictionary *scale = ks[@"s"];
|
||||
if (scale) {
|
||||
_scale = [[LOTKeyframeGroup alloc] initWithData:scale];
|
||||
[_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, -100, 100, -1, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
_matteType = [jsonDictionary[@"tt"] integerValue];
|
||||
|
||||
|
||||
NSMutableArray *masks = [NSMutableArray array];
|
||||
for (NSDictionary *maskJSON in jsonDictionary[@"masksProperties"]) {
|
||||
LOTMask *mask = [[LOTMask alloc] initWithJSON:maskJSON];
|
||||
[masks addObject:mask];
|
||||
}
|
||||
_masks = masks.count ? masks : nil;
|
||||
|
||||
NSMutableArray *shapes = [NSMutableArray array];
|
||||
for (NSDictionary *shapeJSON in jsonDictionary[@"shapes"]) {
|
||||
id shapeItem = [LOTShapeGroup shapeItemWithJSON:shapeJSON];
|
||||
if (shapeItem) {
|
||||
[shapes addObject:shapeItem];
|
||||
}
|
||||
}
|
||||
_shapes = shapes;
|
||||
|
||||
NSArray *effects = jsonDictionary[@"ef"];
|
||||
if (effects.count > 0) {
|
||||
|
||||
NSDictionary *effectNames = @{ @0: @"slider",
|
||||
@1: @"angle",
|
||||
@2: @"color",
|
||||
@3: @"point",
|
||||
@4: @"checkbox",
|
||||
@5: @"group",
|
||||
@6: @"noValue",
|
||||
@7: @"dropDown",
|
||||
@9: @"customValue",
|
||||
@10: @"layerIndex",
|
||||
@20: @"tint",
|
||||
@21: @"fill" };
|
||||
|
||||
for (NSDictionary *effect in effects) {
|
||||
NSNumber *typeNumber = effect[@"ty"];
|
||||
NSString *name = effect[@"nm"];
|
||||
NSString *internalName = effect[@"mn"];
|
||||
NSString *typeString = effectNames[typeNumber];
|
||||
if (typeString) {
|
||||
NSLog(@"%s: Warning: %@ effect not supported: %@ / %@", __PRETTY_FUNCTION__, typeString, internalName, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
NSMutableString *text = [[super description] mutableCopy];
|
||||
[text appendFormat:@" %@ id: %d pid: %d frames: %d-%d", _layerName, (int)_layerID.integerValue, (int)_parentID.integerValue,
|
||||
(int)_inFrame.integerValue, (int)_outFrame.integerValue];
|
||||
return text;
|
||||
}
|
||||
|
||||
@end
|
||||
30
Pods/lottie-ios/lottie-ios/Classes/Models/LOTLayerGroup.h
generated
Normal file
30
Pods/lottie-ios/lottie-ios/Classes/Models/LOTLayerGroup.h
generated
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// LOTLayerGroup.h
|
||||
// Pods
|
||||
//
|
||||
// Created by Brandon Withrow on 2/16/17.
|
||||
//
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class LOTLayer;
|
||||
@class LOTAssetGroup;
|
||||
|
||||
@interface LOTLayerGroup : NSObject
|
||||
|
||||
- (instancetype)initWithLayerJSON:(NSArray *)layersJSON
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate;
|
||||
|
||||
@property (nonatomic, readonly) NSArray <LOTLayer *> *layers;
|
||||
|
||||
- (LOTLayer *)layerModelForID:(NSNumber *)layerID;
|
||||
- (LOTLayer *)layerForReferenceID:(NSString *)referenceID;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
62
Pods/lottie-ios/lottie-ios/Classes/Models/LOTLayerGroup.m
generated
Normal file
62
Pods/lottie-ios/lottie-ios/Classes/Models/LOTLayerGroup.m
generated
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// LOTLayerGroup.m
|
||||
// Pods
|
||||
//
|
||||
// Created by Brandon Withrow on 2/16/17.
|
||||
//
|
||||
//
|
||||
|
||||
#import "LOTLayerGroup.h"
|
||||
#import "LOTLayer.h"
|
||||
#import "LOTAssetGroup.h"
|
||||
|
||||
@implementation LOTLayerGroup {
|
||||
NSDictionary *_modelMap;
|
||||
NSDictionary *_referenceIDMap;
|
||||
}
|
||||
|
||||
- (instancetype)initWithLayerJSON:(NSArray *)layersJSON
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:layersJSON withAssetGroup:assetGroup withFramerate:framerate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSArray *)layersJSON
|
||||
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
|
||||
withFramerate:(NSNumber *)framerate {
|
||||
|
||||
NSMutableArray *layers = [NSMutableArray array];
|
||||
NSMutableDictionary *modelMap = [NSMutableDictionary dictionary];
|
||||
NSMutableDictionary *referenceMap = [NSMutableDictionary dictionary];
|
||||
|
||||
for (NSDictionary *layerJSON in layersJSON) {
|
||||
LOTLayer *layer = [[LOTLayer alloc] initWithJSON:layerJSON
|
||||
withAssetGroup:assetGroup
|
||||
withFramerate:framerate];
|
||||
[layers addObject:layer];
|
||||
if(layer.layerID) {
|
||||
modelMap[layer.layerID] = layer;
|
||||
}
|
||||
if (layer.referenceID) {
|
||||
referenceMap[layer.referenceID] = layer;
|
||||
}
|
||||
}
|
||||
|
||||
_referenceIDMap = referenceMap;
|
||||
_modelMap = modelMap;
|
||||
_layers = layers;
|
||||
}
|
||||
|
||||
- (LOTLayer *)layerModelForID:(NSNumber *)layerID {
|
||||
return _modelMap[layerID];
|
||||
}
|
||||
|
||||
- (LOTLayer *)layerForReferenceID:(NSString *)referenceID {
|
||||
return _referenceIDMap[referenceID];
|
||||
}
|
||||
|
||||
@end
|
||||
29
Pods/lottie-ios/lottie-ios/Classes/Models/LOTMask.h
generated
Normal file
29
Pods/lottie-ios/lottie-ios/Classes/Models/LOTMask.h
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// LOTMask.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
LOTMaskModeAdd,
|
||||
LOTMaskModeSubtract,
|
||||
LOTMaskModeIntersect,
|
||||
LOTMaskModeUnknown
|
||||
} LOTMaskMode;
|
||||
|
||||
@interface LOTMask : NSObject
|
||||
|
||||
- (instancetype _Nonnull)initWithJSON:(NSDictionary * _Nonnull)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) BOOL closed;
|
||||
@property (nonatomic, readonly) BOOL inverted;
|
||||
@property (nonatomic, readonly) LOTMaskMode maskMode;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *maskPath;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *opacity;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *expansion;
|
||||
@end
|
||||
59
Pods/lottie-ios/lottie-ios/Classes/Models/LOTMask.m
generated
Normal file
59
Pods/lottie-ios/lottie-ios/Classes/Models/LOTMask.m
generated
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// LOTMask.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTMask.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTMask
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
NSNumber *closed = jsonDictionary[@"cl"];
|
||||
_closed = closed.boolValue;
|
||||
|
||||
NSNumber *inverted = jsonDictionary[@"inv"];
|
||||
_inverted = inverted.boolValue;
|
||||
|
||||
NSString *mode = jsonDictionary[@"mode"];
|
||||
if ([mode isEqualToString:@"a"]) {
|
||||
_maskMode = LOTMaskModeAdd;
|
||||
} else if ([mode isEqualToString:@"s"]) {
|
||||
_maskMode = LOTMaskModeSubtract;
|
||||
} else if ([mode isEqualToString:@"i"]) {
|
||||
_maskMode = LOTMaskModeIntersect;
|
||||
} else {
|
||||
_maskMode = LOTMaskModeUnknown;
|
||||
}
|
||||
|
||||
NSDictionary *maskshape = jsonDictionary[@"pt"];
|
||||
if (maskshape) {
|
||||
_maskPath = [[LOTKeyframeGroup alloc] initWithData:maskshape];
|
||||
}
|
||||
|
||||
NSDictionary *opacity = jsonDictionary[@"o"];
|
||||
if (opacity) {
|
||||
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
|
||||
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, 0, 100, 0, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *expansion = jsonDictionary[@"x"];
|
||||
if (expansion) {
|
||||
_expansion = [[LOTKeyframeGroup alloc] initWithData:expansion];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
28
Pods/lottie-ios/lottie-ios/Classes/Models/LOTModels.h
generated
Normal file
28
Pods/lottie-ios/lottie-ios/Classes/Models/LOTModels.h
generated
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// LOTModels.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef LOTModels_h
|
||||
#define LOTModels_h
|
||||
|
||||
#import "LOTKeyframe.h"
|
||||
#import "LOTComposition.h"
|
||||
#import "LOTLayer.h"
|
||||
#import "LOTMask.h"
|
||||
#import "LOTShapeCircle.h"
|
||||
#import "LOTShapeFill.h"
|
||||
#import "LOTShapeGroup.h"
|
||||
#import "LOTShapePath.h"
|
||||
#import "LOTShapeRectangle.h"
|
||||
#import "LOTShapeStroke.h"
|
||||
#import "LOTShapeTransform.h"
|
||||
#import "LOTShapeTrimPath.h"
|
||||
#import "LOTLayerGroup.h"
|
||||
#import "LOTAsset.h"
|
||||
#import "LOTShapeGradientFill.h"
|
||||
|
||||
#endif /* LOTModels_h */
|
||||
25
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeCircle.h
generated
Normal file
25
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeCircle.h
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// LOTShapeCircle.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LOTShapeCircle : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *position;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *size;
|
||||
@property (nonatomic, readonly) BOOL reversed;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
40
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeCircle.m
generated
Normal file
40
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeCircle.m
generated
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// LOTShapeCircle.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeCircle.h"
|
||||
|
||||
@implementation LOTShapeCircle
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSDictionary *position = jsonDictionary[@"p"];
|
||||
if (position) {
|
||||
_position = [[LOTKeyframeGroup alloc] initWithData:position];
|
||||
}
|
||||
|
||||
NSDictionary *size= jsonDictionary[@"s"];
|
||||
if (size) {
|
||||
_size = [[LOTKeyframeGroup alloc] initWithData:size];
|
||||
}
|
||||
NSNumber *reversed = jsonDictionary[@"d"];
|
||||
_reversed = (reversed.integerValue == 3);
|
||||
}
|
||||
|
||||
@end
|
||||
26
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeFill.h
generated
Normal file
26
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeFill.h
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// LOTShapeFill.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LOTShapeFill : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly) BOOL fillEnabled;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *color;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
|
||||
@property (nonatomic, readonly) BOOL evenOddFillRule;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
52
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeFill.m
generated
Normal file
52
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeFill.m
generated
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// LOTShapeFill.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeFill.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTShapeFill
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSDictionary *color = jsonDictionary[@"c"];
|
||||
if (color) {
|
||||
_color = [[LOTKeyframeGroup alloc] initWithData:color];
|
||||
}
|
||||
|
||||
NSDictionary *opacity = jsonDictionary[@"o"];
|
||||
if (opacity) {
|
||||
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
|
||||
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, 0, 100, 0, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
NSNumber *evenOdd = jsonDictionary[@"r"];
|
||||
if (evenOdd.integerValue == 2) {
|
||||
_evenOddFillRule = YES;
|
||||
} else {
|
||||
_evenOddFillRule = NO;
|
||||
}
|
||||
|
||||
NSNumber *fillEnabled = jsonDictionary[@"fillEnabled"];
|
||||
_fillEnabled = fillEnabled.boolValue;
|
||||
}
|
||||
|
||||
@end
|
||||
34
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeGradientFill.h
generated
Normal file
34
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeGradientFill.h
generated
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// LOTShapeGradientFill.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/26/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
LOTGradientTypeLinear,
|
||||
LOTGradientTypeRadial
|
||||
} LOTGradientType;
|
||||
|
||||
@interface LOTShapeGradientFill : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly) NSNumber *numberOfColors;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *startPoint;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *endPoint;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *gradient;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
|
||||
@property (nonatomic, readonly) BOOL evenOddFillRule;
|
||||
@property (nonatomic, readonly) LOTGradientType type;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
67
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeGradientFill.m
generated
Normal file
67
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeGradientFill.m
generated
Normal file
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// LOTShapeGradientFill.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/26/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeGradientFill.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTShapeGradientFill
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSNumber *type = jsonDictionary[@"t"];
|
||||
|
||||
if (type.integerValue != 1) {
|
||||
_type = LOTGradientTypeRadial;
|
||||
} else {
|
||||
_type = LOTGradientTypeLinear;
|
||||
}
|
||||
|
||||
NSDictionary *start = jsonDictionary[@"s"];
|
||||
if (start) {
|
||||
_startPoint = [[LOTKeyframeGroup alloc] initWithData:start];
|
||||
}
|
||||
|
||||
NSDictionary *end = jsonDictionary[@"e"];
|
||||
if (end) {
|
||||
_endPoint = [[LOTKeyframeGroup alloc] initWithData:end];
|
||||
}
|
||||
|
||||
NSDictionary *gradient = jsonDictionary[@"g"];
|
||||
if (gradient) {
|
||||
NSDictionary *unwrappedGradient = gradient[@"k"];
|
||||
_numberOfColors = gradient[@"p"];
|
||||
_gradient = [[LOTKeyframeGroup alloc] initWithData:unwrappedGradient];
|
||||
}
|
||||
|
||||
NSDictionary *opacity = jsonDictionary[@"o"];
|
||||
if (opacity) {
|
||||
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
|
||||
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, 0, 100, 0, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
NSNumber *evenOdd = jsonDictionary[@"r"];
|
||||
if (evenOdd.integerValue == 2) {
|
||||
_evenOddFillRule = YES;
|
||||
} else {
|
||||
_evenOddFillRule = NO;
|
||||
}
|
||||
}
|
||||
@end
|
||||
21
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeGroup.h
generated
Normal file
21
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeGroup.h
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// LOTShape.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
@interface LOTShapeGroup : NSObject
|
||||
|
||||
- (instancetype _Nonnull)initWithJSON:(NSDictionary *_Nonnull)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly, nonnull) NSString *keyname;
|
||||
@property (nonatomic, readonly, nonnull) NSArray *items;
|
||||
|
||||
+ (id _Nullable)shapeItemWithJSON:(NSDictionary * _Nonnull)itemJSON;
|
||||
|
||||
@end
|
||||
102
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeGroup.m
generated
Normal file
102
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeGroup.m
generated
Normal file
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// LOTShape.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeGroup.h"
|
||||
#import "LOTShapeFill.h"
|
||||
#import "LOTShapePath.h"
|
||||
#import "LOTShapeCircle.h"
|
||||
#import "LOTShapeStroke.h"
|
||||
#import "LOTShapeTransform.h"
|
||||
#import "LOTShapeRectangle.h"
|
||||
#import "LOTShapeTrimPath.h"
|
||||
#import "LOTShapeGradientFill.h"
|
||||
#import "LOTShapeStar.h"
|
||||
#import "LOTShapeRepeater.h"
|
||||
|
||||
@implementation LOTShapeGroup
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSArray *itemsJSON = jsonDictionary[@"it"];
|
||||
NSMutableArray *items = [NSMutableArray array];
|
||||
for (NSDictionary *itemJSON in itemsJSON) {
|
||||
id newItem = [LOTShapeGroup shapeItemWithJSON:itemJSON];
|
||||
if (newItem) {
|
||||
[items addObject:newItem];
|
||||
}
|
||||
}
|
||||
_items = items;
|
||||
}
|
||||
|
||||
+ (id)shapeItemWithJSON:(NSDictionary *)itemJSON {
|
||||
NSString *type = itemJSON[@"ty"];
|
||||
if ([type isEqualToString:@"gr"]) {
|
||||
LOTShapeGroup *group = [[LOTShapeGroup alloc] initWithJSON:itemJSON];
|
||||
return group;
|
||||
} else if ([type isEqualToString:@"st"]) {
|
||||
LOTShapeStroke *stroke = [[LOTShapeStroke alloc] initWithJSON:itemJSON];
|
||||
return stroke;
|
||||
} else if ([type isEqualToString:@"fl"]) {
|
||||
LOTShapeFill *fill = [[LOTShapeFill alloc] initWithJSON:itemJSON];
|
||||
return fill;
|
||||
} else if ([type isEqualToString:@"tr"]) {
|
||||
LOTShapeTransform *transform = [[LOTShapeTransform alloc] initWithJSON:itemJSON];
|
||||
return transform;
|
||||
} else if ([type isEqualToString:@"sh"]) {
|
||||
LOTShapePath *path = [[LOTShapePath alloc] initWithJSON:itemJSON];
|
||||
return path;
|
||||
} else if ([type isEqualToString:@"el"]) {
|
||||
LOTShapeCircle *circle = [[LOTShapeCircle alloc] initWithJSON:itemJSON];
|
||||
return circle;
|
||||
} else if ([type isEqualToString:@"rc"]) {
|
||||
LOTShapeRectangle *rectangle = [[LOTShapeRectangle alloc] initWithJSON:itemJSON];
|
||||
return rectangle;
|
||||
} else if ([type isEqualToString:@"tm"]) {
|
||||
LOTShapeTrimPath *trim = [[LOTShapeTrimPath alloc] initWithJSON:itemJSON];
|
||||
return trim;
|
||||
} else if ([type isEqualToString:@"gs"]) {
|
||||
NSLog(@"%s: Warning: gradient strokes are not supported", __PRETTY_FUNCTION__);
|
||||
} else if ([type isEqualToString:@"gf"]) {
|
||||
LOTShapeGradientFill *gradientFill = [[LOTShapeGradientFill alloc] initWithJSON:itemJSON];
|
||||
return gradientFill;
|
||||
} else if ([type isEqualToString:@"sr"]) {
|
||||
LOTShapeStar *star = [[LOTShapeStar alloc] initWithJSON:itemJSON];
|
||||
return star;
|
||||
} else if ([type isEqualToString:@"mm"]) {
|
||||
NSString *name = itemJSON[@"nm"];
|
||||
NSLog(@"%s: Warning: merge shape is not supported. name: %@", __PRETTY_FUNCTION__, name);
|
||||
} else if ([type isEqualToString:@"rp"]) {
|
||||
LOTShapeRepeater *repeater = [[LOTShapeRepeater alloc] initWithJSON:itemJSON];
|
||||
return repeater;
|
||||
} else {
|
||||
NSString *name = itemJSON[@"nm"];
|
||||
NSLog(@"%s: Unsupported shape: %@ name: %@", __PRETTY_FUNCTION__, type, name);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
NSMutableString *text = [[super description] mutableCopy];
|
||||
[text appendFormat:@" items: %@", self.items];
|
||||
return text;
|
||||
}
|
||||
|
||||
@end
|
||||
21
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapePath.h
generated
Normal file
21
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapePath.h
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// LOTShapePath.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
@interface LOTShapePath : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly) BOOL closed;
|
||||
@property (nonatomic, readonly) NSNumber *index;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *shapePath;
|
||||
|
||||
@end
|
||||
35
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapePath.m
generated
Normal file
35
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapePath.m
generated
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// LOTShapePath.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapePath.h"
|
||||
|
||||
@implementation LOTShapePath
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
_index = jsonDictionary[@"ind"];
|
||||
_closed = [jsonDictionary[@"closed"] boolValue];
|
||||
NSDictionary *shape = jsonDictionary[@"ks"];
|
||||
if (shape) {
|
||||
_shapePath = [[LOTKeyframeGroup alloc] initWithData:shape];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
22
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeRectangle.h
generated
Normal file
22
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeRectangle.h
generated
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// LOTShapeRectangle.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
@interface LOTShapeRectangle : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *position;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *size;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *cornerRadius;
|
||||
@property (nonatomic, readonly) BOOL reversed;
|
||||
|
||||
@end
|
||||
45
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeRectangle.m
generated
Normal file
45
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeRectangle.m
generated
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// LOTShapeRectangle.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeRectangle.h"
|
||||
|
||||
@implementation LOTShapeRectangle
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSDictionary *position = jsonDictionary[@"p"];
|
||||
if (position) {
|
||||
_position = [[LOTKeyframeGroup alloc] initWithData:position];
|
||||
}
|
||||
|
||||
NSDictionary *cornerRadius = jsonDictionary[@"r"];
|
||||
if (cornerRadius) {
|
||||
_cornerRadius = [[LOTKeyframeGroup alloc] initWithData:cornerRadius];
|
||||
}
|
||||
|
||||
NSDictionary *size = jsonDictionary[@"s"];
|
||||
if (size) {
|
||||
_size = [[LOTKeyframeGroup alloc] initWithData:size];
|
||||
}
|
||||
NSNumber *reversed = jsonDictionary[@"d"];
|
||||
_reversed = (reversed.integerValue == 3);
|
||||
}
|
||||
|
||||
@end
|
||||
30
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeRepeater.h
generated
Normal file
30
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeRepeater.h
generated
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// LOTShapeRepeater.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/28/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LOTShapeRepeater : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *copies;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *offset;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *anchorPoint;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *scale;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *position;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *rotation;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *startOpacity;
|
||||
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *endOpacity;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
83
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeRepeater.m
generated
Normal file
83
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeRepeater.m
generated
Normal file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// LOTShapeRepeater.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/28/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeRepeater.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTShapeRepeater
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSDictionary *copies = jsonDictionary[@"c"];
|
||||
if (copies) {
|
||||
_copies = [[LOTKeyframeGroup alloc] initWithData:copies];
|
||||
}
|
||||
|
||||
NSDictionary *offset = jsonDictionary[@"o"];
|
||||
if (offset) {
|
||||
_offset = [[LOTKeyframeGroup alloc] initWithData:offset];
|
||||
}
|
||||
|
||||
NSDictionary *transform = jsonDictionary[@"tr"];
|
||||
|
||||
NSDictionary *rotation = transform[@"r"];
|
||||
if (rotation) {
|
||||
_rotation = [[LOTKeyframeGroup alloc] initWithData:rotation];
|
||||
[_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_DegreesToRadians(inValue);
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *startOpacity = transform[@"so"];
|
||||
if (startOpacity) {
|
||||
_startOpacity = [[LOTKeyframeGroup alloc] initWithData:startOpacity];
|
||||
[_startOpacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, 0, 100, 0, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *endOpacity = transform[@"eo"];
|
||||
if (endOpacity) {
|
||||
_endOpacity = [[LOTKeyframeGroup alloc] initWithData:endOpacity];
|
||||
[_endOpacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, 0, 100, 0, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *anchorPoint = transform[@"a"];
|
||||
if (anchorPoint) {
|
||||
_anchorPoint = [[LOTKeyframeGroup alloc] initWithData:anchorPoint];
|
||||
}
|
||||
|
||||
NSDictionary *position = transform[@"p"];
|
||||
if (position) {
|
||||
_position = [[LOTKeyframeGroup alloc] initWithData:position];
|
||||
}
|
||||
|
||||
NSDictionary *scale = transform[@"s"];
|
||||
if (scale) {
|
||||
_scale = [[LOTKeyframeGroup alloc] initWithData:scale];
|
||||
[_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, -100, 100, -1, 1);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
35
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeStar.h
generated
Normal file
35
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeStar.h
generated
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// LOTShapeStar.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/27/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
LOTPolystarShapeNone,
|
||||
LOTPolystarShapeStar,
|
||||
LOTPolystarShapePolygon
|
||||
} LOTPolystarShape;
|
||||
|
||||
@interface LOTShapeStar : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *outerRadius;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *outerRoundness;
|
||||
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *innerRadius;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *innerRoundness;
|
||||
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *position;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *numberOfPoints;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *rotation;
|
||||
|
||||
@property (nonatomic, readonly) LOTPolystarShape type;
|
||||
|
||||
@end
|
||||
66
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeStar.m
generated
Normal file
66
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeStar.m
generated
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// LOTShapeStar.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 7/27/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeStar.h"
|
||||
|
||||
@implementation LOTShapeStar
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSDictionary *outerRadius = jsonDictionary[@"or"];
|
||||
if (outerRadius) {
|
||||
_outerRadius = [[LOTKeyframeGroup alloc] initWithData:outerRadius];
|
||||
}
|
||||
|
||||
NSDictionary *outerRoundness = jsonDictionary[@"os"];
|
||||
if (outerRoundness) {
|
||||
_outerRoundness = [[LOTKeyframeGroup alloc] initWithData:outerRoundness];
|
||||
}
|
||||
|
||||
NSDictionary *innerRadius = jsonDictionary[@"ir"];
|
||||
if (innerRadius) {
|
||||
_innerRadius = [[LOTKeyframeGroup alloc] initWithData:innerRadius];
|
||||
}
|
||||
|
||||
NSDictionary *innerRoundness = jsonDictionary[@"is"];
|
||||
if (innerRoundness) {
|
||||
_innerRoundness = [[LOTKeyframeGroup alloc] initWithData:innerRoundness];
|
||||
}
|
||||
|
||||
NSDictionary *position = jsonDictionary[@"p"];
|
||||
if (position) {
|
||||
_position = [[LOTKeyframeGroup alloc] initWithData:position];
|
||||
}
|
||||
|
||||
NSDictionary *numberOfPoints = jsonDictionary[@"pt"];
|
||||
if (numberOfPoints) {
|
||||
_numberOfPoints = [[LOTKeyframeGroup alloc] initWithData:numberOfPoints];
|
||||
}
|
||||
|
||||
NSDictionary *rotation = jsonDictionary[@"r"];
|
||||
if (rotation) {
|
||||
_rotation = [[LOTKeyframeGroup alloc] initWithData:rotation];
|
||||
}
|
||||
|
||||
NSNumber *type = jsonDictionary[@"sy"];
|
||||
_type = type.integerValue;
|
||||
}
|
||||
|
||||
@end
|
||||
39
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeStroke.h
generated
Normal file
39
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeStroke.h
generated
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// LOTShapeStroke.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
LOTLineCapTypeButt,
|
||||
LOTLineCapTypeRound,
|
||||
LOTLineCapTypeUnknown
|
||||
} LOTLineCapType;
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
LOTLineJoinTypeMiter,
|
||||
LOTLineJoinTypeRound,
|
||||
LOTLineJoinTypeBevel
|
||||
} LOTLineJoinType;
|
||||
|
||||
@interface LOTShapeStroke : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly) BOOL fillEnabled;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *color;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *width;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *dashOffset;
|
||||
@property (nonatomic, readonly) LOTLineCapType capType;
|
||||
@property (nonatomic, readonly) LOTLineJoinType joinType;
|
||||
|
||||
@property (nonatomic, readonly) NSArray *lineDashPattern;
|
||||
|
||||
@end
|
||||
73
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeStroke.m
generated
Normal file
73
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeStroke.m
generated
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// LOTShapeStroke.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeStroke.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTShapeStroke
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSDictionary *color = jsonDictionary[@"c"];
|
||||
if (color) {
|
||||
_color = [[LOTKeyframeGroup alloc] initWithData:color];
|
||||
}
|
||||
|
||||
NSDictionary *width = jsonDictionary[@"w"];
|
||||
if (width) {
|
||||
_width = [[LOTKeyframeGroup alloc] initWithData:width];
|
||||
}
|
||||
|
||||
NSDictionary *opacity = jsonDictionary[@"o"];
|
||||
if (opacity) {
|
||||
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
|
||||
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, 0, 100, 0, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
_capType = [jsonDictionary[@"lc"] integerValue] - 1;
|
||||
_joinType = [jsonDictionary[@"lj"] integerValue] - 1;
|
||||
|
||||
NSNumber *fillEnabled = jsonDictionary[@"fillEnabled"];
|
||||
_fillEnabled = fillEnabled.boolValue;
|
||||
|
||||
NSDictionary *dashOffset = nil;
|
||||
NSArray *dashes = jsonDictionary[@"d"];
|
||||
if (dashes) {
|
||||
NSMutableArray *dashPattern = [NSMutableArray array];
|
||||
for (NSDictionary *dash in dashes) {
|
||||
if ([dash[@"n"] isEqualToString:@"o"]) {
|
||||
dashOffset = dash[@"v"];
|
||||
continue;
|
||||
}
|
||||
// TODO DASH PATTERNS
|
||||
NSDictionary *value = dash[@"v"];
|
||||
LOTKeyframeGroup *keyframeGroup = [[LOTKeyframeGroup alloc] initWithData:value];
|
||||
[dashPattern addObject:keyframeGroup];
|
||||
}
|
||||
_lineDashPattern = dashPattern;
|
||||
}
|
||||
if (dashOffset) {
|
||||
_dashOffset = [[LOTKeyframeGroup alloc] initWithData:dashOffset];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
25
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeTransform.h
generated
Normal file
25
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeTransform.h
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// LOTShapeTransform.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
@interface LOTShapeTransform : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *position;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *anchor;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *scale;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *rotation;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
|
||||
|
||||
@end
|
||||
78
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeTransform.m
generated
Normal file
78
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeTransform.m
generated
Normal file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// LOTShapeTransform.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/15/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeTransform.h"
|
||||
#import "LOTHelpers.h"
|
||||
|
||||
@implementation LOTShapeTransform
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSDictionary *position = jsonDictionary[@"p"];
|
||||
if (position) {
|
||||
_position = [[LOTKeyframeGroup alloc] initWithData:position];
|
||||
}
|
||||
|
||||
NSDictionary *anchor = jsonDictionary[@"a"];
|
||||
if (anchor) {
|
||||
_anchor = [[LOTKeyframeGroup alloc] initWithData:anchor];
|
||||
}
|
||||
|
||||
NSDictionary *scale = jsonDictionary[@"s"];
|
||||
if (scale) {
|
||||
_scale = [[LOTKeyframeGroup alloc] initWithData:scale];
|
||||
[_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, -100, 100, -1, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *rotation = jsonDictionary[@"r"];
|
||||
if (rotation) {
|
||||
_rotation = [[LOTKeyframeGroup alloc] initWithData:rotation];
|
||||
[_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_DegreesToRadians(inValue);
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *opacity = jsonDictionary[@"o"];
|
||||
if (opacity) {
|
||||
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
|
||||
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
|
||||
return LOT_RemapValue(inValue, 0, 100, 0, 1);
|
||||
}];
|
||||
}
|
||||
|
||||
NSString *name = jsonDictionary[@"nm"];
|
||||
|
||||
NSDictionary *skew = jsonDictionary[@"sk"];
|
||||
BOOL hasSkew = (skew && [skew[@"k"] isEqual:@0] == NO);
|
||||
NSDictionary *skewAxis = jsonDictionary[@"sa"];
|
||||
BOOL hasSkewAxis = (skewAxis && [skewAxis[@"k"] isEqual:@0] == NO);
|
||||
|
||||
if (hasSkew || hasSkewAxis) {
|
||||
NSLog(@"%s: Warning: skew is not supported: %@", __PRETTY_FUNCTION__, name);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"LOTShapeTransform \"Position: %@ Anchor: %@ Scale: %@ Rotation: %@ Opacity: %@\"", _position.description, _anchor.description, _scale.description, _rotation.description, _opacity.description];
|
||||
}
|
||||
|
||||
@end
|
||||
21
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeTrimPath.h
generated
Normal file
21
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeTrimPath.h
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// LOTShapeTrimPath.h
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by brandon_withrow on 7/26/16.
|
||||
// Copyright © 2016 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "LOTKeyframe.h"
|
||||
|
||||
@interface LOTShapeTrimPath : NSObject
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
|
||||
|
||||
@property (nonatomic, readonly) NSString *keyname;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *start;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *end;
|
||||
@property (nonatomic, readonly) LOTKeyframeGroup *offset;
|
||||
|
||||
@end
|
||||
43
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeTrimPath.m
generated
Normal file
43
Pods/lottie-ios/lottie-ios/Classes/Models/LOTShapeTrimPath.m
generated
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// LOTShapeTrimPath.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by brandon_withrow on 7/26/16.
|
||||
// Copyright © 2016 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTShapeTrimPath.h"
|
||||
|
||||
@implementation LOTShapeTrimPath
|
||||
|
||||
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[self _mapFromJSON:jsonDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
|
||||
|
||||
if (jsonDictionary[@"nm"] ) {
|
||||
_keyname = [jsonDictionary[@"nm"] copy];
|
||||
}
|
||||
|
||||
NSDictionary *start = jsonDictionary[@"s"];
|
||||
if (start) {
|
||||
_start = [[LOTKeyframeGroup alloc] initWithData:start];
|
||||
}
|
||||
|
||||
NSDictionary *end = jsonDictionary[@"e"];
|
||||
if (end) {
|
||||
_end = [[LOTKeyframeGroup alloc] initWithData:end];
|
||||
}
|
||||
|
||||
NSDictionary *offset = jsonDictionary[@"o"];
|
||||
if (offset) {
|
||||
_offset = [[LOTKeyframeGroup alloc] initWithData:offset];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
140
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimatedControl.m
generated
Normal file
140
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimatedControl.m
generated
Normal file
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// LOTAnimatedControl.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 8/25/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTAnimatedControl.h"
|
||||
#import "LOTAnimationView_Internal.h"
|
||||
|
||||
@implementation LOTAnimatedControl {
|
||||
UIControlState _priorState;
|
||||
NSMutableDictionary *_layerMap;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self _commonInit];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
self = [super initWithCoder:aDecoder];
|
||||
if (self) {
|
||||
[self _commonInit];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_commonInit {
|
||||
_animationView = [[LOTAnimationView alloc] init];
|
||||
_animationView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
_animationView.userInteractionEnabled = NO;
|
||||
[self addSubview:_animationView];
|
||||
_layerMap = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
- (LOTComposition *)animationComp {
|
||||
return _animationView.sceneModel;
|
||||
}
|
||||
|
||||
- (void)setAnimationComp:(LOTComposition *)animationComp {
|
||||
[_animationView setSceneModel:animationComp];
|
||||
[self checkStateChangedAndUpdate:YES];
|
||||
}
|
||||
|
||||
- (void)setLayerName:(NSString * _Nonnull)layerName forState:(UIControlState)state {
|
||||
_layerMap[@(state)] = layerName;
|
||||
[self checkStateChangedAndUpdate:YES];
|
||||
}
|
||||
|
||||
#pragma mark - Setter Overrides
|
||||
|
||||
- (void)setEnabled:(BOOL)enabled {
|
||||
_priorState = self.state;
|
||||
[super setEnabled:enabled];
|
||||
[self checkStateChangedAndUpdate:NO];
|
||||
}
|
||||
|
||||
- (void)setSelected:(BOOL)selected {
|
||||
_priorState = self.state;
|
||||
[super setSelected:selected];
|
||||
[self checkStateChangedAndUpdate:NO];
|
||||
}
|
||||
|
||||
- (void)setHighlighted:(BOOL)highlighted {
|
||||
_priorState = self.state;
|
||||
[super setHighlighted:highlighted];
|
||||
[self checkStateChangedAndUpdate:NO];
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
_priorState = self.state;
|
||||
[super touchesBegan:touches withEvent:event];
|
||||
[self checkStateChangedAndUpdate:NO];
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
_priorState = self.state;
|
||||
[super touchesMoved:touches withEvent:event];
|
||||
[self checkStateChangedAndUpdate:NO];
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
_priorState = self.state;
|
||||
[super touchesEnded:touches withEvent:event];
|
||||
[self checkStateChangedAndUpdate:NO];
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
_priorState = self.state;
|
||||
[super touchesCancelled:touches withEvent:event];
|
||||
[self checkStateChangedAndUpdate:NO];
|
||||
}
|
||||
|
||||
- (CGSize)intrinsicContentSize {
|
||||
return _animationView.intrinsicContentSize;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
_animationView.frame = self.bounds;
|
||||
}
|
||||
|
||||
- (UIAccessibilityTraits)accessibilityTraits {
|
||||
return UIAccessibilityTraitButton;
|
||||
}
|
||||
|
||||
- (BOOL)isAccessibilityElement
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private interface implementation
|
||||
|
||||
- (void)checkStateChangedAndUpdate:(BOOL)forceUpdate {
|
||||
if (self.state == _priorState && !forceUpdate) {
|
||||
return;
|
||||
}
|
||||
_priorState = self.state;
|
||||
|
||||
NSString *name = _layerMap[@(self.state)];
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
CALayer *layer = [_animationView layerForKey:name];
|
||||
if (!layer) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (CALayer *child in [_animationView compositionLayers]) {
|
||||
child.hidden = YES;
|
||||
}
|
||||
layer.hidden = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
199
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimatedSwitch.m
generated
Normal file
199
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimatedSwitch.m
generated
Normal file
@@ -0,0 +1,199 @@
|
||||
//
|
||||
// LOTAnimatedSwitch.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 8/25/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTAnimatedSwitch.h"
|
||||
#import "LOTAnimationView.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTAnimatedSwitch {
|
||||
CGFloat _onStartProgress;
|
||||
CGFloat _onEndProgress;
|
||||
CGFloat _offStartProgress;
|
||||
CGFloat _offEndProgress;
|
||||
CGPoint _touchTrackingStart;
|
||||
BOOL _on;
|
||||
BOOL _suppressToggle;
|
||||
BOOL _toggleToState;
|
||||
}
|
||||
|
||||
/// Convenience method to initialize a control from the Main Bundle by name
|
||||
+ (instancetype _Nonnull)switchNamed:(NSString * _Nonnull)toggleName {
|
||||
return [self switchNamed:toggleName inBundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
/// Convenience method to initialize a control from the specified bundle by name
|
||||
+ (instancetype _Nonnull)switchNamed:(NSString * _Nonnull)toggleName inBundle:(NSBundle * _Nonnull)bundle {
|
||||
LOTComposition *composition = [LOTComposition animationNamed:toggleName inBundle:bundle];
|
||||
LOTAnimatedSwitch *animatedControl = [[self alloc] initWithFrame:CGRectZero];
|
||||
if (composition) {
|
||||
[animatedControl setAnimationComp:composition];
|
||||
animatedControl.bounds = composition.compBounds;
|
||||
}
|
||||
return animatedControl;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
self.accessibilityHint = NSLocalizedString(@"Double tap to toggle setting.", @"Double tap to toggle setting.");
|
||||
_onStartProgress = 0;
|
||||
_onEndProgress = 1;
|
||||
_offStartProgress = 1;
|
||||
_offEndProgress = 0;
|
||||
_on = NO;
|
||||
[self addTarget:self action:@selector(_toggle) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setAnimationComp:(LOTComposition *)animationComp {
|
||||
[super setAnimationComp:animationComp];
|
||||
[self setOn:_on animated:NO];
|
||||
}
|
||||
|
||||
#pragma mark - External Methods
|
||||
|
||||
- (void)setProgressRangeForOnState:(CGFloat)fromProgress toProgress:(CGFloat)toProgress {
|
||||
_onStartProgress = fromProgress;
|
||||
_onEndProgress = toProgress;
|
||||
[self setOn:_on animated:NO];
|
||||
}
|
||||
|
||||
- (void)setProgressRangeForOffState:(CGFloat)fromProgress toProgress:(CGFloat)toProgress {
|
||||
_offStartProgress = fromProgress;
|
||||
_offEndProgress = toProgress;
|
||||
[self setOn:_on animated:NO];
|
||||
}
|
||||
|
||||
- (void)setOn:(BOOL)on {
|
||||
[self setOn:on animated:NO];
|
||||
}
|
||||
|
||||
- (void)setOn:(BOOL)on animated:(BOOL)animated {
|
||||
_on = on;
|
||||
|
||||
CGFloat startProgress = on ? _onStartProgress : _offStartProgress;
|
||||
CGFloat endProgress = on ? _onEndProgress : _offEndProgress;
|
||||
CGFloat finalProgress = endProgress;
|
||||
if (self.animationView.animationProgress < MIN(startProgress, endProgress) ||
|
||||
self.animationView.animationProgress > MAX(startProgress, endProgress)) {
|
||||
if (self.animationView.animationProgress != (!_on ? _onEndProgress : _offEndProgress)) {
|
||||
// Current progress is in the wrong timeline. Switch.
|
||||
endProgress = on ? _offStartProgress : _onStartProgress;
|
||||
startProgress = on ? _offEndProgress : _onEndProgress;
|
||||
}
|
||||
}
|
||||
|
||||
if (finalProgress == self.animationView.animationProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (animated) {
|
||||
[self.animationView pause];
|
||||
[self.animationView playFromProgress:startProgress toProgress:endProgress withCompletion:^(BOOL animationFinished) {
|
||||
if (animationFinished) {
|
||||
self.animationView.animationProgress = finalProgress;
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
self.animationView.animationProgress = endProgress;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityValue {
|
||||
return self.isOn ? NSLocalizedString(@"On", @"On") : NSLocalizedString(@"Off", @"Off");
|
||||
}
|
||||
|
||||
#pragma mark - Internal Methods
|
||||
|
||||
- (void)_toggle {
|
||||
if (!_suppressToggle) {
|
||||
[self _toggleAndSendActions];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_toggleAndSendActions {
|
||||
if (self.isEnabled) {
|
||||
#ifndef TARGET_OS_TV
|
||||
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
|
||||
UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
|
||||
[generator impactOccurred];
|
||||
}
|
||||
#endif
|
||||
[self setOn:!_on animated:YES];
|
||||
[self sendActionsForControlEvents:UIControlEventValueChanged];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
|
||||
[super beginTrackingWithTouch:touch withEvent:event];
|
||||
_suppressToggle = NO;
|
||||
_touchTrackingStart = [touch locationInView:self];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
|
||||
BOOL superContinue = [super continueTrackingWithTouch:touch withEvent:event];
|
||||
if (!_interactiveGesture) {
|
||||
return superContinue;
|
||||
}
|
||||
CGPoint location = [touch locationInView:self];
|
||||
CGFloat diff = location.x - _touchTrackingStart.x;
|
||||
if (LOT_PointDistanceFromPoint(_touchTrackingStart, location) > self.bounds.size.width * 0.25) {
|
||||
// The touch has moved enough to register as its own gesture. Suppress the touch up toggle.
|
||||
_suppressToggle = YES;
|
||||
}
|
||||
#ifdef __IPHONE_11_0
|
||||
// Xcode 9+
|
||||
if (@available(iOS 9.0, *)) {
|
||||
#else
|
||||
// Xcode 8-
|
||||
if ([UIView respondsToSelector:@selector(userInterfaceLayoutDirectionForSemanticContentAttribute:)]) {
|
||||
#endif
|
||||
if ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:self.semanticContentAttribute] == UIUserInterfaceLayoutDirectionRightToLeft) {
|
||||
diff = diff * -1;
|
||||
}
|
||||
}
|
||||
if (_on) {
|
||||
diff = diff * -1;
|
||||
if (diff <= 0) {
|
||||
self.animationView.animationProgress = _onEndProgress;
|
||||
_toggleToState = YES;
|
||||
} else {
|
||||
diff = MAX(MIN(self.bounds.size.width, diff), 0);
|
||||
self.animationView.animationProgress = LOT_RemapValue(diff, 0, self.bounds.size.width, _offStartProgress, _offEndProgress);
|
||||
_toggleToState = (diff / self.bounds.size.width) > 0.5 ? NO : YES;
|
||||
}
|
||||
} else {
|
||||
if (diff <= 0) {
|
||||
self.animationView.animationProgress = _offEndProgress;
|
||||
_toggleToState = NO;
|
||||
} else {
|
||||
diff = MAX(MIN(self.bounds.size.width, diff), 0);
|
||||
self.animationView.animationProgress = LOT_RemapValue(diff, 0, self.bounds.size.width, _onStartProgress, _onEndProgress);
|
||||
_toggleToState = (diff / self.bounds.size.width) > 0.5 ? YES : NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
|
||||
[super endTrackingWithTouch:touch withEvent:event];
|
||||
if (!_interactiveGesture) {
|
||||
return;
|
||||
}
|
||||
if (_suppressToggle) {
|
||||
if (_toggleToState != _on) {
|
||||
[self _toggleAndSendActions];
|
||||
} else {
|
||||
[self setOn:_toggleToState animated:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
73
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimationCache.m
generated
Normal file
73
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimationCache.m
generated
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// LOTAnimationCache.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by Brandon Withrow on 1/9/17.
|
||||
// Copyright © 2017 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTAnimationCache.h"
|
||||
|
||||
const NSInteger kLOTCacheSize = 50;
|
||||
|
||||
@implementation LOTAnimationCache {
|
||||
NSMutableDictionary *animationsCache_;
|
||||
NSMutableArray *lruOrderArray_;
|
||||
}
|
||||
|
||||
+ (instancetype)sharedCache {
|
||||
static LOTAnimationCache *sharedCache = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedCache = [[self alloc] init];
|
||||
});
|
||||
return sharedCache;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
animationsCache_ = [[NSMutableDictionary alloc] init];
|
||||
lruOrderArray_ = [[NSMutableArray alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)addAnimation:(LOTComposition *)animation forKey:(NSString *)key {
|
||||
if (lruOrderArray_.count >= kLOTCacheSize) {
|
||||
NSString *oldKey = lruOrderArray_[0];
|
||||
[animationsCache_ removeObjectForKey:oldKey];
|
||||
[lruOrderArray_ removeObject:oldKey];
|
||||
}
|
||||
[lruOrderArray_ removeObject:key];
|
||||
[lruOrderArray_ addObject:key];
|
||||
[animationsCache_ setObject:animation forKey:key];
|
||||
}
|
||||
|
||||
- (LOTComposition *)animationForKey:(NSString *)key {
|
||||
if (!key) {
|
||||
return nil;
|
||||
}
|
||||
LOTComposition *animation = [animationsCache_ objectForKey:key];
|
||||
[lruOrderArray_ removeObject:key];
|
||||
[lruOrderArray_ addObject:key];
|
||||
return animation;
|
||||
}
|
||||
|
||||
- (void)clearCache {
|
||||
[animationsCache_ removeAllObjects];
|
||||
[lruOrderArray_ removeAllObjects];
|
||||
}
|
||||
|
||||
- (void)removeAnimationForKey:(NSString *)key {
|
||||
[lruOrderArray_ removeObject:key];
|
||||
[animationsCache_ removeObjectForKey:key];
|
||||
}
|
||||
|
||||
- (void)disableCaching {
|
||||
[self clearCache];
|
||||
animationsCache_ = nil;
|
||||
lruOrderArray_ = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
127
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimationTransitionController.m
generated
Normal file
127
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimationTransitionController.m
generated
Normal file
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// LOTAnimationTransitionController.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by Brandon Withrow on 1/18/17.
|
||||
// Copyright © 2017 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTAnimationTransitionController.h"
|
||||
#import "LOTAnimationView.h"
|
||||
|
||||
@implementation LOTAnimationTransitionController {
|
||||
LOTAnimationView *transitionAnimationView_;
|
||||
NSString *fromLayerName_;
|
||||
NSString *toLayerName_;
|
||||
NSBundle *inBundle_;
|
||||
BOOL _applyTransform;
|
||||
}
|
||||
|
||||
- (nonnull instancetype)initWithAnimationNamed:(nonnull NSString *)animation
|
||||
fromLayerNamed:(nullable NSString *)fromLayer
|
||||
toLayerNamed:(nullable NSString *)toLayer
|
||||
applyAnimationTransform:(BOOL)applyAnimationTransform {
|
||||
|
||||
return [self initWithAnimationNamed:animation
|
||||
fromLayerNamed:fromLayer
|
||||
toLayerNamed:toLayer
|
||||
applyAnimationTransform:applyAnimationTransform
|
||||
inBundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithAnimationNamed:(NSString *)animation
|
||||
fromLayerNamed:(NSString *)fromLayer
|
||||
toLayerNamed:(NSString *)toLayer
|
||||
applyAnimationTransform:(BOOL)applyAnimationTransform
|
||||
inBundle:(NSBundle *)bundle {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
transitionAnimationView_ = [LOTAnimationView animationNamed:animation inBundle:bundle];
|
||||
fromLayerName_ = fromLayer;
|
||||
toLayerName_ = toLayer;
|
||||
_applyTransform = applyAnimationTransform;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
|
||||
return transitionAnimationView_.animationDuration;
|
||||
}
|
||||
|
||||
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
|
||||
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
|
||||
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
|
||||
UIView *containerView = transitionContext.containerView;
|
||||
|
||||
UIView *toSnapshot = [toVC.view resizableSnapshotViewFromRect:containerView.bounds
|
||||
afterScreenUpdates:YES
|
||||
withCapInsets:UIEdgeInsetsZero];
|
||||
toSnapshot.frame = containerView.bounds;
|
||||
|
||||
UIView *fromSnapshot = [fromVC.view resizableSnapshotViewFromRect:containerView.bounds
|
||||
afterScreenUpdates:NO
|
||||
withCapInsets:UIEdgeInsetsZero];
|
||||
fromSnapshot.frame = containerView.bounds;
|
||||
|
||||
transitionAnimationView_.frame = containerView.bounds;
|
||||
transitionAnimationView_.contentMode = UIViewContentModeScaleAspectFill;
|
||||
[containerView addSubview:transitionAnimationView_];
|
||||
|
||||
BOOL crossFadeViews = NO;
|
||||
|
||||
if (toLayerName_.length) {
|
||||
LOTKeypath *toKeypath = [LOTKeypath keypathWithString:toLayerName_];
|
||||
CGRect convertedBounds = [transitionAnimationView_ convertRect:containerView.bounds toKeypathLayer:toKeypath];
|
||||
toSnapshot.frame = convertedBounds;
|
||||
if (_applyTransform) {
|
||||
[transitionAnimationView_ addSubview:toSnapshot toKeypathLayer:toKeypath];
|
||||
} else {
|
||||
[transitionAnimationView_ maskSubview:toSnapshot toKeypathLayer:toKeypath];
|
||||
}
|
||||
} else {
|
||||
[containerView addSubview:toSnapshot];
|
||||
[containerView sendSubviewToBack:toSnapshot];
|
||||
toSnapshot.alpha = 0;
|
||||
crossFadeViews = YES;
|
||||
}
|
||||
|
||||
if (fromLayerName_.length) {
|
||||
LOTKeypath *fromKeypath = [LOTKeypath keypathWithString:fromLayerName_];
|
||||
CGRect convertedBounds = [transitionAnimationView_ convertRect:containerView.bounds fromKeypathLayer:fromKeypath];
|
||||
fromSnapshot.frame = convertedBounds;
|
||||
if (_applyTransform) {
|
||||
[transitionAnimationView_ addSubview:fromSnapshot toKeypathLayer:fromKeypath];
|
||||
} else {
|
||||
[transitionAnimationView_ maskSubview:fromSnapshot toKeypathLayer:fromKeypath];
|
||||
}
|
||||
} else {
|
||||
[containerView addSubview:fromSnapshot];
|
||||
[containerView sendSubviewToBack:fromSnapshot];
|
||||
}
|
||||
|
||||
[containerView addSubview:toVC.view];
|
||||
toVC.view.hidden = YES;
|
||||
|
||||
if (crossFadeViews) {
|
||||
CGFloat duration = transitionAnimationView_.animationDuration * 0.25;
|
||||
CGFloat delay = (transitionAnimationView_.animationDuration - duration) / 2.f;
|
||||
|
||||
[UIView animateWithDuration:duration
|
||||
delay:delay
|
||||
options:(UIViewAnimationOptionCurveEaseInOut)
|
||||
animations:^{
|
||||
toSnapshot.alpha = 1;
|
||||
} completion:^(BOOL finished) {
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
[transitionAnimationView_ playWithCompletion:^(BOOL animationFinished) {
|
||||
toVC.view.hidden = false;
|
||||
[self->transitionAnimationView_ removeFromSuperview];
|
||||
[transitionContext completeTransition:animationFinished];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
916
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimationView.m
generated
Normal file
916
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimationView.m
generated
Normal file
@@ -0,0 +1,916 @@
|
||||
//
|
||||
// LOTAnimationView
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTAnimationView.h"
|
||||
#import "LOTPlatformCompat.h"
|
||||
#import "LOTModels.h"
|
||||
#import "LOTHelpers.h"
|
||||
#import "LOTAnimationView_Internal.h"
|
||||
#import "LOTAnimationCache.h"
|
||||
#import "LOTCompositionContainer.h"
|
||||
|
||||
#define kCompContainerTransformKey @"compContainerTransformKey"
|
||||
#define kCompContainerPositionKey @"compContainerPositionKey"
|
||||
|
||||
static NSString * const kCompContainerAnimationKey = @"play";
|
||||
|
||||
@implementation LOTAnimationView {
|
||||
LOTCompositionContainer *_compContainer;
|
||||
NSNumber *_playRangeStartFrame;
|
||||
NSNumber *_playRangeEndFrame;
|
||||
CGFloat _playRangeStartProgress;
|
||||
CGFloat _playRangeEndProgress;
|
||||
NSBundle *_bundle;
|
||||
CGFloat _animationProgress;
|
||||
// Properties for tracking automatic restoration of animation.
|
||||
BOOL _shouldRestoreStateWhenAttachedToWindow;
|
||||
LOTAnimationCompletionBlock _completionBlockToRestoreWhenAttachedToWindow;
|
||||
}
|
||||
|
||||
# pragma mark - Convenience Initializers
|
||||
|
||||
+ (nonnull instancetype)animationNamed:(nonnull NSString *)animationName {
|
||||
return [self animationNamed:animationName inBundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
+ (nonnull instancetype)animationNamed:(nonnull NSString *)animationName inBundle:(nonnull NSBundle *)bundle {
|
||||
LOTComposition *comp = [LOTComposition animationNamed:animationName inBundle:bundle];
|
||||
return [[self alloc] initWithModel:comp inBundle:bundle];
|
||||
}
|
||||
|
||||
+ (nonnull instancetype)animationFromJSON:(nonnull NSDictionary *)animationJSON {
|
||||
return [self animationFromJSON:animationJSON inBundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
+ (nonnull instancetype)animationFromJSON:(nullable NSDictionary *)animationJSON inBundle:(nullable NSBundle *)bundle {
|
||||
LOTComposition *comp = [LOTComposition animationFromJSON:animationJSON inBundle:bundle];
|
||||
return [[self alloc] initWithModel:comp inBundle:bundle];
|
||||
}
|
||||
|
||||
+ (nonnull instancetype)animationWithFilePath:(nonnull NSString *)filePath {
|
||||
LOTComposition *comp = [LOTComposition animationWithFilePath:filePath];
|
||||
return [[self alloc] initWithModel:comp inBundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
# pragma mark - Initializers
|
||||
|
||||
- (instancetype)initWithContentsOfURL:(NSURL *)url {
|
||||
return [self initWithContentsOfURL:url errorBlock:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithContentsOfURL:(NSURL *)url
|
||||
errorBlock:(nullable LOTInitializationErrorBlock)errorBlock {
|
||||
self = [self initWithFrame:CGRectZero];
|
||||
if (self) {
|
||||
LOTComposition *laScene = [[LOTAnimationCache sharedCache] animationForKey:url.absoluteString];
|
||||
if (laScene) {
|
||||
laScene.cacheKey = url.absoluteString;
|
||||
[self _initializeAnimationContainer];
|
||||
[self _setupWithSceneModel:laScene];
|
||||
} else {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
|
||||
NSError *error;
|
||||
NSData *animationData = [NSData dataWithContentsOfURL:url options:0 error:&error];
|
||||
if (error || !animationData) {
|
||||
if (errorBlock) {
|
||||
errorBlock(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
NSDictionary *animationJSON = [NSJSONSerialization JSONObjectWithData:animationData
|
||||
options:0 error:&error];
|
||||
if (error || !animationJSON) {
|
||||
if (errorBlock) {
|
||||
errorBlock(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LOTComposition *laScene = [[LOTComposition alloc] initWithJSON:animationJSON withAssetBundle:[NSBundle mainBundle]];
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
[[LOTAnimationCache sharedCache] addAnimation:laScene forKey:url.absoluteString];
|
||||
laScene.cacheKey = url.absoluteString;
|
||||
[self _initializeAnimationContainer];
|
||||
[self _setupWithSceneModel:laScene];
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithModel:(LOTComposition *)model inBundle:(NSBundle *)bundle {
|
||||
self = [self initWithFrame:model.compBounds];
|
||||
if (self) {
|
||||
_bundle = bundle;
|
||||
[self _initializeAnimationContainer];
|
||||
[self _setupWithSceneModel:model];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
[self _commonInit];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder {
|
||||
self = [super initWithCoder:coder];
|
||||
if (self) {
|
||||
[self _commonInit];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
# pragma mark - Inspectables
|
||||
|
||||
- (void)setAnimation:(NSString *)animationName {
|
||||
|
||||
_animation = animationName;
|
||||
|
||||
[self setAnimationNamed:animationName];
|
||||
|
||||
}
|
||||
|
||||
# pragma mark - Internal Methods
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
|
||||
- (void)_initializeAnimationContainer {
|
||||
self.clipsToBounds = YES;
|
||||
}
|
||||
|
||||
- (void)_commonInit {
|
||||
_animationSpeed = 1;
|
||||
_animationProgress = 0;
|
||||
_loopAnimation = NO;
|
||||
_repeatCount = 1;
|
||||
_autoReverseAnimation = NO;
|
||||
_playRangeEndFrame = nil;
|
||||
_playRangeStartFrame = nil;
|
||||
_playRangeEndProgress = 0;
|
||||
_playRangeStartProgress = 0;
|
||||
_shouldRasterizeWhenIdle = NO;
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(_handleWillEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(_handleWillEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
- (void)_initializeAnimationContainer {
|
||||
self.wantsLayer = YES;
|
||||
}
|
||||
|
||||
- (void)_commonInit {
|
||||
_animationSpeed = 1;
|
||||
_animationProgress = 0;
|
||||
_loopAnimation = NO;
|
||||
_repeatCount = 1;
|
||||
_autoReverseAnimation = NO;
|
||||
_playRangeEndFrame = nil;
|
||||
_playRangeStartFrame = nil;
|
||||
_playRangeEndProgress = 0;
|
||||
_playRangeStartProgress = 0;
|
||||
_shouldRasterizeWhenIdle = NO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
- (void)dealloc {
|
||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)_setupWithSceneModel:(LOTComposition *)model {
|
||||
if (_sceneModel) {
|
||||
[self _removeCurrentAnimationIfNecessary];
|
||||
[self _callCompletionIfNecessary:NO];
|
||||
[_compContainer removeFromSuperlayer];
|
||||
_compContainer = nil;
|
||||
_sceneModel = nil;
|
||||
[self _commonInit];
|
||||
}
|
||||
|
||||
_sceneModel = model;
|
||||
_compContainer = [[LOTCompositionContainer alloc] initWithModel:nil inLayerGroup:nil withLayerGroup:_sceneModel.layerGroup withAssestGroup:_sceneModel.assetGroup];
|
||||
[self.layer addSublayer:_compContainer];
|
||||
[self _restoreState];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)_restoreState {
|
||||
if (_isAnimationPlaying) {
|
||||
_isAnimationPlaying = NO;
|
||||
if (_playRangeStartFrame && _playRangeEndFrame) {
|
||||
[self playFromFrame:_playRangeStartFrame toFrame:_playRangeEndFrame withCompletion:self.completionBlock];
|
||||
} else if (_playRangeEndProgress != _playRangeStartProgress) {
|
||||
[self playFromProgress:_playRangeStartProgress toProgress:_playRangeEndProgress withCompletion:self.completionBlock];
|
||||
} else {
|
||||
[self playWithCompletion:self.completionBlock];
|
||||
}
|
||||
} else {
|
||||
self.animationProgress = _animationProgress;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_removeCurrentAnimationIfNecessary {
|
||||
_isAnimationPlaying = NO;
|
||||
[_compContainer removeAllAnimations];
|
||||
_compContainer.shouldRasterize = _shouldRasterizeWhenIdle;
|
||||
}
|
||||
|
||||
- (CGFloat)_progressForFrame:(NSNumber *)frame {
|
||||
if (!_sceneModel) {
|
||||
return 0;
|
||||
}
|
||||
return ((frame.floatValue - _sceneModel.startFrame.floatValue) / (_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue));
|
||||
}
|
||||
|
||||
- (NSNumber *)_frameForProgress:(CGFloat)progress {
|
||||
if (!_sceneModel) {
|
||||
return @0;
|
||||
}
|
||||
return @(((_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue) * progress) + _sceneModel.startFrame.floatValue);
|
||||
}
|
||||
|
||||
- (BOOL)_isSpeedNegative {
|
||||
// If the animation speed is negative, then we're moving backwards.
|
||||
return _animationSpeed >= 0;
|
||||
}
|
||||
|
||||
- (void)_handleWindowChanges:(BOOL)hasNewWindow
|
||||
{
|
||||
// When this view or its superview is leaving the screen, e.g. a modal is presented or another
|
||||
// screen is pushed, this method will get called with newWindow value set to nil - indicating that
|
||||
// this view will be detached from the visible window.
|
||||
// When a view is detached, animations will stop - but will not automatically resumed when it's
|
||||
// re-attached back to window, e.g. when the presented modal is dismissed or another screen is
|
||||
// pop.
|
||||
if (hasNewWindow) {
|
||||
// The view is being re-attached, resume animation if needed.
|
||||
if (_shouldRestoreStateWhenAttachedToWindow) {
|
||||
_shouldRestoreStateWhenAttachedToWindow = NO;
|
||||
|
||||
_isAnimationPlaying = YES;
|
||||
_completionBlock = _completionBlockToRestoreWhenAttachedToWindow;
|
||||
_completionBlockToRestoreWhenAttachedToWindow = nil;
|
||||
|
||||
[self performSelector:@selector(_restoreState) withObject:nil afterDelay:0 inModes:@[NSRunLoopCommonModes]];
|
||||
}
|
||||
} else {
|
||||
// The view is being detached, capture information that need to be restored later.
|
||||
if (_isAnimationPlaying) {
|
||||
LOTAnimationCompletionBlock completion = _completionBlock;
|
||||
[self pause];
|
||||
_shouldRestoreStateWhenAttachedToWindow = YES;
|
||||
_completionBlockToRestoreWhenAttachedToWindow = completion;
|
||||
_completionBlock = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_handleWillEnterBackground {
|
||||
[self _handleWindowChanges: false];
|
||||
}
|
||||
|
||||
- (void)_handleWillEnterForeground {
|
||||
[self _handleWindowChanges: (self.window != nil)];
|
||||
}
|
||||
|
||||
# pragma mark - Completion Block
|
||||
|
||||
- (void)_callCompletionIfNecessary:(BOOL)complete {
|
||||
if (self.completionBlock) {
|
||||
LOTAnimationCompletionBlock completion = self.completionBlock;
|
||||
self.completionBlock = nil;
|
||||
completion(complete);
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark - External Methods
|
||||
|
||||
- (void)setAnimationNamed:(nonnull NSString *)animationName {
|
||||
LOTComposition *comp = [LOTComposition animationNamed:animationName];
|
||||
|
||||
[self _initializeAnimationContainer];
|
||||
[self _setupWithSceneModel:comp];
|
||||
}
|
||||
|
||||
- (void)setAnimationNamed:(NSString *)animationName inBundle:(NSBundle *)bundle {
|
||||
LOTComposition *comp = [LOTComposition animationNamed:animationName inBundle:bundle];
|
||||
|
||||
[self _initializeAnimationContainer];
|
||||
[self _setupWithSceneModel:comp];
|
||||
}
|
||||
|
||||
- (void)setAnimationFromJSON:(nonnull NSDictionary *)animationJSON {
|
||||
LOTComposition *comp = [LOTComposition animationFromJSON:animationJSON];
|
||||
|
||||
[self _initializeAnimationContainer];
|
||||
[self _setupWithSceneModel:comp];
|
||||
}
|
||||
|
||||
- (void)setAnimationFromJSON:(NSDictionary *)animationJSON inBundle:(NSBundle *)bundle {
|
||||
LOTComposition *comp = [LOTComposition animationFromJSON:animationJSON inBundle:bundle];
|
||||
|
||||
[self _initializeAnimationContainer];
|
||||
[self _setupWithSceneModel:comp];
|
||||
}
|
||||
|
||||
# pragma mark - External Methods - Model
|
||||
|
||||
- (void)setSceneModel:(LOTComposition *)sceneModel {
|
||||
[self _setupWithSceneModel:sceneModel];
|
||||
}
|
||||
|
||||
# pragma mark - External Methods - Play Control
|
||||
|
||||
- (void)play {
|
||||
if (!_sceneModel) {
|
||||
_isAnimationPlaying = YES;
|
||||
return;
|
||||
}
|
||||
[self playFromFrame:_sceneModel.startFrame toFrame:_sceneModel.endFrame withCompletion:nil];
|
||||
}
|
||||
|
||||
- (void)playWithCompletion:(LOTAnimationCompletionBlock)completion {
|
||||
if (!_sceneModel) {
|
||||
_isAnimationPlaying = YES;
|
||||
self.completionBlock = completion;
|
||||
return;
|
||||
}
|
||||
[self playFromFrame:_sceneModel.startFrame toFrame:_sceneModel.endFrame withCompletion:completion];
|
||||
}
|
||||
|
||||
- (void)playToProgress:(CGFloat)progress withCompletion:(nullable LOTAnimationCompletionBlock)completion {
|
||||
[self playFromProgress:0 toProgress:progress withCompletion:completion];
|
||||
}
|
||||
|
||||
- (void)playFromProgress:(CGFloat)fromStartProgress
|
||||
toProgress:(CGFloat)toEndProgress
|
||||
withCompletion:(nullable LOTAnimationCompletionBlock)completion {
|
||||
if (!_sceneModel) {
|
||||
_isAnimationPlaying = YES;
|
||||
self.completionBlock = completion;
|
||||
_playRangeStartProgress = fromStartProgress;
|
||||
_playRangeEndProgress = toEndProgress;
|
||||
return;
|
||||
}
|
||||
[self playFromFrame:[self _frameForProgress:fromStartProgress]
|
||||
toFrame:[self _frameForProgress:toEndProgress]
|
||||
withCompletion:completion];
|
||||
}
|
||||
|
||||
- (void)playToFrame:(nonnull NSNumber *)toFrame
|
||||
withCompletion:(nullable LOTAnimationCompletionBlock)completion {
|
||||
[self playFromFrame:_sceneModel.startFrame toFrame:toFrame withCompletion:completion];
|
||||
}
|
||||
|
||||
- (void)playFromFrame:(nonnull NSNumber *)fromStartFrame
|
||||
toFrame:(nonnull NSNumber *)toEndFrame
|
||||
withCompletion:(nullable LOTAnimationCompletionBlock)completion {
|
||||
if (_isAnimationPlaying) {
|
||||
return;
|
||||
}
|
||||
_playRangeStartFrame = fromStartFrame;
|
||||
_playRangeEndFrame = toEndFrame;
|
||||
if (completion) {
|
||||
self.completionBlock = completion;
|
||||
}
|
||||
if (!_sceneModel) {
|
||||
_isAnimationPlaying = YES;
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL playingForward = ((_animationSpeed > 0) && (toEndFrame.floatValue > fromStartFrame.floatValue))
|
||||
|| ((_animationSpeed < 0) && (fromStartFrame.floatValue > toEndFrame.floatValue));
|
||||
|
||||
CGFloat leftFrameValue = MIN(fromStartFrame.floatValue, toEndFrame.floatValue);
|
||||
CGFloat rightFrameValue = MAX(fromStartFrame.floatValue, toEndFrame.floatValue);
|
||||
|
||||
NSNumber *currentFrame = [self _frameForProgress:_animationProgress];
|
||||
|
||||
currentFrame = @(MAX(MIN(currentFrame.floatValue, rightFrameValue), leftFrameValue));
|
||||
|
||||
if (currentFrame.floatValue == rightFrameValue && playingForward) {
|
||||
currentFrame = @(leftFrameValue);
|
||||
} else if (currentFrame.floatValue == leftFrameValue && !playingForward) {
|
||||
currentFrame = @(rightFrameValue);
|
||||
}
|
||||
_animationProgress = [self _progressForFrame:currentFrame];
|
||||
|
||||
CGFloat currentProgress = _animationProgress * (_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue);
|
||||
CGFloat skipProgress;
|
||||
if (playingForward) {
|
||||
skipProgress = currentProgress - leftFrameValue;
|
||||
} else {
|
||||
skipProgress = rightFrameValue - currentProgress;
|
||||
}
|
||||
NSTimeInterval offset = MAX(0, skipProgress) / _sceneModel.framerate.floatValue;
|
||||
if (!self.window) {
|
||||
_shouldRestoreStateWhenAttachedToWindow = YES;
|
||||
_completionBlockToRestoreWhenAttachedToWindow = self.completionBlock;
|
||||
self.completionBlock = nil;
|
||||
} else {
|
||||
NSTimeInterval duration = (ABS(toEndFrame.floatValue - fromStartFrame.floatValue) / _sceneModel.framerate.floatValue);
|
||||
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"currentFrame"];
|
||||
animation.speed = _animationSpeed;
|
||||
animation.fromValue = fromStartFrame;
|
||||
animation.toValue = toEndFrame;
|
||||
animation.duration = duration;
|
||||
animation.fillMode = kCAFillModeBoth;
|
||||
animation.repeatCount = _loopAnimation || _repeatCount < 0 ? HUGE_VALF :_repeatCount;
|
||||
animation.autoreverses = _autoReverseAnimation;
|
||||
animation.delegate = self;
|
||||
animation.removedOnCompletion = NO;
|
||||
if (offset != 0) {
|
||||
CFTimeInterval currentTime = CACurrentMediaTime();
|
||||
CFTimeInterval currentLayerTime = [self.layer convertTime:currentTime fromLayer:nil];
|
||||
animation.beginTime = currentLayerTime - (offset * 1 / _animationSpeed);
|
||||
}
|
||||
[_compContainer addAnimation:animation forKey:kCompContainerAnimationKey];
|
||||
_compContainer.shouldRasterize = NO;
|
||||
}
|
||||
_isAnimationPlaying = YES;
|
||||
}
|
||||
|
||||
#pragma mark - Other Time Controls
|
||||
|
||||
- (void)stop {
|
||||
_isAnimationPlaying = NO;
|
||||
if (_sceneModel) {
|
||||
[self setProgressWithFrame:_sceneModel.startFrame callCompletionIfNecessary:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)pause {
|
||||
if (!_sceneModel ||
|
||||
!_isAnimationPlaying) {
|
||||
_isAnimationPlaying = NO;
|
||||
return;
|
||||
}
|
||||
NSNumber *frame = [_compContainer.presentationLayer.currentFrame copy];
|
||||
[self setProgressWithFrame:frame callCompletionIfNecessary:YES];
|
||||
}
|
||||
|
||||
- (void)setAnimationProgress:(CGFloat)animationProgress {
|
||||
if (!_sceneModel) {
|
||||
_animationProgress = animationProgress;
|
||||
return;
|
||||
}
|
||||
[self setProgressWithFrame:[self _frameForProgress:animationProgress] callCompletionIfNecessary:YES];
|
||||
}
|
||||
|
||||
- (void)setProgressWithFrame:(nonnull NSNumber *)currentFrame {
|
||||
[self setProgressWithFrame:currentFrame callCompletionIfNecessary:YES];
|
||||
}
|
||||
|
||||
- (void)setProgressWithFrame:(nonnull NSNumber *)currentFrame callCompletionIfNecessary:(BOOL)callCompletion {
|
||||
[self _removeCurrentAnimationIfNecessary];
|
||||
|
||||
if (_shouldRestoreStateWhenAttachedToWindow) {
|
||||
_shouldRestoreStateWhenAttachedToWindow = NO;
|
||||
|
||||
self.completionBlock = _completionBlockToRestoreWhenAttachedToWindow;
|
||||
_completionBlockToRestoreWhenAttachedToWindow = nil;
|
||||
}
|
||||
|
||||
_animationProgress = [self _progressForFrame:currentFrame];
|
||||
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
_compContainer.currentFrame = currentFrame;
|
||||
[_compContainer setNeedsDisplay];
|
||||
[CATransaction commit];
|
||||
if (callCompletion) {
|
||||
[self _callCompletionIfNecessary:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setLoopAnimation:(BOOL)loopAnimation {
|
||||
_loopAnimation = loopAnimation;
|
||||
if (_isAnimationPlaying && _sceneModel) {
|
||||
NSNumber *frame = [_compContainer.presentationLayer.currentFrame copy];
|
||||
[self setProgressWithFrame:frame callCompletionIfNecessary:NO];
|
||||
[self playFromFrame:_playRangeStartFrame toFrame:_playRangeEndFrame withCompletion:self.completionBlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setAnimationSpeed:(CGFloat)animationSpeed {
|
||||
_animationSpeed = animationSpeed;
|
||||
if (_isAnimationPlaying && _sceneModel) {
|
||||
NSNumber *frame = [_compContainer.presentationLayer.currentFrame copy];
|
||||
[self setProgressWithFrame:frame callCompletionIfNecessary:NO];
|
||||
[self playFromFrame:_playRangeStartFrame toFrame:_playRangeEndFrame withCompletion:self.completionBlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)forceDrawingUpdate {
|
||||
[self _layoutAndForceUpdate];
|
||||
}
|
||||
|
||||
# pragma mark - External Methods - Idle Rasterization
|
||||
|
||||
- (void)setShouldRasterizeWhenIdle:(BOOL)shouldRasterize {
|
||||
_shouldRasterizeWhenIdle = shouldRasterize;
|
||||
if (!_isAnimationPlaying) {
|
||||
_compContainer.shouldRasterize = _shouldRasterizeWhenIdle;
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark - External Methods - Cache
|
||||
|
||||
- (void)setCacheEnable:(BOOL)cacheEnable {
|
||||
_cacheEnable = cacheEnable;
|
||||
if (!self.sceneModel.cacheKey) {
|
||||
return;
|
||||
}
|
||||
if (cacheEnable) {
|
||||
[[LOTAnimationCache sharedCache] addAnimation:_sceneModel forKey:self.sceneModel.cacheKey];
|
||||
} else {
|
||||
[[LOTAnimationCache sharedCache] removeAnimationForKey:self.sceneModel.cacheKey];
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark - External Methods - Interactive Controls
|
||||
|
||||
- (void)setValueDelegate:(id<LOTValueDelegate> _Nonnull)delegate
|
||||
forKeypath:(LOTKeypath * _Nonnull)keypath {
|
||||
[_compContainer setValueDelegate:delegate forKeypath:keypath];
|
||||
[self _layoutAndForceUpdate];
|
||||
}
|
||||
|
||||
- (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath {
|
||||
return [_compContainer keysForKeyPath:keypath];
|
||||
}
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
return [_compContainer convertPoint:point toKeypathLayer:keypath withParentLayer:self.layer];
|
||||
}
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
return [_compContainer convertRect:rect toKeypathLayer:keypath withParentLayer:self.layer];
|
||||
}
|
||||
|
||||
- (CGPoint)convertPoint:(CGPoint)point
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
return [_compContainer convertPoint:point fromKeypathLayer:keypath withParentLayer:self.layer];
|
||||
}
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
fromKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
return [_compContainer convertRect:rect fromKeypathLayer:keypath withParentLayer:self.layer];
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
|
||||
- (void)addSubview:(nonnull LOTView *)view
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer addSublayer:wrapperView.layer toKeypathLayer:keypath];
|
||||
}
|
||||
|
||||
- (void)maskSubview:(nonnull LOTView *)view
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layoutAndForceUpdate];
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer maskSublayer:wrapperView.layer toKeypathLayer:keypath];
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
- (void)addSubview:(nonnull LOTView *)view
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layout];
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer addSublayer:wrapperView.layer toKeypathLayer:keypath];
|
||||
}
|
||||
|
||||
- (void)maskSubview:(nonnull LOTView *)view
|
||||
toKeypathLayer:(nonnull LOTKeypath *)keypath {
|
||||
[self _layout];
|
||||
CGRect viewRect = view.frame;
|
||||
LOTView *wrapperView = [[LOTView alloc] initWithFrame:viewRect];
|
||||
view.frame = view.bounds;
|
||||
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
[wrapperView addSubview:view];
|
||||
[self addSubview:wrapperView];
|
||||
[_compContainer maskSublayer:wrapperView.layer toKeypathLayer:keypath];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
# pragma mark - Semi-Private Methods
|
||||
|
||||
- (CALayer * _Nullable)layerForKey:(NSString * _Nonnull)keyname {
|
||||
return _compContainer.childMap[keyname];
|
||||
}
|
||||
|
||||
- (NSArray * _Nonnull)compositionLayers {
|
||||
return _compContainer.childLayers;
|
||||
}
|
||||
|
||||
# pragma mark - Getters and Setters
|
||||
|
||||
- (CGFloat)animationDuration {
|
||||
if (!_sceneModel) {
|
||||
return 0;
|
||||
}
|
||||
CAAnimation *play = [_compContainer animationForKey:kCompContainerAnimationKey];
|
||||
if (play) {
|
||||
return play.duration;
|
||||
}
|
||||
return (_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue) / _sceneModel.framerate.floatValue;
|
||||
}
|
||||
|
||||
- (CGFloat)animationProgress {
|
||||
if (_isAnimationPlaying &&
|
||||
_compContainer.presentationLayer) {
|
||||
CGFloat activeProgress = [self _progressForFrame:[(LOTCompositionContainer *)_compContainer.presentationLayer currentFrame]];
|
||||
return activeProgress;
|
||||
}
|
||||
return _animationProgress;
|
||||
}
|
||||
|
||||
# pragma mark - Overrides
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
|
||||
|
||||
#define LOTViewContentMode UIViewContentMode
|
||||
#define LOTViewContentModeScaleToFill UIViewContentModeScaleToFill
|
||||
#define LOTViewContentModeScaleAspectFit UIViewContentModeScaleAspectFit
|
||||
#define LOTViewContentModeScaleAspectFill UIViewContentModeScaleAspectFill
|
||||
#define LOTViewContentModeRedraw UIViewContentModeRedraw
|
||||
#define LOTViewContentModeCenter UIViewContentModeCenter
|
||||
#define LOTViewContentModeTop UIViewContentModeTop
|
||||
#define LOTViewContentModeBottom UIViewContentModeBottom
|
||||
#define LOTViewContentModeLeft UIViewContentModeLeft
|
||||
#define LOTViewContentModeRight UIViewContentModeRight
|
||||
#define LOTViewContentModeTopLeft UIViewContentModeTopLeft
|
||||
#define LOTViewContentModeTopRight UIViewContentModeTopRight
|
||||
#define LOTViewContentModeBottomLeft UIViewContentModeBottomLeft
|
||||
#define LOTViewContentModeBottomRight UIViewContentModeBottomRight
|
||||
|
||||
- (CGSize)intrinsicContentSize {
|
||||
if (!_sceneModel) {
|
||||
return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
|
||||
}
|
||||
return _sceneModel.compBounds.size;
|
||||
}
|
||||
|
||||
- (void)didMoveToSuperview {
|
||||
[super didMoveToSuperview];
|
||||
if (self.superview == nil) {
|
||||
[self _callCompletionIfNecessary:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)willMoveToWindow:(UIWindow *)newWindow {
|
||||
[self _handleWindowChanges:(newWindow != nil)];
|
||||
}
|
||||
|
||||
- (void)didMoveToWindow {
|
||||
#if TARGET_OS_VISION
|
||||
_compContainer.rasterizationScale = 2;
|
||||
#else
|
||||
_compContainer.rasterizationScale = self.window.screen.scale;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setContentMode:(LOTViewContentMode)contentMode {
|
||||
[super setContentMode:contentMode];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
[self _layout];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
- (void)viewWillMoveToWindow:(NSWindow *)newWindow {
|
||||
[self _handleWindowChanges:(newWindow != nil)];
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow {
|
||||
_compContainer.rasterizationScale = self.window.screen.backingScaleFactor;
|
||||
}
|
||||
|
||||
- (void)setCompletionBlock:(LOTAnimationCompletionBlock)completionBlock {
|
||||
if (completionBlock) {
|
||||
_completionBlock = ^(BOOL finished) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{ completionBlock(finished); });
|
||||
};
|
||||
}
|
||||
else {
|
||||
_completionBlock = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setContentMode:(LOTViewContentMode)contentMode {
|
||||
_contentMode = contentMode;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setNeedsLayout {
|
||||
self.needsLayout = YES;
|
||||
}
|
||||
|
||||
- (BOOL)isFlipped {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)wantsUpdateLayer {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)layout {
|
||||
[super layout];
|
||||
[self _layout];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (void)_layoutAndForceUpdate {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
[self _layout];
|
||||
[_compContainer displayWithFrame:_compContainer.currentFrame forceUpdate:YES];
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
- (void)_layout {
|
||||
CGPoint centerPoint = LOT_RectGetCenterPoint(self.bounds);
|
||||
CATransform3D xform;
|
||||
|
||||
if (self.contentMode == LOTViewContentModeScaleToFill) {
|
||||
CGSize scaleSize = CGSizeMake(self.bounds.size.width / self.sceneModel.compBounds.size.width,
|
||||
self.bounds.size.height / self.sceneModel.compBounds.size.height);
|
||||
xform = CATransform3DMakeScale(scaleSize.width, scaleSize.height, 1);
|
||||
} else if (self.contentMode == LOTViewContentModeScaleAspectFit) {
|
||||
CGFloat compAspect = self.sceneModel.compBounds.size.width / self.sceneModel.compBounds.size.height;
|
||||
CGFloat viewAspect = self.bounds.size.width / self.bounds.size.height;
|
||||
BOOL scaleWidth = compAspect > viewAspect;
|
||||
CGFloat dominantDimension = scaleWidth ? self.bounds.size.width : self.bounds.size.height;
|
||||
CGFloat compDimension = scaleWidth ? self.sceneModel.compBounds.size.width : self.sceneModel.compBounds.size.height;
|
||||
CGFloat scale = dominantDimension / compDimension;
|
||||
xform = CATransform3DMakeScale(scale, scale, 1);
|
||||
} else if (self.contentMode == LOTViewContentModeScaleAspectFill) {
|
||||
CGFloat compAspect = self.sceneModel.compBounds.size.width / self.sceneModel.compBounds.size.height;
|
||||
CGFloat viewAspect = self.bounds.size.width / self.bounds.size.height;
|
||||
BOOL scaleWidth = compAspect < viewAspect;
|
||||
CGFloat dominantDimension = scaleWidth ? self.bounds.size.width : self.bounds.size.height;
|
||||
CGFloat compDimension = scaleWidth ? self.sceneModel.compBounds.size.width : self.sceneModel.compBounds.size.height;
|
||||
CGFloat scale = dominantDimension / compDimension;
|
||||
xform = CATransform3DMakeScale(scale, scale, 1);
|
||||
} else {
|
||||
xform = CATransform3DIdentity;
|
||||
}
|
||||
|
||||
// Support use LOTAnimationView with UIView:animate
|
||||
NSArray *animKey = self.layer.animationKeys;
|
||||
CAAnimation *animation;
|
||||
if (animKey && animKey.count > 0) {
|
||||
animation = [self.layer animationForKey:animKey[0]];
|
||||
}
|
||||
|
||||
if (animation) {
|
||||
[_compContainer removeAnimationForKey:kCompContainerPositionKey];
|
||||
[_compContainer removeAnimationForKey:kCompContainerTransformKey];
|
||||
|
||||
id positionAnimCopy = animation.copy;
|
||||
CABasicAnimation *positionAnimation;
|
||||
if (positionAnimCopy && [positionAnimCopy isKindOfClass:CABasicAnimation.class]) {
|
||||
positionAnimation = (CABasicAnimation *)positionAnimCopy;
|
||||
} else {
|
||||
positionAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
|
||||
}
|
||||
positionAnimation.keyPath = @"position";
|
||||
positionAnimation.additive = NO;
|
||||
positionAnimation.fromValue = [NSValue valueWithCGPoint:_compContainer.presentationLayer.position];
|
||||
positionAnimation.toValue = [NSValue valueWithCGPoint:centerPoint];
|
||||
positionAnimation.removedOnCompletion = YES;
|
||||
|
||||
id xformAnimCopy = animation.copy;
|
||||
CABasicAnimation *xformAnimation;
|
||||
if (xformAnimCopy && [xformAnimCopy isKindOfClass:CABasicAnimation.class]) {
|
||||
xformAnimation = (CABasicAnimation *)xformAnimCopy;
|
||||
} else {
|
||||
xformAnimCopy = [CABasicAnimation animationWithKeyPath:@"transform"];
|
||||
}
|
||||
xformAnimation.keyPath = @"transform";
|
||||
xformAnimation.additive = NO;
|
||||
xformAnimation.fromValue = [NSValue valueWithCATransform3D:_compContainer.presentationLayer.transform];
|
||||
xformAnimation.toValue = [NSValue valueWithCATransform3D:xform];
|
||||
xformAnimation.removedOnCompletion = YES;
|
||||
|
||||
_compContainer.transform = CATransform3DIdentity;
|
||||
_compContainer.bounds = _sceneModel.compBounds;
|
||||
_compContainer.viewportBounds = _sceneModel.compBounds;
|
||||
|
||||
_compContainer.position = centerPoint;
|
||||
_compContainer.transform = xform;
|
||||
_compContainer.anchorPoint = self.layer.anchorPoint;
|
||||
|
||||
[_compContainer addAnimation:positionAnimation forKey:kCompContainerPositionKey];
|
||||
[_compContainer addAnimation:xformAnimation forKey:kCompContainerTransformKey];
|
||||
|
||||
} else {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
CATransaction.animationDuration = 0;
|
||||
_compContainer.transform = CATransform3DIdentity;
|
||||
_compContainer.bounds = _sceneModel.compBounds;
|
||||
_compContainer.viewportBounds = _sceneModel.compBounds;
|
||||
_compContainer.transform = xform;
|
||||
_compContainer.position = centerPoint;
|
||||
[CATransaction commit];
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark - CAAnimationDelegate
|
||||
|
||||
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)complete {
|
||||
if ([_compContainer animationForKey:kCompContainerAnimationKey] == anim &&
|
||||
[anim isKindOfClass:[CABasicAnimation class]]) {
|
||||
CABasicAnimation *playAnimation = (CABasicAnimation *)anim;
|
||||
NSNumber *frame = _compContainer.presentationLayer.currentFrame;
|
||||
if (complete) {
|
||||
// Set the final frame based on the animation to/from values. If playing forward, use the
|
||||
// toValue otherwise we want to end on the fromValue.
|
||||
frame = [self _isSpeedNegative] ? (NSNumber *)playAnimation.toValue : (NSNumber *)playAnimation.fromValue;
|
||||
}
|
||||
[self _removeCurrentAnimationIfNecessary];
|
||||
[self setProgressWithFrame:frame callCompletionIfNecessary:NO];
|
||||
[self _callCompletionIfNecessary:complete];
|
||||
}
|
||||
}
|
||||
|
||||
# pragma mark - DEPRECATED
|
||||
|
||||
- (void)addSubview:(nonnull LOTView *)view
|
||||
toLayerNamed:(nonnull NSString *)layer
|
||||
applyTransform:(BOOL)applyTransform {
|
||||
NSLog(@"%s: Function is DEPRECATED. Please use addSubview:forKeypathLayer:", __PRETTY_FUNCTION__);
|
||||
LOTKeypath *keypath = [LOTKeypath keypathWithString:layer];
|
||||
if (applyTransform) {
|
||||
[self addSubview:view toKeypathLayer:keypath];
|
||||
} else {
|
||||
[self maskSubview:view toKeypathLayer:keypath];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGRect)convertRect:(CGRect)rect
|
||||
toLayerNamed:(NSString *_Nullable)layerName {
|
||||
NSLog(@"%s: Function is DEPRECATED. Please use convertRect:forKeypathLayer:", __PRETTY_FUNCTION__);
|
||||
LOTKeypath *keypath = [LOTKeypath keypathWithString:layerName];
|
||||
return [self convertRect:rect toKeypathLayer:keypath];
|
||||
}
|
||||
|
||||
- (void)setValue:(nonnull id)value
|
||||
forKeypath:(nonnull NSString *)keypath
|
||||
atFrame:(nullable NSNumber *)frame {
|
||||
NSLog(@"%s: Function is DEPRECATED and no longer functional. Please use setValueCallback:forKeypath:", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
- (void)logHierarchyKeypaths {
|
||||
NSArray *keypaths = [self keysForKeyPath:[LOTKeypath keypathWithString:@"**"]];
|
||||
for (NSString *keypath in keypaths) {
|
||||
NSLog(@"%@", keypath);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
22
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimationView_Internal.h
generated
Normal file
22
Pods/lottie-ios/lottie-ios/Classes/Private/LOTAnimationView_Internal.h
generated
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// LOTAnimationView_Internal.h
|
||||
// Lottie
|
||||
//
|
||||
// Created by Brandon Withrow on 12/7/16.
|
||||
// Copyright © 2016 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTAnimationView.h"
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
LOTConstraintTypeAlignToBounds,
|
||||
LOTConstraintTypeAlignToLayer,
|
||||
LOTConstraintTypeNone
|
||||
} LOTConstraintType;
|
||||
|
||||
@interface LOTAnimationView () <CAAnimationDelegate>
|
||||
|
||||
- (CALayer * _Nullable)layerForKey:(NSString * _Nonnull)keyname;
|
||||
- (NSArray * _Nonnull)compositionLayers;
|
||||
|
||||
@end
|
||||
80
Pods/lottie-ios/lottie-ios/Classes/Private/LOTBlockCallback.m
generated
Normal file
80
Pods/lottie-ios/lottie-ios/Classes/Private/LOTBlockCallback.m
generated
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// LOTBlockCallback.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 12/15/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTBlockCallback.h"
|
||||
|
||||
@implementation LOTColorBlockCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTColorValueCallbackBlock)block {
|
||||
LOTColorBlockCallback *colorCallback = [[self alloc] init];
|
||||
colorCallback.callback = block;
|
||||
return colorCallback;
|
||||
}
|
||||
|
||||
- (CGColorRef)colorForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startColor:(CGColorRef)startColor endColor:(CGColorRef)endColor currentColor:(CGColorRef)interpolatedColor {
|
||||
return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress, startColor, endColor, interpolatedColor);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTNumberBlockCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTNumberValueCallbackBlock)block {
|
||||
LOTNumberBlockCallback *numberCallback = [[self alloc] init];
|
||||
numberCallback.callback = block;
|
||||
return numberCallback;
|
||||
}
|
||||
|
||||
- (CGFloat)floatValueForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startValue:(CGFloat)startValue endValue:(CGFloat)endValue currentValue:(CGFloat)interpolatedValue {
|
||||
return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress, startValue, endValue, interpolatedValue);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTPointBlockCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTPointValueCallbackBlock)block {
|
||||
LOTPointBlockCallback *callback = [[self alloc] init];
|
||||
callback.callback = block;
|
||||
return callback;
|
||||
}
|
||||
|
||||
- (CGPoint)pointForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint currentPoint:(CGPoint)interpolatedPoint {
|
||||
return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress, startPoint, endPoint, interpolatedPoint);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTSizeBlockCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTSizeValueCallbackBlock)block {
|
||||
LOTSizeBlockCallback *callback = [[self alloc] init];
|
||||
callback.callback = block;
|
||||
return callback;
|
||||
}
|
||||
|
||||
- (CGSize)sizeForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startSize:(CGSize)startSize endSize:(CGSize)endSize currentSize:(CGSize)interpolatedSize {
|
||||
return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress, startSize, endSize, interpolatedSize);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTPathBlockCallback
|
||||
|
||||
+ (instancetype)withBlock:(LOTPathValueCallbackBlock)block {
|
||||
LOTPathBlockCallback *callback = [[self alloc] init];
|
||||
callback.callback = block;
|
||||
return callback;
|
||||
}
|
||||
|
||||
- (CGPathRef)pathForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress {
|
||||
return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
23
Pods/lottie-ios/lottie-ios/Classes/Private/LOTCacheProvider.m
generated
Normal file
23
Pods/lottie-ios/lottie-ios/Classes/Private/LOTCacheProvider.m
generated
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// LOTCacheProvider.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by punmy on 2017/7/8.
|
||||
//
|
||||
//
|
||||
|
||||
#import "LOTCacheProvider.h"
|
||||
|
||||
@implementation LOTCacheProvider
|
||||
|
||||
static id<LOTImageCache> _imageCache;
|
||||
|
||||
+ (id<LOTImageCache>)imageCache {
|
||||
return _imageCache;
|
||||
}
|
||||
|
||||
+ (void)setImageCache:(id<LOTImageCache>)cache {
|
||||
_imageCache = cache;
|
||||
}
|
||||
|
||||
@end
|
||||
142
Pods/lottie-ios/lottie-ios/Classes/Private/LOTComposition.m
generated
Normal file
142
Pods/lottie-ios/lottie-ios/Classes/Private/LOTComposition.m
generated
Normal file
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// LOTScene.m
|
||||
// LottieAnimator
|
||||
//
|
||||
// Created by Brandon Withrow on 12/14/15.
|
||||
// Copyright © 2015 Brandon Withrow. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTComposition.h"
|
||||
#import "LOTLayer.h"
|
||||
#import "LOTAssetGroup.h"
|
||||
#import "LOTLayerGroup.h"
|
||||
#import "LOTAnimationCache.h"
|
||||
|
||||
@implementation LOTComposition
|
||||
|
||||
# pragma mark - Convenience Initializers
|
||||
|
||||
+ (nullable instancetype)animationNamed:(nonnull NSString *)animationName {
|
||||
return [self animationNamed:animationName inBundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
+ (nullable instancetype)animationNamed:(nonnull NSString *)animationName inBundle:(nonnull NSBundle *)bundle {
|
||||
if (!animationName) {
|
||||
return nil;
|
||||
}
|
||||
animationName = [animationName stringByDeletingPathExtension];
|
||||
|
||||
LOTComposition *comp = [[LOTAnimationCache sharedCache] animationForKey:animationName];
|
||||
if (comp) {
|
||||
return comp;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
NSString *filePath = [bundle pathForResource:animationName ofType:@"json"];
|
||||
NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
|
||||
|
||||
if (@available(iOS 9.0, *)) {
|
||||
if (!jsonData) {
|
||||
jsonData = [[NSDataAsset alloc] initWithName:animationName bundle:bundle].data;
|
||||
}
|
||||
}
|
||||
|
||||
NSDictionary *JSONObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
options:0 error:&error] : nil;
|
||||
if (JSONObject && !error) {
|
||||
LOTComposition *laScene = [[self alloc] initWithJSON:JSONObject withAssetBundle:bundle];
|
||||
[[LOTAnimationCache sharedCache] addAnimation:laScene forKey:animationName];
|
||||
laScene.cacheKey = animationName;
|
||||
return laScene;
|
||||
}
|
||||
NSLog(@"%s: Animation Not Found", __PRETTY_FUNCTION__);
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (nullable instancetype)animationWithFilePath:(nonnull NSString *)filePath {
|
||||
NSString *animationName = filePath;
|
||||
|
||||
LOTComposition *comp = [[LOTAnimationCache sharedCache] animationForKey:animationName];
|
||||
if (comp) {
|
||||
return comp;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
|
||||
NSDictionary *JSONObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
options:0 error:&error] : nil;
|
||||
if (JSONObject && !error) {
|
||||
LOTComposition *laScene = [[self alloc] initWithJSON:JSONObject withAssetBundle:[NSBundle mainBundle]];
|
||||
laScene.rootDirectory = [filePath stringByDeletingLastPathComponent];
|
||||
[[LOTAnimationCache sharedCache] addAnimation:laScene forKey:animationName];
|
||||
laScene.cacheKey = animationName;
|
||||
return laScene;
|
||||
}
|
||||
|
||||
NSLog(@"%s: Animation Not Found", __PRETTY_FUNCTION__);
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (nonnull instancetype)animationFromJSON:(nonnull NSDictionary *)animationJSON {
|
||||
return [self animationFromJSON:animationJSON inBundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
+ (nonnull instancetype)animationFromJSON:(nullable NSDictionary *)animationJSON inBundle:(nullable NSBundle *)bundle {
|
||||
return [[self alloc] initWithJSON:animationJSON withAssetBundle:bundle];
|
||||
}
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
- (instancetype _Nonnull)initWithJSON:(NSDictionary * _Nullable)jsonDictionary
|
||||
withAssetBundle:(NSBundle * _Nullable)bundle {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if (jsonDictionary) {
|
||||
[self _mapFromJSON:jsonDictionary withAssetBundle:bundle];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Internal Methods
|
||||
|
||||
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary
|
||||
withAssetBundle:(NSBundle *)bundle {
|
||||
NSNumber *width = jsonDictionary[@"w"];
|
||||
NSNumber *height = jsonDictionary[@"h"];
|
||||
if (width && height) {
|
||||
CGRect bounds = CGRectMake(0, 0, width.floatValue, height.floatValue);
|
||||
_compBounds = bounds;
|
||||
}
|
||||
|
||||
_startFrame = [jsonDictionary[@"ip"] copy];
|
||||
_endFrame = [jsonDictionary[@"op"] copy];
|
||||
_framerate = [jsonDictionary[@"fr"] copy];
|
||||
|
||||
if (_startFrame && _endFrame && _framerate) {
|
||||
NSInteger frameDuration = (_endFrame.integerValue - _startFrame.integerValue) - 1;
|
||||
NSTimeInterval timeDuration = frameDuration / _framerate.floatValue;
|
||||
_timeDuration = timeDuration;
|
||||
}
|
||||
|
||||
NSArray *assetArray = jsonDictionary[@"assets"];
|
||||
if (assetArray.count) {
|
||||
_assetGroup = [[LOTAssetGroup alloc] initWithJSON:assetArray withAssetBundle:bundle withFramerate:_framerate];
|
||||
}
|
||||
|
||||
NSArray *layersJSON = jsonDictionary[@"layers"];
|
||||
if (layersJSON) {
|
||||
_layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON
|
||||
withAssetGroup:_assetGroup
|
||||
withFramerate:_framerate];
|
||||
}
|
||||
|
||||
[_assetGroup finalizeInitializationWithFramerate:_framerate];
|
||||
}
|
||||
|
||||
- (void)setRootDirectory:(NSString *)rootDirectory {
|
||||
_rootDirectory = rootDirectory;
|
||||
self.assetGroup.rootDirectory = rootDirectory;
|
||||
}
|
||||
|
||||
@end
|
||||
56
Pods/lottie-ios/lottie-ios/Classes/Private/LOTInterpolatorCallback.m
generated
Normal file
56
Pods/lottie-ios/lottie-ios/Classes/Private/LOTInterpolatorCallback.m
generated
Normal file
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// LOTInterpolatorCallback.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 1/5/18.
|
||||
// Copyright © 2018 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTInterpolatorCallback.h"
|
||||
#import "CGGeometry+LOTAdditions.h"
|
||||
|
||||
@implementation LOTFloatInterpolatorCallback
|
||||
|
||||
+ (instancetype _Nonnull)withFromFloat:(CGFloat)fromFloat toFloat:(CGFloat)toFloat {
|
||||
LOTFloatInterpolatorCallback *interpolator = [[self alloc] init];
|
||||
interpolator.fromFloat = fromFloat;
|
||||
interpolator.toFloat = toFloat;
|
||||
return interpolator;
|
||||
}
|
||||
- (CGFloat)floatValueForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startValue:(CGFloat)startValue endValue:(CGFloat)endValue currentValue:(CGFloat)interpolatedValue {
|
||||
return LOT_RemapValue(self.currentProgress, 0, 1, self.fromFloat, self.toFloat);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTPointInterpolatorCallback
|
||||
|
||||
+ (instancetype _Nonnull)withFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint {
|
||||
LOTPointInterpolatorCallback *interpolator = [[self alloc] init];
|
||||
interpolator.fromPoint = fromPoint;
|
||||
interpolator.toPoint = toPoint;
|
||||
return interpolator;
|
||||
}
|
||||
- (CGPoint)pointForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint currentPoint:(CGPoint)interpolatedPoint {
|
||||
return LOT_PointInLine(self.fromPoint, self.toPoint, self.currentProgress);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTSizeInterpolatorCallback
|
||||
|
||||
+ (instancetype)withFromSize:(CGSize)fromSize toSize:(CGSize)toSize {
|
||||
LOTSizeInterpolatorCallback *interpolator = [[self alloc] init];
|
||||
interpolator.fromSize = fromSize;
|
||||
interpolator.toSize = toSize;
|
||||
return interpolator;
|
||||
}
|
||||
|
||||
- (CGSize)sizeForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startSize:(CGSize)startSize endSize:(CGSize)endSize currentSize:(CGSize)interpolatedSize {
|
||||
CGPoint from = CGPointMake(self.fromSize.width, self.fromSize.height);
|
||||
CGPoint to = CGPointMake(self.toSize.width, self.toSize.height);
|
||||
CGPoint returnPoint = LOT_PointInLine(from, to, self.currentProgress);
|
||||
return CGSizeMake(returnPoint.x, returnPoint.y);
|
||||
}
|
||||
|
||||
@end
|
||||
140
Pods/lottie-ios/lottie-ios/Classes/Private/LOTKeypath.m
generated
Normal file
140
Pods/lottie-ios/lottie-ios/Classes/Private/LOTKeypath.m
generated
Normal file
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// LOTKeypath.m
|
||||
// Lottie_iOS
|
||||
//
|
||||
// Created by brandon_withrow on 12/13/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTKeypath.h"
|
||||
|
||||
NSString *const kLOTKeypathEnd = @"LOTENDKEYPATH";
|
||||
|
||||
@implementation LOTKeypath {
|
||||
NSInteger _currentDepth;
|
||||
NSMutableArray<NSNumber *> *_fuzzyDepthStack;
|
||||
NSMutableArray *_currentStack;
|
||||
NSArray *_keys;
|
||||
NSMutableDictionary *_searchResults;
|
||||
}
|
||||
|
||||
+ (nonnull LOTKeypath *)keypathWithString:(nonnull NSString *)keypath {
|
||||
return [[self alloc] initWithKeys:[keypath componentsSeparatedByString:@"."]];
|
||||
}
|
||||
|
||||
+ (nonnull LOTKeypath *)keypathWithKeys:(nonnull NSString *)firstKey, ... {
|
||||
NSMutableArray *keys = [NSMutableArray array];
|
||||
va_list args;
|
||||
va_start(args, firstKey);
|
||||
for (NSString *arg = firstKey; arg != nil; arg = va_arg(args, NSString*))
|
||||
{
|
||||
[keys addObject:arg];
|
||||
}
|
||||
va_end(args);
|
||||
return [[self alloc] initWithKeys:keys];
|
||||
}
|
||||
|
||||
- (instancetype)initWithKeys:(NSArray *)keys {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_keys = [NSArray arrayWithArray:keys];
|
||||
NSMutableString *absolutePath = [NSMutableString string];
|
||||
for (int i = 0; i < _keys.count; i++) {
|
||||
if (i > 0) {
|
||||
[absolutePath appendString:@"."];
|
||||
}
|
||||
[absolutePath appendString:_keys[i]];
|
||||
}
|
||||
_currentStack = [NSMutableArray array];
|
||||
_absoluteKeypath = absolutePath;
|
||||
_currentDepth = 0;
|
||||
_fuzzyDepthStack = [NSMutableArray array];
|
||||
_searchResults = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)pushKey:(nonnull NSString *)key {
|
||||
if (_currentDepth == _keys.count &&
|
||||
self.hasFuzzyWildcard == NO) {
|
||||
return NO;
|
||||
}
|
||||
NSString *current = self.currentKey;
|
||||
if (self.hasWildcard ||
|
||||
[current isEqualToString:key]) {
|
||||
[_currentStack addObject:[key copy]];
|
||||
_currentDepth ++;
|
||||
if (self.hasFuzzyWildcard) {
|
||||
[_fuzzyDepthStack addObject:@(_currentDepth)];
|
||||
}
|
||||
return YES;
|
||||
} else if (self.hasFuzzyWildcard) {
|
||||
[_currentStack addObject:[key copy]];
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)popKey {
|
||||
if (_currentDepth == 0) {
|
||||
return;
|
||||
}
|
||||
NSInteger stackCount = _currentStack.count;
|
||||
[_currentStack removeLastObject];
|
||||
|
||||
if (self.hasFuzzyWildcard ) {
|
||||
if (stackCount == _fuzzyDepthStack.lastObject.integerValue) {
|
||||
[_fuzzyDepthStack removeLastObject];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_currentDepth --;
|
||||
}
|
||||
|
||||
- (void)popToRootKey {
|
||||
_currentDepth = 0;
|
||||
[_currentStack removeAllObjects];
|
||||
[_fuzzyDepthStack removeAllObjects];
|
||||
}
|
||||
|
||||
- (NSString *)currentKey {
|
||||
if (_currentDepth == _keys.count) {
|
||||
return kLOTKeypathEnd;
|
||||
}
|
||||
return _keys[_currentDepth];
|
||||
}
|
||||
|
||||
- (NSString *)currentKeyPath {
|
||||
return [_currentStack componentsJoinedByString:@"."];
|
||||
}
|
||||
|
||||
- (BOOL)hasWildcard {
|
||||
if (_currentDepth == _keys.count) {
|
||||
return NO;
|
||||
}
|
||||
return ([_keys[_currentDepth] isEqualToString:@"**"] ||
|
||||
[_keys[_currentDepth] isEqualToString:@"*"]);
|
||||
}
|
||||
|
||||
- (BOOL)hasFuzzyWildcard {
|
||||
if (_currentDepth == 0 ||
|
||||
_currentDepth > _keys.count) {
|
||||
return NO;
|
||||
}
|
||||
return [_keys[_currentDepth - 1] isEqualToString:@"**"];
|
||||
}
|
||||
|
||||
- (BOOL)endOfKeypath {
|
||||
return (_currentDepth == _keys.count);
|
||||
}
|
||||
|
||||
- (void)addSearchResultForCurrentPath:(id _Nonnull)result {
|
||||
[_searchResults setObject:result forKey:self.currentKeyPath];
|
||||
}
|
||||
|
||||
- (NSDictionary *)searchResults {
|
||||
return _searchResults;
|
||||
}
|
||||
|
||||
@end
|
||||
79
Pods/lottie-ios/lottie-ios/Classes/Private/LOTValueCallback.m
generated
Normal file
79
Pods/lottie-ios/lottie-ios/Classes/Private/LOTValueCallback.m
generated
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// LOTValueCallback.m
|
||||
// Lottie
|
||||
//
|
||||
// Created by brandon_withrow on 12/15/17.
|
||||
// Copyright © 2017 Airbnb. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LOTValueCallback.h"
|
||||
|
||||
@implementation LOTColorValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withCGColor:(CGColorRef _Nonnull)color {
|
||||
LOTColorValueCallback *colorCallback = [[self alloc] init];
|
||||
colorCallback.colorValue = color;
|
||||
return colorCallback;
|
||||
}
|
||||
|
||||
- (CGColorRef)colorForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startColor:(CGColorRef)startColor endColor:(CGColorRef)endColor currentColor:(CGColorRef)interpolatedColor {
|
||||
return self.colorValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTNumberValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withFloatValue:(CGFloat)numberValue {
|
||||
LOTNumberValueCallback *numberCallback = [[self alloc] init];
|
||||
numberCallback.numberValue = numberValue;
|
||||
return numberCallback;
|
||||
}
|
||||
|
||||
- (CGFloat)floatValueForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startValue:(CGFloat)startValue endValue:(CGFloat)endValue currentValue:(CGFloat)interpolatedValue {
|
||||
return self.numberValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTPointValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withPointValue:(CGPoint)pointValue {
|
||||
LOTPointValueCallback *callback = [[self alloc] init];
|
||||
callback.pointValue = pointValue;
|
||||
return callback;
|
||||
}
|
||||
|
||||
- (CGPoint)pointForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint currentPoint:(CGPoint)interpolatedPoint {
|
||||
return self.pointValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTSizeValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withPointValue:(CGSize)sizeValue {
|
||||
LOTSizeValueCallback *callback = [[self alloc] init];
|
||||
callback.sizeValue = sizeValue;
|
||||
return callback;
|
||||
}
|
||||
|
||||
- (CGSize)sizeForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startSize:(CGSize)startSize endSize:(CGSize)endSize currentSize:(CGSize)interpolatedSize {
|
||||
return self.sizeValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation LOTPathValueCallback
|
||||
|
||||
+ (instancetype _Nonnull)withCGPath:(CGPathRef _Nonnull)path {
|
||||
LOTPathValueCallback *callback = [[self alloc] init];
|
||||
callback.pathValue = path;
|
||||
return callback;
|
||||
}
|
||||
|
||||
- (CGPathRef)pathForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress {
|
||||
return self.pathValue;
|
||||
}
|
||||
|
||||
@end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user