1
+ /*
2
+ * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3
+ * This product includes software developed at Datadog (https://www.datadoghq.com/).
4
+ * Copyright 2016-Present Datadog, Inc.
5
+ */
6
+
7
+ package com.datadog.reactnative.sessionreplay.extensions
8
+
9
+ import android.content.res.Resources
10
+ import android.graphics.Bitmap
11
+ import android.graphics.drawable.BitmapDrawable
12
+ import android.graphics.drawable.Drawable
13
+ import android.graphics.drawable.ShapeDrawable
14
+ import android.graphics.drawable.VectorDrawable
15
+ import android.widget.ImageView
16
+ import androidx.appcompat.graphics.drawable.DrawerArrowDrawable
17
+ import androidx.core.graphics.drawable.toBitmapOrNull
18
+ import com.facebook.drawee.drawable.ArrayDrawable
19
+ import com.facebook.drawee.drawable.ForwardingDrawable
20
+ import com.facebook.drawee.drawable.RoundedBitmapDrawable
21
+ import com.facebook.drawee.drawable.ScaleTypeDrawable
22
+ import com.facebook.drawee.drawable.ScalingUtils
23
+
24
+ internal fun ScaleTypeDrawable.imageViewScaleType (): ImageView .ScaleType ? {
25
+ return when (this .scaleType) {
26
+ ScalingUtils .ScaleType .CENTER -> ImageView .ScaleType .CENTER
27
+ ScalingUtils .ScaleType .CENTER_CROP -> ImageView .ScaleType .CENTER_CROP
28
+ ScalingUtils .ScaleType .CENTER_INSIDE -> ImageView .ScaleType .CENTER_INSIDE
29
+ ScalingUtils .ScaleType .FIT_CENTER -> ImageView .ScaleType .FIT_CENTER
30
+ ScalingUtils .ScaleType .FIT_START -> ImageView .ScaleType .FIT_START
31
+ ScalingUtils .ScaleType .FIT_END -> ImageView .ScaleType .FIT_END
32
+ ScalingUtils .ScaleType .FIT_XY -> ImageView .ScaleType .FIT_XY
33
+ else -> null
34
+ }
35
+ }
36
+
37
+ internal fun ArrayDrawable.getScaleTypeDrawable (): ScaleTypeDrawable ? {
38
+ for (i in 0 until this .numberOfLayers) {
39
+ try {
40
+ (this .getDrawable(i) as ? ScaleTypeDrawable )?.let {
41
+ return it
42
+ }
43
+ } catch (_: IllegalArgumentException ) { }
44
+ }
45
+
46
+ return null
47
+ }
48
+
49
+ internal fun ArrayDrawable.getDrawableOrNull (index : Int ): Drawable ? {
50
+ return try {
51
+ this .getDrawable(index)
52
+ } catch (_: IllegalArgumentException ) {
53
+ null
54
+ }
55
+ }
56
+
57
+ internal fun ForwardingDrawable.tryToExtractBitmap (resources : Resources ): Bitmap ? {
58
+ val forwardedDrawable = this .drawable
59
+ return if (forwardedDrawable != null ) {
60
+ forwardedDrawable.tryToExtractBitmap(resources)
61
+ } else {
62
+ this .toBitmapOrNull(
63
+ this .intrinsicWidth,
64
+ this .intrinsicHeight,
65
+ Bitmap .Config .ARGB_8888
66
+ )
67
+ }
68
+ }
69
+
70
+ internal fun RoundedBitmapDrawable.tryToExtractBitmap (): Bitmap ? {
71
+ val privateBitmap = try {
72
+ val field = RoundedBitmapDrawable ::class .java.getDeclaredField(" mBitmap" )
73
+ field.isAccessible = true
74
+ field.get(this ) as ? Bitmap
75
+ } catch (_: NoSuchFieldException ) {
76
+ null
77
+ } catch (_: IllegalAccessException ) {
78
+ null
79
+ } catch (_: Exception ) {
80
+ null
81
+ }
82
+
83
+ return privateBitmap ? : this .toBitmapOrNull(
84
+ this .intrinsicWidth,
85
+ this .intrinsicHeight,
86
+ Bitmap .Config .ARGB_8888
87
+ )
88
+ }
89
+
90
+ internal fun BitmapDrawable.tryToExtractBitmap (resources : Resources ): Bitmap ? {
91
+ if (this .bitmap != null ) {
92
+ return this .bitmap
93
+ }
94
+
95
+ if (this .constantState != null ) {
96
+ val copy = this .constantState?.newDrawable(resources)
97
+ return (copy as ? BitmapDrawable )?.bitmap ? : copy?.toBitmapOrNull(
98
+ this .intrinsicWidth,
99
+ this .intrinsicHeight,
100
+ Bitmap .Config .ARGB_8888
101
+ )
102
+ }
103
+
104
+ return null
105
+ }
106
+
107
+ internal fun ArrayDrawable.tryToExtractBitmap (resources : Resources ): Bitmap ? {
108
+ var width = 0
109
+ var height = 0
110
+ for (index in 0 until this .numberOfLayers) {
111
+ val drawable = this .getDrawableOrNull(index) ? : continue
112
+
113
+ if (drawable is ScaleTypeDrawable ) {
114
+ return drawable.tryToExtractBitmap(resources)
115
+ }
116
+
117
+ if (drawable.intrinsicWidth * drawable.intrinsicHeight > width * height) {
118
+ width = drawable.intrinsicWidth
119
+ height = drawable.intrinsicHeight
120
+ }
121
+ }
122
+
123
+ return if (width > 0 && height > 0 )
124
+ this .toBitmapOrNull(width, height, Bitmap .Config .ARGB_8888 )
125
+ else
126
+ null
127
+ }
128
+
129
+ internal fun Drawable.tryToExtractBitmap (
130
+ resources : Resources
131
+ ): Bitmap ? {
132
+ when (this ) {
133
+ is ArrayDrawable -> {
134
+ return this .tryToExtractBitmap(resources)
135
+ }
136
+ is ForwardingDrawable -> {
137
+ return this .tryToExtractBitmap(resources)
138
+ }
139
+ is RoundedBitmapDrawable -> {
140
+ return this .tryToExtractBitmap()
141
+ }
142
+ is BitmapDrawable -> {
143
+ return this .tryToExtractBitmap(resources)
144
+ }
145
+ is VectorDrawable , is ShapeDrawable , is DrawerArrowDrawable -> {
146
+ return this .toBitmapOrNull(
147
+ this .intrinsicWidth,
148
+ this .intrinsicHeight,
149
+ Bitmap .Config .ARGB_8888
150
+ )
151
+ }
152
+ else -> return null
153
+ }
154
+ }
0 commit comments