/*
 * 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);
    }
}
