Here you can find the source of wordWrap(String text, FontMetrics metrics, double width)
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 |
public static String[] wordWrap(String text, FontMetrics metrics, double width)
//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; } }