1 /*
   2  * Copyright (c) 2007, 2013, 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 6689025 8023483
  27  * @summary Tests that transformed Paints are rendered correctly
  28  * @author Dmitri.Trembovetski@sun.com: area=Graphics
  29  * @run main/othervm TransformedPaintTest
  30  * @run main/othervm -Dsun.java2d.opengl=True TransformedPaintTest
  31  */
  32 
  33 import java.awt.Color;
  34 import java.awt.Dimension;
  35 import java.awt.EventQueue;
  36 import java.awt.GradientPaint;
  37 import java.awt.Graphics;
  38 import java.awt.Graphics2D;
  39 import java.awt.GraphicsConfiguration;
  40 import java.awt.GraphicsEnvironment;
  41 import java.awt.LinearGradientPaint;
  42 import java.awt.MultipleGradientPaint.CycleMethod;
  43 import java.awt.Paint;
  44 import java.awt.RadialGradientPaint;
  45 import java.awt.TexturePaint;
  46 import java.awt.geom.Rectangle2D;
  47 import java.awt.image.BufferedImage;
  48 import java.awt.image.VolatileImage;
  49 import java.io.File;
  50 import java.io.IOException;
  51 import java.lang.reflect.InvocationTargetException;
  52 import javax.imageio.ImageIO;
  53 import javax.swing.JFrame;
  54 import javax.swing.JPanel;
  55 
  56 public class TransformedPaintTest {
  57 
  58     private static enum PaintType {
  59         COLOR,
  60         GRADIENT,
  61         LINEAR_GRADIENT,
  62         RADIAL_GRADIENT,
  63         TEXTURE
  64     };
  65 
  66     private static final int CELL_SIZE = 100;
  67     private static final int R_WIDTH = 3 * CELL_SIZE;
  68     private static final int R_HEIGHT = PaintType.values().length * CELL_SIZE;
  69 
  70     private Paint createPaint(PaintType type, int startx, int starty,
  71                               int w, int h)
  72     {
  73         // make sure that the blue color doesn't show up when filling a
  74         // w by h rect
  75         w++; h++;
  76 
  77         int endx = startx + w;
  78         int endy = starty + h;
  79         Rectangle2D.Float r = new Rectangle2D.Float(startx, starty, w, h);
  80         switch (type) {
  81             case COLOR: return Color.red;
  82             case GRADIENT: return
  83                 new GradientPaint(startx, starty, Color.red,
  84                                   endx, endy, Color.green);
  85             case LINEAR_GRADIENT: return
  86                 new LinearGradientPaint(startx, starty, endx, endy,
  87                     new float[] { 0.0f, 0.999f, 1.0f },
  88                     new Color[] { Color.red, Color.green, Color.blue });
  89             case RADIAL_GRADIENT: return
  90                 new RadialGradientPaint(startx, starty,
  91                     (float)Math.sqrt(w * w + h * h),
  92                     new float[] { 0.0f, 0.999f, 1.0f },
  93                     new Color[] { Color.red, Color.green, Color.blue },
  94                     CycleMethod.NO_CYCLE);
  95             case TEXTURE: {
  96                 BufferedImage bi =
  97                     new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
  98                 Graphics2D g = (Graphics2D) bi.getGraphics();
  99                 g.setPaint(createPaint(PaintType.LINEAR_GRADIENT, 0, 0, w, h));
 100                 g.fillRect(0, 0, w, h);
 101                 return new TexturePaint(bi, r);
 102             }
 103         }
 104         return Color.green;
 105     }
 106 
 107     private void renderLine(PaintType type, Graphics2D g,
 108                             int startx, int starty, int w, int h)
 109     {
 110         Paint p = createPaint(type, startx, starty, w, h);
 111         g.setPaint(p);
 112 
 113         // first, no transform
 114         g.fillRect(startx, starty, w, h);
 115 
 116         // translation only
 117         g.translate(w, 0);
 118         g.fillRect(startx, starty, w, h);
 119         g.translate(-w, 0);
 120 
 121         // complex transform
 122         g.translate(startx + w*2, starty);
 123         g.rotate(Math.toRadians(90), w/2, h/2);
 124         g.translate(-startx, -starty);
 125         g.fillRect(startx, starty, w, h);
 126     }
 127 
 128     private void render(Graphics2D g, int w, int h) {
 129         int paintTypes = PaintType.values().length;
 130         int ystep = h / paintTypes;
 131         int y = 0;
 132 
 133         for (PaintType type : PaintType.values()) {
 134             renderLine(type, (Graphics2D)g.create(),
 135                        0, y, h / paintTypes, h / paintTypes);
 136             y += ystep;
 137         }
 138     }
 139 
 140     private void checkBI(BufferedImage bi) {
 141         for (int y = 0; y < bi.getHeight(); y++) {
 142             for (int x = 0; x < bi.getWidth(); x++) {
 143                 if (bi.getRGB(x, y) == Color.blue.getRGB()) {
 144                     try {
 145                         String fileName = "TransformedPaintTest_res.png";
 146                         ImageIO.write(bi, "png", new File(fileName));
 147                         System.err.println("Dumped image to: " + fileName);
 148                     } catch (IOException ex) {}
 149                     throw new RuntimeException("Test failed, blue color found");
 150                 }
 151             }
 152         }
 153     }
 154 
 155     private void runTest() {
 156         GraphicsConfiguration gc = GraphicsEnvironment.
 157             getLocalGraphicsEnvironment().getDefaultScreenDevice().
 158                 getDefaultConfiguration();
 159 
 160         if (gc.getColorModel().getPixelSize() < 16) {
 161             System.out.println("8-bit desktop depth found, test passed");
 162             return;
 163         }
 164 
 165         VolatileImage vi = gc.createCompatibleVolatileImage(R_WIDTH, R_HEIGHT);
 166         BufferedImage bi = null;
 167         do {
 168             vi.validate(gc);
 169             Graphics2D g = vi.createGraphics();
 170             render(g, vi.getWidth(), vi.getHeight());
 171             bi = vi.getSnapshot();
 172         } while (vi.contentsLost());
 173 
 174         checkBI(bi);
 175         System.out.println("Test PASSED.");
 176     }
 177 
 178     private static void showFrame(final TransformedPaintTest t) {
 179         JFrame f = new JFrame("TransformedPaintTest");
 180         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 181         final BufferedImage bi =
 182             new BufferedImage(R_WIDTH, R_HEIGHT, BufferedImage.TYPE_INT_RGB);
 183         JPanel p = new JPanel() {
 184             @Override
 185             protected void paintComponent(Graphics g) {
 186                 super.paintComponent(g);
 187                 Graphics2D g2d = (Graphics2D) g;
 188                 t.render(g2d, R_WIDTH, R_HEIGHT);
 189                 t.render(bi.createGraphics(), R_WIDTH, R_HEIGHT);
 190                 g2d.drawImage(bi, R_WIDTH + 5, 0, null);
 191 
 192                 g.setColor(Color.black);
 193                 g.drawString("Rendered to Back Buffer", 10, 20);
 194                 g.drawString("Rendered to BufferedImage", R_WIDTH + 15, 20);
 195             }
 196         };
 197         p.setPreferredSize(new Dimension(2 * R_WIDTH + 5, R_HEIGHT));
 198         f.add(p);
 199         f.pack();
 200         f.setVisible(true);
 201     }
 202 
 203     public static void main(String[] args) throws
 204         InterruptedException, InvocationTargetException
 205     {
 206         boolean show = (args.length > 0 && "-show".equals(args[0]));
 207 
 208         final TransformedPaintTest t = new TransformedPaintTest();
 209         if (show) {
 210             EventQueue.invokeAndWait(new Runnable() {
 211                 public void run() {
 212                     showFrame(t);
 213                 }
 214             });
 215         } else {
 216             t.runTest();
 217         }
 218     }
 219 }