1 /*
2  * Copyright (c) 2014, 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 import java.awt.Color;
25 import java.awt.Font;
26 import java.awt.Graphics2D;
27 import java.awt.RenderingHints;
28 import java.awt.geom.AffineTransform;
29 import java.awt.image.BufferedImage;
30 import java.io.File;
31 import java.io.IOException;
32 
33 import javax.imageio.ImageIO;
34 
35 import static java.awt.image.BufferedImage.TYPE_INT_RGB;
36 import static java.lang.Math.toRadians;
37 
38 /**
39  * @test
40  * @bug 8065373
41  * @summary Verifies that we get correct direction, when draw rotated string.
42  * @author Sergey Bylokhov
43  * @run main DrawRotatedStringUsingRotatedFont
44  */
45 public final class DrawRotatedStringUsingRotatedFont {
46 
47     private static final int SIZE = 500;
48     private static final String STR = "MMMMMMMMMMMMMMMM";
49 
50     private static AffineTransform[] txs = {
51                             AffineTransform.getRotateInstance(toRadians(00)),
52                             AffineTransform.getRotateInstance(toRadians(45)),
53                             AffineTransform.getRotateInstance(toRadians(-45)),
54                             AffineTransform.getRotateInstance(toRadians(90)),
55                             AffineTransform.getRotateInstance(toRadians(-90)),
56                             AffineTransform.getRotateInstance(toRadians(135)),
57                             AffineTransform.getRotateInstance(toRadians(-135)),
58                             AffineTransform.getRotateInstance(toRadians(180)),
59                             AffineTransform.getRotateInstance(toRadians(-180)),
60                             AffineTransform.getRotateInstance(toRadians(225)),
61                             AffineTransform.getRotateInstance(toRadians(-225)),
62                             AffineTransform.getRotateInstance(toRadians(270)),
63                             AffineTransform.getRotateInstance(toRadians(-270)),
64                             AffineTransform.getRotateInstance(toRadians(315)),
65                             AffineTransform.getRotateInstance(toRadians(-315)),
66                             AffineTransform.getRotateInstance(toRadians(360)),
67                             AffineTransform.getRotateInstance(toRadians(-360))
68     };
69 
main(final String[] args)70     public static void main(final String[] args) throws IOException {
71         for (final AffineTransform tx2 : txs) {
72             for (final AffineTransform tx1 : txs) {
73                 for (final boolean aa : new boolean[]{true, false}) {
74                     final BufferedImage bi1 = createImage(aa, tx1, tx2);
75                     final BufferedImage bi2 = createImage(aa, tx2, tx1);
76                     compareImage(bi1, bi2);
77                     fillTextArea(bi1, tx1, tx2);
78                     fillTextArea(bi2, tx2, tx1);
79                     checkColors(bi1, bi2);
80                 }
81             }
82         }
83         System.out.println("Passed");
84     }
85 
86     /**
87      * Compares two images.
88      */
compareImage(final BufferedImage bi1, final BufferedImage bi2)89     private static void compareImage(final BufferedImage bi1,
90                                      final BufferedImage bi2)
91             throws IOException {
92         for (int i = 0; i < SIZE; ++i) {
93             for (int j = 0; j < SIZE; ++j) {
94                 if (bi1.getRGB(i, j) != bi2.getRGB(i, j)) {
95                     ImageIO.write(bi1, "png", new File("image1.png"));
96                     ImageIO.write(bi2, "png", new File("image2.png"));
97                     throw new RuntimeException("Failed: wrong text location");
98                 }
99             }
100         }
101     }
102 
103     /**
104      * Checks an image color. RED and GREEN are allowed only.
105      */
checkColors(final BufferedImage bi1, final BufferedImage bi2)106     private static void checkColors(final BufferedImage bi1,
107                                     final BufferedImage bi2)
108             throws IOException {
109         for (int i = 0; i < SIZE; ++i) {
110             for (int j = 0; j < SIZE; ++j) {
111                 final int rgb1 = bi1.getRGB(i, j);
112                 final int rgb2 = bi2.getRGB(i, j);
113                 if (rgb1 != rgb2 || rgb1 != 0xFFFF0000 && rgb1 != 0xFF00FF00) {
114                     ImageIO.write(bi1, "png", new File("image1.png"));
115                     ImageIO.write(bi2, "png", new File("image2.png"));
116                     throw new RuntimeException("Failed: wrong text location");
117                 }
118             }
119         }
120     }
121 
122     /**
123      * Creates an BufferedImage and draws a text, using two transformations,
124      * one for graphics and one for font.
125      */
createImage(final boolean aa, final AffineTransform gtx, final AffineTransform ftx)126     private static BufferedImage createImage(final boolean aa,
127                                              final AffineTransform gtx,
128                                              final AffineTransform ftx) {
129         final BufferedImage bi = new BufferedImage(SIZE, SIZE, TYPE_INT_RGB);
130         final Graphics2D bg = bi.createGraphics();
131         bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
132                             aa ? RenderingHints.VALUE_ANTIALIAS_ON
133                                : RenderingHints.VALUE_ANTIALIAS_OFF);
134         bg.setColor(Color.RED);
135         bg.fillRect(0, 0, SIZE, SIZE);
136         bg.translate(100, 100);
137         bg.transform(gtx);
138         bg.setColor(Color.BLACK);
139         bg.setFont(bg.getFont().deriveFont(20.0f).deriveFont(ftx));
140         bg.drawString(STR, 0, 0);
141         bg.dispose();
142         return bi;
143     }
144 
145     /**
146      * Fills the area of text using green solid color.
147      */
fillTextArea(final BufferedImage bi, final AffineTransform tx1, final AffineTransform tx2)148     private static void fillTextArea(final BufferedImage bi,
149                                      final AffineTransform tx1,
150                                      final AffineTransform tx2) {
151         final Graphics2D bg = bi.createGraphics();
152         bg.translate(100, 100);
153         bg.transform(tx1);
154         bg.transform(tx2);
155         bg.setColor(Color.GREEN);
156         final Font font = bg.getFont().deriveFont(20.0f);
157         bg.setFont(font);
158         bg.fill(font.getStringBounds(STR, bg.getFontRenderContext()));
159         bg.dispose();
160     }
161 }
162 
163