1 /*
   2  * Copyright (c) 2007, 2010, 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  * @bug 6613860 6691934
  27  * @summary Tests that the pipelines can handle (in somewhat limited
  28  * manner) mutable Colors
  29  *
  30  * @run main/othervm MutableColorTest
  31  * @run main/othervm -Dsun.java2d.noddraw=true MutableColorTest
  32  * @run main/othervm -Dsun.java2d.opengl=True MutableColorTest
  33  */
  34 
  35 import java.awt.Color;
  36 import java.awt.Graphics2D;
  37 import java.awt.GraphicsConfiguration;
  38 import java.awt.GraphicsEnvironment;
  39 import java.awt.Image;
  40 import java.awt.Transparency;
  41 import java.awt.geom.Ellipse2D;
  42 import java.awt.image.BufferedImage;
  43 import java.awt.image.VolatileImage;
  44 import java.io.File;
  45 import java.io.IOException;
  46 import javax.imageio.ImageIO;
  47 
  48 public class MutableColorTest {
  49 
  50     static Image bmImage;
  51     static Image argbImage;
  52 
  53     static class EvilColor extends Color {
  54         Color colors[] = { Color.red, Color.green, Color.blue };
  55         int currentIndex = 0;
  56         EvilColor() {
  57             super(Color.red.getRGB());
  58         }
  59 
  60         @Override
  61         public int getRGB() {
  62             return colors[currentIndex].getRGB();
  63         }
  64         void nextColor() {
  65             currentIndex++;
  66         }
  67     }
  68 
  69     private static int testImage(Image im,
  70                                  boolean doClip, boolean doTx)
  71     {
  72         int w = im.getWidth(null);
  73         int h = im.getHeight(null);
  74         Graphics2D g = (Graphics2D)im.getGraphics();
  75         EvilColor evilColor = new EvilColor();
  76         g.setColor(evilColor);
  77         g.fillRect(0, 0, w, h);
  78         g.dispose();
  79 
  80         evilColor.nextColor();
  81 
  82         g = (Graphics2D)im.getGraphics();
  83 
  84         if (doTx) {
  85             g.rotate(Math.PI/2.0, w/2, h/2);
  86         }
  87         g.setColor(evilColor);
  88         g.fillRect(0, 0, w, h);
  89         if (doClip) {
  90             g.clip(new Ellipse2D.Float(0, 0, w, h));
  91         }
  92         g.fillRect(0, h/3, w, h/3);
  93 
  94         // tests native BlitBg loop
  95         g.drawImage(bmImage, 0, 2*h/3, evilColor, null);
  96         // tests General BlitBg loop
  97         g.drawImage(argbImage, 0, 2*h/3+h/3/2, evilColor, null);
  98 
  99         return evilColor.getRGB();
 100     }
 101 
 102     private static void testResult(final String desc,
 103                                    final BufferedImage snapshot,
 104                                    final int evilColor) {
 105         for (int y = 0; y < snapshot.getHeight(); y++) {
 106             for (int x = 0; x < snapshot.getWidth(); x++) {
 107                 int snapRGB = snapshot.getRGB(x, y);
 108                 if (!isSameColor(snapRGB, evilColor)) {
 109                     System.err.printf("Wrong RGB for %s at (%d,%d): 0x%x " +
 110                         "instead of 0x%x\n", desc, x, y, snapRGB, evilColor);
 111                     String fileName = "MutableColorTest_"+desc+".png";
 112                     try {
 113                         ImageIO.write(snapshot, "png", new File(fileName));
 114                         System.err.println("Dumped snapshot to "+fileName);
 115                     } catch (IOException ex) {}
 116                     throw new RuntimeException("Test FAILED.");
 117                 }
 118             }
 119         }
 120     }
 121 
 122     public static void main(String[] args) {
 123         GraphicsConfiguration gc =
 124             GraphicsEnvironment.getLocalGraphicsEnvironment().
 125                 getDefaultScreenDevice().getDefaultConfiguration();
 126 
 127         bmImage = gc.createCompatibleImage(64, 64, Transparency.BITMASK);
 128         argbImage = gc.createCompatibleImage(64, 64, Transparency.TRANSLUCENT);
 129 
 130         if (gc.getColorModel().getPixelSize() > 8) {
 131             VolatileImage vi =
 132                 gc.createCompatibleVolatileImage(64, 64, Transparency.OPAQUE);
 133             do {
 134                 if (vi.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE) {
 135                     vi = gc.createCompatibleVolatileImage(64, 64,
 136                                                           Transparency.OPAQUE);
 137                     vi.validate(gc);
 138                 }
 139 
 140                 int color = testImage(vi, false, false);
 141                 testResult("vi_noclip_notx", vi.getSnapshot(), color);
 142 
 143                 color = testImage(vi, true, true);
 144                 testResult("vi_clip_tx", vi.getSnapshot(), color);
 145 
 146                 color = testImage(vi, true, false);
 147                 testResult("vi_clip_notx", vi.getSnapshot(), color);
 148 
 149                 color = testImage(vi, false, true);
 150                 testResult("vi_noclip_tx", vi.getSnapshot(), color);
 151             } while (vi.contentsLost());
 152         }
 153 
 154         BufferedImage bi = new BufferedImage(64, 64, BufferedImage.TYPE_INT_RGB);
 155         int color = testImage(bi, false, false);
 156         testResult("bi_noclip_notx", bi, color);
 157 
 158         color = testImage(bi, true, true);
 159         testResult("bi_clip_tx", bi, color);
 160 
 161         color = testImage(bi, true, false);
 162         testResult("bi_clip_notx", bi, color);
 163 
 164         color = testImage(bi, false, true);
 165         testResult("bi_noclip_tx", bi, color);
 166 
 167         System.err.println("Test passed.");
 168     }
 169 
 170     /*
 171      * We assume that colors with slightly different components
 172      * are the same. This is done just in order to workaround
 173      * peculiarities of OGL rendering pipeline on some platforms.
 174      * See CR 6989217 for more details.
 175      */
 176      private static boolean isSameColor(int color1, int color2) {
 177         final int tolerance = 2;
 178 
 179         for (int i = 0; i < 32; i += 8) {
 180             int c1 = 0xff & (color1 >> i);
 181             int c2 = 0xff & (color2 >> i);
 182 
 183             if (Math.abs(c1 - c2) > tolerance) {
 184                 return false;
 185             }
 186         }
 187         return true;
 188     }
 189 }