United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4707774 : Graphics.drawString( String, int, int ) not precise for large ints

Details
Type:
Bug
Submit Date:
2002-06-25
Status:
Resolved
Updated Date:
2003-03-28
Project Name:
JDK
Resolved Date:
2003-03-21
Component:
client-libs
OS:
windows_2000
Sub-Component:
2d
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.3.1_03,1.4.1
Fixed Versions:
1.4.1_03 (03)

Related Reports
Backport:
Backport:

Sub Tasks

Description

Name: jk109818			Date: 06/25/2002


FULL PRODUCT VERSION :
java version "1.3.1_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_03-b03)
Java HotSpot(TM) Client VM (build 1.3.1_03-b03, mixed mode)

FULL OPERATING SYSTEM VERSION :
4NT  3.01A   Windows NT 5.00

A DESCRIPTION OF THE PROBLEM :
Trying to line up labels drawn with Graphics.drawString(
String, int x, int y) with lines drawn with
Graphics.drawLine(int x, int y, int, int) doesn't work for
large x & y values (i.e. greater than 2^24). Looking at
sun.java2d.SunGraphics2D.drawString shows that the int
parameters are being cast to float and losing precision.

Graphics.drawString( String, int, int) should not cast
arguments to float. If range is an issue, they should
either be cast to double or long.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Look at source for sun.java2d.SunGraphics2D.drawString(
String, int, int)
2. Note that arguments are cast to float
3.

REPRODUCIBILITY :
This bug can be reproduced always.
(Review ID: 153922) 
======================================================================


###@###.### 2002-11-08

Here's a sample that shows the problem. The numbers should centered under
the ticks, but as one moves the scroll handle to the right (past 1/5 or so)
the numbers are no longer precisely centered under the ticks. With the
scroll handle at the far right, labels are far from ticks and some labels
are superimposed because they are "clumping" around values that can be
exactly represented by float.

This problem occurs because drawString casts int x and y parameters to
float, and float numbers only have 24 manitssa bits compared to 32 bits for
ints, so precision is lost with large numbers, making it impossible to
correctly label lines drawn with drawLine.

Note that the problem is still noticeable if one comments out the line to
center the label under a tick.

I made 2 changes to make the problem more apparent:

- Changed labels to be left justified under tick, rather than centered.
It's easier to see now when a tick doesn't line up with the start of a
label. (Left the code to center it as a comment.)

- Set the scrollbar's unit increment to be the same as the tick increment.
Now click-and-hold on the scroll bar arrow shows that the ticks are evenly
spaced, but the labels aren't (once you get past 1/8 or so of the scroll
range).

Here's is the updated file:

(See attached file: DrawStringTest.java)

                                    

Comments
EVALUATION

Problem becomes more appearent from Integer value 67108900 (rounding value of 2^26 to immediate next multiple of 100). I tested this by setting MAX_WIDTH =67109000 (2 ticks more that 2^26 tick).

The bug is reproducible on Solaris as well as Windows platform. However, textpipe.drawString() invocation in drawString(String, int, int) from SunGraphics2D.java invokes 2 different implementations. For Solaris, 'textpipe' is of type 'sun.awt.font.X11TextRenderer' whereas for windows it is of type 'sun.java2d.pipe.SolidTextRenderer'.

Standard API of J2SDK 1.4.x, provides drawString() method of java.awt.Graphics2D  with arguments of type float or int. However, the actual implementation of draw String() method accepts only float type arguments (implemented in GlyphListPipe.java).

I believe, this bug can be resolved by using 'double' instead of 'float' as  parameters to drawString() implementation in GlyphListPipe. And of course, changingmethods wherever these values are passed.

However, use of double instead of float could result into 'PERFORMANCE' degradation as processing double values requires more time than float.

###@###.### 2002-11-12


I did quick build of 1.4.1 workspace by looking at high level and replacing float with double. This did resolve the problem at some extent. Like, I see that strings are aligned properly with ticks upto 2139881800 (slightly less than 2^31 i.e. total no. of ticks).

I guess this will solve this issue. But needs to see the tradeoff between performance and severity of the issue. 

Other suggestion from sybase is use of 'long' instead of 'double' to solve this issue. However as double or long requires 64 bits, there could be performance degradation as compared to current implementation which uses float/int requiring 32-bit data manipulation.

###@###.### 2002-11-13
                                     
2002-11-13
SUGGESTED FIX


Attached webrev_141.tar.Z is the webrev generated for 1.4.1_xx with changes suggested by Jim.
###@###.### 2003-02-05
                                     
2003-02-05
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.4.1_03
mantis-beta
tiger

FIXED IN:
1.4.1_03
mantis-beta
tiger

INTEGRATED IN:
1.4.1_03
mantis-b19
mantis-beta
tiger
tiger-b05

VERIFIED IN:
mantis-beta


                                     
2004-06-14



Hardware and Software, Engineered to Work Together