/*
 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
/*
 * @test
 * @bug 5009033 6603000 6666362
 * @summary Verifies that images transformed with bilinear filtering do not
 * leave artifacts at the edges.
 * @run main/othervm DrawImageBilinear
 * @run main/othervm -Dsun.java2d.opengl=True DrawImageBilinear
 * @author campbelc
 */

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.awt.image.VolatileImage;

public class DrawImageBilinear extends Canvas {

    private static final int SIZE = 5;

    private static boolean done;
    private BufferedImage bimg1, bimg2;
    private VolatileImage vimg;
    private static volatile BufferedImage capture;
    private static void doCapture(Component test) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ex) {}
        // Grab the screen region
        try {
            Robot robot = new Robot();
            Point pt1 = test.getLocationOnScreen();
            Rectangle rect =
                new Rectangle(pt1.x, pt1.y, test.getWidth(), test.getHeight());
            capture = robot.createScreenCapture(rect);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void renderPattern(Graphics g) {
        g.setColor(Color.red);
        g.fillRect(0, 0, SIZE, SIZE);
        //g.setColor(Color.green);
        //g.drawRect(0, 0, SIZE-1, SIZE-1);
        g.dispose();
    }

    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;

        if (bimg1 == null) {
            bimg1 = (BufferedImage)createImage(SIZE, SIZE);
            bimg1.setAccelerationPriority(0.0f);
            renderPattern(bimg1.createGraphics());

            bimg2 = (BufferedImage)createImage(SIZE, SIZE);
            renderPattern(bimg2.createGraphics());

            vimg = createVolatileImage(SIZE, SIZE);
            vimg.validate(getGraphicsConfiguration());
            renderPattern(vimg.createGraphics());
        }

        do {
            g2d.setColor(Color.white);
            g2d.fillRect(0, 0, getWidth(), getHeight());

            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                                 RenderingHints.VALUE_INTERPOLATION_BILINEAR);

            // first time will be a sw->surface blit
            g2d.drawImage(bimg1, 10, 10, 40, 40, null);

            // second time will be a texture->surface blit
            g2d.drawImage(bimg2, 80, 10, 40, 40, null);
            if (!skipOglTextureTest) {
                g2d.drawImage(bimg2, 80, 10, 40, 40, null);
            }

            // third time will be a pbuffer->surface blit
            if (vimg.validate(getGraphicsConfiguration()) != VolatileImage.IMAGE_OK) {
                renderPattern(vimg.createGraphics());
            }
            g2d.drawImage(vimg, 150, 10, 40, 40, null);

            Toolkit.getDefaultToolkit().sync();
        } while (vimg.contentsLost());

        synchronized (this) {
            if (!done) {
                doCapture(this);
                done = true;
            }
            notifyAll();
        }
    }

    public Dimension getPreferredSize() {
        return new Dimension(200, 100);
    }

    private static void testRegion(BufferedImage bi,
                                   Rectangle affectedRegion)
    {
        int x1 = affectedRegion.x;
        int y1 = affectedRegion.y;
        int x2 = x1 + affectedRegion.width;
        int y2 = y1 + affectedRegion.height;

        for (int y = y1; y < y2; y++) {
            for (int x = x1; x < x2; x++) {
                int actual = bi.getRGB(x, y);
                if ((actual != 0xfffe0000) && (actual != 0xffff0000)) {
                    throw new RuntimeException("Test failed at x="+x+" y="+y+
                                               " (expected=0xffff0000"+
                                               " actual=0x"+
                                               Integer.toHexString(actual) +
                                               ")");
                }
            }
        }
    }

    private static boolean skipOglTextureTest = false;

    public static void main(String[] args) {
        boolean show = false;
        for (String arg : args) {
            if ("-show".equals(arg)) {
                show = true;
            }
        }

        String arch = System.getProperty("os.arch");
        boolean isOglEnabled = Boolean.getBoolean("sun.java2d.opengl");
        skipOglTextureTest = isOglEnabled && ("sparc".equals(arch));
        System.out.println("Skip OpenGL texture test: " + skipOglTextureTest);

        DrawImageBilinear test = new DrawImageBilinear();
        Frame frame = new Frame();
        frame.add(test);
        frame.pack();
        frame.setVisible(true);

        // Wait until the component's been painted
        synchronized (test) {
            while (!done) {
                try {
                    test.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException("Failed: Interrupted");
                }
            }
        }

        GraphicsConfiguration gc = frame.getGraphicsConfiguration();
        if (gc.getColorModel() instanceof IndexColorModel) {
            System.out.println("IndexColorModel detected: " +
                               "test considered PASSED");
            frame.dispose();
            return;
        }

        if (!show) {
            frame.dispose();
        }
        if (capture == null) {
            throw new RuntimeException("Failed: capture is null");
        }

        // Test background color
        int pixel = capture.getRGB(5, 5);
        if (pixel != 0xffffffff) {
            throw new RuntimeException("Failed: Incorrect color for " +
                                       "background");
        }

        // Test pixels
        testRegion(capture, new Rectangle(10, 10, 40, 40));
        testRegion(capture, new Rectangle(80, 10, 40, 40));
        testRegion(capture, new Rectangle(150, 10, 40, 40));
    }
}
