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