Skip to main content

Underline isn't painted correctly.

6 replies [Last post]
Anonymous

Could someone shed light on it?

OS Windows 2000, JDK 1.4.2

regards,
Stas

<br />
import javax.swing.*;<br />
import javax.swing.text.*;</p>
<p>public class SwingBugDemo extends JFrame{</p>
<p>    JEditorPane pane=new JEditorPane();<br />
    public SwingBugDemo() throws Exception{<br />
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);</p>
<p>        this.getContentPane().add(new JScrollPane(pane));<br />
        pane.setEditorKit(new StyledEditorKit());<br />
        pane.getDocument().insertString(0,"12 \n",null);<br />
        MutableAttributeSet attrs=new SimpleAttributeSet();<br />
        StyleConstants.setBold(attrs,true);<br />
        StyleConstants.setItalic(attrs,true);<br />
        StyleConstants.setUnderline(attrs,true);<br />
        StyleConstants.setFontFamily(attrs,"Arial");<br />
        StyleConstants.setFontSize(attrs,64);<br />
        pane.getDocument().insertString(4,"aaa\n",attrs);<br />
        pane.getDocument().insertString(8,"bbb\n",attrs);<br />
    }</p>
<p>    public static void main(String args[]) throws Exception {<br />
        SwingBugDemo gI = new SwingBugDemo();<br />
        gI.setSize(300, 300);<br />
        gI.setLocationRelativeTo(null);<br />
        gI.setVisible(true);<br />
    }<br />
}<br />

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Anonymous

to zpm
Thank you but there are some cases where it won't work even without spaces. I can't provide a simple example but it happens.

to Viravan
Thanks.
I didn't implement it because my customer said that I shouldn't fix SUN's bugs and I postponed the fix.

regards,
Stas

Anonymous

Hi Viravan,
Glad to see you:-)
As I predict you can give a valuable advice

Thank you!

I'll try your suggestions.

regards,
Stas

zpm
Offline
Joined: 2003-06-16
Points: 0

Hi Stas,

For your reference, there's a bug filed on this issue: 4984669.

In your particular case, it should help if you remove the extra space after '12'. However, i can hardly imagine a general-case workaround.

viravan
Offline
Joined: 2003-06-23
Points: 0

>there's a bug filed on this issue: 4984669.

Can you provide a link or has the bug report not yet available for viewing?

>In your particular case, it should help if you remove the extra space after '12'

[b]Wicked![/b] I can actually change something outside of the scope of the attributes and have their behavior modified!

>However, i can hardly imagine a general-case workaround.

Try to display the following HTML on IE or NN and compare the results on a JTextPane and you'll see that browsers will underline the two trailing spaces in the first line whereas the JTextPane will strip them off:


THIS IS FIRST LINE��
THIS IS 2ND LINE

I know that [b]Stas[/b] is quite capable of fixing the problem himself, I have extracted the pertinent section of code from my program and posting it here for any one who maybe interested in [i]a general-case workaround[/i]:

[code]
import java.awt.*;
import javax.swing.text.*;

public class myLabelView extends LabelView {
boolean nobr=false,
bold=false,
doubleline=false,
overline=false,
doubleover=false,
overunder=false;
int vAlign=0;
FontMetrics metrics;
public myLabelView(Element elem) {
super(elem);
}
protected void setPropertiesFromAttributes() {
super.setPropertiesFromAttributes();
AttributeSet attr=getAttributes();
if (attr!=null) {
Object obj=attr.getAttribute("NOBR");
if (obj!=null) nobr=((Boolean)obj).booleanValue();
obj=attr.getAttribute("NOWRAP");
if (obj!=null) nobr=true;
bold=StyleConstants.isBold(attr);
doubleline=(attr.getAttribute("2UNDERLINE")!=null);
overline=(attr.getAttribute("OVERLINE")!=null);
doubleover=(attr.getAttribute("2OVERLINE")!=null);
overunder=(attr.getAttribute("OVER-UNDER")!=null);
}
}
public void paint(Graphics g, Shape a) {
Component c = getContainer();
int p0 = getStartOffset();
int p1 = getEndOffset();
Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds();
Color bg = getBackground();
Color fg = getForeground();
if (bg != null) {
g.setColor(bg);
g.fillRect(alloc.x, alloc.y, alloc.width, alloc.height);
}
g.setColor(fg);
checkPainter();
GlyphPainter painter=getGlyphPainter();
painter.paint(this, g, a, p0, p1);
boolean underline = isUnderline();
boolean strike = isStrikeThrough();
if (underline || strike || doubleline || overline || doubleover || overunder) {
/*
View parent = getParent();
if ((parent!=null) && (parent.getEndOffset()==p1)) { // strip whitespace on end
Segment s = getText(p0, p1);
while ((s.count > 0) && (Character.isWhitespace(s.array[s.count-1]))) {
p1 -= 1;
s.count -= 1;
}
}
*/
int x0 = alloc.x;
int p = getStartOffset();
if (p != p0) x0 += (int) painter.getSpan(this, p, p0, getTabExpander(), x0);
int x1 = x0 + (int) painter.getSpan(this, p0, p1, getTabExpander(), x0);
// calculate y coordinate
int d = (int) painter.getDescent(this);
int y = alloc.y + alloc.height - (int) painter.getDescent(this);
int yTmp = y;
if (bold) {
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2.0f));
}
if (underline || doubleline || overunder) {
yTmp += 1;
if (bold) yTmp++;
g.drawLine(x0, yTmp, x1, yTmp);
if (doubleline) {
yTmp += 2;
if (bold) yTmp++;
g.drawLine(x0, yTmp, x1, yTmp);
}
}
if (strike) {
yTmp -= (int) (painter.getAscent(this) * 0.3f);
g.drawLine(x0, yTmp, x1, yTmp);
}
if (overline || doubleover || overunder) {
yTmp = alloc.y + alloc.height - (int) painter.getAscent(this) - 1;
g.drawLine(x0, yTmp, x1, yTmp);
if (doubleover) {
yTmp -= 2;
if (bold) yTmp--;
g.drawLine(x0, yTmp, x1, yTmp);
}
}
}
}
}
[/code]

