1 /*
2  * Copyright (c) 2007, 2018, 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 8198613
28  * @summary Tests that transformed Paints are rendered correctly
29  * @author Dmitri.Trembovetski@sun.com: area=Graphics
30  * @run main/othervm 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 
createPaint(PaintType type, int startx, int starty, int w, int h)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 
renderLine(PaintType type, Graphics2D g, int startx, int starty, int w, int h)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 
render(Graphics2D g, int w, int h)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 
checkBI(BufferedImage bi)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 
runTest()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 
showFrame(final TransformedPaintTest t)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 
main(String[] args)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 }
220