blob: b87a8b0b875f49bc6ca1a30c8b82d65c646a09e8 [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.graphics.cts;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Canvas.EdgeType;
import android.graphics.Canvas.VertexMode;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.DrawFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Picture;
import android.graphics.PorterDuff.Mode;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.graphics.Shader;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.SpannedString;
import android.util.DisplayMetrics;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.ColorUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.InputStream;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class CanvasTest {
private final static int PAINT_COLOR = 0xff00ff00;
private final static int BITMAP_WIDTH = 10;
private final static int BITMAP_HEIGHT = 28;
private final static int FLOAT_ARRAY_LEN = 9;
// used for save related methods tests
private final float[] values1 = {
1, 2, 3, 4, 5, 6, 7, 8, 9
};
private final float[] values2 = {
9, 8, 7, 6, 5, 4, 3, 2, 1
};
private Paint mPaint;
private Canvas mCanvas;
private Bitmap mImmutableBitmap;
private Bitmap mMutableBitmap;
@Before
public void setup() {
mPaint = new Paint();
mPaint.setColor(PAINT_COLOR);
final Resources res = InstrumentationRegistry.getTargetContext().getResources();
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inScaled = false; // bitmap will only be immutable if not scaled during load
mImmutableBitmap = BitmapFactory.decodeResource(res, R.drawable.start, opt);
assertFalse(mImmutableBitmap.isMutable());
mMutableBitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
mCanvas = new Canvas(mMutableBitmap);
}
@Test
public void testCanvas() {
new Canvas();
mMutableBitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
new Canvas(mMutableBitmap);
}
@Test(expected=IllegalStateException.class)
public void testCanvasFromImmutableBitmap() {
// Should throw out IllegalStateException when creating Canvas with an ImmutableBitmap
new Canvas(mImmutableBitmap);
}
@Test(expected=RuntimeException.class)
public void testCanvasFromRecycledBitmap() {
// Should throw out RuntimeException when creating Canvas with a MutableBitmap which
// is recycled
mMutableBitmap.recycle();
new Canvas(mMutableBitmap);
}
@Test(expected=IllegalStateException.class)
public void testSetBitmapToImmutableBitmap() {
// Should throw out IllegalStateException when setting an ImmutableBitmap to a Canvas
mCanvas.setBitmap(mImmutableBitmap);
}
@Test(expected=RuntimeException.class)
public void testSetBitmapToRecycledBitmap() {
// Should throw out RuntimeException when setting Bitmap which is recycled to a Canvas
mMutableBitmap.recycle();
mCanvas.setBitmap(mMutableBitmap);
}
@Test
public void testSetBitmap() {
mMutableBitmap = Bitmap.createBitmap(BITMAP_WIDTH, 31, Config.ARGB_8888);
mCanvas.setBitmap(mMutableBitmap);
assertEquals(BITMAP_WIDTH, mCanvas.getWidth());
assertEquals(31, mCanvas.getHeight());
}
@Test
public void testSetBitmapFromEmpty() {
Canvas canvas = new Canvas();
assertEquals(0, canvas.getWidth());
assertEquals(0, canvas.getHeight());
// now ensure that we can "grow" the canvas
Bitmap normal = Bitmap.createBitmap(10, 10, Config.ARGB_8888);
canvas.setBitmap(normal);
assertEquals(10, canvas.getWidth());
assertEquals(10, canvas.getHeight());
// now draw, and check that the clip was "open"
canvas.drawColor(0xFFFF0000);
assertEquals(0xFFFF0000, normal.getPixel(5, 5));
}
@Test
public void testSetBitmapCleanClip() {
mCanvas.setBitmap(Bitmap.createBitmap(10, 10, Config.ARGB_8888));
Rect r = new Rect(2, 2, 8, 8);
mCanvas.save();
mCanvas.clipRect(r);
assertEquals(r, mCanvas.getClipBounds());
// "reset" the canvas, and then check that the clip is wide open
// and not the previous value
mCanvas.setBitmap(Bitmap.createBitmap(20, 20, Config.ARGB_8888));
r = new Rect(0, 0, 20, 20);
assertEquals(r, mCanvas.getClipBounds());
}
@Test
public void testSetBitmapSaveCount() {
Canvas c = new Canvas(Bitmap.createBitmap(10, 10, Config.ARGB_8888));
int initialSaveCount = c.getSaveCount();
c.save();
assertEquals(c.getSaveCount(), initialSaveCount + 1);
// setBitmap should restore the saveCount to its original/base value
c.setBitmap(Bitmap.createBitmap(10, 10, Config.ARGB_8888));
assertEquals(c.getSaveCount(), initialSaveCount);
}
@Test
public void testIsOpaque() {
assertFalse(mCanvas.isOpaque());
}
@Test(expected=IllegalStateException.class)
public void testRestoreWithoutSave() {
// Should throw out IllegalStateException because cannot restore Canvas before save
mCanvas.restore();
}
@Test
public void testRestore() {
mCanvas.save();
mCanvas.restore();
}
@Test
public void testSave() {
final Matrix m1 = new Matrix();
m1.setValues(values1);
mCanvas.setMatrix(m1);
mCanvas.save();
final Matrix m2 = new Matrix();
m2.setValues(values2);
mCanvas.setMatrix(m2);
final float[] values3 = new float[FLOAT_ARRAY_LEN];
final Matrix m3 = mCanvas.getMatrix();
m3.getValues(values3);
assertArrayEquals(values2, values3, 0.0f);
mCanvas.restore();
final float[] values4 = new float[FLOAT_ARRAY_LEN];
final Matrix m4 = mCanvas.getMatrix();
m4.getValues(values4);
assertArrayEquals(values1, values4, 0.0f);
}
@Test
public void testSaveLayer1() {
final Paint p = new Paint();
final RectF rF = new RectF(0, 10, 31, 0);
// test save everything
Matrix m1 = new Matrix();
m1.setValues(values1);
mCanvas.setMatrix(m1);
mCanvas.saveLayer(rF, p);
Matrix m2 = new Matrix();
m2.setValues(values2);
mCanvas.setMatrix(m2);
float[] values3 = new float[FLOAT_ARRAY_LEN];
Matrix m3 = mCanvas.getMatrix();
m3.getValues(values3);
assertArrayEquals(values2, values3, 0.0f);
mCanvas.restore();
float[] values4 = new float[FLOAT_ARRAY_LEN];
Matrix m4 = mCanvas.getMatrix();
m4.getValues(values4);
assertArrayEquals(values1, values4, 0.0f);
}
@Test
public void testSaveLayer2() {
final Paint p = new Paint();
// test save everything
Matrix m1 = new Matrix();
m1.setValues(values1);
mCanvas.setMatrix(m1);
mCanvas.saveLayer(10, 0, 0, 31, p);
Matrix m2 = new Matrix();
m2.setValues(values2);
mCanvas.setMatrix(m2);
float[] values3 = new float[FLOAT_ARRAY_LEN];
Matrix m3 = mCanvas.getMatrix();
m3.getValues(values3);
assertArrayEquals(values2, values3, 0.0f);
mCanvas.restore();
float[] values4 = new float[FLOAT_ARRAY_LEN];
Matrix m4 = mCanvas.getMatrix();
m4.getValues(values4);
assertArrayEquals(values1, values4, 0.0f);
}
@Test
public void testSaveLayerAlpha1() {
final RectF rF = new RectF(0, 10, 31, 0);
// test save everything
Matrix m1 = new Matrix();
m1.setValues(values1);
mCanvas.setMatrix(m1);
mCanvas.saveLayerAlpha(rF, 0xff);
Matrix m2 = new Matrix();
m2.setValues(values2);
mCanvas.setMatrix(m2);
float[] values3 = new float[FLOAT_ARRAY_LEN];
Matrix m3 = mCanvas.getMatrix();
m3.getValues(values3);
assertArrayEquals(values2, values3, 0.0f);
mCanvas.restore();
float[] values4 = new float[FLOAT_ARRAY_LEN];
Matrix m4 = mCanvas.getMatrix();
m4.getValues(values4);
assertArrayEquals(values1, values4, 0.0f);
}
@Test
public void testSaveLayerAlpha2() {
// test save everything
Matrix m1 = new Matrix();
m1.setValues(values1);
mCanvas.setMatrix(m1);
mCanvas.saveLayerAlpha(0, 10, 31, 0, 0xff);
Matrix m2 = new Matrix();
m2.setValues(values2);
mCanvas.setMatrix(m2);
float[] values3 = new float[FLOAT_ARRAY_LEN];
Matrix m3 = mCanvas.getMatrix();
m3.getValues(values3);
assertArrayEquals(values2, values3, 0.0f);
mCanvas.restore();
float[] values4 = new float[FLOAT_ARRAY_LEN];
Matrix m4 = mCanvas.getMatrix();
m4.getValues(values4);
assertArrayEquals(values1, values4, 0.0f);
}
@Test
public void testGetSaveCount() {
// why is 1 not 0
assertEquals(1, mCanvas.getSaveCount());
mCanvas.save();
assertEquals(2, mCanvas.getSaveCount());
mCanvas.save();
assertEquals(3, mCanvas.getSaveCount());
mCanvas.saveLayer(new RectF(), new Paint());
assertEquals(4, mCanvas.getSaveCount());
mCanvas.saveLayerAlpha(new RectF(), 0);
assertEquals(5, mCanvas.getSaveCount());
}
@Test(expected=IllegalArgumentException.class)
public void testRestoreToCountIllegalSaveCount() {
// Should throw out IllegalArgumentException because saveCount is less than 1
mCanvas.restoreToCount(0);
}
@Test
public void testRestoreToCountExceptionBehavior() {
int restoreTo = mCanvas.save();
mCanvas.save();
int beforeCount = mCanvas.getSaveCount();
boolean exceptionObserved = false;
try {
mCanvas.restoreToCount(restoreTo - 1);
} catch (IllegalArgumentException e) {
exceptionObserved = true;
}
// restore to count threw, AND did no restoring
assertTrue(exceptionObserved);
assertEquals(beforeCount, mCanvas.getSaveCount());
}
@Test
public void testRestoreToCount() {
final Matrix m1 = new Matrix();
m1.setValues(values1);
mCanvas.setMatrix(m1);
final int count = mCanvas.save();
assertTrue(count > 0);
final Matrix m2 = new Matrix();
m2.setValues(values2);
mCanvas.setMatrix(m2);
final float[] values3 = new float[FLOAT_ARRAY_LEN];
final Matrix m3 = mCanvas.getMatrix();
m3.getValues(values3);
assertArrayEquals(values2, values3, 0.0f);
mCanvas.restoreToCount(count);
final float[] values4 = new float[FLOAT_ARRAY_LEN];
final Matrix m4 = mCanvas.getMatrix();
m4.getValues(values4);
assertArrayEquals(values1, values4, 0.0f);
}
@Test
public void testGetMatrix1() {
final float[] f1 = {
1, 2, 3, 4, 5, 6, 7, 8, 9
};
final Matrix m1 = new Matrix();
m1.setValues(f1);
mCanvas.setMatrix(m1);
final Matrix m2 = new Matrix(m1);
mCanvas.getMatrix(m2);
assertTrue(m1.equals(m2));
final float[] f2 = new float[FLOAT_ARRAY_LEN];
m2.getValues(f2);
assertArrayEquals(f1, f2, 0.0f);
}
@Test
public void testGetMatrix2() {
final float[] f1 = {
1, 2, 3, 4, 5, 6, 7, 8, 9
};
final Matrix m1 = new Matrix();
m1.setValues(f1);
mCanvas.setMatrix(m1);
final Matrix m2 = mCanvas.getMatrix();
assertTrue(m1.equals(m2));
final float[] f2 = new float[FLOAT_ARRAY_LEN];
m2.getValues(f2);
assertArrayEquals(f1, f2, 0.0f);
}
@Test
public void testTranslate() {
preCompare();
mCanvas.translate(0.10f, 0.28f);
final float[] values = new float[FLOAT_ARRAY_LEN];
mCanvas.getMatrix().getValues(values);
assertArrayEquals(new float[] {
1.0f, 0.0f, 0.1f, 0.0f, 1.0f, 0.28f, 0.0f, 0.0f, 1.0f
}, values, 0.0f);
}
@Test
public void testScale1() {
preCompare();
mCanvas.scale(0.5f, 0.5f);
final float[] values = new float[FLOAT_ARRAY_LEN];
mCanvas.getMatrix().getValues(values);
assertArrayEquals(new float[] {
0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f
}, values, 0.0f);
}
@Test
public void testScale2() {
preCompare();
mCanvas.scale(3.0f, 3.0f, 1.0f, 1.0f);
final float[] values = new float[FLOAT_ARRAY_LEN];
mCanvas.getMatrix().getValues(values);
assertArrayEquals(new float[] {
3.0f, 0.0f, -2.0f, 0.0f, 3.0f, -2.0f, 0.0f, 0.0f, 1.0f
}, values, 0.0f);
}
@Test
public void testRotate1() {
preCompare();
mCanvas.rotate(90);
final float[] values = new float[FLOAT_ARRAY_LEN];
mCanvas.getMatrix().getValues(values);
assertArrayEquals(new float[] {
0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
}, values, 0.0f);
}
@Test
public void testRotate2() {
preCompare();
mCanvas.rotate(30, 1.0f, 0.0f);
final float[] values = new float[FLOAT_ARRAY_LEN];
mCanvas.getMatrix().getValues(values);
assertArrayEquals(new float[] {
0.8660254f, -0.5f, 0.13397461f, 0.5f, 0.8660254f, -0.5f, 0.0f, 0.0f, 1.0f
}, values, 0.0f);
}
@Test
public void testSkew() {
preCompare();
mCanvas.skew(1.0f, 3.0f);
final float[] values = new float[FLOAT_ARRAY_LEN];
mCanvas.getMatrix().getValues(values);
assertArrayEquals(new float[] {
1.0f, 1.0f, 0.0f, 3.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f
}, values, 0.0f);
}
@Test
public void testConcat() {
preCompare();
final Matrix m = new Matrix();
final float[] values = {0, 1, 2, 3, 4, 5, 6, 7, 8};
m.setValues(values);
mCanvas.concat(m);
mCanvas.getMatrix().getValues(values);
assertArrayEquals(new float[] {
0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f
}, values, 0.0f);
}
@Test
public void testClipRectF() {
mCanvas.save();
// intersect with clip larger than canvas
assertTrue(mCanvas.clipRect(new RectF(0, 0, 10, 31), Op.INTERSECT));
// intersect with clip outside of canvas bounds
assertFalse(mCanvas.clipRect(new RectF(10, 31, 11, 32), Op.INTERSECT));
// replace with the original clip
mCanvas.restore();
// intersect with clip that covers top portion of canvas
assertTrue(mCanvas.clipRect(new RectF(0, 0, 20, 10), Op.INTERSECT));
// intersect with clip that covers bottom portion of canvas
assertFalse(mCanvas.clipRect(new RectF(0, 10, 20, 32), Op.INTERSECT));
// ensure that difference doesn't widen already closed clip
assertFalse(mCanvas.clipRect(new RectF(0, 0, 10, 31), Op.DIFFERENCE));
}
@Test
public void testClipRect() {
mCanvas.save();
// intersect with clip larger than canvas
assertTrue(mCanvas.clipRect(new Rect(0, 0, 10, 31), Op.INTERSECT));
// intersect with clip outside of canvas bounds
assertFalse(mCanvas.clipRect(new Rect(10, 31, 11, 32), Op.INTERSECT));
// replace with the original clip
mCanvas.restore();
// intersect with clip that covers top portion of canvas
assertTrue(mCanvas.clipRect(new Rect(0, 0, 20, 10), Op.INTERSECT));
// intersect with clip that covers bottom portion of canvas
assertFalse(mCanvas.clipRect(new Rect(0, 10, 20, 32), Op.INTERSECT));
// ensure that difference doesn't widen already closed clip
assertFalse(mCanvas.clipRect(new Rect(0, 0, 10, 31), Op.DIFFERENCE));
}
@Test
public void testClipRect4I() {
mCanvas.save();
// intersect with clip larger than canvas
assertTrue(mCanvas.clipRect(0, 0, 10, 31, Op.INTERSECT));
// intersect with clip outside of canvas bounds
assertFalse(mCanvas.clipRect(10, 31, 11, 32, Op.INTERSECT));
// replace with the original clip
mCanvas.restore();
// intersect with clip that covers top portion of canvas
assertTrue(mCanvas.clipRect(0, 0, 20, 10, Op.INTERSECT));
// intersect with clip that covers bottom portion of canvas
assertFalse(mCanvas.clipRect(0, 10, 20, 32, Op.INTERSECT));
// ensure that difference doesn't widen already closed clip
assertFalse(mCanvas.clipRect(0, 0, 10, 31, Op.DIFFERENCE));
}
@Test
public void testClipRect4F() {
mCanvas.save();
// intersect with clip larger than canvas
assertTrue(mCanvas.clipRect(0f, 0f, 10f, 31f, Op.INTERSECT));
// intersect with clip outside of canvas bounds
assertFalse(mCanvas.clipRect(10f, 31f, 11f, 32f, Op.INTERSECT));
// replace with the original clip
mCanvas.restore();
// intersect with clip that covers top portion of canvas
assertTrue(mCanvas.clipRect(0f, 0f, 20f, 10f, Op.INTERSECT));
// intersect with clip that covers bottom portion of canvas
assertFalse(mCanvas.clipRect(0f, 10f, 20f, 32f, Op.INTERSECT));
// ensure that difference doesn't widen already closed clip
assertFalse(mCanvas.clipRect(0f, 0f, 10f, 31f, Op.DIFFERENCE));
}
@Test
public void testClipOutRectF() {
// remove center, clip not empty
assertTrue(mCanvas.clipOutRect(new RectF(1, 1, 9, 27)));
// replace clip, verify difference doesn't widen
assertFalse(mCanvas.clipRect(new RectF(0, 0, 0, 0)));
assertFalse(mCanvas.clipOutRect(new RectF(0, 0, 100, 100)));
}
@Test
public void testClipOutRect() {
// remove center, clip not empty
assertTrue(mCanvas.clipOutRect(new Rect(1, 1, 9, 27)));
// replace clip, verify difference doesn't widen
assertFalse(mCanvas.clipRect(new Rect(0, 0, 0, 0)));
assertFalse(mCanvas.clipOutRect(new Rect(0, 0, 100, 100)));
}
@Test
public void testClipOutRect4I() {
// remove center, clip not empty
assertTrue(mCanvas.clipOutRect(1, 1, 9, 27));
// replace clip, verify difference doesn't widen
assertFalse(mCanvas.clipRect(0, 0, 0, 0));
assertFalse(mCanvas.clipOutRect(0, 0, 100, 100));
}
@Test
public void testClipOutRect4F() {
// remove center, clip not empty
assertTrue(mCanvas.clipOutRect(1f, 1f, 9f, 27f));
// replace clip, verify difference doesn't widen
assertFalse(mCanvas.clipRect(0f, 0f, 0f, 0f));
assertFalse(mCanvas.clipOutRect(0f, 0f, 100f, 100f));
}
@Test
public void testIntersectClipRectF() {
// intersect with clip larger than canvas
assertTrue(mCanvas.clipRect(new RectF(0, 0, 10, 31)));
// intersect with clip outside of canvas bounds
assertFalse(mCanvas.clipRect(new RectF(10, 31, 11, 32)));
}
@Test
public void testIntersectClipRect() {
// intersect with clip larger than canvas
assertTrue(mCanvas.clipRect(new Rect(0, 0, 10, 31)));
// intersect with clip outside of canvas bounds
assertFalse(mCanvas.clipRect(new Rect(10, 31, 11, 32)));
}
@Test
public void testIntersectClipRect4F() {
// intersect with clip larger than canvas
assertTrue(mCanvas.clipRect(0, 0, 10, 31));
// intersect with clip outside of canvas bounds
assertFalse(mCanvas.clipRect(10, 31, 11, 32));
}
@Test
public void testClipPath1() {
final Path p = new Path();
p.addRect(new RectF(0, 0, 10, 31), Direction.CCW);
assertTrue(mCanvas.clipPath(p));
}
@Test
public void testClipPath2() {
final Path p = new Path();
p.addRect(new RectF(0, 0, 10, 31), Direction.CW);
final Path pIn = new Path();
pIn.addOval(new RectF(0, 0, 20, 10), Direction.CW);
final Path pOut = new Path();
pOut.addRoundRect(new RectF(10, 31, 11, 32), 0.5f, 0.5f, Direction.CW);
mCanvas.save();
// intersect with clip larger than canvas
assertTrue(mCanvas.clipPath(p, Op.INTERSECT));
// intersect with clip outside of canvas bounds
assertFalse(mCanvas.clipPath(pOut, Op.INTERSECT));
// replace with the original clip
mCanvas.restore();
// intersect with clip that covers top portion of canvas
assertTrue(mCanvas.clipPath(pIn, Op.INTERSECT));
// intersect with clip outside of canvas bounds
assertFalse(mCanvas.clipPath(pOut, Op.INTERSECT));
// ensure that difference doesn't widen already closed clip
assertFalse(mCanvas.clipPath(p, Op.DIFFERENCE));
}
@Test
public void testClipOutPath() {
final Path p = new Path();
p.addRect(new RectF(5, 5, 10, 10), Direction.CW);
assertTrue(mCanvas.clipOutPath(p));
}
@Test
public void testClipInversePath() {
final Path p = new Path();
p.addRoundRect(new RectF(0, 0, 10, 10), 0.5f, 0.5f, Direction.CW);
p.setFillType(Path.FillType.INVERSE_WINDING);
assertTrue(mCanvas.clipPath(p, Op.INTERSECT));
mCanvas.drawColor(PAINT_COLOR);
assertEquals(Color.TRANSPARENT, mMutableBitmap.getPixel(0, 0));
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 20));
}
@Test
public void testGetDrawFilter() {
assertNull(mCanvas.getDrawFilter());
final DrawFilter dF = new DrawFilter();
mCanvas.setDrawFilter(dF);
assertTrue(dF.equals(mCanvas.getDrawFilter()));
}
@Test
public void testQuickReject1() {
assertFalse(mCanvas.quickReject(new RectF(0, 0, 10, 31), EdgeType.AA));
assertFalse(mCanvas.quickReject(new RectF(0, 0, 10, 31), EdgeType.BW));
}
@Test
public void testQuickReject2() {
final Path p = new Path();
p.addRect(new RectF(0, 0, 10, 31), Direction.CCW);
assertFalse(mCanvas.quickReject(p, EdgeType.AA));
assertFalse(mCanvas.quickReject(p, EdgeType.BW));
}
@Test
public void testQuickReject3() {
assertFalse(mCanvas.quickReject(0, 0, 10, 31, EdgeType.AA));
assertFalse(mCanvas.quickReject(0, 0, 10, 31, EdgeType.BW));
}
@Test
public void testGetClipBounds1() {
final Rect r = new Rect();
assertTrue(mCanvas.getClipBounds(r));
assertEquals(BITMAP_WIDTH, r.width());
assertEquals(BITMAP_HEIGHT, r.height());
}
@Test
public void testGetClipBounds2() {
final Rect r = mCanvas.getClipBounds();
assertEquals(BITMAP_WIDTH, r.width());
assertEquals(BITMAP_HEIGHT, r.height());
}
private void verifyDrewColor(int color) {
assertEquals(color, mMutableBitmap.getPixel(0, 0));
assertEquals(color, mMutableBitmap.getPixel(BITMAP_WIDTH / 2, BITMAP_HEIGHT / 2));
assertEquals(color, mMutableBitmap.getPixel(BITMAP_WIDTH - 1, BITMAP_HEIGHT - 1));
}
@Test
public void testDrawRGB() {
final int alpha = 0xff;
final int red = 0xff;
final int green = 0xff;
final int blue = 0xff;
mCanvas.drawRGB(red, green, blue);
final int color = alpha << 24 | red << 16 | green << 8 | blue;
verifyDrewColor(color);
}
@Test
public void testDrawARGB() {
final int alpha = 0xff;
final int red = 0x22;
final int green = 0x33;
final int blue = 0x44;
mCanvas.drawARGB(alpha, red, green, blue);
final int color = alpha << 24 | red << 16 | green << 8 | blue;
verifyDrewColor(color);
}
@Test
public void testDrawColor1() {
final int color = Color.RED;
mCanvas.drawColor(color);
verifyDrewColor(color);
}
@Test
public void testDrawColor2() {
mCanvas.drawColor(Color.RED, Mode.CLEAR);
mCanvas.drawColor(Color.RED, Mode.DARKEN);
mCanvas.drawColor(Color.RED, Mode.DST);
mCanvas.drawColor(Color.RED, Mode.DST_ATOP);
mCanvas.drawColor(Color.RED, Mode.DST_IN);
mCanvas.drawColor(Color.RED, Mode.DST_OUT);
mCanvas.drawColor(Color.RED, Mode.DST_OVER);
mCanvas.drawColor(Color.RED, Mode.LIGHTEN);
mCanvas.drawColor(Color.RED, Mode.MULTIPLY);
mCanvas.drawColor(Color.RED, Mode.SCREEN);
mCanvas.drawColor(Color.RED, Mode.SRC);
mCanvas.drawColor(Color.RED, Mode.SRC_ATOP);
mCanvas.drawColor(Color.RED, Mode.SRC_IN);
mCanvas.drawColor(Color.RED, Mode.SRC_OUT);
mCanvas.drawColor(Color.RED, Mode.SRC_OVER);
mCanvas.drawColor(Color.RED, Mode.XOR);
}
@Test
public void testDrawPaint() {
mCanvas.drawPaint(mPaint);
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 0));
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawPointsInvalidOffset() {
// Should throw out ArrayIndexOutOfBoundsException because of invalid offset
mCanvas.drawPoints(new float[]{
10.0f, 29.0f
}, -1, 2, mPaint);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawPointsInvalidCount() {
// Should throw out ArrayIndexOutOfBoundsException because of invalid count
mCanvas.drawPoints(new float[]{
10.0f, 29.0f
}, 0, 31, mPaint);
}
@Test
public void testDrawPoints1() {
// normal case
mCanvas.drawPoints(new float[] {
0, 0
}, 0, 2, mPaint);
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 0));
}
@Test
public void testDrawPoints2() {
mCanvas.drawPoints(new float[]{0, 0}, mPaint);
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 0));
}
@Test
public void testDrawPoint() {
mCanvas.drawPoint(0, 0, mPaint);
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 0));
}
@Test
public void testDrawLine() {
mCanvas.drawLine(0, 0, 10, 12, mPaint);
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 0));
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawLinesInvalidOffset() {
// Should throw out ArrayIndexOutOfBoundsException because of invalid offset
mCanvas.drawLines(new float[]{
0, 0, 10, 31
}, 2, 4, new Paint());
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawLinesInvalidCount() {
// Should throw out ArrayIndexOutOfBoundsException because of invalid count
mCanvas.drawLines(new float[]{
0, 0, 10, 31
}, 0, 8, new Paint());
}
@Test
public void testDrawLines1() {
// normal case
mCanvas.drawLines(new float[] {
0, 0, 10, 12
}, 0, 4, mPaint);
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 0));
}
@Test
public void testDrawLines2() {
mCanvas.drawLines(new float[] {
0, 0, 10, 12
}, mPaint);
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 0));
}
private void verifyDrewPaint() {
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 0));
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(5, 6));
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(9, 11));
}
@Test
public void testDrawRect1() {
mCanvas.drawRect(new RectF(0, 0, 10, 12), mPaint);
verifyDrewPaint();
}
@Test
public void testDrawRect2() {
mCanvas.drawRect(new Rect(0, 0, 10, 12), mPaint);
verifyDrewPaint();
}
@Test
public void testDrawRect3() {
mCanvas.drawRect(0, 0, 10, 12, mPaint);
verifyDrewPaint();
}
@Test(expected=NullPointerException.class)
public void testDrawOvalNull() {
// Should throw out NullPointerException because oval is null
mCanvas.drawOval(null, mPaint);
}
@Test
public void testDrawOval() {
// normal case
mCanvas.drawOval(new RectF(0, 0, 10, 12), mPaint);
}
@Test
public void testDrawCircle() {
// special case: circle's radius <= 0
mCanvas.drawCircle(10.0f, 10.0f, -1.0f, mPaint);
// normal case
mCanvas.drawCircle(10, 12, 3, mPaint);
assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(9, 11));
}
@Test(expected=NullPointerException.class)
public void testDrawArcNullOval() {
// Should throw NullPointerException because oval is null
mCanvas.drawArc(null, 10.0f, 29.0f, true, mPaint);
}
@Test
public void testDrawArc() {
// normal case
mCanvas.drawArc(new RectF(0, 0, 10, 12), 10, 11, false, mPaint);
mCanvas.drawArc(new RectF(0, 0, 10, 12), 10, 11, true, mPaint);
// special case: sweepAngle >= abs(360)
mCanvas.drawArc(new RectF(0, 0, 10, 12), 10, 400, true, mPaint);
mCanvas.drawArc(new RectF(0, 0, 10, 12), 10, -400, true, mPaint);
mCanvas.drawArc(new RectF(0, 0, 10, 12), 10, Float.POSITIVE_INFINITY, true, mPaint);
mCanvas.drawArc(new RectF(0, 0, 10, 12), 10, Float.NEGATIVE_INFINITY, true, mPaint);
}
@Test(expected=NullPointerException.class)
public void testDrawRoundRectNull() {
// Should throw out NullPointerException because RoundRect is null
mCanvas.drawRoundRect(null, 10.0f, 29.0f, mPaint);
}
@Test
public void testDrawRoundRect() {
mCanvas.drawRoundRect(new RectF(0, 0, 10, 12), 8, 8, mPaint);
}
@Test
public void testDrawPath() {
mCanvas.drawPath(new Path(), mPaint);
}
@Test(expected=RuntimeException.class)
public void testDrawBitmapAtPointRecycled() {
Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
b.recycle();
// Should throw out RuntimeException because bitmap has been recycled
mCanvas.drawBitmap(b, 10.0f, 29.0f, mPaint);
}
@Test
public void testDrawBitmapAtPoint() {
Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 12, Config.ARGB_8888);
mCanvas.drawBitmap(b, 10, 12, null);
mCanvas.drawBitmap(b, 5, 12, mPaint);
}
@Test(expected=RuntimeException.class)
public void testDrawBitmapSrcDstFloatRecycled() {
Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
b.recycle();
// Should throw out RuntimeException because bitmap has been recycled
mCanvas.drawBitmap(b, null, new RectF(), mPaint);
}
@Test
public void testDrawBitmapSrcDstFloat() {
Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
mCanvas.drawBitmap(b, new Rect(), new RectF(), null);
mCanvas.drawBitmap(b, new Rect(), new RectF(), mPaint);
}
@Test(expected=RuntimeException.class)
public void testDrawBitmapSrcDstIntRecycled() {
Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
b.recycle();
// Should throw out RuntimeException because bitmap has been recycled
mCanvas.drawBitmap(b, null, new Rect(), mPaint);
}
@Test
public void testDrawBitmapSrcDstInt() {
Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
mCanvas.drawBitmap(b, new Rect(), new Rect(), null);
mCanvas.drawBitmap(b, new Rect(), new Rect(), mPaint);
}
@Test(expected=IllegalArgumentException.class)
public void testDrawBitmapIntsNegativeWidth() {
// Should throw out IllegalArgumentException because width is less than 0
mCanvas.drawBitmap(new int[2008], 10, 10, 10, 10, -1, 10, true, null);
}
@Test(expected=IllegalArgumentException.class)
public void testDrawBitmapIntsNegativeHeight() {
// Should throw out IllegalArgumentException because height is less than 0
mCanvas.drawBitmap(new int[2008], 10, 10, 10, 10, 10, -1, true, null);
}
@Test(expected=IllegalArgumentException.class)
public void testDrawBitmapIntsBadStride() {
// Should throw out IllegalArgumentException because stride less than width and
// bigger than -width
mCanvas.drawBitmap(new int[2008], 10, 5, 10, 10, 10, 10, true, null);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapIntsNegativeOffset() {
// Should throw out ArrayIndexOutOfBoundsException because offset less than 0
mCanvas.drawBitmap(new int[2008], -1, 10, 10, 10, 10, 10, true, null);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapIntsBadOffset() {
// Should throw out ArrayIndexOutOfBoundsException because sum of offset and width
// is bigger than colors' length
mCanvas.drawBitmap(new int[29], 10, 29, 10, 10, 20, 10, true, null);
}
@Test
public void testDrawBitmapInts() {
final int[] colors = new int[2008];
// special case: width equals to 0
mCanvas.drawBitmap(colors, 10, 10, 10, 10, 0, 10, true, null);
// special case: height equals to 0
mCanvas.drawBitmap(colors, 10, 10, 10, 10, 10, 0, true, null);
// normal case
mCanvas.drawBitmap(colors, 10, 10, 10, 10, 10, 29, true, null);
mCanvas.drawBitmap(colors, 10, 10, 10, 10, 10, 29, true, mPaint);
}
@Test(expected=IllegalArgumentException.class)
public void testDrawBitmapFloatsNegativeWidth() {
// Should throw out IllegalArgumentException because width is less than 0
mCanvas.drawBitmap(new int[2008], 10, 10, 10.0f, 10.0f, -1, 10, true, null);
}
@Test(expected=IllegalArgumentException.class)
public void testDrawBitmapFloatsNegativeHeight() {
// Should throw out IllegalArgumentException because height is less than 0
mCanvas.drawBitmap(new int[2008], 10, 10, 10.0f, 10.0f, 10, -1, true, null);
}
@Test(expected=IllegalArgumentException.class)
public void testDrawBitmapFloatsBadStride() {
// Should throw out IllegalArgumentException because stride less than width and
// bigger than -width
mCanvas.drawBitmap(new int[2008], 10, 5, 10.0f, 10.0f, 10, 10, true, null);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapFloatsNegativeOffset() {
// Should throw out ArrayIndexOutOfBoundsException because offset less than 0
mCanvas.drawBitmap(new int[2008], -1, 10, 10.0f, 10.0f, 10, 10, true, null);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapFloatsBadOffset() {
// Should throw out ArrayIndexOutOfBoundsException because sum of offset and width
// is bigger than colors' length
mCanvas.drawBitmap(new int[29], 10, 29, 10.0f, 10.0f, 20, 10, true, null);
}
@Test
public void testDrawBitmapFloats() {
final int[] colors = new int[2008];
// special case: width equals to 0
mCanvas.drawBitmap(colors, 10, 10, 10.0f, 10.0f, 0, 10, true, null);
// special case: height equals to 0
mCanvas.drawBitmap(colors, 10, 10, 10.0f, 10.0f, 10, 0, true, null);
// normal case
mCanvas.drawBitmap(colors, 10, 10, 10.0f, 10.0f, 10, 29, true, null);
mCanvas.drawBitmap(colors, 10, 10, 10.0f, 10.0f, 10, 29, true, mPaint);
}
@Test
public void testDrawBitmapMatrix() {
final Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
mCanvas.drawBitmap(b, new Matrix(), null);
mCanvas.drawBitmap(b, new Matrix(), mPaint);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapMeshNegativeWidth() {
final Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
// Should throw out ArrayIndexOutOfBoundsException because meshWidth less than 0
mCanvas.drawBitmapMesh(b, -1, 10, null, 0, null, 0, null);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapMeshNegativeHeight() {
final Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
// Should throw out ArrayIndexOutOfBoundsException because meshHeight is less than 0
mCanvas.drawBitmapMesh(b, 10, -1, null, 0, null, 0, null);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapMeshNegativeVertOffset() {
final Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
// Should throw out ArrayIndexOutOfBoundsException because vertOffset is less than 0
mCanvas.drawBitmapMesh(b, 10, 10, null, -1, null, 0, null);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapMeshNegativeColorOffset() {
final Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
// Should throw out ArrayIndexOutOfBoundsException because colorOffset is less than 0
mCanvas.drawBitmapMesh(b, 10, 10, null, 10, null, -1, null);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapMeshTooFewVerts() {
final Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
// Should throw out ArrayIndexOutOfBoundsException because verts' length is too short
mCanvas.drawBitmapMesh(b, 10, 10, new float[] {
10.0f, 29.0f
}, 10, null, 10, null);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawBitmapMeshTooFewColors() {
final Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
// Should throw out ArrayIndexOutOfBoundsException because colors' length is too short
// abnormal case: colors' length is too short
final float[] verts = new float[2008];
mCanvas.drawBitmapMesh(b, 10, 10, verts, 10, new int[] {
10, 29
}, 10, null);
}
@Test
public void testDrawBitmapMesh() {
final Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, 29, Config.ARGB_8888);
// special case: meshWidth equals to 0
mCanvas.drawBitmapMesh(b, 0, 10, null, 10, null, 10, null);
// special case: meshHeight equals to 0
mCanvas.drawBitmapMesh(b, 10, 0, null, 10, null, 10, null);
// normal case
final float[] verts = new float[2008];
final int[] colors = new int[2008];
mCanvas.drawBitmapMesh(b, 10, 10, verts, 10, colors, 10, null);
mCanvas.drawBitmapMesh(b, 10, 10, verts, 10, colors, 10, mPaint);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawVerticesTooFewVerts() {
final float[] verts = new float[10];
final float[] texs = new float[10];
final int[] colors = new int[10];
final short[] indices = {
0, 1, 2, 3, 4, 1
};
// Should throw out ArrayIndexOutOfBoundsException because sum of vertOffset and
// vertexCount is bigger than verts' length
mCanvas.drawVertices(VertexMode.TRIANGLES, 10, verts, 8, texs, 0, colors, 0, indices,
0, 4, mPaint);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawVerticesTooFewTexs() {
final float[] verts = new float[10];
final float[] texs = new float[10];
final int[] colors = new int[10];
final short[] indices = {
0, 1, 2, 3, 4, 1
};
// Should throw out ArrayIndexOutOfBoundsException because sum of texOffset and
// vertexCount is bigger thatn texs' length
mCanvas.drawVertices(VertexMode.TRIANGLES, 10, verts, 0, texs, 30, colors, 0, indices,
0, 4, mPaint);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawVerticesTooFewColors() {
final float[] verts = new float[10];
final float[] texs = new float[10];
final int[] colors = new int[10];
final short[] indices = {
0, 1, 2, 3, 4, 1
};
// Should throw out ArrayIndexOutOfBoundsException because sum of colorOffset and
// vertexCount is bigger than colors' length
mCanvas.drawVertices(VertexMode.TRIANGLES, 10, verts, 0, texs, 0, colors, 30, indices,
0, 4, mPaint);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawVerticesTooFewIndices() {
final float[] verts = new float[10];
final float[] texs = new float[10];
final int[] colors = new int[10];
final short[] indices = {
0, 1, 2, 3, 4, 1
};
// Should throw out ArrayIndexOutOfBoundsException because sum of indexOffset and
// indexCount is bigger than indices' length
mCanvas.drawVertices(VertexMode.TRIANGLES, 10, verts, 0, texs, 0, colors, 0, indices,
10, 30, mPaint);
}
@Test
public void testDrawVertices() {
final float[] verts = new float[10];
final float[] texs = new float[10];
final int[] colors = new int[10];
final short[] indices = {
0, 1, 2, 3, 4, 1
};
// special case: in texs, colors, indices, one of them, two of them and
// all are null
mCanvas.drawVertices(VertexMode.TRIANGLES, 0, verts, 0, null, 0, colors, 0, indices, 0, 0,
mPaint);
mCanvas.drawVertices(VertexMode.TRIANGLE_STRIP, 0, verts, 0, null, 0, null, 0, indices, 0,
0, mPaint);
mCanvas.drawVertices(VertexMode.TRIANGLE_FAN, 0, verts, 0, null, 0, null, 0, null, 0, 0,
mPaint);
// normal case: texs, colors, indices are not null
mCanvas.drawVertices(VertexMode.TRIANGLES, 10, verts, 0, texs, 0, colors, 0, indices, 0, 6,
mPaint);
mCanvas.drawVertices(VertexMode.TRIANGLE_STRIP, 10, verts, 0, texs, 0, colors, 0, indices,
0, 6, mPaint);
mCanvas.drawVertices(VertexMode.TRIANGLE_FAN, 10, verts, 0, texs, 0, colors, 0, indices, 0,
6, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawArrayTextNegativeIndex() {
final char[] text = { 'a', 'n', 'd', 'r', 'o', 'i', 'd' };
// Should throw out IndexOutOfBoundsException because index is less than 0
mCanvas.drawText(text, -1, 7, 10, 10, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawArrayTextNegativeCount() {
final char[] text = { 'a', 'n', 'd', 'r', 'o', 'i', 'd' };
// Should throw out IndexOutOfBoundsException because count is less than 0
mCanvas.drawText(text, 0, -1, 10, 10, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawArrayTextTextLengthTooSmall() {
final char[] text = { 'a', 'n', 'd', 'r', 'o', 'i', 'd' };
// Should throw out IndexOutOfBoundsException because sum of index and count
// is bigger than text's length
mCanvas.drawText(text, 0, 10, 10, 10, mPaint);
}
@Test
public void testDrawArrayText() {
final char[] text = { 'a', 'n', 'd', 'r', 'o', 'i', 'd' };
// normal case
mCanvas.drawText(text, 0, 7, 10, 10, mPaint);
}
@Test
public void testDrawStringTextAtPosition() {
mCanvas.drawText("android", 10, 30, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextTextAtPositionWithOffsetsNegativeStart() {
// Should throw out IndexOutOfBoundsException because start is less than 0
mCanvas.drawText("android", -1, 7, 10, 30, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextTextAtPositionWithOffsetsNegativeEnd() {
// Should throw out IndexOutOfBoundsException because end is less than 0
mCanvas.drawText("android", 0, -1, 10, 30, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextTextAtPositionWithOffsetsStartEndMismatch() {
// Should throw out IndexOutOfBoundsException because start is bigger than end
mCanvas.drawText("android", 3, 1, 10, 30, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextTextAtPositionWithOffsetsTextTooLong() {
// Should throw out IndexOutOfBoundsException because end subtracts start should
// bigger than text's length
mCanvas.drawText("android", 0, 10, 10, 30, mPaint);
}
@Test
public void testDrawTextTextAtPositionWithOffsets() {
final String t1 = "android";
mCanvas.drawText(t1, 0, 7, 10, 30, mPaint);
final SpannedString t2 = new SpannedString(t1);
mCanvas.drawText(t2, 0, 7, 10, 30, mPaint);
final SpannableString t3 = new SpannableString(t2);
mCanvas.drawText(t3, 0, 7, 10, 30, mPaint);
final SpannableStringBuilder t4 = new SpannableStringBuilder(t1);
mCanvas.drawText(t4, 0, 7, 10, 30, mPaint);
final StringBuffer t5 = new StringBuffer(t1);
mCanvas.drawText(t5, 0, 7, 10, 30, mPaint);
}
@Test
public void testDrawTextRun() {
final String text = "android";
final Paint paint = new Paint();
mCanvas.drawTextRun(text, 0, 0, 0, 0, 0.0f, 0.0f, false, paint);
mCanvas.drawTextRun(text, 0, text.length(), 0, text.length(), 0.0f, 0.0f, false, paint);
mCanvas.drawTextRun(text, text.length(), text.length(), text.length(), text.length(),
0.0f, 0.0f, false, paint);
}
@Test(expected=NullPointerException.class)
public void testDrawTextRunNullCharArray() {
// Should throw out NullPointerException because text is null
mCanvas.drawTextRun((char[]) null, 0, 0, 0, 0, 0.0f, 0.0f, false, new Paint());
}
@Test(expected=NullPointerException.class)
public void testDrawTextRunNullCharSequence() {
// Should throw out NullPointerException because text is null
mCanvas.drawTextRun((CharSequence) null, 0, 0, 0, 0, 0.0f, 0.0f, false, new Paint());
}
@Test(expected=NullPointerException.class)
public void testDrawTextRunCharArrayNullPaint() {
// Should throw out NullPointerException because paint is null
mCanvas.drawTextRun("android".toCharArray(), 0, 0, 0, 0, 0.0f, 0.0f, false, null);
}
@Test(expected=NullPointerException.class)
public void testDrawTextRunCharSequenceNullPaint() {
// Should throw out NullPointerException because paint is null
mCanvas.drawTextRun("android", 0, 0, 0, 0, 0.0f, 0.0f, false, null);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunNegativeIndex() {
final String text = "android";
final Paint paint = new Paint();
// Should throw out IndexOutOfBoundsException because index is less than 0
mCanvas.drawTextRun(text.toCharArray(), -1, text.length(), 0, text.length(), 0.0f, 0.0f,
false, new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunNegativeCount() {
final String text = "android";
// Should throw out IndexOutOfBoundsException because count is less than 0
mCanvas.drawTextRun(text.toCharArray(), 0, -1, 0, text.length(), 0.0f, 0.0f, false,
new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunContestIndexTooLarge() {
final String text = "android";
// Should throw out IndexOutOfBoundsException because contextIndex is bigger than index
mCanvas.drawTextRun(text.toCharArray(), 0, text.length(), 1, text.length(), 0.0f, 0.0f,
false, new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunContestIndexTooSmall() {
final String text = "android";
// Should throw out IndexOutOfBoundsException because contextIndex + contextCount
// is less than index + count
mCanvas.drawTextRun(text, 0, text.length(), 0, text.length() - 1, 0.0f, 0.0f, false,
new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunIndexTooLarge() {
final String text = "android";
final Paint paint = new Paint();
// Should throw out IndexOutOfBoundsException because index + count is bigger than
// text length
mCanvas.drawTextRun(text.toCharArray(), 0, text.length() + 1, 0, text.length() + 1,
0.0f, 0.0f, false, new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunNegativeContextStart() {
final String text = "android";
final Paint paint = new Paint();
// Should throw out IndexOutOfBoundsException because contextStart is less than 0
mCanvas.drawTextRun(text, 0, text.length(), -1, text.length(), 0.0f, 0.0f, false,
new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunStartLessThanContextStart() {
final String text = "android";
// Should throw out IndexOutOfBoundsException because start is less than contextStart
mCanvas.drawTextRun(text, 0, text.length(), 1, text.length(), 0.0f, 0.0f, false,
new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunEndLessThanStart() {
final String text = "android";
// Should throw out IndexOutOfBoundsException because end is less than start
mCanvas.drawTextRun(text, 1, 0, 0, text.length(), 0.0f, 0.0f, false, new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunContextEndLessThanEnd() {
final String text = "android";
// Should throw out IndexOutOfBoundsException because contextEnd is less than end
mCanvas.drawTextRun(text, 0, text.length(), 0, text.length() - 1, 0.0f, 0.0f, false,
new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawTextRunContextEndLargerThanTextLength() {
final String text = "android";
// Should throw out IndexOutOfBoundsException because contextEnd is bigger than
// text length
mCanvas.drawTextRun(text, 0, text.length(), 0, text.length() + 1, 0.0f, 0.0f, false,
new Paint());
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawPosTextWithIndexAndCountNegativeIndex() {
final char[] text = {
'a', 'n', 'd', 'r', 'o', 'i', 'd'
};
final float[] pos = new float[]{
0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f,
7.0f, 7.0f
};
// Should throw out IndexOutOfBoundsException because index is less than 0
mCanvas.drawPosText(text, -1, 7, pos, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawPosTextWithIndexAndCountTextTooShort() {
final char[] text = {
'a', 'n', 'd', 'r', 'o', 'i', 'd'
};
final float[] pos = new float[]{
0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f,
7.0f, 7.0f
};
// Should throw out IndexOutOfBoundsException because sum of index and count is
// bigger than text's length
mCanvas.drawPosText(text, 1, 10, pos, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawPosTextWithIndexAndCountCountTooLarge() {
final char[] text = {
'a', 'n', 'd', 'r', 'o', 'i', 'd'
};
// Should throw out IndexOutOfBoundsException because 2 times of count is
// bigger than pos' length
mCanvas.drawPosText(text, 1, 10, new float[] {
10.0f, 30.f
}, mPaint);
}
@Test
public void testDrawPosTextWithIndexAndCount() {
final char[] text = {
'a', 'n', 'd', 'r', 'o', 'i', 'd'
};
final float[] pos = new float[]{
0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f,
7.0f, 7.0f
};
// normal case
mCanvas.drawPosText(text, 0, 7, pos, mPaint);
}
@Test(expected=IndexOutOfBoundsException.class)
public void testDrawPosTextCountTooLarge() {
final String text = "android";
// Should throw out IndexOutOfBoundsException because 2 times of count is
// bigger than pos' length
mCanvas.drawPosText(text, new float[]{
10.0f, 30.f
}, mPaint);
}
@Test
public void testDrawPosText() {
final String text = "android";
final float[] pos = new float[]{
0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f,
7.0f, 7.0f
};
// normal case
mCanvas.drawPosText(text, pos, mPaint);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawTextOnPathWithIndexAndCountNegativeIndex() {
final char[] text = { 'a', 'n', 'd', 'r', 'o', 'i', 'd' };
// Should throw out ArrayIndexOutOfBoundsException because index is smaller than 0
mCanvas.drawTextOnPath(text, -1, 7, new Path(), 10.0f, 10.0f, mPaint);
}
@Test(expected=ArrayIndexOutOfBoundsException.class)
public void testDrawTextOnPathWithIndexAndCountTextTooShort() {
final char[] text = { 'a', 'n', 'd', 'r', 'o', 'i', 'd' };
// Should throw out ArrayIndexOutOfBoundsException because sum of index and
// count is bigger than text's length
mCanvas.drawTextOnPath(text, 0, 10, new Path(), 10.0f, 10.0f, mPaint);
}
@Test
public void testDrawTextOnPathWithIndexAndCount() {
final char[] text = { 'a', 'n', 'd', 'r', 'o', 'i', 'd' };
// normal case
mCanvas.drawTextOnPath(text, 0, 7, new Path(), 10.0f, 10.0f, mPaint);
}
@Test
public void testDrawTextOnPathtestDrawTextRunNegativeCount() {
final Path path = new Path();
// no character in text
mCanvas.drawTextOnPath("", path, 10.0f, 10.0f, mPaint);
// There are characters in text
mCanvas.drawTextOnPath("android", path, 10.0f, 10.0f, mPaint);
}
@Test
public void testDrawPicture1() {
mCanvas.drawPicture(new Picture());
}
@Test
public void testDrawPicture2() {
final RectF dst = new RectF(0, 0, 10, 31);
final Picture p = new Picture();
// picture width or length not bigger than 0
mCanvas.drawPicture(p, dst);
p.beginRecording(10, 30);
mCanvas.drawPicture(p, dst);
}
@Test
public void testDrawPicture3() {
final Rect dst = new Rect(0, 10, 30, 0);
final Picture p = new Picture();
// picture width or length not bigger than 0
mCanvas.drawPicture(p, dst);
p.beginRecording(10, 30);
mCanvas.drawPicture(p, dst);
}
@Test
public void testDensity() {
// set Density
mCanvas.setDensity(DisplayMetrics.DENSITY_DEFAULT);
assertEquals(DisplayMetrics.DENSITY_DEFAULT, mCanvas.getDensity());
// set Density
mCanvas.setDensity(DisplayMetrics.DENSITY_HIGH);
assertEquals(DisplayMetrics.DENSITY_HIGH, mCanvas.getDensity());
}
@Test(expected = IllegalArgumentException.class)
public void testDrawHwBitmap_inSwCanvas() {
Bitmap hwBitmap = mImmutableBitmap.copy(Config.HARDWARE, false);
mCanvas.drawBitmap(hwBitmap, 0, 0, null); // we verify this specific call should IAE
}
@Test(expected = IllegalArgumentException.class)
public void testDrawHwBitmap_inPictureCanvas_inSwCanvas() {
Bitmap hwBitmap = mImmutableBitmap.copy(Config.HARDWARE, false);
Picture picture = new Picture();
Canvas pictureCanvas = picture.beginRecording(100, 100);
pictureCanvas.drawBitmap(hwBitmap, 0, 0, null);
mCanvas.drawPicture(picture); // we verify this specific call should IAE
}
@Test(expected = IllegalArgumentException.class)
public void testDrawHwBitmap_inPictureCanvas_inPictureCanvas_inSwCanvas() {
Bitmap hwBitmap = mImmutableBitmap.copy(Config.HARDWARE, false);
Picture innerPicture = new Picture();
Canvas pictureCanvas = innerPicture.beginRecording(100, 100);
pictureCanvas.drawBitmap(hwBitmap, 0, 0, null);
Picture outerPicture = new Picture();
Canvas outerPictureCanvas = outerPicture.beginRecording(100, 100);
outerPictureCanvas.drawPicture(innerPicture);
mCanvas.drawPicture(outerPicture); // we verify this specific call should IAE
}
@Test(expected = IllegalArgumentException.class)
public void testHwBitmapShaderInSwCanvas1() {
Bitmap hwBitmap = mImmutableBitmap.copy(Config.HARDWARE, false);
BitmapShader bitmapShader = new BitmapShader(hwBitmap, Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT);
RadialGradient gradientShader = new RadialGradient(10, 10, 30, Color.BLACK, Color.CYAN,
Shader.TileMode.REPEAT);
Shader shader = new ComposeShader(gradientShader, bitmapShader, Mode.OVERLAY);
Paint p = new Paint();
p.setShader(shader);
mCanvas.drawRect(0, 0, 10, 10, p);
}
@Test(expected = IllegalArgumentException.class)
public void testHwBitmapShaderInSwCanvas2() {
Bitmap hwBitmap = mImmutableBitmap.copy(Config.HARDWARE, false);
BitmapShader bitmapShader = new BitmapShader(hwBitmap, Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT);
RadialGradient gradientShader = new RadialGradient(10, 10, 30, Color.BLACK, Color.CYAN,
Shader.TileMode.REPEAT);
Shader shader = new ComposeShader(bitmapShader, gradientShader, Mode.OVERLAY);
Paint p = new Paint();
p.setShader(shader);
mCanvas.drawRect(0, 0, 10, 10, p);
}
private void preCompare() {
final float[] values = new float[FLOAT_ARRAY_LEN];
mCanvas.getMatrix().getValues(values);
assertArrayEquals(new float[] {
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f
}, values, 0.0f);
}
private RectF getDeviceClip() {
final RectF clip = new RectF(mCanvas.getClipBounds());
mCanvas.getMatrix().mapRect(clip);
return clip;
}
@Test
public void testDrawBitmapColorBehavior() {
try {
// Create a wide gamut bitmap where the pixel value is slightly less than max red.
Resources resources = InstrumentationRegistry.getTargetContext().getResources();
InputStream in = resources.getAssets().open("almost-red-adobe.png");
Bitmap bitmap = BitmapFactory.decodeStream(in);
// Draw the bitmap to an sRGB canvas.
Bitmap canvasBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(canvasBitmap);
canvas.drawBitmap(bitmap, 0, 0, null);
// Verify that the pixel is now max red.
Assert.assertEquals(0xFFFF0000, canvasBitmap.getPixel(0, 0));
} catch (IOException e) {
fail();
}
}
@Test
public void testShadowLayer_paintColorPreserved() {
Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setShadowLayer(5.0f, 10.0f, 10.0f, 0xFFFF0000);
paint.setColor(0xFF0000FF);
canvas.drawPaint(paint);
// Since the shadow is in the background, the canvas should be blue.
ColorUtils.verifyColor(0xFF0000FF, bitmap.getPixel(50, 50));
}
}