Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8344648

[Text,TextFlow] Public API for Text Layout Info

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Unresolved
    • Icon: P4 P4
    • jfx25
    • javafx
    • None
    • source
    • minimal
    • Applications may extend Text/TextFlow classes and add methods with the same signature (but different return type).
    • Java API
    • JDK

      Summary

      Adds public LayoutInfo getLayoutInfo() method to Text and TextFlow classes for the purpose of getting additional information about the layout of text.

      Problem

      Applications dealing with text-based Nodes, such as those providing rich text editors, need more information about the layout of text than currently provided via public API.

      While partial information about the text layout can be obtained by reverse-engineering undocumented PathElement[] returned by the existing caretShape() and rangeShape() methods in the Text and TextFlow classes, other information, such as strike-through geometry, cannot be obtained via public API at all.

      Reverse engineering is currently successful because developers realize that the PathElement[] array contains a sequence of MoveTo and LineTo elements, and nothing else. This may or may not be true in the future, and in general the structure of this array, while suitable for using with the Path class, is not documented.

      The application and library developers typically resolve to creating custom nodes that extend TextFlow, or use the hacks like drawing mid-height lines for the strike-through decoration.

      Solution

      Please refer to https://github.com/andy-goryachev-oracle/Test/blob/main/doc/Text/LayoutInfo.md

      Specification

      javafx.scene.text.Text

          /**
           * Returns the object which provides a view into the text layout for this node, which allows for querying
           * the details of the layout.
           * <p>
           * While there is no general guarantee that successive invocations of this method return the same instance,
           * it is safe to either cache this object or call this method each time, since the information obtained from
           * this lightweight object remains valid until the next layout cycle.
           * <p>
           * The information obtained after the next layout cycle might be different as a result
           * of actions such as resizing of the container, or modification of certain properties.
           * For example updating the text or the font might change the layout, but a change of color would not.
           *
           * @return the layout information
           * @since 25
           */
          public final LayoutInfo getLayoutInfo()

      javafx.scene.text.TextFlow

          /**
           * Returns the object which provides a view into the text layout for this node, which allows for querying
           * the details of the layout.
           * <p>
           * While there is no general guarantee that successive invocations of this method return the same instance,
           * it is safe to either cache this object or call this method each time, since the information obtained from
           * this lightweight object remains valid until the next layout cycle.
           * <p>
           * The information obtained after the next layout cycle might be different as a result
           * of actions such as resizing of the container, or modification of certain properties.
           * For example updating the text or the font might change the layout, but a change of color would not.
           *
           * @return the layout information
           * @since 25
           */
          public final LayoutInfo getLayoutInfo()

      javafx.scene.text.LayoutInfo

      This class provides a view into the text layout used by the Text and TextFlow nodes, with the purpose of querying the details of the layout such as break up of the text into lines, as well as geometry of other shapes derived from the layout (selection, underline, etc.).

      The information obtained via this object may change after the next layout cycle, which may come as a result of actions such as resizing of the container, or modification of certain properties. For example updating the text or the font might change the layout, but a change of color would not.

      /**
       * Provides a view into the text layout used in a {@code Text} or a {@code TextFlow} node,
       * with purpose of querying the details of the layout such as break up of the text into lines,
       * as well as geometry of other shapes derived from the layout (selection, underline, etc.).
       * <p>
       * The information obtained via this object may change after the next layout cycle, which may come as a result
       * of actions such as resizing of the container, or modification of certain properties.
       * For example updating the text or the font might change the layout, but a change of color would not.
       *
       * @since 25
       */
      public abstract sealed class LayoutInfo permits PrismLayoutInfo {
          /**
           * Constructor for subclasses to call.
           */
          protected LayoutInfo() {
      
          /**
           * Returns the logical bounds of the layout.
           * Depending on {@code includeLineSpacing}, the return value may include the line spacing after the
           * last line of text.
           *
           * @param includeLineSpacing determines whether the line spacing after last text line should be included
           * @return the layout bounds
           */
          public abstract Rectangle2D getBounds(boolean includeLineSpacing);
      
          /**
           * Returns the number of text lines in the layout.
           * @return the number of text lines
           */
          public abstract int getTextLineCount();
      
          /**
           * Returns the immutable list of text lines in the layout.
           *
           * @param includeLineSpacing determines whether the result includes the line spacing
           * @return the immutable list of {@code TextLineInfo} objects
           */
          public abstract List<TextLineInfo> getTextLines(boolean includeLineSpacing);
      
          /**
           * Returns the {@code TextLineInfo} object which contains information about
           * the text line at index {@code index}.
           *
           * @param index the line index
           * @param includeLineSpacing determines whether the result includes the line spacing
           * @return the {@code TextLineInfo} object
           * @throws IndexOutOfBoundsException if the index is out of range
           *     {@code (index < 0 || index > getTextLineCount())}
           */
          public abstract TextLineInfo getTextLine(int index, boolean includeLineSpacing);
      
          /**
           * Returns the geometry of the text selection, as an immutable list of {@code Rectangle2D} objects,
           * for the given start and end offsets.
           *
           * @param start the start offset
           * @param end the end offset
           * @param includeLineSpacing determines whether the result includes the line spacing
           * @return the immutable list of {@code Rectangle2D} objects
           */
          public abstract List<Rectangle2D> selectionShape(int start, int end, boolean includeLineSpacing);
      
          /**
           * Returns the geometry of the strike-through shape, as an immutable list of {@code Rectangle2D} objects,
           * for the given start and end offsets.
           *
           * @param start the start offset
           * @param end the end offset
           * @return the immutable list of {@code Rectangle2D} objects
           */
          public abstract List<Rectangle2D> strikeThroughShape(int start, int end);
      
          /**
           * Returns the geometry of the underline shape, as an immutable list of {@code Rectangle2D} objects,
           * for the given start and end offsets.
           *
           * @param start the start offset
           * @param end the end offset
           * @return the immutable list of {@code Rectangle2D} objects
           */
          public abstract List<Rectangle2D> underlineShape(int start, int end);
      
          /**
           * Returns the information related to the caret at the specified character index and the character bias.
           *
           * @param charIndex the character index
           * @param leading whether the caret is biased on the leading edge of the character
           * @return the {@code CaretInfo} object
           */
          public abstract CaretInfo caretInfo(int charIndex, boolean leading);
      }

      javafx.scene.text.TextLineInfo

      Provides the information about a text line in a text layout:

      /**
       * Provides the information about a text line in a text layout.
       *
       * @param start the start offset for the line
       * @param end the end offset for the line (index of the last character + 1)
       * @param bounds the bounds of the text line, in local coordinates:
       * <ul>
       *   <li>
       *     {@code minX} - the x origin of the line (relative to the layout).
       *     The x origin is defined by TextAlignment of the text layout, always zero
       *     for left-aligned text.
       *   <li>
       *     {@code minY} - the ascent of the line (negative).
       *     The ascent of the line is the max ascent of all fonts in the line.
       *   <li>
       *     {@code width} - the width of the line.
       *     The width for the line is sum of all the run widths in the line, it is not
       *     affect by the wrapping width but it will include any changes caused by
       *     justification.
       *   <li>
       *     {@code height} - the height of the line.
       *     The height of the line is sum of the max ascent, max descent, and
       *     max line gap of all the fonts in the line.
       * </ul>
       *
       * @since 25
       */
      public record TextLineInfo(int start, int end, Rectangle2D bounds) {
      }

      javafx.scene.text.CaretInfo

      Provides the information associated with the caret:

      /**
       * Provides the information associated with the caret.
       * <p>
       * Typically, the caret is represented by a single vertical line which visually indicates the
       * position within the text.  In some cases, where the caret is positioned between left-to-right and
       * right-to-left text, two line segments will be shown, indicating the insertion position for both left-to-right
       * and right-to-left character.
       *
       * @since 25
       */
      public sealed abstract class CaretInfo permits PrismCaretInfo {
          /**
           * Constructor for subclasses to call.
           */
          protected CaretInfo() {
          }
      
          /**
           * Returns the number of segments representing the caret.
           *
           * @return the number of segments representing the caret
           */
          public abstract int getSegmentCount();
      
          /**
           * Returns the geometry of the segment at the specified index.
           *
           * @param index the line index
           * @return the bounds of the caret segment
           * @throws IndexOutOfBoundsException if the index is out of range
           *     {@code (index < 0 || index > getSegmentCount())}
           */
          public abstract Rectangle2D getSegmentAt(int index);
      }

            angorya Andy Goryachev
            angorya Andy Goryachev
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated: