1/*
2 * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @key headful
27 * @bug 6613860 6691934
28 * @summary Tests that the pipelines can handle (in somewhat limited
29 * manner) mutable Colors
30 *
31 * @run main/othervm MutableColorTest
32 * @run main/othervm -Dsun.java2d.noddraw=true MutableColorTest
33 * @run main/othervm -Dsun.java2d.opengl=True MutableColorTest
34 */
35
36import java.awt.Color;
37import java.awt.Graphics2D;
38import java.awt.GraphicsConfiguration;
39import java.awt.GraphicsEnvironment;
40import java.awt.Image;
41import java.awt.Transparency;
42import java.awt.geom.Ellipse2D;
43import java.awt.image.BufferedImage;
44import java.awt.image.VolatileImage;
45import java.io.File;
46import java.io.IOException;
47import javax.imageio.ImageIO;
48
49public class MutableColorTest {
50
51    static Image bmImage;
52    static Image argbImage;
53
54    static class EvilColor extends Color {
55        Color colors[] = { Color.red, Color.green, Color.blue };
56        int currentIndex = 0;
57        EvilColor() {
58            super(Color.red.getRGB());
59        }
60
61        @Override
62        public int getRGB() {
63            return colors[currentIndex].getRGB();
64        }
65        void nextColor() {
66            currentIndex++;
67        }
68    }
69
70    private static int testImage(Image im,
71                                 boolean doClip, boolean doTx)
72    {
73        int w = im.getWidth(null);
74        int h = im.getHeight(null);
75        Graphics2D g = (Graphics2D)im.getGraphics();
76        EvilColor evilColor = new EvilColor();
77        g.setColor(evilColor);
78        g.fillRect(0, 0, w, h);
79        g.dispose();
80
81        evilColor.nextColor();
82
83        g = (Graphics2D)im.getGraphics();
84
85        if (doTx) {
86            g.rotate(Math.PI/2.0, w/2, h/2);
87        }
88        g.setColor(evilColor);
89        g.fillRect(0, 0, w, h);
90        if (doClip) {
91            g.clip(new Ellipse2D.Float(0, 0, w, h));
92        }
93        g.fillRect(0, h/3, w, h/3);
94
95        // tests native BlitBg loop
96        g.drawImage(bmImage, 0, 2*h/3, evilColor, null);
97        // tests General BlitBg loop
98        g.drawImage(argbImage, 0, 2*h/3+h/3/2, evilColor, null);
99
100        return evilColor.getRGB();
101    }
102
103    private static void testResult(final String desc,
104                                   final BufferedImage snapshot,
105                                   final int evilColor) {
106        for (int y = 0; y < snapshot.getHeight(); y++) {
107            for (int x = 0; x < snapshot.getWidth(); x++) {
108                int snapRGB = snapshot.getRGB(x, y);
109                if (!isSameColor(snapRGB, evilColor)) {
110                    System.err.printf("Wrong RGB for %s at (%d,%d): 0x%x " +
111                        "instead of 0x%x\n", desc, x, y, snapRGB, evilColor);
112                    String fileName = "MutableColorTest_"+desc+".png";
113                    try {
114                        ImageIO.write(snapshot, "png", new File(fileName));
115                        System.err.println("Dumped snapshot to "+fileName);
116                    } catch (IOException ex) {}
117                    throw new RuntimeException("Test FAILED.");
118                }
119            }
120        }
121    }
122
123    public static void main(String[] args) {
124        GraphicsConfiguration gc =
125            GraphicsEnvironment.getLocalGraphicsEnvironment().
126                getDefaultScreenDevice().getDefaultConfiguration();
127
128        bmImage = gc.createCompatibleImage(64, 64, Transparency.BITMASK);
129        argbImage = gc.createCompatibleImage(64, 64, Transparency.TRANSLUCENT);
130
131        if (gc.getColorModel().getPixelSize() > 8) {
132            VolatileImage vi =
133                gc.createCompatibleVolatileImage(64, 64, Transparency.OPAQUE);
134            do {
135                if (vi.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) {
136                    vi = gc.createCompatibleVolatileImage(64, 64,
137                                                          Transparency.OPAQUE);
138                    vi.validate(gc);
139                }
140
141                int color = testImage(vi, false, false);
142                testResult("vi_noclip_notx", vi.getSnapshot(), color);
143
144                color = testImage(vi, true, true);
145                testResult("vi_clip_tx", vi.getSnapshot(), color);
146
147                color = testImage(vi, true, false);
148                testResult("vi_clip_notx", vi.getSnapshot(), color);
149
150                color = testImage(vi, false, true);
151                testResult("vi_noclip_tx", vi.getSnapshot(), color);
152            } while (vi.contentsLost());
153        }
154
155        BufferedImage bi = new BufferedImage(64, 64, BufferedImage.TYPE_INT_RGB);
156        int color = testImage(bi, false, false);
157        testResult("bi_noclip_notx", bi, color);
158
159        color = testImage(bi, true, true);
160        testResult("bi_clip_tx", bi, color);
161
162        color = testImage(bi, true, false);
163        testResult("bi_clip_notx", bi, color);
164
165        color = testImage(bi, false, true);
166        testResult("bi_noclip_tx", bi, color);
167
168        System.err.println("Test passed.");
169    }
170
171    /*
172     * We assume that colors with slightly different components
173     * are the same. This is done just in order to workaround
174     * peculiarities of OGL rendering pipeline on some platforms.
175     * See CR 6989217 for more details.
176     */
177     private static boolean isSameColor(int color1, int color2) {
178        final int tolerance = 2;
179
180        for (int i = 0; i < 32; i += 8) {
181            int c1 = 0xff & (color1 >> i);
182            int c2 = 0xff & (color2 >> i);
183
184            if (Math.abs(c1 - c2) > tolerance) {
185                return false;
186            }
187        }
188        return true;
189    }
190}
191