1/*
2 * Copyright (c) 2008, 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 6728834 6749060
27 * @summary Tests that LCD AA text rendering works properly with destinations
28 * being VolatileImage of all transparency types
29 * @author Dmitri.Trembovetski: area=Graphics
30 * @run main/manual/othervm -Dsun.java2d.d3d=false NonOpaqueDestLCDAATest
31 * @run main/manual/othervm NonOpaqueDestLCDAATest
32 * @run main/manual/othervm -Dsun.java2d.opengl=True NonOpaqueDestLCDAATest
33 */
34
35import java.awt.AlphaComposite;
36import java.awt.Color;
37import java.awt.Dimension;
38import java.awt.EventQueue;
39import java.awt.Font;
40import java.awt.Graphics;
41import java.awt.Graphics2D;
42import java.awt.GraphicsConfiguration;
43import java.awt.Image;
44import java.awt.RenderingHints;
45import java.awt.event.ActionEvent;
46import java.awt.event.ActionListener;
47import java.awt.event.ComponentAdapter;
48import java.awt.event.ComponentEvent;
49import java.awt.event.WindowAdapter;
50import java.awt.event.WindowEvent;
51import java.awt.image.BufferedImage;
52import java.awt.image.VolatileImage;
53import java.io.File;
54import java.util.concurrent.CountDownLatch;
55import javax.imageio.ImageIO;
56import javax.swing.JButton;
57import javax.swing.JFrame;
58import javax.swing.JPanel;
59import javax.swing.JTextArea;
60import static java.awt.Transparency.*;
61
62public class NonOpaqueDestLCDAATest extends JFrame implements ActionListener {
63    private static volatile boolean passed = true;
64    private static CountDownLatch complete = new CountDownLatch(1);
65
66    public NonOpaqueDestLCDAATest() {
67        JTextArea desc = new JTextArea();
68        desc.setText(
69            "\n  Instructions: the three text strings below should appear" +
70            "  readable, without smudges or misshapen bold glyphs.\n" +
71            "  You may need a magnifier to notice some bad colorfringing in "+
72            "  in SW Translucent case, especially in vertical stems.\n\n"+
73            "  Basically text rendered to TRANSLUCENT destination should look"+
74            "  similar to one rendered to OPAQUE - it may differ in whether or" +
75            "  not it's LCD, but it should look 'correct'\n\n"+
76            "If the text looks fine the test PASSED otherwise it FAILED.\n");
77        desc.setEditable(false);
78        desc.setBackground(Color.black);
79        desc.setForeground(Color.green);
80        add("North", desc);
81        JPanel renderPanel = new JPanel() {
82            @Override
83            public void paintComponent(Graphics g) {
84                render(g, getWidth(), getHeight());
85            }
86        };
87        renderPanel.setPreferredSize(new Dimension(1024, 650));
88        renderPanel.addComponentListener(new ComponentAdapter() {
89            @Override
90            public void componentResized(ComponentEvent e) {
91                images = null;
92            }
93        });
94        add("Center", renderPanel);
95
96        JButton passedBtn = new JButton("Passed");
97        JButton failedBtn = new JButton("Failed");
98        passedBtn.addActionListener(this);
99        failedBtn.addActionListener(this);
100        JPanel p = new JPanel();
101        p.add(passedBtn);
102        p.add(failedBtn);
103        add("South", p);
104        addWindowListener(new WindowAdapter() {
105            @Override
106            public void windowClosing(WindowEvent e) {
107                complete.countDown();
108            }
109        });
110        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
111    }
112
113    public void render(Graphics g, int w, int h) {
114        initImages(w, h);
115
116        g.setColor(new Color(0xAD, 0xD8, 0xE6));
117        g.fillRect(0, 0, w, h);
118
119        Graphics2D g2d = (Graphics2D) g.create();
120        for (Image im : images) {
121            g2d.drawImage(im, 0, 0, null);
122            g2d.translate(0, im.getHeight(null));
123        }
124    }
125
126    String tr[] = { "OPAQUE", "BITMASK", "TRANSLUCENT" };
127    @Override
128    public void actionPerformed(ActionEvent e) {
129        if (e.getActionCommand().equals("Passed")) {
130            passed = true;
131            System.out.println("Test Passed");
132        } else if (e.getActionCommand().equals("Failed")) {
133            System.out.println("Test Failed");
134            for (int i = 0; i < images.length; i++) {
135                String f = "NonOpaqueDestLCDAATest_"+tr[i];
136                try {
137                    if (images[i] instanceof VolatileImage) {
138                        f += "_vi.png";
139                        ImageIO.write(((VolatileImage)images[i]).
140                                getSnapshot(), "png", new File(f));
141                    } else {
142                        f += "_bi.png";
143                        ImageIO.write((BufferedImage)images[i],
144                                       "png", new File(f));
145                    }
146                    System.out.printf("Dumped %s image to %s\n", tr[i], f);
147                } catch (Throwable t) {}
148            }
149            passed = false;
150        }
151        dispose();
152        complete.countDown();
153    }
154
155    static void clear(Graphics2D  g, int type, int w, int h) {
156        Graphics2D gg = (Graphics2D) g.create();
157        if (type > OPAQUE) {
158            gg.setColor(new Color(0, 0, 0, 0));
159            gg.setComposite(AlphaComposite.Src);
160        } else {
161            gg.setColor(new Color(0xAD, 0xD8, 0xE6));
162        }
163        gg.fillRect(0, 0, w, h);
164    }
165
166    private void render(Image im, int type, String s) {
167        Graphics2D g2d = (Graphics2D) im.getGraphics();
168        clear(g2d, type, im.getWidth(null), im.getHeight(null));
169        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
170                RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
171        Font f = new Font("Dialog", Font.BOLD, 40);// g2d.getFont().deriveFont(32.0f);
172        g2d.setColor(Color.white);
173        g2d.setFont(g2d.getFont().deriveFont(36.0f));
174        g2d.drawString(s, 10, im.getHeight(null) / 2);
175    }
176
177    Image images[];
178    private void initImages(int w, int h) {
179        if (images == null) {
180            images = new Image[6];
181            GraphicsConfiguration gc = getGraphicsConfiguration();
182            for (int i = OPAQUE; i <= TRANSLUCENT; i++) {
183                VolatileImage vi =
184                    gc.createCompatibleVolatileImage(w,h/images.length,i);
185                images[i-1] = vi;
186                vi.validate(gc);
187                String s = "LCD AA Text rendered to " + tr[i - 1] + " HW destination";
188                render(vi, i, s);
189
190                s = "LCD AA Text rendered to " + tr[i - 1] + " SW destination";
191                images[i-1+3] = gc.createCompatibleImage(w, h/images.length, i);
192                render(images[i-1+3], i, s);
193            }
194        }
195    }
196
197    public static void main(String[] args) throws InterruptedException {
198        EventQueue.invokeLater(new Runnable() {
199            @Override
200            public void run() {
201                NonOpaqueDestLCDAATest t = new NonOpaqueDestLCDAATest();
202                t.pack();
203                t.setVisible(true);
204            }
205        });
206
207        complete.await();
208        if (!passed) {
209            throw new RuntimeException("Test Failed!");
210        }
211    }
212}
213