@amazon-devices/expo-image 2.0.1758683737
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +2 -0
- package/CHANGELOG.md +285 -0
- package/CMakeLists.txt +91 -0
- package/LICENSE +7 -0
- package/README.kepler.md +123 -0
- package/README.md +54 -0
- package/THIRD_PARTY_NOTICES.txt +24 -0
- package/android/build.gradle +124 -0
- package/android/proguard-rules.pro +28 -0
- package/android/src/main/AndroidManifest.xml +15 -0
- package/android/src/main/java/expo/modules/image/Exceptions.kt +9 -0
- package/android/src/main/java/expo/modules/image/ExpoImageAppGlideModule.kt +19 -0
- package/android/src/main/java/expo/modules/image/ExpoImageModule.kt +192 -0
- package/android/src/main/java/expo/modules/image/ExpoImageView.kt +220 -0
- package/android/src/main/java/expo/modules/image/ExpoImageViewWrapper.kt +652 -0
- package/android/src/main/java/expo/modules/image/GlideModel.kt +73 -0
- package/android/src/main/java/expo/modules/image/ImageUtils.kt +50 -0
- package/android/src/main/java/expo/modules/image/ImageViewWrapperTarget.kt +313 -0
- package/android/src/main/java/expo/modules/image/ResourceIdHelper.kt +47 -0
- package/android/src/main/java/expo/modules/image/ThumbnailRequestCoordinatorExtension.kt +21 -0
- package/android/src/main/java/expo/modules/image/YogaUtils.kt +20 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurHashFetcher.kt +32 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashDecoder.kt +189 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashModelLoader.kt +30 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashModelLoaderFactory.kt +14 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashModule.kt +17 -0
- package/android/src/main/java/expo/modules/image/dataurls/Base64DataFetcher.kt +27 -0
- package/android/src/main/java/expo/modules/image/dataurls/Base64ModelLoader.kt +24 -0
- package/android/src/main/java/expo/modules/image/dataurls/Base64ModelLoaderFactory.kt +12 -0
- package/android/src/main/java/expo/modules/image/dataurls/Base64Module.kt +16 -0
- package/android/src/main/java/expo/modules/image/drawing/OutlineProvider.kt +201 -0
- package/android/src/main/java/expo/modules/image/enums/ContentFit.kt +89 -0
- package/android/src/main/java/expo/modules/image/enums/ImageCacheType.kt +14 -0
- package/android/src/main/java/expo/modules/image/enums/Priority.kt +15 -0
- package/android/src/main/java/expo/modules/image/events/GlideRequestListener.kt +64 -0
- package/android/src/main/java/expo/modules/image/events/OkHttpProgressListener.kt +26 -0
- package/android/src/main/java/expo/modules/image/okhttp/ExpoImageOkHttpClientGlideModule.kt +80 -0
- package/android/src/main/java/expo/modules/image/okhttp/GlideUrlWrapperLoader.kt +55 -0
- package/android/src/main/java/expo/modules/image/records/CachePolicy.kt +10 -0
- package/android/src/main/java/expo/modules/image/records/ContentPosition.kt +89 -0
- package/android/src/main/java/expo/modules/image/records/ImageTransition.kt +8 -0
- package/android/src/main/java/expo/modules/image/records/SourceMap.kt +160 -0
- package/android/src/main/java/expo/modules/image/records/events.kt +25 -0
- package/android/src/main/java/expo/modules/image/svg/SVGDecoder.kt +33 -0
- package/android/src/main/java/expo/modules/image/svg/SVGDrawableTranscoder.kt +37 -0
- package/android/src/main/java/expo/modules/image/svg/SVGModule.kt +26 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashDecoder.kt +365 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashFetcher.kt +31 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashModelLoader.kt +26 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashModelLoaderFactory.kt +14 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashModule.kt +17 -0
- package/build/ExpoImage.d.ts +15 -0
- package/build/ExpoImage.d.ts.map +1 -0
- package/build/ExpoImage.js +75 -0
- package/build/ExpoImage.js.map +1 -0
- package/build/ExpoImage.kepler.d.ts +23 -0
- package/build/ExpoImage.kepler.d.ts.map +1 -0
- package/build/ExpoImage.kepler.js +71 -0
- package/build/ExpoImage.kepler.js.map +1 -0
- package/build/ExpoImage.web.d.ts +9 -0
- package/build/ExpoImage.web.d.ts.map +1 -0
- package/build/ExpoImage.web.js +90 -0
- package/build/ExpoImage.web.js.map +1 -0
- package/build/ExpoImageModules.d.ts +3 -0
- package/build/ExpoImageModules.d.ts.map +1 -0
- package/build/ExpoImageModules.js +4 -0
- package/build/ExpoImageModules.js.map +1 -0
- package/build/ExpoImageModules.kepler.d.ts +6 -0
- package/build/ExpoImageModules.kepler.d.ts.map +1 -0
- package/build/ExpoImageModules.kepler.js +5 -0
- package/build/ExpoImageModules.kepler.js.map +1 -0
- package/build/Image.d.ts +30 -0
- package/build/Image.d.ts.map +1 -0
- package/build/Image.js +49 -0
- package/build/Image.js.map +1 -0
- package/build/Image.types.d.ts +374 -0
- package/build/Image.types.d.ts.map +1 -0
- package/build/Image.types.js +2 -0
- package/build/Image.types.js.map +1 -0
- package/build/ImageBackground.d.ts +6 -0
- package/build/ImageBackground.d.ts.map +1 -0
- package/build/ImageBackground.js +13 -0
- package/build/ImageBackground.js.map +1 -0
- package/build/ImageViewNativeComponent.d.ts +20 -0
- package/build/ImageViewNativeComponent.d.ts.map +1 -0
- package/build/ImageViewNativeComponent.js +42 -0
- package/build/ImageViewNativeComponent.js.map +1 -0
- package/build/NativeImageLoaderKepler.d.ts +18 -0
- package/build/NativeImageLoaderKepler.d.ts.map +1 -0
- package/build/NativeImageLoaderKepler.js +3 -0
- package/build/NativeImageLoaderKepler.js.map +1 -0
- package/build/fabric/registerNativeComponent.d.ts +15 -0
- package/build/fabric/registerNativeComponent.d.ts.map +1 -0
- package/build/fabric/registerNativeComponent.js +47 -0
- package/build/fabric/registerNativeComponent.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/build/utils/AssetSourceResolver.web.d.ts +24 -0
- package/build/utils/AssetSourceResolver.web.d.ts.map +1 -0
- package/build/utils/AssetSourceResolver.web.js +67 -0
- package/build/utils/AssetSourceResolver.web.js.map +1 -0
- package/build/utils/blurhash/base83.d.ts +3 -0
- package/build/utils/blurhash/base83.d.ts.map +1 -0
- package/build/utils/blurhash/base83.js +103 -0
- package/build/utils/blurhash/base83.js.map +1 -0
- package/build/utils/blurhash/decode.d.ts +7 -0
- package/build/utils/blurhash/decode.d.ts.map +1 -0
- package/build/utils/blurhash/decode.js +92 -0
- package/build/utils/blurhash/decode.js.map +1 -0
- package/build/utils/blurhash/error.d.ts +4 -0
- package/build/utils/blurhash/error.d.ts.map +1 -0
- package/build/utils/blurhash/error.js +8 -0
- package/build/utils/blurhash/error.js.map +1 -0
- package/build/utils/blurhash/useBlurhash.d.ts +8 -0
- package/build/utils/blurhash/useBlurhash.d.ts.map +1 -0
- package/build/utils/blurhash/useBlurhash.js +64 -0
- package/build/utils/blurhash/useBlurhash.js.map +1 -0
- package/build/utils/blurhash/utils.d.ts +5 -0
- package/build/utils/blurhash/utils.d.ts.map +1 -0
- package/build/utils/blurhash/utils.js +21 -0
- package/build/utils/blurhash/utils.js.map +1 -0
- package/build/utils/resolveAssetSource.d.ts +3 -0
- package/build/utils/resolveAssetSource.d.ts.map +1 -0
- package/build/utils/resolveAssetSource.js +3 -0
- package/build/utils/resolveAssetSource.js.map +1 -0
- package/build/utils/resolveAssetSource.web.d.ts +9 -0
- package/build/utils/resolveAssetSource.web.d.ts.map +1 -0
- package/build/utils/resolveAssetSource.web.js +31 -0
- package/build/utils/resolveAssetSource.web.js.map +1 -0
- package/build/utils/resolveHashString.d.ts +14 -0
- package/build/utils/resolveHashString.d.ts.map +1 -0
- package/build/utils/resolveHashString.js +31 -0
- package/build/utils/resolveHashString.js.map +1 -0
- package/build/utils/resolveHashString.web.d.ts +20 -0
- package/build/utils/resolveHashString.web.d.ts.map +1 -0
- package/build/utils/resolveHashString.web.js +31 -0
- package/build/utils/resolveHashString.web.js.map +1 -0
- package/build/utils/resolveSources.d.ts +8 -0
- package/build/utils/resolveSources.d.ts.map +1 -0
- package/build/utils/resolveSources.js +45 -0
- package/build/utils/resolveSources.js.map +1 -0
- package/build/utils/thumbhash/thumbhash.d.ts +66 -0
- package/build/utils/thumbhash/thumbhash.d.ts.map +1 -0
- package/build/utils/thumbhash/thumbhash.js +338 -0
- package/build/utils/thumbhash/thumbhash.js.map +1 -0
- package/build/utils.d.ts +17 -0
- package/build/utils.d.ts.map +1 -0
- package/build/utils.js +85 -0
- package/build/utils.js.map +1 -0
- package/build/web/AnimationManager.d.ts +37 -0
- package/build/web/AnimationManager.d.ts.map +1 -0
- package/build/web/AnimationManager.js +155 -0
- package/build/web/AnimationManager.js.map +1 -0
- package/build/web/ColorTintFilter.d.ts +12 -0
- package/build/web/ColorTintFilter.d.ts.map +1 -0
- package/build/web/ColorTintFilter.js +30 -0
- package/build/web/ColorTintFilter.js.map +1 -0
- package/build/web/ImageWrapper.d.ts +5 -0
- package/build/web/ImageWrapper.d.ts.map +1 -0
- package/build/web/ImageWrapper.js +44 -0
- package/build/web/ImageWrapper.js.map +1 -0
- package/build/web/ImageWrapper.types.d.ts +29 -0
- package/build/web/ImageWrapper.types.d.ts.map +1 -0
- package/build/web/ImageWrapper.types.js +2 -0
- package/build/web/ImageWrapper.types.js.map +1 -0
- package/build/web/getImageWrapperEventHandler.d.ts +8 -0
- package/build/web/getImageWrapperEventHandler.d.ts.map +1 -0
- package/build/web/getImageWrapperEventHandler.js +25 -0
- package/build/web/getImageWrapperEventHandler.js.map +1 -0
- package/build/web/hooks.d.ts +13 -0
- package/build/web/hooks.d.ts.map +1 -0
- package/build/web/hooks.js +58 -0
- package/build/web/hooks.js.map +1 -0
- package/build/web/imageStyles.d.ts +2 -0
- package/build/web/imageStyles.d.ts.map +1 -0
- package/build/web/imageStyles.js +137 -0
- package/build/web/imageStyles.js.map +1 -0
- package/build/web/positioning.d.ts +11 -0
- package/build/web/positioning.d.ts.map +1 -0
- package/build/web/positioning.js +35 -0
- package/build/web/positioning.js.map +1 -0
- package/build/web/useSourceSelection.d.ts +14 -0
- package/build/web/useSourceSelection.d.ts.map +1 -0
- package/build/web/useSourceSelection.js +98 -0
- package/build/web/useSourceSelection.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/Blurhash.swift +326 -0
- package/ios/BlurhashLoader.swift +52 -0
- package/ios/ContentFit.swift +55 -0
- package/ios/ContentPosition.swift +108 -0
- package/ios/ExpoImage.podspec +30 -0
- package/ios/ImageCachePolicy.swift +24 -0
- package/ios/ImageCacheType.swift +21 -0
- package/ios/ImageModule.swift +127 -0
- package/ios/ImagePriority.swift +22 -0
- package/ios/ImageSource.swift +44 -0
- package/ios/ImageTransition.swift +67 -0
- package/ios/ImageUtils.swift +227 -0
- package/ios/ImageView.swift +469 -0
- package/ios/Loaders/PhotoLibraryAssetLoader.swift +146 -0
- package/ios/Thumbhash.swift +550 -0
- package/ios/ThumbhashLoader.swift +53 -0
- package/jest.config.js +3 -0
- package/kepler/ExpoImage.cpp +63 -0
- package/kepler/ExpoImage.h +29 -0
- package/kepler/ExpoImageCacheHandler.cpp +15 -0
- package/kepler/ExpoImageCacheHandler.h +28 -0
- package/kepler/ExpoImageComponent.cpp +579 -0
- package/kepler/ExpoImageComponent.h +199 -0
- package/kepler/ImageWrapper/BlurhashImageWrapper.cpp +37 -0
- package/kepler/ImageWrapper/BlurhashImageWrapper.h +23 -0
- package/kepler/ImageWrapper/CacheImageWrapper.cpp +80 -0
- package/kepler/ImageWrapper/CacheImageWrapper.h +41 -0
- package/kepler/ImageWrapper/HashImageWrapper.cpp +21 -0
- package/kepler/ImageWrapper/HashImageWrapper.h +22 -0
- package/kepler/ImageWrapper/ImageWrapper.cpp +24 -0
- package/kepler/ImageWrapper/ImageWrapper.h +33 -0
- package/kepler/ImageWrapper/LocalImageWrapper.cpp +61 -0
- package/kepler/ImageWrapper/LocalImageWrapper.h +30 -0
- package/kepler/ImageWrapper/ThumbhashImageWrapper.cpp +33 -0
- package/kepler/ImageWrapper/ThumbhashImageWrapper.h +20 -0
- package/kepler/KeplerImageViewComponent.h +64 -0
- package/kepler/KeplerInit.cpp +35 -0
- package/kepler/blurhash/common.h +32 -0
- package/kepler/blurhash/decode.cpp +187 -0
- package/kepler/blurhash/decode.h +58 -0
- package/kepler/contentposition/ImageContentPosition.cpp +86 -0
- package/kepler/contentposition/ImageContentPosition.h +48 -0
- package/kepler/enums/ImageContentFit.h +17 -0
- package/kepler/enums/ImagePriority.h +17 -0
- package/kepler/managers/ExpoImageManager.cpp +38 -0
- package/kepler/managers/ExpoImageManager.h +23 -0
- package/kepler/test/ExpoImage.cpp +73 -0
- package/kepler/test/ExpoImageComponent.cpp +290 -0
- package/kepler/test/blurhash/decode.cpp +39 -0
- package/kepler/test/contentposition/ImageContentPosition.cpp +100 -0
- package/kepler/test/managers/ExpoImageManager.cpp +39 -0
- package/kepler/test/thumbhash/decode.cpp +18 -0
- package/kepler/test/utils/LoaderDelegate.cpp +130 -0
- package/kepler/thumbhash/decode.cpp +166 -0
- package/kepler/thumbhash/decode.h +22 -0
- package/kepler/utils/PlaceholderImageLoaderDelegate.cpp +26 -0
- package/kepler/utils/PlaceholderImageLoaderDelegate.h +26 -0
- package/kepler/utils/PrefetchImageLoaderDelegate.cpp +55 -0
- package/kepler/utils/PrefetchImageLoaderDelegate.h +35 -0
- package/kepler/utils/SourceImageLoaderDelegate.cpp +47 -0
- package/kepler/utils/SourceImageLoaderDelegate.h +42 -0
- package/kepler/utils/SourceImageLoaderDelegateEmitter.cpp +15 -0
- package/kepler/utils/SourceImageLoaderDelegateEmitter.h +28 -0
- package/kepler-compatibility.json +8 -0
- package/package.json +1 -0
- package/react-native.config.js +22 -0
- package/src/ExpoImage.kepler.tsx +119 -0
- package/src/ExpoImage.tsx +119 -0
- package/src/ExpoImage.web.tsx +155 -0
- package/src/ExpoImageModules.kepler.ts +7 -0
- package/src/ExpoImageModules.ts +4 -0
- package/src/Image.tsx +82 -0
- package/src/Image.types.ts +450 -0
- package/src/ImageBackground.tsx +18 -0
- package/src/ImageViewNativeComponent.ts +59 -0
- package/src/NativeImageLoaderKepler.ts +22 -0
- package/src/fabric/registerNativeComponent.ts +70 -0
- package/src/index.ts +3 -0
- package/src/utils/AssetSourceResolver.web.ts +88 -0
- package/src/utils/blurhash/base83.ts +104 -0
- package/src/utils/blurhash/decode.ts +114 -0
- package/src/utils/blurhash/error.ts +7 -0
- package/src/utils/blurhash/useBlurhash.tsx +81 -0
- package/src/utils/blurhash/utils.ts +21 -0
- package/src/utils/resolveAssetSource.tsx +3 -0
- package/src/utils/resolveAssetSource.web.ts +40 -0
- package/src/utils/resolveHashString.tsx +36 -0
- package/src/utils/resolveHashString.web.tsx +33 -0
- package/src/utils/resolveSources.tsx +48 -0
- package/src/utils/thumbhash/thumbhash.ts +387 -0
- package/src/utils.ts +109 -0
- package/src/web/AnimationManager.tsx +224 -0
- package/src/web/ColorTintFilter.tsx +36 -0
- package/src/web/ImageWrapper.tsx +85 -0
- package/src/web/ImageWrapper.types.ts +36 -0
- package/src/web/getImageWrapperEventHandler.ts +29 -0
- package/src/web/hooks.ts +72 -0
- package/src/web/imageStyles.tsx +136 -0
- package/src/web/positioning.ts +48 -0
- package/src/web/useSourceSelection.ts +151 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
package expo.modules.image.events
|
|
2
|
+
|
|
3
|
+
import android.graphics.drawable.Drawable
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.bumptech.glide.load.DataSource
|
|
6
|
+
import com.bumptech.glide.load.engine.GlideException
|
|
7
|
+
import com.bumptech.glide.request.RequestListener
|
|
8
|
+
import com.bumptech.glide.request.target.Target
|
|
9
|
+
import expo.modules.image.ExpoImageViewWrapper
|
|
10
|
+
import expo.modules.image.enums.ImageCacheType
|
|
11
|
+
import expo.modules.image.records.ImageErrorEvent
|
|
12
|
+
import expo.modules.image.records.ImageLoadEvent
|
|
13
|
+
import expo.modules.image.records.ImageSource
|
|
14
|
+
import java.lang.ref.WeakReference
|
|
15
|
+
import java.util.*
|
|
16
|
+
|
|
17
|
+
class GlideRequestListener(
|
|
18
|
+
private val expoImageViewWrapper: WeakReference<ExpoImageViewWrapper>
|
|
19
|
+
) : RequestListener<Drawable> {
|
|
20
|
+
override fun onLoadFailed(
|
|
21
|
+
e: GlideException?,
|
|
22
|
+
model: Any?,
|
|
23
|
+
target: Target<Drawable>,
|
|
24
|
+
isFirstResource: Boolean
|
|
25
|
+
): Boolean {
|
|
26
|
+
val errorMessage = e
|
|
27
|
+
?.message
|
|
28
|
+
// Glide always append that line to the end of the message.
|
|
29
|
+
// It's not possible to call `logRootCauses` from the JS, so we decided to remove it.
|
|
30
|
+
?.removeSuffix("\n call GlideException#logRootCauses(String) for more detail")
|
|
31
|
+
?: "Unknown error"
|
|
32
|
+
|
|
33
|
+
expoImageViewWrapper
|
|
34
|
+
.get()
|
|
35
|
+
?.onError
|
|
36
|
+
?.invoke(ImageErrorEvent(errorMessage))
|
|
37
|
+
|
|
38
|
+
Log.e("ExpoImage", errorMessage)
|
|
39
|
+
e?.logRootCauses("ExpoImage")
|
|
40
|
+
return false
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
override fun onResourceReady(
|
|
44
|
+
resource: Drawable,
|
|
45
|
+
model: Any,
|
|
46
|
+
target: Target<Drawable>,
|
|
47
|
+
dataSource: DataSource,
|
|
48
|
+
isFirstResource: Boolean
|
|
49
|
+
): Boolean {
|
|
50
|
+
expoImageViewWrapper.get()?.onLoad?.invoke(
|
|
51
|
+
ImageLoadEvent(
|
|
52
|
+
cacheType = ImageCacheType.fromNativeValue(dataSource).name.lowercase(Locale.getDefault()),
|
|
53
|
+
source = ImageSource(
|
|
54
|
+
url = model.toString(),
|
|
55
|
+
width = resource.intrinsicWidth,
|
|
56
|
+
height = resource.intrinsicHeight,
|
|
57
|
+
mediaType = null // TODO(@lukmccall): add mediaType
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return false
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package expo.modules.image.events
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.modules.network.ProgressListener
|
|
4
|
+
import expo.modules.image.ExpoImageViewWrapper
|
|
5
|
+
import expo.modules.image.records.ImageProgressEvent
|
|
6
|
+
import java.lang.ref.WeakReference
|
|
7
|
+
|
|
8
|
+
class OkHttpProgressListener(
|
|
9
|
+
private val expoImageViewWrapper: WeakReference<ExpoImageViewWrapper>
|
|
10
|
+
) : ProgressListener {
|
|
11
|
+
override fun onProgress(bytesWritten: Long, contentLength: Long, done: Boolean) {
|
|
12
|
+
// OkHttp calls that function twice at the end - when the last byte was downloaded with done set to false,
|
|
13
|
+
// and also shortly after, with done set to true. In both cases, the bytesWritten and the contentLength are equal.
|
|
14
|
+
// We want to avoid sending two same events to JS, that's why we return when done is set to true.
|
|
15
|
+
if (contentLength <= 0 || done) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
expoImageViewWrapper.get()?.onProgress?.invoke(
|
|
20
|
+
ImageProgressEvent(
|
|
21
|
+
loaded = bytesWritten.toInt(),
|
|
22
|
+
total = contentLength.toInt()
|
|
23
|
+
)
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
package expo.modules.image.okhttp
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.bumptech.glide.Glide
|
|
5
|
+
import com.bumptech.glide.Registry
|
|
6
|
+
import com.bumptech.glide.annotation.GlideModule
|
|
7
|
+
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader
|
|
8
|
+
import com.bumptech.glide.load.model.GlideUrl
|
|
9
|
+
import com.bumptech.glide.load.model.Headers
|
|
10
|
+
import com.bumptech.glide.module.LibraryGlideModule
|
|
11
|
+
import expo.modules.image.events.OkHttpProgressListener
|
|
12
|
+
import okhttp3.OkHttpClient
|
|
13
|
+
import java.io.InputStream
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* GlideUrl with custom cache key.
|
|
17
|
+
* It wraps the base implementation and overrides logic behind cache key and when two
|
|
18
|
+
* objects are equal. Typically, Glide uses the only cache key to compare objects.
|
|
19
|
+
* It won't suit our use case. We want to make custom cache key transparent and
|
|
20
|
+
* not use it to compare objects.
|
|
21
|
+
*/
|
|
22
|
+
class GlideUrlWithCustomCacheKey(
|
|
23
|
+
uri: String?,
|
|
24
|
+
headers: Headers?,
|
|
25
|
+
private val cacheKey: String
|
|
26
|
+
) : GlideUrl(uri, headers) {
|
|
27
|
+
/**
|
|
28
|
+
* Cached hash code value
|
|
29
|
+
*/
|
|
30
|
+
private var hashCode = 0
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @return a super cache key from [GlideUrl]
|
|
34
|
+
*/
|
|
35
|
+
private fun getBaseCacheKey(): String = super.getCacheKey()
|
|
36
|
+
|
|
37
|
+
override fun getCacheKey(): String = cacheKey
|
|
38
|
+
|
|
39
|
+
// Mostly copied from GlideUrl::equal
|
|
40
|
+
override fun equals(other: Any?): Boolean {
|
|
41
|
+
if (other is GlideUrlWithCustomCacheKey) {
|
|
42
|
+
return getBaseCacheKey() == other.getBaseCacheKey() && headers.equals(other.headers)
|
|
43
|
+
} else if (other is GlideUrl) {
|
|
44
|
+
return getBaseCacheKey() == other.cacheKey && headers.equals(other.headers)
|
|
45
|
+
}
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Mostly copied from GlideUrl::hashCode
|
|
50
|
+
override fun hashCode(): Int {
|
|
51
|
+
if (hashCode == 0) {
|
|
52
|
+
hashCode = getBaseCacheKey().hashCode()
|
|
53
|
+
hashCode = 31 * hashCode + headers.hashCode()
|
|
54
|
+
}
|
|
55
|
+
return hashCode
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* To connect listener with the request we have to create custom model.
|
|
61
|
+
* In that way, we're passing more information to the final data loader.
|
|
62
|
+
*/
|
|
63
|
+
data class GlideUrlWrapper(val glideUrl: GlideUrl) {
|
|
64
|
+
var progressListener: OkHttpProgressListener? = null
|
|
65
|
+
|
|
66
|
+
override fun toString(): String {
|
|
67
|
+
return glideUrl.toString()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@GlideModule
|
|
72
|
+
class ExpoImageOkHttpClientGlideModule : LibraryGlideModule() {
|
|
73
|
+
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
|
|
74
|
+
val client = OkHttpClient()
|
|
75
|
+
// We don't use the `GlideUrl` directly but we want to replace the default okhttp loader anyway
|
|
76
|
+
// to make sure that the app will use only one client.
|
|
77
|
+
registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory(client))
|
|
78
|
+
registry.prepend(GlideUrlWrapper::class.java, InputStream::class.java, GlideUrlWrapperLoader.Factory(client))
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
package expo.modules.image.okhttp
|
|
2
|
+
|
|
3
|
+
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader
|
|
4
|
+
import com.bumptech.glide.load.Options
|
|
5
|
+
import com.bumptech.glide.load.model.ModelLoader
|
|
6
|
+
import com.bumptech.glide.load.model.ModelLoaderFactory
|
|
7
|
+
import com.bumptech.glide.load.model.MultiModelLoaderFactory
|
|
8
|
+
import com.facebook.react.modules.network.ProgressResponseBody
|
|
9
|
+
import okhttp3.Interceptor
|
|
10
|
+
import okhttp3.OkHttpClient
|
|
11
|
+
import java.io.InputStream
|
|
12
|
+
|
|
13
|
+
class GlideUrlWrapperLoader(
|
|
14
|
+
private val commonClient: OkHttpClient
|
|
15
|
+
) : ModelLoader<GlideUrlWrapper, InputStream> {
|
|
16
|
+
override fun buildLoadData(
|
|
17
|
+
model: GlideUrlWrapper,
|
|
18
|
+
width: Int,
|
|
19
|
+
height: Int,
|
|
20
|
+
options: Options
|
|
21
|
+
): ModelLoader.LoadData<InputStream>? {
|
|
22
|
+
val loader = OkHttpUrlLoader(
|
|
23
|
+
commonClient
|
|
24
|
+
.newBuilder()
|
|
25
|
+
.addInterceptor(
|
|
26
|
+
Interceptor { chain ->
|
|
27
|
+
val originalResponse = chain.proceed(chain.request())
|
|
28
|
+
originalResponse
|
|
29
|
+
.newBuilder()
|
|
30
|
+
.body(
|
|
31
|
+
ProgressResponseBody(originalResponse.body) { bytesWritten, contentLength, done ->
|
|
32
|
+
model.progressListener?.onProgress(bytesWritten, contentLength, done)
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
.build()
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
.build()
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return loader.buildLoadData(model.glideUrl, width, height, options)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// The default http loader always returns true.
|
|
45
|
+
override fun handles(model: GlideUrlWrapper): Boolean = true
|
|
46
|
+
|
|
47
|
+
class Factory(
|
|
48
|
+
private val commonClient: OkHttpClient
|
|
49
|
+
) : ModelLoaderFactory<GlideUrlWrapper, InputStream> {
|
|
50
|
+
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<GlideUrlWrapper, InputStream> =
|
|
51
|
+
GlideUrlWrapperLoader(commonClient)
|
|
52
|
+
|
|
53
|
+
override fun teardown() = Unit
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
package expo.modules.image.records
|
|
2
|
+
|
|
3
|
+
import android.graphics.Matrix
|
|
4
|
+
import android.graphics.RectF
|
|
5
|
+
import expo.modules.image.calcXTranslation
|
|
6
|
+
import expo.modules.image.calcYTranslation
|
|
7
|
+
import expo.modules.kotlin.records.Field
|
|
8
|
+
import expo.modules.kotlin.records.Record
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Represents a position value that might be either `Double` or `String`.
|
|
12
|
+
* TODO(@lukmccall): Use `Either` instead of `Any`
|
|
13
|
+
*/
|
|
14
|
+
typealias ContentPositionValue = Any
|
|
15
|
+
|
|
16
|
+
private typealias CalcAxisOffset = (
|
|
17
|
+
value: Float,
|
|
18
|
+
imageRect: RectF,
|
|
19
|
+
viewRect: RectF,
|
|
20
|
+
isPercentage: Boolean,
|
|
21
|
+
isReverse: Boolean
|
|
22
|
+
) -> Float
|
|
23
|
+
|
|
24
|
+
class ContentPosition : Record {
|
|
25
|
+
@Field
|
|
26
|
+
val top: ContentPositionValue? = null
|
|
27
|
+
|
|
28
|
+
@Field
|
|
29
|
+
val bottom: ContentPositionValue? = null
|
|
30
|
+
|
|
31
|
+
@Field
|
|
32
|
+
val right: ContentPositionValue? = null
|
|
33
|
+
|
|
34
|
+
@Field
|
|
35
|
+
val left: ContentPositionValue? = null
|
|
36
|
+
|
|
37
|
+
private fun ContentPositionValue?.calcOffset(
|
|
38
|
+
isReverse: Boolean,
|
|
39
|
+
imageRect: RectF,
|
|
40
|
+
viewRect: RectF,
|
|
41
|
+
calcAxisOffset: CalcAxisOffset
|
|
42
|
+
): Float? {
|
|
43
|
+
if (this == null) {
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return if (this is Double) {
|
|
48
|
+
val value = this.toFloat()
|
|
49
|
+
calcAxisOffset(value, imageRect, viewRect, false, isReverse)
|
|
50
|
+
} else {
|
|
51
|
+
val value = this as String
|
|
52
|
+
|
|
53
|
+
if (value == "center") {
|
|
54
|
+
calcAxisOffset(50f, imageRect, viewRect, true, isReverse)
|
|
55
|
+
} else {
|
|
56
|
+
calcAxisOffset(value.removeSuffix("%").toFloat(), imageRect, viewRect, true, isReverse)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private fun offsetX(
|
|
62
|
+
imageRect: RectF,
|
|
63
|
+
viewRect: RectF
|
|
64
|
+
): Float {
|
|
65
|
+
return left.calcOffset(false, imageRect, viewRect, ::calcXTranslation)
|
|
66
|
+
?: right.calcOffset(true, imageRect, viewRect, ::calcXTranslation)
|
|
67
|
+
?: calcXTranslation(50f, imageRect, viewRect, isPercentage = true) // default value
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private fun offsetY(
|
|
71
|
+
imageRect: RectF,
|
|
72
|
+
viewRect: RectF
|
|
73
|
+
): Float {
|
|
74
|
+
return top.calcOffset(false, imageRect, viewRect, ::calcYTranslation)
|
|
75
|
+
?: bottom.calcOffset(true, imageRect, viewRect, ::calcYTranslation)
|
|
76
|
+
?: calcYTranslation(50f, imageRect, viewRect, isPercentage = true) // default value
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
internal fun apply(to: Matrix, imageRect: RectF, viewRect: RectF) {
|
|
80
|
+
val xOffset = offsetX(imageRect, viewRect)
|
|
81
|
+
val yOffset = offsetY(imageRect, viewRect)
|
|
82
|
+
|
|
83
|
+
to.postTranslate(xOffset, yOffset)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
companion object {
|
|
87
|
+
val center = ContentPosition()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
package expo.modules.image.records
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.net.Uri
|
|
5
|
+
import com.bumptech.glide.load.model.GlideUrl
|
|
6
|
+
import com.bumptech.glide.load.model.Headers
|
|
7
|
+
import com.bumptech.glide.load.model.LazyHeaders
|
|
8
|
+
import com.bumptech.glide.request.RequestOptions
|
|
9
|
+
import com.bumptech.glide.signature.ApplicationVersionSignature
|
|
10
|
+
import expo.modules.image.GlideBlurhashModel
|
|
11
|
+
import expo.modules.image.GlideModel
|
|
12
|
+
import expo.modules.image.GlideRawModel
|
|
13
|
+
import expo.modules.image.GlideThumbhashModel
|
|
14
|
+
import expo.modules.image.GlideUriModel
|
|
15
|
+
import expo.modules.image.GlideUrlModel
|
|
16
|
+
import expo.modules.image.ResourceIdHelper
|
|
17
|
+
import expo.modules.image.okhttp.GlideUrlWithCustomCacheKey
|
|
18
|
+
import expo.modules.kotlin.records.Field
|
|
19
|
+
import expo.modules.kotlin.records.Record
|
|
20
|
+
|
|
21
|
+
data class SourceMap(
|
|
22
|
+
@Field val uri: String? = null,
|
|
23
|
+
@Field val width: Int = 0,
|
|
24
|
+
@Field val height: Int = 0,
|
|
25
|
+
@Field val scale: Double = 1.0,
|
|
26
|
+
@Field val headers: Map<String, String>? = null,
|
|
27
|
+
@Field val cacheKey: String? = null
|
|
28
|
+
) : Record {
|
|
29
|
+
private var parsedUri: Uri? = null
|
|
30
|
+
|
|
31
|
+
private fun isDataUrl() = parsedUri?.scheme?.startsWith("data") ?: false
|
|
32
|
+
|
|
33
|
+
private fun isContentUrl() = parsedUri?.scheme?.startsWith("content") ?: false
|
|
34
|
+
|
|
35
|
+
private fun isResourceUri() = parsedUri?.scheme?.startsWith("android.resource") ?: false
|
|
36
|
+
|
|
37
|
+
private fun isLocalResourceUri() = parsedUri?.scheme?.startsWith("res") ?: false
|
|
38
|
+
|
|
39
|
+
private fun isLocalFileUri() = parsedUri?.scheme?.startsWith("file") ?: false
|
|
40
|
+
|
|
41
|
+
private fun isSvg() = parsedUri?.toString()?.substring(parsedUri.toString().lastIndexOf('.'))?.startsWith(".svg") ?: false
|
|
42
|
+
|
|
43
|
+
fun isBlurhash() = parsedUri?.scheme?.startsWith("blurhash") ?: false
|
|
44
|
+
|
|
45
|
+
fun isThumbhash() = parsedUri?.scheme?.startsWith("thumbhash") ?: false
|
|
46
|
+
|
|
47
|
+
internal fun createGlideModel(context: Context): GlideModel? {
|
|
48
|
+
if (uri.isNullOrBlank()) {
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (parsedUri == null) {
|
|
53
|
+
parsedUri = computeUri(context)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (isContentUrl() || isDataUrl()) {
|
|
57
|
+
return GlideRawModel(uri)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (isBlurhash()) {
|
|
61
|
+
return GlideBlurhashModel(
|
|
62
|
+
parsedUri!!,
|
|
63
|
+
width,
|
|
64
|
+
height
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (isThumbhash()) {
|
|
69
|
+
return GlideThumbhashModel(
|
|
70
|
+
parsedUri!!
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (isResourceUri()) {
|
|
75
|
+
return GlideUriModel(parsedUri!!)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (isLocalResourceUri()) {
|
|
79
|
+
return GlideUriModel(
|
|
80
|
+
// Convert `res:/` scheme to `android.resource://`.
|
|
81
|
+
// Otherwise, glide can't understand the Uri.
|
|
82
|
+
Uri.parse(parsedUri!!.toString().replace("res:/", "android.resource://" + context.packageName + "/"))
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (isLocalFileUri()) {
|
|
87
|
+
return GlideRawModel(parsedUri!!.toString())
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
val glideUrl = if (cacheKey == null) {
|
|
91
|
+
GlideUrl(uri, getCustomHeaders())
|
|
92
|
+
} else {
|
|
93
|
+
GlideUrlWithCustomCacheKey(uri, getCustomHeaders(), cacheKey)
|
|
94
|
+
}
|
|
95
|
+
return GlideUrlModel(glideUrl)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
internal fun createOptions(context: Context): RequestOptions {
|
|
99
|
+
return RequestOptions()
|
|
100
|
+
.apply {
|
|
101
|
+
if (parsedUri == null) {
|
|
102
|
+
parsedUri = computeUri(context)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Override the size for local assets (apart from SVGs). This ensures that
|
|
106
|
+
// resizeMode "center" displays the image in the correct size.
|
|
107
|
+
if (width != 0 && height != 0 && !isSvg()) {
|
|
108
|
+
override((width * scale).toInt(), (height * scale).toInt())
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (isResourceUri()) {
|
|
112
|
+
// Every local resource (drawable) in Android has its own unique numeric id, which are
|
|
113
|
+
// generated at build time. Although these ids are unique, they are not guaranteed unique
|
|
114
|
+
// across builds. The underlying glide implementation caches these resources. To make
|
|
115
|
+
// sure the cache does not return the wrong image, we should clear the cache when the
|
|
116
|
+
// application version changes.
|
|
117
|
+
apply(
|
|
118
|
+
RequestOptions.signatureOf(ApplicationVersionSignature.obtain(context))
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private fun getCustomHeaders(): Headers {
|
|
125
|
+
if (headers == null) {
|
|
126
|
+
return LazyHeaders.DEFAULT
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return LazyHeaders
|
|
130
|
+
.Builder()
|
|
131
|
+
.apply {
|
|
132
|
+
headers.forEach { (key, value) ->
|
|
133
|
+
addHeader(key, value)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
.build()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private fun computeUri(context: Context): Uri? {
|
|
140
|
+
val stringUri = uri ?: return null
|
|
141
|
+
return try {
|
|
142
|
+
val uri: Uri = Uri.parse(stringUri)
|
|
143
|
+
// Verify scheme is set, so that relative uri (used by static resources) are not handled.
|
|
144
|
+
if (uri.scheme == null) {
|
|
145
|
+
computeLocalUri(stringUri, context)
|
|
146
|
+
} else {
|
|
147
|
+
uri
|
|
148
|
+
}
|
|
149
|
+
} catch (e: Exception) {
|
|
150
|
+
computeLocalUri(stringUri, context)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private fun computeLocalUri(stringUri: String, context: Context): Uri? {
|
|
155
|
+
return ResourceIdHelper.getResourceUri(context, stringUri)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
internal val pixelCount: Double
|
|
159
|
+
get() = width * height * scale * scale
|
|
160
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package expo.modules.image.records
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.records.Field
|
|
4
|
+
import expo.modules.kotlin.records.Record
|
|
5
|
+
|
|
6
|
+
data class ImageSource(
|
|
7
|
+
@Field val url: String,
|
|
8
|
+
@Field val width: Int,
|
|
9
|
+
@Field val height: Int,
|
|
10
|
+
@Field val mediaType: String?
|
|
11
|
+
) : Record
|
|
12
|
+
|
|
13
|
+
data class ImageLoadEvent(
|
|
14
|
+
@Field val cacheType: String,
|
|
15
|
+
@Field val source: ImageSource
|
|
16
|
+
) : Record
|
|
17
|
+
|
|
18
|
+
data class ImageProgressEvent(
|
|
19
|
+
@Field val loaded: Int,
|
|
20
|
+
@Field val total: Int
|
|
21
|
+
) : Record
|
|
22
|
+
|
|
23
|
+
data class ImageErrorEvent(
|
|
24
|
+
@Field val error: String
|
|
25
|
+
) : Record
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package expo.modules.image.svg
|
|
2
|
+
|
|
3
|
+
import com.bumptech.glide.load.Options
|
|
4
|
+
import com.bumptech.glide.load.ResourceDecoder
|
|
5
|
+
import com.bumptech.glide.load.engine.Resource
|
|
6
|
+
import com.bumptech.glide.load.resource.SimpleResource
|
|
7
|
+
import com.caverock.androidsvg.SVG
|
|
8
|
+
import com.caverock.androidsvg.SVGParseException
|
|
9
|
+
import java.io.IOException
|
|
10
|
+
import java.io.InputStream
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Decodes an SVG internal representation from an [InputStream].
|
|
14
|
+
*
|
|
15
|
+
* Copied from https://github.com/bumptech/glide/blob/10acc31a16b4c1b5684f69e8de3117371dfa77a8/samples/svg/src/main/java/com/bumptech/glide/samples/svg/SvgDecoder.java
|
|
16
|
+
* and rewritten to Kotlin.
|
|
17
|
+
*/
|
|
18
|
+
class SVGDecoder : ResourceDecoder<InputStream, SVG> {
|
|
19
|
+
// TODO: Can we tell?
|
|
20
|
+
override fun handles(source: InputStream, options: Options) = true
|
|
21
|
+
|
|
22
|
+
@Throws(IOException::class)
|
|
23
|
+
override fun decode(source: InputStream, width: Int, height: Int, options: Options): Resource<SVG>? {
|
|
24
|
+
return try {
|
|
25
|
+
val svg: SVG = SVG.getFromInputStream(source)
|
|
26
|
+
svg.documentWidth = width.toFloat()
|
|
27
|
+
svg.documentHeight = height.toFloat()
|
|
28
|
+
SimpleResource(svg)
|
|
29
|
+
} catch (ex: SVGParseException) {
|
|
30
|
+
throw IOException("Cannot load SVG from stream", ex)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
package expo.modules.image.svg
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import android.graphics.Canvas
|
|
6
|
+
import android.graphics.Picture
|
|
7
|
+
import android.graphics.drawable.BitmapDrawable
|
|
8
|
+
import android.graphics.drawable.Drawable
|
|
9
|
+
import android.graphics.drawable.PictureDrawable
|
|
10
|
+
import com.bumptech.glide.load.Options
|
|
11
|
+
import com.bumptech.glide.load.engine.Resource
|
|
12
|
+
import com.bumptech.glide.load.resource.SimpleResource
|
|
13
|
+
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder
|
|
14
|
+
import com.caverock.androidsvg.SVG
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Convert the [SVG]'s internal representation to an Android-compatible one ([Picture]).
|
|
18
|
+
*
|
|
19
|
+
* Copied from https://github.com/bumptech/glide/blob/10acc31a16b4c1b5684f69e8de3117371dfa77a8/samples/svg/src/main/java/com/bumptech/glide/samples/svg/SvgDrawableTranscoder.java
|
|
20
|
+
* and rewritten to Kotlin.
|
|
21
|
+
*/
|
|
22
|
+
class SVGDrawableTranscoder(val context: Context) : ResourceTranscoder<SVG?, Drawable> {
|
|
23
|
+
override fun transcode(toTranscode: Resource<SVG?>, options: Options): Resource<Drawable> {
|
|
24
|
+
val picture = toTranscode.get().renderToPicture()
|
|
25
|
+
val drawable = PictureDrawable(picture)
|
|
26
|
+
val width = drawable.intrinsicWidth
|
|
27
|
+
val height = drawable.intrinsicHeight
|
|
28
|
+
|
|
29
|
+
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
30
|
+
val canvas = Canvas(bitmap)
|
|
31
|
+
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
|
32
|
+
drawable.draw(canvas)
|
|
33
|
+
|
|
34
|
+
val newDrawable = BitmapDrawable(context.resources, bitmap)
|
|
35
|
+
return SimpleResource(newDrawable)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package expo.modules.image.svg
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.drawable.Drawable
|
|
5
|
+
import com.bumptech.glide.Glide
|
|
6
|
+
import com.bumptech.glide.Registry
|
|
7
|
+
import com.bumptech.glide.annotation.GlideModule
|
|
8
|
+
import com.bumptech.glide.module.LibraryGlideModule
|
|
9
|
+
import com.caverock.androidsvg.SVG
|
|
10
|
+
import java.io.InputStream
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* [LibraryGlideModule] registering support for SVG to Glide.
|
|
14
|
+
*
|
|
15
|
+
* Copied from https://github.com/bumptech/glide/blob/10acc31a16b4c1b5684f69e8de3117371dfa77a8/samples/svg/src/main/java/com/bumptech/glide/samples/svg/SvgModule.java
|
|
16
|
+
* and rewritten to Kotlin.
|
|
17
|
+
*/
|
|
18
|
+
@GlideModule
|
|
19
|
+
class SVGModule : LibraryGlideModule() {
|
|
20
|
+
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
|
|
21
|
+
super.registerComponents(context, glide, registry)
|
|
22
|
+
registry
|
|
23
|
+
.append(InputStream::class.java, SVG::class.java, SVGDecoder())
|
|
24
|
+
.register(SVG::class.java, Drawable::class.java, SVGDrawableTranscoder(context))
|
|
25
|
+
}
|
|
26
|
+
}
|