Here comes another bunch of methods for TextLayout. Again, this is based
on the specs:

http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec/j2d-fonts.html

and is backed up by the tests in the Harmony testsuite.

/Roman

Index: java/awt/font/TextLayout.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/font/TextLayout.java,v
retrieving revision 1.20
diff -u -1 -5 -r1.20 TextLayout.java
--- java/awt/font/TextLayout.java	27 Nov 2006 11:17:21 -0000	1.20
+++ java/awt/font/TextLayout.java	27 Nov 2006 13:10:29 -0000
@@ -588,50 +588,97 @@
               info[0] = (float) glyphRect.getMaxY();
           }
         else
           {
             if (leading)
               info[0] = (float) glyphRect.getMinX();
             else
               info[0] = (float) glyphRect.getMaxX();
           }
         info[0] += run.location;
         info[1] = run.font.getItalicAngle();
       }
     return info;
   }
 
-  public Shape getCaretShape (TextHitInfo hit)
+  public Shape getCaretShape(TextHitInfo hit)
   {
-    return getCaretShape( hit, getBounds() );
+    return getCaretShape(hit, getBounds());
   }
 
-  public Shape getCaretShape (TextHitInfo hit, Rectangle2D bounds)
-    throws NotImplementedException
+  public Shape getCaretShape(TextHitInfo hit, Rectangle2D bounds)
   {
-    throw new Error ("not implemented");
+    // TODO: Handle vertical shapes somehow.
+    float[] info = getCaretInfo(hit);
+    float x1 = info[0];
+    float y1 = (float) bounds.getMinY();
+    float x2 = info[0];
+    float y2 = (float) bounds.getMaxY();
+    if (info[1] != 0)
+      {
+        // Shift x1 and x2 according to the slope.
+        x1 -= y1 * info[1];
+        x2 -= y2 * info[1];
+      }
+    GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 2);
+    path.moveTo(x1, y1);
+    path.lineTo(x2, y2);
+    return path;
   }
 
-  public Shape[] getCaretShapes (int offset)
+  public Shape[] getCaretShapes(int offset)
   {
-    return getCaretShapes( offset, getBounds() );
+    return getCaretShapes(offset, getNaturalBounds());
   }
 
-  public Shape[] getCaretShapes (int offset, Rectangle2D bounds)
-    throws NotImplementedException
+  public Shape[] getCaretShapes(int offset, Rectangle2D bounds)
   {
-    throw new Error ("not implemented");
+    return getCaretShapes(offset, bounds, DEFAULT_CARET_POLICY);
+  }
+
+  public Shape[] getCaretShapes(int offset, Rectangle2D bounds,
+                                CaretPolicy policy)
+  {
+    // The RI returns a 2-size array even when there's only one
+    // shape in it.
+    Shape[] carets = new Shape[2];
+    TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
+    int caretHit1 = hitToCaret(hit1);
+    TextHitInfo hit2 = hit1.getOtherHit();
+    int caretHit2 = hitToCaret(hit2);
+    if (caretHit1 == caretHit2)
+      {
+        carets[0] = getCaretShape(hit1);
+        carets[1] = null; // The RI returns null in this seldom case.
+      }
+    else
+      {
+        Shape caret1 = getCaretShape(hit1);
+        Shape caret2 = getCaretShape(hit2);
+        TextHitInfo strong = policy.getStrongCaret(hit1, hit2, this);
+        if (strong == hit1)
+          {
+            carets[0] = caret1;
+            carets[1] = caret2;
+          }
+        else
+          {
+            carets[0] = caret2;
+            carets[1] = caret1;
+          }
+      }
+    return carets;
   }
 
   public int getCharacterCount ()
   {
     return length;
   }
 
   public byte getCharacterLevel (int index)
   {
     byte level;
     if( bidi == null )
       level = 0;
     else
       level = (byte) bidi.getLevelAt(index);
     return level;

Reply via email to