139 lines
3.5 KiB
Java
139 lines
3.5 KiB
Java
package speiger.src.coreengine.rendering.gui.renderer.lexer;
|
|
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
|
|
import speiger.src.collections.objects.lists.ObjectArrayList;
|
|
import speiger.src.collections.objects.utils.ObjectLists;
|
|
import speiger.src.coreengine.rendering.gui.renderer.FontRenderer;
|
|
import speiger.src.coreengine.rendering.gui.renderer.IFontRenderer.CharInstance;
|
|
import speiger.src.coreengine.utils.helpers.TextUtil;
|
|
|
|
public class TextLexer
|
|
{
|
|
FontRenderer render;
|
|
List<Word> helper = new ObjectArrayList<Word>();
|
|
|
|
public TextLexer(FontRenderer render)
|
|
{
|
|
this.render = render;
|
|
}
|
|
|
|
public void getWords(String text, TextContext context, List<Word> words)
|
|
{
|
|
text = render.clearInvalidLetters(text);
|
|
Word current = new Word(context.getScale());
|
|
for(int i = 0,j=0,m=text.length();i<m;i++,j++)
|
|
{
|
|
char letter = text.charAt(i);
|
|
if(letter == '§' && context.allowsSpecial() && i + 1 < m && text.charAt(i + 1) == '<')
|
|
{
|
|
String search = TextUtil.searchUntil(text, i + 2, '>', FontRenderer.INVALID_SEARCH);
|
|
if(search.length() > 0)
|
|
{
|
|
context.apply(search.toLowerCase(Locale.ROOT).split(","), j--);
|
|
i += search.length()+2;
|
|
continue;
|
|
}
|
|
}
|
|
WordType type = WordType.getByLetter(letter);
|
|
if(current.getType() != type || type != null && type.isNewLine())
|
|
{
|
|
if(!current.isEmpty())
|
|
{
|
|
words.add(current);
|
|
current = new Word(current);
|
|
}
|
|
current.setSpecail(type);
|
|
}
|
|
if(Character.isHighSurrogate(letter) && i + 1 < m)
|
|
{
|
|
char extra = text.charAt(i + 1);
|
|
if(Character.isLowSurrogate(extra))
|
|
{
|
|
i++;
|
|
current.addLetter(render.getInstance(Character.toCodePoint(letter, extra), context.isBold()));
|
|
continue;
|
|
}
|
|
}
|
|
current.addLetter(render.getInstance(letter, context.isBold()));
|
|
}
|
|
if(!current.isEmpty())
|
|
{
|
|
words.add(current);
|
|
}
|
|
}
|
|
|
|
public List<Line> evaluateLines(String text, TextContext context, float maxWidth)
|
|
{
|
|
if(text == null || text.isEmpty() || maxWidth < 10F * context.getScale())
|
|
{
|
|
return ObjectLists.empty();
|
|
}
|
|
List<Line> lines = new ObjectArrayList<>();
|
|
getWords(text, context, helper);
|
|
Line line = new Line(maxWidth);
|
|
for(int i = 0;i<helper.size();i++)
|
|
{
|
|
Word word = helper.get(i);
|
|
if(word.isNewLine())
|
|
{
|
|
line.addWord(word);
|
|
line.finishLine();
|
|
lines.add(line);
|
|
line = new Line(maxWidth);
|
|
continue;
|
|
}
|
|
if(!line.attemptAddingWord(word))
|
|
{
|
|
if(line.isEmpty() || (context.isSingle() && (word.size() != 1 || word.getWidth() < maxWidth - line.getWidth())))
|
|
{
|
|
Word removedWord = helper.remove(i--);
|
|
splitWords(i+1, removedWord, maxWidth - line.getWidth() - 1F, context.getScale());
|
|
}
|
|
else
|
|
{
|
|
line.finishLine();
|
|
lines.add(line);
|
|
line = new Line(maxWidth);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
if(!line.isEmpty())
|
|
{
|
|
line.finishLine();
|
|
lines.add(line);
|
|
}
|
|
helper.clear();
|
|
return lines;
|
|
}
|
|
|
|
private void splitWords(int index, Word word, float maxLength, float scale)
|
|
{
|
|
Word newWord = word.getPrev() != null ? new Word(word.getPrev()) : new Word(scale);
|
|
for(CharInstance letter : word.instanceIterator())
|
|
{
|
|
float width = letter.getXAdvance() * scale;
|
|
if(width + newWord.getWidth() > maxLength)
|
|
{
|
|
helper.add(index++, newWord);
|
|
newWord = new Word(newWord);
|
|
}
|
|
newWord.addLetter(letter);
|
|
}
|
|
if(newWord.size() > 0)
|
|
{
|
|
helper.add(index++, newWord);
|
|
if(word.getNext() != null)
|
|
{
|
|
word.getNext().setPrev(newWord);
|
|
}
|
|
}
|
|
else if(word.getNext() != null)
|
|
{
|
|
word.getNext().setPrev(newWord.getPrev());
|
|
}
|
|
}
|
|
}
|