jdk/src/share/classes/java/awt/font/LineBreakMeasurer.java
author prr
Sat, 03 Dec 2011 16:26:08 -0800
changeset 11081 4a18889223e4
parent 5506 202f599c92aa
child 21244 7c2ac5ca05a2
permissions -rw-r--r--
7117199: Fix javac warnings in src/share/classes/java/awt/font Reviewed-by: jgodinez, bae
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     2
 * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 * The original version of this source code and documentation is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
 * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * of IBM. These materials are provided under terms of a License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * Agreement between Taligent and Sun. This technology is protected
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 * by multiple US and International patents.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * This notice and attribution to Taligent may not be removed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 * Taligent is a registered trademark of Taligent, Inc.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
package java.awt.font;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import java.text.BreakIterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import java.text.CharacterIterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import java.text.AttributedCharacterIterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import java.awt.font.FontRenderContext;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * The <code>LineBreakMeasurer</code> class allows styled text to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * broken into lines (or segments) that fit within a particular visual
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * advance.  This is useful for clients who wish to display a paragraph of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * text that fits within a specific width, called the <b>wrapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * width</b>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * <code>LineBreakMeasurer</code> is constructed with an iterator over
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * styled text.  The iterator's range should be a single paragraph in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * text.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * <code>LineBreakMeasurer</code> maintains a position in the text for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * start of the next text segment.  Initially, this position is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * start of text.  Paragraphs are assigned an overall direction (either
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * left-to-right or right-to-left) according to the bidirectional
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * formatting rules.  All segments obtained from a paragraph have the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * same direction as the paragraph.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * Segments of text are obtained by calling the method
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * <code>nextLayout</code>, which returns a {@link TextLayout}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * representing the text that fits within the wrapping width.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * The <code>nextLayout</code> method moves the current position
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * to the end of the layout returned from <code>nextLayout</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * <code>LineBreakMeasurer</code> implements the most commonly used
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * line-breaking policy: Every word that fits within the wrapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * width is placed on the line. If the first word does not fit, then all
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * of the characters that fit within the wrapping width are placed on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * line.  At least one character is placed on each line.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * The <code>TextLayout</code> instances returned by
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * <code>LineBreakMeasurer</code> treat tabs like 0-width spaces.  Clients
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 * who wish to obtain tab-delimited segments for positioning should use
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * the overload of <code>nextLayout</code> which takes a limiting offset
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * in the text.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * The limiting offset should be the first character after the tab.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 * The <code>TextLayout</code> objects returned from this method end
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 * at the limit provided (or before, if the text between the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * position and the limit won't fit entirely within the  wrapping
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 * width).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 * Clients who are laying out tab-delimited text need a slightly
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 * different line-breaking policy after the first segment has been
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 * placed on a line.  Instead of fitting partial words in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 * remaining space, they should place words which don't fit in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 * remaining space entirely on the next line.  This change of policy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
 * can be requested in the overload of <code>nextLayout</code> which
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 * takes a <code>boolean</code> parameter.  If this parameter is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
 * <code>true</code>, <code>nextLayout</code> returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 * <code>null</code> if the first word won't fit in
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 * the given space.  See the tab sample below.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 * In general, if the text used to construct the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 * <code>LineBreakMeasurer</code> changes, a new
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 * <code>LineBreakMeasurer</code> must be constructed to reflect
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 * the change.  (The old <code>LineBreakMeasurer</code> continues to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 * function properly, but it won't be aware of the text change.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
 * Nevertheless, if the text change is the insertion or deletion of a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
 * single character, an existing <code>LineBreakMeasurer</code> can be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
 * 'updated' by calling <code>insertChar</code> or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
 * <code>deleteChar</code>. Updating an existing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
 * <code>LineBreakMeasurer</code> is much faster than creating a new one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
 * Clients who modify text based on user typing should take advantage
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
 * of these methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
 * <strong>Examples</strong>:<p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
 * Rendering a paragraph in a component
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
 * <blockquote>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
 * public void paint(Graphics graphics) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
 *     Point2D pen = new Point2D(10, 20);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
 *     Graphics2D g2d = (Graphics2D)graphics;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
 *     FontRenderContext frc = g2d.getFontRenderContext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
 *     // let styledText be an AttributedCharacterIterator containing at least
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
 *     // one character
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
 *     LineBreakMeasurer measurer = new LineBreakMeasurer(styledText, frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
 *     float wrappingWidth = getSize().width - 15;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
 *     while (measurer.getPosition() < fStyledText.length()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
 *         TextLayout layout = measurer.nextLayout(wrappingWidth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
 *         pen.y += (layout.getAscent());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
 *         float dx = layout.isLeftToRight() ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
 *             0 : (wrappingWidth - layout.getAdvance());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
 *         layout.draw(graphics, pen.x + dx, pen.y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
 *         pen.y += layout.getDescent() + layout.getLeading();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
 * }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
 * </blockquote>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
 * Rendering text with tabs.  For simplicity, the overall text
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
 * direction is assumed to be left-to-right
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
 * <blockquote>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
 * public void paint(Graphics graphics) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
 *     float leftMargin = 10, rightMargin = 310;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
 *     float[] tabStops = { 100, 250 };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
 *     // assume styledText is an AttributedCharacterIterator, and the number
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
 *     // of tabs in styledText is tabCount
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
 *     int[] tabLocations = new int[tabCount+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
 *     int i = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
 *     for (char c = styledText.first(); c != styledText.DONE; c = styledText.next()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
 *         if (c == '\t') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
 *             tabLocations[i++] = styledText.getIndex();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
 *         }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
 *     tabLocations[tabCount] = styledText.getEndIndex() - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
 *     // Now tabLocations has an entry for every tab's offset in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
 *     // the text.  For convenience, the last entry is tabLocations
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
 *     // is the offset of the last character in the text.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
 *     LineBreakMeasurer measurer = new LineBreakMeasurer(styledText);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
 *     int currentTab = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
 *     float verticalPos = 20;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
 *     while (measurer.getPosition() < styledText.getEndIndex()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
 *         // Lay out and draw each line.  All segments on a line
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
 *         // must be computed before any drawing can occur, since
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
 *         // we must know the largest ascent on the line.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
 *         // TextLayouts are computed and stored in a Vector;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
 *         // their horizontal positions are stored in a parallel
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
 *         // Vector.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
 *         // lineContainsText is true after first segment is drawn
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
 *         boolean lineContainsText = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
 *         boolean lineComplete = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
 *         float maxAscent = 0, maxDescent = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
 *         float horizontalPos = leftMargin;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
 *         Vector layouts = new Vector(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
 *         Vector penPositions = new Vector(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
 *         while (!lineComplete) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
 *             float wrappingWidth = rightMargin - horizontalPos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
 *             TextLayout layout =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
 *                     measurer.nextLayout(wrappingWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
 *                                         tabLocations[currentTab]+1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
 *                                         lineContainsText);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
 *             // layout can be null if lineContainsText is true
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
 *             if (layout != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
 *                 layouts.addElement(layout);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
 *                 penPositions.addElement(new Float(horizontalPos));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
 *                 horizontalPos += layout.getAdvance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
 *                 maxAscent = Math.max(maxAscent, layout.getAscent());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
 *                 maxDescent = Math.max(maxDescent,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
 *                     layout.getDescent() + layout.getLeading());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
 *             } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
 *                 lineComplete = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
 *             }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
 *             lineContainsText = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
 *             if (measurer.getPosition() == tabLocations[currentTab]+1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
 *                 currentTab++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
 *             }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
 *             if (measurer.getPosition() == styledText.getEndIndex())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
 *                 lineComplete = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
 *             else if (horizontalPos >= tabStops[tabStops.length-1])
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
 *                 lineComplete = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
 *             if (!lineComplete) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
 *                 // move to next tab stop
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
 *                 int j;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
 *                 for (j=0; horizontalPos >= tabStops[j]; j++) {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
 *                 horizontalPos = tabStops[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
 *             }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
 *         }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
 *         verticalPos += maxAscent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
 *         Enumeration layoutEnum = layouts.elements();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
 *         Enumeration positionEnum = penPositions.elements();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
 *         // now iterate through layouts and draw them
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
 *         while (layoutEnum.hasMoreElements()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
 *             TextLayout nextLayout = (TextLayout) layoutEnum.nextElement();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
 *             Float nextPosition = (Float) positionEnum.nextElement();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
 *             nextLayout.draw(graphics, nextPosition.floatValue(), verticalPos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
 *         }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
 *         verticalPos += maxDescent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
 * }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
 * </blockquote>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
 * @see TextLayout
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
public final class LineBreakMeasurer {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
    private BreakIterator breakIter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    private int start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    private int pos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    private int limit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    private TextMeasurer measurer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    private CharArrayIterator charIter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
     * Constructs a <code>LineBreakMeasurer</code> for the specified text.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
     * @param text the text for which this <code>LineBreakMeasurer</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
     *       produces <code>TextLayout</code> objects; the text must contain
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
     *       at least one character; if the text available through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
     *       <code>iter</code> changes, further calls to this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
     *       <code>LineBreakMeasurer</code> instance are undefined (except,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
     *       in some cases, when <code>insertChar</code> or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
     *       <code>deleteChar</code> are invoked afterward - see below)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
     * @param frc contains information about a graphics device which is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
     *       needed to measure the text correctly;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
     *       text measurements can vary slightly depending on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
     *       device resolution, and attributes such as antialiasing; this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     *       parameter does not specify a translation between the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
     *       <code>LineBreakMeasurer</code> and user space
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
     * @see LineBreakMeasurer#insertChar
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
     * @see LineBreakMeasurer#deleteChar
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
    public LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
        this(text, BreakIterator.getLineInstance(), frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
     * Constructs a <code>LineBreakMeasurer</code> for the specified text.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
     * @param text the text for which this <code>LineBreakMeasurer</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
     *     produces <code>TextLayout</code> objects; the text must contain
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
     *     at least one character; if the text available through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     *     <code>iter</code> changes, further calls to this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     *     <code>LineBreakMeasurer</code> instance are undefined (except,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     *     in some cases, when <code>insertChar</code> or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     *     <code>deleteChar</code> are invoked afterward - see below)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     * @param breakIter the {@link BreakIterator} which defines line
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     *     breaks
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
     * @param frc contains information about a graphics device which is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
     *       needed to measure the text correctly;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
     *       text measurements can vary slightly depending on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
     *       device resolution, and attributes such as antialiasing; this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     *       parameter does not specify a translation between the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     *       <code>LineBreakMeasurer</code> and user space
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     * @throws IllegalArgumentException if the text has less than one character
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
     * @see LineBreakMeasurer#insertChar
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
     * @see LineBreakMeasurer#deleteChar
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
    public LineBreakMeasurer(AttributedCharacterIterator text,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
                             BreakIterator breakIter,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
                             FontRenderContext frc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        if (text.getEndIndex() - text.getBeginIndex() < 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
            throw new IllegalArgumentException("Text must contain at least one character.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        this.breakIter = breakIter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        this.measurer = new TextMeasurer(text, frc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        this.limit = text.getEndIndex();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        this.pos = this.start = text.getBeginIndex();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        charIter = new CharArrayIterator(measurer.getChars(), this.start);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        this.breakIter.setText(charIter);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
     * Returns the position at the end of the next layout.  Does NOT
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
     * update the current position of this <code>LineBreakMeasurer</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
     * @param wrappingWidth the maximum visible advance permitted for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
     *    the text in the next layout
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
     * @return an offset in the text representing the limit of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
     *    next <code>TextLayout</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
    public int nextOffset(float wrappingWidth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
        return nextOffset(wrappingWidth, limit, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
     * Returns the position at the end of the next layout.  Does NOT
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
     * update the current position of this <code>LineBreakMeasurer</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
     * @param wrappingWidth the maximum visible advance permitted for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
     *    the text in the next layout
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
     * @param offsetLimit the first character that can not be included
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
     *    in the next layout, even if the text after the limit would fit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
     *    within the wrapping width; <code>offsetLimit</code> must be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
     *    greater than the current position
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
     * @param requireNextWord if <code>true</code>, the current position
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
     *    that is returned if the entire next word does not fit within
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
     *    <code>wrappingWidth</code>; if <code>false</code>, the offset
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
     *    returned is at least one greater than the current position
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
     * @return an offset in the text representing the limit of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     *    next <code>TextLayout</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
    public int nextOffset(float wrappingWidth, int offsetLimit,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                          boolean requireNextWord) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        int nextOffset = pos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
        if (pos < limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
            if (offsetLimit <= pos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                    throw new IllegalArgumentException("offsetLimit must be after current position");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
            int charAtMaxAdvance =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
                            measurer.getLineBreakIndex(pos, wrappingWidth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
            if (charAtMaxAdvance == limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                nextOffset = limit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
            else if (Character.isWhitespace(measurer.getChars()[charAtMaxAdvance-start])) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                nextOffset = breakIter.following(charAtMaxAdvance);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
            else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
            // Break is in a word;  back up to previous break.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
                // NOTE:  I think that breakIter.preceding(limit) should be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
                // equivalent to breakIter.last(), breakIter.previous() but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
                // the authors of BreakIterator thought otherwise...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
                // If they were equivalent then the first branch would be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
                // unnecessary.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
                int testPos = charAtMaxAdvance + 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
                if (testPos == limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
                    breakIter.last();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
                    nextOffset = breakIter.previous();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
                else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
                    nextOffset = breakIter.preceding(testPos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
                if (nextOffset <= pos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                    // first word doesn't fit on line
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                    if (requireNextWord) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
                        nextOffset = pos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                    else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                        nextOffset = Math.max(pos+1, charAtMaxAdvance);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
        if (nextOffset > offsetLimit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
            nextOffset = offsetLimit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        return nextOffset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
     * Returns the next layout, and updates the current position.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
     * @param wrappingWidth the maximum visible advance permitted for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
     *     the text in the next layout
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
     * @return a <code>TextLayout</code>, beginning at the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
     *     position, which represents the next line fitting within
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
     *     <code>wrappingWidth</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
    public TextLayout nextLayout(float wrappingWidth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        return nextLayout(wrappingWidth, limit, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
     * Returns the next layout, and updates the current position.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
     * @param wrappingWidth the maximum visible advance permitted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
     *    for the text in the next layout
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
     * @param offsetLimit the first character that can not be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
     *    included in the next layout, even if the text after the limit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
     *    would fit within the wrapping width; <code>offsetLimit</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
     *    must be greater than the current position
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
     * @param requireNextWord if <code>true</code>, and if the entire word
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
     *    at the current position does not fit within the wrapping width,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
     *    <code>null</code> is returned. If <code>false</code>, a valid
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
     *    layout is returned that includes at least the character at the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
     *    current position
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
     * @return a <code>TextLayout</code>, beginning at the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
     *    position, that represents the next line fitting within
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
     *    <code>wrappingWidth</code>.  If the current position is at the end
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
     *    of the text used by this <code>LineBreakMeasurer</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
     *    <code>null</code> is returned
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
    public TextLayout nextLayout(float wrappingWidth, int offsetLimit,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
                                 boolean requireNextWord) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        if (pos < limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
            int layoutLimit = nextOffset(wrappingWidth, offsetLimit, requireNextWord);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
            if (layoutLimit == pos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
            TextLayout result = measurer.getLayout(pos, layoutLimit);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
            pos = layoutLimit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
            return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
     * Returns the current position of this <code>LineBreakMeasurer</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
     * @return the current position of this <code>LineBreakMeasurer</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
     * @see #setPosition
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
    public int getPosition() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
        return pos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
     * Sets the current position of this <code>LineBreakMeasurer</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
     * @param newPosition the current position of this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
     *    <code>LineBreakMeasurer</code>; the position should be within the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
     *    text used to construct this <code>LineBreakMeasurer</code> (or in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
     *    the text most recently passed to <code>insertChar</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
     *    or <code>deleteChar</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
     * @see #getPosition
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
    public void setPosition(int newPosition) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
        if (newPosition < start || newPosition > limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
            throw new IllegalArgumentException("position is out of range");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
        pos = newPosition;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
     * Updates this <code>LineBreakMeasurer</code> after a single
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
     * character is inserted into the text, and sets the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
     * position to the beginning of the paragraph.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
     * @param newParagraph the text after the insertion
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
     * @param insertPos the position in the text at which the character
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
     *    is inserted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
     * @throws IndexOutOfBoundsException if <code>insertPos</code> is less
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
     *         than the start of <code>newParagraph</code> or greater than
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
     *         or equal to the end of <code>newParagraph</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
     * @throws NullPointerException if <code>newParagraph</code> is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
     *         <code>null</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
     * @see #deleteChar
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
    public void insertChar(AttributedCharacterIterator newParagraph,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                           int insertPos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        measurer.insertChar(newParagraph, insertPos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
        limit = newParagraph.getEndIndex();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        pos = start = newParagraph.getBeginIndex();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
        charIter.reset(measurer.getChars(), newParagraph.getBeginIndex());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        breakIter.setText(charIter);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
     * Updates this <code>LineBreakMeasurer</code> after a single
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
     * character is deleted from the text, and sets the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
     * position to the beginning of the paragraph.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
     * @param newParagraph the text after the deletion
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
     * @param deletePos the position in the text at which the character
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
     *    is deleted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
     * @throws IndexOutOfBoundsException if <code>deletePos</code> is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
     *         less than the start of <code>newParagraph</code> or greater
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
     *         than the end of <code>newParagraph</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
     * @throws NullPointerException if <code>newParagraph</code> is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
     *         <code>null</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
     * @see #insertChar
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
    public void deleteChar(AttributedCharacterIterator newParagraph,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
                           int deletePos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        measurer.deleteChar(newParagraph, deletePos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        limit = newParagraph.getEndIndex();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
        pos = start = newParagraph.getBeginIndex();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
        charIter.reset(measurer.getChars(), start);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
        breakIter.setText(charIter);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
}