use of android.text.Spanned in project Jota-Text-Editor-old by jiro-aqua.
the class Layout method getLineMax.
private float getLineMax(int line, Object[] tabs, boolean full) {
int start = getLineStart(line);
int end;
if (full) {
end = getLineEnd(line);
} else {
end = getLineVisibleEnd(line);
}
boolean tab = getLineContainsTab(line);
if (tabs == null && tab && mText instanceof Spanned) {
tabs = ((Spanned) mText).getSpans(start, end, TabStopSpan.class);
}
return measureText(mPaint, mWorkPaint, mText, start, end, null, tab, tabs);
}
use of android.text.Spanned in project Jota-Text-Editor-old by jiro-aqua.
the class Layout method getOffsetAtStartOf.
private int getOffsetAtStartOf(int offset) {
if (offset == 0)
return 0;
CharSequence text = mText;
char c = text.charAt(offset);
if (c >= '�' && c <= '�') {
char c1 = text.charAt(offset - 1);
if (c1 >= '�' && c1 <= '�')
offset -= 1;
}
if (mSpannedText) {
ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset, ReplacementSpan.class);
for (int i = 0; i < spans.length; i++) {
int start = ((Spanned) text).getSpanStart(spans[i]);
int end = ((Spanned) text).getSpanEnd(spans[i]);
if (start < offset && end > offset)
offset = start;
}
}
return offset;
}
use of android.text.Spanned in project Jota-Text-Editor-old by jiro-aqua.
the class Layout method nextTab.
/**
* Returns the position of the next tab stop after h on the line.
*
* @param text the text
* @param start start of the line
* @param end limit of the line
* @param h the current horizontal offset
* @param tabs the tabs, can be null. If it is null, any tabs in effect
* on the line will be used. If there are no tabs, a default offset
* will be used to compute the tab stop.
* @return the offset of the next tab stop.
*/
/* package */
static float nextTab(CharSequence text, int start, int end, float h, Object[] tabs) {
float nh = Float.MAX_VALUE;
boolean alltabs = false;
if (text instanceof Spanned) {
if (tabs == null) {
tabs = ((Spanned) text).getSpans(start, end, TabStopSpan.class);
alltabs = true;
}
for (int i = 0; i < tabs.length; i++) {
if (!alltabs) {
if (!(tabs[i] instanceof TabStopSpan))
continue;
}
int where = ((TabStopSpan) tabs[i]).getTabStop();
if (where < nh && where > h)
nh = where;
}
if (nh != Float.MAX_VALUE)
return nh;
}
return ((int) ((h + TAB_INCREMENT) / TAB_INCREMENT)) * TAB_INCREMENT;
}
use of android.text.Spanned in project Jota-Text-Editor-old by jiro-aqua.
the class TextUtils method commaEllipsize.
/**
* Converts a CharSequence of the comma-separated form "Andy, Bob,
* Charles, David" that is too wide to fit into the specified width
* into one like "Andy, Bob, 2 more".
*
* @param text the text to truncate
* @param p the Paint with which to measure the text
* @param avail the horizontal width available for the text
* @param oneMore the string for "1 more" in the current locale
* @param more the string for "%d more" in the current locale
*/
public static CharSequence commaEllipsize(CharSequence text, TextPaint p, float avail, String oneMore, String more) {
int len = text.length();
char[] buf = new char[len];
TextUtils.getChars(text, 0, len, buf, 0);
int commaCount = 0;
for (int i = 0; i < len; i++) {
if (buf[i] == ',') {
commaCount++;
}
}
float[] wid;
if (text instanceof Spanned) {
Spanned sp = (Spanned) text;
TextPaint temppaint = new TextPaint();
wid = new float[len * 2];
int next;
for (int i = 0; i < len; i = next) {
next = sp.nextSpanTransition(i, len, MetricAffectingSpan.class);
Styled.getTextWidths(p, temppaint, sp, i, next, wid, null);
System.arraycopy(wid, 0, wid, len + i, next - i);
}
System.arraycopy(wid, len, wid, 0, len);
} else {
wid = new float[len];
p.getTextWidths(text, 0, len, wid);
}
int ok = 0;
int okRemaining = commaCount + 1;
String okFormat = "";
int w = 0;
int count = 0;
for (int i = 0; i < len; i++) {
w += wid[i];
if (buf[i] == ',') {
count++;
int remaining = commaCount - count + 1;
float moreWid;
String format;
if (remaining == 1) {
format = " " + oneMore;
} else {
format = " " + String.format(more, remaining);
}
moreWid = p.measureText(format);
if (w + moreWid <= avail) {
ok = i + 1;
okRemaining = remaining;
okFormat = format;
}
}
}
if (w <= avail) {
return text;
} else {
SpannableStringBuilder out = new SpannableStringBuilder(okFormat);
out.insert(0, text, 0, ok);
return out;
}
}
use of android.text.Spanned in project Jota-Text-Editor-old by jiro-aqua.
the class TextUtils method ellipsize.
/**
* Returns the original text if it fits in the specified width
* given the properties of the specified Paint,
* or, if it does not fit, a copy with ellipsis character added
* at the specified edge or center.
* If <code>preserveLength</code> is specified, the returned copy
* will be padded with zero-width spaces to preserve the original
* length and offsets instead of truncating.
* If <code>callback</code> is non-null, it will be called to
* report the start and end of the ellipsized range.
*/
public static CharSequence ellipsize(CharSequence text, TextPaint p, float avail, TruncateAt where, boolean preserveLength, EllipsizeCallback callback) {
if (sEllipsis == null) {
Resources r = Resources.getSystem();
sEllipsis = r.getString(R.string.ellipsis);
}
int len = text.length();
if (!(text instanceof Spanned)) {
float wid = p.measureText(text, 0, len);
if (wid <= avail) {
if (callback != null) {
callback.ellipsized(0, 0);
}
return text;
}
float ellipsiswid = p.measureText(sEllipsis);
if (ellipsiswid > avail) {
if (callback != null) {
callback.ellipsized(0, len);
}
if (preserveLength) {
char[] buf = obtain(len);
for (int i = 0; i < len; i++) {
buf[i] = '';
}
String ret = new String(buf, 0, len);
recycle(buf);
return ret;
} else {
return "";
}
}
if (where == TruncateAt.START) {
int fit = p.breakText(text, 0, len, false, avail - ellipsiswid, null);
if (callback != null) {
callback.ellipsized(0, len - fit);
}
if (preserveLength) {
return blank(text, 0, len - fit);
} else {
return sEllipsis + text.toString().substring(len - fit, len);
}
} else if (where == TruncateAt.END) {
int fit = p.breakText(text, 0, len, true, avail - ellipsiswid, null);
if (callback != null) {
callback.ellipsized(fit, len);
}
if (preserveLength) {
return blank(text, fit, len);
} else {
return text.toString().substring(0, fit) + sEllipsis;
}
} else /* where == TruncateAt.MIDDLE */
{
int right = p.breakText(text, 0, len, false, (avail - ellipsiswid) / 2, null);
float used = p.measureText(text, len - right, len);
int left = p.breakText(text, 0, len - right, true, avail - ellipsiswid - used, null);
if (callback != null) {
callback.ellipsized(left, len - right);
}
if (preserveLength) {
return blank(text, left, len - right);
} else {
String s = text.toString();
return s.substring(0, left) + sEllipsis + s.substring(len - right, len);
}
}
}
// But do the Spanned cases by hand, because it's such a pain
// to iterate the span transitions backwards and getTextWidths()
// will give us the information we need.
// getTextWidths() always writes into the start of the array,
// so measure each span into the first half and then copy the
// results into the second half to use later.
float[] wid = new float[len * 2];
TextPaint temppaint = new TextPaint();
Spanned sp = (Spanned) text;
int next;
for (int i = 0; i < len; i = next) {
next = sp.nextSpanTransition(i, len, MetricAffectingSpan.class);
Styled.getTextWidths(p, temppaint, sp, i, next, wid, null);
System.arraycopy(wid, 0, wid, len + i, next - i);
}
float sum = 0;
for (int i = 0; i < len; i++) {
sum += wid[len + i];
}
if (sum <= avail) {
if (callback != null) {
callback.ellipsized(0, 0);
}
return text;
}
float ellipsiswid = p.measureText(sEllipsis);
if (ellipsiswid > avail) {
if (callback != null) {
callback.ellipsized(0, len);
}
if (preserveLength) {
char[] buf = obtain(len);
for (int i = 0; i < len; i++) {
buf[i] = '';
}
SpannableString ss = new SpannableString(new String(buf, 0, len));
recycle(buf);
copySpansFrom(sp, 0, len, Object.class, ss, 0);
return ss;
} else {
return "";
}
}
if (where == TruncateAt.START) {
sum = 0;
int i;
for (i = len; i >= 0; i--) {
float w = wid[len + i - 1];
if (w + sum + ellipsiswid > avail) {
break;
}
sum += w;
}
if (callback != null) {
callback.ellipsized(0, i);
}
if (preserveLength) {
SpannableString ss = new SpannableString(blank(text, 0, i));
copySpansFrom(sp, 0, len, Object.class, ss, 0);
return ss;
} else {
SpannableStringBuilder out = new SpannableStringBuilder(sEllipsis);
out.insert(1, text, i, len);
return out;
}
} else if (where == TruncateAt.END) {
sum = 0;
int i;
for (i = 0; i < len; i++) {
float w = wid[len + i];
if (w + sum + ellipsiswid > avail) {
break;
}
sum += w;
}
if (callback != null) {
callback.ellipsized(i, len);
}
if (preserveLength) {
SpannableString ss = new SpannableString(blank(text, i, len));
copySpansFrom(sp, 0, len, Object.class, ss, 0);
return ss;
} else {
SpannableStringBuilder out = new SpannableStringBuilder(sEllipsis);
out.insert(0, text, 0, i);
return out;
}
} else /* where = TruncateAt.MIDDLE */
{
float lsum = 0, rsum = 0;
int left = 0, right = len;
float ravail = (avail - ellipsiswid) / 2;
for (right = len; right >= 0; right--) {
float w = wid[len + right - 1];
if (w + rsum > ravail) {
break;
}
rsum += w;
}
float lavail = avail - ellipsiswid - rsum;
for (left = 0; left < right; left++) {
float w = wid[len + left];
if (w + lsum > lavail) {
break;
}
lsum += w;
}
if (callback != null) {
callback.ellipsized(left, right);
}
if (preserveLength) {
SpannableString ss = new SpannableString(blank(text, left, right));
copySpansFrom(sp, 0, len, Object.class, ss, 0);
return ss;
} else {
SpannableStringBuilder out = new SpannableStringBuilder(sEllipsis);
out.insert(0, text, 0, left);
out.insert(out.length(), text, right, len);
return out;
}
}
}
Aggregations