Home | History | Annotate | Download | only in font
      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 
     22 package java.awt.font;
     23 
     24 import java.text.AttributedCharacterIterator; //???AWT: import java.text.BreakIterator;
     25 
     26 import 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  */
     36 public 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