/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * @author Oleg V. Khaschansky * @version $Revision$ */ package java.awt.font; import java.text.AttributedCharacterIterator; //???AWT: import java.text.BreakIterator; import org.apache.harmony.awt.internal.nls.Messages; /** * The class LineBreakMeasurer provides methods to measure the graphical * representation of a text in order to determine where to add line breaks so * the resulting line of text fits its wrapping width. The wrapping width * defines the visual width of the paragraph. * * @since Android 1.0 */ public final class LineBreakMeasurer { /** * The tm. */ private TextMeasurer tm = null; // ???AWT private BreakIterator bi = null; /** * The position. */ private int position = 0; /** * The maxpos. */ int maxpos = 0; /** * Instantiates a new LineBreakMeasurer object for the specified text. * * @param text * the AttributedCharacterIterator object which contains text * with at least one character. * @param frc * the FontRenderContext represented information about graphic * device. */ public LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc) { // ???AWT: this(text, BreakIterator.getLineInstance(), frc); } /* * ???AWT public LineBreakMeasurer( AttributedCharacterIterator text, * BreakIterator bi, FontRenderContext frc ) { tm = new TextMeasurer(text, * frc); this.bi = bi; this.bi.setText(text); position = * text.getBeginIndex(); maxpos = tm.aci.getEndIndex(); } */ /** * Deletes a character from the specified position of the text, updates this * LineBreakMeasurer object. * * @param newText * the new text. * @param pos * the position of the character which is deleted. */ public void deleteChar(AttributedCharacterIterator newText, int pos) { tm.deleteChar(newText, pos); // ???AWT: bi.setText(newText); position = newText.getBeginIndex(); maxpos--; } /** * Gets current position of this LineBreakMeasurer. * * @return the current position of this LineBreakMeasurer */ public int getPosition() { return position; } /** * Inserts a character at the specified position in the text, updates this * LineBreakMeasurer object. * * @param newText * the new text. * @param pos * the position of the character which is inserted. */ public void insertChar(AttributedCharacterIterator newText, int pos) { tm.insertChar(newText, pos); // ???AWT: bi.setText(newText); position = newText.getBeginIndex(); maxpos++; } /** * Returns the next line of text, updates current position in this * LineBreakMeasurer. * * @param wrappingWidth * the maximum visible line width. * @param offsetLimit * the limit point within the text indicating that no further * text should be included on the line; the paragraph break. * @param requireNextWord * if true, null is returned (the entire word at the current * position does not fit within the wrapping width); if false, a * valid layout is returned that includes at least the character * at the current position. * @return the next TextLayout which begins at the current position and * represents the next line of text with width wrappingWidth, null * is returned if the entire word at the current position does not * fit within the wrapping width. */ public TextLayout nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord) { if (position == maxpos) { return null; } int nextPosition = nextOffset(wrappingWidth, offsetLimit, requireNextWord); if (nextPosition == position) { return null; } TextLayout layout = tm.getLayout(position, nextPosition); position = nextPosition; return layout; } /** * Returns the next line of text. * * @param wrappingWidth * the maximum visible line width. * @return the next line of text. */ public TextLayout nextLayout(float wrappingWidth) { return nextLayout(wrappingWidth, maxpos, false); } /** * Returns the end position of the next line of text. * * @param wrappingWidth * the maximum visible line width. * @return the end position of the next line of text. */ public int nextOffset(float wrappingWidth) { return nextOffset(wrappingWidth, maxpos, false); } /** * Returns the end position of the next line of text. * * @param wrappingWidth * the maximum visible line width. * @param offsetLimit * the limit point withing the text indicating that no further * text should be included on the line; the paragraph break. * @param requireNextWord * if true, the current position is returned if the entire next * word does not fit within wrappingWidth; if false, the offset * returned is at least one greater than the current position. * @return the end position of the next line of text. * @throws IllegalArgumentException * if the offsetLimit is less than the current position. */ public int nextOffset(float wrappingWidth, int offsetLimit, boolean requireNextWord) { if (offsetLimit <= position) { // awt.203=Offset limit should be greater than current position. throw new IllegalArgumentException(Messages.getString("awt.203")); //$NON-NLS-1$ } if (position == maxpos) { return position; } int breakPos = tm.getLineBreakIndex(position, wrappingWidth); int correctedPos = breakPos; // This check is required because bi.preceding(maxpos) throws an // exception /* * ???AWT if (breakPos == maxpos) { correctedPos = maxpos; } else if * (Character.isWhitespace(bi.getText().setIndex(breakPos))) { * correctedPos = bi.following(breakPos); } else { correctedPos = * bi.preceding(breakPos); } */ if (position >= correctedPos) { if (requireNextWord) { correctedPos = position; } else { correctedPos = Math.max(position + 1, breakPos); } } return Math.min(correctedPos, offsetLimit); } /** * Sets the new position of this LineBreakMeasurer. * * @param pos * the new position of this LineBreakMeasurer. */ public void setPosition(int pos) { if (tm.aci.getBeginIndex() > pos || maxpos < pos) { // awt.33=index is out of range throw new IllegalArgumentException(Messages.getString("awt.33")); //$NON-NLS-1$ } position = pos; } }