1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.O; 4 import static android.os.Build.VERSION_CODES.O_MR1; 5 import static android.os.Build.VERSION_CODES.P; 6 import static android.os.Build.VERSION_CODES.Q; 7 import static android.os.Build.VERSION_CODES.R; 8 import static android.os.Build.VERSION_CODES.S; 9 10 import android.graphics.Bitmap; 11 import android.graphics.Canvas; 12 import android.graphics.Rect; 13 import org.robolectric.annotation.Implementation; 14 import org.robolectric.annotation.Implements; 15 import org.robolectric.nativeruntime.CanvasNatives; 16 import org.robolectric.nativeruntime.DefaultNativeRuntimeLoader; 17 import org.robolectric.nativeruntime.HardwareRendererNatives; 18 import org.robolectric.versioning.AndroidVersions.U; 19 20 /** Shadow for {@link Canvas} that is backed by native code */ 21 @Implements( 22 value = Canvas.class, 23 minSdk = O, 24 isInAndroidSdk = false, 25 callNativeMethodsByDefault = true) 26 public class ShadowNativeCanvas extends ShadowNativeBaseCanvas { 27 28 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nFreeCaches()29 protected static void nFreeCaches() { 30 CanvasNatives.nFreeCaches(); 31 } 32 33 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nFreeTextLayoutCaches()34 protected static void nFreeTextLayoutCaches() { 35 CanvasNatives.nFreeTextLayoutCaches(); 36 } 37 38 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nGetNativeFinalizer()39 protected static long nGetNativeFinalizer() { 40 return CanvasNatives.nGetNativeFinalizer(); 41 } 42 43 @Implementation(minSdk = P, maxSdk = U.SDK_INT) nSetCompatibilityVersion(int apiLevel)44 protected static void nSetCompatibilityVersion(int apiLevel) { 45 CanvasNatives.nSetCompatibilityVersion(apiLevel); 46 } 47 48 @Implementation(minSdk = O, maxSdk = P) nInitRaster(Bitmap bitmap)49 protected static long nInitRaster(Bitmap bitmap) { 50 return nInitRaster(bitmap != null ? bitmap.getNativeInstance() : 0); 51 } 52 53 @Implementation(minSdk = Q, maxSdk = U.SDK_INT) nInitRaster(long bitmapHandle)54 protected static long nInitRaster(long bitmapHandle) { 55 DefaultNativeRuntimeLoader.injectAndLoad(); 56 return CanvasNatives.nInitRaster(bitmapHandle); 57 } 58 59 @Implementation(minSdk = O, maxSdk = P) nSetBitmap(long canvasHandle, Bitmap bitmap)60 protected static void nSetBitmap(long canvasHandle, Bitmap bitmap) { 61 CanvasNatives.nSetBitmap(canvasHandle, bitmap != null ? bitmap.getNativeInstance() : 0); 62 } 63 64 @Implementation(minSdk = Q, maxSdk = U.SDK_INT) nSetBitmap(long canvasHandle, long bitmapHandle)65 protected static void nSetBitmap(long canvasHandle, long bitmapHandle) { 66 CanvasNatives.nSetBitmap(canvasHandle, bitmapHandle); 67 } 68 69 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nGetClipBounds(long nativeCanvas, Rect bounds)70 protected static boolean nGetClipBounds(long nativeCanvas, Rect bounds) { 71 return CanvasNatives.nGetClipBounds(nativeCanvas, bounds); 72 } 73 74 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nIsOpaque(long canvasHandle)75 protected static boolean nIsOpaque(long canvasHandle) { 76 return CanvasNatives.nIsOpaque(canvasHandle); 77 } 78 79 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nGetWidth(long canvasHandle)80 protected static int nGetWidth(long canvasHandle) { 81 return CanvasNatives.nGetWidth(canvasHandle); 82 } 83 84 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nGetHeight(long canvasHandle)85 protected static int nGetHeight(long canvasHandle) { 86 return CanvasNatives.nGetHeight(canvasHandle); 87 } 88 89 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nSave(long canvasHandle, int saveFlags)90 protected static int nSave(long canvasHandle, int saveFlags) { 91 return CanvasNatives.nSave(canvasHandle, saveFlags); 92 } 93 94 @Implementation(minSdk = S, maxSdk = U.SDK_INT) nSaveLayer( long nativeCanvas, float l, float t, float r, float b, long nativePaint)95 protected static int nSaveLayer( 96 long nativeCanvas, float l, float t, float r, float b, long nativePaint) { 97 return CanvasNatives.nSaveLayer(nativeCanvas, l, t, r, b, nativePaint); 98 } 99 100 @Implementation(minSdk = O, maxSdk = R) nSaveLayer( long nativeCanvas, float l, float t, float r, float b, long nativePaint, int layerFlags)101 protected static int nSaveLayer( 102 long nativeCanvas, float l, float t, float r, float b, long nativePaint, int layerFlags) { 103 return nSaveLayer(nativeCanvas, l, t, r, b, nativePaint); 104 } 105 106 @Implementation(minSdk = S, maxSdk = U.SDK_INT) nSaveLayerAlpha( long nativeCanvas, float l, float t, float r, float b, int alpha)107 protected static int nSaveLayerAlpha( 108 long nativeCanvas, float l, float t, float r, float b, int alpha) { 109 return CanvasNatives.nSaveLayerAlpha(nativeCanvas, l, t, r, b, alpha); 110 } 111 112 @Implementation(minSdk = O, maxSdk = R) nSaveLayerAlpha( long nativeCanvas, float l, float t, float r, float b, int alpha, int layerFlags)113 protected static int nSaveLayerAlpha( 114 long nativeCanvas, float l, float t, float r, float b, int alpha, int layerFlags) { 115 return nSaveLayerAlpha(nativeCanvas, l, t, r, b, alpha); 116 } 117 118 @Implementation(minSdk = Q, maxSdk = U.SDK_INT) nSaveUnclippedLayer(long nativeCanvas, int l, int t, int r, int b)119 protected static int nSaveUnclippedLayer(long nativeCanvas, int l, int t, int r, int b) { 120 return CanvasNatives.nSaveUnclippedLayer(nativeCanvas, l, t, r, b); 121 } 122 123 @Implementation(minSdk = Q, maxSdk = U.SDK_INT) nRestoreUnclippedLayer(long nativeCanvas, int saveCount, long nativePaint)124 protected static void nRestoreUnclippedLayer(long nativeCanvas, int saveCount, long nativePaint) { 125 CanvasNatives.nRestoreUnclippedLayer(nativeCanvas, saveCount, nativePaint); 126 } 127 128 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nRestore(long canvasHandle)129 protected static boolean nRestore(long canvasHandle) { 130 return CanvasNatives.nRestore(canvasHandle); 131 } 132 133 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nRestoreToCount(long canvasHandle, int saveCount)134 protected static void nRestoreToCount(long canvasHandle, int saveCount) { 135 CanvasNatives.nRestoreToCount(canvasHandle, saveCount); 136 } 137 138 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nGetSaveCount(long canvasHandle)139 protected static int nGetSaveCount(long canvasHandle) { 140 return CanvasNatives.nGetSaveCount(canvasHandle); 141 } 142 143 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nTranslate(long canvasHandle, float dx, float dy)144 protected static void nTranslate(long canvasHandle, float dx, float dy) { 145 CanvasNatives.nTranslate(canvasHandle, dx, dy); 146 } 147 148 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nScale(long canvasHandle, float sx, float sy)149 protected static void nScale(long canvasHandle, float sx, float sy) { 150 CanvasNatives.nScale(canvasHandle, sx, sy); 151 } 152 153 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nRotate(long canvasHandle, float degrees)154 protected static void nRotate(long canvasHandle, float degrees) { 155 CanvasNatives.nRotate(canvasHandle, degrees); 156 } 157 158 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nSkew(long canvasHandle, float sx, float sy)159 protected static void nSkew(long canvasHandle, float sx, float sy) { 160 CanvasNatives.nSkew(canvasHandle, sx, sy); 161 } 162 163 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nConcat(long nativeCanvas, long nativeMatrix)164 protected static void nConcat(long nativeCanvas, long nativeMatrix) { 165 CanvasNatives.nConcat(nativeCanvas, nativeMatrix); 166 } 167 168 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nSetMatrix(long nativeCanvas, long nativeMatrix)169 protected static void nSetMatrix(long nativeCanvas, long nativeMatrix) { 170 CanvasNatives.nSetMatrix(nativeCanvas, nativeMatrix); 171 } 172 173 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nClipRect( long nativeCanvas, float left, float top, float right, float bottom, int regionOp)174 protected static boolean nClipRect( 175 long nativeCanvas, float left, float top, float right, float bottom, int regionOp) { 176 return CanvasNatives.nClipRect(nativeCanvas, left, top, right, bottom, regionOp); 177 } 178 179 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nClipPath(long nativeCanvas, long nativePath, int regionOp)180 protected static boolean nClipPath(long nativeCanvas, long nativePath, int regionOp) { 181 return CanvasNatives.nClipPath(nativeCanvas, nativePath, regionOp); 182 } 183 184 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nSetDrawFilter(long nativeCanvas, long nativeFilter)185 protected static void nSetDrawFilter(long nativeCanvas, long nativeFilter) { 186 CanvasNatives.nSetDrawFilter(nativeCanvas, nativeFilter); 187 } 188 189 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nGetMatrix(long nativeCanvas, long nativeMatrix)190 protected static void nGetMatrix(long nativeCanvas, long nativeMatrix) { 191 CanvasNatives.nGetMatrix(nativeCanvas, nativeMatrix); 192 } 193 194 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nQuickReject(long nativeCanvas, long nativePath)195 protected static boolean nQuickReject(long nativeCanvas, long nativePath) { 196 return CanvasNatives.nQuickReject(nativeCanvas, nativePath); 197 } 198 199 @Implementation(minSdk = O, maxSdk = U.SDK_INT) nQuickReject( long nativeCanvas, float left, float top, float right, float bottom)200 protected static boolean nQuickReject( 201 long nativeCanvas, float left, float top, float right, float bottom) { 202 return CanvasNatives.nQuickReject(nativeCanvas, left, top, right, bottom); 203 } 204 205 @Implementation(minSdk = O, maxSdk = O_MR1) nSetHighContrastText(long renderer, boolean highContrastText)206 protected static void nSetHighContrastText(long renderer, boolean highContrastText) { 207 HardwareRendererNatives.nSetHighContrastText(highContrastText); 208 } 209 210 /** 211 * In Android P and below, Canvas.saveUnclippedLayer called {@link 212 * ShadowNativeCanvas#nSaveLayer(long, float, float, float, float, long)}. 213 * 214 * <p>However, in Android Q, a new native method was added specifically to save unclipped layers. 215 * Use this new method to fix things like ScrollView fade effects in P and below. 216 */ 217 @Implementation(minSdk = P, maxSdk = P) saveUnclippedLayer(int left, int top, int right, int bottom)218 protected int saveUnclippedLayer(int left, int top, int right, int bottom) { 219 return nSaveUnclippedLayer(getNativeCanvas(), left, top, right, bottom); 220 } 221 } 222