Integrate unsubmitted cupcake change 131127:
CTS: add test cases for graphics.ComposeShader, CornerPathEffect, DashPathEffect, DiscretePathEffect, EmbossMaskFilter and LightingColorFilter
diff --git a/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java b/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
new file mode 100644
index 0000000..a52ede1
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2009 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 dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ComposeShader;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.PixelXorXfermode;
+import android.graphics.PorterDuff;
+import android.graphics.Shader;
+import android.graphics.Xfermode;
+import android.graphics.Bitmap.Config;
+import android.graphics.Shader.TileMode;
+import android.util.Log;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(ComposeShader.class)
+public class ComposeShaderTest extends TestCase {
+
+ private static final int SIZE = 255;
+ private static final int TOLERANCE = 5;
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "ComposeShader",
+ args = {Shader.class, Shader.class, PorterDuff.Mode.class}
+ )
+ public void testPorterDuff() {
+ LinearGradient blueGradient = new LinearGradient(0, 0, SIZE, 0,
+ Color.GREEN, Color.BLUE, Shader.TileMode.CLAMP);
+ LinearGradient redGradient = new LinearGradient(0, 0, 0, SIZE,
+ Color.GREEN, Color.RED, Shader.TileMode.CLAMP);
+ ComposeShader shader = new ComposeShader(blueGradient, redGradient, PorterDuff.Mode.SCREEN);
+
+ Bitmap bitmap = Bitmap.createBitmap(SIZE, SIZE, Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ Paint paint = new Paint();
+ paint.setShader(shader);
+ canvas.drawPaint(paint);
+
+ for (int y = 0; y < SIZE; y++) {
+ for (int x = 0; x < SIZE; x++) {
+ float greenX = 1f - (x / 255f);
+ float greenY = 1f - (y / 255f);
+ int green = (int)((greenX + greenY - greenX * greenY) * 255);
+ int pixel = bitmap.getPixel(x, y);
+ try {
+ assertEquals(0xFF, Color.alpha(pixel), TOLERANCE);
+ assertEquals(y, Color.red(pixel), TOLERANCE);
+ assertEquals(green, Color.green(pixel), TOLERANCE);
+ assertEquals(x, Color.blue(pixel), TOLERANCE);
+ } catch (Error e) {
+ Log.w(getClass().getName(), "Failed at (" + x + "," + y + ")");
+ throw e;
+ }
+ }
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "ComposeShader",
+ args = {Shader.class, Shader.class, Xfermode.class}
+ )
+ public void testXfermode() {
+ Bitmap greenBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
+ greenBitmap.eraseColor(Color.GREEN);
+ Bitmap cyanBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
+ cyanBitmap.eraseColor(Color.CYAN);
+
+ BitmapShader blueShader = new BitmapShader(greenBitmap, TileMode.CLAMP, TileMode.CLAMP);
+ BitmapShader redShader = new BitmapShader(cyanBitmap, TileMode.CLAMP, TileMode.CLAMP);
+
+ PixelXorXfermode xferMode = new PixelXorXfermode(Color.WHITE);
+
+ ComposeShader shader = new ComposeShader(blueShader, redShader, xferMode);
+
+ Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ Paint paint = new Paint();
+ paint.setShader(shader);
+ canvas.drawPaint(paint);
+
+ // white ^ green ^ cyan = yellow
+ assertEquals(Color.YELLOW, bitmap.getPixel(0, 0));
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/CornerPathEffectTest.java b/tests/tests/graphics/src/android/graphics/cts/CornerPathEffectTest.java
new file mode 100644
index 0000000..eceb290
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/CornerPathEffectTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009 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 dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.ToBeFixed;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.CornerPathEffect;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathEffect;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.RectF;
+import android.graphics.Bitmap.Config;
+import android.graphics.Paint.Style;
+import android.graphics.PorterDuff.Mode;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(CornerPathEffect.class)
+public class CornerPathEffectTest extends TestCase {
+ private static final int BITMAP_WIDTH = 100;
+ private static final int BITMAP_HEIGHT = 100;
+ private static final int PADDING = 10;
+ private static final int RADIUS = 20;
+ private static final int TOLERANCE = 5;
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "CornerPathEffect",
+ args = {float.class}
+ )
+ @ToBeFixed(bug = "2037365", explanation = "CornerPathEffect ends the path prematurely it " +
+ "is not closed.")
+ public void testCornerPathEffect() {
+ Path path = new Path();
+ path.moveTo(0, PADDING);
+ path.lineTo(BITMAP_WIDTH - PADDING, PADDING);
+ path.lineTo(BITMAP_WIDTH - PADDING, BITMAP_HEIGHT);
+
+ PathEffect effect = new CornerPathEffect(RADIUS);
+
+ Paint pathPaint = new Paint();
+ pathPaint.setColor(Color.GREEN);
+ pathPaint.setStyle(Style.STROKE);
+ pathPaint.setStrokeWidth(0);
+ pathPaint.setPathEffect(effect);
+
+ Bitmap bitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+
+ // draw the path using the corner path effect
+ canvas.drawPath(path, pathPaint);
+
+ // create a path that describes the expected shape after the corner is rounded
+ Path expectedPath = new Path();
+ RectF oval = new RectF(BITMAP_WIDTH - PADDING - 2 * RADIUS, PADDING,
+ BITMAP_WIDTH - PADDING, PADDING + 2 * RADIUS);
+ expectedPath.moveTo(0, PADDING);
+ expectedPath.arcTo(oval, 270, 90);
+ expectedPath.lineTo(BITMAP_WIDTH - PADDING, BITMAP_HEIGHT);
+
+ // A paint that draws the expected path with a tolerance width into the red channel
+ Paint expectedPaint = new Paint();
+ expectedPaint.setColor(Color.RED);
+ expectedPaint.setStyle(Style.STROKE);
+ expectedPaint.setStrokeWidth(TOLERANCE);
+ expectedPaint.setXfermode(new PorterDuffXfermode(Mode.SCREEN));
+
+ canvas.drawPath(expectedPath, expectedPaint);
+
+ int numPixels = 0;
+ for (int y = 0; y < BITMAP_HEIGHT; y++) {
+ for (int x = 0; x < BITMAP_WIDTH; x++) {
+ int pixel = bitmap.getPixel(x, y);
+ if (Color.green(pixel) > 0) {
+ numPixels += 1;
+ // green path must overlap with red guide line
+ assertEquals(Color.YELLOW, pixel);
+ }
+ }
+ }
+ // number of pixels that should be on a straight line
+ int straightLines = BITMAP_WIDTH - PADDING - RADIUS + BITMAP_HEIGHT - PADDING - RADIUS;
+ // number of pixels forming the corner
+ int cornerPixels = numPixels - straightLines;
+ // rounded corner must have less pixels than a sharp corner
+ assertTrue(cornerPixels < 2 * RADIUS);
+ // ... but not as few as a diagonal
+ // ToBeFixed: The following should be assertTrue (see bug 2037365)
+ assertFalse(cornerPixels > RADIUS);
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/DashPathEffectTest.java b/tests/tests/graphics/src/android/graphics/cts/DashPathEffectTest.java
new file mode 100644
index 0000000..1e3aa17
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/DashPathEffectTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2009 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 dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.ToBeFixed;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.DashPathEffect;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathEffect;
+import android.graphics.Bitmap.Config;
+import android.graphics.Paint.Style;
+import android.util.Log;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(DashPathEffect.class)
+public class DashPathEffectTest extends TestCase {
+ private static final int BITMAP_WIDTH = 200;
+ private static final int BITMAP_HEIGHT = 20;
+ private static final int START_X = 10;
+ private static final int END_X = BITMAP_WIDTH - START_X;
+ private static final int COORD_Y = BITMAP_HEIGHT / 2;
+ private static final float[] PATTERN = new float[] { 15, 5, 10, 5 };
+ private static final int OFFSET = 5;
+ private static final int BACKGROUND = Color.TRANSPARENT;
+ private static final int FOREGROUND = Color.GREEN;
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "DashPathEffect",
+ args = {float[].class, float.class}
+ )
+ @ToBeFixed(bug = "2039296", explanation = "Javadoc for phase parameter is wrong. The phase" +
+ " determines the start offset within the pattern and not an initial gap")
+ public void testDashPathEffect() {
+ PathEffect effect = new DashPathEffect(PATTERN, OFFSET);
+ Bitmap bitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
+ bitmap.eraseColor(BACKGROUND);
+
+ Path path = new Path();
+ path.moveTo(START_X, COORD_Y);
+ path.lineTo(END_X, COORD_Y);
+
+ Paint paint = new Paint();
+ paint.setStyle(Style.STROKE);
+ paint.setStrokeWidth(0);
+ paint.setColor(FOREGROUND);
+ paint.setPathEffect(effect);
+
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawPath(path, paint);
+
+ PatternIterator iterator = new PatternIterator(PATTERN, OFFSET);
+ for (int y = 0; y < BITMAP_HEIGHT; y++) {
+ for (int x = 0; x < BITMAP_WIDTH; x++) {
+ try {
+ if (y == COORD_Y && x >= START_X && x < END_X) {
+ if (iterator.next()) {
+ assertEquals(FOREGROUND, bitmap.getPixel(x, y));
+ } else {
+ assertEquals(BACKGROUND, bitmap.getPixel(x, y));
+ }
+ } else {
+ assertEquals(BACKGROUND, bitmap.getPixel(x, y));
+ }
+ } catch (Error e) {
+ Log.w(getClass().getName(), "Failed at (" + x + "," + y + ")");
+ throw e;
+ }
+ }
+ }
+ }
+
+ private static class PatternIterator {
+ private int mPatternOffset;
+ private int mLength;
+ private final float[] mPattern;
+
+ /**
+ * Create an instance that iterates through the given pattern starting at the given offset.
+ */
+ PatternIterator(final float[] pattern, int offset) {
+ mPattern = pattern;
+ while (offset-- > 0) {
+ next();
+ }
+ }
+
+ /**
+ * Determine whether to draw the current pixel and move on to the next.
+ */
+ boolean next() {
+ int oldPatternOffset = mPatternOffset;
+ mLength += 1;
+ if (mLength == mPattern[mPatternOffset]) {
+ mLength = 0;
+ mPatternOffset += 1;
+ mPatternOffset %= mPattern.length;
+ }
+ // even offsets are 'on'
+ return (oldPatternOffset & 1) == 0;
+ }
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/DiscretePathEffectTest.java b/tests/tests/graphics/src/android/graphics/cts/DiscretePathEffectTest.java
new file mode 100644
index 0000000..d54dc83
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/DiscretePathEffectTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2009 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 dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.DiscretePathEffect;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Bitmap.Config;
+import android.graphics.Paint.Style;
+import android.graphics.PorterDuff.Mode;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(DiscretePathEffect.class)
+public class DiscretePathEffectTest extends TestCase {
+ private static final int BITMAP_WIDTH = 200;
+ private static final int BITMAP_HEIGHT = 100;
+ private static final int START_X = 10;
+ private static final int END_X = BITMAP_WIDTH - START_X;
+ private static final int COORD_Y = BITMAP_HEIGHT / 2;
+ private static final int SEGMENT_LENGTH = 10; // must be < BITMAP_WIDTH
+ private static final int DEVIATION = 10; // must be < BITMAP_HEIGHT
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "DiscretePathEffect",
+ args = {float.class, float.class}
+ )
+ public void testDiscretePathEffect() {
+ DiscretePathEffect effect = new DiscretePathEffect(SEGMENT_LENGTH, DEVIATION);
+
+ Paint paint = new Paint();
+ paint.setColor(Color.GREEN);
+ paint.setStyle(Style.STROKE);
+ paint.setStrokeWidth(0);
+ paint.setPathEffect(effect);
+
+ Path path = new Path();
+ path.moveTo(START_X, COORD_Y);
+ path.lineTo(END_X, COORD_Y);
+
+ Bitmap bitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
+ bitmap.eraseColor(Color.TRANSPARENT);
+
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawPath(path, paint);
+
+ // draw guide line into red channel (each segment should cross this once)
+ paint = new Paint();
+ paint.setColor(Color.RED);
+ paint.setStyle(Style.STROKE);
+ paint.setStrokeWidth(0);
+ paint.setXfermode(new PorterDuffXfermode(Mode.SCREEN));
+ canvas.drawPath(path, paint);
+
+ // draw guide rectangle into blue channel (each segment must be completely inside this)
+ paint.setColor(Color.BLUE);
+ paint.setStrokeWidth(1 + 2 * DEVIATION);
+ canvas.drawPath(path, paint);
+
+ int intersect = 0;
+ int numGreenPixels = 0;
+ int minY = BITMAP_HEIGHT;
+ int maxY = 0;
+ for (int y = 0; y < BITMAP_HEIGHT; y++) {
+ for (int x = 0; x < BITMAP_WIDTH; x++) {
+ int pixel = bitmap.getPixel(x, y);
+ if (Color.green(pixel) > 0) {
+ numGreenPixels += 1;
+ minY = Math.min(minY, y);
+ maxY = Math.max(maxY, y);
+ assertEquals(0xFF, Color.blue(pixel));
+ if (Color.red(pixel) > 0) {
+ intersect += 1;
+ }
+ }
+ }
+ }
+ int lineLength = END_X - START_X;
+ // the number of pixels in all segments must be at least the same as the line length
+ assertTrue(numGreenPixels >= lineLength);
+ // green line must vary in y direction
+ assertTrue(maxY - minY > 0);
+ // ... but not too much
+ assertTrue(maxY - minY <= 1 + 2 * DEVIATION);
+ // intersecting pixels must be less than line length, otherwise deviation doesn't work
+ assertTrue(intersect < lineLength);
+ // there must be at least as many intersecting pixels as there are full segments
+ assertTrue(intersect >= lineLength / SEGMENT_LENGTH);
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/EmbossMaskFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/EmbossMaskFilterTest.java
new file mode 100644
index 0000000..10bfbad
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/EmbossMaskFilterTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2009 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 dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.EmbossMaskFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.Bitmap.Config;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(EmbossMaskFilter.class)
+public class EmbossMaskFilterTest extends TestCase {
+ private static final int BITMAP_WIDTH = 100;
+ private static final int BITMAP_HEIGHT = 100;
+ private static final int START_X = 10;
+ private static final int END_X = BITMAP_WIDTH - START_X;
+ private static final int CENTER_X = (START_X + END_X) / 2;
+ private static final int CENTER_Y = BITMAP_HEIGHT / 2;
+ private static final int STROKE_WIDTH = 10;
+
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Javadoc is incomplete, cannot test all parameters",
+ method = "EmbossMaskFilter",
+ args = {float[].class, float.class, float.class, float.class}
+ )
+ public void testEmbossMaskFilter() {
+ EmbossMaskFilter filter = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.5f, 8, 3);
+
+ Paint paint = new Paint();
+ paint.setMaskFilter(filter);
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeWidth(STROKE_WIDTH);
+ paint.setColor(Color.GRAY);
+
+ Path path = new Path();
+ path.moveTo(START_X, CENTER_Y);
+ path.lineTo(END_X, CENTER_Y);
+
+ Bitmap bitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
+ bitmap.eraseColor(Color.BLACK);
+
+ Canvas c = new Canvas(bitmap);
+ c.drawPath(path, paint);
+
+ Rect top = new Rect(0, 0, BITMAP_WIDTH, CENTER_Y);
+ Rect bottom = new Rect(0, CENTER_Y, BITMAP_WIDTH, BITMAP_HEIGHT);
+ Rect left = new Rect(0, 0, CENTER_X, BITMAP_HEIGHT);
+ Rect right = new Rect(CENTER_X, 0, BITMAP_WIDTH, BITMAP_HEIGHT);
+
+ assertTrue(brightness(bitmap, top) > brightness(bitmap, bottom));
+ assertTrue(brightness(bitmap, left) > brightness(bitmap, right));
+
+ // emboss must not change anything outside the drawn shape
+ top.bottom = CENTER_Y - STROKE_WIDTH / 2;
+ assertEquals(0, brightness(bitmap, top));
+ bottom.top = CENTER_Y + STROKE_WIDTH / 2;
+ assertEquals(0, brightness(bitmap, bottom));
+ left.right = START_X;
+ assertEquals(0, brightness(bitmap, left));
+ right.left = END_X;
+ assertEquals(0, brightness(bitmap, right));
+ }
+
+ /**
+ * Calculate the cumulative brightness of all pixels in the given rectangle.
+ * Ignores alpha channel. Maximum returned value depends on the size of the rectangle.
+ */
+ private long brightness(Bitmap b, Rect rect) {
+ long color = 0;
+ for (int y = rect.top; y < rect.bottom; y++) {
+ for (int x = rect.left; x < rect.right; x++) {
+ int pixel = b.getPixel(x, y);
+ color += Color.red(pixel) + Color.green(pixel) + Color.blue(pixel);
+ }
+ }
+ return color;
+ }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
new file mode 100644
index 0000000..0bb2027
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2009 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 dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LightingColorFilter;
+import android.graphics.Paint;
+import android.graphics.Bitmap.Config;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(LightingColorFilter.class)
+public class LightingColorFilterTest extends TestCase {
+
+ private static final int TOLERANCE = 2;
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ method = "LightingColorFilter",
+ args = {int.class, int.class}
+ )
+ public void testLightingColorFilter() {
+ Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+
+ Paint paint = new Paint();
+
+ paint.setColor(Color.MAGENTA);
+ paint.setColorFilter(new LightingColorFilter(Color.WHITE, Color.BLACK));
+ canvas.drawPaint(paint);
+ assertColor(Color.MAGENTA, bitmap.getPixel(0, 0));
+
+ paint.setColor(Color.MAGENTA);
+ paint.setColorFilter(new LightingColorFilter(Color.CYAN, Color.BLACK));
+ canvas.drawPaint(paint);
+ assertColor(Color.BLUE, bitmap.getPixel(0, 0));
+
+ paint.setColor(Color.MAGENTA);
+ paint.setColorFilter(new LightingColorFilter(Color.BLUE, Color.GREEN));
+ canvas.drawPaint(paint);
+ assertColor(Color.CYAN, bitmap.getPixel(0, 0));
+
+ // alpha is ignored
+ bitmap.eraseColor(Color.TRANSPARENT);
+ paint.setColor(Color.MAGENTA);
+ paint.setColorFilter(new LightingColorFilter(Color.TRANSPARENT, Color.argb(0, 0, 0xFF, 0)));
+ canvas.drawPaint(paint);
+ assertColor(Color.GREEN, bitmap.getPixel(0, 0));
+
+ // channels get clipped (no overflow into green or alpha)
+ paint.setColor(Color.MAGENTA);
+ paint.setColorFilter(new LightingColorFilter(Color.WHITE, Color.MAGENTA));
+ canvas.drawPaint(paint);
+ assertColor(Color.MAGENTA, bitmap.getPixel(0, 0));
+
+ // multiply before add
+ paint.setColor(Color.argb(255, 60, 20, 40));
+ paint.setColorFilter(
+ new LightingColorFilter(Color.rgb(0x80, 0xFF, 0x80), Color.rgb(0, 10, 10)));
+ canvas.drawPaint(paint);
+ assertColor(Color.argb(255, 30, 30, 30), bitmap.getPixel(0, 0));
+
+ // source alpha remains unchanged
+ bitmap.eraseColor(Color.TRANSPARENT);
+ paint.setColor(Color.argb(0x80, 60, 20, 40));
+ paint.setColorFilter(
+ new LightingColorFilter(Color.rgb(0x80, 0xFF, 0x80), Color.rgb(0, 10, 10)));
+ canvas.drawPaint(paint);
+ assertColor(Color.argb(0x80, 30, 30, 30), bitmap.getPixel(0, 0));
+ }
+
+ private void assertColor(int expected, int actual) {
+ assertEquals(Color.alpha(expected), Color.alpha(actual), TOLERANCE);
+ assertEquals(Color.red(expected), Color.red(actual), TOLERANCE);
+ assertEquals(Color.green(expected), Color.green(actual), TOLERANCE);
+ assertEquals(Color.blue(expected), Color.blue(actual), TOLERANCE);
+ }
+}