7cb9e5821e
Reviewed-by: psadhukhan, prr
312 lines
11 KiB
Java
312 lines
11 KiB
Java
/*
|
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
import java.awt.BasicStroke;
|
|
import java.awt.Color;
|
|
import java.awt.Font;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.RenderingHints;
|
|
import java.awt.Shape;
|
|
import java.awt.font.FontRenderContext;
|
|
import java.awt.font.GlyphVector;
|
|
import java.awt.geom.AffineTransform;
|
|
import java.awt.geom.Line2D;
|
|
import java.awt.geom.Path2D;
|
|
import java.awt.geom.PathIterator;
|
|
import static java.awt.geom.PathIterator.SEG_CLOSE;
|
|
import static java.awt.geom.PathIterator.SEG_CUBICTO;
|
|
import static java.awt.geom.PathIterator.SEG_LINETO;
|
|
import static java.awt.geom.PathIterator.SEG_MOVETO;
|
|
import static java.awt.geom.PathIterator.SEG_QUADTO;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Locale;
|
|
import java.util.logging.Handler;
|
|
import java.util.logging.LogRecord;
|
|
import java.util.logging.Logger;
|
|
import javax.imageio.ImageIO;
|
|
|
|
/**
|
|
* @test
|
|
* @bug 8144718
|
|
* @summary Check the Stroker.drawBezApproxForArc() bug (stoke with round
|
|
* joins): if cosext2 > 0.5, it generates curves with NaN coordinates
|
|
* @run main TextClipErrorTest
|
|
*/
|
|
public class TextClipErrorTest {
|
|
|
|
static final boolean SAVE_IMAGE = false;
|
|
static final boolean SERIALIZE = false;
|
|
|
|
public static void main(String[] args) {
|
|
Locale.setDefault(Locale.US);
|
|
|
|
// initialize j.u.l Looger:
|
|
final Logger log = Logger.getLogger("sun.java2d.marlin");
|
|
log.addHandler(new Handler() {
|
|
@Override
|
|
public void publish(LogRecord record) {
|
|
Throwable th = record.getThrown();
|
|
// detect any Throwable:
|
|
if (th != null) {
|
|
System.out.println("Test failed:\n" + record.getMessage());
|
|
th.printStackTrace(System.out);
|
|
|
|
throw new RuntimeException("Test failed: ", th);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void flush() {
|
|
}
|
|
|
|
@Override
|
|
public void close() throws SecurityException {
|
|
}
|
|
});
|
|
|
|
log.info("TextClipErrorTest: start");
|
|
|
|
// enable Marlin logging & internal checks:
|
|
System.setProperty("sun.java2d.renderer.log", "true");
|
|
System.setProperty("sun.java2d.renderer.useLogger", "true");
|
|
System.setProperty("sun.java2d.renderer.doChecks", "true");
|
|
|
|
BufferedImage image = new BufferedImage(256, 256,
|
|
BufferedImage.TYPE_INT_ARGB);
|
|
|
|
Graphics2D g2d = image.createGraphics();
|
|
g2d.setColor(Color.red);
|
|
try {
|
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
|
RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
Font font = g2d.getFont();
|
|
FontRenderContext frc = new FontRenderContext(
|
|
new AffineTransform(), true, true);
|
|
|
|
g2d.setStroke(new BasicStroke(4.0f,
|
|
BasicStroke.CAP_ROUND,
|
|
BasicStroke.JOIN_ROUND));
|
|
|
|
final Shape badShape;
|
|
if (SERIALIZE) {
|
|
final GlyphVector gv1 = font.createGlyphVector(frc, "\u00d6");
|
|
final Shape textShape = gv1.getOutline();
|
|
|
|
final AffineTransform at1 = AffineTransform.getTranslateInstance(
|
|
-2091202.554154681, 5548.601436981691);
|
|
badShape = at1.createTransformedShape(textShape);
|
|
serializeShape(badShape);
|
|
} else {
|
|
badShape = deserializeShape();
|
|
}
|
|
|
|
g2d.draw(badShape);
|
|
|
|
// Draw anything within bounds and it fails:
|
|
g2d.draw(new Line2D.Double(10, 20, 30, 40));
|
|
|
|
if (SAVE_IMAGE) {
|
|
final File file = new File("TextClipErrorTest.png");
|
|
System.out.println("Writing file: " + file.getAbsolutePath());
|
|
ImageIO.write(image, "PNG", file);
|
|
}
|
|
} catch (IOException ex) {
|
|
ex.printStackTrace();
|
|
} finally {
|
|
g2d.dispose();
|
|
log.info("TextClipErrorTest: end");
|
|
}
|
|
}
|
|
|
|
private static void serializeShape(Shape shape) {
|
|
final double[] coords = new double[6];
|
|
|
|
final int len = 32;
|
|
final ArrayList<Integer> typeList = new ArrayList<Integer>(len);
|
|
final ArrayList<double[]> coordsList = new ArrayList<double[]>(len);
|
|
|
|
for (PathIterator pi = shape.getPathIterator(null);
|
|
!pi.isDone(); pi.next())
|
|
{
|
|
switch (pi.currentSegment(coords)) {
|
|
case SEG_MOVETO:
|
|
typeList.add(SEG_MOVETO);
|
|
coordsList.add(Arrays.copyOf(coords, 2));
|
|
break;
|
|
case SEG_LINETO:
|
|
typeList.add(SEG_LINETO);
|
|
coordsList.add(Arrays.copyOf(coords, 2));
|
|
break;
|
|
case SEG_QUADTO:
|
|
typeList.add(SEG_QUADTO);
|
|
coordsList.add(Arrays.copyOf(coords, 4));
|
|
break;
|
|
case SEG_CUBICTO:
|
|
typeList.add(SEG_CUBICTO);
|
|
coordsList.add(Arrays.copyOf(coords, 6));
|
|
break;
|
|
case SEG_CLOSE:
|
|
typeList.add(SEG_CLOSE);
|
|
coordsList.add(null);
|
|
break;
|
|
default:
|
|
}
|
|
}
|
|
|
|
final StringBuilder sb = new StringBuilder(1024);
|
|
// types:
|
|
sb.append("private static final int[] SHAPE_TYPES = new int[]{\n");
|
|
for (Integer i : typeList) {
|
|
sb.append(i).append(",\n");
|
|
}
|
|
sb.append("};\n");
|
|
|
|
// coords:
|
|
sb.append("private static final double[][] SHAPE_COORDS = new double[][]{\n");
|
|
for (double[] c : coordsList) {
|
|
if (c == null) {
|
|
sb.append("null,\n");
|
|
} else {
|
|
sb.append("new double[]{");
|
|
for (int i = 0; i < c.length; i++) {
|
|
sb.append(c[i]).append(",");
|
|
}
|
|
sb.append("},\n");
|
|
}
|
|
}
|
|
sb.append("};\n");
|
|
|
|
System.out.println("Shape size: " + typeList.size());
|
|
System.out.println("Serialized shape:\n" + sb.toString());
|
|
}
|
|
|
|
private static Shape deserializeShape() {
|
|
final Path2D.Double path = new Path2D.Double();
|
|
|
|
for (int i = 0; i < SHAPE_TYPES.length; i++) {
|
|
double[] coords = SHAPE_COORDS[i];
|
|
|
|
switch (SHAPE_TYPES[i]) {
|
|
case SEG_MOVETO:
|
|
path.moveTo(coords[0], coords[1]);
|
|
break;
|
|
case SEG_LINETO:
|
|
path.lineTo(coords[0], coords[1]);
|
|
break;
|
|
case SEG_QUADTO:
|
|
path.quadTo(coords[0], coords[1],
|
|
coords[2], coords[3]);
|
|
break;
|
|
case SEG_CUBICTO:
|
|
path.curveTo(coords[0], coords[1],
|
|
coords[2], coords[3],
|
|
coords[4], coords[5]);
|
|
break;
|
|
case SEG_CLOSE:
|
|
path.closePath();
|
|
break;
|
|
default:
|
|
}
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
// generated code:
|
|
private static final int[] SHAPE_TYPES = new int[]{
|
|
0,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
4,
|
|
0,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
2,
|
|
4,
|
|
0,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
4,
|
|
0,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
4,
|
|
};
|
|
|
|
private static final double[][] SHAPE_COORDS = new double[][]{
|
|
new double[]{-2091197.819779681, 5540.648311981691,},
|
|
new double[]{-2091199.116654681, 5540.648311981691, -2091199.874467181, 5541.609249481691,},
|
|
new double[]{-2091200.632279681, 5542.570186981691, -2091200.632279681, 5544.242061981691,},
|
|
new double[]{-2091200.632279681, 5545.882686981691, -2091199.874467181, 5546.843624481691,},
|
|
new double[]{-2091199.116654681, 5547.804561981691, -2091197.819779681, 5547.804561981691,},
|
|
new double[]{-2091196.538529681, 5547.804561981691, -2091195.780717181, 5546.843624481691,},
|
|
new double[]{-2091195.022904681, 5545.882686981691, -2091195.022904681, 5544.242061981691,},
|
|
new double[]{-2091195.022904681, 5542.570186981691, -2091195.780717181, 5541.609249481691,},
|
|
new double[]{-2091196.538529681, 5540.648311981691, -2091197.819779681, 5540.648311981691,},
|
|
null,
|
|
new double[]{-2091197.819779681, 5539.695186981691,},
|
|
new double[]{-2091195.991654681, 5539.695186981691, -2091194.890092181, 5540.929561981691,},
|
|
new double[]{-2091193.788529681, 5542.163936981691, -2091193.788529681, 5544.242061981691,},
|
|
new double[]{-2091193.788529681, 5546.304561981691, -2091194.890092181, 5547.538936981691,},
|
|
new double[]{-2091195.991654681, 5548.773311981691, -2091197.819779681, 5548.773311981691,},
|
|
new double[]{-2091199.663529681, 5548.773311981691, -2091200.772904681, 5547.538936981691,},
|
|
new double[]{-2091201.882279681, 5546.304561981691, -2091201.882279681, 5544.242061981691,},
|
|
new double[]{-2091201.882279681, 5542.163936981691, -2091200.772904681, 5540.929561981691,},
|
|
new double[]{-2091199.663529681, 5539.695186981691, -2091197.819779681, 5539.695186981691,},
|
|
null,
|
|
new double[]{-2091197.210404681, 5537.835811981691,},
|
|
new double[]{-2091196.022904681, 5537.835811981691,},
|
|
new double[]{-2091196.022904681, 5539.023311981691,},
|
|
new double[]{-2091197.210404681, 5539.023311981691,},
|
|
new double[]{-2091197.210404681, 5537.835811981691,},
|
|
null,
|
|
new double[]{-2091199.632279681, 5537.835811981691,},
|
|
new double[]{-2091198.444779681, 5537.835811981691,},
|
|
new double[]{-2091198.444779681, 5539.023311981691,},
|
|
new double[]{-2091199.632279681, 5539.023311981691,},
|
|
new double[]{-2091199.632279681, 5537.835811981691,},
|
|
null,
|
|
};
|
|
|
|
}
|