8023392: Swing text components printed with spaces between chars
Reviewed-by: alexsch, alexp
This commit is contained in:
parent
b33bcb9185
commit
8053376ea2
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2013, 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
|
||||
@ -33,6 +33,7 @@ import java.awt.event.*;
|
||||
import java.awt.font.*;
|
||||
import java.awt.geom.*;
|
||||
import java.awt.print.PrinterGraphics;
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
|
||||
@ -504,22 +505,25 @@ public class SwingUtilities2 {
|
||||
* it to fit in the screen width. This distributes the spacing
|
||||
* more evenly than directly laying out to the screen advances.
|
||||
*/
|
||||
float screenWidth = (float)
|
||||
g2d.getFont().getStringBounds(text, DEFAULT_FRC).getWidth();
|
||||
TextLayout layout = createTextLayout(c, text, g2d.getFont(),
|
||||
g2d.getFontRenderContext());
|
||||
String trimmedText = trimTrailingSpaces(text);
|
||||
if (!trimmedText.isEmpty()) {
|
||||
float screenWidth = (float) g2d.getFont().getStringBounds
|
||||
(trimmedText, DEFAULT_FRC).getWidth();
|
||||
TextLayout layout = createTextLayout(c, text, g2d.getFont(),
|
||||
g2d.getFontRenderContext());
|
||||
|
||||
layout = layout.getJustifiedLayout(screenWidth);
|
||||
/* Use alternate print color if specified */
|
||||
Color col = g2d.getColor();
|
||||
if (col instanceof PrintColorUIResource) {
|
||||
g2d.setColor(((PrintColorUIResource)col).getPrintColor());
|
||||
layout = layout.getJustifiedLayout(screenWidth);
|
||||
/* Use alternate print color if specified */
|
||||
Color col = g2d.getColor();
|
||||
if (col instanceof PrintColorUIResource) {
|
||||
g2d.setColor(((PrintColorUIResource)col).getPrintColor());
|
||||
}
|
||||
|
||||
layout.draw(g2d, x, y);
|
||||
|
||||
g2d.setColor(col);
|
||||
}
|
||||
|
||||
layout.draw(g2d, x, y);
|
||||
|
||||
g2d.setColor(col);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -789,25 +793,27 @@ public class SwingUtilities2 {
|
||||
if (frc != null &&
|
||||
!isFontRenderContextPrintCompatible
|
||||
(deviceFontRenderContext, frc)) {
|
||||
TextLayout layout =
|
||||
createTextLayout(c, new String(data, offset, length),
|
||||
g2d.getFont(),
|
||||
deviceFontRenderContext);
|
||||
float screenWidth = (float)g2d.getFont().
|
||||
getStringBounds(data, offset, offset + length, frc).
|
||||
getWidth();
|
||||
layout = layout.getJustifiedLayout(screenWidth);
|
||||
|
||||
/* Use alternate print color if specified */
|
||||
Color col = g2d.getColor();
|
||||
if (col instanceof PrintColorUIResource) {
|
||||
g2d.setColor(((PrintColorUIResource)col).getPrintColor());
|
||||
String text = new String(data, offset, length);
|
||||
TextLayout layout = new TextLayout(text, g2d.getFont(),
|
||||
deviceFontRenderContext);
|
||||
String trimmedText = trimTrailingSpaces(text);
|
||||
if (!trimmedText.isEmpty()) {
|
||||
float screenWidth = (float)g2d.getFont().
|
||||
getStringBounds(trimmedText, frc).getWidth();
|
||||
layout = layout.getJustifiedLayout(screenWidth);
|
||||
|
||||
/* Use alternate print color if specified */
|
||||
Color col = g2d.getColor();
|
||||
if (col instanceof PrintColorUIResource) {
|
||||
g2d.setColor(((PrintColorUIResource)col).getPrintColor());
|
||||
}
|
||||
|
||||
layout.draw(g2d,x,y);
|
||||
|
||||
g2d.setColor(col);
|
||||
}
|
||||
|
||||
layout.draw(g2d,x,y);
|
||||
|
||||
g2d.setColor(col);
|
||||
|
||||
return nextX;
|
||||
}
|
||||
}
|
||||
@ -888,14 +894,23 @@ public class SwingUtilities2 {
|
||||
} else {
|
||||
frc = g2d.getFontRenderContext();
|
||||
}
|
||||
TextLayout layout = new TextLayout(iterator, frc);
|
||||
TextLayout layout;
|
||||
if (isPrinting) {
|
||||
FontRenderContext deviceFRC = g2d.getFontRenderContext();
|
||||
if (!isFontRenderContextPrintCompatible(frc, deviceFRC)) {
|
||||
float screenWidth = layout.getAdvance();
|
||||
layout = new TextLayout(iterator, deviceFRC);
|
||||
layout = layout.getJustifiedLayout(screenWidth);
|
||||
AttributedCharacterIterator trimmedIt =
|
||||
getTrimmedTrailingSpacesIterator(iterator);
|
||||
if (trimmedIt != null) {
|
||||
float screenWidth = new TextLayout(trimmedIt, frc).
|
||||
getAdvance();
|
||||
layout = layout.getJustifiedLayout(screenWidth);
|
||||
}
|
||||
} else {
|
||||
layout = new TextLayout(iterator, frc);
|
||||
}
|
||||
} else {
|
||||
layout = new TextLayout(iterator, frc);
|
||||
}
|
||||
layout.draw(g2d, x, y);
|
||||
retVal = layout.getAdvance();
|
||||
@ -1047,6 +1062,39 @@ public class SwingUtilities2 {
|
||||
return (g instanceof PrinterGraphics || g instanceof PrintGraphics);
|
||||
}
|
||||
|
||||
private static String trimTrailingSpaces(String s) {
|
||||
int i = s.length() - 1;
|
||||
while(i >= 0 && Character.isWhitespace(s.charAt(i))) {
|
||||
i--;
|
||||
}
|
||||
return s.substring(0, i + 1);
|
||||
}
|
||||
|
||||
private static AttributedCharacterIterator getTrimmedTrailingSpacesIterator
|
||||
(AttributedCharacterIterator iterator) {
|
||||
int curIdx = iterator.getIndex();
|
||||
|
||||
char c = iterator.last();
|
||||
while(c != CharacterIterator.DONE && Character.isWhitespace(c)) {
|
||||
c = iterator.previous();
|
||||
}
|
||||
|
||||
if (c != CharacterIterator.DONE) {
|
||||
int endIdx = iterator.getIndex();
|
||||
|
||||
if (endIdx == iterator.getEndIndex() - 1) {
|
||||
iterator.setIndex(curIdx);
|
||||
return iterator;
|
||||
} else {
|
||||
AttributedString trimmedText = new AttributedString(iterator,
|
||||
iterator.getBeginIndex(), endIdx + 1);
|
||||
return trimmedText.getIterator();
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the SelectedTextColor should be used for painting text
|
||||
* foreground for the specified highlight.
|
||||
|
20
jdk/test/java/awt/print/bug8023392/bug8023392.html
Normal file
20
jdk/test/java/awt/print/bug8023392/bug8023392.html
Normal file
@ -0,0 +1,20 @@
|
||||
<html>
|
||||
<!--
|
||||
@test
|
||||
@bug 8023392
|
||||
@summary Swing text components printed with spaces between chars
|
||||
@author Anton Nashatyrev
|
||||
@run applet/manual=yesno bug8023392.html
|
||||
-->
|
||||
<head>
|
||||
<title> Bug 8023392 </title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Bug ID: 8023392</h1>
|
||||
|
||||
<p> See the dialog box (usually in upper left corner) for instructions</p>
|
||||
|
||||
<APPLET CODE="bug8023392.class" WIDTH=400 HEIGHT=400></APPLET>
|
||||
</body>
|
||||
</html>
|
286
jdk/test/java/awt/print/bug8023392/bug8023392.java
Normal file
286
jdk/test/java/awt/print/bug8023392/bug8023392.java
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
test
|
||||
@bug 8023392
|
||||
@summary Swing text components printed with spaces between chars
|
||||
@author Anton Nashatyrev
|
||||
@run applet/manual=yesno bug8023392.html
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.LineBorder;
|
||||
import java.applet.Applet;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.print.PageFormat;
|
||||
import java.awt.print.Printable;
|
||||
import java.awt.print.PrinterException;
|
||||
import java.awt.print.PrinterJob;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
|
||||
|
||||
public class bug8023392 extends Applet {
|
||||
static final String[] instructions = {
|
||||
"A Frame containing several pairs of labels ((a) and (b)) is displayed.",
|
||||
"Labels of each pair look the same and are left-aligned (with spaces ",
|
||||
"between chars).",
|
||||
"1. Hit the print button.",
|
||||
"2. Select any available printer (printing to file is also fine).",
|
||||
"3. Look at the printing result (paper, PDF, PS, etc.):",
|
||||
" The (a) and (b) labels should look almost the same and the (a) labels",
|
||||
" shouldn't appear as if they are stretched along X axis."};
|
||||
|
||||
public void init() {
|
||||
this.setLayout(new BorderLayout());
|
||||
add(new SimplePrint2(), BorderLayout.CENTER);
|
||||
|
||||
Sysout.createDialogWithInstructions(instructions);
|
||||
|
||||
}
|
||||
|
||||
public static class SimplePrint2 extends JPanel
|
||||
implements ActionListener, Printable {
|
||||
JLabel label1;
|
||||
JLabel label2;
|
||||
JButton printButton;
|
||||
|
||||
|
||||
public SimplePrint2() {
|
||||
setLayout(new BorderLayout());
|
||||
label1 = new JLabel("2a) a b c d e" +
|
||||
" ");
|
||||
label2 = new JLabel("2b) a b c d e");
|
||||
|
||||
Box p1 = new Box(BoxLayout.Y_AXIS);
|
||||
p1.add(label1);
|
||||
p1.add(label2);
|
||||
p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") {
|
||||
String s = "3a) a b c d e ";
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
sun.swing.SwingUtilities2.drawChars(this, g, s.toCharArray(),
|
||||
0, s.length(), 0, 15);
|
||||
}
|
||||
});
|
||||
p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") {
|
||||
String s = "3b) a b c d e";
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
sun.swing.SwingUtilities2.drawChars(this, g, s.toCharArray(),
|
||||
0, s.length(), 0, 15);
|
||||
}
|
||||
});
|
||||
p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") {
|
||||
String s = "4a) a b c d e ";
|
||||
AttributedCharacterIterator it;
|
||||
{
|
||||
AttributedString as = new AttributedString(s);
|
||||
as.addAttribute(TextAttribute.FONT, getFont());
|
||||
as.addAttribute(TextAttribute.FOREGROUND, Color.RED, 3, 8);
|
||||
it = as.getIterator();
|
||||
}
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
sun.swing.SwingUtilities2.drawString(this, g, it, 0, 15);
|
||||
}
|
||||
});
|
||||
|
||||
p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") {
|
||||
String s = "4b) a b c d e";
|
||||
AttributedCharacterIterator it;
|
||||
{
|
||||
AttributedString as = new AttributedString(s);
|
||||
as.addAttribute(TextAttribute.FONT, getFont());
|
||||
as.addAttribute(TextAttribute.FOREGROUND, Color.RED, 3, 8);
|
||||
it = as.getIterator();
|
||||
}
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
sun.swing.SwingUtilities2.drawString(this, g, it, 0, 15);
|
||||
}
|
||||
});
|
||||
|
||||
JPanel p2 = new JPanel();
|
||||
printButton = new JButton("Print");
|
||||
printButton.addActionListener(this);
|
||||
p2.add(printButton);
|
||||
|
||||
Container c = this;
|
||||
c.add(p1, BorderLayout.CENTER);
|
||||
c.add(p2, BorderLayout.SOUTH);
|
||||
|
||||
String[] data = {
|
||||
"1a) \u30aa\u30f3\u30e9\u30a4\u30f3\u6d88\u8fbc" +
|
||||
" ",
|
||||
"1b) \u30aa\u30f3\u30e9\u30a4\u30f3\u6d88\u8fbc"
|
||||
};
|
||||
JList l0 = new JList(data);
|
||||
l0.setVisibleRowCount(l0.getModel().getSize());
|
||||
JScrollPane jsp = new JScrollPane(l0);
|
||||
l0.setBorder(new LineBorder(Color.GRAY));
|
||||
c.add(jsp, BorderLayout.NORTH);
|
||||
|
||||
for (Component comp : new Component[]{label1, label2, printButton}) {
|
||||
comp.setFont(new Font("Monospaced", 0, 16));
|
||||
}
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
PrinterJob job = PrinterJob.getPrinterJob();
|
||||
job.setPrintable(this);
|
||||
if (job.printDialog()) {
|
||||
try {
|
||||
job.print();
|
||||
} catch (PrinterException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int print(Graphics graphics,
|
||||
PageFormat pageFormat,
|
||||
int pageIndex)
|
||||
throws PrinterException {
|
||||
if (pageIndex >= 1) {
|
||||
return Printable.NO_SUCH_PAGE;
|
||||
}
|
||||
|
||||
this.paint(graphics);
|
||||
return Printable.PAGE_EXISTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* *************************************************
|
||||
* Standard Test Machinery
|
||||
* DO NOT modify anything below -- it's a standard
|
||||
* chunk of code whose purpose is to make user
|
||||
* interaction uniform, and thereby make it simpler
|
||||
* to read and understand someone else's test.
|
||||
* **************************************************
|
||||
*/
|
||||
class Sysout {
|
||||
private static TestDialog dialog;
|
||||
|
||||
public static void createDialogWithInstructions(String[] instructions) {
|
||||
dialog = new TestDialog(new Frame(), "Instructions");
|
||||
dialog.printInstructions(instructions);
|
||||
dialog.show();
|
||||
println("Any messages for the tester will display here.");
|
||||
}
|
||||
|
||||
public static void createDialog() {
|
||||
dialog = new TestDialog(new Frame(), "Instructions");
|
||||
String[] defInstr = {"Instructions will appear here. ", ""};
|
||||
dialog.printInstructions(defInstr);
|
||||
dialog.show();
|
||||
println("Any messages for the tester will display here.");
|
||||
}
|
||||
|
||||
|
||||
public static void printInstructions(String[] instructions) {
|
||||
dialog.printInstructions(instructions);
|
||||
}
|
||||
|
||||
|
||||
public static void println(String messageIn) {
|
||||
dialog.displayMessage(messageIn);
|
||||
}
|
||||
|
||||
}// Sysout class
|
||||
|
||||
|
||||
class TestDialog extends Dialog {
|
||||
|
||||
TextArea instructionsText;
|
||||
TextArea messageText;
|
||||
int maxStringLength = 80;
|
||||
|
||||
//DO NOT call this directly, go through Sysout
|
||||
public TestDialog(Frame frame, String name) {
|
||||
super(frame, name);
|
||||
int scrollBoth = TextArea.SCROLLBARS_BOTH;
|
||||
instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
|
||||
add("North", instructionsText);
|
||||
|
||||
messageText = new TextArea("", 5, maxStringLength, scrollBoth);
|
||||
add("South", messageText);
|
||||
|
||||
pack();
|
||||
|
||||
show();
|
||||
}// TestDialog()
|
||||
|
||||
//DO NOT call this directly, go through Sysout
|
||||
public void printInstructions(String[] instructions) {
|
||||
//Clear out any current instructions
|
||||
instructionsText.setText("");
|
||||
|
||||
//Go down array of instruction strings
|
||||
|
||||
String printStr, remainingStr;
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
//chop up each into pieces maxSringLength long
|
||||
remainingStr = instructions[i];
|
||||
while (remainingStr.length() > 0) {
|
||||
//if longer than max then chop off first max chars to print
|
||||
if (remainingStr.length() >= maxStringLength) {
|
||||
//Try to chop on a word boundary
|
||||
int posOfSpace = remainingStr.
|
||||
lastIndexOf(' ', maxStringLength - 1);
|
||||
|
||||
if (posOfSpace <= 0) posOfSpace = maxStringLength - 1;
|
||||
|
||||
printStr = remainingStr.substring(0, posOfSpace + 1);
|
||||
remainingStr = remainingStr.substring(posOfSpace + 1);
|
||||
}
|
||||
//else just print
|
||||
else {
|
||||
printStr = remainingStr;
|
||||
remainingStr = "";
|
||||
}
|
||||
|
||||
instructionsText.append(printStr + "\n");
|
||||
|
||||
}// while
|
||||
|
||||
}// for
|
||||
|
||||
}//printInstructions()
|
||||
|
||||
//DO NOT call this directly, go through Sysout
|
||||
public void displayMessage(String messageIn) {
|
||||
messageText.append(messageIn + "\n");
|
||||
}
|
||||
|
||||
}// TestDialog class
|
||||
|
Loading…
Reference in New Issue
Block a user