1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17/* 18 * @author Oleg V. Khaschansky 19 * @version $Revision$ 20 */ 21 22package java.awt.font; 23 24import java.text.AttributedCharacterIterator; //???AWT: import java.text.BreakIterator; 25 26import org.apache.harmony.awt.internal.nls.Messages; 27 28/** 29 * The class LineBreakMeasurer provides methods to measure the graphical 30 * representation of a text in order to determine where to add line breaks so 31 * the resulting line of text fits its wrapping width. The wrapping width 32 * defines the visual width of the paragraph. 33 * 34 * @since Android 1.0 35 */ 36public final class LineBreakMeasurer { 37 38 /** 39 * The tm. 40 */ 41 private TextMeasurer tm = null; 42 43 // ???AWT private BreakIterator bi = null; 44 /** 45 * The position. 46 */ 47 private int position = 0; 48 49 /** 50 * The maxpos. 51 */ 52 int maxpos = 0; 53 54 /** 55 * Instantiates a new LineBreakMeasurer object for the specified text. 56 * 57 * @param text 58 * the AttributedCharacterIterator object which contains text 59 * with at least one character. 60 * @param frc 61 * the FontRenderContext represented information about graphic 62 * device. 63 */ 64 public LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc) { 65 // ???AWT: this(text, BreakIterator.getLineInstance(), frc); 66 } 67 68 /* 69 * ???AWT public LineBreakMeasurer( AttributedCharacterIterator text, 70 * BreakIterator bi, FontRenderContext frc ) { tm = new TextMeasurer(text, 71 * frc); this.bi = bi; this.bi.setText(text); position = 72 * text.getBeginIndex(); maxpos = tm.aci.getEndIndex(); } 73 */ 74 75 /** 76 * Deletes a character from the specified position of the text, updates this 77 * LineBreakMeasurer object. 78 * 79 * @param newText 80 * the new text. 81 * @param pos 82 * the position of the character which is deleted. 83 */ 84 public void deleteChar(AttributedCharacterIterator newText, int pos) { 85 tm.deleteChar(newText, pos); 86 // ???AWT: bi.setText(newText); 87 88 position = newText.getBeginIndex(); 89 90 maxpos--; 91 } 92 93 /** 94 * Gets current position of this LineBreakMeasurer. 95 * 96 * @return the current position of this LineBreakMeasurer 97 */ 98 public int getPosition() { 99 return position; 100 } 101 102 /** 103 * Inserts a character at the specified position in the text, updates this 104 * LineBreakMeasurer object. 105 * 106 * @param newText 107 * the new text. 108 * @param pos 109 * the position of the character which is inserted. 110 */ 111 public void insertChar(AttributedCharacterIterator newText, int pos) { 112 tm.insertChar(newText, pos); 113 // ???AWT: bi.setText(newText); 114 115 position = newText.getBeginIndex(); 116 117 maxpos++; 118 } 119 120 /** 121 * Returns the next line of text, updates current position in this 122 * LineBreakMeasurer. 123 * 124 * @param wrappingWidth 125 * the maximum visible line width. 126 * @param offsetLimit 127 * the limit point within the text indicating that no further 128 * text should be included on the line; the paragraph break. 129 * @param requireNextWord 130 * if true, null is returned (the entire word at the current 131 * position does not fit within the wrapping width); if false, a 132 * valid layout is returned that includes at least the character 133 * at the current position. 134 * @return the next TextLayout which begins at the current position and 135 * represents the next line of text with width wrappingWidth, null 136 * is returned if the entire word at the current position does not 137 * fit within the wrapping width. 138 */ 139 public TextLayout nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord) { 140 if (position == maxpos) { 141 return null; 142 } 143 144 int nextPosition = nextOffset(wrappingWidth, offsetLimit, requireNextWord); 145 146 if (nextPosition == position) { 147 return null; 148 } 149 TextLayout layout = tm.getLayout(position, nextPosition); 150 position = nextPosition; 151 return layout; 152 } 153 154 /** 155 * Returns the next line of text. 156 * 157 * @param wrappingWidth 158 * the maximum visible line width. 159 * @return the next line of text. 160 */ 161 public TextLayout nextLayout(float wrappingWidth) { 162 return nextLayout(wrappingWidth, maxpos, false); 163 } 164 165 /** 166 * Returns the end position of the next line of text. 167 * 168 * @param wrappingWidth 169 * the maximum visible line width. 170 * @return the end position of the next line of text. 171 */ 172 public int nextOffset(float wrappingWidth) { 173 return nextOffset(wrappingWidth, maxpos, false); 174 } 175 176 /** 177 * Returns the end position of the next line of text. 178 * 179 * @param wrappingWidth 180 * the maximum visible line width. 181 * @param offsetLimit 182 * the limit point withing the text indicating that no further 183 * text should be included on the line; the paragraph break. 184 * @param requireNextWord 185 * if true, the current position is returned if the entire next 186 * word does not fit within wrappingWidth; if false, the offset 187 * returned is at least one greater than the current position. 188 * @return the end position of the next line of text. 189 * @throws IllegalArgumentException 190 * if the offsetLimit is less than the current position. 191 */ 192 public int nextOffset(float wrappingWidth, int offsetLimit, boolean requireNextWord) { 193 if (offsetLimit <= position) { 194 // awt.203=Offset limit should be greater than current position. 195 throw new IllegalArgumentException(Messages.getString("awt.203")); //$NON-NLS-1$ 196 } 197 198 if (position == maxpos) { 199 return position; 200 } 201 202 int breakPos = tm.getLineBreakIndex(position, wrappingWidth); 203 int correctedPos = breakPos; 204 205 // This check is required because bi.preceding(maxpos) throws an 206 // exception 207 /* 208 * ???AWT if (breakPos == maxpos) { correctedPos = maxpos; } else if 209 * (Character.isWhitespace(bi.getText().setIndex(breakPos))) { 210 * correctedPos = bi.following(breakPos); } else { correctedPos = 211 * bi.preceding(breakPos); } 212 */ 213 214 if (position >= correctedPos) { 215 if (requireNextWord) { 216 correctedPos = position; 217 } else { 218 correctedPos = Math.max(position + 1, breakPos); 219 } 220 } 221 222 return Math.min(correctedPos, offsetLimit); 223 } 224 225 /** 226 * Sets the new position of this LineBreakMeasurer. 227 * 228 * @param pos 229 * the new position of this LineBreakMeasurer. 230 */ 231 public void setPosition(int pos) { 232 if (tm.aci.getBeginIndex() > pos || maxpos < pos) { 233 // awt.33=index is out of range 234 throw new IllegalArgumentException(Messages.getString("awt.33")); //$NON-NLS-1$ 235 } 236 position = pos; 237 } 238} 239