package org.emdev.common.textmarkup.line;
import android.graphics.Canvas;
import android.graphics.Rect;
import org.emdev.common.textmarkup.RenderingStyle;
import org.emdev.common.textmarkup.RenderingStyle.Script;
import org.emdev.common.textmarkup.RenderingStyle.Strike;
import org.emdev.common.xml.TextProvider;
import org.emdev.utils.HyphenationUtils;
public class TextElement extends AbstractLineElement {
protected static final int[] starts = new int[100];
protected static final int[] lengths = new int[100];
protected static final float[] parts = new float[100];
public final char[] chars;
public final int start;
public final int length;
public final int offset;
public final RenderingStyle style;
public TextElement(final TextProvider text, final RenderingStyle style) {
super(style.paint.measureText(text.chars, 0, text.size), style.script == Script.SUPER ? style.textSize * 5 / 2 : style.textSize, false);
this.chars = text.chars;
this.start = 0;
this.length = text.size;
this.style = style;
this.offset = style.script == Script.SUPER ? (-style.textSize)
: style.script == Script.SUB ? style.textSize / 2 : 0;
}
public TextElement(final char[] ch, final int st, final int len, final RenderingStyle style) {
super(style.paint.measureText(ch, st, len), style.script == Script.SUPER ? style.textSize * 5 / 2 : style.textSize, false);
this.chars = ch;
this.start = st;
this.length = len;
this.style = style;
this.offset = style.script == Script.SUPER ? (-style.textSize)
: style.script == Script.SUB ? style.textSize / 2 : 0;
}
TextElement(final TextElement original, final int st, final int len, final float width) {
super(width, original.style.textSize, false);
this.chars = original.chars;
this.start = st;
this.length = len;
this.style = original.style;
this.offset = original.offset;
}
@Override
public float render(final Canvas c, final int y, final int x, final float additionalWidth, final float left,
final float right, final int nightmode) {
if (left < x + width && x < right) {
final int yy = y + offset;
c.drawText(chars, start, length, x, yy, style.paint);
if (style.strike == Strike.THROUGH) {
c.drawLine(x, yy - style.textSize / 4, x + width, yy - style.textSize / 4, style.paint);
c.drawRect(x, yy - style.textSize / 4, x + width, yy - style.textSize / 4 + 1, style.paint);
}
}
return width;
}
@Override
public AbstractLineElement[] split(final float remaining, boolean hyphenEnabled) {
if (!hyphenEnabled) {
return null;
}
final int count = HyphenationUtils.hyphenateWord(chars, start, length, starts, lengths);
if (count == 0) {
return null;
}
final float dwidth = this.style.defis.width;
final int firstStart = this.start;
int firstLen = 0;
float summ = dwidth;
int next = 0;
for (; next < parts.length; next++) {
final float width = style.paint.measureText(chars, starts[next], lengths[next]);
final float total = summ + width;
if (total > remaining) {
break;
}
summ = total;
firstLen += lengths[next];
}
if (next == 0) {
return null;
}
final int secondStart = starts[next];
final int secondLength = this.length - (starts[next] - this.start);
final TextElement first = new TextElement(this, firstStart, firstLen, summ - dwidth);
final TextElement second = new TextElement(this, secondStart, secondLength, this.width - first.width);
final AbstractLineElement[] result = { first, this.style.defis, second };
return result;
}
public int indexOf(final char[] pattern) {
int start1 = start;
if (pattern.length > 0) {
if (pattern.length + start1 - start > length) {
return -1;
}
while (true) {
int i = start1;
boolean found = false;
for (; i < start + length; i++) {
if (chars[i] == pattern[0]) {
found = true;
break;
}
}
if (!found || pattern.length + i - start > length) {
return -1; // handles subCount > count || start >= count
}
int o1 = i, o2 = 0;
while (++o2 < pattern.length && chars[++o1] == pattern[o2]) {
// Intentionally empty
}
if (o2 == pattern.length) {
return i - start;
}
start1 = i + 1;
}
}
return (start1 < length || start1 == 0) ? start1 - start : length - start;
}
public int indexOfIgnoreCases(final char[] pattern) {
int start1 = start;
if (pattern.length > 0) {
if (pattern.length + start1 - start > length) {
return -1;
}
while (true) {
int i = start1;
boolean found = false;
for (; i < start + length; i++) {
if (Character.toLowerCase(chars[i]) == pattern[0]) {
found = true;
break;
}
}
if (!found || pattern.length + i - start > length) {
return -1; // handles subCount > count || start >= count
}
int o1 = i, o2 = 0;
while (++o2 < pattern.length && Character.toLowerCase(chars[++o1]) == pattern[o2]) {
// Intentionally empty
}
if (o2 == pattern.length) {
return i - start;
}
start1 = i + 1;
}
}
return (start1 < length || start1 == 0) ? start1 - start : length - start;
}
@Override
public String toString() {
return new String(chars, start, length);
}
public void getTextBounds(Rect bounds) {
style.paint.getTextBounds(chars, start, length, bounds);
}
}