I have implemented a GlyphPainter (for painting text in
javax.swing.text) based on the new TextLayout class. While doing so I
came across some small problems (namely, hitTestChar() returning null
when it shouldn't) which are fixed by this patch.
IMO this should be in the release as it's a clear bugfix (and doesn't
have the potential for regressions as this method is new in this
release).
2006-12-04 Roman Kennke <[EMAIL PROTECTED]>
* java/awt/font/TextLayout.java
(hitTestChar): Fixed conditions for inclusion of range.
Use layout information in the run for more efficiency.
/Roman
Index: java/awt/font/TextLayout.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/font/TextLayout.java,v
retrieving revision 1.23
diff -u -1 -5 -r1.23 TextLayout.java
--- java/awt/font/TextLayout.java 29 Nov 2006 10:28:22 -0000 1.23
+++ java/awt/font/TextLayout.java 4 Dec 2006 18:32:22 -0000
@@ -1162,99 +1162,95 @@
else
{
if (x < bounds.getMinX())
return TextHitInfo.leading(0);
else if (x > bounds.getMaxX())
return TextHitInfo.trailing(getCharacterCount() - 1);
}
TextHitInfo hitInfo = null;
if (isVertical())
{
// Search for the run at the location.
// TODO: Perform binary search for maximum efficiency. However, we
// need the run location laid out statically to do that.
int numRuns = runs.length;
- float offs = 0;
Run hitRun = null;
for (int i = 0; i < numRuns && hitRun == null; i++)
{
Run run = runs[i];
Rectangle2D lBounds = run.glyphVector.getLogicalBounds();
- if (lBounds.getMinY() + offs <= y && lBounds.getMaxY() + offs > y)
+ if (lBounds.getMinY() + run.location <= y
+ && lBounds.getMaxY() + run.location >= y)
hitRun = run;
- else
- offs += lBounds.getHeight();
}
// Now we have (hopefully) found a run that hits. Now find the
// right character.
if (hitRun != null)
{
GlyphVector gv = hitRun.glyphVector;
for (int i = hitRun.runStart;
i < hitRun.runEnd && hitInfo == null; i++)
{
int gi = i - hitRun.runStart;
Rectangle2D lBounds = gv.getGlyphLogicalBounds(gi)
.getBounds2D();
- if (lBounds.getMinY() + offs <= y
- && lBounds.getMaxY() + offs > y)
+ if (lBounds.getMinY() + hitRun.location <= y
+ && lBounds.getMaxY() + hitRun.location >= y)
{
// Found hit. Now check if we are leading or trailing.
boolean leading = true;
- if (lBounds.getCenterY() + offs <= y)
+ if (lBounds.getCenterY() + hitRun.location <= y)
leading = false;
hitInfo = leading ? TextHitInfo.leading(i)
: TextHitInfo.trailing(i);
}
}
}
}
else
{
// Search for the run at the location.
// TODO: Perform binary search for maximum efficiency. However, we
// need the run location laid out statically to do that.
int numRuns = runs.length;
- float offs = 0;
Run hitRun = null;
for (int i = 0; i < numRuns && hitRun == null; i++)
{
Run run = runs[i];
Rectangle2D lBounds = run.glyphVector.getLogicalBounds();
- if (lBounds.getMinX() + offs <= x && lBounds.getMaxX() + offs > x)
+ if (lBounds.getMinX() + run.location <= x
+ && lBounds.getMaxX() + run.location >= x)
hitRun = run;
- else
- offs += lBounds.getWidth();
}
// Now we have (hopefully) found a run that hits. Now find the
// right character.
if (hitRun != null)
{
GlyphVector gv = hitRun.glyphVector;
for (int i = hitRun.runStart;
i < hitRun.runEnd && hitInfo == null; i++)
{
int gi = i - hitRun.runStart;
Rectangle2D lBounds = gv.getGlyphLogicalBounds(gi)
.getBounds2D();
- if (lBounds.getMinX() + offs <= x
- && lBounds.getMaxX() + offs > x)
+ if (lBounds.getMinX() + hitRun.location <= x
+ && lBounds.getMaxX() + hitRun.location >= x)
{
// Found hit. Now check if we are leading or trailing.
boolean leading = true;
- if (lBounds.getCenterX() + offs <= x)
+ if (lBounds.getCenterX() + hitRun.location <= x)
leading = false;
hitInfo = leading ? TextHitInfo.leading(i)
: TextHitInfo.trailing(i);
}
}
}
}
return hitInfo;
}
public boolean isLeftToRight ()
{
return leftToRight;
}