From a1f459ab48aae72dab7b5aef9f9d1b771c92f479 Mon Sep 17 00:00:00 2001 From: peter-iakovlev Date: Fri, 14 Jun 2019 15:23:33 +0100 Subject: [PATCH 01/26] Create README.md --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000..0353e3d6d5 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Telegram iOS Source Code Compilation Guide + +1. Install the brew package manager, if you haven’t already. +2. Install the packages pkg-config, yasm: +brew install pkg-config yasm +3. Clone the project from GitHub: + +git clone --recursive https://github.com/peter-iakovlev/Telegram-iOS.git + +4. Open Telegram-iOS.workspace. +5. Open the Telegram-iOS-Fork scheme. +6. Replace the contents of Config-Fork.xcconfig with +APP_NAME=Telegram Fork +APP_BUNDLE_ID=fork.telegram.Fork +APP_SPECIFIC_URL_SCHEME=tgfork + +GLOBAL_CONSTANTS = APP_CONFIG_IS_INTERNAL_BUILD=false APP_CONFIG_IS_APPSTORE_BUILD=true APP_CONFIG_APPSTORE_ID=0 APP_SPECIFIC_URL_SCHEME="\"$(APP_SPECIFIC_URL_SCHEME)\"" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GLOBAL_CONSTANTS) + +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) APP_CONFIG_API_ID=8 APP_CONFIG_API_HASH="\"7245de8e747a0d6fbe11f7cc14fcc0bb\"" APP_CONFIG_HOCKEYAPP_ID="\"\"" +7. Replace group ID in Telegram-iOS-Fork.entitlements with group.fork.telegram.Fork. +8. Start the compilation process. +9. To run the app on your device, you will need to set the correct values for the signature, .entitlements files and package IDs in accordance with your developer account values. From 8b51706b53617db455fc729ef670b31ee588fd51 Mon Sep 17 00:00:00 2001 From: peter-iakovlev Date: Fri, 14 Jun 2019 15:25:20 +0100 Subject: [PATCH 02/26] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0353e3d6d5..1b8d55c988 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,14 @@ brew install pkg-config yasm 3. Clone the project from GitHub: +``` git clone --recursive https://github.com/peter-iakovlev/Telegram-iOS.git +``` 4. Open Telegram-iOS.workspace. 5. Open the Telegram-iOS-Fork scheme. 6. Replace the contents of Config-Fork.xcconfig with +``` APP_NAME=Telegram Fork APP_BUNDLE_ID=fork.telegram.Fork APP_SPECIFIC_URL_SCHEME=tgfork @@ -18,6 +21,7 @@ GLOBAL_CONSTANTS = APP_CONFIG_IS_INTERNAL_BUILD=false APP_CONFIG_IS_APPSTORE_BUI GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GLOBAL_CONSTANTS) GCC_PREPROCESSOR_DEFINITIONS = $(inherited) APP_CONFIG_API_ID=8 APP_CONFIG_API_HASH="\"7245de8e747a0d6fbe11f7cc14fcc0bb\"" APP_CONFIG_HOCKEYAPP_ID="\"\"" -7. Replace group ID in Telegram-iOS-Fork.entitlements with group.fork.telegram.Fork. +``` +7. Replace group ID in Telegram-iOS-Fork.entitlements with `group.fork.telegram.Fork`. 8. Start the compilation process. 9. To run the app on your device, you will need to set the correct values for the signature, .entitlements files and package IDs in accordance with your developer account values. From 6d20a702c37d49e56e393f87625a96a24cf654db Mon Sep 17 00:00:00 2001 From: Peter <> Date: Fri, 14 Jun 2019 15:32:26 +0100 Subject: [PATCH 03/26] Update Readme --- README.md | 17 ++--------------- Telegram-iOS/Config-Fork.xcconfig | 2 +- Telegram-iOS/Telegram-iOS-Fork.entitlements | 2 +- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1b8d55c988..3a9768dd90 100644 --- a/README.md +++ b/README.md @@ -8,20 +8,7 @@ brew install pkg-config yasm ``` git clone --recursive https://github.com/peter-iakovlev/Telegram-iOS.git ``` - 4. Open Telegram-iOS.workspace. 5. Open the Telegram-iOS-Fork scheme. -6. Replace the contents of Config-Fork.xcconfig with -``` -APP_NAME=Telegram Fork -APP_BUNDLE_ID=fork.telegram.Fork -APP_SPECIFIC_URL_SCHEME=tgfork - -GLOBAL_CONSTANTS = APP_CONFIG_IS_INTERNAL_BUILD=false APP_CONFIG_IS_APPSTORE_BUILD=true APP_CONFIG_APPSTORE_ID=0 APP_SPECIFIC_URL_SCHEME="\"$(APP_SPECIFIC_URL_SCHEME)\"" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GLOBAL_CONSTANTS) - -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) APP_CONFIG_API_ID=8 APP_CONFIG_API_HASH="\"7245de8e747a0d6fbe11f7cc14fcc0bb\"" APP_CONFIG_HOCKEYAPP_ID="\"\"" -``` -7. Replace group ID in Telegram-iOS-Fork.entitlements with `group.fork.telegram.Fork`. -8. Start the compilation process. -9. To run the app on your device, you will need to set the correct values for the signature, .entitlements files and package IDs in accordance with your developer account values. +6. Start the compilation process. +7. To run the app on your device, you will need to set the correct values for the signature, .entitlements files and package IDs in accordance with your developer account values. diff --git a/Telegram-iOS/Config-Fork.xcconfig b/Telegram-iOS/Config-Fork.xcconfig index 5139070d6f..c3192251c1 100644 --- a/Telegram-iOS/Config-Fork.xcconfig +++ b/Telegram-iOS/Config-Fork.xcconfig @@ -5,4 +5,4 @@ APP_SPECIFIC_URL_SCHEME=tgfork GLOBAL_CONSTANTS = APP_CONFIG_IS_INTERNAL_BUILD=false APP_CONFIG_IS_APPSTORE_BUILD=true APP_CONFIG_APPSTORE_ID=0 APP_SPECIFIC_URL_SCHEME="\"$(APP_SPECIFIC_URL_SCHEME)\"" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GLOBAL_CONSTANTS) -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) APP_CONFIG_API_ID=8 APP_CONFIG_API_HASH="\"7245de8e747a0d6fbe11f7cc14fcc0bb\"" APP_CONFIG_HOCKEYAPP_ID="\"\"" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) APP_CONFIG_API_ID=8 APP_CONFIG_API_HASH="\"7245de8e747a0d6fbe11f7cc14fcc0bb\"" APP_CONFIG_HOCKEYAPP_ID="\"\"" \ No newline at end of file diff --git a/Telegram-iOS/Telegram-iOS-Fork.entitlements b/Telegram-iOS/Telegram-iOS-Fork.entitlements index 3b7b8a376e..b7e410258c 100644 --- a/Telegram-iOS/Telegram-iOS-Fork.entitlements +++ b/Telegram-iOS/Telegram-iOS-Fork.entitlements @@ -13,7 +13,7 @@ com.apple.security.application-groups - group.fork.telegram.Telegram-iOS + group.fork.telegram.Fork From 85f1c9bfad4f59f91465280689c696dedd67f6f5 Mon Sep 17 00:00:00 2001 From: peter-iakovlev Date: Fri, 14 Jun 2019 15:35:34 +0100 Subject: [PATCH 04/26] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3a9768dd90..133afbe21a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ 1. Install the brew package manager, if you haven’t already. 2. Install the packages pkg-config, yasm: +``` brew install pkg-config yasm +``` 3. Clone the project from GitHub: ``` From 5c22aa844238d4b20f59f85ee1a17e83bae1aa88 Mon Sep 17 00:00:00 2001 From: Peter <> Date: Thu, 20 Jun 2019 17:17:06 +0200 Subject: [PATCH 05/26] Simplify reproducible build --- buildbox/guest-build-telegram.sh | 41 ++++++++++++++++++++++---------- fastlane/Fastfile | 4 +++- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/buildbox/guest-build-telegram.sh b/buildbox/guest-build-telegram.sh index ba7bc34620..5db29946be 100644 --- a/buildbox/guest-build-telegram.sh +++ b/buildbox/guest-build-telegram.sh @@ -2,6 +2,8 @@ if [ "$1" == "hockeyapp" ]; then FASTLANE_BUILD_CONFIGURATION="internalhockeyapp" + CERTS_PATH="codesigning_data/certs" + PROFILES_PATH="codesigning_data/profiles" elif [ "$1" == "appstore" ]; then FASTLANE_BUILD_CONFIGURATION="testflight_llc" if [ -z "$TELEGRAM_BUILD_APPSTORE_PASSWORD" ]; then @@ -14,8 +16,16 @@ elif [ "$1" == "appstore" ]; then fi FASTLANE_PASSWORD="$TELEGRAM_BUILD_APPSTORE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$TELEGRAM_BUILD_APPSTORE_TEAM_NAME" + CERTS_PATH="codesigning_data/certs" + PROFILES_PATH="codesigning_data/profiles" elif [ "$1" == "verify" ]; then FASTLANE_BUILD_CONFIGURATION="build_for_appstore" + CERTS_PATH="buildbox/fake-codesigning/certs" + PROFILES_PATH="buildbox/fake-codesigning/profiles" +elif [ "$1" == "verify-local" ]; then + FASTLANE_BUILD_CONFIGURATION="build_for_appstore" + CERTS_PATH="buildbox/fake-codesigning/certs" + PROFILES_PATH="buildbox/fake-codesigning/profiles" else echo "Unknown configuration $1" exit 1 @@ -24,34 +34,39 @@ fi MY_KEYCHAIN="temp.keychain" MY_KEYCHAIN_PASSWORD="secret" +if [ ! -z "$(security list-keychains | grep "$MY_KEYCHAIN")" ]; then + security delete-keychain "$MY_KEYCHAIN" || true +fi security create-keychain -p "$MY_KEYCHAIN_PASSWORD" "$MY_KEYCHAIN" security list-keychains -d user -s "$MY_KEYCHAIN" $(security list-keychains -d user | sed s/\"//g) security set-keychain-settings "$MY_KEYCHAIN" security unlock-keychain -p "$MY_KEYCHAIN_PASSWORD" "$MY_KEYCHAIN" -CERTS_PATH="codesigning_data/certs" for f in $(ls "$CERTS_PATH"); do fastlane run import_certificate "certificate_path:$CERTS_PATH/$f" keychain_name:"$MY_KEYCHAIN" keychain_password:"$MY_KEYCHAIN_PASSWORD" log_output:true done mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles" -PROFILES_PATH="codesigning_data/profiles" for f in $(ls "$PROFILES_PATH"); do PROFILE_PATH="$PROFILES_PATH/$f" uuid=`grep UUID -A1 -a "$PROFILE_PATH" | grep -io "[-A-F0-9]\{36\}"` - cp "$PROFILE_PATH" "$HOME/Library/MobileDevice/Provisioning Profiles/$uuid.mobileprovision" + cp -f "$PROFILE_PATH" "$HOME/Library/MobileDevice/Provisioning Profiles/$uuid.mobileprovision" done -SOURCE_PATH="telegram-ios" +if [ "$1" == "verify-local" ]; then + fastlane "$FASTLANE_BUILD_CONFIGURATION" +else + SOURCE_PATH="telegram-ios" -if [ -d "$SOURCE_PATH" ]; then - echo "$SOURCE_PATH must not exist" - exit 1 + if [ -d "$SOURCE_PATH" ]; then + echo "Directory $SOURCE_PATH should not exist" + exit 1 + fi + + echo "Unpacking files..." + tar -xf "source.tar" + + cd "$SOURCE_PATH" + FASTLANE_PASSWORD="$FASTLANE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$FASTLANE_ITC_TEAM_NAME" fastlane "$FASTLANE_BUILD_CONFIGURATION" fi - -echo "Unpacking files..." -tar -xf "source.tar" - -cd "$SOURCE_PATH" -FASTLANE_PASSWORD="$FASTLANE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$FASTLANE_ITC_TEAM_NAME" fastlane "$FASTLANE_BUILD_CONFIGURATION" diff --git a/fastlane/Fastfile b/fastlane/Fastfile index f8d9f1f6fa..5dffc7a870 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -63,4 +63,6 @@ lane :build_for_appstore do |options| ) end -import "../../Telegram-iOS-Shared/fastlane/Fastfile" +if File.exists?("../../Telegram-iOS-Shared/fastlane/Fastfile") + import "../../Telegram-iOS-Shared/fastlane/Fastfile" +end From 5d50fe1478b459d1de32cc4c5dd0b8027e6e1f84 Mon Sep 17 00:00:00 2001 From: Peter <> Date: Sun, 23 Jun 2019 10:30:48 +0200 Subject: [PATCH 06/26] Experimental BC1 compression --- .../TelegramUI/AnimatedStickerUtils.swift | 9 +- .../TelegramUIPrivate/module.modulemap | 1 + .../project.pbxproj | 48 +++ .../third-party/bc1/BC1Compression.cpp | 300 ++++++++++++++++++ .../third-party/bc1/BC1Compression.h | 51 +++ .../TelegramUI/third-party/bc1/BMPImage.cpp | 213 +++++++++++++ .../TelegramUI/third-party/bc1/BMPImage.h | 59 ++++ .../TelegramUI/third-party/bc1/ColorVec.h | 103 ++++++ .../TelegramUI/third-party/bc1/DDSImage.cpp | 222 +++++++++++++ .../TelegramUI/third-party/bc1/DDSImage.h | 51 +++ .../TelegramUI/third-party/bc1/Image.cpp | 43 +++ submodules/TelegramUI/third-party/bc1/Image.h | 79 +++++ .../third-party/bc1/TextureCompression.cpp | 13 + .../third-party/bc1/TextureCompression.h | 11 + .../third-party/bc1/TypeDefinitions.h | 126 ++++++++ 15 files changed, 1328 insertions(+), 1 deletion(-) create mode 100644 submodules/TelegramUI/third-party/bc1/BC1Compression.cpp create mode 100644 submodules/TelegramUI/third-party/bc1/BC1Compression.h create mode 100644 submodules/TelegramUI/third-party/bc1/BMPImage.cpp create mode 100644 submodules/TelegramUI/third-party/bc1/BMPImage.h create mode 100644 submodules/TelegramUI/third-party/bc1/ColorVec.h create mode 100644 submodules/TelegramUI/third-party/bc1/DDSImage.cpp create mode 100644 submodules/TelegramUI/third-party/bc1/DDSImage.h create mode 100644 submodules/TelegramUI/third-party/bc1/Image.cpp create mode 100644 submodules/TelegramUI/third-party/bc1/Image.h create mode 100644 submodules/TelegramUI/third-party/bc1/TextureCompression.cpp create mode 100644 submodules/TelegramUI/third-party/bc1/TextureCompression.h create mode 100644 submodules/TelegramUI/third-party/bc1/TypeDefinitions.h diff --git a/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift b/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift index d565c29669..ce3fbd0638 100644 --- a/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift +++ b/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift @@ -123,8 +123,12 @@ func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: CGSize) let previousFrameData = malloc(frameLength)! memset(previousFrameData, 0, frameLength) + let bc1FrameData = malloc(frameLength)! + memset(bc1FrameData, 0, frameLength) + defer { free(previousFrameData) + free(bc1FrameData) } var compressedFrameData = Data(count: frameLength) @@ -155,7 +159,6 @@ func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: CGSize) drawingTime += CACurrentMediaTime() - drawStartTime - let appendStartTime = CACurrentMediaTime() compressedFrameData.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in let length = compression_encode_buffer(bytes, compressedFrameDataLength, previousFrameData.assumingMemoryBound(to: UInt8.self), frameLength, scratchData, COMPRESSION_LZ4) var frameLengthValue: Int32 = Int32(length) @@ -165,6 +168,10 @@ func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: CGSize) memcpy(previousFrameData, singleContext.bytes, frameLength) + let appendStartTime = CACurrentMediaTime() + + compressRGBAToBC1(previousFrameData.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), bc1FrameData.assumingMemoryBound(to: UInt8.self)) + appendingTime += CACurrentMediaTime() - appendStartTime currentFrame += 1 } diff --git a/submodules/TelegramUI/TelegramUI/TelegramUIPrivate/module.modulemap b/submodules/TelegramUI/TelegramUI/TelegramUIPrivate/module.modulemap index 959651e6e7..d42155914f 100644 --- a/submodules/TelegramUI/TelegramUI/TelegramUIPrivate/module.modulemap +++ b/submodules/TelegramUI/TelegramUI/TelegramUIPrivate/module.modulemap @@ -23,4 +23,5 @@ module TelegramUIPrivateModule { header "../TGProxyItem.h" header "../UIImage+ImageEffects.h" header "../YUV.h" + header "../../third-party/bc1/TextureCompression.h" } diff --git a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj index b6758ebd22..9d214e3b27 100644 --- a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj +++ b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj @@ -265,6 +265,18 @@ D01590AB22BD467B0017C33E /* AnimationRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01590AA22BD467B0017C33E /* AnimationRenderer.swift */; }; D01590AE22BD58AD0017C33E /* YUV.h in Headers */ = {isa = PBXBuildFile; fileRef = D01590AC22BD58AD0017C33E /* YUV.h */; }; D01590AF22BD58AD0017C33E /* YUV.m in Sources */ = {isa = PBXBuildFile; fileRef = D01590AD22BD58AD0017C33E /* YUV.m */; }; + D01590BA22BDAEBC0017C33E /* ColorVec.h in Headers */ = {isa = PBXBuildFile; fileRef = D01590B022BDAEB30017C33E /* ColorVec.h */; }; + D01590BB22BDAEBC0017C33E /* BC1Compression.h in Headers */ = {isa = PBXBuildFile; fileRef = D01590B122BDAEBB0017C33E /* BC1Compression.h */; }; + D01590BC22BDAEBC0017C33E /* BMPImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D01590B222BDAEBB0017C33E /* BMPImage.h */; }; + D01590BD22BDAEBC0017C33E /* DDSImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D01590B322BDAEBB0017C33E /* DDSImage.cpp */; }; + D01590BE22BDAEBC0017C33E /* Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D01590B422BDAEBB0017C33E /* Image.cpp */; }; + D01590BF22BDAEBC0017C33E /* Image.h in Headers */ = {isa = PBXBuildFile; fileRef = D01590B522BDAEBC0017C33E /* Image.h */; }; + D01590C022BDAEBC0017C33E /* BC1Compression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D01590B622BDAEBC0017C33E /* BC1Compression.cpp */; }; + D01590C122BDAEBC0017C33E /* DDSImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D01590B722BDAEBC0017C33E /* DDSImage.h */; }; + D01590C222BDAEBC0017C33E /* TypeDefinitions.h in Headers */ = {isa = PBXBuildFile; fileRef = D01590B822BDAEBC0017C33E /* TypeDefinitions.h */; }; + D01590C322BDAEBC0017C33E /* BMPImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D01590B922BDAEBC0017C33E /* BMPImage.cpp */; }; + D01590C722BE61CB0017C33E /* TextureCompression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D01590C522BE61CB0017C33E /* TextureCompression.cpp */; }; + D01590C922BE62C40017C33E /* TextureCompression.h in Headers */ = {isa = PBXBuildFile; fileRef = D01590C822BE62C40017C33E /* TextureCompression.h */; }; D015E04F225D2E5900CB9E8A /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D015E04E225D2E5900CB9E8A /* WebP.framework */; }; D017734C22049BF800DA06A7 /* UpgradedAccounts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D017734B22049BF800DA06A7 /* UpgradedAccounts.swift */; }; D01776B31F1D69A80044446D /* RadialStatusNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01776B21F1D69A80044446D /* RadialStatusNode.swift */; }; @@ -1466,6 +1478,18 @@ D01590AA22BD467B0017C33E /* AnimationRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimationRenderer.swift; sourceTree = ""; }; D01590AC22BD58AD0017C33E /* YUV.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YUV.h; sourceTree = ""; }; D01590AD22BD58AD0017C33E /* YUV.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YUV.m; sourceTree = ""; }; + D01590B022BDAEB30017C33E /* ColorVec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ColorVec.h; path = "third-party/bc1/ColorVec.h"; sourceTree = SOURCE_ROOT; }; + D01590B122BDAEBB0017C33E /* BC1Compression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BC1Compression.h; path = "third-party/bc1/BC1Compression.h"; sourceTree = SOURCE_ROOT; }; + D01590B222BDAEBB0017C33E /* BMPImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BMPImage.h; path = "third-party/bc1/BMPImage.h"; sourceTree = SOURCE_ROOT; }; + D01590B322BDAEBB0017C33E /* DDSImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DDSImage.cpp; path = "third-party/bc1/DDSImage.cpp"; sourceTree = SOURCE_ROOT; }; + D01590B422BDAEBB0017C33E /* Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Image.cpp; path = "third-party/bc1/Image.cpp"; sourceTree = SOURCE_ROOT; }; + D01590B522BDAEBC0017C33E /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Image.h; path = "third-party/bc1/Image.h"; sourceTree = SOURCE_ROOT; }; + D01590B622BDAEBC0017C33E /* BC1Compression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BC1Compression.cpp; path = "third-party/bc1/BC1Compression.cpp"; sourceTree = SOURCE_ROOT; }; + D01590B722BDAEBC0017C33E /* DDSImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DDSImage.h; path = "third-party/bc1/DDSImage.h"; sourceTree = SOURCE_ROOT; }; + D01590B822BDAEBC0017C33E /* TypeDefinitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeDefinitions.h; path = "third-party/bc1/TypeDefinitions.h"; sourceTree = SOURCE_ROOT; }; + D01590B922BDAEBC0017C33E /* BMPImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BMPImage.cpp; path = "third-party/bc1/BMPImage.cpp"; sourceTree = SOURCE_ROOT; }; + D01590C522BE61CB0017C33E /* TextureCompression.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TextureCompression.cpp; path = "../third-party/bc1/TextureCompression.cpp"; sourceTree = ""; }; + D01590C822BE62C40017C33E /* TextureCompression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextureCompression.h; path = "third-party/bc1/TextureCompression.h"; sourceTree = SOURCE_ROOT; }; D015E04E225D2E5900CB9E8A /* WebP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = WebP.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D017494D1E1059570057C89A /* StringWithAppliedEntities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringWithAppliedEntities.swift; sourceTree = ""; }; D01749501E1067E40057C89A /* HashtagSearchController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HashtagSearchController.swift; sourceTree = ""; }; @@ -2801,11 +2825,23 @@ D01590A922BD46690017C33E /* Animation */ = { isa = PBXGroup; children = ( + D01590B622BDAEBC0017C33E /* BC1Compression.cpp */, + D01590B122BDAEBB0017C33E /* BC1Compression.h */, + D01590B922BDAEBC0017C33E /* BMPImage.cpp */, + D01590B222BDAEBB0017C33E /* BMPImage.h */, + D01590B022BDAEB30017C33E /* ColorVec.h */, + D01590B322BDAEBB0017C33E /* DDSImage.cpp */, + D01590B722BDAEBC0017C33E /* DDSImage.h */, + D01590B422BDAEBB0017C33E /* Image.cpp */, + D01590B522BDAEBC0017C33E /* Image.h */, + D01590B822BDAEBC0017C33E /* TypeDefinitions.h */, D01590AA22BD467B0017C33E /* AnimationRenderer.swift */, D01590A522BD460C0017C33E /* MetalAnimationRenderer.swift */, D01590A722BD462C0017C33E /* SoftwareAnimationRenderer.swift */, D01590AC22BD58AD0017C33E /* YUV.h */, D01590AD22BD58AD0017C33E /* YUV.m */, + D01590C822BE62C40017C33E /* TextureCompression.h */, + D01590C522BE61CB0017C33E /* TextureCompression.cpp */, ); name = Animation; sourceTree = ""; @@ -4872,6 +4908,7 @@ D0E9BA591F055A2200F079A4 /* STPWeakStrongMacros.h in Headers */, D0E9BADE1F0574D800F079A4 /* STPBackendAPIAdapter.h in Headers */, D0E9BAD11F0573C000F079A4 /* STPToken.h in Headers */, + D01590C222BDAEBC0017C33E /* TypeDefinitions.h in Headers */, D0AE303622B1D3620058D3BC /* TGBridgeAudioDecoder.h in Headers */, D0E9BAE71F0574FF00F079A4 /* STPCustomer.h in Headers */, D0208AD51FA33D14001F0D5F /* RaiseToListenActivator.h in Headers */, @@ -4881,6 +4918,7 @@ D0E9BA511F0559DA00F079A4 /* STPImageLibrary.h in Headers */, D0E9BA4C1F0559C700F079A4 /* NSString+Stripe_CardBrands.h in Headers */, D00817E022B47A14008A895F /* UIImage+ImageEffects.h in Headers */, + D01590BA22BDAEBC0017C33E /* ColorVec.h in Headers */, D0E9BAE11F0574D800F079A4 /* STPBankAccount.h in Headers */, D0E9BACE1F0573AF00F079A4 /* STPBlocks.h in Headers */, D0E9BA2A1F0557A600F079A4 /* STPFormEncoder.h in Headers */, @@ -4905,9 +4943,12 @@ D00817CD22B47A14008A895F /* TGAutoDownloadPreferences.h in Headers */, D0E9BACB1F05738600F079A4 /* STPAPIPostRequest.h in Headers */, D0E9BA561F055A0B00F079A4 /* STPFormTextField.h in Headers */, + D01590C122BDAEBC0017C33E /* DDSImage.h in Headers */, D008177C22B46B7E008A895F /* TGItemProviderSignals.h in Headers */, D0E9BABE1F05735F00F079A4 /* STPPaymentConfiguration+Private.h in Headers */, + D01590BB22BDAEBC0017C33E /* BC1Compression.h in Headers */, D0E9BACA1F05738600F079A4 /* STPAPIClient+Private.h in Headers */, + D01590BC22BDAEBC0017C33E /* BMPImage.h in Headers */, D0E9BA251F05578900F079A4 /* STPCardBrand.h in Headers */, D0E9BAC81F05738600F079A4 /* STPAPIClient+ApplePay.h in Headers */, D0E9BA451F0559A500F079A4 /* STPAPIResponseDecodable.h in Headers */, @@ -4916,10 +4957,12 @@ D00817D722B47A14008A895F /* TGBridgeServer.h in Headers */, D00817CE22B47A14008A895F /* TGProxyItem.h in Headers */, D0E9BA401F0558FE00F079A4 /* StripeError.h in Headers */, + D01590C922BE62C40017C33E /* TextureCompression.h in Headers */, D0E9BA191F05574500F079A4 /* STPPaymentCardTextField.h in Headers */, D0E9BA3F1F0558FE00F079A4 /* STPSource.h in Headers */, D008177A22B46B7E008A895F /* TGShareLocationSignals.h in Headers */, D0E9BABC1F05735F00F079A4 /* STPPaymentConfiguration.h in Headers */, + D01590BF22BDAEBC0017C33E /* Image.h in Headers */, D0E9BA2E1F0557D400F079A4 /* STPAddress.h in Headers */, D0E9BA5C1F055A3300F079A4 /* STPBINRange.h in Headers */, D0E9BA3A1F0558E800F079A4 /* NSString+Stripe.h in Headers */, @@ -5278,6 +5321,7 @@ 0910B0EF21FA532D00F8F87D /* WallpaperResources.swift in Sources */, 09E4A807223D4B860038140F /* AccountUtils.swift in Sources */, D069F5D0212700B90000565A /* StickerPanePeerSpecificSetupGridItem.swift in Sources */, + D01590C022BDAEBC0017C33E /* BC1Compression.cpp in Sources */, D0750C8322B2E4EE00BE5F6E /* SharedNotificationManager.swift in Sources */, D0EC6D041EB9F58800EBF1C3 /* opusenc.m in Sources */, D0A8998D217A294100759EE6 /* SaveIncomingMediaController.swift in Sources */, @@ -5349,6 +5393,7 @@ D09D88731F86D56B00BEB4C9 /* AuthorizationLayout.swift in Sources */, D0EC6D281EB9F58800EBF1C3 /* MediaResources.swift in Sources */, D0E9BA671F055B5500F079A4 /* BotCheckoutNativeCardEntryControllerNode.swift in Sources */, + D01590C722BE61CB0017C33E /* TextureCompression.cpp in Sources */, D0EC6D291EB9F58800EBF1C3 /* FetchVideoMediaResource.swift in Sources */, 09EDAD2E221164440012A50B /* AutodownloadSizeLimitItem.swift in Sources */, D0AFCC791F4C8D2C000720C6 /* InstantPageSlideshowItem.swift in Sources */, @@ -5406,6 +5451,7 @@ D0EB42011F30ED4F00838FE6 /* LegacyImageProcessors.m in Sources */, D087BFAF1F741BB7003FD209 /* ShareLoadingContainerNode.swift in Sources */, D0EC6D3F1EB9F58800EBF1C3 /* MediaNavigationAccessoryPanel.swift in Sources */, + D01590C322BDAEBC0017C33E /* BMPImage.cpp in Sources */, D0E9BA3B1F0558E800F079A4 /* NSString+Stripe.m in Sources */, D0CE8CE51F6F354400AA2DB0 /* ChatTextInputAccessoryItem.swift in Sources */, D0EC6D401EB9F58800EBF1C3 /* MediaNavigationAccessoryContainerNode.swift in Sources */, @@ -5535,6 +5581,7 @@ D0FFF7F81F55B83600BEBC01 /* InstantPageAudioNode.swift in Sources */, D0B37C5E1F8D26A8004252DF /* ThemeSettingsChatPreviewItem.swift in Sources */, D01590A822BD462C0017C33E /* SoftwareAnimationRenderer.swift in Sources */, + D01590BE22BDAEBC0017C33E /* Image.cpp in Sources */, D093D7DB2062CFF500BC3599 /* SecureIdAuthFormContentNode.swift in Sources */, D0EC6D821EB9F58800EBF1C3 /* ChatControllerInteraction.swift in Sources */, D0EC6D831EB9F58800EBF1C3 /* ChatControllerNode.swift in Sources */, @@ -5832,6 +5879,7 @@ D0EC6E031EB9F58900EBF1C3 /* GalleryFooterContentNode.swift in Sources */, D0E9BA0A1F0457DD00F079A4 /* BotCheckoutWebInteractionController.swift in Sources */, D0EC6E041EB9F58900EBF1C3 /* SecretMediaPreviewController.swift in Sources */, + D01590BD22BDAEBC0017C33E /* DDSImage.cpp in Sources */, 09F2158D225CF5BC00AEDF6D /* Pasteboard.swift in Sources */, D0C26D571FDF2388004ABF18 /* OpenChatMessage.swift in Sources */, D00817CA22B47A14008A895F /* WatchRequestHandlers.swift in Sources */, diff --git a/submodules/TelegramUI/third-party/bc1/BC1Compression.cpp b/submodules/TelegramUI/third-party/bc1/BC1Compression.cpp new file mode 100644 index 0000000000..5f59ed8c54 --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/BC1Compression.cpp @@ -0,0 +1,300 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "BC1Compression.h" +#include "ColorVec.h" +#include +#include +#include + +namespace DTX1CompressorDecompressor +{ + bool BC1Compression::Compress(const BMPImage & bmpImage, BC1DDSImage & ddsImage) + { + unsigned char* dtaPtr = bmpImage.GetData(); + if (dtaPtr == nullptr) + { + return false; // should return an error code + } + + const unsigned int width = bmpImage.GetWidth(); + const unsigned int height = bmpImage.GetHeight(); + const unsigned int nBlocks = (width / 4) * (height / 4); + + // reserve memory for the ddsImage + unsigned char* ddsImageData = new unsigned char[nBlocks * m_blockSize]; + + // TODO: this first pass over the image may not be needed, for now we use it as to get things working first + // here we get data of the bmp image as pixels array + std::vector pixelData(width * height); + for (unsigned int row = 0; row < height; ++row) + { + for (unsigned int col = 0; col < width; ++col) + { + unsigned int index = (height - 1 - row) * width + col; // image is reversed in rows (upside down), so row = 0 is the bottom of the image + std::memcpy(&pixelData[index].bgra, dtaPtr, 3); + dtaPtr += 3; + } + } + + // compress all 4x4 blocks of the bmpImage + unsigned char* ddsDataPtr = ddsImageData; + for (unsigned int row = 0; row < height; row += 4) + { + for (unsigned int col = 0; col < width; col += 4) + { + // TODO : potentially we could use multiple threads to compress multiple blocks in parallel + CompressBlock(pixelData, row, col, width, ddsDataPtr); + ddsDataPtr += m_blockSize; + } + } + + // finialize dds image initialization (headers + data) + if(!ddsImage.InitWithData(ddsImageData, width, height)) + { + if(ddsImageData != nullptr) + delete[] ddsImageData; + + return false; // should return an error code + } + + return true; + } + + bool BC1Compression::DeCompress(const BC1DDSImage & ddsImage, BMPImage & bmpImage) + { + unsigned char* ddsDataPtr = ddsImage.GetData(); + if (ddsDataPtr == nullptr) + { + return false; // should return an error code + } + + const unsigned int width = ddsImage.GetWidth(); + const unsigned int height = ddsImage.GetHeight(); + + // similar to compression we use the aid of a pixel array + std::vector pixelData(width * height); + + // de-compress all 4x4 blocks of the ddsImage + for (unsigned int row = 0; row < height; row += 4) + { + for (unsigned int col = 0; col < width; col += 4) + { + // TODO : potentially we could use multiple threads to de-compress multiple blocks in parallel + DeCompressBlock(pixelData, row, col, width, ddsDataPtr); + ddsDataPtr += m_blockSize; + } + } + + // copy pixel data to the actual bmp image + unsigned char* bmpImgData = new unsigned char[3 * width * height]; + unsigned char* bmpDataPtr = bmpImgData; + + for (unsigned int row = 0; row < height; ++row) + { + for (unsigned int col = 0; col < width; ++col) + { + unsigned int index = (height - 1 - row) * width + col; // image is reversed in rows (upside down), so row = 0 is the bottom of the image + std::memcpy(bmpDataPtr, &pixelData[index].bgra, 3); + bmpDataPtr += 3; + } + } + + // finialize bmp image initialization (headers + data) + if (!bmpImage.InitWithData(bmpImgData, width, height)) + { + if (bmpImgData != nullptr) + delete[] bmpImgData; + + return false; + } + + return true; + } + + void BC1Compression::CompressBlock(const std::vector & pixelData, unsigned int row, unsigned int col, unsigned int width, unsigned char* ddsDataPtr) const + { + // find the min-max + int maxVal = -1; + Pixel24Bit maxColor; + + int minVal = INT_MAX; + Pixel24Bit minColor; + + for (unsigned int r = row; r < row + 4; ++r) + { + for (unsigned int c = col; c < col + 4; ++c) + { + unsigned int pixelIndex = r * width + c; + int l = pixelData[pixelIndex].GetLuminance(); + + if (l > maxVal) + { + maxColor.SetPixel24Bit(pixelData[pixelIndex]); + maxVal = l; + } + + if (l < minVal) + { + minColor.SetPixel24Bit(pixelData[pixelIndex]); + minVal = l; + } + } + } + + // fix the end points colors min and max based on their RGB565 values + unsigned short minColorRGB565 = minColor.ConvertTo565(); + unsigned short maxColorRGB565 = maxColor.ConvertTo565(); + if (minColorRGB565 > maxColorRGB565) + { + std::swap(minColor, maxColor); + std::swap(minColorRGB565, maxColorRGB565); + } + + // set the first two colors to compressed block + std::memcpy(ddsDataPtr, &maxColorRGB565, 2); + ddsDataPtr += 2; + + std::memcpy(ddsDataPtr, &minColorRGB565, 2); + ddsDataPtr += 2; + + // fix : min and max colors can be collapsed to the same color! i.e. maxColorRGB565 == minColorRGB565 + // therefore we use the reverted 24 bit colors for the enconding below + maxColor.LoadFrom565(maxColorRGB565); + minColor.LoadFrom565(minColorRGB565); + + // intermediate colors (check BC1 Section on https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx) + Pixel24Bit color2, color3; + for (unsigned int i = 0; i < 3; ++i) + { + color2.bgra[i] = (2 * maxColor.bgra[i] + 1 * minColor.bgra[i]) / 3; + color3.bgra[i] = (1 * maxColor.bgra[i] + 2 * minColor.bgra[i]) / 3; + } + + // find the closest color for each color and set its offset bit + unsigned int pixelCount = 0; + unsigned int encodedOffsets = 0; + for (unsigned int r = row; r < row + 4; ++r) + { + for (unsigned int c = col; c < col + 4; ++c) + { + unsigned int pixelIndex = r * width + c; + + Pixel24Bit color; + color.SetPixel24Bit(pixelData[pixelIndex]); + + int minD = color.SqrDistanceTo(maxColor); + unsigned int offset = 0; + + int d = color.SqrDistanceTo(minColor); + if (d < minD) + { + minD = d; + offset = 1; + } + + d = color.SqrDistanceTo(color2); + if (d < minD) + { + minD = d; + offset = 2; + } + + d = color.SqrDistanceTo(color3); + if (d < minD) + { + minD = d; + offset = 3; + } + + // here the offsets are set in a way that the final enconded set of bits are : + // pixel 16 offset | pixel 15 offset | ....... | pixel 0 offset + // each offset is 2 bit, the resulting econded offsets is 32bit = 16bit * 2 = 4 bytes + unsigned int shift = (unsigned int)(pixelCount << 1); + encodedOffsets |= (offset << shift ); + pixelCount++; + } + } + + // write the whole enconded offsets 4 byte word to the compressed block + std::memcpy(ddsDataPtr, &encodedOffsets, 4); + ddsDataPtr += 4; + } + + void BC1Compression::DeCompressBlock(std::vector & pixelData, unsigned int row, unsigned int col, unsigned int width, unsigned char* ddsDataPtr) const + { + // get the first two colors from compressed block + Pixel24Bit minColor, maxColor; + + unsigned short maxColorRGB565; + std::memcpy(&maxColorRGB565, ddsDataPtr, 2); + ddsDataPtr += 2; + maxColor.LoadFrom565(maxColorRGB565); + + unsigned short minColorRGB565; + std::memcpy(&minColorRGB565, ddsDataPtr, 2); + ddsDataPtr += 2; + minColor.LoadFrom565(minColorRGB565); + + // interpolate the other two colors + Pixel24Bit color2, color3; + for (unsigned int i = 0; i < 3; ++i) + { + color2.bgra[i] = (2 * maxColor.bgra[i] + 1 * minColor.bgra[i]) / 3; + color3.bgra[i] = (1 * maxColor.bgra[i] + 2 * minColor.bgra[i]) / 3; + } + + // get the encoded offset + unsigned int encodedOffsets; + std::memcpy(&encodedOffsets, ddsDataPtr, 4); + ddsDataPtr += 4; + + // set for each pixel their color according to the 2bit offset in the compressed block + for (unsigned int r = row; r < row + 4; ++r) + { + for (unsigned int c = col; c < col + 4; ++c) + { + unsigned int offset = (encodedOffsets & (unsigned int) 0x03); // the two right hand side bits + encodedOffsets = encodedOffsets >> 2; + + // get the color according to the offset + Pixel24Bit color; + if(offset == 0) + color.SetPixel24Bit(maxColor); + + else if(offset == 1) + color.SetPixel24Bit(minColor); + + else if(offset == 2) + color.SetPixel24Bit(color2); + + else if(offset == 3) + color.SetPixel24Bit(color3); + + // set the color + unsigned int pixelIndex = r * width + c; + pixelData[pixelIndex].SetPixel24Bit(color); + } + } + } + +} diff --git a/submodules/TelegramUI/third-party/bc1/BC1Compression.h b/submodules/TelegramUI/third-party/bc1/BC1Compression.h new file mode 100644 index 0000000000..2c181d0b82 --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/BC1Compression.h @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef RL_BC1_COMPRESSION_H +#define RL_BC1_COMPRESSION_H + +#include "TypeDefinitions.h" +#include "BMPImage.h" +#include "DDSImage.h" +#include + +namespace DTX1CompressorDecompressor +{ + // class for handlling BC1 compression of BMP Textures + class BC1Compression + { + public: + bool Compress(const BMPImage & bmpImage, BC1DDSImage & ddsImage); + bool DeCompress(const BC1DDSImage & ddsImage, BMPImage & bmpImage); + + private: + void CompressBlock(const std::vector & pixelData, unsigned int row, unsigned int col, unsigned int width, unsigned char* ddsDataPtr) const; + void DeCompressBlock(std::vector & pixelData, unsigned int row, unsigned int col, unsigned int width, unsigned char* ddsDataPtr) const; + + // a compressed BC1 block is 8 bytes + const unsigned int m_blockSize = 8; + }; + +} + +#endif // !RL_BC1_COMPRESSION_H + diff --git a/submodules/TelegramUI/third-party/bc1/BMPImage.cpp b/submodules/TelegramUI/third-party/bc1/BMPImage.cpp new file mode 100644 index 0000000000..451dc70cea --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/BMPImage.cpp @@ -0,0 +1,213 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "BMPImage.h" +#include +#include + +namespace DTX1CompressorDecompressor +{ + BMPImage::BMPImage() : Image() + { + } + + BMPImage::BMPImage(const BMPImage & other) + { + m_width = other.m_width; + m_height = other.m_height; + m_fileHeader = other.m_fileHeader; + m_bitMapInfoHeader = other.m_bitMapInfoHeader; + + if (other.m_data == nullptr) + m_data = nullptr; + else + std::memcpy(m_data, other.m_data, other.m_bitMapInfoHeader.biSizeImage); + } + + BMPImage::BMPImage(BMPImage && other) : Image() + { + // initializes this with other data, and resets other with the "Image()" default data + Swap(*this, other); + } + + BMPImage & BMPImage::operator=(BMPImage other) + { + // copy and swap idiom + // here 'other' is a copy (since has been passed here by value) that is constructed either using the copy constructor or the move constructor, depending if it is an rvalue or a lvalue + Swap(*this, other); + return *this; + } + + void Swap(BMPImage & img1, BMPImage & img2) + { + using std::swap; + + swap(img1.m_fileHeader, img2.m_fileHeader); + swap(img1.m_bitMapInfoHeader, img2.m_bitMapInfoHeader); + swap(img1.m_width, img2.m_width); + swap(img1.m_height, img2.m_height); + swap(img1.m_data, img2.m_data); + } + + BMPImage::~BMPImage() + { + } + + bool BMPImage::InitWithData(unsigned char* data, unsigned int width, unsigned int height) + { + // checks for valid data + if (data == nullptr) + { + std::cout << "BMPImage::InitWithData:: data is null !" << std::endl; + return false; + } + + // check for image size width and height multiples of 4 + if (width % 4 != 0 || height % 4 != 0) + { + std::cout << "BMPImage::InitWithData:: the image is not supported. It needs width and height multiple of 4..." << std::endl; + return false; + } + + // we will overwrite previous data contained in this BMPImage instance + ReleaseImageMemory(); + + // take ownership of the data + m_data = data; + m_width = width; + m_height = height; + + // populate headers + DWORD bothHeadersSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + DWORD infoHeaderSize = sizeof(BITMAPINFOHEADER); + DWORD dataSize = 3 * width * height; // 3 bytes per pixel + WORD bitCount = 24; + LONG prefferedResOnX = 3780; // TODO : make this one and the next one as arguments ? + LONG prefferedResOnY = 3780; + + m_fileHeader.bfType = BM_FORMAT_TAG; + m_fileHeader.bfSize = bothHeadersSize + dataSize; + m_fileHeader.bfReserved1 = 0; + m_fileHeader.bfReserved2 = 0; + m_fileHeader.bfOffBits = bothHeadersSize; // header offset to the actual data (both headers sizes = 54 bytes) + + m_bitMapInfoHeader.biSize = infoHeaderSize; + m_bitMapInfoHeader.biWidth = static_cast(width); + m_bitMapInfoHeader.biHeight = static_cast(height); + m_bitMapInfoHeader.biPlanes = 1; + m_bitMapInfoHeader.biBitCount = bitCount; + m_bitMapInfoHeader.biCompression = 0; + m_bitMapInfoHeader.biSizeImage = dataSize; + m_bitMapInfoHeader.biXPelsPerMeter = prefferedResOnX; + m_bitMapInfoHeader.biYPelsPerMeter = prefferedResOnY; + m_bitMapInfoHeader.biClrUsed = 0; + m_bitMapInfoHeader.biClrImportant = 0; + + return true; + } + + bool BMPImage::ReadFromFile(const char * fileName) + { + std::ifstream imgFile(fileName, std::ifstream::binary); + + if (imgFile.is_open()) + { + // read header bytes + imgFile.read(reinterpret_cast(&m_fileHeader), sizeof(m_fileHeader)); + imgFile.read(reinterpret_cast(&m_bitMapInfoHeader), sizeof(m_bitMapInfoHeader)); + + // check the type of file + if (m_fileHeader.bfType != BM_FORMAT_TAG) + { + std::cout << " file was not found to be on BMP format... " << std::endl; + return false; + } + + // check for image size width and height multiples of 4 + if (m_bitMapInfoHeader.biWidth % 4 != 0 || m_bitMapInfoHeader.biHeight % 4 != 0) + { + std::cout << " the image is not supported. It needs width and height multiple of 4..." << std::endl; + return false; + } + + // check for 24 bit bitmaps only + if (m_bitMapInfoHeader.biBitCount != 24) + { + std::cout << " the image is not supported. It needs to be RGB-24 bit (8 bits per pixel) ..." << std::endl; + return false; + } + + // make sure we delete memory for any previous image we had loaded into this instance + ReleaseImageMemory(); + + // allocate the memory needed for all our data + m_width = static_cast(m_bitMapInfoHeader.biWidth); + m_height = static_cast(m_bitMapInfoHeader.biHeight); + + unsigned int dataByteSize = 3 * m_width * m_height; + m_data = new unsigned char[dataByteSize]; + + // read color data + imgFile.read(reinterpret_cast(m_data), dataByteSize); + + // release the file + imgFile.close(); + } + else + { + std::cout << std::endl <<" cannot read file : " << fileName << std::endl; + return false; + } + + return true; + } + + bool BMPImage::SaveToFile(const char * fileName) + { + if (m_data == nullptr) + return false; + + std::ofstream imgFile(fileName, std::ifstream::binary); + + if(imgFile.is_open()) + { + // write headers + imgFile.write(reinterpret_cast(&m_fileHeader), sizeof(m_fileHeader)); + imgFile.write(reinterpret_cast(&m_bitMapInfoHeader), sizeof(m_bitMapInfoHeader)); + + // write data + unsigned int dataByteSize = 3 * m_width * m_height; + imgFile.write(reinterpret_cast(m_data), dataByteSize); + + // release file + imgFile.close(); + } + else + { + std::cout << std::endl << "error creating or opening file : " << fileName << std::endl; + return false; + } + + return true; + } + +} diff --git a/submodules/TelegramUI/third-party/bc1/BMPImage.h b/submodules/TelegramUI/third-party/bc1/BMPImage.h new file mode 100644 index 0000000000..09b01160f2 --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/BMPImage.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef RL_BMP_IMAGE_H +#define RL_BMP_IMAGE_H + +#include "Image.h" + +namespace DTX1CompressorDecompressor +{ + // class for loading and handling BMP images + class BMPImage : public Image + { + public: + BMPImage(); + BMPImage(const BMPImage & other); + BMPImage(BMPImage && other); + BMPImage& operator=(BMPImage other); + friend void Swap(BMPImage & img1, BMPImage & img2); + ~BMPImage(); + + + // a initalizator with data loaded from other sources (for example, from a decompressed DDS image), + // if color data in this image instance is already set, it will be ovewritten + // this instance will take ownership of the data + bool InitWithData(unsigned char* data, unsigned int width, unsigned int height); + + // populates the headers and the color data (if color data is already set, it will be ovewritten with the data of the file being loaded) + bool ReadFromFile(const char* fileName); + + // saves this data to disc ( will create a BMP image : fileName.bmp ) + bool SaveToFile(const char* fileName); + + private: + BITMAPFILEHEADER m_fileHeader; + BITMAPINFOHEADER m_bitMapInfoHeader; + }; +} + +#endif // !BMP_ IMAGE_H diff --git a/submodules/TelegramUI/third-party/bc1/ColorVec.h b/submodules/TelegramUI/third-party/bc1/ColorVec.h new file mode 100644 index 0000000000..a78c9e9d5f --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/ColorVec.h @@ -0,0 +1,103 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef RL_COLOR_VEC_H +#define RL_COLOR_VEC_H + +#include "TypeDefinitions.h" +#include + +namespace DTX1CompressorDecompressor +{ + const unsigned short RED_MASK = DWRMASK; + const unsigned short GREEN_MASK = DWGMASK; + const unsigned short BLUE_MASK = DWBMASK; + + // structure to represent a pixel + // 3 bytes = 24 bits per pixel (but is going to be padded to 4 bytes anyway so we make it explicit) + struct Pixel24Bit + { + unsigned char bgra[4]; // 4 to make explicit the padding + + Pixel24Bit() + { + bgra[0] = 0; + bgra[1] = 0; + bgra[2] = 0; + bgra[3] = 0; + } + + void SetPixel24Bit(const Pixel24Bit & other) + { + bgra[0] = other.bgra[0]; + bgra[1] = other.bgra[1]; + bgra[2] = other.bgra[2]; + bgra[3] = 0; + } + + const int SqrDistanceTo(const Pixel24Bit & other) const + { + int db = (bgra[0] - other.bgra[0]); + int dg = (bgra[1] - other.bgra[1]); + int dr = (bgra[2] - other.bgra[2]); + return db*db + dg*dg + dr*dr; + } + + const int GetLuminance() const + { + return (bgra[2] + bgra[1] * 2 + bgra[0]); + } + + unsigned short ConvertTo565() + { + // Adapted from : + // https://msdn.microsoft.com/en-us/library/windows/desktop/dd390989(v=vs.85).aspx + + return ((bgra[2] >> 3) << 11) | ((bgra[1] >> 2) << 5) | (bgra[0] >> 3); + } + + void LoadFrom565(unsigned short rgb) + { + // Adapted from : + // https://msdn.microsoft.com/en-us/library/windows/desktop/dd390989(v=vs.85).aspx + + unsigned char redVal = ((rgb & RED_MASK) >> 11) << 3; + unsigned char greenVal = ((rgb & GREEN_MASK) >> 5) << 2; + unsigned char blueVal = (rgb & BLUE_MASK) << 3; + + bgra[0] = blueVal; + bgra[1] = greenVal; + bgra[2] = redVal; + bgra[3] = 0; + } + + void PrintColor() const + { + std::cout << "(B,G,R) = (" << (int)bgra[0] << ", " << (int)bgra[1] << " , " << (int)bgra[2] << ");" << std::endl; + } + }; + +} + + +#endif // !RL_COLOR_VEC_H + diff --git a/submodules/TelegramUI/third-party/bc1/DDSImage.cpp b/submodules/TelegramUI/third-party/bc1/DDSImage.cpp new file mode 100644 index 0000000000..8c0101cfe3 --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/DDSImage.cpp @@ -0,0 +1,222 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "DDSImage.h" +#include +#include +#include + +namespace DTX1CompressorDecompressor +{ + BC1DDSImage::BC1DDSImage() : Image() + { + } + + BC1DDSImage::BC1DDSImage(const BC1DDSImage & other) + { + m_width = other.m_width; + m_height = other.m_height; + m_header = other.m_header; + m_dwMagic = other.m_dwMagic; + + if (other.m_data == nullptr) + m_data = nullptr; + else + { + unsigned int nBlocks = (m_width / 4) * (m_height / 4); + unsigned int blockSize = 8; + unsigned int dataByteSize = nBlocks * blockSize; + std::memcpy(m_data, other.m_data, dataByteSize); + } + } + + BC1DDSImage::BC1DDSImage(BC1DDSImage && other) : Image() + { + Swap(*this, other); + } + + BC1DDSImage & BC1DDSImage::operator=(BC1DDSImage other) + { + Swap(*this, other); + return *this; + } + + void Swap(BC1DDSImage & img1, BC1DDSImage & img2) + { + using std::swap; + + swap(img1.m_dwMagic, img2.m_dwMagic); + swap(img1.m_header, img2.m_header); + swap(img1.m_width, img2.m_width); + swap(img1.m_height, img2.m_height); + swap(img1.m_data, img2.m_data); + } + + BC1DDSImage::~BC1DDSImage() + { + } + + bool BC1DDSImage::InitWithData(unsigned char * data, unsigned int width, unsigned int height) + { + // checks for valid data + if (data == nullptr) + { + std::cout << "BC1DDSImage::InitWithData:: data is null !" << std::endl; + return false; + } + + // check for image size width and height multiples of 4 + if (width % 4 != 0 || height % 4 != 0) + { + std::cout << "BC1DDSImage::InitWithData:: the image is not supported. It needs width and height multiple of 4..." << std::endl; + return false; + } + + // we will overwrite previous data contained in this BMPImage instance + ReleaseImageMemory(); + + // take ownership of the data + m_data = data; + m_width = width; + m_height = height; + + // populate headers + DWORD sizeOfHeader = sizeof(DDS_HEADER); + DWORD sizeOfPixelFormat = sizeof(DDS_PIXELFORMAT); + DWORD blockSize = 8; // 8 bytes + + m_dwMagic = DDS_FORMAT_TAG; + + m_header.dwSize = sizeOfHeader; + m_header.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + m_header.dwHeight = height; + m_header.dwWidth = width; + m_header.dwPitchOrLinearSize = 0; + m_header.dwDepth = 0; + m_header.dwMipMapCount = 0; + m_header.dwCaps1 = DDSCAPS_TEXTURE; + m_header.dwCaps2 = 0; + + m_header.ddspf.dwSize = sizeOfPixelFormat; + m_header.ddspf.dwFlags = DDPF_FOURCC; + m_header.ddspf.dwFourCC = DXT1; + m_header.ddspf.dwRGBBitCount = 0; + m_header.ddspf.dwRBitMask = 0; + m_header.ddspf.dwGBitMask = 0; + m_header.ddspf.dwBBitMask = 0; + m_header.ddspf.dwABitMask = 0; + + return true; + } + + bool BC1DDSImage::ReadFromFile(const char * fileName) + { + std::ifstream imgFile(fileName, std::ifstream::binary); + + if (imgFile.is_open()) + { + // read magic number to DDS FORMAT + imgFile.read(reinterpret_cast(&m_dwMagic), sizeof(m_dwMagic)); + + if (m_dwMagic != DDS_FORMAT_TAG) + { + std::cout << " file was not found to be a valid DDS image... " << std::endl; + return false; + } + + // read header + imgFile.read(reinterpret_cast(&m_header), sizeof(m_header)); + + // check is DTX1 + if (m_header.ddspf.dwFlags != DDPF_FOURCC || m_header.ddspf.dwFourCC != DXT1) + { + std::cout << " the image is not a valid DXT1 image file ..." << std::endl; + return false; + } + + // check for image size width and height multiples of 4 + if (m_header.dwHeight % 4 != 0 || m_header.dwWidth % 4 != 0) + { + std::cout << " the image is not supported. It needs width and height multiple of 4..." << std::endl; + return false; + } + + // make sure we delete memory for any previous image we had loaded into this instance + ReleaseImageMemory(); + + // allocate the memory needed for all our data + m_width = static_cast(m_header.dwWidth); + m_height = static_cast(m_header.dwHeight); + + unsigned int nBlocks = (m_width / 4) * (m_height / 4); + unsigned int blockSize = 8; + unsigned int dataByteSize = nBlocks * blockSize; + + m_data = new unsigned char[dataByteSize]; + + // read color data + imgFile.read(reinterpret_cast(m_data), dataByteSize); + + // release the file + imgFile.close(); + } + else + { + std::cout << std::endl << " cannot read file : " << fileName << std::endl; + return false; + } + + return true; + } + + bool BC1DDSImage::SaveToFile(const char * fileName) + { + if (m_data == nullptr) + return false; + + std::ofstream imgFile(fileName, std::ifstream::binary); + + if (imgFile.is_open()) + { + // write headers + imgFile.write(reinterpret_cast(&m_dwMagic), sizeof(m_dwMagic)); + imgFile.write(reinterpret_cast(&m_header), sizeof(m_header)); + + // write data + unsigned int nBlocks = (m_width / 4) * (m_height / 4); + unsigned int blockSize = 8; + unsigned int dataByteSize = nBlocks * blockSize; + + imgFile.write(reinterpret_cast(m_data), dataByteSize); + + // release file + imgFile.close(); + } + else + { + std::cout << std::endl << "error creating or opening file : " << fileName << std::endl; + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/submodules/TelegramUI/third-party/bc1/DDSImage.h b/submodules/TelegramUI/third-party/bc1/DDSImage.h new file mode 100644 index 0000000000..4a00b9a6e8 --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/DDSImage.h @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef RL_DDS_IMAGE_H +#define RL_DDS_IMAGE_H + +#include "Image.h" + +namespace DTX1CompressorDecompressor +{ + // class for loading and handling BC1 DDS images + class BC1DDSImage : public Image + { + public: + BC1DDSImage(); + BC1DDSImage(const BC1DDSImage & other); + BC1DDSImage(BC1DDSImage && other); + BC1DDSImage& operator=(BC1DDSImage other); + friend void Swap(BC1DDSImage & img1, BC1DDSImage & img2); + ~BC1DDSImage(); + + // Image interface implementation + bool InitWithData(unsigned char* data, unsigned int width, unsigned int height); + bool ReadFromFile(const char* fileName); + bool SaveToFile(const char* fileName); + + private: + DWORD m_dwMagic; + DDS_HEADER m_header; + }; +} +#endif \ No newline at end of file diff --git a/submodules/TelegramUI/third-party/bc1/Image.cpp b/submodules/TelegramUI/third-party/bc1/Image.cpp new file mode 100644 index 0000000000..e08e779413 --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/Image.cpp @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "Image.h" + +namespace DTX1CompressorDecompressor +{ + Image::~Image() + { + ReleaseImageMemory(); + } + + void Image::ReleaseImageMemory() + { + if (m_ownData) { + delete[] m_data; + } + + m_data = nullptr; + m_width = 0; + m_height = 0; + } + +} diff --git a/submodules/TelegramUI/third-party/bc1/Image.h b/submodules/TelegramUI/third-party/bc1/Image.h new file mode 100644 index 0000000000..a1b5d729b8 --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/Image.h @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef RL_IMAGE_H +#define RL_IMAGE_H + +#include "TypeDefinitions.h" +#include "ColorVec.h" + +namespace DTX1CompressorDecompressor +{ + // base class for all images + class Image + { + public: + virtual ~Image(); + + // frees the image data if any + void ReleaseImageMemory(); + + // a initalizator with data loaded from other sources + virtual bool InitWithData(unsigned char* data, unsigned int width, unsigned int height) = 0; + + // initializator from file + virtual bool ReadFromFile(const char* fileName) = 0; + + // saves the image to disc + virtual bool SaveToFile(const char* fileName) = 0; + + // gets the width in pixels of the loaded image + inline unsigned int GetWidth() const + { + return m_width; + } + + // gets the height in pixels of the loaded image + inline unsigned int GetHeight() const + { + return m_height; + } + + // gets the data pointer + inline unsigned char* GetData() const + { + return m_data; + } + + public: + Image() : m_data(nullptr), m_width(0), m_height(0) {}; + + bool m_ownData; + unsigned char* m_data; + unsigned int m_width; + unsigned int m_height; + }; + +} + + +#endif // !RL_IMAGE_H diff --git a/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp b/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp new file mode 100644 index 0000000000..452ba3f0af --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp @@ -0,0 +1,13 @@ +#import "TextureCompression.h" +#import "BC1Compression.h" + +void compressRGBAToBC1(uint8_t const * _Nonnull argb, int width, int height, uint8_t * _Nonnull bc1) { + DTX1CompressorDecompressor::BC1Compression compression; + DTX1CompressorDecompressor::BMPImage image; + image.InitWithData((unsigned char *)argb, width, height); + image.m_ownData = false; + DTX1CompressorDecompressor::BC1DDSImage ddsImage; + compression.Compress(image, ddsImage); + int numBlocks = width * height / (4 * 4); + memcpy(bc1, ddsImage.GetData(), numBlocks * 8); +} diff --git a/submodules/TelegramUI/third-party/bc1/TextureCompression.h b/submodules/TelegramUI/third-party/bc1/TextureCompression.h new file mode 100644 index 0000000000..29b5c6f932 --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/TextureCompression.h @@ -0,0 +1,11 @@ +#import + +#ifdef __cplusplus +extern "C" { +#endif + +void compressRGBAToBC1(uint8_t const * _Nonnull argb, int width, int height, uint8_t * _Nonnull bc1); + +#ifdef __cplusplus +} +#endif diff --git a/submodules/TelegramUI/third-party/bc1/TypeDefinitions.h b/submodules/TelegramUI/third-party/bc1/TypeDefinitions.h new file mode 100644 index 0000000000..fad2a615f7 --- /dev/null +++ b/submodules/TelegramUI/third-party/bc1/TypeDefinitions.h @@ -0,0 +1,126 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017 Ricardo David CM (http://ricardo-david.com), +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef RL_TYPE_DEF_H +#define RL_TYPE_DEF_H + +namespace DTX1CompressorDecompressor +{ + + // 19778 = 0x4D42 = 'BM' for bitmap format , 0x20534444 = "DDS" for DDS format + // check https://msdn.microsoft.com/en-us/library/vs/alm/dd183374(v=vs.85).aspx (BMP) + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb943991(v=vs.85).aspx (DDS) + #define BM_FORMAT_TAG 0x4D42 + #define DDS_FORMAT_TAG 0x20534444 + + // DDS flags : https://msdn.microsoft.com/en-us/library/windows/desktop/bb943982(v=vs.85).aspx + #define DDSD_CAPS 0x1 + #define DDSD_HEIGHT 0x2 + #define DDSD_WIDTH 0x4 + #define DDSD_PIXELFORMAT 0x1000 + #define DDSCAPS_TEXTURE 0x1000 + + #define DWRMASK 0xF800 + #define DWGMASK 0x7E0 + #define DWBMASK 0x1F + + #define DDPF_FOURCC 0x4 + #define DXT1 0x31545844 + + typedef int LONG; // 4 bytes + typedef unsigned short WORD; // 2 bytes + typedef unsigned int DWORD; // 4 bytes + +// this pragma is needed for memory alignment +// without this the WORDs of the structs below will be padded to 4 bytes, then the structs will be bigger than we want + +#pragma pack(2) + + // Adapted from the Microsoft documentation: + // https://msdn.microsoft.com/en-us/library/vs/alm/dd183392(v=vs.85).aspx + + // 14 bytes + struct BITMAPFILEHEADER + { + WORD bfType; + DWORD bfSize; + WORD bfReserved1; + WORD bfReserved2; + DWORD bfOffBits; + }; + + // 40 bytes + struct BITMAPINFOHEADER + { + DWORD biSize; + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; + }; + + // Adapted from the Microsoft documentation: + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb943984(v=vs.85).aspx + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb943982(v=vs.85).aspx + + // 32 bytes + struct DDS_PIXELFORMAT + { + DWORD dwSize; + DWORD dwFlags; + DWORD dwFourCC; + DWORD dwRGBBitCount; + DWORD dwRBitMask; + DWORD dwGBitMask; + DWORD dwBBitMask; + DWORD dwABitMask; + }; + + // 124 bytes + struct DDS_HEADER + { + DWORD dwSize; + DWORD dwFlags; + DWORD dwHeight; + DWORD dwWidth; + DWORD dwPitchOrLinearSize; + DWORD dwDepth; + DWORD dwMipMapCount; + DWORD dwReserved1[11]; + DDS_PIXELFORMAT ddspf; + DWORD dwCaps1; + DWORD dwCaps2; + DWORD dwReserved2[3]; + }; + +#pragma pack() + +} + +#endif // !RL_TYPE_DEF_H + From 1f36b62a7eca6a0b08ed936efec70f2d20e19e72 Mon Sep 17 00:00:00 2001 From: Peter <> Date: Mon, 24 Jun 2019 19:51:27 +0300 Subject: [PATCH 07/26] Update build script --- buildbox/guest-build-telegram.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buildbox/guest-build-telegram.sh b/buildbox/guest-build-telegram.sh index 5db29946be..f0241e200b 100644 --- a/buildbox/guest-build-telegram.sh +++ b/buildbox/guest-build-telegram.sh @@ -20,8 +20,8 @@ elif [ "$1" == "appstore" ]; then PROFILES_PATH="codesigning_data/profiles" elif [ "$1" == "verify" ]; then FASTLANE_BUILD_CONFIGURATION="build_for_appstore" - CERTS_PATH="buildbox/fake-codesigning/certs" - PROFILES_PATH="buildbox/fake-codesigning/profiles" + CERTS_PATH="codesigning_data/certs" + PROFILES_PATH="codesigning_data/profiles" elif [ "$1" == "verify-local" ]; then FASTLANE_BUILD_CONFIGURATION="build_for_appstore" CERTS_PATH="buildbox/fake-codesigning/certs" From 3c844dbeb524e3a4afb7d2ec4ad7229a7b829f8a Mon Sep 17 00:00:00 2001 From: Peter <> Date: Mon, 24 Jun 2019 21:28:09 +0300 Subject: [PATCH 08/26] Added scripts for build verification --- buildbox/build-telegram.sh | 11 +- buildbox/guest-build-telegram.sh | 12 +- fastlane/Fastfile | 9 +- tools/ipadiff.py | 316 +++++++++++++++++++++++++++++++ tools/main.cpp | 262 +++++++++++++++++++++++++ 5 files changed, 602 insertions(+), 8 deletions(-) create mode 100644 tools/ipadiff.py create mode 100644 tools/main.cpp diff --git a/buildbox/build-telegram.sh b/buildbox/build-telegram.sh index 9f5fbb86ac..ee74b7a554 100644 --- a/buildbox/build-telegram.sh +++ b/buildbox/build-telegram.sh @@ -25,6 +25,15 @@ else exit 1 fi +COMMIT_ID=$(git rev-parse HEAD) +if [ -z "$2" ]; then + COMMIT_COUNT=$(git rev-list --count HEAD) + COMMIT_COUNT="$(($COMMIT_COUNT+1000))" + BUILD_NUMBER="$COMMIT_COUNT" +else + BUILD_NUMBER="$2" +fi + BASE_DIR=$(pwd) if [ "$BUILD_CONFIGURATION" == "hockeyapp" ] || [ "$BUILD_CONFIGURATION" == "appstore" ]; then @@ -87,7 +96,7 @@ else fi scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/guest-build-telegram.sh" "$BUILDBOX_DIR/transient-data/source.tar" telegram@"$VM_IP": -ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null telegram@"$VM_IP" -o ServerAliveInterval=60 -t "export TELEGRAM_BUILD_APPSTORE_PASSWORD=\"$TELEGRAM_BUILD_APPSTORE_PASSWORD\"; export TELEGRAM_BUILD_APPSTORE_TEAM_NAME=\"$TELEGRAM_BUILD_APPSTORE_TEAM_NAME\"; bash -l guest-build-telegram.sh $BUILD_CONFIGURATION" || true +ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null telegram@"$VM_IP" -o ServerAliveInterval=60 -t "export TELEGRAM_BUILD_APPSTORE_PASSWORD=\"$TELEGRAM_BUILD_APPSTORE_PASSWORD\"; export TELEGRAM_BUILD_APPSTORE_TEAM_NAME=\"$TELEGRAM_BUILD_APPSTORE_TEAM_NAME\"; export BUILD_NUMBER=\"$BUILD_NUMBER\"; export COMMIT_ID=\"$COMMIT_ID\"; bash -l guest-build-telegram.sh $BUILD_CONFIGURATION" || true if [ "$BUILD_CONFIGURATION" == "appstore" ]; then ARCHIVE_PATH="$HOME/telegram-builds-archive" diff --git a/buildbox/guest-build-telegram.sh b/buildbox/guest-build-telegram.sh index f0241e200b..c08c7da671 100644 --- a/buildbox/guest-build-telegram.sh +++ b/buildbox/guest-build-telegram.sh @@ -1,5 +1,15 @@ #!/bin/sh +if [ -z "BUILD_NUMBER" ]; then + echo "BUILD_NUMBER is not set" + exit 1 +fi + +if [ -z "COMMIT_ID" ]; then + echo "COMMIT_ID is not set" + exit 1 +fi + if [ "$1" == "hockeyapp" ]; then FASTLANE_BUILD_CONFIGURATION="internalhockeyapp" CERTS_PATH="codesigning_data/certs" @@ -68,5 +78,5 @@ else tar -xf "source.tar" cd "$SOURCE_PATH" - FASTLANE_PASSWORD="$FASTLANE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$FASTLANE_ITC_TEAM_NAME" fastlane "$FASTLANE_BUILD_CONFIGURATION" + FASTLANE_PASSWORD="$FASTLANE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$FASTLANE_ITC_TEAM_NAME" fastlane "$FASTLANE_BUILD_CONFIGURATION" build_number:"$BUILD_NUMBER" commit_hash:"$COMMIT_ID" fi diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 5dffc7a870..ed178e3a90 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -16,6 +16,7 @@ app_identifier_llc = [ signing_identity_llc = "iPhone Distribution: Digital Fortress LLC (C67CF9S4VU)" lane :do_build_app do |options| + puts("Building with build number: " + options[:build_number] + ", commit id: " + options[:commit_id]) gym( workspace: "Telegram-iOS.xcworkspace", configuration: options[:configuration], @@ -39,16 +40,12 @@ lane :do_build_app do |options| end lane :build_for_appstore do |options| - commit = last_git_commit - commit_count = sh("git rev-list --count HEAD") - commit_count_int = commit_count.to_i + 1000 - commit_count_string = commit_count_int.to_s do_build_app( configuration: "ReleaseAppStoreLLC", scheme: "Telegram-iOS-AppStoreLLC", export_method: "app-store", - build_number: commit_count_string, - commit_id: commit[:commit_hash], + build_number: options[:build_number], + commit_id: options[:commit_hash], signingCertificate: signing_identity_llc, provisioningProfiles: { base_app_identifier_llc => "match AppStore " + base_app_identifier_llc, diff --git a/tools/ipadiff.py b/tools/ipadiff.py new file mode 100644 index 0000000000..11455dd713 --- /dev/null +++ b/tools/ipadiff.py @@ -0,0 +1,316 @@ +import sys +import os +import glob +import tempfile +import re +import filecmp +import subprocess +from zipfile import ZipFile + + +def get_file_list(dir): + result_files = [] + result_dirs = [] + for root, dirs, files in os.walk(dir, topdown=False): + for name in files: + result_files.append(os.path.relpath(os.path.join(root, name), dir)) + for name in dirs: + result_dirs.append(os.path.relpath(os.path.join(root, name), dir)) + return set(result_dirs), set(result_files) + + +def remove_codesign_dirs(dirs): + result = set() + for dir in dirs: + if dir == 'SC_Info': + continue + if re.match('Watch/.*\\.appex/SC_Info', dir): + continue + if re.match('PlugIns/.*\\.appex/SC_Info', dir): + continue + if re.match('Frameworks/.*\\.framework/SC_Info', dir): + continue + result.add(dir) + return result + + +def remove_codesign_files(files): + result = set() + for f in files: + if f == 'embedded.mobileprovision': + continue + if re.match('.*/.*\\.appex/embedded.mobileprovision', f): + continue + if f == '_CodeSignature/CodeResources': + continue + if f == 'CrackerXI': + continue + if re.match('Watch/.*\\.app/embedded.mobileprovision', f): + continue + if re.match('PlugIns/.*\\.appex/_CodeSignature/CodeResources', f): + continue + if re.match('Frameworks/.*\\.framework/_CodeSignature/CodeResources', f): + continue + if f == 'Frameworks/ModernProto.framework/ModernProto': + continue + result.add(f) + return result + + +def remove_watch_files(files): + result = set() + excluded = set() + for f in files: + if re.match('Watch/.*', f): + excluded.add(f) + else: + result.add(f) + return (result, excluded) + + +def remove_plugin_files(files): + result = set() + excluded = set() + for f in files: + if False and re.match('PlugIns/.*', f): + excluded.add(f) + else: + result.add(f) + return (result, excluded) + + +def remove_asset_files(files): + result = set() + excluded = set() + for f in files: + if re.match('.*\\.car', f): + excluded.add(f) + else: + result.add(f) + return (result, excluded) + + +def remove_nib_files(files): + result = set() + excluded = set() + for f in files: + if re.match('.*\\.nib', f): + excluded.add(f) + else: + result.add(f) + return (result, excluded) + + +def diff_dirs(ipa1, dir1, ipa2, dir2): + only_in_ipa1 = dir1.difference(dir2) + only_in_ipa2 = dir2.difference(dir1) + if len(only_in_ipa1) == 0 and len(only_in_ipa2) == 0: + return + print('Directory structure doesn\'t match in ' + ipa1 + ' and ' + ipa2) + if len(only_in_ipa1) != 0: + print('Directories not present in ' + ipa2) + for dir in only_in_ipa1: + print(' ' + dir) + if len(only_in_ipa2) != 0: + print('Directories not present in ' + ipa1) + for dir in only_in_ipa2: + print(' ' + dir) + + sys.exit(1) + + +def is_binary(file): + out = os.popen('file "' + file + '"').read() + if out.find('Mach-O') == -1: + return False + return True + + +def is_xcconfig(file): + if re.match('.*\\.xcconfig', file): + return True + else: + return False + + +def diff_binaries(tempdir, self_base_path, file1, file2): + diff_app = tempdir + '/main' + if not os.path.isfile(diff_app): + if not os.path.isfile(self_base_path + '/main.cpp'): + print('Could not find ' + self_base_path + '/main.cpp') + sys.exit(1) + subprocess.call(['clang', self_base_path + '/main.cpp', '-lc++', '-o', diff_app]) + if not os.path.isfile(diff_app): + print('Could not compile ' + self_base_path + '/main.cpp') + sys.exit(1) + + result = os.popen(diff_app + ' ' + file1 + ' ' + file2).read().strip() + if result == 'Encrypted': + return 'binary_encrypted' + elif result == 'Equal': + return 'equal' + elif result == 'Not Equal': + return 'not_equal' + else: + print('Unexpected data from binary diff code: ' + result) + sys.exit(1) + + +def is_plist(file1): + if file1.find('.plist') == -1: + return False + return True + + +def diff_plists(file1, file2): + remove_properties = ['UISupportedDevices', 'DTAppStoreToolsBuild', 'MinimumOSVersion', 'BuildMachineOSBuild'] + + clean1_properties = '' + clean2_properties = '' + + with open(os.devnull, 'w') as devnull: + for property in remove_properties: + if not subprocess.call(['plutil', '-extract', property, 'xml1', '-o', '-', file1], stderr=devnull, stdout=devnull): + clean1_properties += ' | plutil -remove ' + property + ' -r -o - -- -' + if not subprocess.call(['plutil', '-extract', property, 'xml1', '-o', '-', file2], stderr=devnull, stdout=devnull): + clean2_properties += ' | plutil -remove ' + property + ' -r -o - -- -' + + data1 = os.popen('plutil -convert xml1 "' + file1 + '" -o -' + clean1_properties).read() + data2 = os.popen('plutil -convert xml1 "' + file2 + '" -o -' + clean2_properties).read() + + if data1 == data2: + return 'equal' + else: + with open('lhs.plist', 'wb') as f: + f.write(str.encode(data1)) + with open('rhs.plist', 'wb') as f: + f.write(str.encode(data2)) + sys.exit(1) + return 'not_equal' + + +def diff_xcconfigs(file1, file2): + with open(file1, 'rb') as f: + data1 = f.read().strip() + with open(file2, 'rb') as f: + data2 = f.read().strip() + if data1 != data2: + return 'not_equal' + return 'equal' + + +def diff_files(ipa1, files1, ipa2, files2): + only_in_ipa1 = files1.difference(files2) + only_in_ipa2 = files2.difference(files1) + if len(only_in_ipa1) == 0 and len(only_in_ipa2) == 0: + return + if len(only_in_ipa1) != 0: + print('Files not present in ' + ipa2) + for f in only_in_ipa1: + print(' ' + f) + if len(only_in_ipa2) != 0: + print('Files not present in ' + ipa1) + for f in only_in_ipa2: + print(' ' + f) + + sys.exit(1) + + +def base_app_dir(path): + result = glob.glob(path + '/Payload/*.app') + if len(result) == 1: + return result[0] + else: + print('Could not find .app directory at ' + path + '/Payload') + sys.exit(1) + + +def diff_file(tempdir, self_base_path, path1, path2): + if is_plist(path1): + return diff_plists(path1, path2) + elif is_binary(path1): + return diff_binaries(tempdir, self_base_path, path1, path2) + elif is_xcconfig(path1): + return diff_xcconfigs(path1, path2) + else: + if filecmp.cmp(path1, path2): + return 'equal' + return 'not_equal' + + +def ipadiff(self_base_path, ipa1, ipa2): + tempdir = tempfile.mkdtemp() + + ipa1_dir = tempdir + '/ipa1' + ipa2_dir = tempdir + '/ipa2' + + ZipFile(ipa1, 'r').extractall(path=ipa1_dir) + ZipFile(ipa2, 'r').extractall(path=ipa2_dir) + (ipa1_dirs, ipa1_files) = get_file_list(base_app_dir(ipa1_dir)) + (ipa2_dirs, ipa2_files) = get_file_list(base_app_dir(ipa2_dir)) + + clean_ipa1_dirs = remove_codesign_dirs(ipa1_dirs) + clean_ipa2_dirs = remove_codesign_dirs(ipa2_dirs) + + clean_ipa1_files = remove_codesign_files(ipa1_files) + clean_ipa2_files = remove_codesign_files(ipa2_files) + + diff_dirs(ipa1, clean_ipa1_dirs, ipa2, clean_ipa2_dirs) + diff_files(ipa1, clean_ipa1_files, ipa2, clean_ipa2_files) + + clean_ipa1_files, watch_ipa1_files = remove_watch_files(clean_ipa1_files) + clean_ipa2_files, watch_ipa2_files = remove_watch_files(clean_ipa2_files) + + clean_ipa1_files, plugin_ipa1_files = remove_plugin_files(clean_ipa1_files) + clean_ipa2_files, plugin_ipa2_files = remove_plugin_files(clean_ipa2_files) + + clean_ipa1_files, asset_ipa1_files = remove_asset_files(clean_ipa1_files) + clean_ipa2_files, asset_ipa2_files = remove_asset_files(clean_ipa2_files) + + clean_ipa1_files, nib_ipa1_files = remove_nib_files(clean_ipa1_files) + clean_ipa2_files, nib_ipa2_files = remove_nib_files(clean_ipa2_files) + + different_files = [] + encrypted_files = [] + for relative_file_path in clean_ipa1_files: + file_result = diff_file(tempdir, self_base_path, base_app_dir(ipa1_dir) + '/' + relative_file_path, base_app_dir(ipa2_dir) + '/' + relative_file_path) + if file_result == 'equal': + pass + elif file_result == 'binary_encrypted': + encrypted_files.append(relative_file_path) + else: + different_files.append(relative_file_path) + + if len(different_files) != 0: + print('Different files in ' + ipa1 + ' and ' + ipa2) + for relative_file_path in different_files: + print(' ' + relative_file_path) + else: + if len(encrypted_files) != 0 or len(watch_ipa1_files) != 0 or len(plugin_ipa1_files) != 0: + print('IPAs are equal, except for the files that can\'t currently be checked:') + else: + print('IPAs are equal') + + if len(encrypted_files) != 0: + print(' Excluded files that couldn\'t be checked due to being encrypted:') + for relative_file_path in encrypted_files: + print(' ' + relative_file_path) + if len(watch_ipa1_files) != 0: + print(' IPAs contain Watch directory with a Watch app which currently can\'t be checked.') + if len(plugin_ipa1_files) != 0: + print(' IPAs contain PlugIns directory with app extensions. Extensions can\'t currently be checked.') + if len(asset_ipa1_files) != 0: + print(' IPAs contain .car (Asset Catalog) files that are compiled by the App Store and can\'t currently be checked:') + for relative_file_path in asset_ipa1_files: + print(' ' + relative_file_path) + if len(nib_ipa1_files) != 0: + print(' IPAs contain .nib (compiled Interface Builder) files that are compiled by the App Store and can\'t currently be checked:') + for relative_file_path in nib_ipa1_files: + print(' ' + relative_file_path) + + +if len(sys.argv) != 3: + print('Usage: ipadiff ipa1 ipa2') + sys.exit(1) + +ipadiff(os.path.dirname(sys.argv[0]), sys.argv[1], sys.argv[2]) diff --git a/tools/main.cpp b/tools/main.cpp new file mode 100644 index 0000000000..99c513eda5 --- /dev/null +++ b/tools/main.cpp @@ -0,0 +1,262 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static uint32_t funcSwap32(uint32_t input) { + return OSSwapBigToHostInt32(input); +} + +static uint32_t funcNoSwap32(uint32_t input) { + return OSSwapLittleToHostInt32(input); +} + +static bool cleanArch(std::vector &archData, bool &isEncrypted) { + uint32_t (*swap32)(uint32_t) = funcNoSwap32; + + uint32_t offset = 0; + + const struct mach_header* header = (struct mach_header*)(archData.data() + offset); + + switch (header->magic) { + case MH_CIGAM: + swap32 = funcSwap32; + case MH_MAGIC: + offset += sizeof(struct mach_header); + break; + case MH_CIGAM_64: + swap32 = funcSwap32; + case MH_MAGIC_64: + offset += sizeof(struct mach_header_64); + break; + default: + return nullptr; + } + + uint32_t commandCount = swap32(header->ncmds); + + for (uint32_t i = 0; i < commandCount; i++) { + const struct load_command* loadCommand = (const struct load_command*)(archData.data() + offset); + uint32_t commandSize = swap32(loadCommand->cmdsize); + + uint32_t commandType = swap32(loadCommand->cmd); + if (commandType == LC_CODE_SIGNATURE) { + const struct linkedit_data_command *dataCommand = (const struct linkedit_data_command *)(archData.data() + offset); + uint32_t dataOffset = swap32(dataCommand->dataoff); + uint32_t dataSize = swap32(dataCommand->datasize); + + // account for different signature size + memset(archData.data() + offset + offsetof(linkedit_data_command, datasize), 0, sizeof(uint32_t)); + + // remove signature + archData.erase(archData.begin() + dataOffset, archData.begin() + dataOffset + dataSize); + } else if (commandType == LC_SEGMENT_64) { + const struct segment_command_64 *segmentCommand = (const struct segment_command_64 *)(archData.data() + offset); + std::string segmentName = std::string(segmentCommand->segname); + if (segmentName == "__LINKEDIT") { + // account for different signature size + memset(archData.data() + offset + offsetof(segment_command_64, vmsize), 0, sizeof(uint32_t)); + // account for different file size because of signatures + memset(archData.data() + offset + offsetof(segment_command_64, filesize), 0, sizeof(uint32_t)); + } + } else if (commandType == LC_ID_DYLIB) { + // account for dylib timestamp + memset(archData.data() + offset + offsetof(dylib_command, dylib) + offsetof(struct dylib, timestamp), 0, sizeof(uint32_t)); + } else if (commandType == LC_UUID) { + // account for dylib uuid + memset(archData.data() + offset + offsetof(uuid_command, uuid), 0, 16); + } else if (commandType == LC_ENCRYPTION_INFO_64) { + const struct encryption_info_command_64 *encryptionInfoCommand = (const struct encryption_info_command_64 *)(archData.data() + offset); + if (encryptionInfoCommand->cryptid != 0) { + isEncrypted = true; + } + } + + offset += commandSize; + } + + return true; +} + +static std::vector parseFat(std::vector const &fileData) { + size_t offset = 0; + + const struct fat_header *fatHeader = (const struct fat_header *)fileData.data(); + offset += sizeof(*fatHeader); + + size_t initialOffset = offset; + + uint32_t archCount = OSSwapBigToHostInt32(fatHeader->nfat_arch); + + for (uint32_t i = 0; i < archCount; i++) { + const struct fat_arch *arch = (const struct fat_arch *)(fileData.data() + offset); + offset += sizeof(*arch); + + uint32_t archOffset = OSSwapBigToHostInt32(arch->offset); + uint32_t archSize = OSSwapBigToHostInt32(arch->size); + cpu_type_t cputype = OSSwapBigToHostInt32(arch->cputype); + + if (cputype == CPU_TYPE_ARM64) { + std::vector archData; + archData.resize(archSize); + memcpy(archData.data(), fileData.data() + archOffset, archSize); + return archData; + } + } + + offset = initialOffset; + + for (uint32_t i = 0; i < archCount; i++) { + const struct fat_arch *arch = (const struct fat_arch *)(fileData.data() + offset); + offset += sizeof(*arch); + + uint32_t archOffset = OSSwapBigToHostInt32(arch->offset); + uint32_t archSize = OSSwapBigToHostInt32(arch->size); + cpu_type_t cputype = OSSwapBigToHostInt32(arch->cputype); + cpu_type_t cpusubtype = OSSwapBigToHostInt32(arch->cpusubtype); + + if (cputype == CPU_TYPE_ARM && cpusubtype == CPU_SUBTYPE_ARM_V7K) { + std::vector archData; + archData.resize(archSize); + memcpy(archData.data(), fileData.data() + archOffset, archSize); + return archData; + } + } + + return std::vector(); +} + +static std::vector parseMachO(std::vector const &fileData) { + const uint32_t *magic = (const uint32_t *)fileData.data(); + + if (*magic == FAT_CIGAM || *magic == FAT_MAGIC) { + return parseFat(fileData); + } else { + return fileData; + } +} + +static std::vector readFile(std::string const &file) { + int fd = open(file.c_str(), O_RDONLY); + + if (fd == -1) { + return std::vector(); + } + + struct stat st; + fstat(fd, &st); + + std::vector fileData; + fileData.resize((size_t)st.st_size); + read(fd, fileData.data(), (size_t)st.st_size); + close(fd); + + return fileData; +} + +static void writeDataToFile(std::vector const &data, std::string const &path) { + int fd = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd == -1) { + return; + } + + write(fd, data.data(), data.size()); + + close(fd); +} + +static std::vector stripSwiftSymbols(std::string const &file) { + std::string command; + command += "xcrun strip -ST -o /dev/stdout \""; + command += file; + command += "\" 2> /dev/null"; + + uint8_t buffer[128]; + std::vector result; + FILE *pipe = popen(command.c_str(), "r"); + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + while (true) { + size_t readBytes = fread(buffer, 1, 128, pipe); + if (readBytes <= 0) { + break; + } + result.insert(result.end(), buffer, buffer + readBytes); + } + pclose(pipe); + + return result; +} + +static bool endsWith(std::string const &mainStr, std::string const &toMatch) { + if(mainStr.size() >= toMatch.size() && mainStr.compare(mainStr.size() - toMatch.size(), toMatch.size(), toMatch) == 0) { + return true; + } else { + return false; + } +} + +int main(int argc, const char *argv[]) { + if (argc != 3) { + printf("Usage: machofilediff file1 file2\n"); + return 1; + } + + std::string file1 = argv[1]; + std::string file2 = argv[2]; + + std::vector fileData1; + if (endsWith(file1, ".dylib")) { + fileData1 = stripSwiftSymbols(file1); + } else { + fileData1 = readFile(file1); + } + + std::vector fileData2; + if (endsWith(file2, ".dylib")) { + fileData2 = stripSwiftSymbols(file2); + } else { + fileData2 = readFile(file2); + } + + std::vector arch1 = parseMachO(fileData1); + if (arch1.size() == 0) { + printf("Couldn't parse %s\n", file1.c_str()); + return 1; + } + + std::vector arch2 = parseMachO(fileData2); + if (arch2.size() == 0) { + printf("Couldn't parse %s\n", file2.c_str()); + return 1; + } + + bool arch1Encrypted = false; + bool arch2Encrypted = false; + cleanArch(arch1, arch1Encrypted); + cleanArch(arch2, arch2Encrypted); + + if (arch1 == arch2) { + printf("Equal\n"); + return 0; + } else { + if (arch1Encrypted || arch2Encrypted) { + printf("Encrypted\n"); + } else { + printf("Not Equal\n"); + } + + return 1; + } + + return 0; +} From daa27c0f47f136af6ec549e731b66f2596f6ab7d Mon Sep 17 00:00:00 2001 From: Peter <> Date: Tue, 25 Jun 2019 22:54:48 +0300 Subject: [PATCH 09/26] YUV+a animation compression --- .../contents.xcworkspacedata | 3 + submodules/Display/Display/GridNode.swift | 3 + submodules/RLottie/Info.plist | 22 + .../RLottie_Xcode.xcodeproj/project.pbxproj | 875 ++++++++++++++++++ submodules/RLottie/Sources/LottieInstance.h | 16 + submodules/RLottie/Sources/LottieInstance.mm | 32 + submodules/RLottie/Sources/RLottie.h | 19 + .../TelegramCore/TelegramMediaFile.swift | 16 +- .../TelegramUI/AnimatedStickerUtils.swift | 258 ++---- .../CachedResourceRepresentations.swift | 10 +- .../TelegramUI/ChatControllerNode.swift | 2 +- .../ChatInterfaceStateInputPanels.swift | 2 +- .../TelegramUI/ChatMediaInputNode.swift | 2 +- .../ChatMediaInputStickerGridItem.swift | 46 +- .../ChatMediaInputStickerPane.swift | 15 +- .../ChatMessageAnimatedStickerItemNode.swift | 248 ++--- .../TelegramUI/ChatMessageItem.swift | 2 +- .../ChatMessageStickerItemNode.swift | 2 +- .../TelegramUI/ChatTextInputPanelNode.swift | 8 +- .../FetchCachedRepresentations.swift | 5 +- .../TelegramUI/MetalAnimationRenderer.swift | 16 +- .../SoftwareAnimationRenderer.swift | 6 +- .../StickerPackPreviewGridItem.swift | 29 +- .../StickerPreviewPeekContent.swift | 23 +- .../TelegramUI/StickerResources.swift | 6 +- submodules/TelegramUI/TelegramUI/YUV.h | 7 +- submodules/TelegramUI/TelegramUI/YUV.m | 155 ++-- .../project.pbxproj | 82 +- .../third-party/bc1/BC1Compression.cpp | 7 +- .../third-party/bc1/TextureCompression.cpp | 39 +- .../third-party/bc1/TextureCompression.h | 2 + 31 files changed, 1529 insertions(+), 429 deletions(-) create mode 100644 submodules/RLottie/Info.plist create mode 100644 submodules/RLottie/RLottie_Xcode.xcodeproj/project.pbxproj create mode 100644 submodules/RLottie/Sources/LottieInstance.h create mode 100644 submodules/RLottie/Sources/LottieInstance.mm create mode 100644 submodules/RLottie/Sources/RLottie.h diff --git a/Telegram-iOS.xcworkspace/contents.xcworkspacedata b/Telegram-iOS.xcworkspace/contents.xcworkspacedata index 8b5bceb4c8..cad6be2ce4 100644 --- a/Telegram-iOS.xcworkspace/contents.xcworkspacedata +++ b/Telegram-iOS.xcworkspace/contents.xcworkspacedata @@ -1,6 +1,9 @@ + + diff --git a/submodules/Display/Display/GridNode.swift b/submodules/Display/Display/GridNode.swift index 72727165aa..e0f8c2e475 100644 --- a/submodules/Display/Display/GridNode.swift +++ b/submodules/Display/Display/GridNode.swift @@ -217,6 +217,8 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { private var sectionNodes: [WrappedGridSection: ASDisplayNode] = [:] private var itemLayout = GridNodeItemLayout(contentSize: CGSize(), items: [], sections: []) + public var setupNode: ((GridItemNode) -> Void)? + private var applyingContentOffset = false public var visibleItemsUpdated: ((GridNodeVisibleItems) -> Void)? @@ -845,6 +847,7 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { self.addItemNode(index: item.index, itemNode: itemNode, lowestSectionNode: lowestSectionNode) addedNodes = true itemNode.updateLayout(item: self.items[item.index], size: item.frame.size, isVisible: bounds.intersects(item.frame), synchronousLoads: synchronousLoads) + self.setupNode?(itemNode) } } diff --git a/submodules/RLottie/Info.plist b/submodules/RLottie/Info.plist new file mode 100644 index 0000000000..e1fe4cfb7b --- /dev/null +++ b/submodules/RLottie/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/submodules/RLottie/RLottie_Xcode.xcodeproj/project.pbxproj b/submodules/RLottie/RLottie_Xcode.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..099862aed2 --- /dev/null +++ b/submodules/RLottie/RLottie_Xcode.xcodeproj/project.pbxproj @@ -0,0 +1,875 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + D010DF4122C225E4009324D4 /* RLottie.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF3F22C225E4009324D4 /* RLottie.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D010E07022C237CE009324D4 /* rlottiecommon.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF4D22C237CE009324D4 /* rlottiecommon.h */; }; + D010E07222C237CE009324D4 /* rlottie.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF4F22C237CE009324D4 /* rlottie.h */; }; + D010E07322C237CE009324D4 /* rlottie_capi.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF5022C237CE009324D4 /* rlottie_capi.h */; }; + D010E10422C237CE009324D4 /* lottieanimation_capi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DFEC22C237CE009324D4 /* lottieanimation_capi.cpp */; }; + D010E10722C237CE009324D4 /* lottiemodel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DFF022C237CE009324D4 /* lottiemodel.cpp */; }; + D010E10822C237CE009324D4 /* lottieitem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DFF122C237CE009324D4 /* lottieitem.cpp */; }; + D010E10A22C237CE009324D4 /* lottieanimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DFF322C237CE009324D4 /* lottieanimation.cpp */; }; + D010E10B22C237CE009324D4 /* lottiekeypath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DFF422C237CE009324D4 /* lottiekeypath.cpp */; }; + D010E10C22C237CE009324D4 /* lottieparser.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DFF522C237CE009324D4 /* lottieparser.h */; }; + D010E10D22C237CE009324D4 /* lottieparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DFF622C237CE009324D4 /* lottieparser.cpp */; }; + D010E10E22C237CE009324D4 /* lottieloader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DFF722C237CE009324D4 /* lottieloader.cpp */; }; + D010E10F22C237CE009324D4 /* lottieitem.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DFF822C237CE009324D4 /* lottieitem.h */; }; + D010E11022C237CE009324D4 /* lottiekeypath.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DFF922C237CE009324D4 /* lottiekeypath.h */; }; + D010E11222C237CE009324D4 /* lottieproxymodel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DFFB22C237CE009324D4 /* lottieproxymodel.cpp */; }; + D010E11322C237CE009324D4 /* fwd.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DFFD22C237CE009324D4 /* fwd.h */; }; + D010E11422C237CE009324D4 /* memorystream.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DFFE22C237CE009324D4 /* memorystream.h */; }; + D010E11522C237CE009324D4 /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DFFF22C237CE009324D4 /* reader.h */; }; + D010E11622C237CE009324D4 /* prettywriter.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00022C237CE009324D4 /* prettywriter.h */; }; + D010E11722C237CE009324D4 /* ostreamwrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00122C237CE009324D4 /* ostreamwrapper.h */; }; + D010E11822C237CE009324D4 /* encodedstream.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00222C237CE009324D4 /* encodedstream.h */; }; + D010E11922C237CE009324D4 /* filereadstream.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00322C237CE009324D4 /* filereadstream.h */; }; + D010E11A22C237CE009324D4 /* cursorstreamwrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00422C237CE009324D4 /* cursorstreamwrapper.h */; }; + D010E11B22C237CE009324D4 /* istreamwrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00522C237CE009324D4 /* istreamwrapper.h */; }; + D010E11C22C237CE009324D4 /* stringbuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00622C237CE009324D4 /* stringbuffer.h */; }; + D010E11D22C237CE009324D4 /* ieee754.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00822C237CE009324D4 /* ieee754.h */; }; + D010E11E22C237CE009324D4 /* strtod.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00922C237CE009324D4 /* strtod.h */; }; + D010E11F22C237CE009324D4 /* swap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00A22C237CE009324D4 /* swap.h */; }; + D010E12022C237CE009324D4 /* regex.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00B22C237CE009324D4 /* regex.h */; }; + D010E12122C237CE009324D4 /* diyfp.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00C22C237CE009324D4 /* diyfp.h */; }; + D010E12222C237CE009324D4 /* biginteger.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00D22C237CE009324D4 /* biginteger.h */; }; + D010E12322C237CE009324D4 /* strfunc.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00E22C237CE009324D4 /* strfunc.h */; }; + D010E12422C237CE009324D4 /* itoa.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E00F22C237CE009324D4 /* itoa.h */; }; + D010E12522C237CE009324D4 /* stack.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01022C237CE009324D4 /* stack.h */; }; + D010E12622C237CE009324D4 /* dtoa.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01122C237CE009324D4 /* dtoa.h */; }; + D010E12722C237CE009324D4 /* meta.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01222C237CE009324D4 /* meta.h */; }; + D010E12822C237CE009324D4 /* pow10.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01322C237CE009324D4 /* pow10.h */; }; + D010E12922C237CE009324D4 /* encodings.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01422C237CE009324D4 /* encodings.h */; }; + D010E12A22C237CE009324D4 /* schema.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01522C237CE009324D4 /* schema.h */; }; + D010E12B22C237CE009324D4 /* stream.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01622C237CE009324D4 /* stream.h */; }; + D010E12C22C237CE009324D4 /* filewritestream.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01722C237CE009324D4 /* filewritestream.h */; }; + D010E12D22C237CE009324D4 /* rapidjson.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01822C237CE009324D4 /* rapidjson.h */; }; + D010E12E22C237CE009324D4 /* document.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01922C237CE009324D4 /* document.h */; }; + D010E12F22C237CE009324D4 /* allocators.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01A22C237CE009324D4 /* allocators.h */; }; + D010E13022C237CE009324D4 /* writer.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01B22C237CE009324D4 /* writer.h */; }; + D010E13122C237CE009324D4 /* error.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01D22C237CE009324D4 /* error.h */; }; + D010E13222C237CE009324D4 /* en.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01E22C237CE009324D4 /* en.h */; }; + D010E13322C237CE009324D4 /* memorybuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E01F22C237CE009324D4 /* memorybuffer.h */; }; + D010E13422C237CE009324D4 /* pointer.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E02022C237CE009324D4 /* pointer.h */; }; + D010E13722C237CE009324D4 /* lottieproxymodel.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E02422C237CE009324D4 /* lottieproxymodel.h */; }; + D010E13822C237CE009324D4 /* lottiemodel.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E02522C237CE009324D4 /* lottiemodel.h */; }; + D010E13922C237CE009324D4 /* lottieloader.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E02622C237CE009324D4 /* lottieloader.h */; }; + D010E13A22C237CE009324D4 /* vdasher.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E02822C237CE009324D4 /* vdasher.h */; }; + D010E13B22C237CE009324D4 /* vrle.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E02922C237CE009324D4 /* vrle.h */; }; + D010E13C22C237CE009324D4 /* velapsedtimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E02A22C237CE009324D4 /* velapsedtimer.cpp */; }; + D010E13E22C237CE009324D4 /* velapsedtimer.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E02C22C237CE009324D4 /* velapsedtimer.h */; }; + D010E14022C237CE009324D4 /* vrect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E02E22C237CE009324D4 /* vrect.cpp */; }; + D010E14122C237CF009324D4 /* vdasher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E02F22C237CE009324D4 /* vdasher.cpp */; }; + D010E14222C237CF009324D4 /* vbezier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E03022C237CE009324D4 /* vbezier.cpp */; }; + D010E14422C237CF009324D4 /* pixman-arm-neon-asm.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E03322C237CE009324D4 /* pixman-arm-neon-asm.h */; }; + D010E14522C237CF009324D4 /* vregion.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E03422C237CE009324D4 /* vregion.h */; }; + D010E14822C237CF009324D4 /* vregion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E03722C237CE009324D4 /* vregion.cpp */; }; + D010E14922C237CF009324D4 /* vpath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E03822C237CE009324D4 /* vpath.cpp */; }; + D010E14A22C237CF009324D4 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E03922C237CE009324D4 /* config.h */; }; + D010E14C22C237CF009324D4 /* v_ft_types.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E03C22C237CE009324D4 /* v_ft_types.h */; }; + D010E14D22C237CF009324D4 /* v_ft_raster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E03D22C237CE009324D4 /* v_ft_raster.cpp */; }; + D010E14F22C237CF009324D4 /* v_ft_stroker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E03F22C237CE009324D4 /* v_ft_stroker.cpp */; }; + D010E15022C237CF009324D4 /* v_ft_math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E04022C237CE009324D4 /* v_ft_math.cpp */; }; + D010E15122C237CF009324D4 /* v_ft_stroker.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04122C237CE009324D4 /* v_ft_stroker.h */; }; + D010E15222C237CF009324D4 /* v_ft_math.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04222C237CE009324D4 /* v_ft_math.h */; }; + D010E15322C237CF009324D4 /* v_ft_raster.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04322C237CE009324D4 /* v_ft_raster.h */; }; + D010E15422C237CF009324D4 /* vcompositionfunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E04422C237CE009324D4 /* vcompositionfunctions.cpp */; }; + D010E15522C237CF009324D4 /* vdrawhelper.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04522C237CE009324D4 /* vdrawhelper.h */; }; + D010E15622C237CF009324D4 /* vbitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E04622C237CE009324D4 /* vbitmap.cpp */; }; + D010E15722C237CF009324D4 /* vdrawable.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04722C237CE009324D4 /* vdrawable.h */; }; + D010E15822C237CF009324D4 /* vbitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04822C237CE009324D4 /* vbitmap.h */; }; + D010E15922C237CF009324D4 /* vpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04922C237CE009324D4 /* vpoint.h */; }; + D010E15A22C237CF009324D4 /* vpathmesure.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04A22C237CE009324D4 /* vpathmesure.h */; }; + D010E15B22C237CF009324D4 /* vdebug.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04B22C237CE009324D4 /* vdebug.h */; }; + D010E15C22C237CF009324D4 /* vpath.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E04C22C237CE009324D4 /* vpath.h */; }; + D010E15F22C237CF009324D4 /* stb_image.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E05022C237CE009324D4 /* stb_image.h */; }; + D010E16022C237CF009324D4 /* stb_image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E05122C237CE009324D4 /* stb_image.cpp */; }; + D010E16222C237CF009324D4 /* vtaskqueue.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E05322C237CE009324D4 /* vtaskqueue.h */; }; + D010E16322C237CF009324D4 /* vline.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E05422C237CE009324D4 /* vline.h */; }; + D010E16422C237CF009324D4 /* vdrawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E05522C237CE009324D4 /* vdrawable.cpp */; }; + D010E16522C237CF009324D4 /* vpathmesure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E05622C237CE009324D4 /* vpathmesure.cpp */; }; + D010E16622C237CF009324D4 /* vbrush.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E05722C237CE009324D4 /* vbrush.h */; }; + D010E16722C237CF009324D4 /* vpainter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E05822C237CE009324D4 /* vpainter.cpp */; }; + D010E16822C237CF009324D4 /* vdebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E05922C237CE009324D4 /* vdebug.cpp */; }; + D010E16922C237CF009324D4 /* vimageloader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E05A22C237CE009324D4 /* vimageloader.cpp */; }; + D010E16A22C237CF009324D4 /* vglobal.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E05B22C237CE009324D4 /* vglobal.h */; }; + D010E16B22C237CF009324D4 /* vraster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E05C22C237CE009324D4 /* vraster.cpp */; }; + D010E16C22C237CF009324D4 /* vpainter.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E05D22C237CE009324D4 /* vpainter.h */; }; + D010E16D22C237CF009324D4 /* vmatrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E05E22C237CE009324D4 /* vmatrix.cpp */; }; + D010E16E22C237CF009324D4 /* vrect.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E05F22C237CE009324D4 /* vrect.h */; }; + D010E16F22C237CF009324D4 /* vinterpolator.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E06022C237CE009324D4 /* vinterpolator.h */; }; + D010E17022C237CF009324D4 /* vbezier.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E06122C237CE009324D4 /* vbezier.h */; }; + D010E17122C237CF009324D4 /* vdrawhelper_sse2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E06222C237CE009324D4 /* vdrawhelper_sse2.cpp */; }; + D010E17222C237CF009324D4 /* vinterpolator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E06322C237CE009324D4 /* vinterpolator.cpp */; }; + D010E17322C237CF009324D4 /* vdrawhelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E06422C237CE009324D4 /* vdrawhelper.cpp */; }; + D010E17422C237CF009324D4 /* vstackallocator.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E06522C237CE009324D4 /* vstackallocator.h */; }; + D010E17522C237CF009324D4 /* vimageloader.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E06622C237CE009324D4 /* vimageloader.h */; }; + D010E17622C237CF009324D4 /* vraster.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E06722C237CE009324D4 /* vraster.h */; }; + D010E17722C237CF009324D4 /* vmatrix.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E06822C237CE009324D4 /* vmatrix.h */; }; + D010E17822C237CF009324D4 /* vrle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E06922C237CE009324D4 /* vrle.cpp */; }; + D010E17922C237CF009324D4 /* vcowptr.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E06A22C237CE009324D4 /* vcowptr.h */; }; + D010E17A22C237CF009324D4 /* vbrush.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010E06B22C237CE009324D4 /* vbrush.cpp */; }; + D010E17F22C23C42009324D4 /* LottieInstance.mm in Sources */ = {isa = PBXBuildFile; fileRef = D010E17E22C23C42009324D4 /* LottieInstance.mm */; }; + D010E18122C23D57009324D4 /* LottieInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = D010E18022C23D57009324D4 /* LottieInstance.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + D010DF3C22C225E4009324D4 /* RLottie.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RLottie.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D010DF3F22C225E4009324D4 /* RLottie.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RLottie.h; sourceTree = ""; }; + D010DF4022C225E4009324D4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D010DF4D22C237CE009324D4 /* rlottiecommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rlottiecommon.h; sourceTree = ""; }; + D010DF4F22C237CE009324D4 /* rlottie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rlottie.h; sourceTree = ""; }; + D010DF5022C237CE009324D4 /* rlottie_capi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rlottie_capi.h; sourceTree = ""; }; + D010DFEC22C237CE009324D4 /* lottieanimation_capi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lottieanimation_capi.cpp; sourceTree = ""; }; + D010DFF022C237CE009324D4 /* lottiemodel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lottiemodel.cpp; sourceTree = ""; }; + D010DFF122C237CE009324D4 /* lottieitem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lottieitem.cpp; sourceTree = ""; }; + D010DFF322C237CE009324D4 /* lottieanimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lottieanimation.cpp; sourceTree = ""; }; + D010DFF422C237CE009324D4 /* lottiekeypath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lottiekeypath.cpp; sourceTree = ""; }; + D010DFF522C237CE009324D4 /* lottieparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lottieparser.h; sourceTree = ""; }; + D010DFF622C237CE009324D4 /* lottieparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lottieparser.cpp; sourceTree = ""; }; + D010DFF722C237CE009324D4 /* lottieloader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lottieloader.cpp; sourceTree = ""; }; + D010DFF822C237CE009324D4 /* lottieitem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lottieitem.h; sourceTree = ""; }; + D010DFF922C237CE009324D4 /* lottiekeypath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lottiekeypath.h; sourceTree = ""; }; + D010DFFB22C237CE009324D4 /* lottieproxymodel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lottieproxymodel.cpp; sourceTree = ""; }; + D010DFFD22C237CE009324D4 /* fwd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fwd.h; sourceTree = ""; }; + D010DFFE22C237CE009324D4 /* memorystream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memorystream.h; sourceTree = ""; }; + D010DFFF22C237CE009324D4 /* reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = ""; }; + D010E00022C237CE009324D4 /* prettywriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prettywriter.h; sourceTree = ""; }; + D010E00122C237CE009324D4 /* ostreamwrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ostreamwrapper.h; sourceTree = ""; }; + D010E00222C237CE009324D4 /* encodedstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = encodedstream.h; sourceTree = ""; }; + D010E00322C237CE009324D4 /* filereadstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filereadstream.h; sourceTree = ""; }; + D010E00422C237CE009324D4 /* cursorstreamwrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cursorstreamwrapper.h; sourceTree = ""; }; + D010E00522C237CE009324D4 /* istreamwrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = istreamwrapper.h; sourceTree = ""; }; + D010E00622C237CE009324D4 /* stringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stringbuffer.h; sourceTree = ""; }; + D010E00822C237CE009324D4 /* ieee754.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ieee754.h; sourceTree = ""; }; + D010E00922C237CE009324D4 /* strtod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strtod.h; sourceTree = ""; }; + D010E00A22C237CE009324D4 /* swap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = swap.h; sourceTree = ""; }; + D010E00B22C237CE009324D4 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = ""; }; + D010E00C22C237CE009324D4 /* diyfp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = diyfp.h; sourceTree = ""; }; + D010E00D22C237CE009324D4 /* biginteger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = biginteger.h; sourceTree = ""; }; + D010E00E22C237CE009324D4 /* strfunc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strfunc.h; sourceTree = ""; }; + D010E00F22C237CE009324D4 /* itoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = itoa.h; sourceTree = ""; }; + D010E01022C237CE009324D4 /* stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack.h; sourceTree = ""; }; + D010E01122C237CE009324D4 /* dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dtoa.h; sourceTree = ""; }; + D010E01222C237CE009324D4 /* meta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = meta.h; sourceTree = ""; }; + D010E01322C237CE009324D4 /* pow10.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pow10.h; sourceTree = ""; }; + D010E01422C237CE009324D4 /* encodings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = encodings.h; sourceTree = ""; }; + D010E01522C237CE009324D4 /* schema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = schema.h; sourceTree = ""; }; + D010E01622C237CE009324D4 /* stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stream.h; sourceTree = ""; }; + D010E01722C237CE009324D4 /* filewritestream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filewritestream.h; sourceTree = ""; }; + D010E01822C237CE009324D4 /* rapidjson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rapidjson.h; sourceTree = ""; }; + D010E01922C237CE009324D4 /* document.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = document.h; sourceTree = ""; }; + D010E01A22C237CE009324D4 /* allocators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = allocators.h; sourceTree = ""; }; + D010E01B22C237CE009324D4 /* writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = writer.h; sourceTree = ""; }; + D010E01D22C237CE009324D4 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = ""; }; + D010E01E22C237CE009324D4 /* en.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = en.h; sourceTree = ""; }; + D010E01F22C237CE009324D4 /* memorybuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memorybuffer.h; sourceTree = ""; }; + D010E02022C237CE009324D4 /* pointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pointer.h; sourceTree = ""; }; + D010E02422C237CE009324D4 /* lottieproxymodel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lottieproxymodel.h; sourceTree = ""; }; + D010E02522C237CE009324D4 /* lottiemodel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lottiemodel.h; sourceTree = ""; }; + D010E02622C237CE009324D4 /* lottieloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lottieloader.h; sourceTree = ""; }; + D010E02822C237CE009324D4 /* vdasher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vdasher.h; sourceTree = ""; }; + D010E02922C237CE009324D4 /* vrle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vrle.h; sourceTree = ""; }; + D010E02A22C237CE009324D4 /* velapsedtimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = velapsedtimer.cpp; sourceTree = ""; }; + D010E02B22C237CE009324D4 /* vdrawhelper_neon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vdrawhelper_neon.cpp; sourceTree = ""; }; + D010E02C22C237CE009324D4 /* velapsedtimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = velapsedtimer.h; sourceTree = ""; }; + D010E02E22C237CE009324D4 /* vrect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vrect.cpp; sourceTree = ""; }; + D010E02F22C237CE009324D4 /* vdasher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vdasher.cpp; sourceTree = ""; }; + D010E03022C237CE009324D4 /* vbezier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vbezier.cpp; sourceTree = ""; }; + D010E03322C237CE009324D4 /* pixman-arm-neon-asm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "pixman-arm-neon-asm.h"; sourceTree = ""; }; + D010E03422C237CE009324D4 /* vregion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vregion.h; sourceTree = ""; }; + D010E03522C237CE009324D4 /* pixman-arm-neon-asm.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "pixman-arm-neon-asm.S"; sourceTree = ""; }; + D010E03722C237CE009324D4 /* vregion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vregion.cpp; sourceTree = ""; }; + D010E03822C237CE009324D4 /* vpath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vpath.cpp; sourceTree = ""; }; + D010E03922C237CE009324D4 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; + D010E03C22C237CE009324D4 /* v_ft_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v_ft_types.h; sourceTree = ""; }; + D010E03D22C237CE009324D4 /* v_ft_raster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = v_ft_raster.cpp; sourceTree = ""; }; + D010E03F22C237CE009324D4 /* v_ft_stroker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = v_ft_stroker.cpp; sourceTree = ""; }; + D010E04022C237CE009324D4 /* v_ft_math.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = v_ft_math.cpp; sourceTree = ""; }; + D010E04122C237CE009324D4 /* v_ft_stroker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v_ft_stroker.h; sourceTree = ""; }; + D010E04222C237CE009324D4 /* v_ft_math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v_ft_math.h; sourceTree = ""; }; + D010E04322C237CE009324D4 /* v_ft_raster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = v_ft_raster.h; sourceTree = ""; }; + D010E04422C237CE009324D4 /* vcompositionfunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vcompositionfunctions.cpp; sourceTree = ""; }; + D010E04522C237CE009324D4 /* vdrawhelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vdrawhelper.h; sourceTree = ""; }; + D010E04622C237CE009324D4 /* vbitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vbitmap.cpp; sourceTree = ""; }; + D010E04722C237CE009324D4 /* vdrawable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vdrawable.h; sourceTree = ""; }; + D010E04822C237CE009324D4 /* vbitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vbitmap.h; sourceTree = ""; }; + D010E04922C237CE009324D4 /* vpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vpoint.h; sourceTree = ""; }; + D010E04A22C237CE009324D4 /* vpathmesure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vpathmesure.h; sourceTree = ""; }; + D010E04B22C237CE009324D4 /* vdebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vdebug.h; sourceTree = ""; }; + D010E04C22C237CE009324D4 /* vpath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vpath.h; sourceTree = ""; }; + D010E05022C237CE009324D4 /* stb_image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stb_image.h; sourceTree = ""; }; + D010E05122C237CE009324D4 /* stb_image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stb_image.cpp; sourceTree = ""; }; + D010E05322C237CE009324D4 /* vtaskqueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vtaskqueue.h; sourceTree = ""; }; + D010E05422C237CE009324D4 /* vline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vline.h; sourceTree = ""; }; + D010E05522C237CE009324D4 /* vdrawable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vdrawable.cpp; sourceTree = ""; }; + D010E05622C237CE009324D4 /* vpathmesure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vpathmesure.cpp; sourceTree = ""; }; + D010E05722C237CE009324D4 /* vbrush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vbrush.h; sourceTree = ""; }; + D010E05822C237CE009324D4 /* vpainter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vpainter.cpp; sourceTree = ""; }; + D010E05922C237CE009324D4 /* vdebug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vdebug.cpp; sourceTree = ""; }; + D010E05A22C237CE009324D4 /* vimageloader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vimageloader.cpp; sourceTree = ""; }; + D010E05B22C237CE009324D4 /* vglobal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vglobal.h; sourceTree = ""; }; + D010E05C22C237CE009324D4 /* vraster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vraster.cpp; sourceTree = ""; }; + D010E05D22C237CE009324D4 /* vpainter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vpainter.h; sourceTree = ""; }; + D010E05E22C237CE009324D4 /* vmatrix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vmatrix.cpp; sourceTree = ""; }; + D010E05F22C237CE009324D4 /* vrect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vrect.h; sourceTree = ""; }; + D010E06022C237CE009324D4 /* vinterpolator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vinterpolator.h; sourceTree = ""; }; + D010E06122C237CE009324D4 /* vbezier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vbezier.h; sourceTree = ""; }; + D010E06222C237CE009324D4 /* vdrawhelper_sse2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vdrawhelper_sse2.cpp; sourceTree = ""; }; + D010E06322C237CE009324D4 /* vinterpolator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vinterpolator.cpp; sourceTree = ""; }; + D010E06422C237CE009324D4 /* vdrawhelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vdrawhelper.cpp; sourceTree = ""; }; + D010E06522C237CE009324D4 /* vstackallocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vstackallocator.h; sourceTree = ""; }; + D010E06622C237CE009324D4 /* vimageloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vimageloader.h; sourceTree = ""; }; + D010E06722C237CE009324D4 /* vraster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vraster.h; sourceTree = ""; }; + D010E06822C237CE009324D4 /* vmatrix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmatrix.h; sourceTree = ""; }; + D010E06922C237CE009324D4 /* vrle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vrle.cpp; sourceTree = ""; }; + D010E06A22C237CE009324D4 /* vcowptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vcowptr.h; sourceTree = ""; }; + D010E06B22C237CE009324D4 /* vbrush.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vbrush.cpp; sourceTree = ""; }; + D010E17E22C23C42009324D4 /* LottieInstance.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LottieInstance.mm; sourceTree = ""; }; + D010E18022C23D57009324D4 /* LottieInstance.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LottieInstance.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D010DF3922C225E4009324D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D010DF3222C225E4009324D4 = { + isa = PBXGroup; + children = ( + D010DF4022C225E4009324D4 /* Info.plist */, + D010DF3E22C225E4009324D4 /* Sources */, + D010DF3D22C225E4009324D4 /* Products */, + ); + sourceTree = ""; + }; + D010DF3D22C225E4009324D4 /* Products */ = { + isa = PBXGroup; + children = ( + D010DF3C22C225E4009324D4 /* RLottie.framework */, + ); + name = Products; + sourceTree = ""; + }; + D010DF3E22C225E4009324D4 /* Sources */ = { + isa = PBXGroup; + children = ( + D010DF4722C237CE009324D4 /* rlottie */, + D010DF3F22C225E4009324D4 /* RLottie.h */, + D010E18022C23D57009324D4 /* LottieInstance.h */, + D010E17E22C23C42009324D4 /* LottieInstance.mm */, + ); + path = Sources; + sourceTree = ""; + }; + D010DF4722C237CE009324D4 /* rlottie */ = { + isa = PBXGroup; + children = ( + D010DF4B22C237CE009324D4 /* inc */, + D010DFE422C237CE009324D4 /* src */, + ); + path = rlottie; + sourceTree = ""; + }; + D010DF4B22C237CE009324D4 /* inc */ = { + isa = PBXGroup; + children = ( + D010DF4D22C237CE009324D4 /* rlottiecommon.h */, + D010DF4F22C237CE009324D4 /* rlottie.h */, + D010DF5022C237CE009324D4 /* rlottie_capi.h */, + ); + path = inc; + sourceTree = ""; + }; + D010DFE422C237CE009324D4 /* src */ = { + isa = PBXGroup; + children = ( + D010DFE622C237CE009324D4 /* binding */, + D010DFEF22C237CE009324D4 /* lottie */, + D010E02722C237CE009324D4 /* vector */, + ); + path = src; + sourceTree = ""; + }; + D010DFE622C237CE009324D4 /* binding */ = { + isa = PBXGroup; + children = ( + D010DFEA22C237CE009324D4 /* c */, + ); + path = binding; + sourceTree = ""; + }; + D010DFEA22C237CE009324D4 /* c */ = { + isa = PBXGroup; + children = ( + D010DFEC22C237CE009324D4 /* lottieanimation_capi.cpp */, + ); + path = c; + sourceTree = ""; + }; + D010DFEF22C237CE009324D4 /* lottie */ = { + isa = PBXGroup; + children = ( + D010DFF022C237CE009324D4 /* lottiemodel.cpp */, + D010DFF122C237CE009324D4 /* lottieitem.cpp */, + D010DFF322C237CE009324D4 /* lottieanimation.cpp */, + D010DFF422C237CE009324D4 /* lottiekeypath.cpp */, + D010DFF522C237CE009324D4 /* lottieparser.h */, + D010DFF622C237CE009324D4 /* lottieparser.cpp */, + D010DFF722C237CE009324D4 /* lottieloader.cpp */, + D010DFF822C237CE009324D4 /* lottieitem.h */, + D010DFF922C237CE009324D4 /* lottiekeypath.h */, + D010DFFB22C237CE009324D4 /* lottieproxymodel.cpp */, + D010DFFC22C237CE009324D4 /* rapidjson */, + D010E02422C237CE009324D4 /* lottieproxymodel.h */, + D010E02522C237CE009324D4 /* lottiemodel.h */, + D010E02622C237CE009324D4 /* lottieloader.h */, + ); + path = lottie; + sourceTree = ""; + }; + D010DFFC22C237CE009324D4 /* rapidjson */ = { + isa = PBXGroup; + children = ( + D010DFFD22C237CE009324D4 /* fwd.h */, + D010DFFE22C237CE009324D4 /* memorystream.h */, + D010DFFF22C237CE009324D4 /* reader.h */, + D010E00022C237CE009324D4 /* prettywriter.h */, + D010E00122C237CE009324D4 /* ostreamwrapper.h */, + D010E00222C237CE009324D4 /* encodedstream.h */, + D010E00322C237CE009324D4 /* filereadstream.h */, + D010E00422C237CE009324D4 /* cursorstreamwrapper.h */, + D010E00522C237CE009324D4 /* istreamwrapper.h */, + D010E00622C237CE009324D4 /* stringbuffer.h */, + D010E00722C237CE009324D4 /* internal */, + D010E01422C237CE009324D4 /* encodings.h */, + D010E01522C237CE009324D4 /* schema.h */, + D010E01622C237CE009324D4 /* stream.h */, + D010E01722C237CE009324D4 /* filewritestream.h */, + D010E01822C237CE009324D4 /* rapidjson.h */, + D010E01922C237CE009324D4 /* document.h */, + D010E01A22C237CE009324D4 /* allocators.h */, + D010E01B22C237CE009324D4 /* writer.h */, + D010E01C22C237CE009324D4 /* error */, + D010E01F22C237CE009324D4 /* memorybuffer.h */, + D010E02022C237CE009324D4 /* pointer.h */, + ); + path = rapidjson; + sourceTree = ""; + }; + D010E00722C237CE009324D4 /* internal */ = { + isa = PBXGroup; + children = ( + D010E00822C237CE009324D4 /* ieee754.h */, + D010E00922C237CE009324D4 /* strtod.h */, + D010E00A22C237CE009324D4 /* swap.h */, + D010E00B22C237CE009324D4 /* regex.h */, + D010E00C22C237CE009324D4 /* diyfp.h */, + D010E00D22C237CE009324D4 /* biginteger.h */, + D010E00E22C237CE009324D4 /* strfunc.h */, + D010E00F22C237CE009324D4 /* itoa.h */, + D010E01022C237CE009324D4 /* stack.h */, + D010E01122C237CE009324D4 /* dtoa.h */, + D010E01222C237CE009324D4 /* meta.h */, + D010E01322C237CE009324D4 /* pow10.h */, + ); + path = internal; + sourceTree = ""; + }; + D010E01C22C237CE009324D4 /* error */ = { + isa = PBXGroup; + children = ( + D010E01D22C237CE009324D4 /* error.h */, + D010E01E22C237CE009324D4 /* en.h */, + ); + path = error; + sourceTree = ""; + }; + D010E02722C237CE009324D4 /* vector */ = { + isa = PBXGroup; + children = ( + D010E02822C237CE009324D4 /* vdasher.h */, + D010E02922C237CE009324D4 /* vrle.h */, + D010E02A22C237CE009324D4 /* velapsedtimer.cpp */, + D010E02B22C237CE009324D4 /* vdrawhelper_neon.cpp */, + D010E02C22C237CE009324D4 /* velapsedtimer.h */, + D010E02E22C237CE009324D4 /* vrect.cpp */, + D010E02F22C237CE009324D4 /* vdasher.cpp */, + D010E03022C237CE009324D4 /* vbezier.cpp */, + D010E03122C237CE009324D4 /* pixman */, + D010E03822C237CE009324D4 /* vpath.cpp */, + D010E03922C237CE009324D4 /* config.h */, + D010E03A22C237CE009324D4 /* freetype */, + D010E04422C237CE009324D4 /* vcompositionfunctions.cpp */, + D010E04522C237CE009324D4 /* vdrawhelper.h */, + D010E04622C237CE009324D4 /* vbitmap.cpp */, + D010E04722C237CE009324D4 /* vdrawable.h */, + D010E04822C237CE009324D4 /* vbitmap.h */, + D010E04922C237CE009324D4 /* vpoint.h */, + D010E04A22C237CE009324D4 /* vpathmesure.h */, + D010E04B22C237CE009324D4 /* vdebug.h */, + D010E04C22C237CE009324D4 /* vpath.h */, + D010E04D22C237CE009324D4 /* stb */, + D010E05322C237CE009324D4 /* vtaskqueue.h */, + D010E05422C237CE009324D4 /* vline.h */, + D010E05522C237CE009324D4 /* vdrawable.cpp */, + D010E05622C237CE009324D4 /* vpathmesure.cpp */, + D010E05722C237CE009324D4 /* vbrush.h */, + D010E05822C237CE009324D4 /* vpainter.cpp */, + D010E05922C237CE009324D4 /* vdebug.cpp */, + D010E05A22C237CE009324D4 /* vimageloader.cpp */, + D010E05B22C237CE009324D4 /* vglobal.h */, + D010E05C22C237CE009324D4 /* vraster.cpp */, + D010E05D22C237CE009324D4 /* vpainter.h */, + D010E05E22C237CE009324D4 /* vmatrix.cpp */, + D010E05F22C237CE009324D4 /* vrect.h */, + D010E06022C237CE009324D4 /* vinterpolator.h */, + D010E06122C237CE009324D4 /* vbezier.h */, + D010E06222C237CE009324D4 /* vdrawhelper_sse2.cpp */, + D010E06322C237CE009324D4 /* vinterpolator.cpp */, + D010E06422C237CE009324D4 /* vdrawhelper.cpp */, + D010E06522C237CE009324D4 /* vstackallocator.h */, + D010E06622C237CE009324D4 /* vimageloader.h */, + D010E06722C237CE009324D4 /* vraster.h */, + D010E06822C237CE009324D4 /* vmatrix.h */, + D010E06922C237CE009324D4 /* vrle.cpp */, + D010E06A22C237CE009324D4 /* vcowptr.h */, + D010E06B22C237CE009324D4 /* vbrush.cpp */, + ); + path = vector; + sourceTree = ""; + }; + D010E03122C237CE009324D4 /* pixman */ = { + isa = PBXGroup; + children = ( + D010E03322C237CE009324D4 /* pixman-arm-neon-asm.h */, + D010E03422C237CE009324D4 /* vregion.h */, + D010E03522C237CE009324D4 /* pixman-arm-neon-asm.S */, + D010E03722C237CE009324D4 /* vregion.cpp */, + ); + path = pixman; + sourceTree = ""; + }; + D010E03A22C237CE009324D4 /* freetype */ = { + isa = PBXGroup; + children = ( + D010E03C22C237CE009324D4 /* v_ft_types.h */, + D010E03D22C237CE009324D4 /* v_ft_raster.cpp */, + D010E03F22C237CE009324D4 /* v_ft_stroker.cpp */, + D010E04022C237CE009324D4 /* v_ft_math.cpp */, + D010E04122C237CE009324D4 /* v_ft_stroker.h */, + D010E04222C237CE009324D4 /* v_ft_math.h */, + D010E04322C237CE009324D4 /* v_ft_raster.h */, + ); + path = freetype; + sourceTree = ""; + }; + D010E04D22C237CE009324D4 /* stb */ = { + isa = PBXGroup; + children = ( + D010E05022C237CE009324D4 /* stb_image.h */, + D010E05122C237CE009324D4 /* stb_image.cpp */, + ); + path = stb; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + D010DF3722C225E4009324D4 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D010E17622C237CF009324D4 /* vraster.h in Headers */, + D010E12622C237CE009324D4 /* dtoa.h in Headers */, + D010E14422C237CF009324D4 /* pixman-arm-neon-asm.h in Headers */, + D010E16E22C237CF009324D4 /* vrect.h in Headers */, + D010E17922C237CF009324D4 /* vcowptr.h in Headers */, + D010E12022C237CE009324D4 /* regex.h in Headers */, + D010E12422C237CE009324D4 /* itoa.h in Headers */, + D010E13022C237CE009324D4 /* writer.h in Headers */, + D010E11322C237CE009324D4 /* fwd.h in Headers */, + D010E13822C237CE009324D4 /* lottiemodel.h in Headers */, + D010E13E22C237CE009324D4 /* velapsedtimer.h in Headers */, + D010E11422C237CE009324D4 /* memorystream.h in Headers */, + D010E12E22C237CE009324D4 /* document.h in Headers */, + D010E12522C237CE009324D4 /* stack.h in Headers */, + D010E12C22C237CE009324D4 /* filewritestream.h in Headers */, + D010E17022C237CF009324D4 /* vbezier.h in Headers */, + D010E07222C237CE009324D4 /* rlottie.h in Headers */, + D010E11822C237CE009324D4 /* encodedstream.h in Headers */, + D010E11722C237CE009324D4 /* ostreamwrapper.h in Headers */, + D010E15222C237CF009324D4 /* v_ft_math.h in Headers */, + D010E14522C237CF009324D4 /* vregion.h in Headers */, + D010E16C22C237CF009324D4 /* vpainter.h in Headers */, + D010DF4122C225E4009324D4 /* RLottie.h in Headers */, + D010E17722C237CF009324D4 /* vmatrix.h in Headers */, + D010E12D22C237CE009324D4 /* rapidjson.h in Headers */, + D010E11E22C237CE009324D4 /* strtod.h in Headers */, + D010E14A22C237CF009324D4 /* config.h in Headers */, + D010E17422C237CF009324D4 /* vstackallocator.h in Headers */, + D010E10C22C237CE009324D4 /* lottieparser.h in Headers */, + D010E15A22C237CF009324D4 /* vpathmesure.h in Headers */, + D010E13922C237CE009324D4 /* lottieloader.h in Headers */, + D010E12F22C237CE009324D4 /* allocators.h in Headers */, + D010E16322C237CF009324D4 /* vline.h in Headers */, + D010E11C22C237CE009324D4 /* stringbuffer.h in Headers */, + D010E13422C237CE009324D4 /* pointer.h in Headers */, + D010E12222C237CE009324D4 /* biginteger.h in Headers */, + D010E11D22C237CE009324D4 /* ieee754.h in Headers */, + D010E11A22C237CE009324D4 /* cursorstreamwrapper.h in Headers */, + D010E15722C237CF009324D4 /* vdrawable.h in Headers */, + D010E07022C237CE009324D4 /* rlottiecommon.h in Headers */, + D010E16A22C237CF009324D4 /* vglobal.h in Headers */, + D010E12822C237CE009324D4 /* pow10.h in Headers */, + D010E11B22C237CE009324D4 /* istreamwrapper.h in Headers */, + D010E11922C237CE009324D4 /* filereadstream.h in Headers */, + D010E12922C237CE009324D4 /* encodings.h in Headers */, + D010E13722C237CE009324D4 /* lottieproxymodel.h in Headers */, + D010E14C22C237CF009324D4 /* v_ft_types.h in Headers */, + D010E16622C237CF009324D4 /* vbrush.h in Headers */, + D010E12322C237CE009324D4 /* strfunc.h in Headers */, + D010E07322C237CE009324D4 /* rlottie_capi.h in Headers */, + D010E15F22C237CF009324D4 /* stb_image.h in Headers */, + D010E12122C237CE009324D4 /* diyfp.h in Headers */, + D010E13122C237CE009324D4 /* error.h in Headers */, + D010E15822C237CF009324D4 /* vbitmap.h in Headers */, + D010E15922C237CF009324D4 /* vpoint.h in Headers */, + D010E18122C23D57009324D4 /* LottieInstance.h in Headers */, + D010E12A22C237CE009324D4 /* schema.h in Headers */, + D010E12722C237CE009324D4 /* meta.h in Headers */, + D010E13322C237CE009324D4 /* memorybuffer.h in Headers */, + D010E13A22C237CE009324D4 /* vdasher.h in Headers */, + D010E15B22C237CF009324D4 /* vdebug.h in Headers */, + D010E15522C237CF009324D4 /* vdrawhelper.h in Headers */, + D010E13222C237CE009324D4 /* en.h in Headers */, + D010E17522C237CF009324D4 /* vimageloader.h in Headers */, + D010E15122C237CF009324D4 /* v_ft_stroker.h in Headers */, + D010E16222C237CF009324D4 /* vtaskqueue.h in Headers */, + D010E11F22C237CE009324D4 /* swap.h in Headers */, + D010E15322C237CF009324D4 /* v_ft_raster.h in Headers */, + D010E11522C237CE009324D4 /* reader.h in Headers */, + D010E11622C237CE009324D4 /* prettywriter.h in Headers */, + D010E11022C237CE009324D4 /* lottiekeypath.h in Headers */, + D010E15C22C237CF009324D4 /* vpath.h in Headers */, + D010E10F22C237CE009324D4 /* lottieitem.h in Headers */, + D010E12B22C237CE009324D4 /* stream.h in Headers */, + D010E13B22C237CE009324D4 /* vrle.h in Headers */, + D010E16F22C237CF009324D4 /* vinterpolator.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + D010DF3B22C225E4009324D4 /* RLottie */ = { + isa = PBXNativeTarget; + buildConfigurationList = D010DF4422C225E4009324D4 /* Build configuration list for PBXNativeTarget "RLottie" */; + buildPhases = ( + D010DF3722C225E4009324D4 /* Headers */, + D010DF3822C225E4009324D4 /* Sources */, + D010DF3922C225E4009324D4 /* Frameworks */, + D010DF3A22C225E4009324D4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RLottie; + productName = RLottie; + productReference = D010DF3C22C225E4009324D4 /* RLottie.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D010DF3322C225E4009324D4 /* Project object */ = { + isa = PBXProject; + attributes = { + DefaultBuildSystemTypeForWorkspace = Latest; + LastUpgradeCheck = 1010; + ORGANIZATIONNAME = "Telegram LLP"; + TargetAttributes = { + D010DF3B22C225E4009324D4 = { + CreatedOnToolsVersion = 10.1; + }; + }; + }; + buildConfigurationList = D010DF3622C225E4009324D4 /* Build configuration list for PBXProject "RLottie_Xcode" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D010DF3222C225E4009324D4; + productRefGroup = D010DF3D22C225E4009324D4 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D010DF3B22C225E4009324D4 /* RLottie */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D010DF3A22C225E4009324D4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D010DF3822C225E4009324D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D010E14922C237CF009324D4 /* vpath.cpp in Sources */, + D010E16022C237CF009324D4 /* stb_image.cpp in Sources */, + D010E17822C237CF009324D4 /* vrle.cpp in Sources */, + D010E16422C237CF009324D4 /* vdrawable.cpp in Sources */, + D010E10E22C237CE009324D4 /* lottieloader.cpp in Sources */, + D010E16522C237CF009324D4 /* vpathmesure.cpp in Sources */, + D010E16722C237CF009324D4 /* vpainter.cpp in Sources */, + D010E16D22C237CF009324D4 /* vmatrix.cpp in Sources */, + D010E17122C237CF009324D4 /* vdrawhelper_sse2.cpp in Sources */, + D010E10B22C237CE009324D4 /* lottiekeypath.cpp in Sources */, + D010E10A22C237CE009324D4 /* lottieanimation.cpp in Sources */, + D010E14822C237CF009324D4 /* vregion.cpp in Sources */, + D010E17322C237CF009324D4 /* vdrawhelper.cpp in Sources */, + D010E15422C237CF009324D4 /* vcompositionfunctions.cpp in Sources */, + D010E16B22C237CF009324D4 /* vraster.cpp in Sources */, + D010E10822C237CE009324D4 /* lottieitem.cpp in Sources */, + D010E11222C237CE009324D4 /* lottieproxymodel.cpp in Sources */, + D010E10722C237CE009324D4 /* lottiemodel.cpp in Sources */, + D010E14022C237CE009324D4 /* vrect.cpp in Sources */, + D010E10422C237CE009324D4 /* lottieanimation_capi.cpp in Sources */, + D010E17A22C237CF009324D4 /* vbrush.cpp in Sources */, + D010E14F22C237CF009324D4 /* v_ft_stroker.cpp in Sources */, + D010E14222C237CF009324D4 /* vbezier.cpp in Sources */, + D010E14122C237CF009324D4 /* vdasher.cpp in Sources */, + D010E15022C237CF009324D4 /* v_ft_math.cpp in Sources */, + D010E16822C237CF009324D4 /* vdebug.cpp in Sources */, + D010E10D22C237CE009324D4 /* lottieparser.cpp in Sources */, + D010E17222C237CF009324D4 /* vinterpolator.cpp in Sources */, + D010E15622C237CF009324D4 /* vbitmap.cpp in Sources */, + D010E17F22C23C42009324D4 /* LottieInstance.mm in Sources */, + D010E13C22C237CE009324D4 /* velapsedtimer.cpp in Sources */, + D010E14D22C237CF009324D4 /* v_ft_raster.cpp in Sources */, + D010E16922C237CF009324D4 /* vimageloader.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + D010DF4222C225E4009324D4 /* DebugHockeyapp */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = DebugHockeyapp; + }; + D010DF4322C225E4009324D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D010DF4522C225E4009324D4 /* DebugHockeyapp */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + PRODUCT_BUNDLE_IDENTIFIER = org.telegram.RLottie; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugHockeyapp; + }; + D010DF4622C225E4009324D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + PRODUCT_BUNDLE_IDENTIFIER = org.telegram.RLottie; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D010DF3622C225E4009324D4 /* Build configuration list for PBXProject "RLottie_Xcode" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D010DF4222C225E4009324D4 /* DebugHockeyapp */, + D010DF4322C225E4009324D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D010DF4422C225E4009324D4 /* Build configuration list for PBXNativeTarget "RLottie" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D010DF4522C225E4009324D4 /* DebugHockeyapp */, + D010DF4622C225E4009324D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D010DF3322C225E4009324D4 /* Project object */; +} diff --git a/submodules/RLottie/Sources/LottieInstance.h b/submodules/RLottie/Sources/LottieInstance.h new file mode 100644 index 0000000000..42c949e81c --- /dev/null +++ b/submodules/RLottie/Sources/LottieInstance.h @@ -0,0 +1,16 @@ +#ifndef Lottie_h +#define Lottie_h + +#import + +@interface LottieInstance : NSObject + +@property (nonatomic, readonly) int32_t frameCount; +@property (nonatomic, readonly) int32_t frameRate; + +- (instancetype _Nullable)initWithData:(NSData * _Nonnull)data cacheKey:(NSString * _Nonnull)cacheKey; +- (void)renderFrameWithIndex:(int32_t)index into:(uint8_t * _Nonnull)buffer width:(int32_t)width height:(int32_t)height; + +@end + +#endif /* Lottie_h */ diff --git a/submodules/RLottie/Sources/LottieInstance.mm b/submodules/RLottie/Sources/LottieInstance.mm new file mode 100644 index 0000000000..849339297b --- /dev/null +++ b/submodules/RLottie/Sources/LottieInstance.mm @@ -0,0 +1,32 @@ +#import "LottieInstance.h" + +#include + +@interface LottieInstance () { + std::unique_ptr _animation; +} + +@end + +@implementation LottieInstance + +- (instancetype _Nullable)initWithData:(NSData * _Nonnull)data cacheKey:(NSString * _Nonnull)cacheKey { + self = [super init]; + if (self != nil) { + _animation = rlottie::Animation::loadFromData(std::string(reinterpret_cast(data.bytes), data.length), std::string([cacheKey UTF8String])); + if (_animation == nullptr) { + return nil; + } + + _frameCount = (int32_t)_animation->totalFrame(); + _frameRate = (int32_t)_animation->frameRate(); + } + return self; +} + +- (void)renderFrameWithIndex:(int32_t)index into:(uint8_t * _Nonnull)buffer width:(int32_t)width height:(int32_t)height { + rlottie::Surface surface((uint32_t *)buffer, width, height, width * 4); + _animation->renderSync(index, surface); +} + +@end diff --git a/submodules/RLottie/Sources/RLottie.h b/submodules/RLottie/Sources/RLottie.h new file mode 100644 index 0000000000..6f9e94b224 --- /dev/null +++ b/submodules/RLottie/Sources/RLottie.h @@ -0,0 +1,19 @@ +// +// RLottie.h +// RLottie +// +// Created by Peter on 6/25/19. +// Copyright © 2019 Telegram LLP. All rights reserved. +// + +#import + +//! Project version number for RLottie. +FOUNDATION_EXPORT double RLottieVersionNumber; + +//! Project version string for RLottie. +FOUNDATION_EXPORT const unsigned char RLottieVersionString[]; + +#import + + diff --git a/submodules/TelegramCore/TelegramCore/TelegramMediaFile.swift b/submodules/TelegramCore/TelegramCore/TelegramMediaFile.swift index d7170bd462..7e318c1419 100644 --- a/submodules/TelegramCore/TelegramCore/TelegramMediaFile.swift +++ b/submodules/TelegramCore/TelegramCore/TelegramMediaFile.swift @@ -363,6 +363,14 @@ public final class TelegramMediaFile: Media, Equatable { return false } + public var isAnimatedSticker: Bool { + if let fileName = self.fileName, fileName.hasSuffix(".tgs"), self.mimeType == "application/x-tgsticker" { + return true + } else { + return false + } + } + public var isMusic: Bool { for attribute in self.attributes { if case .Audio(false, _, _, _, _) = attribute { @@ -382,7 +390,13 @@ public final class TelegramMediaFile: Media, Equatable { } public var dimensions: CGSize? { - return dimensionsForFileAttributes(self.attributes) + if let value = dimensionsForFileAttributes(self.attributes) { + return value + } else if self.isAnimatedSticker { + return CGSize(width: 512.0, height: 512.0) + } else { + return nil + } } public var duration: Int32? { diff --git a/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift b/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift index ce3fbd0638..60b52b783e 100644 --- a/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift +++ b/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift @@ -8,6 +8,7 @@ import Lottie import TelegramUIPrivateModule import Compression import GZip +import RLottie private func validateAnimationItems(_ items: [Any]?, shapes: Bool = true) -> Bool { if let items = items { @@ -81,7 +82,7 @@ func validateAnimationComposition(json: [AnyHashable: Any]) -> Bool { } @available(iOS 9.0, *) -func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: CGSize) -> Signal { +func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: CGSize, cacheKey: String) -> Signal { return Signal({ subscriber in let queue = Queue() @@ -91,170 +92,97 @@ func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: CGSize) var appendingTime: Double = 0 let decompressedData = TGGUnzipData(data) - if let decompressedData = decompressedData, let json = (try? JSONSerialization.jsonObject(with: decompressedData, options: [])) as? [AnyHashable: Any] { - if validateAnimationComposition(json: json) { - let model = LOTComposition(json: json) - if let startFrame = model.startFrame?.int32Value, let endFrame = model.endFrame?.int32Value { - print("read at \(CACurrentMediaTime() - startTime)") - - var randomId: Int64 = 0 - arc4random_buf(&randomId, 8) - let path = NSTemporaryDirectory() + "\(randomId).lz4v" - guard let fileContext = ManagedFile(queue: queue, path: path, mode: .readwrite) else { - return - } - - let videoSize = CGSize(width: size.width, height: size.height * 2.0) - let scale = size.width / 512.0 - - var currentFrame: Int32 = 0 - - let container = LOTAnimationLayerContainer(model: model, size: size) - - let singleContext = DrawingContext(size: size, scale: 1.0, clear: true) - - var fps: Int32 = model.framerate?.int32Value ?? 30 - let _ = fileContext.write(&fps, count: 4) - - if true { - let frameLength = singleContext.length - assert(frameLength % 16 == 0) - - let previousFrameData = malloc(frameLength)! - memset(previousFrameData, 0, frameLength) - - let bc1FrameData = malloc(frameLength)! - memset(bc1FrameData, 0, frameLength) - - defer { - free(previousFrameData) - free(bc1FrameData) - } - - var compressedFrameData = Data(count: frameLength) - let compressedFrameDataLength = compressedFrameData.count - - let scratchData = malloc(compression_encode_scratch_buffer_size(COMPRESSION_LZ4))! - defer { - free(scratchData) - } - - while startFrame + currentFrame < endFrame { - let drawStartTime = CACurrentMediaTime() - singleContext.withContext { context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.saveGState() - context.scaleBy(x: scale, y: scale) - container?.renderFrame(startFrame + currentFrame, in: context) - context.restoreGState() - } - - var lhs = previousFrameData.assumingMemoryBound(to: UInt64.self) - var rhs = singleContext.bytes.assumingMemoryBound(to: UInt64.self) - for _ in 0 ..< frameLength / 8 { - lhs.pointee = rhs.pointee ^ lhs.pointee - lhs = lhs.advanced(by: 1) - rhs = rhs.advanced(by: 1) - } - - drawingTime += CACurrentMediaTime() - drawStartTime - - compressedFrameData.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in - let length = compression_encode_buffer(bytes, compressedFrameDataLength, previousFrameData.assumingMemoryBound(to: UInt8.self), frameLength, scratchData, COMPRESSION_LZ4) - var frameLengthValue: Int32 = Int32(length) - let _ = fileContext.write(&frameLengthValue, count: 4) - let _ = fileContext.write(bytes, count: length) - } - - memcpy(previousFrameData, singleContext.bytes, frameLength) - - let appendStartTime = CACurrentMediaTime() - - compressRGBAToBC1(previousFrameData.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), bc1FrameData.assumingMemoryBound(to: UInt8.self)) - - appendingTime += CACurrentMediaTime() - appendStartTime - currentFrame += 1 - } - - if startFrame + currentFrame >= endFrame { - subscriber.putNext(path) - subscriber.putCompletion() - print("animation render time \(CACurrentMediaTime() - startTime)") - print("of which drawing time \(drawingTime)") - print("of which appending time \(appendingTime)") - } - } else { - let bgrg422Length = Int(size.width) * 2 * Int(size.height) - let aLength = Int(size.width) * Int(size.height) - let frameLength = bgrg422Length + aLength - - assert(frameLength % 16 == 0) - - let currentFrameData = malloc(frameLength)! - let previousFrameData = malloc(frameLength)! - memset(previousFrameData, 0, frameLength) - - defer { - free(currentFrameData) - free(previousFrameData) - } - - let fps: Int32 = model.framerate?.int32Value ?? 30 - - var compressedFrameData = Data(count: bgrg422Length + aLength) - let compressedFrameDataLength = compressedFrameData.count - - let scratchData = malloc(compression_encode_scratch_buffer_size(COMPRESSION_LZ4))! - defer { - free(scratchData) - } - - while startFrame + currentFrame < endFrame { - let drawStartTime = CACurrentMediaTime() - singleContext.withContext { context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.saveGState() - context.scaleBy(x: scale, y: scale) - container?.renderFrame(startFrame + currentFrame, in: context) - context.restoreGState() - } - - encodeRGBAToBRGR422A(currentFrameData.assumingMemoryBound(to: UInt8.self).advanced(by: 0), currentFrameData.assumingMemoryBound(to: UInt8.self).advanced(by: bgrg422Length), singleContext.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height)) - - var lhs = previousFrameData.assumingMemoryBound(to: UInt64.self) - var rhs = currentFrameData.assumingMemoryBound(to: UInt64.self) - for _ in 0 ..< frameLength / 8 { - lhs.pointee = rhs.pointee ^ lhs.pointee - lhs = lhs.advanced(by: 1) - rhs = rhs.advanced(by: 1) - } - - drawingTime += CACurrentMediaTime() - drawStartTime - - let appendStartTime = CACurrentMediaTime() - compressedFrameData.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in - let length = compression_encode_buffer(bytes, compressedFrameDataLength, previousFrameData.assumingMemoryBound(to: UInt8.self), frameLength, scratchData, COMPRESSION_LZ4) - var frameLengthValue: Int32 = Int32(length) - let _ = fileContext.write(&frameLengthValue, count: 4) - let _ = fileContext.write(bytes, count: length) - } - - memcpy(previousFrameData, currentFrameData, frameLength) - - appendingTime += CACurrentMediaTime() - appendStartTime - currentFrame += 1 - } - - if startFrame + currentFrame >= endFrame { - subscriber.putNext(path) - subscriber.putCompletion() - print("animation render time \(CACurrentMediaTime() - startTime)") - print("of which drawing time \(drawingTime)") - print("of which appending time \(appendingTime)") - } - } - } + if let decompressedData = decompressedData, let player = LottieInstance(data: decompressedData, cacheKey: cacheKey) { + let endFrame = Int(player.frameCount) + print("read at \(CACurrentMediaTime() - startTime)") + + var randomId: Int64 = 0 + arc4random_buf(&randomId, 8) + let path = NSTemporaryDirectory() + "\(randomId).lz4v" + guard let fileContext = ManagedFile(queue: queue, path: path, mode: .readwrite) else { + return } + + let scale = size.width / 512.0 + + var currentFrame: Int32 = 0 + + var fps: Int32 = player.frameRate + let _ = fileContext.write(&fps, count: 4) + var widthValue: Int32 = Int32(size.width) + var heightValue: Int32 = Int32(size.height) + let _ = fileContext.write(&widthValue, count: 4) + let _ = fileContext.write(&heightValue, count: 4) + + let frameLength = Int(size.width) * Int(size.height) * 4 + assert(frameLength % 16 == 0) + + let currentFrameData = malloc(frameLength)! + memset(currentFrameData, 0, frameLength) + + let yuvaLength = Int(size.width) * Int(size.height) * 2 + Int(size.width) * Int(size.height) / 2 + assert(yuvaLength % 8 == 0) + var yuvaFrameData = malloc(yuvaLength)! + memset(yuvaFrameData, 0, yuvaLength) + + var previousYuvaFrameData = malloc(yuvaLength)! + memset(previousYuvaFrameData, 0, yuvaLength) + + defer { + free(currentFrameData) + free(previousYuvaFrameData) + free(yuvaFrameData) + } + + var compressedFrameData = Data(count: frameLength) + let compressedFrameDataLength = compressedFrameData.count + + let scratchData = malloc(compression_encode_scratch_buffer_size(COMPRESSION_LZ4))! + defer { + free(scratchData) + } + + while currentFrame < endFrame { + let drawStartTime = CACurrentMediaTime() + memset(currentFrameData, 0, frameLength) + player.renderFrame(with: Int32(currentFrame), into: currentFrameData.assumingMemoryBound(to: UInt8.self), width: Int32(size.width), height: Int32(size.height)) + + let appendStartTime = CACurrentMediaTime() + + encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), currentFrameData.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height)) + //decodeYUVAToRGBA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), singleContext.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height)) + + appendingTime += CACurrentMediaTime() - appendStartTime + + var lhs = previousYuvaFrameData.assumingMemoryBound(to: UInt64.self) + var rhs = yuvaFrameData.assumingMemoryBound(to: UInt64.self) + for _ in 0 ..< yuvaLength / 8 { + lhs.pointee = rhs.pointee ^ lhs.pointee + lhs = lhs.advanced(by: 1) + rhs = rhs.advanced(by: 1) + } + + drawingTime += CACurrentMediaTime() - drawStartTime + + compressedFrameData.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in + let length = compression_encode_buffer(bytes, compressedFrameDataLength, previousYuvaFrameData.assumingMemoryBound(to: UInt8.self), yuvaLength, scratchData, COMPRESSION_LZ4) + var frameLengthValue: Int32 = Int32(length) + let _ = fileContext.write(&frameLengthValue, count: 4) + let _ = fileContext.write(bytes, count: length) + } + + let tmp = previousYuvaFrameData + previousYuvaFrameData = yuvaFrameData + yuvaFrameData = tmp + + currentFrame += 1 + } + + subscriber.putNext(path) + subscriber.putCompletion() + print("animation render time \(CACurrentMediaTime() - startTime)") + print("of which drawing time \(drawingTime)") + print("of which appending time \(appendingTime)") } } return EmptyDisposable @@ -364,7 +292,7 @@ func convertCompressedLottieToCombinedMp4(data: Data, size: CGSize) -> Signal= endFrame { assetWriterInput.markAsFinished() assetWriter.finishWriting { subscriber.putNext(path) diff --git a/submodules/TelegramUI/TelegramUI/CachedResourceRepresentations.swift b/submodules/TelegramUI/TelegramUI/CachedResourceRepresentations.swift index 513de44094..20bd11248e 100644 --- a/submodules/TelegramUI/TelegramUI/CachedResourceRepresentations.swift +++ b/submodules/TelegramUI/TelegramUI/CachedResourceRepresentations.swift @@ -216,8 +216,16 @@ final class CachedEmojiRepresentation: CachedMediaResourceRepresentation { } final class CachedAnimatedStickerRepresentation: CachedMediaResourceRepresentation { + let width: Int32 + let height: Int32 + var uniqueId: String { - return "animated-sticker-v3" + return "animated-sticker-\(self.width)x\(self.height)-v3" + } + + init(width: Int32, height: Int32) { + self.width = width + self.height = height } func isEqual(to: CachedMediaResourceRepresentation) -> Bool { diff --git a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift index e5aed30622..f898ec9ab0 100644 --- a/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatControllerNode.swift @@ -268,7 +268,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.historyNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) - self.textInputPanelNode = ChatTextInputPanelNode(theme: chatPresentationInterfaceState.theme, presentController: { [weak self] controller in + self.textInputPanelNode = ChatTextInputPanelNode(presentationInterfaceState: chatPresentationInterfaceState, presentController: { [weak self] controller in self?.interfaceInteraction?.presentController(controller, nil) }) self.textInputPanelNode?.storedInputLanguage = chatPresentationInterfaceState.interfaceState.inputLanguage diff --git a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateInputPanels.swift b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateInputPanels.swift index defa532eaf..d3de4c634a 100644 --- a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateInputPanels.swift +++ b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateInputPanels.swift @@ -219,7 +219,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState textInputPanelNode.context = context return textInputPanelNode } else { - let panel = ChatTextInputPanelNode(theme: chatPresentationInterfaceState.theme, presentController: { [weak interfaceInteraction] controller in + let panel = ChatTextInputPanelNode(presentationInterfaceState: chatPresentationInterfaceState, presentController: { [weak interfaceInteraction] controller in interfaceInteraction?.presentController(controller, nil) }) panel.interfaceInteraction = interfaceInteraction diff --git a/submodules/TelegramUI/TelegramUI/ChatMediaInputNode.swift b/submodules/TelegramUI/TelegramUI/ChatMediaInputNode.swift index d5958bb212..85f712d9a0 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMediaInputNode.swift @@ -1321,7 +1321,7 @@ final class ChatMediaInputNode: ChatInputNode { self.gifPane.updateLayout(size: CGSize(width: width - leftInset - rightInset, height: panelHeight), topInset: 41.0, bottomInset: bottomInset, isExpanded: isExpanded, isVisible: isVisible, transition: transition) - self.stickerPane.updateLayout(size: CGSize(width: width - leftInset - rightInset, height: panelHeight), topInset: 41.0, bottomInset: bottomInset, isExpanded: isExpanded, isVisible: isVisible, transition: transition) + self.stickerPane.updateLayout(size: CGSize(width: width - leftInset - rightInset, height: panelHeight), topInset: 41.0, bottomInset: bottomInset, isExpanded: isExpanded, isVisible: isVisible && visiblePanes.contains(where: { $0.0 == .stickers }), transition: transition) self.trendingPane.updateLayout(size: CGSize(width: width - leftInset - rightInset, height: panelHeight), topInset: 41.0, bottomInset: bottomInset, isExpanded: isExpanded, isVisible: isVisible, transition: transition) if self.gifPane.supernode != nil { diff --git a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift index b20e3336ca..9fd8b27fbb 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift @@ -166,11 +166,21 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { private var currentState: (Account, StickerPackItem, CGSize)? private var currentSize: CGSize? private let imageNode: TransformImageNode + private var animationNode: StickerAnimationNode? private let stickerFetchedDisposable = MetaDisposable() var currentIsPreviewing = false + override var isVisibleInGrid: Bool { + didSet { + self.updateVisibility() + } + } + + private var isPanelVisible = false + private var isPlaying = false + var interfaceInteraction: ChatControllerInteraction? var inputNodeInteraction: ChatMediaInputNodeInteraction? var selected: (() -> Void)? @@ -208,7 +218,22 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { } if self.currentState == nil || self.currentState!.0 !== item.account || self.currentState!.1 != item.stickerItem { if let dimensions = item.stickerItem.file.dimensions { - self.imageNode.setSignal(chatMessageSticker(account: item.account, file: item.stickerItem.file, small: true, synchronousLoad: synchronousLoads && isVisible)) + if item.stickerItem.file.isAnimatedSticker { + if self.animationNode == nil { + let animationNode = StickerAnimationNode() + self.animationNode = animationNode + self.addSubnode(animationNode) + } + self.animationNode?.setup(account: item.account, fileReference: FileMediaReference.standalone(media: item.stickerItem.file), width: 140, height: 140) + self.animationNode?.visibility = self.isVisibleInGrid + } else { + if let animationNode = self.animationNode { + animationNode.visibility = false + self.animationNode = nil + animationNode.removeFromSupernode() + } + self.imageNode.setSignal(chatMessageSticker(account: item.account, file: item.stickerItem.file, small: true, synchronousLoad: synchronousLoads && isVisible)) + } self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.account, fileReference: stickerPackFileReference(item.stickerItem.file), resource: chatMessageStickerResource(file: item.stickerItem.file, small: true)).start()) self.currentState = (item.account, item.stickerItem, dimensions) @@ -226,6 +251,10 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { let imageSize = mediaDimensions.aspectFitted(boundingSize) self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))() self.imageNode.frame = CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: (size.height - imageSize.height) / 2.0), size: imageSize) + if let animationNode = self.animationNode { + animationNode.frame = CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: (size.height - imageSize.height) / 2.0), size: imageSize) + animationNode.updateLayout(size: imageSize) + } } } } @@ -244,6 +273,21 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { return self.imageNode } + func updateIsPanelVisible(_ isPanelVisible: Bool) { + if self.isPanelVisible != isPanelVisible { + self.isPanelVisible = isPanelVisible + self.updateVisibility() + } + } + + func updateVisibility() { + let isPlaying = self.isPanelVisible && self.isVisibleInGrid + if self.isPlaying != isPlaying { + self.isPlaying = isPlaying + self.animationNode?.visibility = isPlaying + } + } + func updatePreviewing(animated: Bool) { var isPreviewing = false if let (_, item, _) = self.currentState, let interaction = self.inputNodeInteraction { diff --git a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerPane.swift b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerPane.swift index 6da49891d7..d2caf0a433 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerPane.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerPane.swift @@ -103,6 +103,14 @@ final class ChatMediaInputStickerPane: ChatMediaInputPane { fixGridScrolling(strongSelf.gridNode) } } + self.gridNode.setupNode = { [weak self] itemNode in + guard let strongSelf = self else { + return + } + if let itemNode = itemNode as? ChatMediaInputStickerGridItemNode { + itemNode.updateIsPanelVisible(strongSelf.isPaneVisible) + } + } self.gridNode.scrollView.alwaysBounceVertical = true } @@ -152,10 +160,9 @@ final class ChatMediaInputStickerPane: ChatMediaInputPane { if self.isPaneVisible != isVisible { self.isPaneVisible = isVisible - if isVisible { - self.gridNode.forEachItemNode { itemNode in - if let _ = itemNode as? ChatMediaInputStickerGridItemNode { - } + self.gridNode.forEachItemNode { itemNode in + if let itemNode = itemNode as? ChatMediaInputStickerGridItemNode { + itemNode.updateIsPanelVisible(isVisible) } } } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift index 0710b2bf90..ac14e6d0d9 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift @@ -27,11 +27,17 @@ private final class AnimationFrameCache { } func set(index: Int, bytes: UnsafeRawPointer, length: Int) { - self.cache[index] = NSPurgeableData(bytes: bytes, length: length) + let data = NSPurgeableData(bytes: bytes, length: length) + data.endContentAccess() + self.cache[index] = data + } + + func removeAll() { + self.cache.removeAll() } } -private final class StickerAnimationNode: ASDisplayNode { +final class StickerAnimationNode: ASDisplayNode { private var account: Account? private var fileReference: FileMediaReference? private let disposable = MetaDisposable() @@ -80,8 +86,8 @@ private final class StickerAnimationNode: ASDisplayNode { self.addSubnode(self.renderer!) } - func setup(account: Account, fileReference: FileMediaReference) { - self.disposable.set(chatMessageAnimationData(postbox: account.postbox, fileReference: fileReference, synchronousLoad: false).start(next: { [weak self] data in + func setup(account: Account, fileReference: FileMediaReference, width: Int, height: Int) { + self.disposable.set(chatMessageAnimationData(postbox: account.postbox, fileReference: fileReference, width: width, height: height, synchronousLoad: false).start(next: { [weak self] data in if let strongSelf = self, data.complete { strongSelf.data = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: [.mappedRead]) if strongSelf.visibility { @@ -106,160 +112,104 @@ private final class StickerAnimationNode: ASDisplayNode { self.timer?.invalidate() var scratchBuffer = Data(count: compression_decode_scratch_buffer_size(COMPRESSION_LZ4)) - let width = 320 - let height = 320 - var offset = 0 + var width = 0 + var height = 0 var fps: Int32 = 0 data.withUnsafeBytes { (bytes: UnsafePointer) -> Void in - memcpy(&fps, bytes, 4) + memcpy(&fps, bytes.advanced(by: offset), 4) offset += 4 + var widthValue: Int32 = 0 + var heightValue: Int32 = 0 + memcpy(&widthValue, bytes.advanced(by: offset), 4) + offset += 4 + memcpy(&heightValue, bytes.advanced(by: offset), 4) + offset += 4 + width = Int(widthValue) + height = Int(heightValue) } - if true { - var decodeBuffer = Data(count: width * 4 * height) - var frameBuffer = Data(count: width * 4 * height) - let decodeBufferLength = decodeBuffer.count - frameBuffer.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in - memset(bytes, 0, decodeBufferLength) - } - - var frameIndex = 0 - let timer = SwiftSignalKit.Timer(timeout: 1.0 / Double(fps), repeat: true, completion: { [weak self] in - guard let strongSelf = self else { - return - } - data.withUnsafeBytes { (bytes: UnsafePointer) -> Void in - var frameLength: Int32 = 0 - memcpy(&frameLength, bytes.advanced(by: offset), 4) - - var usedCache = false - strongSelf.frameCache.get(index: frameIndex, { data in - if let data = data { - usedCache = true - - strongSelf.renderer?.render(width: 320, height: 320, bytes: data.bytes, length: data.length) - - if !strongSelf.reportedStarted { - strongSelf.reportedStarted = true - strongSelf.started() - } - } - }) - - if !usedCache { - scratchBuffer.withUnsafeMutableBytes { (scratchBytes: UnsafeMutablePointer) -> Void in - decodeBuffer.withUnsafeMutableBytes { (decodeBytes: UnsafeMutablePointer) -> Void in - frameBuffer.withUnsafeMutableBytes { (frameBytes: UnsafeMutablePointer) -> Void in - compression_decode_buffer(decodeBytes, decodeBufferLength, bytes.advanced(by: offset + 4), Int(frameLength), UnsafeMutableRawPointer(scratchBytes), COMPRESSION_LZ4) - - var lhs = UnsafeMutableRawPointer(frameBytes).assumingMemoryBound(to: UInt64.self) - var rhs = UnsafeRawPointer(decodeBytes).assumingMemoryBound(to: UInt64.self) - for _ in 0 ..< decodeBufferLength / 8 { - lhs.pointee = lhs.pointee ^ rhs.pointee - lhs = lhs.advanced(by: 1) - rhs = rhs.advanced(by: 1) - } - - strongSelf.renderer?.render(width: 320, height: 320, bytes: frameBytes, length: decodeBufferLength) - - strongSelf.frameCache.set(index: frameIndex, bytes: frameBytes, length: decodeBufferLength) - } - } - } - - if !strongSelf.reportedStarted { - strongSelf.reportedStarted = true - strongSelf.started() - } - } - - offset += 4 + Int(frameLength) - frameIndex += 1 - if offset == dataCount { - offset = 4 - frameIndex = 0 - } - } - }, queue: Queue.mainQueue()) - self.timer = timer - timer.start() - } else { - var decodeBuffer = Data(count: width * 2 * height + width * height) - var frameBuffer = Data(count: width * 2 * height + width * height) - let decodeBufferLength = decodeBuffer.count - frameBuffer.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in - memset(bytes, 0, decodeBufferLength) - } - - var frameIndex = 0 - let timer = SwiftSignalKit.Timer(timeout: 1.0 / Double(offset), repeat: true, completion: { [weak self] in - guard let strongSelf = self else { - return - } - data.withUnsafeBytes { (bytes: UnsafePointer) -> Void in - var frameLength: Int32 = 0 - memcpy(&frameLength, bytes.advanced(by: offset), 4) - - var usedCache = false - strongSelf.frameCache.get(index: frameIndex, { data in - if let data = data { - usedCache = true - - strongSelf.renderer?.render(width: 320, height: 320, bytes: data.bytes, length: data.length) - - if !strongSelf.reportedStarted { - strongSelf.reportedStarted = true - strongSelf.started() - } - } - }) - - if !usedCache { - scratchBuffer.withUnsafeMutableBytes { (scratchBytes: UnsafeMutablePointer) -> Void in - decodeBuffer.withUnsafeMutableBytes { (decodeBytes: UnsafeMutablePointer) -> Void in - frameBuffer.withUnsafeMutableBytes { (frameBytes: UnsafeMutablePointer) -> Void in - compression_decode_buffer(decodeBytes, decodeBufferLength, bytes.advanced(by: offset + 4), Int(frameLength), UnsafeMutableRawPointer(scratchBytes), COMPRESSION_LZ4) - - var lhs = UnsafeMutableRawPointer(frameBytes).assumingMemoryBound(to: UInt64.self) - var rhs = UnsafeRawPointer(decodeBytes).assumingMemoryBound(to: UInt64.self) - for _ in 0 ..< Int(decodeBufferLength) / 8 { - lhs.pointee = lhs.pointee ^ rhs.pointee - lhs = lhs.advanced(by: 1) - rhs = rhs.advanced(by: 1) - } - - strongSelf.renderer?.render(width: 320, height: 320, bytes: frameBytes, length: decodeBufferLength) - - strongSelf.frameCache.set(index: frameIndex, bytes: frameBytes, length: decodeBufferLength) - } - } - } - - if !strongSelf.reportedStarted { - strongSelf.reportedStarted = true - strongSelf.started() - } - } - - offset += 4 + Int(frameLength) - frameIndex += 1 - if offset == dataCount { - offset = 0 - frameIndex = 0 - } - } - }, queue: Queue.mainQueue()) - self.timer = timer - timer.start() + let initialOffset = offset + + var decodeBuffer = Data(count: width * 4 * height) + var frameBuffer = Data(count: width * 4 * height) + let decodeBufferLength = decodeBuffer.count + frameBuffer.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in + memset(bytes, 0, decodeBufferLength) } + + var frameIndex = 0 + let timer = SwiftSignalKit.Timer(timeout: 1.0 / Double(fps), repeat: true, completion: { [weak self] in + guard let strongSelf = self else { + return + } + data.withUnsafeBytes { (bytes: UnsafePointer) -> Void in + var frameLength: Int32 = 0 + memcpy(&frameLength, bytes.advanced(by: offset), 4) + + var usedCache = false + strongSelf.frameCache.get(index: frameIndex, { data in + if let data = data { + usedCache = true + + strongSelf.renderer?.render(width: width, height: height, bytes: data.bytes, length: data.length) + + if !strongSelf.reportedStarted { + strongSelf.reportedStarted = true + strongSelf.started() + } + } + }) + + if !usedCache { + scratchBuffer.withUnsafeMutableBytes { (scratchBytes: UnsafeMutablePointer) -> Void in + decodeBuffer.withUnsafeMutableBytes { (decodeBytes: UnsafeMutablePointer) -> Void in + frameBuffer.withUnsafeMutableBytes { (frameBytes: UnsafeMutablePointer) -> Void in + compression_decode_buffer(decodeBytes, decodeBufferLength, bytes.advanced(by: offset + 4), Int(frameLength), UnsafeMutableRawPointer(scratchBytes), COMPRESSION_LZ4) + + var lhs = UnsafeMutableRawPointer(frameBytes).assumingMemoryBound(to: UInt64.self) + var rhs = UnsafeRawPointer(decodeBytes).assumingMemoryBound(to: UInt64.self) + for _ in 0 ..< decodeBufferLength / 8 { + lhs.pointee = lhs.pointee ^ rhs.pointee + lhs = lhs.advanced(by: 1) + rhs = rhs.advanced(by: 1) + } + + strongSelf.renderer?.render(width: width, height: height, bytes: frameBytes, length: decodeBufferLength) + + //strongSelf.frameCache.set(index: frameIndex, bytes: frameBytes, length: decodeBufferLength) + } + } + } + + if !strongSelf.reportedStarted { + strongSelf.reportedStarted = true + strongSelf.started() + } + } + + offset += 4 + Int(frameLength) + frameIndex += 1 + if offset == dataCount { + offset = initialOffset + frameIndex = 0 + frameBuffer.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in + memset(bytes, 0, decodeBufferLength) + } + } + } + }, queue: Queue.mainQueue()) + self.timer = timer + timer.start() } } func stop() { self.timer?.invalidate() self.timer = nil + self.reportedStarted = false + self.frameCache.removeAll() } func updateLayout(size: CGSize) { @@ -366,7 +316,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if self.telegramFile?.id != telegramFile.id { self.telegramFile = telegramFile self.imageNode.setSignal(chatMessageSticker(account: item.context.account, file: telegramFile, small: false, thumbnail: true)) - self.animationNode.setup(account: item.context.account, fileReference: .message(message: MessageReference(item.message), media: telegramFile)) + self.animationNode.setup(account: item.context.account, fileReference: .message(message: MessageReference(item.message), media: telegramFile), width: 360, height: 360) } break } @@ -374,7 +324,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, Bool) -> Void) { - let displaySize = CGSize(width: 162.0, height: 162.0) + let displaySize = CGSize(width: 184.0, height: 184.0) let telegramFile = self.telegramFile let layoutConstants = self.layoutConstants let imageLayout = self.imageNode.asyncLayout() @@ -387,14 +337,14 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in let incoming = item.message.effectivelyIncoming(item.context.account.peerId) - var imageSize: CGSize = CGSize(width: 160.0, height: 160.0) - /*if let telegramFile = telegramFile { + var imageSize: CGSize = CGSize(width: 200.0, height: 200.0) + if let telegramFile = telegramFile { if let dimensions = telegramFile.dimensions { imageSize = dimensions.aspectFitted(displaySize) } else if let thumbnailSize = telegramFile.previewRepresentations.first?.dimensions { imageSize = thumbnailSize.aspectFitted(displaySize) } - }*/ + } let avatarInset: CGFloat var hasAvatar = false diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageItem.swift b/submodules/TelegramUI/TelegramUI/ChatMessageItem.swift index e5262ec77a..fd9bd147e3 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageItem.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageItem.swift @@ -353,7 +353,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { loop: for media in self.message.media { if let telegramFile = media as? TelegramMediaFile { - if let fileName = telegramFile.fileName, fileName.hasSuffix(".tgs") && telegramFile.mimeType == "application/x-tgsticker", let size = telegramFile.size, size > 0 && size <= 64 * 1024, !telegramFile.previewRepresentations.isEmpty { + if telegramFile.isAnimatedSticker, let size = telegramFile.size, size > 0 && size <= 64 * 1024, !telegramFile.previewRepresentations.isEmpty { viewClassName = ChatMessageAnimatedStickerItemNode.self break loop } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift index f1ff78b432..3debf63e5f 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift @@ -117,7 +117,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, Bool) -> Void) { - let displaySize = CGSize(width: 162.0, height: 162.0) + let displaySize = CGSize(width: 184.0, height: 184.0) let telegramFile = self.telegramFile let layoutConstants = self.layoutConstants let imageLayout = self.imageNode.asyncLayout() diff --git a/submodules/TelegramUI/TelegramUI/ChatTextInputPanelNode.swift b/submodules/TelegramUI/TelegramUI/ChatTextInputPanelNode.swift index ae04d17996..c39d0610f9 100644 --- a/submodules/TelegramUI/TelegramUI/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatTextInputPanelNode.swift @@ -317,10 +317,12 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { private let accessoryButtonSpacing: CGFloat = 0.0 private let accessoryButtonInset: CGFloat = 2.0 - init(theme: PresentationTheme, presentController: @escaping (ViewController) -> Void) { + init(presentationInterfaceState: ChatPresentationInterfaceState, presentController: @escaping (ViewController) -> Void) { + self.presentationInterfaceState = presentationInterfaceState + self.textInputContainer = ASDisplayNode() self.textInputContainer.clipsToBounds = true - self.textInputContainer.backgroundColor = theme.chat.inputPanel.inputBackgroundColor + self.textInputContainer.backgroundColor = presentationInterfaceState.theme.chat.inputPanel.inputBackgroundColor self.textInputBackgroundNode = ASImageNode() self.textInputBackgroundNode.displaysAsynchronously = false @@ -335,7 +337,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.searchLayoutProgressView = UIImageView(image: searchLayoutProgressImage) self.searchLayoutProgressView.isHidden = true - self.actionButtons = ChatTextInputActionButtonsNode(theme: theme, presentController: presentController) + self.actionButtons = ChatTextInputActionButtonsNode(theme: presentationInterfaceState.theme, presentController: presentController) super.init() diff --git a/submodules/TelegramUI/TelegramUI/FetchCachedRepresentations.swift b/submodules/TelegramUI/TelegramUI/FetchCachedRepresentations.swift index 95a094b3b5..5162de2352 100644 --- a/submodules/TelegramUI/TelegramUI/FetchCachedRepresentations.swift +++ b/submodules/TelegramUI/TelegramUI/FetchCachedRepresentations.swift @@ -889,7 +889,7 @@ private func fetchAnimatedStickerRepresentation(account: Account, resource: Medi return Signal({ subscriber in if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) { if #available(iOS 9.0, *) { - return experimentalConvertCompressedLottieToCombinedMp4(data: data, size: CGSize(width: 320.0, height: 320.0)).start(next: { path in + return experimentalConvertCompressedLottieToCombinedMp4(data: data, size: CGSize(width: CGFloat(representation.width), height: CGFloat(representation.height)), cacheKey: "\(resource.id.uniqueId)-\(representation.uniqueId)").start(next: { path in subscriber.putNext(CachedMediaResourceRepresentationResult(temporaryPath: path)) subscriber.putCompletion() }) @@ -899,5 +899,6 @@ private func fetchAnimatedStickerRepresentation(account: Account, resource: Medi } else { return EmptyDisposable } - }) |> runOn(Queue.concurrentDefaultQueue()) + }) + |> runOn(Queue.concurrentDefaultQueue()) } diff --git a/submodules/TelegramUI/TelegramUI/MetalAnimationRenderer.swift b/submodules/TelegramUI/TelegramUI/MetalAnimationRenderer.swift index 7251e4eb19..c88c2c8d65 100644 --- a/submodules/TelegramUI/TelegramUI/MetalAnimationRenderer.swift +++ b/submodules/TelegramUI/TelegramUI/MetalAnimationRenderer.swift @@ -55,12 +55,12 @@ vertex VertexOut basic_vertex( fragment float4 basic_fragment( VertexOut interpolated [[stage_in]], texture2d texColor [[ texture(0) ]], - sampler samplerColor [[ sampler(0) ]], - texture2d texA [[ texture(1) ]], - sampler samplerA [[ sampler(1) ]] + sampler samplerColor [[ sampler(0) ]]//, + //texture2d texA [[ texture(1) ]], + //sampler samplerA [[ sampler(1) ]] ) { float4 color = texColor.sample(samplerColor, interpolated.texCoord); - float4 alpha = texA.sample(samplerA, interpolated.texCoord); + float4 alpha = 1.0;//texA.sample(samplerA, interpolated.texCoord); return float4(color.r * alpha.a, color.g * alpha.a, color.b * alpha.a, alpha.a); } """, options: nil) @@ -89,7 +89,7 @@ fragment float4 basic_fragment( let dataSize = vertexData.count * MemoryLayout.size(ofValue: vertexData[0]) self.vertexBuffer = device.makeBuffer(bytes: vertexData, length: dataSize, options: [])! - let colorTextureDesc: MTLTextureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .bgrg422, width: 320, height: 320, mipmapped: false) + let colorTextureDesc: MTLTextureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .pvrtc_rgb_4bpp, width: 512, height: 512, mipmapped: false) colorTextureDesc.sampleCount = 1 if #available(iOS 9.0, *) { colorTextureDesc.storageMode = .private @@ -146,10 +146,10 @@ fragment float4 basic_fragment( } let bgrgLength = width * 2 * height - let alphaLength = width * height + //let alphaLength = width * height - self.colorTexture.replace(region: MTLRegionMake2D(0, 0, width, height), mipmapLevel: 0, withBytes: bytes.assumingMemoryBound(to: UInt8.self), bytesPerRow: width * 2) - self.alphaTexture.replace(region: MTLRegionMake2D(0, 0, width, height), mipmapLevel: 0, withBytes: bytes.assumingMemoryBound(to: UInt8.self).advanced(by: bgrgLength), bytesPerRow: width) + self.colorTexture.replace(region: MTLRegionMake2D(0, 0, width, height), mipmapLevel: 0, withBytes: bytes.assumingMemoryBound(to: UInt8.self), bytesPerRow: width / 2) + //self.alphaTexture.replace(region: MTLRegionMake2D(0, 0, width, height), mipmapLevel: 0, withBytes: bytes.assumingMemoryBound(to: UInt8.self).advanced(by: bgrgLength), bytesPerRow: width) let renderPassDescriptor = MTLRenderPassDescriptor() let drawable = self.metalLayer.nextDrawable()! diff --git a/submodules/TelegramUI/TelegramUI/SoftwareAnimationRenderer.swift b/submodules/TelegramUI/TelegramUI/SoftwareAnimationRenderer.swift index 31104db17e..c0a8a295c7 100644 --- a/submodules/TelegramUI/TelegramUI/SoftwareAnimationRenderer.swift +++ b/submodules/TelegramUI/TelegramUI/SoftwareAnimationRenderer.swift @@ -7,11 +7,7 @@ import TelegramUIPrivateModule final class SoftwareAnimationRenderer: ASDisplayNode, AnimationRenderer { func render(width: Int, height: Int, bytes: UnsafeRawPointer, length: Int) { let image = generateImagePixel(CGSize(width: CGFloat(width), height: CGFloat(height)), scale: 1.0, pixelGenerator: { _, pixelData in - if true { - memcpy(pixelData, bytes, length) - } else { - encodeBRGR422AToRGBA(bytes.assumingMemoryBound(to: UInt8.self), bytes.assumingMemoryBound(to: UInt8.self).advanced(by: width * 2 * height), pixelData, Int32(width), Int32(height)) - } + decodeYUVAToRGBA(bytes.assumingMemoryBound(to: UInt8.self), pixelData, Int32(width), Int32(height)) }) self.contents = image?.cgImage diff --git a/submodules/TelegramUI/TelegramUI/StickerPackPreviewGridItem.swift b/submodules/TelegramUI/TelegramUI/StickerPackPreviewGridItem.swift index 075fd8ae4e..51feb375f6 100644 --- a/submodules/TelegramUI/TelegramUI/StickerPackPreviewGridItem.swift +++ b/submodules/TelegramUI/TelegramUI/StickerPackPreviewGridItem.swift @@ -49,6 +49,14 @@ private let textFont = Font.regular(20.0) final class StickerPackPreviewGridItemNode: GridItemNode { private var currentState: (Account, StickerPackItem, CGSize)? private let imageNode: TransformImageNode + private var animationNode: StickerAnimationNode? + + override var isVisibleInGrid: Bool { + didSet { + self.animationNode?.visibility = self.isVisibleInGrid + } + } + private let textNode: ASTextNode private var currentIsPreviewing = false @@ -101,7 +109,22 @@ final class StickerPackPreviewGridItemNode: GridItemNode { } self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: .black, paragraphAlignment: .right) if let dimensions = stickerItem.file.dimensions { - self.imageNode.setSignal(chatMessageSticker(account: account, file: stickerItem.file, small: true)) + if stickerItem.file.isAnimatedSticker { + if self.animationNode == nil { + let animationNode = StickerAnimationNode() + self.animationNode = animationNode + self.addSubnode(animationNode) + } + self.animationNode?.setup(account: account, fileReference: FileMediaReference.standalone(media: stickerItem.file), width: 140, height: 140) + self.animationNode?.visibility = self.isVisibleInGrid + } else { + if let animationNode = self.animationNode { + animationNode.visibility = false + self.animationNode = nil + animationNode.removeFromSupernode() + } + self.imageNode.setSignal(chatMessageSticker(account: account, file: stickerItem.file, small: true)) + } self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(stickerItem.file), resource: chatMessageStickerResource(file: stickerItem.file, small: true)).start()) @@ -125,6 +148,10 @@ final class StickerPackPreviewGridItemNode: GridItemNode { let imageSize = mediaDimensions.aspectFitted(boundingSize) self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))() self.imageNode.frame = CGRect(origin: CGPoint(x: floor((bounds.size.width - imageSize.width) / 2.0), y: (bounds.size.height - imageSize.height) / 2.0), size: imageSize) + if let animationNode = self.animationNode { + animationNode.frame = CGRect(origin: CGPoint(x: floor((bounds.size.width - imageSize.width) / 2.0), y: (bounds.size.height - imageSize.height) / 2.0), size: imageSize) + animationNode.updateLayout(size: imageSize) + } let boundingFrame = CGRect(origin: CGPoint(x: floor((bounds.size.width - boundingSize.width) / 2.0), y: (bounds.size.height - boundingSize.height) / 2.0), size: boundingSize) let textSize = CGSize(width: 32.0, height: 24.0) self.textNode.frame = CGRect(origin: CGPoint(x: boundingFrame.maxX - 1.0 - textSize.width, y: boundingFrame.height + 10.0 - textSize.height), size: textSize) diff --git a/submodules/TelegramUI/TelegramUI/StickerPreviewPeekContent.swift b/submodules/TelegramUI/TelegramUI/StickerPreviewPeekContent.swift index c9cce2f335..8d2e6cd5f1 100644 --- a/submodules/TelegramUI/TelegramUI/StickerPreviewPeekContent.swift +++ b/submodules/TelegramUI/TelegramUI/StickerPreviewPeekContent.swift @@ -66,6 +66,8 @@ private final class StickerPreviewPeekContentNode: ASDisplayNode, PeekController private var textNode: ASTextNode private var imageNode: TransformImageNode + private var animationNode: StickerAnimationNode? + private var containerLayout: (ContainerViewLayout, CGFloat)? init(account: Account, item: StickerPreviewPeekItem) { @@ -80,13 +82,28 @@ private final class StickerPreviewPeekContentNode: ASDisplayNode, PeekController self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(32.0), textColor: .black) break } + + if item.file.isAnimatedSticker { + let animationNode = StickerAnimationNode() + self.animationNode = animationNode + + self.animationNode?.setup(account: account, fileReference: FileMediaReference.standalone(media: item.file), width: 320, height: 320) + self.animationNode?.visibility = true + } else { + self.animationNode = nil + } + self.imageNode.setSignal(chatMessageSticker(account: account, file: item.file, small: false, fetched: true)) super.init() self.isUserInteractionEnabled = false - self.addSubnode(self.imageNode) + if let animationNode = self.animationNode { + self.addSubnode(animationNode) + } else { + self.addSubnode(self.imageNode) + } } func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { @@ -100,6 +117,10 @@ private final class StickerPreviewPeekContentNode: ASDisplayNode, PeekController self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))() let imageFrame = CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: textSize.height + textSpacing), size: imageSize) self.imageNode.frame = imageFrame + if let animationNode = self.animationNode { + animationNode.frame = imageFrame + animationNode.updateLayout(size: imageSize) + } self.textNode.frame = CGRect(origin: CGPoint(x: floor((imageFrame.size.width - textSize.width) / 2.0), y: -textSize.height - textSpacing), size: textSize) diff --git a/submodules/TelegramUI/TelegramUI/StickerResources.swift b/submodules/TelegramUI/TelegramUI/StickerResources.swift index ae10100c7c..33c43fcd3c 100644 --- a/submodules/TelegramUI/TelegramUI/StickerResources.swift +++ b/submodules/TelegramUI/TelegramUI/StickerResources.swift @@ -168,8 +168,8 @@ private func chatMessageStickerPackThumbnailData(postbox: Postbox, representatio } } -func chatMessageAnimationData(postbox: Postbox, fileReference: FileMediaReference, synchronousLoad: Bool) -> Signal { - let maybeFetched = postbox.mediaBox.cachedResourceRepresentation(fileReference.media.resource, representation: CachedAnimatedStickerRepresentation(), pathExtension: "mp4", complete: false, fetch: false, attemptSynchronously: synchronousLoad) +func chatMessageAnimationData(postbox: Postbox, fileReference: FileMediaReference, width: Int, height: Int, synchronousLoad: Bool) -> Signal { + let maybeFetched = postbox.mediaBox.cachedResourceRepresentation(fileReference.media.resource, representation: CachedAnimatedStickerRepresentation(width: Int32(width), height: Int32(height)), pathExtension: "mp4", complete: false, fetch: false, attemptSynchronously: synchronousLoad) return maybeFetched |> take(1) @@ -177,7 +177,7 @@ func chatMessageAnimationData(postbox: Postbox, fileReference: FileMediaReferenc if maybeData.complete { return .single(maybeData) } else { - return postbox.mediaBox.cachedResourceRepresentation(fileReference.media.resource, representation: CachedAnimatedStickerRepresentation(), pathExtension: "mp4", complete: false) + return postbox.mediaBox.cachedResourceRepresentation(fileReference.media.resource, representation: CachedAnimatedStickerRepresentation(width: Int32(width), height: Int32(height)), pathExtension: "mp4", complete: false) } } } diff --git a/submodules/TelegramUI/TelegramUI/YUV.h b/submodules/TelegramUI/TelegramUI/YUV.h index a13fe86332..9208d75f39 100644 --- a/submodules/TelegramUI/TelegramUI/YUV.h +++ b/submodules/TelegramUI/TelegramUI/YUV.h @@ -1,7 +1,4 @@ #import -void encodeRGBAToBRGR422A(uint8_t * _Nonnull bgrg422, uint8_t * _Nonnull a, uint8_t const * _Nonnull argb, int width, int height); -void encodeBRGR422AToRGBA(uint8_t const * _Nonnull bgrg422, uint8_t const * _Nonnull a, uint8_t * _Nonnull argb, int width, int height); - -NSData * _Nonnull encodeSparseBuffer(uint8_t const * _Nonnull bytes, int length); -void decodeSparseeBuffer(uint8_t * _Nonnull bytes, uint8_t const * _Nonnull buffer); +void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height); +void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height); diff --git a/submodules/TelegramUI/TelegramUI/YUV.m b/submodules/TelegramUI/TelegramUI/YUV.m index 43277cabd0..14de0384e6 100644 --- a/submodules/TelegramUI/TelegramUI/YUV.m +++ b/submodules/TelegramUI/TelegramUI/YUV.m @@ -1,67 +1,96 @@ #import "YUV.h" +#import -void encodeRGBAToBRGR422A(uint8_t *bgrg422, uint8_t *a, uint8_t const *argb, int width, int height) { - int i, j; - int lineWidth = width * 2; - for (j = 0; j < height; j++) { - for (i = 0; i < width; i += 2) { - int A1 = argb[(j * width + i) * 4 + 0]; - int R1 = argb[(j * width + i) * 4 + 3]; - int G1 = argb[(j * width + i) * 4 + 2]; - int B1 = argb[(j * width + i) * 4 + 1]; - - int A2 = argb[(j * width + i) * 4 + 4]; - int R2 = argb[(j * width + i) * 4 + 7]; - int G2 = argb[(j * width + i) * 4 + 6]; - int B2 = argb[(j * width + i) * 4 + 5]; - - bgrg422[j * lineWidth + (i / 2) * 4 + 0] = (uint8_t)((B1 + B2) >> 1); - bgrg422[j * lineWidth + (i / 2) * 4 + 1] = G1; - bgrg422[j * lineWidth + (i / 2) * 4 + 2] = (uint8_t)((R1 + R2) >> 1); - bgrg422[j * lineWidth + (i / 2) * 4 + 3] = G2; - - a[j * width + i + 0] = A1; - a[j * width + i + 1] = A2; - } - } -} - -void encodeBRGR422AToRGBA(uint8_t const * _Nonnull bgrg422, uint8_t const * _Nonnull const a, uint8_t * _Nonnull argb, int width, int height) { - int i, j; - int lineWidth = width * 2; - for (j = 0; j < height; j++) { - for (i = 0; i < width; i += 2) { - argb[(j * width + i) * 4 + 0] = a[j * width + i + 0]; - argb[(j * width + i) * 4 + 3] = bgrg422[j * lineWidth + (i / 2) * 4 + 2]; - argb[(j * width + i) * 4 + 2] = bgrg422[j * lineWidth + (i / 2) * 4 + 1]; - argb[(j * width + i) * 4 + 1] = bgrg422[j * lineWidth + (i / 2) * 4 + 0]; - - argb[(j * width + i) * 4 + 4] = a[j * width + i + 1]; - argb[(j * width + i) * 4 + 7] = bgrg422[j * lineWidth + (i / 2) * 4 + 2]; - argb[(j * width + i) * 4 + 6] = bgrg422[j * lineWidth + (i / 2) * 4 + 3]; - argb[(j * width + i) * 4 + 5] = bgrg422[j * lineWidth + (i / 2) * 4 + 0]; - } - } -} - -NSData * _Nonnull encodeSparseBuffer(uint8_t const * _Nonnull bytes, int length) { - NSMutableData *result = [[NSMutableData alloc] init]; - int offset = 0; - int currentStart = 0; - int currentType = 0; - while (offset != length) { - if (bytes[offset] == 0) { - if (currentType != 0) { - - } - } else { - - } - offset += 1; - } - return result; -} - -void decodeSparseeBuffer(uint8_t * _Nonnull bytes, uint8_t const * _Nonnull buffer) { +void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height) { + vImage_YpCbCrPixelRange pixelRange = (vImage_YpCbCrPixelRange){ 0, 128, 255, 255, 255, 0, 255, 0 }; + vImage_ARGBToYpCbCr info; + vImage_Error error; + error = vImageConvert_ARGBToYpCbCr_GenerateConversion(kvImage_ARGBToYpCbCrMatrix_ITU_R_601_4, &pixelRange, &info, kvImageARGB8888, kvImage420Yp8_Cb8_Cr8, 0); + if (error != kvImageNoError) { + return; + } + + vImage_Buffer src; + src.data = (void *)argb; + src.width = width; + src.height = height; + src.rowBytes = width * 4; + + uint8_t permuteMap[4] = {3, 2, 1, 0}; + error = vImagePermuteChannels_ARGB8888(&src, &src, permuteMap, kvImageDoNotTile); + + error = vImageUnpremultiplyData_ARGB8888(&src, &src, kvImageDoNotTile); + + uint8_t *buf = (uint8_t *)argb; + uint8_t *alpha = yuva + (width * height * 1 + width * height * 1); + for (int i = 0; i < width * height; i += 2) { + uint8_t a0 = (buf[i * 4 + 0] >> 4) << 4; + uint8_t a1 = (buf[(i + 1) * 4 + 0] >> 4) << 4; + alpha[i / 2] = (a0 & (0xf0U)) | ((a1 & (0xf0U)) >> 4); + } + + vImage_Buffer destYp; + destYp.data = (void *)(yuva + 0); + destYp.width = width; + destYp.height = height; + destYp.rowBytes = width; + + vImage_Buffer destCbCr; + destCbCr.data = (void *)(yuva + width * height * 1); + destCbCr.width = width; + destCbCr.height = height; + destCbCr.rowBytes = width; + + error = vImageConvert_ARGB8888To420Yp8_CbCr8(&src, &destYp, &destCbCr, &info, NULL, kvImageDoNotTile); + if (error != kvImageNoError) { + return; + } +} + +void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height) { + vImage_YpCbCrPixelRange pixelRange = (vImage_YpCbCrPixelRange){ 0, 128, 255, 255, 255, 0, 255, 0 }; + vImage_YpCbCrToARGB info; + + vImage_Error error; + error = vImageConvert_YpCbCrToARGB_GenerateConversion(kvImage_YpCbCrToARGBMatrix_ITU_R_601_4, &pixelRange, &info, kvImage420Yp8_Cb8_Cr8, kvImageARGB8888, 0); + if (error != kvImageNoError) { + return; + } + + vImage_Buffer srcYp; + srcYp.data = (void *)(yuva + 0); + srcYp.width = width; + srcYp.height = height; + srcYp.rowBytes = width * 1; + + vImage_Buffer srcCbCr; + srcCbCr.data = (void *)(yuva + width * height * 1); + srcCbCr.width = width; + srcCbCr.height = height; + srcCbCr.rowBytes = width * 1; + + vImage_Buffer dest; + dest.data = (void *)argb; + dest.width = width; + dest.height = height; + dest.rowBytes = width * 4; + + error = vImageConvert_420Yp8_CbCr8ToARGB8888(&srcYp, &srcCbCr, &dest, &info, NULL, 0xff, kvImageDoNotTile); + + uint8_t const *alpha = yuva + (width * height * 1 + width * height * 1); + for (int i = 0; i < width * height; i += 2) { + uint8_t a = alpha[i / 2]; + argb[i * 4 + 0] = (a & (0xf0U)); + argb[(i + 1) * 4 + 0] = (a & (0x0fU)) << 4; + } + + error = vImagePremultiplyData_ARGB8888(&dest, &dest, kvImageDoNotTile); + + uint8_t permuteMap[4] = {3, 2, 1, 0}; + error = vImagePermuteChannels_ARGB8888(&dest, &dest, permuteMap, kvImageDoNotTile); + + if (error != kvImageNoError) { + return; + } } diff --git a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj index 9d214e3b27..5bb26b24a5 100644 --- a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj +++ b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj @@ -255,6 +255,26 @@ D0104F2A1F471DA6004E4881 /* InstantImageGalleryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0104F291F471DA6004E4881 /* InstantImageGalleryItem.swift */; }; D0104F2C1F471EEB004E4881 /* InstantPageGalleryFooterContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0104F2B1F471EEB004E4881 /* InstantPageGalleryFooterContentNode.swift */; }; D0105D682182680E007C04A7 /* IsMediaStreamable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0105D672182680E007C04A7 /* IsMediaStreamable.swift */; }; + D010DF1F22C18769009324D4 /* PvrTcEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF0C22C18767009324D4 /* PvrTcEncoder.cpp */; }; + D010DF2022C18769009324D4 /* PvrTcPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF0D22C18767009324D4 /* PvrTcPacket.h */; }; + D010DF2122C18769009324D4 /* MortonTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF0E22C18767009324D4 /* MortonTable.cpp */; }; + D010DF2222C18769009324D4 /* BitScale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF0F22C18767009324D4 /* BitScale.cpp */; }; + D010DF2322C18769009324D4 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF1022C18767009324D4 /* main.cpp */; }; + D010DF2422C18769009324D4 /* AlphaBitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1122C18767009324D4 /* AlphaBitmap.h */; }; + D010DF2522C18769009324D4 /* Interval.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1222C18767009324D4 /* Interval.h */; }; + D010DF2622C18769009324D4 /* PvrTcEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1322C18767009324D4 /* PvrTcEncoder.h */; }; + D010DF2722C18769009324D4 /* Bitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1422C18767009324D4 /* Bitmap.h */; }; + D010DF2822C18769009324D4 /* PvrTcDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF1522C18768009324D4 /* PvrTcDecoder.cpp */; }; + D010DF2922C18769009324D4 /* BitScale.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1622C18768009324D4 /* BitScale.h */; }; + D010DF2A22C18769009324D4 /* PvrTcPacket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF1722C18768009324D4 /* PvrTcPacket.cpp */; }; + D010DF2B22C18769009324D4 /* BitUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1822C18768009324D4 /* BitUtility.h */; }; + D010DF2C22C18769009324D4 /* MortonTable.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1922C18768009324D4 /* MortonTable.h */; }; + D010DF2D22C18769009324D4 /* Point2.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1A22C18768009324D4 /* Point2.h */; }; + D010DF2E22C18769009324D4 /* PvrTcDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1B22C18768009324D4 /* PvrTcDecoder.h */; }; + D010DF2F22C18769009324D4 /* RgbaBitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1C22C18769009324D4 /* RgbaBitmap.h */; }; + D010DF3022C18769009324D4 /* RgbBitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1D22C18769009324D4 /* RgbBitmap.h */; }; + D010DF3122C18769009324D4 /* ColorRgba.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1E22C18769009324D4 /* ColorRgba.h */; }; + D010E17D22C238BC009324D4 /* RLottie.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D010E17C22C238BC009324D4 /* RLottie.framework */; }; D0119CD020CAE75F00895300 /* LegacySecureIdAttachmentMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0119CCF20CAE75F00895300 /* LegacySecureIdAttachmentMenu.swift */; }; D013630C208FA62400EB3653 /* SecureIdDocumentGalleryFooterContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D013630B208FA62400EB3653 /* SecureIdDocumentGalleryFooterContentNode.swift */; }; D0147BA7206E8B4F00E40378 /* SecureIdAuthAcceptNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0147BA6206E8B4F00E40378 /* SecureIdAuthAcceptNode.swift */; }; @@ -1467,6 +1487,26 @@ D0104F2B1F471EEB004E4881 /* InstantPageGalleryFooterContentNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstantPageGalleryFooterContentNode.swift; sourceTree = ""; }; D0105D591D80B957008755D8 /* ChatChannelSubscriberInputPanelNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatChannelSubscriberInputPanelNode.swift; sourceTree = ""; }; D0105D672182680E007C04A7 /* IsMediaStreamable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IsMediaStreamable.swift; sourceTree = ""; }; + D010DF0C22C18767009324D4 /* PvrTcEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PvrTcEncoder.cpp; path = "third-party/etc2/PvrTcEncoder.cpp"; sourceTree = SOURCE_ROOT; }; + D010DF0D22C18767009324D4 /* PvrTcPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PvrTcPacket.h; path = "third-party/etc2/PvrTcPacket.h"; sourceTree = SOURCE_ROOT; }; + D010DF0E22C18767009324D4 /* MortonTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MortonTable.cpp; path = "third-party/etc2/MortonTable.cpp"; sourceTree = SOURCE_ROOT; }; + D010DF0F22C18767009324D4 /* BitScale.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BitScale.cpp; path = "third-party/etc2/BitScale.cpp"; sourceTree = SOURCE_ROOT; }; + D010DF1022C18767009324D4 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = "third-party/etc2/main.cpp"; sourceTree = SOURCE_ROOT; }; + D010DF1122C18767009324D4 /* AlphaBitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AlphaBitmap.h; path = "third-party/etc2/AlphaBitmap.h"; sourceTree = SOURCE_ROOT; }; + D010DF1222C18767009324D4 /* Interval.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Interval.h; path = "third-party/etc2/Interval.h"; sourceTree = SOURCE_ROOT; }; + D010DF1322C18767009324D4 /* PvrTcEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PvrTcEncoder.h; path = "third-party/etc2/PvrTcEncoder.h"; sourceTree = SOURCE_ROOT; }; + D010DF1422C18767009324D4 /* Bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Bitmap.h; path = "third-party/etc2/Bitmap.h"; sourceTree = SOURCE_ROOT; }; + D010DF1522C18768009324D4 /* PvrTcDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PvrTcDecoder.cpp; path = "third-party/etc2/PvrTcDecoder.cpp"; sourceTree = SOURCE_ROOT; }; + D010DF1622C18768009324D4 /* BitScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BitScale.h; path = "third-party/etc2/BitScale.h"; sourceTree = SOURCE_ROOT; }; + D010DF1722C18768009324D4 /* PvrTcPacket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PvrTcPacket.cpp; path = "third-party/etc2/PvrTcPacket.cpp"; sourceTree = SOURCE_ROOT; }; + D010DF1822C18768009324D4 /* BitUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BitUtility.h; path = "third-party/etc2/BitUtility.h"; sourceTree = SOURCE_ROOT; }; + D010DF1922C18768009324D4 /* MortonTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MortonTable.h; path = "third-party/etc2/MortonTable.h"; sourceTree = SOURCE_ROOT; }; + D010DF1A22C18768009324D4 /* Point2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Point2.h; path = "third-party/etc2/Point2.h"; sourceTree = SOURCE_ROOT; }; + D010DF1B22C18768009324D4 /* PvrTcDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PvrTcDecoder.h; path = "third-party/etc2/PvrTcDecoder.h"; sourceTree = SOURCE_ROOT; }; + D010DF1C22C18769009324D4 /* RgbaBitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RgbaBitmap.h; path = "third-party/etc2/RgbaBitmap.h"; sourceTree = SOURCE_ROOT; }; + D010DF1D22C18769009324D4 /* RgbBitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RgbBitmap.h; path = "third-party/etc2/RgbBitmap.h"; sourceTree = SOURCE_ROOT; }; + D010DF1E22C18769009324D4 /* ColorRgba.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ColorRgba.h; path = "third-party/etc2/ColorRgba.h"; sourceTree = SOURCE_ROOT; }; + D010E17C22C238BC009324D4 /* RLottie.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = RLottie.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D0119CCF20CAE75F00895300 /* LegacySecureIdAttachmentMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacySecureIdAttachmentMenu.swift; sourceTree = ""; }; D0127A0C1E6424AC003BFF2E /* ChatPinnedMessageTitlePanelNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatPinnedMessageTitlePanelNode.swift; sourceTree = ""; }; D013630B208FA62400EB3653 /* SecureIdDocumentGalleryFooterContentNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdDocumentGalleryFooterContentNode.swift; sourceTree = ""; }; @@ -2417,6 +2457,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D010E17D22C238BC009324D4 /* RLottie.framework in Frameworks */, D03AE67522B945D30078411C /* BuildConfig.framework in Frameworks */, D03AE67322B9459C0078411C /* HockeySDK.framework in Frameworks */, D02D634A22B85B94006BE519 /* PushKit.framework in Frameworks */, @@ -2825,6 +2866,25 @@ D01590A922BD46690017C33E /* Animation */ = { isa = PBXGroup; children = ( + D010DF1122C18767009324D4 /* AlphaBitmap.h */, + D010DF1422C18767009324D4 /* Bitmap.h */, + D010DF0F22C18767009324D4 /* BitScale.cpp */, + D010DF1622C18768009324D4 /* BitScale.h */, + D010DF1822C18768009324D4 /* BitUtility.h */, + D010DF1E22C18769009324D4 /* ColorRgba.h */, + D010DF1222C18767009324D4 /* Interval.h */, + D010DF1022C18767009324D4 /* main.cpp */, + D010DF0E22C18767009324D4 /* MortonTable.cpp */, + D010DF1922C18768009324D4 /* MortonTable.h */, + D010DF1A22C18768009324D4 /* Point2.h */, + D010DF1522C18768009324D4 /* PvrTcDecoder.cpp */, + D010DF1B22C18768009324D4 /* PvrTcDecoder.h */, + D010DF0C22C18767009324D4 /* PvrTcEncoder.cpp */, + D010DF1322C18767009324D4 /* PvrTcEncoder.h */, + D010DF1722C18768009324D4 /* PvrTcPacket.cpp */, + D010DF0D22C18767009324D4 /* PvrTcPacket.h */, + D010DF1C22C18769009324D4 /* RgbaBitmap.h */, + D010DF1D22C18769009324D4 /* RgbBitmap.h */, D01590B622BDAEBC0017C33E /* BC1Compression.cpp */, D01590B122BDAEBB0017C33E /* BC1Compression.h */, D01590B922BDAEBC0017C33E /* BMPImage.cpp */, @@ -3539,6 +3599,7 @@ D08D45281D5E340200A7428A /* Frameworks */ = { isa = PBXGroup; children = ( + D010E17C22C238BC009324D4 /* RLottie.framework */, D03AE67422B945D30078411C /* BuildConfig.framework */, D03AE67222B9459C0078411C /* HockeySDK.framework */, D02D634922B85B94006BE519 /* PushKit.framework */, @@ -4904,20 +4965,26 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + D010DF2B22C18769009324D4 /* BitUtility.h in Headers */, D0E9BA221F05577700F079A4 /* STPCard.h in Headers */, + D010DF3122C18769009324D4 /* ColorRgba.h in Headers */, D0E9BA591F055A2200F079A4 /* STPWeakStrongMacros.h in Headers */, D0E9BADE1F0574D800F079A4 /* STPBackendAPIAdapter.h in Headers */, + D010DF2922C18769009324D4 /* BitScale.h in Headers */, D0E9BAD11F0573C000F079A4 /* STPToken.h in Headers */, + D010DF2C22C18769009324D4 /* MortonTable.h in Headers */, D01590C222BDAEBC0017C33E /* TypeDefinitions.h in Headers */, D0AE303622B1D3620058D3BC /* TGBridgeAudioDecoder.h in Headers */, D0E9BAE71F0574FF00F079A4 /* STPCustomer.h in Headers */, D0208AD51FA33D14001F0D5F /* RaiseToListenActivator.h in Headers */, D00817DA22B47A14008A895F /* TGPresentationAutoNightPreferences.h in Headers */, D0E9BAE31F0574D800F079A4 /* STPBankAccountParams.h in Headers */, + D010DF3022C18769009324D4 /* RgbBitmap.h in Headers */, D0E9BA361F05585000F079A4 /* STPPhoneNumberValidator.h in Headers */, D0E9BA511F0559DA00F079A4 /* STPImageLibrary.h in Headers */, D0E9BA4C1F0559C700F079A4 /* NSString+Stripe_CardBrands.h in Headers */, D00817E022B47A14008A895F /* UIImage+ImageEffects.h in Headers */, + D010DF2E22C18769009324D4 /* PvrTcDecoder.h in Headers */, D01590BA22BDAEBC0017C33E /* ColorVec.h in Headers */, D0E9BAE11F0574D800F079A4 /* STPBankAccount.h in Headers */, D0E9BACE1F0573AF00F079A4 /* STPBlocks.h in Headers */, @@ -4931,6 +4998,7 @@ D01590AE22BD58AD0017C33E /* YUV.h in Headers */, D008177B22B46B7E008A895F /* TGContactModel.h in Headers */, D0E9BA291F0557A600F079A4 /* STPFormEncodable.h in Headers */, + D010DF2F22C18769009324D4 /* RgbaBitmap.h in Headers */, D0E9BA141F05574500F079A4 /* STPCardValidationState.h in Headers */, D00701A12029F6D0006B9E34 /* TGMimeTypeMap.h in Headers */, D0E9BA461F0559A500F079A4 /* NSDictionary+Stripe.h in Headers */, @@ -4942,13 +5010,18 @@ D0E9BADF1F0574D800F079A4 /* STPDispatchFunctions.h in Headers */, D00817CD22B47A14008A895F /* TGAutoDownloadPreferences.h in Headers */, D0E9BACB1F05738600F079A4 /* STPAPIPostRequest.h in Headers */, + D010DF2722C18769009324D4 /* Bitmap.h in Headers */, + D010DF2422C18769009324D4 /* AlphaBitmap.h in Headers */, D0E9BA561F055A0B00F079A4 /* STPFormTextField.h in Headers */, D01590C122BDAEBC0017C33E /* DDSImage.h in Headers */, D008177C22B46B7E008A895F /* TGItemProviderSignals.h in Headers */, + D010DF2522C18769009324D4 /* Interval.h in Headers */, + D010DF2622C18769009324D4 /* PvrTcEncoder.h in Headers */, D0E9BABE1F05735F00F079A4 /* STPPaymentConfiguration+Private.h in Headers */, D01590BB22BDAEBC0017C33E /* BC1Compression.h in Headers */, D0E9BACA1F05738600F079A4 /* STPAPIClient+Private.h in Headers */, D01590BC22BDAEBC0017C33E /* BMPImage.h in Headers */, + D010DF2D22C18769009324D4 /* Point2.h in Headers */, D0E9BA251F05578900F079A4 /* STPCardBrand.h in Headers */, D0E9BAC81F05738600F079A4 /* STPAPIClient+ApplePay.h in Headers */, D0E9BA451F0559A500F079A4 /* STPAPIResponseDecodable.h in Headers */, @@ -4960,6 +5033,7 @@ D01590C922BE62C40017C33E /* TextureCompression.h in Headers */, D0E9BA191F05574500F079A4 /* STPPaymentCardTextField.h in Headers */, D0E9BA3F1F0558FE00F079A4 /* STPSource.h in Headers */, + D010DF2022C18769009324D4 /* PvrTcPacket.h in Headers */, D008177A22B46B7E008A895F /* TGShareLocationSignals.h in Headers */, D0E9BABC1F05735F00F079A4 /* STPPaymentConfiguration.h in Headers */, D01590BF22BDAEBC0017C33E /* Image.h in Headers */, @@ -5203,6 +5277,7 @@ D093D7DD2062D09A00BC3599 /* SecureIdAuthFormFieldNode.swift in Sources */, 092F36902157AB46001A9F49 /* ItemListCallListItem.swift in Sources */, D0EC6CC61EB9F58800EBF1C3 /* PresenceStrings.swift in Sources */, + D010DF1F22C18769009324D4 /* PvrTcEncoder.cpp in Sources */, D00817D522B47A14008A895F /* ApplicationShortcutItem.swift in Sources */, D077C5C122B59A800097D617 /* ApplicationContext.swift in Sources */, D0EC6CC71EB9F58800EBF1C3 /* PeerNotificationSoundStrings.swift in Sources */, @@ -5344,6 +5419,7 @@ 09CE95042236C6B300A7D2C3 /* CachedInstantPages.swift in Sources */, D0AB269E21D56A12008F6685 /* ChannelPermissionsController.swift in Sources */, D0B69C3920EBB397003632C7 /* ChatMessageInteractiveInstantVideoNode.swift in Sources */, + D010DF2822C18769009324D4 /* PvrTcDecoder.cpp in Sources */, 09F79A0D21C88E8900820234 /* LegacyWebSearchEditor.swift in Sources */, 09F21565225C83E100AEDF6D /* ChatListStatusNode.swift in Sources */, D056CD701FF147B000880D28 /* IconButtonNode.swift in Sources */, @@ -5644,6 +5720,7 @@ 09D304152173C0E900C00567 /* WatchManager.swift in Sources */, 9F06830921A404AB001D8EDB /* NotificationExceptionControllerNode.swift in Sources */, D039FB1921711B5D00BD1BAD /* PlatformVideoContent.swift in Sources */, + D010DF2122C18769009324D4 /* MortonTable.cpp in Sources */, D0CAD8FD20AE467D00ACD96E /* PeerChannelMemberCategoriesContextsManager.swift in Sources */, D035734B22B5CCCA00F0920D /* LegacyBuffer.swift in Sources */, D0430B001FF4570500A35ADD /* WebController.swift in Sources */, @@ -5689,6 +5766,7 @@ D0EC6DA91EB9F58900EBF1C3 /* ChatPresentationInterfaceState.swift in Sources */, D0EC6DAA1EB9F58900EBF1C3 /* ChatPanelInterfaceInteraction.swift in Sources */, D00FF2091F4E2414006FA332 /* InstantPageSettingsNode.swift in Sources */, + D010DF2A22C18769009324D4 /* PvrTcPacket.cpp in Sources */, D0BE3037206139F500FBE6D8 /* ImageCompression.swift in Sources */, 09AE3823214C110900850BFD /* LegacySecureIdScanController.swift in Sources */, D0EC6DAB1EB9F58900EBF1C3 /* ChatInterfaceStateAccessoryPanels.swift in Sources */, @@ -5785,6 +5863,7 @@ D0EC6DD81EB9F58900EBF1C3 /* VerticalListContextResultsChatInputPanelButtonItem.swift in Sources */, D04281F4200E5AB0009DDE36 /* ChatRecentActionsController.swift in Sources */, 09FE756D2153F5F900A3120F /* CallRouteActionSheetItem.swift in Sources */, + D010DF2222C18769009324D4 /* BitScale.cpp in Sources */, D0BFAE4E20AB1D7B00793CF2 /* DisabledContextResultsChatInputContextPanelNode.swift in Sources */, D064EF871F69A06F00AC0398 /* MessageContentKind.swift in Sources */, D020A9DA1FEAE675008C66F7 /* OverlayPlayerController.swift in Sources */, @@ -6047,6 +6126,7 @@ D00BDA1F1EE5B69200C64C5E /* ChannelAdminController.swift in Sources */, D0EC6E501EB9F58900EBF1C3 /* ChannelAdminsController.swift in Sources */, D0EC6E511EB9F58900EBF1C3 /* ChannelBlacklistController.swift in Sources */, + D010DF2322C18769009324D4 /* main.cpp in Sources */, D0EC6E521EB9F58900EBF1C3 /* ChannelInfoController.swift in Sources */, D0EC6E531EB9F58900EBF1C3 /* ChannelMembersController.swift in Sources */, D02B676320800A00001A864A /* PaneSearchBarPlaceholderItem.swift in Sources */, @@ -6894,7 +6974,7 @@ PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_INSTALL_OBJC_HEADER = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 4.0; USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/third-party/FFmpeg-iOS/include"; }; diff --git a/submodules/TelegramUI/third-party/bc1/BC1Compression.cpp b/submodules/TelegramUI/third-party/bc1/BC1Compression.cpp index 5f59ed8c54..1b71328b29 100644 --- a/submodules/TelegramUI/third-party/bc1/BC1Compression.cpp +++ b/submodules/TelegramUI/third-party/bc1/BC1Compression.cpp @@ -52,7 +52,7 @@ namespace DTX1CompressorDecompressor { unsigned int index = (height - 1 - row) * width + col; // image is reversed in rows (upside down), so row = 0 is the bottom of the image std::memcpy(&pixelData[index].bgra, dtaPtr, 3); - dtaPtr += 3; + dtaPtr += 4; } } @@ -106,7 +106,8 @@ namespace DTX1CompressorDecompressor } // copy pixel data to the actual bmp image - unsigned char* bmpImgData = new unsigned char[3 * width * height]; + unsigned char* bmpImgData = new unsigned char[4 * width * height]; + memset(bmpImgData, 0xff, 4 * width * height); unsigned char* bmpDataPtr = bmpImgData; for (unsigned int row = 0; row < height; ++row) @@ -115,7 +116,7 @@ namespace DTX1CompressorDecompressor { unsigned int index = (height - 1 - row) * width + col; // image is reversed in rows (upside down), so row = 0 is the bottom of the image std::memcpy(bmpDataPtr, &pixelData[index].bgra, 3); - bmpDataPtr += 3; + bmpDataPtr += 4; } } diff --git a/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp b/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp index 452ba3f0af..f118086bbf 100644 --- a/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp +++ b/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp @@ -1,13 +1,36 @@ #import "TextureCompression.h" #import "BC1Compression.h" +#import "PvrTcEncoder.h" +#import "PvrTcDecoder.h" +#import "RgbaBitmap.h" void compressRGBAToBC1(uint8_t const * _Nonnull argb, int width, int height, uint8_t * _Nonnull bc1) { - DTX1CompressorDecompressor::BC1Compression compression; - DTX1CompressorDecompressor::BMPImage image; - image.InitWithData((unsigned char *)argb, width, height); - image.m_ownData = false; - DTX1CompressorDecompressor::BC1DDSImage ddsImage; - compression.Compress(image, ddsImage); - int numBlocks = width * height / (4 * 4); - memcpy(bc1, ddsImage.GetData(), numBlocks * 8); + Javelin::RgbaBitmap bitmap(width, height); + uint8_t *data = (uint8_t *)bitmap.GetData(); + for (int i = 0; i < width * height; i++) { + data[i * 4 + 0] = argb[i * 4 + 0]; + data[i * 4 + 1] = argb[i * 4 + 1]; + data[i * 4 + 2] = argb[i * 4 + 2]; + data[i * 4 + 3] = argb[i * 4 + 3]; + } + Javelin::PvrTcEncoder::EncodeRgb4Bpp(bc1, bitmap); +} + +void decompressBC1ToRGBA(uint8_t const * _Nonnull bc1, int width, int height, uint8_t * _Nonnull argb) { + uint8_t *data = (uint8_t *)malloc(width * height * 3); + Javelin::PvrTcDecoder::DecodeRgb4Bpp((Javelin::ColorRgba *)data, Javelin::Point2(width, height), bc1); + for (int i = 0; i < width * height; i++) { + uint8_t r = data[i * 3 + 0]; + uint8_t g = data[i * 3 + 1]; + uint8_t b = data[i * 3 + 2]; + argb[i * 4 + 3] = 255; + argb[i * 4 + 2] = b; + argb[i * 4 + 1] = g; + argb[i * 4 + 0] = r; + } + free(data); +} + +void compressRGBAToETC2(uint8_t const * _Nonnull argb, int width, int height, uint8_t * _Nonnull etc2) { + } diff --git a/submodules/TelegramUI/third-party/bc1/TextureCompression.h b/submodules/TelegramUI/third-party/bc1/TextureCompression.h index 29b5c6f932..b013ac17d2 100644 --- a/submodules/TelegramUI/third-party/bc1/TextureCompression.h +++ b/submodules/TelegramUI/third-party/bc1/TextureCompression.h @@ -5,6 +5,8 @@ extern "C" { #endif void compressRGBAToBC1(uint8_t const * _Nonnull argb, int width, int height, uint8_t * _Nonnull bc1); +void decompressBC1ToRGBA(uint8_t const * _Nonnull bc1, int width, int height, uint8_t * _Nonnull argb); +void compressRGBAToETC2(uint8_t const * _Nonnull argb, int width, int height, uint8_t * _Nonnull etc2); #ifdef __cplusplus } From 933dc95261e67d95b8ef6abca3c38eab32515395 Mon Sep 17 00:00:00 2001 From: Peter <> Date: Tue, 25 Jun 2019 23:34:24 +0300 Subject: [PATCH 10/26] Update YUV --- buildbox/build-telegram.sh | 3 +- buildbox/guest-build-telegram.sh | 2 +- .../ChatMediaInputStickerGridItem.swift | 1 + .../ChatMessageAnimatedStickerItemNode.swift | 3 +- submodules/TelegramUI/TelegramUI/YUV.m | 4 +- .../project.pbxproj | 78 +------------------ .../third-party/bc1/TextureCompression.cpp | 12 +-- 7 files changed, 12 insertions(+), 91 deletions(-) diff --git a/buildbox/build-telegram.sh b/buildbox/build-telegram.sh index ee74b7a554..580e04a625 100644 --- a/buildbox/build-telegram.sh +++ b/buildbox/build-telegram.sh @@ -26,6 +26,7 @@ else fi COMMIT_ID=$(git rev-parse HEAD) +COMMIT_AUTHOR=$(git log -1 --pretty=format:'%an') if [ -z "$2" ]; then COMMIT_COUNT=$(git rev-list --count HEAD) COMMIT_COUNT="$(($COMMIT_COUNT+1000))" @@ -96,7 +97,7 @@ else fi scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/guest-build-telegram.sh" "$BUILDBOX_DIR/transient-data/source.tar" telegram@"$VM_IP": -ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null telegram@"$VM_IP" -o ServerAliveInterval=60 -t "export TELEGRAM_BUILD_APPSTORE_PASSWORD=\"$TELEGRAM_BUILD_APPSTORE_PASSWORD\"; export TELEGRAM_BUILD_APPSTORE_TEAM_NAME=\"$TELEGRAM_BUILD_APPSTORE_TEAM_NAME\"; export BUILD_NUMBER=\"$BUILD_NUMBER\"; export COMMIT_ID=\"$COMMIT_ID\"; bash -l guest-build-telegram.sh $BUILD_CONFIGURATION" || true +ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null telegram@"$VM_IP" -o ServerAliveInterval=60 -t "export TELEGRAM_BUILD_APPSTORE_PASSWORD=\"$TELEGRAM_BUILD_APPSTORE_PASSWORD\"; export TELEGRAM_BUILD_APPSTORE_TEAM_NAME=\"$TELEGRAM_BUILD_APPSTORE_TEAM_NAME\"; export BUILD_NUMBER=\"$BUILD_NUMBER\"; export COMMIT_ID=\"$COMMIT_ID\"; export COMMIT_AUTHOR=\"$COMMIT_AUTHOR\"; bash -l guest-build-telegram.sh $BUILD_CONFIGURATION" || true if [ "$BUILD_CONFIGURATION" == "appstore" ]; then ARCHIVE_PATH="$HOME/telegram-builds-archive" diff --git a/buildbox/guest-build-telegram.sh b/buildbox/guest-build-telegram.sh index c08c7da671..1cf45bbc71 100644 --- a/buildbox/guest-build-telegram.sh +++ b/buildbox/guest-build-telegram.sh @@ -78,5 +78,5 @@ else tar -xf "source.tar" cd "$SOURCE_PATH" - FASTLANE_PASSWORD="$FASTLANE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$FASTLANE_ITC_TEAM_NAME" fastlane "$FASTLANE_BUILD_CONFIGURATION" build_number:"$BUILD_NUMBER" commit_hash:"$COMMIT_ID" + FASTLANE_PASSWORD="$FASTLANE_PASSWORD" FASTLANE_ITC_TEAM_NAME="$FASTLANE_ITC_TEAM_NAME" fastlane "$FASTLANE_BUILD_CONFIGURATION" build_number:"$BUILD_NUMBER" commit_hash:"$COMMIT_ID" commit_author:"$COMMIT_AUTHOR" fi diff --git a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift index 9fd8b27fbb..11f27eada4 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift @@ -221,6 +221,7 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { if item.stickerItem.file.isAnimatedSticker { if self.animationNode == nil { let animationNode = StickerAnimationNode() + animationNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:)))) self.animationNode = animationNode self.addSubnode(animationNode) } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift index ac14e6d0d9..da213e8467 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift @@ -626,8 +626,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } if let item = self.item, self.imageNode.frame.contains(location) { - //self.animationNode.play() - //let _ = item.controllerInteraction.openMessage(item.message, .default) + let _ = item.controllerInteraction.openMessage(item.message, .default) return } diff --git a/submodules/TelegramUI/TelegramUI/YUV.m b/submodules/TelegramUI/TelegramUI/YUV.m index 14de0384e6..103dbea0cd 100644 --- a/submodules/TelegramUI/TelegramUI/YUV.m +++ b/submodules/TelegramUI/TelegramUI/YUV.m @@ -6,7 +6,7 @@ void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height) vImage_ARGBToYpCbCr info; vImage_Error error; - error = vImageConvert_ARGBToYpCbCr_GenerateConversion(kvImage_ARGBToYpCbCrMatrix_ITU_R_601_4, &pixelRange, &info, kvImageARGB8888, kvImage420Yp8_Cb8_Cr8, 0); + error = vImageConvert_ARGBToYpCbCr_GenerateConversion(kvImage_ARGBToYpCbCrMatrix_ITU_R_709_2, &pixelRange, &info, kvImageARGB8888, kvImage420Yp8_Cb8_Cr8, 0); if (error != kvImageNoError) { return; } @@ -53,7 +53,7 @@ void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height) vImage_YpCbCrToARGB info; vImage_Error error; - error = vImageConvert_YpCbCrToARGB_GenerateConversion(kvImage_YpCbCrToARGBMatrix_ITU_R_601_4, &pixelRange, &info, kvImage420Yp8_Cb8_Cr8, kvImageARGB8888, 0); + error = vImageConvert_YpCbCrToARGB_GenerateConversion(kvImage_YpCbCrToARGBMatrix_ITU_R_709_2, &pixelRange, &info, kvImage420Yp8_Cb8_Cr8, kvImageARGB8888, 0); if (error != kvImageNoError) { return; } diff --git a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj index 5bb26b24a5..dafe61f683 100644 --- a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj +++ b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj @@ -255,25 +255,6 @@ D0104F2A1F471DA6004E4881 /* InstantImageGalleryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0104F291F471DA6004E4881 /* InstantImageGalleryItem.swift */; }; D0104F2C1F471EEB004E4881 /* InstantPageGalleryFooterContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0104F2B1F471EEB004E4881 /* InstantPageGalleryFooterContentNode.swift */; }; D0105D682182680E007C04A7 /* IsMediaStreamable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0105D672182680E007C04A7 /* IsMediaStreamable.swift */; }; - D010DF1F22C18769009324D4 /* PvrTcEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF0C22C18767009324D4 /* PvrTcEncoder.cpp */; }; - D010DF2022C18769009324D4 /* PvrTcPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF0D22C18767009324D4 /* PvrTcPacket.h */; }; - D010DF2122C18769009324D4 /* MortonTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF0E22C18767009324D4 /* MortonTable.cpp */; }; - D010DF2222C18769009324D4 /* BitScale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF0F22C18767009324D4 /* BitScale.cpp */; }; - D010DF2322C18769009324D4 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF1022C18767009324D4 /* main.cpp */; }; - D010DF2422C18769009324D4 /* AlphaBitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1122C18767009324D4 /* AlphaBitmap.h */; }; - D010DF2522C18769009324D4 /* Interval.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1222C18767009324D4 /* Interval.h */; }; - D010DF2622C18769009324D4 /* PvrTcEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1322C18767009324D4 /* PvrTcEncoder.h */; }; - D010DF2722C18769009324D4 /* Bitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1422C18767009324D4 /* Bitmap.h */; }; - D010DF2822C18769009324D4 /* PvrTcDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF1522C18768009324D4 /* PvrTcDecoder.cpp */; }; - D010DF2922C18769009324D4 /* BitScale.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1622C18768009324D4 /* BitScale.h */; }; - D010DF2A22C18769009324D4 /* PvrTcPacket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D010DF1722C18768009324D4 /* PvrTcPacket.cpp */; }; - D010DF2B22C18769009324D4 /* BitUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1822C18768009324D4 /* BitUtility.h */; }; - D010DF2C22C18769009324D4 /* MortonTable.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1922C18768009324D4 /* MortonTable.h */; }; - D010DF2D22C18769009324D4 /* Point2.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1A22C18768009324D4 /* Point2.h */; }; - D010DF2E22C18769009324D4 /* PvrTcDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1B22C18768009324D4 /* PvrTcDecoder.h */; }; - D010DF2F22C18769009324D4 /* RgbaBitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1C22C18769009324D4 /* RgbaBitmap.h */; }; - D010DF3022C18769009324D4 /* RgbBitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1D22C18769009324D4 /* RgbBitmap.h */; }; - D010DF3122C18769009324D4 /* ColorRgba.h in Headers */ = {isa = PBXBuildFile; fileRef = D010DF1E22C18769009324D4 /* ColorRgba.h */; }; D010E17D22C238BC009324D4 /* RLottie.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D010E17C22C238BC009324D4 /* RLottie.framework */; }; D0119CD020CAE75F00895300 /* LegacySecureIdAttachmentMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0119CCF20CAE75F00895300 /* LegacySecureIdAttachmentMenu.swift */; }; D013630C208FA62400EB3653 /* SecureIdDocumentGalleryFooterContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D013630B208FA62400EB3653 /* SecureIdDocumentGalleryFooterContentNode.swift */; }; @@ -1487,25 +1468,6 @@ D0104F2B1F471EEB004E4881 /* InstantPageGalleryFooterContentNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstantPageGalleryFooterContentNode.swift; sourceTree = ""; }; D0105D591D80B957008755D8 /* ChatChannelSubscriberInputPanelNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatChannelSubscriberInputPanelNode.swift; sourceTree = ""; }; D0105D672182680E007C04A7 /* IsMediaStreamable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IsMediaStreamable.swift; sourceTree = ""; }; - D010DF0C22C18767009324D4 /* PvrTcEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PvrTcEncoder.cpp; path = "third-party/etc2/PvrTcEncoder.cpp"; sourceTree = SOURCE_ROOT; }; - D010DF0D22C18767009324D4 /* PvrTcPacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PvrTcPacket.h; path = "third-party/etc2/PvrTcPacket.h"; sourceTree = SOURCE_ROOT; }; - D010DF0E22C18767009324D4 /* MortonTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MortonTable.cpp; path = "third-party/etc2/MortonTable.cpp"; sourceTree = SOURCE_ROOT; }; - D010DF0F22C18767009324D4 /* BitScale.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BitScale.cpp; path = "third-party/etc2/BitScale.cpp"; sourceTree = SOURCE_ROOT; }; - D010DF1022C18767009324D4 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = "third-party/etc2/main.cpp"; sourceTree = SOURCE_ROOT; }; - D010DF1122C18767009324D4 /* AlphaBitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AlphaBitmap.h; path = "third-party/etc2/AlphaBitmap.h"; sourceTree = SOURCE_ROOT; }; - D010DF1222C18767009324D4 /* Interval.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Interval.h; path = "third-party/etc2/Interval.h"; sourceTree = SOURCE_ROOT; }; - D010DF1322C18767009324D4 /* PvrTcEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PvrTcEncoder.h; path = "third-party/etc2/PvrTcEncoder.h"; sourceTree = SOURCE_ROOT; }; - D010DF1422C18767009324D4 /* Bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Bitmap.h; path = "third-party/etc2/Bitmap.h"; sourceTree = SOURCE_ROOT; }; - D010DF1522C18768009324D4 /* PvrTcDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PvrTcDecoder.cpp; path = "third-party/etc2/PvrTcDecoder.cpp"; sourceTree = SOURCE_ROOT; }; - D010DF1622C18768009324D4 /* BitScale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BitScale.h; path = "third-party/etc2/BitScale.h"; sourceTree = SOURCE_ROOT; }; - D010DF1722C18768009324D4 /* PvrTcPacket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PvrTcPacket.cpp; path = "third-party/etc2/PvrTcPacket.cpp"; sourceTree = SOURCE_ROOT; }; - D010DF1822C18768009324D4 /* BitUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BitUtility.h; path = "third-party/etc2/BitUtility.h"; sourceTree = SOURCE_ROOT; }; - D010DF1922C18768009324D4 /* MortonTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MortonTable.h; path = "third-party/etc2/MortonTable.h"; sourceTree = SOURCE_ROOT; }; - D010DF1A22C18768009324D4 /* Point2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Point2.h; path = "third-party/etc2/Point2.h"; sourceTree = SOURCE_ROOT; }; - D010DF1B22C18768009324D4 /* PvrTcDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PvrTcDecoder.h; path = "third-party/etc2/PvrTcDecoder.h"; sourceTree = SOURCE_ROOT; }; - D010DF1C22C18769009324D4 /* RgbaBitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RgbaBitmap.h; path = "third-party/etc2/RgbaBitmap.h"; sourceTree = SOURCE_ROOT; }; - D010DF1D22C18769009324D4 /* RgbBitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RgbBitmap.h; path = "third-party/etc2/RgbBitmap.h"; sourceTree = SOURCE_ROOT; }; - D010DF1E22C18769009324D4 /* ColorRgba.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ColorRgba.h; path = "third-party/etc2/ColorRgba.h"; sourceTree = SOURCE_ROOT; }; D010E17C22C238BC009324D4 /* RLottie.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = RLottie.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D0119CCF20CAE75F00895300 /* LegacySecureIdAttachmentMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacySecureIdAttachmentMenu.swift; sourceTree = ""; }; D0127A0C1E6424AC003BFF2E /* ChatPinnedMessageTitlePanelNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatPinnedMessageTitlePanelNode.swift; sourceTree = ""; }; @@ -2866,25 +2828,6 @@ D01590A922BD46690017C33E /* Animation */ = { isa = PBXGroup; children = ( - D010DF1122C18767009324D4 /* AlphaBitmap.h */, - D010DF1422C18767009324D4 /* Bitmap.h */, - D010DF0F22C18767009324D4 /* BitScale.cpp */, - D010DF1622C18768009324D4 /* BitScale.h */, - D010DF1822C18768009324D4 /* BitUtility.h */, - D010DF1E22C18769009324D4 /* ColorRgba.h */, - D010DF1222C18767009324D4 /* Interval.h */, - D010DF1022C18767009324D4 /* main.cpp */, - D010DF0E22C18767009324D4 /* MortonTable.cpp */, - D010DF1922C18768009324D4 /* MortonTable.h */, - D010DF1A22C18768009324D4 /* Point2.h */, - D010DF1522C18768009324D4 /* PvrTcDecoder.cpp */, - D010DF1B22C18768009324D4 /* PvrTcDecoder.h */, - D010DF0C22C18767009324D4 /* PvrTcEncoder.cpp */, - D010DF1322C18767009324D4 /* PvrTcEncoder.h */, - D010DF1722C18768009324D4 /* PvrTcPacket.cpp */, - D010DF0D22C18767009324D4 /* PvrTcPacket.h */, - D010DF1C22C18769009324D4 /* RgbaBitmap.h */, - D010DF1D22C18769009324D4 /* RgbBitmap.h */, D01590B622BDAEBC0017C33E /* BC1Compression.cpp */, D01590B122BDAEBB0017C33E /* BC1Compression.h */, D01590B922BDAEBC0017C33E /* BMPImage.cpp */, @@ -4965,26 +4908,20 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - D010DF2B22C18769009324D4 /* BitUtility.h in Headers */, D0E9BA221F05577700F079A4 /* STPCard.h in Headers */, - D010DF3122C18769009324D4 /* ColorRgba.h in Headers */, D0E9BA591F055A2200F079A4 /* STPWeakStrongMacros.h in Headers */, D0E9BADE1F0574D800F079A4 /* STPBackendAPIAdapter.h in Headers */, - D010DF2922C18769009324D4 /* BitScale.h in Headers */, D0E9BAD11F0573C000F079A4 /* STPToken.h in Headers */, - D010DF2C22C18769009324D4 /* MortonTable.h in Headers */, D01590C222BDAEBC0017C33E /* TypeDefinitions.h in Headers */, D0AE303622B1D3620058D3BC /* TGBridgeAudioDecoder.h in Headers */, D0E9BAE71F0574FF00F079A4 /* STPCustomer.h in Headers */, D0208AD51FA33D14001F0D5F /* RaiseToListenActivator.h in Headers */, D00817DA22B47A14008A895F /* TGPresentationAutoNightPreferences.h in Headers */, D0E9BAE31F0574D800F079A4 /* STPBankAccountParams.h in Headers */, - D010DF3022C18769009324D4 /* RgbBitmap.h in Headers */, D0E9BA361F05585000F079A4 /* STPPhoneNumberValidator.h in Headers */, D0E9BA511F0559DA00F079A4 /* STPImageLibrary.h in Headers */, D0E9BA4C1F0559C700F079A4 /* NSString+Stripe_CardBrands.h in Headers */, D00817E022B47A14008A895F /* UIImage+ImageEffects.h in Headers */, - D010DF2E22C18769009324D4 /* PvrTcDecoder.h in Headers */, D01590BA22BDAEBC0017C33E /* ColorVec.h in Headers */, D0E9BAE11F0574D800F079A4 /* STPBankAccount.h in Headers */, D0E9BACE1F0573AF00F079A4 /* STPBlocks.h in Headers */, @@ -4998,7 +4935,6 @@ D01590AE22BD58AD0017C33E /* YUV.h in Headers */, D008177B22B46B7E008A895F /* TGContactModel.h in Headers */, D0E9BA291F0557A600F079A4 /* STPFormEncodable.h in Headers */, - D010DF2F22C18769009324D4 /* RgbaBitmap.h in Headers */, D0E9BA141F05574500F079A4 /* STPCardValidationState.h in Headers */, D00701A12029F6D0006B9E34 /* TGMimeTypeMap.h in Headers */, D0E9BA461F0559A500F079A4 /* NSDictionary+Stripe.h in Headers */, @@ -5010,18 +4946,13 @@ D0E9BADF1F0574D800F079A4 /* STPDispatchFunctions.h in Headers */, D00817CD22B47A14008A895F /* TGAutoDownloadPreferences.h in Headers */, D0E9BACB1F05738600F079A4 /* STPAPIPostRequest.h in Headers */, - D010DF2722C18769009324D4 /* Bitmap.h in Headers */, - D010DF2422C18769009324D4 /* AlphaBitmap.h in Headers */, D0E9BA561F055A0B00F079A4 /* STPFormTextField.h in Headers */, D01590C122BDAEBC0017C33E /* DDSImage.h in Headers */, D008177C22B46B7E008A895F /* TGItemProviderSignals.h in Headers */, - D010DF2522C18769009324D4 /* Interval.h in Headers */, - D010DF2622C18769009324D4 /* PvrTcEncoder.h in Headers */, D0E9BABE1F05735F00F079A4 /* STPPaymentConfiguration+Private.h in Headers */, D01590BB22BDAEBC0017C33E /* BC1Compression.h in Headers */, D0E9BACA1F05738600F079A4 /* STPAPIClient+Private.h in Headers */, D01590BC22BDAEBC0017C33E /* BMPImage.h in Headers */, - D010DF2D22C18769009324D4 /* Point2.h in Headers */, D0E9BA251F05578900F079A4 /* STPCardBrand.h in Headers */, D0E9BAC81F05738600F079A4 /* STPAPIClient+ApplePay.h in Headers */, D0E9BA451F0559A500F079A4 /* STPAPIResponseDecodable.h in Headers */, @@ -5033,7 +4964,6 @@ D01590C922BE62C40017C33E /* TextureCompression.h in Headers */, D0E9BA191F05574500F079A4 /* STPPaymentCardTextField.h in Headers */, D0E9BA3F1F0558FE00F079A4 /* STPSource.h in Headers */, - D010DF2022C18769009324D4 /* PvrTcPacket.h in Headers */, D008177A22B46B7E008A895F /* TGShareLocationSignals.h in Headers */, D0E9BABC1F05735F00F079A4 /* STPPaymentConfiguration.h in Headers */, D01590BF22BDAEBC0017C33E /* Image.h in Headers */, @@ -5277,7 +5207,6 @@ D093D7DD2062D09A00BC3599 /* SecureIdAuthFormFieldNode.swift in Sources */, 092F36902157AB46001A9F49 /* ItemListCallListItem.swift in Sources */, D0EC6CC61EB9F58800EBF1C3 /* PresenceStrings.swift in Sources */, - D010DF1F22C18769009324D4 /* PvrTcEncoder.cpp in Sources */, D00817D522B47A14008A895F /* ApplicationShortcutItem.swift in Sources */, D077C5C122B59A800097D617 /* ApplicationContext.swift in Sources */, D0EC6CC71EB9F58800EBF1C3 /* PeerNotificationSoundStrings.swift in Sources */, @@ -5419,7 +5348,6 @@ 09CE95042236C6B300A7D2C3 /* CachedInstantPages.swift in Sources */, D0AB269E21D56A12008F6685 /* ChannelPermissionsController.swift in Sources */, D0B69C3920EBB397003632C7 /* ChatMessageInteractiveInstantVideoNode.swift in Sources */, - D010DF2822C18769009324D4 /* PvrTcDecoder.cpp in Sources */, 09F79A0D21C88E8900820234 /* LegacyWebSearchEditor.swift in Sources */, 09F21565225C83E100AEDF6D /* ChatListStatusNode.swift in Sources */, D056CD701FF147B000880D28 /* IconButtonNode.swift in Sources */, @@ -5720,7 +5648,6 @@ 09D304152173C0E900C00567 /* WatchManager.swift in Sources */, 9F06830921A404AB001D8EDB /* NotificationExceptionControllerNode.swift in Sources */, D039FB1921711B5D00BD1BAD /* PlatformVideoContent.swift in Sources */, - D010DF2122C18769009324D4 /* MortonTable.cpp in Sources */, D0CAD8FD20AE467D00ACD96E /* PeerChannelMemberCategoriesContextsManager.swift in Sources */, D035734B22B5CCCA00F0920D /* LegacyBuffer.swift in Sources */, D0430B001FF4570500A35ADD /* WebController.swift in Sources */, @@ -5766,7 +5693,6 @@ D0EC6DA91EB9F58900EBF1C3 /* ChatPresentationInterfaceState.swift in Sources */, D0EC6DAA1EB9F58900EBF1C3 /* ChatPanelInterfaceInteraction.swift in Sources */, D00FF2091F4E2414006FA332 /* InstantPageSettingsNode.swift in Sources */, - D010DF2A22C18769009324D4 /* PvrTcPacket.cpp in Sources */, D0BE3037206139F500FBE6D8 /* ImageCompression.swift in Sources */, 09AE3823214C110900850BFD /* LegacySecureIdScanController.swift in Sources */, D0EC6DAB1EB9F58900EBF1C3 /* ChatInterfaceStateAccessoryPanels.swift in Sources */, @@ -5863,7 +5789,6 @@ D0EC6DD81EB9F58900EBF1C3 /* VerticalListContextResultsChatInputPanelButtonItem.swift in Sources */, D04281F4200E5AB0009DDE36 /* ChatRecentActionsController.swift in Sources */, 09FE756D2153F5F900A3120F /* CallRouteActionSheetItem.swift in Sources */, - D010DF2222C18769009324D4 /* BitScale.cpp in Sources */, D0BFAE4E20AB1D7B00793CF2 /* DisabledContextResultsChatInputContextPanelNode.swift in Sources */, D064EF871F69A06F00AC0398 /* MessageContentKind.swift in Sources */, D020A9DA1FEAE675008C66F7 /* OverlayPlayerController.swift in Sources */, @@ -6126,7 +6051,6 @@ D00BDA1F1EE5B69200C64C5E /* ChannelAdminController.swift in Sources */, D0EC6E501EB9F58900EBF1C3 /* ChannelAdminsController.swift in Sources */, D0EC6E511EB9F58900EBF1C3 /* ChannelBlacklistController.swift in Sources */, - D010DF2322C18769009324D4 /* main.cpp in Sources */, D0EC6E521EB9F58900EBF1C3 /* ChannelInfoController.swift in Sources */, D0EC6E531EB9F58900EBF1C3 /* ChannelMembersController.swift in Sources */, D02B676320800A00001A864A /* PaneSearchBarPlaceholderItem.swift in Sources */, @@ -6974,7 +6898,7 @@ PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_INSTALL_OBJC_HEADER = YES; - SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/third-party/FFmpeg-iOS/include"; }; diff --git a/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp b/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp index f118086bbf..8aed619664 100644 --- a/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp +++ b/submodules/TelegramUI/third-party/bc1/TextureCompression.cpp @@ -1,11 +1,7 @@ #import "TextureCompression.h" -#import "BC1Compression.h" -#import "PvrTcEncoder.h" -#import "PvrTcDecoder.h" -#import "RgbaBitmap.h" void compressRGBAToBC1(uint8_t const * _Nonnull argb, int width, int height, uint8_t * _Nonnull bc1) { - Javelin::RgbaBitmap bitmap(width, height); + /*Javelin::RgbaBitmap bitmap(width, height); uint8_t *data = (uint8_t *)bitmap.GetData(); for (int i = 0; i < width * height; i++) { data[i * 4 + 0] = argb[i * 4 + 0]; @@ -13,11 +9,11 @@ void compressRGBAToBC1(uint8_t const * _Nonnull argb, int width, int height, uin data[i * 4 + 2] = argb[i * 4 + 2]; data[i * 4 + 3] = argb[i * 4 + 3]; } - Javelin::PvrTcEncoder::EncodeRgb4Bpp(bc1, bitmap); + Javelin::PvrTcEncoder::EncodeRgb4Bpp(bc1, bitmap);*/ } void decompressBC1ToRGBA(uint8_t const * _Nonnull bc1, int width, int height, uint8_t * _Nonnull argb) { - uint8_t *data = (uint8_t *)malloc(width * height * 3); + /*uint8_t *data = (uint8_t *)malloc(width * height * 3); Javelin::PvrTcDecoder::DecodeRgb4Bpp((Javelin::ColorRgba *)data, Javelin::Point2(width, height), bc1); for (int i = 0; i < width * height; i++) { uint8_t r = data[i * 3 + 0]; @@ -28,7 +24,7 @@ void decompressBC1ToRGBA(uint8_t const * _Nonnull bc1, int width, int height, ui argb[i * 4 + 1] = g; argb[i * 4 + 0] = r; } - free(data); + free(data);*/ } void compressRGBAToETC2(uint8_t const * _Nonnull argb, int width, int height, uint8_t * _Nonnull etc2) { From f50c7ddb2683afb56a85341738fa32171117af88 Mon Sep 17 00:00:00 2001 From: Peter <> Date: Tue, 25 Jun 2019 23:59:11 +0300 Subject: [PATCH 11/26] Fix workspace configuration --- .../contents.xcworkspacedata | 2 +- .../RLottie_Xcode.xcodeproj/project.pbxproj | 251 +++++++++++++++--- 2 files changed, 214 insertions(+), 39 deletions(-) diff --git a/Telegram-iOS.xcworkspace/contents.xcworkspacedata b/Telegram-iOS.xcworkspace/contents.xcworkspacedata index cad6be2ce4..da55a164a5 100644 --- a/Telegram-iOS.xcworkspace/contents.xcworkspacedata +++ b/Telegram-iOS.xcworkspace/contents.xcworkspacedata @@ -2,7 +2,7 @@ + location = "group:submodules/RLottie/RLottie_Xcode.xcodeproj"> diff --git a/submodules/RLottie/RLottie_Xcode.xcodeproj/project.pbxproj b/submodules/RLottie/RLottie_Xcode.xcodeproj/project.pbxproj index 099862aed2..81d0c5f528 100644 --- a/submodules/RLottie/RLottie_Xcode.xcodeproj/project.pbxproj +++ b/submodules/RLottie/RLottie_Xcode.xcodeproj/project.pbxproj @@ -677,7 +677,178 @@ /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ - D010DF4222C225E4009324D4 /* DebugHockeyapp */ = { + D010DF4222C225E4009324D4 /* DebugAppStoreLLC */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = DebugAppStoreLLC; + }; + D010DF4322C225E4009324D4 /* ReleaseAppStoreLLC */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = ReleaseAppStoreLLC; + }; + D010DF4522C225E4009324D4 /* DebugAppStoreLLC */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + PRODUCT_BUNDLE_IDENTIFIER = org.telegram.RLottie; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugAppStoreLLC; + }; + D010DF4622C225E4009324D4 /* ReleaseAppStoreLLC */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + PRODUCT_BUNDLE_IDENTIFIER = org.telegram.RLottie; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = ReleaseAppStoreLLC; + }; + D0AF792F22C2C26A00CECCB8 /* DebugHockeyapp */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -739,7 +910,34 @@ }; name = DebugHockeyapp; }; - D010DF4322C225E4009324D4 /* Release */ = { + D0AF793022C2C26A00CECCB8 /* DebugHockeyapp */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = s; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + PRODUCT_BUNDLE_IDENTIFIER = org.telegram.RLottie; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugHockeyapp; + }; + D0AF793122C2C27700CECCB8 /* ReleaseHockeyappInternal */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -793,36 +991,9 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = ReleaseHockeyappInternal; }; - D010DF4522C225E4009324D4 /* DebugHockeyapp */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_OPTIMIZATION_LEVEL = s; - INFOPLIST_FILE = Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MACH_O_TYPE = staticlib; - PRODUCT_BUNDLE_IDENTIFIER = org.telegram.RLottie; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = DebugHockeyapp; - }; - D010DF4622C225E4009324D4 /* Release */ = { + D0AF793222C2C27700CECCB8 /* ReleaseHockeyappInternal */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; @@ -846,7 +1017,7 @@ SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; }; - name = Release; + name = ReleaseHockeyappInternal; }; /* End XCBuildConfiguration section */ @@ -854,20 +1025,24 @@ D010DF3622C225E4009324D4 /* Build configuration list for PBXProject "RLottie_Xcode" */ = { isa = XCConfigurationList; buildConfigurations = ( - D010DF4222C225E4009324D4 /* DebugHockeyapp */, - D010DF4322C225E4009324D4 /* Release */, + D010DF4222C225E4009324D4 /* DebugAppStoreLLC */, + D0AF792F22C2C26A00CECCB8 /* DebugHockeyapp */, + D010DF4322C225E4009324D4 /* ReleaseAppStoreLLC */, + D0AF793122C2C27700CECCB8 /* ReleaseHockeyappInternal */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = ReleaseAppStoreLLC; }; D010DF4422C225E4009324D4 /* Build configuration list for PBXNativeTarget "RLottie" */ = { isa = XCConfigurationList; buildConfigurations = ( - D010DF4522C225E4009324D4 /* DebugHockeyapp */, - D010DF4622C225E4009324D4 /* Release */, + D010DF4522C225E4009324D4 /* DebugAppStoreLLC */, + D0AF793022C2C26A00CECCB8 /* DebugHockeyapp */, + D010DF4622C225E4009324D4 /* ReleaseAppStoreLLC */, + D0AF793222C2C27700CECCB8 /* ReleaseHockeyappInternal */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = ReleaseAppStoreLLC; }; /* End XCConfigurationList section */ }; From 0fd1a50d7f3eb169370fe0528f7136e973cdb84b Mon Sep 17 00:00:00 2001 From: Peter <> Date: Wed, 26 Jun 2019 00:14:52 +0300 Subject: [PATCH 12/26] Add rlottie --- .../RLottie/Sources/rlottie/.Gifs/1.gif | Bin 0 -> 5884534 bytes .../RLottie/Sources/rlottie/.Gifs/2.gif | Bin 0 -> 1078299 bytes .../RLottie/Sources/rlottie/.clang-format | 90 + submodules/RLottie/Sources/rlottie/.gitignore | 11 + .../RLottie/Sources/rlottie/.travis.yml | 35 + submodules/RLottie/Sources/rlottie/AUTHORS | 8 + .../RLottie/Sources/rlottie/CMakeLists.txt | 134 + submodules/RLottie/Sources/rlottie/COPYING | 17 + submodules/RLottie/Sources/rlottie/README.md | 250 + .../rlottie/cmake/rlottieConfig.cmake.in | 16 + .../Sources/rlottie/example/CMakeLists.txt | 11 + .../RLottie/Sources/rlottie/example/demo.cpp | 73 + .../Sources/rlottie/example/efl_animview.cpp | 319 + .../Sources/rlottie/example/evasapp.cpp | 141 + .../RLottie/Sources/rlottie/example/evasapp.h | 75 + .../RLottie/Sources/rlottie/example/gif.h | 835 ++ .../Sources/rlottie/example/lottie2gif.cpp | 142 + .../Sources/rlottie/example/lottieview.cpp | 198 + .../Sources/rlottie/example/lottieview.h | 579 ++ .../Sources/rlottie/example/lottieviewer.cpp | 255 + .../rlottie/example/lottieviewtest.cpp | 127 + .../Sources/rlottie/example/meson.build | 62 + .../Sources/rlottie/example/pathtest.cpp | 126 + .../example/resource/1643-exploding-star.json | 1 + .../example/resource/1667-firework.json | 1 + .../rlottie/example/resource/360º_degree.json | 1 + .../Sources/rlottie/example/resource/3d.json | 1 + .../example/resource/4479-fireworks.json | 1 + .../example/resource/5317-fireworkds.json | 1 + .../example/resource/5344-honey-sack-hud.json | 1 + .../rlottie/example/resource/Indicators1.json | 1 + .../ModernPictogramsForLottie_LoudMute.json | 1 + .../example/resource/StickAndBall.json | 1 + .../A Shapes_All_01_1920x1080.json | 1 + .../B Fills_All_01_1920x1080.json | 1 + .../C Strokes_All_01_1920x1080.json | 1 + .../D Transforms_All_01_1920x1080.json | 1 + .../E Interpolation_All_01_1920x1080.json | 1 + .../F Masks_All_01_1920x1080.json | 1 + .../F Masks_All_02_1920x1080.json | 1 + .../rlottie/example/resource/_alarm.json | 1 + .../example/resource/a_cup_of_coffee.json | 1 + .../rlottie/example/resource/a_mountain.json | 1 + .../example/resource/abstract_circle.json | 1 + .../rlottie/example/resource/acrobatics.json | 1 + .../rlottie/example/resource/anubis.json | 1 + .../Sources/rlottie/example/resource/ao.json | 1 + .../resource/balloons_with_string.json | 1 + .../rlottie/example/resource/bell.json | 1 + .../example/resource/birth_stone_logo.json | 1 + .../example/resource/bounching_ball.json | 1 + .../rlottie/example/resource/browser.json | 1 + .../rlottie/example/resource/confetti.json | 1 + .../rlottie/example/resource/cooking.json | 1 + .../Sources/rlottie/example/resource/dna.json | 1 + .../rlottie/example/resource/done.json | 1 + .../example/resource/dynamic_path_test.json | 1 + .../example/resource/dynamic_property.json | 1 + .../rlottie/example/resource/eid_mubarak.json | 1 + .../rlottie/example/resource/emoji_shock.json | 1 + .../rlottie/example/resource/emoji_wink.json | 1 + .../example/resource/file_transfer.json | 1 + .../example/resource/fingerprint_success.json | 1 + .../example/resource/funky_chicken.json | 1 + .../rlottie/example/resource/gears.json | 1 + .../example/resource/gears_or_settings.json | 1 + .../example/resource/glow_loading.json | 1 + .../gradient_animated_background.json | 1 + .../resource/gradient_sleepy_loader.json | 1 + .../rlottie/example/resource/happy.json | 1 + .../rlottie/example/resource/heart.json | 1 + .../rlottie/example/resource/hourglass.json | 1 + .../example/resource/icon_animation.json | 1 + .../example/resource/image_embedded.json | 1 + .../rlottie/example/resource/image_test.json | 1 + .../rlottie/example/resource/images/img_0.png | Bin 0 -> 101560 bytes .../rlottie/example/resource/imprint.json | 1 + .../example/resource/insta_camera.json | 1 + .../resource/intelia_logo_animation.json | 1 + .../example/resource/it's_lunch_time!.json | 1 + .../example/resource/jolly_walker.json | 1 + .../rlottie/example/resource/layout.edc | 93 + .../rlottie/example/resource/layout.edj | Bin 0 -> 9106 bytes .../example/resource/leap_frog_loader.json | 1 + .../rlottie/example/resource/like.json | 1 + .../rlottie/example/resource/loader.json | 1 + .../rlottie/example/resource/loader_4.json | 1 + .../example/resource/loader_animation.json | 1 + .../rlottie/example/resource/loading.json | 1 + .../rlottie/example/resource/loading_.json | 1 + .../example/resource/loading_animation.json | 1 + .../example/resource/loading_rectangles.json | 1 + .../looping_landscape_+_plane_+_clouds.json | 1 + .../rlottie/example/resource/maps.json | 1 + .../rlottie/example/resource/mask.json | 1 + .../resource/material_wave_loading.json | 1 + .../matte_two_item_with_lowerlayer.json | 1 + .../rlottie/example/resource/mnemonics.json | 1 + .../example/resource/movie_loading.json | 1 + .../rlottie/example/resource/mughead.json | 1 + .../rlottie/example/resource/night_own.json | 1 + .../rlottie/example/resource/ondas.json | 1 + .../example/resource/party_penguin.json | 1 + .../rlottie/example/resource/peli-canon.json | 1 + .../example/resource/personal_character.json | 1 + .../example/resource/polystar_anim.json | 1 + .../polystar_line_clockwise_trim.json | 1 + .../rlottie/example/resource/pumped_up.json | 1 + .../rlottie/example/resource/red_box.json | 1 + .../resource/ripple_loading_animation.json | 1 + .../rlottie/example/resource/settings.json | 1 + .../example/resource/spin,_lil_loader_v2.json | 1 + .../example/resource/square_wheel.json | 1 + .../example/resource/starts_transparent.json | 1 + .../example/resource/static_dynamic_dash.json | 1 + .../rlottie/example/resource/telegram.json | 1 + .../resource/tile_grid_loading_animation.json | 1 + .../rlottie/example/resource/tractor.json | 1 + .../example/resource/triib_manage.json | 1 + .../rlottie/example/resource/waves_.json | 1 + .../rlottie/example/resource/windmill.json | 1 + .../example/resource/world_locations.json | 1 + .../rlottie/example/resource/worm.json | 1 + .../rlottie/example/resource/you're_in!.json | 1 + .../Sources/rlottie/example/uxsampletest.cpp | 134 + .../Sources/rlottie/example/vectortest.cpp | 31 + .../Sources/rlottie/inc/CMakeLists.txt | 4 + .../RLottie/Sources/rlottie/inc/meson.build | 5 + .../RLottie/Sources/rlottie/inc/rlottie.h | 462 + .../Sources/rlottie/inc/rlottie_capi.h | 241 + .../Sources/rlottie/inc/rlottiecommon.h | 237 + .../Sources/rlottie/licenses/COPYING.FTL | 166 + .../Sources/rlottie/licenses/COPYING.LGPL | 504 ++ .../Sources/rlottie/licenses/COPYING.PIX | 42 + .../Sources/rlottie/licenses/COPYING.RPD | 57 + .../Sources/rlottie/licenses/COPYING.STB | 17 + .../RLottie/Sources/rlottie/meson.build | 41 + .../RLottie/Sources/rlottie/meson_options.txt | 15 + .../rlottie/packaging/rlottie.manifest | 5 + .../Sources/rlottie/packaging/rlottie.spec | 69 + .../RLottie/Sources/rlottie/rlottie.pc.in | 6 + .../Sources/rlottie/src/CMakeLists.txt | 6 + .../rlottie/src/binding/CMakeLists.txt | 1 + .../rlottie/src/binding/c/CMakeLists.txt | 9 + .../src/binding/c/lottieanimation_capi.cpp | 151 + .../Sources/rlottie/src/binding/c/meson.build | 6 + .../Sources/rlottie/src/binding/meson.build | 2 + .../Sources/rlottie/src/lottie/CMakeLists.txt | 16 + .../rlottie/src/lottie/lottieanimation.cpp | 411 + .../Sources/rlottie/src/lottie/lottieitem.cpp | 1731 ++++ .../Sources/rlottie/src/lottie/lottieitem.h | 525 ++ .../rlottie/src/lottie/lottiekeypath.cpp | 86 + .../rlottie/src/lottie/lottiekeypath.h | 46 + .../rlottie/src/lottie/lottieloader.cpp | 121 + .../Sources/rlottie/src/lottie/lottieloader.h | 38 + .../rlottie/src/lottie/lottiemodel.cpp | 324 + .../Sources/rlottie/src/lottie/lottiemodel.h | 970 +++ .../rlottie/src/lottie/lottieparser.cpp | 2244 +++++ .../Sources/rlottie/src/lottie/lottieparser.h | 34 + .../rlottie/src/lottie/lottieproxymodel.cpp | 0 .../rlottie/src/lottie/lottieproxymodel.h | 335 + .../Sources/rlottie/src/lottie/meson.build | 14 + .../rlottie/src/lottie/rapidjson/allocators.h | 284 + .../lottie/rapidjson/cursorstreamwrapper.h | 78 + .../rlottie/src/lottie/rapidjson/document.h | 2652 ++++++ .../src/lottie/rapidjson/encodedstream.h | 299 + .../rlottie/src/lottie/rapidjson/encodings.h | 716 ++ .../rlottie/src/lottie/rapidjson/error/en.h | 74 + .../src/lottie/rapidjson/error/error.h | 161 + .../src/lottie/rapidjson/filereadstream.h | 99 + .../src/lottie/rapidjson/filewritestream.h | 104 + .../rlottie/src/lottie/rapidjson/fwd.h | 151 + .../lottie/rapidjson/internal/biginteger.h | 290 + .../src/lottie/rapidjson/internal/diyfp.h | 271 + .../src/lottie/rapidjson/internal/dtoa.h | 245 + .../src/lottie/rapidjson/internal/ieee754.h | 78 + .../src/lottie/rapidjson/internal/itoa.h | 308 + .../src/lottie/rapidjson/internal/meta.h | 186 + .../src/lottie/rapidjson/internal/pow10.h | 55 + .../src/lottie/rapidjson/internal/regex.h | 740 ++ .../src/lottie/rapidjson/internal/stack.h | 232 + .../src/lottie/rapidjson/internal/strfunc.h | 69 + .../src/lottie/rapidjson/internal/strtod.h | 290 + .../src/lottie/rapidjson/internal/swap.h | 46 + .../src/lottie/rapidjson/istreamwrapper.h | 128 + .../src/lottie/rapidjson/memorybuffer.h | 70 + .../src/lottie/rapidjson/memorystream.h | 71 + .../lottie/rapidjson/msinttypes/inttypes.h | 316 + .../src/lottie/rapidjson/msinttypes/stdint.h | 300 + .../src/lottie/rapidjson/ostreamwrapper.h | 81 + .../rlottie/src/lottie/rapidjson/pointer.h | 1414 ++++ .../src/lottie/rapidjson/prettywriter.h | 277 + .../rlottie/src/lottie/rapidjson/rapidjson.h | 656 ++ .../rlottie/src/lottie/rapidjson/reader.h | 2230 +++++ .../rlottie/src/lottie/rapidjson/schema.h | 2497 ++++++ .../rlottie/src/lottie/rapidjson/stream.h | 250 + .../src/lottie/rapidjson/stringbuffer.h | 121 + .../rlottie/src/lottie/rapidjson/writer.h | 709 ++ .../RLottie/Sources/rlottie/src/meson.build | 14 + .../Sources/rlottie/src/vector/CMakeLists.txt | 33 + .../Sources/rlottie/src/vector/config.h | 16 + .../src/vector/freetype/CMakeLists.txt | 11 + .../rlottie/src/vector/freetype/meson.build | 10 + .../rlottie/src/vector/freetype/v_ft_math.cpp | 456 + .../rlottie/src/vector/freetype/v_ft_math.h | 438 + .../src/vector/freetype/v_ft_raster.cpp | 1456 ++++ .../rlottie/src/vector/freetype/v_ft_raster.h | 613 ++ .../src/vector/freetype/v_ft_stroker.cpp | 1917 +++++ .../src/vector/freetype/v_ft_stroker.h | 319 + .../rlottie/src/vector/freetype/v_ft_types.h | 160 + .../Sources/rlottie/src/vector/meson.build | 39 + .../Sources/rlottie/src/vector/pixman/1 | 2 + .../Sources/rlottie/src/vector/pixman/2 | 2794 ++++++ .../rlottie/src/vector/pixman/CMakeLists.txt | 17 + .../rlottie/src/vector/pixman/meson.build | 11 + .../src/vector/pixman/pixman-arm-neon-asm.S | 497 ++ .../src/vector/pixman/pixman-arm-neon-asm.h | 1126 +++ .../rlottie/src/vector/pixman/vregion.cpp | 2086 +++++ .../rlottie/src/vector/pixman/vregion.h | 89 + .../rlottie/src/vector/stb/CMakeLists.txt | 7 + .../rlottie/src/vector/stb/meson.build | 8 + .../rlottie/src/vector/stb/stb_image.cpp | 67 + .../rlottie/src/vector/stb/stb_image.h | 7468 +++++++++++++++++ .../Sources/rlottie/src/vector/vbezier.cpp | 138 + .../Sources/rlottie/src/vector/vbezier.h | 134 + .../Sources/rlottie/src/vector/vbitmap.cpp | 227 + .../Sources/rlottie/src/vector/vbitmap.h | 59 + .../Sources/rlottie/src/vector/vbrush.cpp | 114 + .../Sources/rlottie/src/vector/vbrush.h | 95 + .../src/vector/vcompositionfunctions.cpp | 174 + .../Sources/rlottie/src/vector/vcowptr.h | 122 + .../Sources/rlottie/src/vector/vdasher.cpp | 215 + .../Sources/rlottie/src/vector/vdasher.h | 57 + .../Sources/rlottie/src/vector/vdebug.cpp | 754 ++ .../Sources/rlottie/src/vector/vdebug.h | 183 + .../Sources/rlottie/src/vector/vdrawable.cpp | 91 + .../Sources/rlottie/src/vector/vdrawable.h | 68 + .../rlottie/src/vector/vdrawhelper.cpp | 945 +++ .../Sources/rlottie/src/vector/vdrawhelper.h | 248 + .../rlottie/src/vector/vdrawhelper_neon.cpp | 27 + .../rlottie/src/vector/vdrawhelper_sse2.cpp | 498 ++ .../rlottie/src/vector/velapsedtimer.cpp | 47 + .../rlottie/src/vector/velapsedtimer.h | 37 + .../Sources/rlottie/src/vector/vglobal.h | 323 + .../rlottie/src/vector/vimageloader.cpp | 226 + .../Sources/rlottie/src/vector/vimageloader.h | 26 + .../rlottie/src/vector/vinterpolator.cpp | 154 + .../rlottie/src/vector/vinterpolator.h | 84 + .../Sources/rlottie/src/vector/vline.h | 92 + .../Sources/rlottie/src/vector/vmatrix.cpp | 731 ++ .../Sources/rlottie/src/vector/vmatrix.h | 102 + .../Sources/rlottie/src/vector/vpainter.cpp | 206 + .../Sources/rlottie/src/vector/vpainter.h | 60 + .../Sources/rlottie/src/vector/vpath.cpp | 699 ++ .../Sources/rlottie/src/vector/vpath.h | 273 + .../rlottie/src/vector/vpathmesure.cpp | 61 + .../Sources/rlottie/src/vector/vpathmesure.h | 38 + .../Sources/rlottie/src/vector/vpoint.h | 207 + .../Sources/rlottie/src/vector/vraster.cpp | 535 ++ .../Sources/rlottie/src/vector/vraster.h | 46 + .../Sources/rlottie/src/vector/vrect.cpp | 64 + .../Sources/rlottie/src/vector/vrect.h | 166 + .../Sources/rlottie/src/vector/vrle.cpp | 731 ++ .../RLottie/Sources/rlottie/src/vector/vrle.h | 198 + .../rlottie/src/vector/vstackallocator.h | 152 + .../Sources/rlottie/src/vector/vtaskqueue.h | 83 + .../RLottie/Sources/rlottie/test/meson.build | 25 + .../rlottie/test/test_lottieanimation.cpp | 34 + .../test/test_lottieanimation_capi.cpp | 34 + .../Sources/rlottie/test/test_vpath.cpp | 190 + .../Sources/rlottie/test/testsgregion.cpp | 120 + .../Sources/rlottie/test/testsuite.cpp | 6 + 272 files changed, 58902 insertions(+) create mode 100755 submodules/RLottie/Sources/rlottie/.Gifs/1.gif create mode 100755 submodules/RLottie/Sources/rlottie/.Gifs/2.gif create mode 100644 submodules/RLottie/Sources/rlottie/.clang-format create mode 100644 submodules/RLottie/Sources/rlottie/.gitignore create mode 100644 submodules/RLottie/Sources/rlottie/.travis.yml create mode 100644 submodules/RLottie/Sources/rlottie/AUTHORS create mode 100644 submodules/RLottie/Sources/rlottie/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/COPYING create mode 100644 submodules/RLottie/Sources/rlottie/README.md create mode 100644 submodules/RLottie/Sources/rlottie/cmake/rlottieConfig.cmake.in create mode 100644 submodules/RLottie/Sources/rlottie/example/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/example/demo.cpp create mode 100644 submodules/RLottie/Sources/rlottie/example/efl_animview.cpp create mode 100644 submodules/RLottie/Sources/rlottie/example/evasapp.cpp create mode 100644 submodules/RLottie/Sources/rlottie/example/evasapp.h create mode 100644 submodules/RLottie/Sources/rlottie/example/gif.h create mode 100644 submodules/RLottie/Sources/rlottie/example/lottie2gif.cpp create mode 100644 submodules/RLottie/Sources/rlottie/example/lottieview.cpp create mode 100644 submodules/RLottie/Sources/rlottie/example/lottieview.h create mode 100644 submodules/RLottie/Sources/rlottie/example/lottieviewer.cpp create mode 100644 submodules/RLottie/Sources/rlottie/example/lottieviewtest.cpp create mode 100644 submodules/RLottie/Sources/rlottie/example/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/example/pathtest.cpp create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/1643-exploding-star.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/1667-firework.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/360º_degree.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/3d.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/4479-fireworks.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/5317-fireworkds.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/5344-honey-sack-hud.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/Indicators1.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/ModernPictogramsForLottie_LoudMute.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/StickAndBall.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/UXSample_1920x1080/A Shapes_All_01_1920x1080.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/UXSample_1920x1080/B Fills_All_01_1920x1080.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/UXSample_1920x1080/C Strokes_All_01_1920x1080.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/UXSample_1920x1080/D Transforms_All_01_1920x1080.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/UXSample_1920x1080/E Interpolation_All_01_1920x1080.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/UXSample_1920x1080/F Masks_All_01_1920x1080.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/UXSample_1920x1080/F Masks_All_02_1920x1080.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/_alarm.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/a_cup_of_coffee.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/a_mountain.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/abstract_circle.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/acrobatics.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/anubis.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/ao.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/balloons_with_string.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/bell.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/birth_stone_logo.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/bounching_ball.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/browser.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/confetti.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/cooking.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/dna.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/done.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/dynamic_path_test.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/dynamic_property.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/eid_mubarak.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/emoji_shock.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/emoji_wink.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/file_transfer.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/fingerprint_success.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/funky_chicken.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/gears.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/gears_or_settings.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/glow_loading.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/gradient_animated_background.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/gradient_sleepy_loader.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/happy.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/heart.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/hourglass.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/icon_animation.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/image_embedded.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/image_test.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/images/img_0.png create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/imprint.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/insta_camera.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/intelia_logo_animation.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/it's_lunch_time!.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/jolly_walker.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/layout.edc create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/layout.edj create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/leap_frog_loader.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/like.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/loader.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/loader_4.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/loader_animation.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/loading.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/loading_.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/loading_animation.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/loading_rectangles.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/looping_landscape_+_plane_+_clouds.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/maps.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/mask.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/material_wave_loading.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/matte_two_item_with_lowerlayer.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/mnemonics.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/movie_loading.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/mughead.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/night_own.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/ondas.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/party_penguin.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/peli-canon.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/personal_character.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/polystar_anim.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/polystar_line_clockwise_trim.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/pumped_up.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/red_box.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/ripple_loading_animation.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/settings.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/spin,_lil_loader_v2.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/square_wheel.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/starts_transparent.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/static_dynamic_dash.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/telegram.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/tile_grid_loading_animation.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/tractor.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/triib_manage.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/waves_.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/windmill.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/world_locations.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/worm.json create mode 100644 submodules/RLottie/Sources/rlottie/example/resource/you're_in!.json create mode 100644 submodules/RLottie/Sources/rlottie/example/uxsampletest.cpp create mode 100644 submodules/RLottie/Sources/rlottie/example/vectortest.cpp create mode 100644 submodules/RLottie/Sources/rlottie/inc/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/inc/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/inc/rlottie.h create mode 100644 submodules/RLottie/Sources/rlottie/inc/rlottie_capi.h create mode 100644 submodules/RLottie/Sources/rlottie/inc/rlottiecommon.h create mode 100644 submodules/RLottie/Sources/rlottie/licenses/COPYING.FTL create mode 100644 submodules/RLottie/Sources/rlottie/licenses/COPYING.LGPL create mode 100644 submodules/RLottie/Sources/rlottie/licenses/COPYING.PIX create mode 100644 submodules/RLottie/Sources/rlottie/licenses/COPYING.RPD create mode 100644 submodules/RLottie/Sources/rlottie/licenses/COPYING.STB create mode 100644 submodules/RLottie/Sources/rlottie/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/meson_options.txt create mode 100644 submodules/RLottie/Sources/rlottie/packaging/rlottie.manifest create mode 100644 submodules/RLottie/Sources/rlottie/packaging/rlottie.spec create mode 100644 submodules/RLottie/Sources/rlottie/rlottie.pc.in create mode 100644 submodules/RLottie/Sources/rlottie/src/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/src/binding/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/src/binding/c/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/src/binding/c/lottieanimation_capi.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/binding/c/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/src/binding/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottieanimation.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottieitem.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottieitem.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottiekeypath.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottiekeypath.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottieloader.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottieloader.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottiemodel.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottiemodel.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottieparser.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottieparser.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottieproxymodel.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/lottieproxymodel.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/allocators.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/cursorstreamwrapper.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/document.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/encodedstream.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/encodings.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/error/en.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/error/error.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/filereadstream.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/filewritestream.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/fwd.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/biginteger.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/diyfp.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/dtoa.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/ieee754.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/itoa.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/meta.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/pow10.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/regex.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/stack.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/strfunc.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/strtod.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/internal/swap.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/istreamwrapper.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/memorybuffer.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/memorystream.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/msinttypes/inttypes.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/msinttypes/stdint.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/ostreamwrapper.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/pointer.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/prettywriter.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/rapidjson.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/reader.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/schema.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/stream.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/stringbuffer.h create mode 100644 submodules/RLottie/Sources/rlottie/src/lottie/rapidjson/writer.h create mode 100644 submodules/RLottie/Sources/rlottie/src/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/config.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/freetype/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/freetype/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/freetype/v_ft_math.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/freetype/v_ft_math.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/freetype/v_ft_raster.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/freetype/v_ft_raster.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/freetype/v_ft_stroker.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/freetype/v_ft_stroker.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/freetype/v_ft_types.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/pixman/1 create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/pixman/2 create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/pixman/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/pixman/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/pixman/pixman-arm-neon-asm.S create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/pixman/pixman-arm-neon-asm.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/pixman/vregion.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/pixman/vregion.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/stb/CMakeLists.txt create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/stb/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/stb/stb_image.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/stb/stb_image.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vbezier.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vbezier.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vbitmap.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vbitmap.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vbrush.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vbrush.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vcompositionfunctions.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vcowptr.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdasher.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdasher.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdebug.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdebug.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdrawable.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdrawable.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdrawhelper.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdrawhelper.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdrawhelper_neon.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vdrawhelper_sse2.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/velapsedtimer.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/velapsedtimer.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vglobal.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vimageloader.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vimageloader.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vinterpolator.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vinterpolator.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vline.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vmatrix.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vmatrix.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vpainter.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vpainter.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vpath.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vpath.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vpathmesure.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vpathmesure.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vpoint.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vraster.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vraster.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vrect.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vrect.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vrle.cpp create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vrle.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vstackallocator.h create mode 100644 submodules/RLottie/Sources/rlottie/src/vector/vtaskqueue.h create mode 100644 submodules/RLottie/Sources/rlottie/test/meson.build create mode 100644 submodules/RLottie/Sources/rlottie/test/test_lottieanimation.cpp create mode 100644 submodules/RLottie/Sources/rlottie/test/test_lottieanimation_capi.cpp create mode 100644 submodules/RLottie/Sources/rlottie/test/test_vpath.cpp create mode 100644 submodules/RLottie/Sources/rlottie/test/testsgregion.cpp create mode 100644 submodules/RLottie/Sources/rlottie/test/testsuite.cpp diff --git a/submodules/RLottie/Sources/rlottie/.Gifs/1.gif b/submodules/RLottie/Sources/rlottie/.Gifs/1.gif new file mode 100755 index 0000000000000000000000000000000000000000..7f33920b72f019a262e0e117161b72380055f04a GIT binary patch literal 5884534 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%0Dg>>)a@-7b9=0xCNe2D!N>8FNRkr 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�+6h%25IA5yAcF$HS_`Lg5lF`69>pLcrw^ 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

krITYB4x^zDb<}C##_kxEjIbt@tQR((#A- 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