Note that the section where trailing whitespaces are eliminated has been commented out and this [b]LabelView[/b] subclass will display the line in bold if the text is bold. In addition, it can be used to do double-underline, single overline, double-overline, as well as over-and-under line.

;o)

V.V.

zpm
Offline
Joined: 2003-06-16
Points: 0

The URL for the bug ought to be
http://onesearch.sun.com/search/developers/index.jsp?qt=4984669&col=java...

but, alas, it isn't there yet =(
I believe there's a timegap before a newborn bug appears at the bug parade, so check it out later...

viravan
Offline
Joined: 2003-06-23
Points: 0

Howdy Stas:

You can probably fix this bug yourself at the line indicated below (GlyphView.java):

[code]
final void paintTextUsingColor(Graphics g, Shape a, Color c, int p0, int p1) {
// render the glyphs
g.setColor(c);
painter.paint(this, g, a, p0, p1);

// render underline or strikethrough if set.
boolean underline = isUnderline();
boolean strike = isStrikeThrough();
if (underline || strike) {
// calculate x coordinates
Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds();
View parent = getParent();
if ((parent != null) && (parent.getEndOffset() == p1)) {
// strip whitespace on end
Segment s = getText(p0, p1);
while ((s.count > 0) && (Character.isWhitespace(s.array[s.count-1]))) { // bug is here!!!
p1 -= 1;
s.count -= 1;
}
SegmentCache.releaseSharedSegment(s);
}
int x0 = alloc.x;
int p = getStartOffset();
if (p != p0) {
x0 += (int) painter.getSpan(this, p, p0, getTabExpander(), x0);
}
int x1 = x0 + (int) painter.getSpan(this, p0, p1, getTabExpander(), x0);

// calculate y coordinate
int d = (int) painter.getDescent(this);
int y = alloc.y + alloc.height - (int) painter.getDescent(this);
if (underline) {
int yTmp = y;
yTmp += 1;
g.drawLine(x0, yTmp, x1, yTmp);
}
if (strike) {
int yTmp = y;
// move y coordinate above baseline
yTmp -= (int) (painter.getAscent(this) * 0.3f);
g.drawLine(x0, yTmp, x1, yTmp);
}

}
}
[/code]

To fix the bug, modify isWhiteSpace to ignore [b]\n[/b]. Or else, try this;

[code]
import javax.swing.*;
import javax.swing.text.*;

public class SwingBugDemo extends JFrame{

JEditorPane pane=new JEditorPane();
public SwingBugDemo() throws Exception{
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.getContentPane().add(new JScrollPane(pane));
pane.setEditorKit(new StyledEditorKit());
DefaultStyledDocument doc=(DefaultStyledDocument)pane.getDocument();
doc.insertString(0,"12 \n",null);
MutableAttributeSet attrs=new SimpleAttributeSet();
StyleConstants.setBold(attrs,true);
StyleConstants.setItalic(attrs,true);
StyleConstants.setUnderline(attrs,true);
StyleConstants.setFontFamily(attrs,"Arial");
StyleConstants.setFontSize(attrs,64);
doc.insertString(4,"aaa\n",null);
doc.setCharacterAttributes(4,3,attrs,false);
doc.insertString(8,"bbb\n",null);
doc.setCharacterAttributes(8,3,attrs,false);
}

public static void main(String args[]) throws Exception {
SwingBugDemo gI = new SwingBugDemo();
gI.setSize(300, 300);
gI.setLocationRelativeTo(null);
gI.setVisible(true);
}
}
[/code]

;o)

V.V.