blob: 7947286516656dfd520a5d2c291e910f1f2c3b57 [file] [log] [blame]
/*
* Copyright (C) 2014 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/LICENSE2.0
*
* Unless required by applicable law or agreed to in riting, 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.uirendering.cts.testclasses;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.test.suitebuilder.annotation.SmallTest;
import android.uirendering.cts.bitmapcomparers.BitmapComparer;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.testinfrastructure.CanvasClient;
import android.uirendering.cts.testinfrastructure.DisplayModifier;
import android.uirendering.cts.testinfrastructure.ResourceModifier;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Test cases of all combination of resource modifications.
*/
public class SweepTests extends ActivityTestBase {
private static final String TAG = "SweepTests";
public static final int BG_COLOR = 0xFFFFFFFF;
public static final int DST_COLOR = 0xFFFFCC44;
public static final int SRC_COLOR = 0xFF66AAFF;
public static final int MULTIPLY_COLOR = 0xFF668844;
public static final int SCREEN_COLOR = 0xFFFFEEFF;
public static final int FILTER_COLOR = 0xFFBB0000;
public static final int RECT0_COLOR = 0x33808080;
public static final int RECT1_COLOR = 0x66808080;
public static final int RECT2_COLOR = 0x99808080;
public static final int RECT3_COLOR = 0xCC808080;
// These points are in pairs, the first being the lower left corner, the second is only in the
// Destination bitmap, the third is the intersection of the two bitmaps, and the fourth is in
// the Source bitmap.
private final static Point[] XFERMODE_TEST_POINTS = new Point[] {
new Point(1, 160), new Point(50, 50), new Point(70, 70), new Point(140, 140)
};
/**
* There are 4 locations we care about in any filter testing.
*
* 1) Both empty
* 2) Only src, dst empty
* 3) Both src + dst
* 4) Only dst, src empty
*/
private final Map<PorterDuff.Mode, int[]> XFERMODE_COLOR_MAP = new LinkedHashMap<PorterDuff.Mode, int[]>() {
{
put(PorterDuff.Mode.SRC, new int[] {
BG_COLOR, BG_COLOR, SRC_COLOR, SRC_COLOR
});
put(PorterDuff.Mode.DST, new int[] {
BG_COLOR, DST_COLOR, DST_COLOR, BG_COLOR
});
put(PorterDuff.Mode.SRC_OVER, new int[] {
BG_COLOR, DST_COLOR, SRC_COLOR, SRC_COLOR
});
put(PorterDuff.Mode.DST_OVER, new int[] {
BG_COLOR, DST_COLOR, DST_COLOR, SRC_COLOR
});
put(PorterDuff.Mode.SRC_IN, new int[] {
BG_COLOR, BG_COLOR, SRC_COLOR, BG_COLOR
});
put(PorterDuff.Mode.DST_IN, new int[] {
BG_COLOR, BG_COLOR, DST_COLOR, BG_COLOR
});
put(PorterDuff.Mode.SRC_OUT, new int[] {
BG_COLOR, BG_COLOR, BG_COLOR, SRC_COLOR
});
put(PorterDuff.Mode.DST_OUT, new int[] {
BG_COLOR, DST_COLOR, BG_COLOR, BG_COLOR
});
put(PorterDuff.Mode.SRC_ATOP, new int[] {
BG_COLOR, DST_COLOR, SRC_COLOR, BG_COLOR
});
put(PorterDuff.Mode.DST_ATOP, new int[] {
BG_COLOR, BG_COLOR, DST_COLOR, SRC_COLOR
});
put(PorterDuff.Mode.XOR, new int[] {
BG_COLOR, DST_COLOR, BG_COLOR, SRC_COLOR
});
put(PorterDuff.Mode.MULTIPLY, new int[] {
BG_COLOR, BG_COLOR, MULTIPLY_COLOR, BG_COLOR
});
put(PorterDuff.Mode.SCREEN, new int[] {
BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR
});
}
};
private final static DisplayModifier XFERMODE_MODIFIER = new DisplayModifier() {
private final RectF mSrcRect = new RectF(60, 60, 160, 160);
private final RectF mDstRect = new RectF(20, 20, 120, 120);
private final Bitmap mSrcBitmap = createSrc();
private final Bitmap mDstBitmap = createDst();
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
int sc = canvas.saveLayer(0, 0, TEST_WIDTH, TEST_HEIGHT, null);
canvas.drawBitmap(mDstBitmap, 0, 0, null);
canvas.drawBitmap(mSrcBitmap, 0, 0, paint);
canvas.restoreToCount(sc);
}
private Bitmap createSrc() {
Bitmap srcB = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
Bitmap.Config.ARGB_8888);
Canvas srcCanvas = new Canvas(srcB);
Paint srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
srcPaint.setColor(SRC_COLOR);
srcCanvas.drawRect(mSrcRect, srcPaint);
return srcB;
}
private Bitmap createDst() {
Bitmap dstB = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
Bitmap.Config.ARGB_8888);
Canvas dstCanvas = new Canvas(dstB);
Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
dstPaint.setColor(DST_COLOR);
dstCanvas.drawOval(mDstRect, dstPaint);
return dstB;
}
};
// We care about one point in each of the four rectangles of different alpha values, as well as
// the area outside the rectangles
private final static Point[] COLOR_FILTER_ALPHA_POINTS = new Point[] {
new Point(15, 90), new Point(45, 90), new Point(75, 90), new Point(105, 90),
new Point(135, 90)
};
private final Map<PorterDuff.Mode, int[]> COLOR_FILTER_ALPHA_MAP = new LinkedHashMap<PorterDuff.Mode, int[]>() {
{
put(PorterDuff.Mode.SRC, new int[] {
FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR
});
put(PorterDuff.Mode.DST, new int[] {
0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
});
put(PorterDuff.Mode.SRC_OVER, new int[] {
0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000
});
put(PorterDuff.Mode.DST_OVER, new int[] {
0xFFAF1A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
});
put(PorterDuff.Mode.SRC_IN, new int[] {
0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC83333, 0xFFFFFFFF
});
put(PorterDuff.Mode.DST_IN, new int[] {
0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
});
put(PorterDuff.Mode.SRC_OUT, new int[] {
0xFFC83333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
});
put(PorterDuff.Mode.DST_OUT, new int[] {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
});
put(PorterDuff.Mode.SRC_ATOP, new int[] {
0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC93333, 0xFFFFFFFF
});
put(PorterDuff.Mode.DST_ATOP, new int[] {
0xFFB01A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
});
put(PorterDuff.Mode.XOR, new int[] {
0xFFC93333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
});
put(PorterDuff.Mode.MULTIPLY, new int[] {
0xFFDFCCCC, 0xFFBE9999, 0xFF9E6666, 0xFF7E3333, 0xFFFFFFFF
});
put(PorterDuff.Mode.SCREEN, new int[] {
0xFFC21A1A, 0xFFC93333, 0xFFD04D4D, 0xFFD66666, 0xFFBB0000
});
}
};
private final static DisplayModifier COLOR_FILTER_ALPHA_MODIFIER = new DisplayModifier() {
private final static int mBlockWidths = 30;
private final int[] mColorValues = new int[] {RECT0_COLOR, RECT1_COLOR, RECT2_COLOR,
RECT3_COLOR};
private final Bitmap mBitmap = createQuadRectBitmap();
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, paint);
}
private Bitmap createQuadRectBitmap() {
Bitmap bitmap = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
for (int i = 0 ; i < 4 ; i++) {
paint.setColor(mColorValues[i]);
canvas.drawRect(i * mBlockWidths, 0, (i + 1) * mBlockWidths, MODIFIER_HEIGHT, paint);
}
return bitmap;
}
};
private final static DisplayModifier COLOR_FILTER_GRADIENT_MODIFIER = new DisplayModifier() {
private final Rect mBounds = new Rect(30, 30, 150, 150);
private final int[] mColors = new int[] {
Color.RED, Color.GREEN, Color.BLUE
};
private final Bitmap mBitmap = createGradient();
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, paint);
}
private Bitmap createGradient() {
LinearGradient gradient = new LinearGradient(30, 90, 150, 90, mColors, null,
Shader.TileMode.REPEAT);
Bitmap bitmap = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
Bitmap.Config.ARGB_8888);
Paint p = new Paint();
p.setShader(gradient);
Canvas c = new Canvas(bitmap);
c.drawRect(mBounds, p);
return bitmap;
}
};
public static final DisplayModifier mCircleDrawModifier = new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawCircle(ActivityTestBase.TEST_WIDTH / 2,
ActivityTestBase.TEST_HEIGHT / 2,
ActivityTestBase.TEST_HEIGHT / 2, paint);
}
};
/**
* 0.5 defines minimum similarity as 50%
*/
private static final float HIGH_THRESHOLD = 0.5f;
private static final BitmapComparer[] DEFAULT_MSSIM_COMPARER = new BitmapComparer[] {
new MSSIMComparer(HIGH_THRESHOLD)
};
@SmallTest
public void testBasicDraws() {
sweepModifiersForMask(DisplayModifier.Accessor.SHAPES_MASK, null, DEFAULT_MSSIM_COMPARER,
null);
}
@SmallTest
public void testBasicShaders() {
sweepModifiersForMask(DisplayModifier.Accessor.SHADER_MASK, mCircleDrawModifier,
DEFAULT_MSSIM_COMPARER, null);
}
@SmallTest
public void testColorFilterUsingGradient() {
sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
COLOR_FILTER_GRADIENT_MODIFIER, DEFAULT_MSSIM_COMPARER, null);
}
@SmallTest
public void testColorFiltersAlphas() {
BitmapVerifier[] bitmapVerifiers =
new BitmapVerifier[DisplayModifier.PORTERDUFF_MODES.length];
int index = 0;
for (PorterDuff.Mode mode : DisplayModifier.PORTERDUFF_MODES) {
bitmapVerifiers[index] = new SamplePointVerifier(COLOR_FILTER_ALPHA_POINTS,
COLOR_FILTER_ALPHA_MAP.get(mode));
index++;
}
sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
COLOR_FILTER_ALPHA_MODIFIER, null, bitmapVerifiers);
}
@SmallTest
public void testXfermodes() {
BitmapVerifier[] bitmapVerifiers =
new BitmapVerifier[DisplayModifier.PORTERDUFF_MODES.length];
int index = 0;
for (PorterDuff.Mode mode : DisplayModifier.PORTERDUFF_MODES) {
bitmapVerifiers[index] = new SamplePointVerifier(XFERMODE_TEST_POINTS,
XFERMODE_COLOR_MAP.get(mode));
index++;
}
sweepModifiersForMask(DisplayModifier.Accessor.XFERMODE_MASK, XFERMODE_MODIFIER,
null, bitmapVerifiers);
}
/*
* TODO: fix this test for L MR1
@SmallTest
public void testShaderSweeps() {
int mask = DisplayModifier.Accessor.AA_MASK |
DisplayModifier.Accessor.SHADER_MASK |
DisplayModifier.Accessor.XFERMODE_MASK |
DisplayModifier.Accessor.SHAPES_MASK;
sweepModifiersForMask(mask, null, DEFAULT_MSSIM_COMPARER, null);
}
*/
protected void sweepModifiersForMask(int mask, final DisplayModifier drawOp,
BitmapComparer[] bitmapComparers, BitmapVerifier[] bitmapVerifiers) {
if ((mask & DisplayModifier.Accessor.ALL_OPTIONS_MASK) == 0) {
throw new IllegalArgumentException("Attempt to test with a mask that is invalid");
}
// Get the accessor of all the different modifications possible
final DisplayModifier.Accessor modifierAccessor = new DisplayModifier.Accessor(mask);
// Initialize the resources that we will need to access
ResourceModifier.init(getActivity().getResources());
// For each modification combination, we will get the CanvasClient associated with it and
// from there execute a normal canvas test with that.
CanvasClient canvasClient = new CanvasClient() {
@Override
public void draw(Canvas canvas, int width, int height) {
Paint paint = new Paint();
modifierAccessor.modifyDrawing(canvas, paint);
if (drawOp != null) {
drawOp.modifyDrawing(paint, canvas);
}
}
};
int index = 0;
// Create the test cases with each combination
do {
canvasClient.setDebugString(modifierAccessor.getDebugString());
if (bitmapComparers != null) {
int arrIndex = Math.min(index, bitmapComparers.length - 1);
createTest().addCanvasClient(canvasClient).runWithComparer(bitmapComparers[arrIndex]);
} else {
int arrIndex = Math.min(index, bitmapVerifiers.length - 1);
createTest().addCanvasClient(canvasClient).runWithVerifier(bitmapVerifiers[arrIndex]);
}
index++;
} while (modifierAccessor.step());
}
}