Merge change 9520 into donut

* changes:
  Integrate unsubmitted cupcake change 131131: 	CTS: add test cases for graphics.LinearGradient, PaintFlagsDrawFilter, PathDashPathEffect, PixelXorXfermode and PorterDuffColorFilter
diff --git a/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java b/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java
new file mode 100644
index 0000000..2f26272
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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 dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Bitmap.Config;
+import android.graphics.Shader.TileMode;
+import android.test.AndroidTestCase;
+
+@TestTargetClass(LinearGradient.class)
+public class LinearGradientTest extends AndroidTestCase {
+
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "LinearGradient",
+            args = {float.class, float.class, float.class, float.class, int[].class, float[].class,
+                    android.graphics.Shader.TileMode.class}
+        ),
+        @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "LinearGradient",
+            args = {float.class, float.class, float.class, float.class, int.class, int.class,
+                    android.graphics.Shader.TileMode.class}
+        )
+    })
+    public void testLinearGradient() {
+        Bitmap b;
+        LinearGradient lg;
+        int[] color = { Color.BLUE, Color.GREEN, Color.RED };
+        float[] position = { 0.0f, 1.0f / 3.0f, 2.0f / 3.0f };
+
+        lg = new LinearGradient(0, 0, 0, 40, color, position, TileMode.CLAMP);
+        b = drawLinearGradient(lg);
+
+        // The pixels in same gradient line should be equivalent
+        assertEquals(b.getPixel(10, 10), b.getPixel(20, 10));
+        // BLUE -> GREEN, B sub-value decreasing while G sub-value increasing
+        assertTrue(Color.blue(b.getPixel(10, 0)) > Color.blue(b.getPixel(10, 5)));
+        assertTrue(Color.blue(b.getPixel(10, 5)) > Color.blue(b.getPixel(10, 10)));
+        assertTrue(Color.green(b.getPixel(10, 0)) < Color.green(b.getPixel(10, 5)));
+        assertTrue(Color.green(b.getPixel(10, 5)) < Color.green(b.getPixel(10, 10)));
+        // GREEN -> RED, G sub-value decreasing while R sub-value increasing
+        assertTrue(Color.green(b.getPixel(10, 15)) > Color.green(b.getPixel(10, 20)));
+        assertTrue(Color.green(b.getPixel(10, 20)) > Color.green(b.getPixel(10, 25)));
+        assertTrue(Color.red(b.getPixel(10, 15)) < Color.red(b.getPixel(10, 20)));
+        assertTrue(Color.red(b.getPixel(10, 20)) < Color.red(b.getPixel(10, 25)));
+
+        lg = new LinearGradient(0, 0, 0, 40, Color.RED, Color.BLUE, TileMode.CLAMP);
+        b= drawLinearGradient(lg);
+
+        // The pixels in same gradient line should be equivalent
+        assertEquals(b.getPixel(10, 10), b.getPixel(20, 10));
+        // RED -> BLUE, R sub-value decreasing while B sub-value increasing
+        assertTrue(Color.red(b.getPixel(10, 0)) > Color.red(b.getPixel(10, 15)));
+        assertTrue(Color.red(b.getPixel(10, 15)) > Color.red(b.getPixel(10, 30)));
+        assertTrue(Color.blue(b.getPixel(10, 0)) < Color.blue(b.getPixel(10, 15)));
+        assertTrue(Color.blue(b.getPixel(10, 15)) < Color.blue(b.getPixel(10, 30)));
+    }
+
+    private Bitmap drawLinearGradient(LinearGradient lg) {
+        Paint paint = new Paint();
+        paint.setShader(lg);
+        Bitmap b = Bitmap.createBitmap(40, 40, Config.ARGB_8888);
+        b.eraseColor(Color.BLACK);
+        Canvas canvas = new Canvas(b);
+        canvas.drawPaint(paint);
+        return b;
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java
new file mode 100644
index 0000000..bf39818
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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 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.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.Rect;
+import android.graphics.Bitmap.Config;
+import android.graphics.Paint.Align;
+import android.test.AndroidTestCase;
+
+@TestTargetClass(PaintFlagsDrawFilter.class)
+public class PaintFlagsDrawFilterTest extends AndroidTestCase {
+
+    private static final float TEXT_SIZE = 20;
+    private static final float TEXT_X = 50;
+    private static final float TEXT_Y = 50;
+    private static final String TEXT = "Test";
+    private static final int BITMAP_WIDTH = 100;
+    private static final int BITMAP_HEIGHT = 100;
+    private float mTextWidth;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "PaintFlagsDrawFilter",
+        args = {int.class, int.class}
+    )
+    public void testPaintFlagsDrawFilter() {
+
+        Bitmap bitmapWithoutFilter = drawText(null);
+
+        PaintFlagsDrawFilter filter = new PaintFlagsDrawFilter(Paint.UNDERLINE_TEXT_FLAG, 0);
+        Bitmap bitmapWithFilter = drawText(filter);
+
+        Bitmap combined = delta(bitmapWithoutFilter, bitmapWithFilter);
+        assertUnderline(combined);
+    }
+
+    private Bitmap drawText(PaintFlagsDrawFilter filter) {
+        Paint p = new Paint(Paint.UNDERLINE_TEXT_FLAG);
+        p.setColor(Color.RED);
+        p.setTextSize(TEXT_SIZE);
+        p.setTextAlign(Align.CENTER);
+        mTextWidth = p.measureText(TEXT);
+        Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
+        Canvas c = new Canvas(b);
+        c.setDrawFilter(filter);
+        c.drawColor(Color.BLACK);
+        c.drawText(TEXT, TEXT_X, TEXT_Y, p);
+        return b;
+    }
+
+    private Bitmap delta(Bitmap bitmapWithoutFilter, Bitmap bitmapWithFilter) {
+        Bitmap combinedBitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Config.ARGB_8888);
+        combinedBitmap.eraseColor(Color.BLACK);
+        int pixelWithoutFilter;
+        int pixelWithFilter;
+        for (int i = 0; i < BITMAP_WIDTH; i++) {
+            for (int j = 0; j < BITMAP_HEIGHT; j++) {
+                pixelWithoutFilter = bitmapWithoutFilter.getPixel(i, j);
+                pixelWithFilter = bitmapWithFilter.getPixel(i, j);
+                if (pixelWithoutFilter != pixelWithFilter) {
+                    assertEquals(Color.RED, pixelWithoutFilter);
+                    assertEquals(Color.BLACK, pixelWithFilter);
+                    combinedBitmap.setPixel(i, j, Color.RED);
+                }
+            }
+        }
+        return combinedBitmap;
+    }
+
+    private void assertUnderline(Bitmap bitmap) {
+        // Find smallest rectangle containing all RED pixels
+        Rect rect = new Rect(BITMAP_WIDTH, BITMAP_HEIGHT, 0, 0);
+        for (int y = 0; y < BITMAP_HEIGHT; y++) {
+            for (int x = 0; x < BITMAP_WIDTH; x++) {
+                int pixel = bitmap.getPixel(x, y);
+                if (pixel == Color.RED) {
+                    rect.left = Math.min(rect.left, x);
+                    rect.right = Math.max(rect.right, x);
+                    rect.top = Math.min(rect.top, y);
+                    rect.bottom = Math.max(rect.bottom, y);
+                }
+            }
+        }
+        // underline is at least one pixel high
+        assertTrue(rect.top <= rect.bottom);
+        // underline is roughly the same length at the text (5% tolerance)
+        assertEquals(mTextWidth, rect.right - rect.left, mTextWidth * 0.05);
+        // underline is under the text or at least at the bottom of it
+        assertTrue(rect.top >= TEXT_Y);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PathDashPathEffectTest.java b/tests/tests/graphics/src/android/graphics/cts/PathDashPathEffectTest.java
new file mode 100644
index 0000000..eadd932
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/PathDashPathEffectTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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 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.Paint;
+import android.graphics.Path;
+import android.graphics.PathDashPathEffect;
+import android.graphics.RectF;
+import android.graphics.Bitmap.Config;
+import android.graphics.Path.Direction;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(PathDashPathEffect.class)
+public class PathDashPathEffectTest extends TestCase {
+
+    private static final int SQUARE = 10;
+    private static final int ADVANCE = 30;
+    private static final int WIDTH = 100;
+    private static final int HEIGHT = 100;
+
+    @TestTargetNew(
+        level = TestLevel.SUFFICIENT,
+        method = "PathDashPathEffect",
+        args = {android.graphics.Path.class, float.class, float.class,
+                android.graphics.PathDashPathEffect.Style.class}
+    )
+    public void testPathDashPathEffect() {
+        Bitmap b = Bitmap.createBitmap(WIDTH, HEIGHT, Config.ARGB_8888);
+        b.eraseColor(Color.BLACK);
+        PathDashPathEffect effect = new PathDashPathEffect(shape(), ADVANCE, 0,
+                PathDashPathEffect.Style.TRANSLATE);
+        Canvas canvas = new Canvas(b);
+        Paint p = new Paint();
+        p.setPathEffect(effect);
+        p.setColor(Color.RED);
+        canvas.drawPath(path(), p);
+
+        Bitmap expected = Bitmap.createBitmap(WIDTH, HEIGHT, Config.ARGB_8888);
+        expected.eraseColor(Color.BLACK);
+        canvas = new Canvas(expected);
+        p = new Paint();
+        p.setColor(Color.RED);
+        RectF rect = new RectF(0, HEIGHT / 2 - SQUARE, 0, HEIGHT / 2 + SQUARE);
+        for (int i = 0; i <= WIDTH + SQUARE; i += ADVANCE) {
+            rect.left = i - SQUARE;
+            rect.right = i + SQUARE;
+            canvas.drawRect(rect, p);
+        }
+
+        int diffCount = 0;
+        for (int y = 0; y < HEIGHT; y++) {
+            for (int x = 0; x < WIDTH; x++) {
+                if (expected.getPixel(x, y) != b.getPixel(x, y)) {
+                    diffCount += 1;
+                }
+            }
+        }
+        assertEquals(0, diffCount);
+    }
+
+    private static Path path() {
+        Path p = new Path();
+        p.moveTo(0, HEIGHT / 2);
+        p.lineTo(WIDTH, HEIGHT / 2);
+        return p;
+    }
+
+    private static Path shape() {
+        Path p = new Path();
+        p.addRect(new RectF(-SQUARE, -SQUARE, SQUARE, SQUARE), Direction.CCW);
+        return p;
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PixelXorXfermodeTest.java b/tests/tests/graphics/src/android/graphics/cts/PixelXorXfermodeTest.java
new file mode 100644
index 0000000..780e49a
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/PixelXorXfermodeTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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 android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PixelXorXfermode;
+import android.graphics.Bitmap.Config;
+import android.test.AndroidTestCase;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@TestTargetClass(PixelXorXfermode.class)
+public class PixelXorXfermodeTest extends AndroidTestCase {
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "PixelXorXfermode",
+        args = {int.class}
+    )
+    public void testPixelXorXfermode() {
+        int width = 100;
+        int height = 100;
+        Bitmap b1 = Bitmap.createBitmap(width / 2, height, Config.ARGB_8888);
+        b1.eraseColor(Color.WHITE);
+        Bitmap b2 = Bitmap.createBitmap(width, height / 2, Config.ARGB_8888);
+        b2.eraseColor(Color.CYAN);
+
+        Bitmap target = Bitmap.createBitmap(width, height, Config.ARGB_8888);
+        target.eraseColor(Color.BLACK);
+        Canvas canvas = new Canvas(target);
+        Paint p = new Paint();
+        canvas.drawBitmap(b1, 0, 0, p);
+        p.setXfermode(new PixelXorXfermode(Color.GREEN));
+        canvas.drawBitmap(b2, 0, height / 2, p);
+        assertEquals(Color.WHITE, target.getPixel(width / 4, height / 4));
+        // white ^ green ^ cyan = yellow
+        assertEquals(Color.YELLOW, target.getPixel(width / 4, height * 3 / 4));
+        // black ^ green ^ cyan = blue
+        assertEquals(Color.BLUE, target.getPixel(width * 3 / 4, height * 3 / 4));
+
+        // XOR transfer always results in an opaque image
+        p.setXfermode(new PixelXorXfermode(alphaColor(Color.GREEN, 25)));
+        target.eraseColor(alphaColor(Color.BLACK, 42));
+        p.setColor(alphaColor(Color.CYAN, 5));
+        canvas.drawPaint(p);
+        // result is always opaque, even though all inputs have alpha
+        assertEquals(255, Color.alpha(target.getPixel(0, 0)));
+    }
+
+    private int alphaColor(int color, int alpha) {
+        int red = Color.red(color);
+        int green = Color.green(color);
+        int blue = Color.blue(color);
+        return Color.argb(alpha, red, green, blue);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java
new file mode 100644
index 0000000..e0f5bd2
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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 android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.Bitmap.Config;
+import android.test.AndroidTestCase;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+@TestTargetClass(PorterDuffColorFilter.class)
+public class PorterDuffColorFilterTest extends AndroidTestCase {
+
+    private static final int TOLERANCE = 5;
+
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        method = "PorterDuffColorFilter",
+        args = {int.class, PorterDuff.Mode.class}
+    )
+    public void testPorterDuffColorFilter() {
+        int width = 100;
+        int height = 100;
+        Bitmap b1 = Bitmap.createBitmap(width / 2, height, Config.ARGB_8888);
+        b1.eraseColor(Color.RED);
+        Bitmap b2 = Bitmap.createBitmap(width, height / 2, Config.ARGB_8888);
+        b2.eraseColor(Color.BLUE);
+
+        Bitmap target = Bitmap.createBitmap(width, height, Config.ARGB_8888);
+        target.eraseColor(Color.TRANSPARENT);
+        Canvas canvas = new Canvas(target);
+        // semi-transparent green
+        int filterColor = Color.argb(0x80, 0, 0xFF, 0);
+        PorterDuffColorFilter filter = new PorterDuffColorFilter(filterColor, PorterDuff.Mode.SRC);
+        Paint p = new Paint();
+        canvas.drawBitmap(b1, 0, 0, p);
+        p.setColorFilter(filter);
+        canvas.drawBitmap(b2, 0, height / 2, p);
+        assertEquals(Color.RED, target.getPixel(width / 4, height / 4));
+        int lowerLeft = target.getPixel(width / 4, height * 3 / 4);
+        assertEquals(0x80, Color.red(lowerLeft), TOLERANCE);
+        assertEquals(0x80, Color.green(lowerLeft), TOLERANCE);
+        int lowerRight = target.getPixel(width * 3 / 4, height * 3 / 4);
+        assertEquals(filterColor, lowerRight);
+
+        target.eraseColor(Color.BLACK);
+        filter = new PorterDuffColorFilter(filterColor, PorterDuff.Mode.DST);
+        p.setColorFilter(null);
+        canvas.drawBitmap(b1, 0, 0, p);
+        p.setColorFilter(filter);
+        canvas.drawBitmap(b2, 0, height / 2, p);
+        assertEquals(Color.RED, target.getPixel(width / 4, height / 4));
+        assertEquals(Color.BLUE, target.getPixel(width / 4, height * 3 / 4));
+        assertEquals(Color.BLUE, target.getPixel(width * 3 / 4, height * 3 / 4));
+
+        target.eraseColor(Color.BLACK);
+        filter = new PorterDuffColorFilter(Color.GREEN, PorterDuff.Mode.SCREEN);
+        p.setColorFilter(null);
+        canvas.drawBitmap(b1, 0, 0, p);
+        p.setColorFilter(filter);
+        canvas.drawBitmap(b2, 0, height / 2, p);
+        assertEquals(Color.RED, target.getPixel(width / 4, height / 4));
+        assertEquals(Color.CYAN, target.getPixel(width / 4, height * 3 / 4));
+        assertEquals(Color.CYAN, target.getPixel(width * 3 / 4, height * 3 / 4));
+    }
+}