JDK-4707774 : Graphics.drawString( String, int, int ) not precise for large ints
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.3.1_03,1.4.1
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-06-25
  • Updated: 2003-03-28
  • Resolved: 2003-03-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other Other
1.4.1_03 03Fixed 1.4.2Fixed
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
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
14-06-2004

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

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
13-11-2002