Java FontMetrics wordWrap(String text, FontMetrics metrics, double width)

Here you can find the source of wordWrap(String text, FontMetrics metrics, double width)

Description

Returns the specified text in lines that fit within the specified width when the specified font metrics are applied to the text

License

Open Source License

Parameter

Parameter Description
text the text to wrap
metrics the font metrics to calculate the text size for
width the width that the text must fit within

Return

the input text split in lines that fit the specified width

Declaration

public static String[] wordWrap(String text, FontMetrics metrics,
        double width) 

Method Source Code

//package com.java2s;

import java.awt.FontMetrics;

import java.util.ArrayList;

import java.util.List;

import java.util.Stack;

public class Main {
    /**//from  ww  w.j  a  v  a 2s. c  o  m
     * Returns the specified text in lines that fit within the specified
     * width when the specified font metrics are applied to the text
     * @param text the text to wrap
     * @param metrics the font metrics to calculate the text size for
     * @param width the width that the text must fit within
     * @return the input text split in lines that fit the specified width
     */
    public static String[] wordWrap(String text, FontMetrics metrics,
            double width) {
        List<String> result = new ArrayList<String>();
        // First split the processing into lines already delimited by
        // newlines. We want the result to retain all newlines in position.
        String[] lines = text.split("\n");

        for (int i = 0; i < lines.length; i++) {
            int lineWidth = 0; // the display width of the current line
            int charCount = 0; // keeps count of current position in the line
            StringBuilder currentLine = new StringBuilder();

            // Split the words of the current line by spaces and tabs
            // The words are trimmed of tabs, space and newlines, therefore
            String[] words = lines[i].split("\\s+");

            // Need to a form a stack of the words in reverse order
            // This is because if a word is split during the process 
            // the remainder of the word is added to the front of the 
            // stack and processed next
            Stack<String> wordStack = new Stack<String>();

            for (int j = words.length - 1; j >= 0; j--) {
                wordStack.push(words[j]);
            }

            while (!wordStack.isEmpty()) {
                String word = wordStack.pop();

                // Work out what whitespace exists before this word.
                // and add the width of the whitespace to the calculation
                int whitespaceCount = 0;

                if (word.length() > 0) {
                    // Concatenate any preceding whitespace to the
                    // word and calculate the number of characters of that
                    // whitespace
                    char firstWordLetter = word.charAt(0);
                    int letterIndex = lines[i].indexOf(firstWordLetter,
                            charCount);
                    String whitespace = lines[i].substring(charCount,
                            letterIndex);
                    whitespaceCount = whitespace.length();
                    word = whitespace.concat(word);
                }

                double wordLength;

                // If the line width is zero, we are at the start of a newline
                // We don't proceed preceeding whitespace in the width
                // calculation
                if (lineWidth > 0) {
                    wordLength = metrics.stringWidth(word);
                } else {
                    wordLength = metrics.stringWidth(word.trim());
                }

                // Does the width of line so far plus the width of the 
                // current word exceed the allowed width?
                if (lineWidth + wordLength > width) {
                    if (lineWidth > 0) {
                        // There is already at least one word on this line
                        // and the current word takes the overall width over
                        // the allowed width. Because there is something on
                        // the line, complete the current line, reset the width
                        // counter, create a new line and put the current word
                        // back on the stack for processing in the next round
                        result.add(currentLine.toString());
                        currentLine = new StringBuilder();
                        wordStack.push(word.trim());
                        lineWidth = 0;
                    } else {
                        // There are no words on the current line and the 
                        // current word does not fit on it. Find the maximum
                        // number of characters of this word that just fit
                        // in the available width
                        word = word.trim();

                        for (int j = 1; j <= word.length(); j++) {
                            wordLength = metrics.stringWidth(word
                                    .substring(0, j));

                            if (lineWidth + wordLength > width) {
                                // The last character took us over the allowed
                                // width, deducted it unless there is only one
                                // character, in which case we have to use it
                                // since we can't split it...
                                j = j > 1 ? j - 1 : j;
                                String chars = word.substring(0, j);
                                currentLine = currentLine.append(chars);
                                // Return the unprocessed part of the word 
                                // to the stack
                                wordStack.push(word.substring(j,
                                        word.length()));
                                result.add(currentLine.toString());
                                currentLine = new StringBuilder();
                                lineWidth = 0;
                                // Increment char counter allowing for white 
                                // space in the original word
                                charCount = charCount + chars.length()
                                        + whitespaceCount;
                                break;
                            }
                        }
                    }
                } else {
                    // The current word does not take the total line width
                    // over the allowed width. Append the word, removing
                    // preceeding whitespace if it is the first word in the
                    // line.
                    if (lineWidth > 0) {
                        currentLine = currentLine.append(word);
                    } else {
                        currentLine = currentLine.append(word.trim());
                    }

                    lineWidth += wordLength;
                    charCount += word.length();
                }
            }

            // If there is anything in the current line after processing all of
            // the words in this line, add it to the result.
            if (currentLine.length() > 0 || result.isEmpty()) {
                result.add(currentLine.toString());
            }
        }

        return result.toArray(new String[result.size()]);
    }

    /**
     * Returns the index of the given object in the given array of -1 if the
     * object is not contained in the array.
     */
    public static int indexOf(Object[] array, Object obj) {
        if (obj != null && array != null) {
            for (int i = 0; i < array.length; i++) {
                if (array[i] == obj) {
                    return i;
                }
            }
        }

        return -1;
    }
}

Related

  1. splitStringWithLength(String s, int length, FontMetrics fm)
  2. splitText(String text, String delim, FontMetrics fontMetrics, int width)
  3. stringByTruncatingToFitInWidth(String s, int width, Graphics g, String truncatedSuffix)
  4. stringDimension(Graphics g, Font f, String s)
  5. StringDimension(Graphics g, String text)
  6. wrapText(String text, int width, FontMetrics fontMetrics)