最佳的自动换行的算法? [英] Best word wrap algorithm?
问题描述
自动换行是一个必须具备的现代文本编辑器的功能。
Word wrap is one of must-have features in modern text editor.
你知道如何处理自动换行? 什么是自动换行的最佳算法?
Do you know how to handle word wrap? What is the best algorithm for word-wrap?
更新: 如果文字是几百万行,我怎样才能使自动换行非常之快?
updated: If text is several million lines, how can I make word-wrap very fast?
更新:为什么我需要的解决方案?因为我的项目必须绘制文本的各种缩放级别,同时外形美观。
updated: Why I need the solution? Because my projects must draw text with various zoom level and simultaneously beautiful appearance.
更新:运行环境是Windows Mobile设备。最高600MHz的速度非常小的内存大小。
updated: Running environment is Windows Mobile devices. Maximum 600MHz speed with very small memory size.
更新:我应该如何处理行信息?让我们假设原始数据有三条线。
updated: How should I handle line information? Let's assume original data has three lines.
THIS IS LINE 1.
THIS IS LINE 2.
THIS IS LINE 3.
在断字的文字会显示像这样:
After word break text will be shown like this:
THIS IS
LINE 1.
THIS IS
LINE 2.
THIS IS
LINE 3.
我应该拨出3线多吗?或者有什么其他的建议?
Should I allocate 3 lines more? Or any other suggestions?
推荐答案
下面是我写在C#中自动换算法。它应该很容易翻译成其他语言(也许除了 IndexOfAny
)。
Here is a word-wrap algorithm I've written in C#. It should be fairly easy to translate into other languages (except perhaps for IndexOfAny
).
static char[] splitChars = new char[] { ' ', '-', '\t' };
private static string WordWrap(string str, int width)
{
string[] words = Explode(str, splitChars);
int curLineLength = 0;
StringBuilder strBuilder = new StringBuilder();
for(int i = 0; i < words.Length; i += 1)
{
string word = words[i];
// If adding the new word to the current line would be too long,
// then put it on a new line (and split it up if it's too long).
if (curLineLength + word.Length > width)
{
// Only move down to a new line if we have text on the current line.
// Avoids situation where wrapped whitespace causes emptylines in text.
if (curLineLength > 0)
{
strBuilder.Append(Environment.NewLine);
curLineLength = 0;
}
// If the current word is too long to fit on a line even on it's own then
// split the word up.
while (word.Length > width)
{
strBuilder.Append(word.Substring(0, width - 1) + "-");
word = word.Substring(width - 1);
strBuilder.Append(Environment.NewLine);
}
// Remove leading whitespace from the word so the new line starts flush to the left.
word = word.TrimStart();
}
strBuilder.Append(word);
curLineLength += word.Length;
}
return strBuilder.ToString();
}
private static string[] Explode(string str, char[] splitChars)
{
List<string> parts = new List<string>();
int startIndex = 0;
while (true)
{
int index = str.IndexOfAny(splitChars, startIndex);
if (index == -1)
{
parts.Add(str.Substring(startIndex));
return parts.ToArray();
}
string word = str.Substring(startIndex, index - startIndex);
char nextChar = str.Substring(index, 1)[0];
// Dashes and the likes should stick to the word occuring before it. Whitespace doesn't have to.
if (char.IsWhiteSpace(nextChar))
{
parts.Add(word);
parts.Add(nextChar.ToString());
}
else
{
parts.Add(word + nextChar);
}
startIndex = index + 1;
}
}
这是相当原始 - 它分裂的空格,制表符和破折号。它确保破折号坚持到它之前的单词(这样你就不会结束与堆栈\正溢出),尽管它不利于移动的小连字符的话换行,而不是分裂他们。它拆分的话,如果他们太久了一条线。
It's fairly primitive - it splits on spaces, tabs and dashes. It does make sure that dashes stick to the word before it (so you don't end up with stack\n-overflow) though it doesn't favour moving small hyphenated words to a newline rather than splitting them. It does split up words if they are too long for a line.
这也是非常特定的文化,因为我不知道很多关于其他文化的自动换行规则。
It's also fairly culturally specific, as I don't know much about the word-wrapping rules of other cultures.
这篇关于最佳的自动换行的算法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!