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