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;
   }
 

Reply via email to